head     56.1;
access   ;
symbols  ;
locks    ; strict;
comment  @# @;


56.1
date     91.11.05.09.34.44;  author jwh;  state Exp;
branches ;
next     55.1;

55.1
date     91.08.25.10.13.10;  author jwh;  state Exp;
branches ;
next     54.2;

54.2
date     91.08.21.14.41.04;  author jwh;  state Exp;
branches ;
next     54.1;

54.1
date     91.03.18.15.20.15;  author jwh;  state Exp;
branches ;
next     53.1;

53.1
date     91.03.11.19.21.46;  author jwh;  state Exp;
branches ;
next     52.1;

52.1
date     91.02.19.09.05.34;  author jwh;  state Exp;
branches ;
next     51.2;

51.2
date     91.02.10.16.14.37;  author jwh;  state Exp;
branches ;
next     51.1;

51.1
date     91.01.30.16.04.44;  author jwh;  state Exp;
branches ;
next     1.1;

1.1
date     91.01.16.15.31.57;  author jwh;  state Exp;
branches ;
next     ;


desc
@first version.
@


56.1
log
@Automatic bump of revision number for PWS version 3.25
@
text
@@


55.1
log
@Automatic bump of revision number for PWS version 3.25A
@
text
@@


54.2
log
@
pws2rcs automatic delta on Wed Aug 21 13:42:03 MDT 1991
@
text
@@


54.1
log
@Automatic bump of revision number for PWS version 3.24
@
text
@a0 354
*
*       x_operr.sa 3.3 12/18/90
*
*       fpsp_operr --- FPSP handler for operand error exception
*
*       See 68040 User's Manual pp. 9-44f
*
* Note 1: For trap disabled 040 does the following:
* If the dest is a fp reg, then an extended precision non_signaling
* NAN is stored in the dest reg.  If the dest format is b, w, or l and
* the source op is a NAN, then garbage is stored as the result (actually
* the upper 32 bits of the mantissa are sent to the integer unit). If
* the dest format is integer (b, w, l) and the operr is caused by
* integer overflow, or the source op is inf, then the result stored is
* garbage.
* There are three cases in which operr is incorrectly signaled on the
* 040.  This occurs for move_out of format b, w, or l for the largest
* negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
*
*         On opclass = 011 fmove.(b,w,l) that causes a conversion
*         overflow -> OPERR, the exponent in wbte (and fpte) is:
*               byte    56 - (62 - exp)
*               word    48 - (62 - exp)
*               long    32 - (62 - exp)
*
*                       where exp = (true exp) - 1
*
*  So, wbtemp and fptemp will contain the following on erroneoulsy
*         signalled operr:
*                       fpts = 1
*                       fpte = $4000  (15 bit externally)
*               byte    fptm = $ffffffff ffffff80
*               word    fptm = $ffffffff ffff8000
*               long    fptm = $ffffffff 80000000
*
* Note 2: For trap enabled 040 does the following:
* If the inst is move_out, then same as Note 1.
* If the inst is not move_out, the dest is not modified.
* The exceptional operand is not defined for integer overflow
* during a move_out.
*

*               Copyright (C) Motorola, Inc. 1990
*                       All Rights Reserved
*
*       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
*       The copyright notice above does not evidence any
*       actual or intended publication of such source code.



	include fpsp_h

	refr    mem_write
	refr    real_operr
	refr    real_inex
	refr    get_fline
	refr    fpsp_done
	refr    reg_dest

	def     fpsp_operr
fpsp_operr    equ    *
*
	link            a6,#-LOCAL_SIZE
	fsave           -(a7)
	movem.l         d0-d1/a0-a1,USER_DA(a6)
	fmovem.x        fp0-fp3,USER_FP0(a6)
	fmovem.l        FPCONTROL/FPSTATUS/FPIADDR,USER_FPCONTROL(a6)
*
* Check if this is an opclass 3 instruction.
*  If so, fall through, else branch to operr_end
*
	btst    #TFLAG,T_BYTE(a6)
	beq.b   operr_end

*
* If the destination size is B,W,or L, the operr must be
* handled here.
*
	move.l  CMDREG1B(a6),d0
	bfextu  d0{3:3},d0      ;0=long, 4=word, 6=byte
	cmpi.b  #0,d0           ;determine size; check long
	beq.w   operr_long
	cmpi.b  #4,d0           ;check word
	beq.w   operr_word
	cmpi.b  #6,d0           ;check byte
	beq.w   operr_byte

*
* The size is not B,W,or L, so the operr is handled by the
* kernel handler.  Set the operr bits and clean up, leaving
* only the integer exception frame on the stack, and the
* fpu in the original exceptional state.
*
operr_end    equ    *
	bset            #operr_bit,FPSTATUS_EXCEPT(a6)
	bset            #aiop_bit,FPSTATUS_AEXCEPT(a6)

	movem.l         USER_DA(a6),d0-d1/a0-a1
	fmovem.x        USER_FP0(a6),fp0-fp3
	fmovem.l        USER_FPCONTROL(a6),FPCONTROL/FPSTATUS/FPIADDR
	frestore        (a7)+
	unlk            a6
	bra.l           real_operr

operr_long    equ    *
	moveq   #4,d1           ;write size to d1
	move.b  STAG(a6),d0     ;test stag for nan
	andi.b  #$e0,d0         ;clr all but tag
	cmpi.b  #$60,d0         ;check for nan
	beq     operr_nan
	cmpi.l  #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
	bne.b   chklerr         ;if not equal, check for incorrect operr
	bsr     check_upper     ;check if exp and ms mant are special
	tst.l   d0
	bne.b   chklerr         ;if d0 is true, check for incorrect operr
	move.l  #$80000000,d0   ;store special case result
	bsr     operr_store
	bra.w   not_enabled     ;clean and exit
*
*       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chklerr    equ    *
	move.w  FPTEMP_EX(a6),d0
	and.w   #$7FFF,d0       ;ignore sign bit
	cmp.w   #$3FFE,d0       ;this is the only possible exponent value
	bne.b   chklerr2
fixlong    equ    *
	move.l  FPTEMP_LO(a6),d0
	bsr     operr_store
	bra.w   not_enabled
chklerr2    equ    *
	move.w  FPTEMP_EX(a6),d0
	and.w   #$7FFF,d0       ;ignore sign bit
	cmp.w   #$4000,d0
	bhs.w   store_max       ;exponent out of range

	move.l  FPTEMP_LO(a6),d0
	and.l   #$7FFF0000,d0   ;look for all 1's on bits 30-16
	cmp.l   #$7FFF0000,d0
	beq.b   fixlong

	tst.l   FPTEMP_LO(a6)
	bpl.b   chklepos
	cmpi.l  #$FFFFFFFF,FPTEMP_HI(a6)
	beq.b   fixlong
	bra.w   store_max
chklepos    equ    *
	tst.l   FPTEMP_HI(a6)
	beq.b   fixlong
	bra.w   store_max

operr_word    equ    *
	moveq   #2,d1           ;write size to d1
	move.b  STAG(a6),d0     ;test stag for nan
	andi.b  #$e0,d0         ;clr all but tag
	cmpi.b  #$60,d0         ;check for nan
	beq.w   operr_nan
	cmpi.l  #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
	bne.b   chkwerr         ;if not equal, check for incorrect operr
	bsr     check_upper     ;check if exp and ms mant are special
	tst.l   d0
	bne.b   chkwerr         ;if d0 is true, check for incorrect operr
	move.l  #$80000000,d0   ;store special case result
	bsr     operr_store
	bra.w   not_enabled     ;clean and exit
*
*       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chkwerr    equ    *
	move.w  FPTEMP_EX(a6),d0
	and.w   #$7FFF,d0       ;ignore sign bit
	cmp.w   #$3FFE,d0       ;this is the only possible exponent value
	bne.b   store_max
	move.l  FPTEMP_LO(a6),d0
	swap    d0
	bsr     operr_store
	bra.w   not_enabled

operr_byte    equ    *
	moveq   #1,d1           ;write size to d1
	move.b  STAG(a6),d0     ;test stag for nan
	andi.b  #$e0,d0         ;clr all but tag
	cmpi.b  #$60,d0         ;check for nan
	beq.b   operr_nan
	cmpi.l  #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
	bne.b   chkberr         ;if not equal, check for incorrect operr
	bsr     check_upper     ;check if exp and ms mant are special
	tst.l   d0
	bne.b   chkberr         ;if d0 is true, check for incorrect operr
	move.l  #$80000000,d0   ;store special case result
	bsr     operr_store
	bra.w   not_enabled     ;clean and exit
*
*       CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
*
chkberr    equ    *
	move.w  FPTEMP_EX(a6),d0
	and.w   #$7FFF,d0       ;ignore sign bit
	cmp.w   #$3FFE,d0       ;this is the only possible exponent value
	bne.b   store_max
	move.l  FPTEMP_LO(a6),d0
	asl.l   #8,d0
	swap    d0
	bsr     operr_store
	bra.w   not_enabled

*
* This operr condition is not of the special case.  Set operr
* and aiop and write the portion of the nan to memory for the
* given size.
*
operr_nan    equ    *
	ori.l   #opaop_mask,USER_FPSTATUS(a6) ;set operr & aiop
	move.l  ETEMP_HI(a6),d0 ;output will be from upper 32 bits
	bsr     operr_store
	bra     end_operr
*
* Store_max loads the max pos or negative for the size, sets
* the operr and aiop bits, and clears inex and ainex, incorrectly
* set by the 040.
*
store_max    equ    *
	ori.l   #opaop_mask,USER_FPSTATUS(a6) ;set operr & aiop
	bclr    #inex2_bit,FPSTATUS_EXCEPT(a6)
	bclr    #ainex_bit,FPSTATUS_AEXCEPT(a6)
	fmove.l #0,FPSTATUS

	tst.w   FPTEMP_EX(a6)   ;check sign
	blt.b   load_neg
	move.l  #$7fffffff,d0
	bsr     operr_store
	bra     end_operr
load_neg    equ    *
	move.l  #$80000000,d0
	bsr     operr_store
	bra     end_operr

*
* This routine stores the data in d0, for the given size in d1,
* to memory or data register as required.  A read of the fline
* is required to determine the destination.
*
operr_store    equ    *
	move.l  d0,L_SCR1(a6)   ;move write data to L_SCR1
	move.l  d1,-(a7)        ;save register size
	bsr.l   get_fline       ;fline returned in d0
	move.l  (a7)+,d1
	bftst   d0{26:3}                ;if mode is zero, dest is Dn
	bne.b   dest_mem
*
* Destination is Dn.  Get register number from d0. Data is on
* the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
*
	andi.l  #7,d0           ;isolate register number
	cmpi.l  #4,d1
	beq.b   op_long         ;the most frequent case
	cmpi.l  #2,d1
	bne.b   op_con
	or.l    #8,d0
	bra.b   op_con
op_long    equ    *
	or.l    #$10,d0
op_con    equ    *
	move.l  d0,d1           ;format size:reg for reg_dest
	bra.l   reg_dest        ;call to reg_dest returns to caller
*                               ;of operr_store
*
* Destination is memory.  Get <ea> from integer exception frame
* and call mem_write.
*
dest_mem    equ    *
	lea     L_SCR1(a6),a0   ;put ptr to write data in a0
	move.l  EXC_EA(a6),a1   ;put user destination address in a1
	move.l  d1,d0           ;put size in d0
	bsr.l   mem_write
	rts
*
* Check the exponent for $c000 and the upper 32 bits of the
* mantissa for $ffffffff.  If both are true, return d0 clr
* and store the lower n bits of the least lword of FPTEMP
* to d0 for write out.  If not, it is a real operr, and set d0.
*
check_upper    equ    *
	cmpi.l  #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
	bne.b   true_operr      ;if not all 1's then was true operr
	cmpi.w  #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
	beq.b   not_true_operr  ;branch if not true operr
	cmpi.w  #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
	beq.b   not_true_operr  ;branch if not true operr
true_operr    equ    *
	move.l  #1,d0           ;signal real operr
	rts
not_true_operr    equ    *
	clr.l   d0              ;signal no real operr
	rts

*
* End_operr tests for operr enabled.  If not, it cleans up the stack
* and does an rte.  If enabled, it cleans up the stack and branches
* to the kernel operr handler with only the integer exception
* frame on the stack and the fpu in the original exceptional state
* with correct data written to the destination.
*
end_operr    equ    *
	btst            #operr_bit,FPCONTROL_ENABLE(a6)
	beq.b           not_enabled
enabled    equ    *
	movem.l         USER_DA(a6),d0-d1/a0-a1
	fmovem.x        USER_FP0(a6),fp0-fp3
	fmovem.l        USER_FPCONTROL(a6),FPCONTROL/FPSTATUS/FPIADDR
	frestore        (a7)+
	unlk            a6
	bra.l           real_operr

not_enabled    equ    *
*
* It is possible to have either inex2 or inex1 exceptions with the
* operr.  If the inex enable bit is set in the FPCONTROL, and either
* inex2 or inex1 occured, we must clean up and branch to the
* real inex handler.
*
ck_inex    equ    *
	move.b  FPCONTROL_ENABLE(a6),d0
	and.b   FPSTATUS_EXCEPT(a6),d0
	andi.b  #$3,d0
	beq.w   operr_exit
*
* Inexact enabled and reported, and we must take an inexact exception.
*
take_inex    equ    *
	move.b          #INEX_VEC,EXC_VEC+1(a6)
	move.l          USER_FPSTATUS(a6),FPSTATUS_SHADOW(a6)
	ori.l           #sx_mask,E_BYTE(a6)
	movem.l         USER_DA(a6),d0-d1/a0-a1
	fmovem.x        USER_FP0(a6),fp0-fp3
	fmovem.l        USER_FPCONTROL(a6),FPCONTROL/FPSTATUS/FPIADDR
	frestore        (a7)+
	unlk            a6
	bra.l           real_inex
*
* Since operr is only an E1 exception, there is no need to frestore
* any state back to the fpu.
*
operr_exit    equ    *
	movem.l         USER_DA(a6),d0-d1/a0-a1
	fmovem.x        USER_FP0(a6),fp0-fp3
	fmovem.l        USER_FPCONTROL(a6),FPCONTROL/FPSTATUS/FPIADDR
	unlk            a6
	bra.l           fpsp_done

	end


@


53.1
log
@Automatic bump of revision number for PWS version 3.24B
@
text
@@


52.1
log
@Automatic bump of revision number for PWS version 3.24A
@
text
@@


51.2
log
@*** empty log message ***
@
text
@@


51.1
log
@Automatic bump of revision number for PWS version 3.24d
@
text
@d52 1
a52 1
	include fpsp.h
@


1.1
log
@Initial revision
@
text
@@
