[BACK]Return to x_store.sa CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / fpsp

File: [local] / sys / arch / m68k / fpsp / x_store.sa (download)

Revision 1.1, Tue Mar 4 16:07:08 2008 UTC (16 years, 2 months ago) by nbrk
Branch point for: MAIN

Initial revision

*	$OpenBSD: x_store.sa,v 1.2 1996/05/29 21:05:49 niklas Exp $
*	$NetBSD: x_store.sa,v 1.3 1994/10/26 07:50:29 cgd Exp $

*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
*	M68000 Hi-Performance Microprocessor Division
*	M68040 Software Package 
*
*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
*	All rights reserved.
*
*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
*	To the maximum extent permitted by applicable law,
*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
*	PARTICULAR PURPOSE and any warranty against infringement with
*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
*	and any accompanying written materials. 
*
*	To the maximum extent permitted by applicable law,
*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
*	and support of the SOFTWARE.  
*
*	You are hereby granted a copyright license to use, modify, and
*	distribute the SOFTWARE so long as this entire notice is retained
*	without alteration in any modified and/or redistributed versions,
*	and that such modified versions are clearly identified as such.
*	No licenses are granted by implication, estoppel or otherwise
*	under any patents or trademarks of Motorola, Inc.

*
*	x_store.sa 3.2 1/24/91
*
*	store --- store operand to memory or register
*
*	Used by underflow and overflow handlers.
*
*	a6 = points to fp value to be stored.
*

X_STORE	IDNT    2,1 Motorola 040 Floating Point Software Package

	section	8

fpreg_mask:
	dc.b	$80,$40,$20,$10,$08,$04,$02,$01

	include	fpsp.h

	xref	mem_write
	xref	get_fline
	xref	g_opcls
	xref	g_dfmtou
	xref	reg_dest

	xdef	dest_ext
	xdef	dest_dbl
	xdef	dest_sgl

	xdef	store
store:
	btst.b	#E3,E_BYTE(a6)
	beq.b	E1_sto
E3_sto:
	move.l	CMDREG3B(a6),d0
	bfextu	d0{6:3},d0		;isolate dest. reg from cmdreg3b
sto_fp:
	lea	fpreg_mask,a1
	move.b	(a1,d0.w),d0		;convert reg# to dynamic register mask
	tst.b	LOCAL_SGN(a0)
	beq.b	is_pos
	bset.b	#sign_bit,LOCAL_EX(a0)
is_pos:
	fmovem.x (a0),d0		;move to correct register
*
*	if fp0-fp3 is being modified, we must put a copy
*	in the USER_FPn variable on the stack because all exception
*	handlers restore fp0-fp3 from there.
*
	cmp.b	#$80,d0		
	bne.b	not_fp0
	fmovem.x fp0,USER_FP0(a6)
	rts
not_fp0:
	cmp.b	#$40,d0
	bne.b	not_fp1
	fmovem.x fp1,USER_FP1(a6)
	rts
not_fp1:
	cmp.b	#$20,d0
	bne.b	not_fp2
	fmovem.x fp2,USER_FP2(a6)
	rts
not_fp2:
	cmp.b	#$10,d0
	bne.b	not_fp3
	fmovem.x fp3,USER_FP3(a6)
	rts
not_fp3:
	rts

E1_sto:
	bsr.l	g_opcls		;returns opclass in d0
	cmpi.b	#3,d0
	beq	opc011		;branch if opclass 3
	move.l	CMDREG1B(a6),d0
	bfextu	d0{6:3},d0	;extract destination register
	bra.b	sto_fp

opc011:
	bsr.l	g_dfmtou	;returns dest format in d0
*				;ext=00, sgl=01, dbl=10
	move.l	a0,a1		;save source addr in a1
	move.l	EXC_EA(a6),a0	;get the address
	tst.l	d0		;if dest format is extended
	beq.w	dest_ext	;then branch
	cmpi.l	#1,d0		;if dest format is single
	beq.b	dest_sgl	;then branch
*
*	fall through to dest_dbl
*

*
*	dest_dbl --- write double precision value to user space
*
*Input
*	a0 -> destination address
*	a1 -> source in extended precision
*Output
*	a0 -> destroyed
*	a1 -> destroyed
*	d0 -> 0
*
*Changes extended precision to double precision.
* Note: no attempt is made to round the extended value to double.
*	dbl_sign = ext_sign
*	dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
*	get rid of ext integer bit
*	dbl_mant = ext_mant{62:12}
*
*	    	---------------   ---------------    ---------------
*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
*	    	---------------   ---------------    ---------------
*	   	 95	    64    63 62	      32      31     11	  0
*				     |			     |
*				     |			     |
*				     |			     |
*		 	             v   		     v
*	    		      ---------------   ---------------
*  double   ->  	      |s|exp| mant  |   |  mant       |
*	    		      ---------------   ---------------
*	   	 	      63     51   32   31	       0
*
dest_dbl:
	clr.l	d0		;clear d0
	move.w	LOCAL_EX(a1),d0	;get exponent
	sub.w	#$3fff,d0	;subtract extended precision bias
	cmp.w	#$4000,d0	;check if inf
	beq.b	inf		;if so, special case
	add.w	#$3ff,d0	;add double precision bias
	swap	d0		;d0 now in upper word
	lsl.l	#4,d0		;d0 now in proper place for dbl prec exp
	tst.b	LOCAL_SGN(a1)	
	beq.b	get_mant	;if postive, go process mantissa
	bset.l	#31,d0		;if negative, put in sign information
*				; before continuing
	bra.b	get_mant	;go process mantissa
inf:
	move.l	#$7ff00000,d0	;load dbl inf exponent
	clr.l	LOCAL_HI(a1)	;clear msb
	tst.b	LOCAL_SGN(a1)
	beq.b	dbl_inf		;if positive, go ahead and write it
	bset.l	#31,d0		;if negative put in sign information
dbl_inf:
	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
	bra.b	dbl_wrt
get_mant:
	move.l	LOCAL_HI(a1),d1	;get ms mantissa
	bfextu	d1{1:20},d1	;get upper 20 bits of ms
	or.l	d1,d0		;put these bits in ms word of double
	move.l	d0,LOCAL_EX(a1)	;put the new exp back on the stack
	move.l	LOCAL_HI(a1),d1	;get ms mantissa
	move.l	#21,d0		;load shift count
	lsl.l	d0,d1		;put lower 11 bits in upper bits
	move.l	d1,LOCAL_HI(a1)	;build lower lword in memory
	move.l	LOCAL_LO(a1),d1	;get ls mantissa
	bfextu	d1{0:21},d0	;get ls 21 bits of double
	or.l	d0,LOCAL_HI(a1)	;put them in double result
dbl_wrt:
	move.l	#$8,d0		;byte count for double precision number
	exg	a0,a1		;a0=supervisor source, a1=user dest
	bsr.l	mem_write	;move the number to the user's memory
	rts
*
*	dest_sgl --- write single precision value to user space
*
*Input
*	a0 -> destination address
*	a1 -> source in extended precision
*
*Output
*	a0 -> destroyed
*	a1 -> destroyed
*	d0 -> 0
*
*Changes extended precision to single precision.
*	sgl_sign = ext_sign
*	sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
*	get rid of ext integer bit
*	sgl_mant = ext_mant{62:12}
*
*	    	---------------   ---------------    ---------------
*  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
*	    	---------------   ---------------    ---------------
*	   	 95	    64    63 62	   40 32      31     12	  0
*				     |	   |
*				     |	   |
*				     |	   |
*		 	             v     v
*	    		      ---------------
*  single   ->  	      |s|exp| mant  |
*	    		      ---------------
*	   	 	      31     22     0
*
dest_sgl:
	clr.l	d0
	move.w	LOCAL_EX(a1),d0	;get exponent
	sub.w	#$3fff,d0	;subtract extended precision bias
	cmp.w	#$4000,d0	;check if inf
	beq.b	sinf		;if so, special case
	add.w	#$7f,d0		;add single precision bias
	swap	d0		;put exp in upper word of d0
	lsl.l	#7,d0		;shift it into single exp bits
	tst.b	LOCAL_SGN(a1)	
	beq.b	get_sman	;if positive, continue
	bset.l	#31,d0		;if negative, put in sign first
	bra.b	get_sman	;get mantissa
sinf:
	move.l	#$7f800000,d0	;load single inf exp to d0
	tst.b	LOCAL_SGN(a1)
	beq.b	sgl_wrt		;if positive, continue
	bset.l	#31,d0		;if negative, put in sign info
	bra.b	sgl_wrt

get_sman:
	move.l	LOCAL_HI(a1),d1	;get ms mantissa
	bfextu	d1{1:23},d1	;get upper 23 bits of ms
	or.l	d1,d0		;put these bits in ms word of single

sgl_wrt:
	move.l	d0,L_SCR1(a6)	;put the new exp back on the stack
	move.l	#$4,d0		;byte count for single precision number
	tst.l	a0		;users destination address
	beq.b	sgl_Dn		;destination is a data register
	exg	a0,a1		;a0=supervisor source, a1=user dest
	lea.l	L_SCR1(a6),a0	;point a0 to data
	bsr.l	mem_write	;move the number to the user's memory
	rts
sgl_Dn:
	bsr.l	get_fline	;returns fline word in d0
	and.w	#$7,d0		;isolate register number
	move.l	d0,d1		;d1 has size:reg formatted for reg_dest
	or.l	#$10,d1		;reg_dest wants size added to reg#
	bra.l	reg_dest	;size is X, rts in reg_dest will
*				;return to caller of dest_sgl
	
dest_ext:
	tst.b	LOCAL_SGN(a1)	;put back sign into exponent word
	beq.b	dstx_cont
	bset.b	#sign_bit,LOCAL_EX(a1)
dstx_cont:
	clr.b	LOCAL_SGN(a1)	;clear out the sign byte

	move.l	#$0c,d0		;byte count for extended number
	exg	a0,a1		;a0=supervisor source, a1=user dest
	bsr.l	mem_write	;move the number to the user's memory
	rts

	end