cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

do_func.S (13813B)


      1|
      2|	do_func.sa 3.4 2/18/91
      3|
      4| Do_func performs the unimplemented operation.  The operation
      5| to be performed is determined from the lower 7 bits of the
      6| extension word (except in the case of fmovecr and fsincos).
      7| The opcode and tag bits form an index into a jump table in
      8| tbldo.sa.  Cases of zero, infinity and NaN are handled in
      9| do_func by forcing the default result.  Normalized and
     10| denormalized (there are no unnormalized numbers at this
     11| point) are passed onto the emulation code.
     12|
     13| CMDREG1B and STAG are extracted from the fsave frame
     14| and combined to form the table index.  The function called
     15| will start with a0 pointing to the ETEMP operand.  Dyadic
     16| functions can find FPTEMP at -12(a0).
     17|
     18| Called functions return their result in fp0.  Sincos returns
     19| sin(x) in fp0 and cos(x) in fp1.
     20|
     21
     22|		Copyright (C) Motorola, Inc. 1990
     23|			All Rights Reserved
     24|
     25|       For details on the license for this file, please see the
     26|       file, README, in this same directory.
     27
     28DO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
     29
     30	|section	8
     31
     32#include "fpsp.h"
     33
     34	|xref	t_dz2
     35	|xref	t_operr
     36	|xref	t_inx2
     37	|xref	t_resdnrm
     38	|xref	dst_nan
     39	|xref	src_nan
     40	|xref	nrm_set
     41	|xref	sto_cos
     42
     43	|xref	tblpre
     44	|xref	slognp1,slogn,slog10,slog2
     45	|xref	slognd,slog10d,slog2d
     46	|xref	smod,srem
     47	|xref	sscale
     48	|xref	smovcr
     49
     50PONE:	.long	0x3fff0000,0x80000000,0x00000000	|+1
     51MONE:	.long	0xbfff0000,0x80000000,0x00000000	|-1
     52PZERO:	.long	0x00000000,0x00000000,0x00000000	|+0
     53MZERO:	.long	0x80000000,0x00000000,0x00000000	|-0
     54PINF:	.long	0x7fff0000,0x00000000,0x00000000	|+inf
     55MINF:	.long	0xffff0000,0x00000000,0x00000000	|-inf
     56QNAN:	.long	0x7fff0000,0xffffffff,0xffffffff	|non-signaling nan
     57PPIBY2:  .long	0x3FFF0000,0xC90FDAA2,0x2168C235	|+PI/2
     58MPIBY2:  .long	0xbFFF0000,0xC90FDAA2,0x2168C235	|-PI/2
     59
     60	.global	do_func
     61do_func:
     62	clrb	CU_ONLY(%a6)
     63|
     64| Check for fmovecr.  It does not follow the format of fp gen
     65| unimplemented instructions.  The test is on the upper 6 bits;
     66| if they are $17, the inst is fmovecr.  Call entry smovcr
     67| directly.
     68|
     69	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
     70	cmpil	#0x17,%d0		|if op class and size fields are $17,
     71|				;it is FMOVECR; if not, continue
     72	bnes	not_fmovecr
     73	jmp	smovcr		|fmovecr; jmp directly to emulation
     74
     75not_fmovecr:
     76	movew	CMDREG1B(%a6),%d0
     77	andl	#0x7F,%d0
     78	cmpil	#0x38,%d0		|if the extension is >= $38,
     79	bge	serror		|it is illegal
     80	bfextu	STAG(%a6){#0:#3},%d1
     81	lsll	#3,%d0		|make room for STAG
     82	addl	%d1,%d0		|combine for final index into table
     83	leal	tblpre,%a1	|start of monster jump table
     84	movel	(%a1,%d0.w*4),%a1	|real target address
     85	leal	ETEMP(%a6),%a0	|a0 is pointer to src op
     86	movel	USER_FPCR(%a6),%d1
     87	andl	#0xFF,%d1		| discard all but rounding mode/prec
     88	fmovel	#0,%fpcr
     89	jmp	(%a1)
     90|
     91|	ERROR
     92|
     93	.global	serror
     94serror:
     95	st	STORE_FLG(%a6)
     96	rts
     97|
     98| These routines load forced values into fp0.  They are called
     99| by index into tbldo.
    100|
    101| Load a signed zero to fp0 and set inex2/ainex
    102|
    103	.global	snzrinx
    104snzrinx:
    105	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
    106	bnes	ld_mzinx	|if negative, branch
    107	bsr	ld_pzero	|bsr so we can return and set inx
    108	bra	t_inx2		|now, set the inx for the next inst
    109ld_mzinx:
    110	bsr	ld_mzero	|if neg, load neg zero, return here
    111	bra	t_inx2		|now, set the inx for the next inst
    112|
    113| Load a signed zero to fp0; do not set inex2/ainex
    114|
    115	.global	szero
    116szero:
    117	btstb	#sign_bit,LOCAL_EX(%a0) |get sign of source operand
    118	bne	ld_mzero	|if neg, load neg zero
    119	bra	ld_pzero	|load positive zero
    120|
    121| Load a signed infinity to fp0; do not set inex2/ainex
    122|
    123	.global	sinf
    124sinf:
    125	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
    126	bne	ld_minf			|if negative branch
    127	bra	ld_pinf
    128|
    129| Load a signed one to fp0; do not set inex2/ainex
    130|
    131	.global	sone
    132sone:
    133	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
    134	bne	ld_mone
    135	bra	ld_pone
    136|
    137| Load a signed pi/2 to fp0; do not set inex2/ainex
    138|
    139	.global	spi_2
    140spi_2:
    141	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
    142	bne	ld_mpi2
    143	bra	ld_ppi2
    144|
    145| Load either a +0 or +inf for plus/minus operand
    146|
    147	.global	szr_inf
    148szr_inf:
    149	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
    150	bne	ld_pzero
    151	bra	ld_pinf
    152|
    153| Result is either an operr or +inf for plus/minus operand
    154| [Used by slogn, slognp1, slog10, and slog2]
    155|
    156	.global	sopr_inf
    157sopr_inf:
    158	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
    159	bne	t_operr
    160	bra	ld_pinf
    161|
    162|	FLOGNP1
    163|
    164	.global	sslognp1
    165sslognp1:
    166	fmovemx (%a0),%fp0-%fp0
    167	fcmpb	#-1,%fp0
    168	fbgt	slognp1
    169	fbeq	t_dz2		|if = -1, divide by zero exception
    170	fmovel	#0,%FPSR		|clr N flag
    171	bra	t_operr		|take care of operands < -1
    172|
    173|	FETOXM1
    174|
    175	.global	setoxm1i
    176setoxm1i:
    177	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
    178	bne	ld_mone
    179	bra	ld_pinf
    180|
    181|	FLOGN
    182|
    183| Test for 1.0 as an input argument, returning +zero.  Also check
    184| the sign and return operr if negative.
    185|
    186	.global	sslogn
    187sslogn:
    188	btstb	#sign_bit,LOCAL_EX(%a0)
    189	bne	t_operr		|take care of operands < 0
    190	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
    191	bne	slogn
    192	cmpil	#0x80000000,LOCAL_HI(%a0)
    193	bne	slogn
    194	tstl	LOCAL_LO(%a0)
    195	bne	slogn
    196	fmovex	PZERO,%fp0
    197	rts
    198
    199	.global	sslognd
    200sslognd:
    201	btstb	#sign_bit,LOCAL_EX(%a0)
    202	beq	slognd
    203	bra	t_operr		|take care of operands < 0
    204
    205|
    206|	FLOG10
    207|
    208	.global	sslog10
    209sslog10:
    210	btstb	#sign_bit,LOCAL_EX(%a0)
    211	bne	t_operr		|take care of operands < 0
    212	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
    213	bne	slog10
    214	cmpil	#0x80000000,LOCAL_HI(%a0)
    215	bne	slog10
    216	tstl	LOCAL_LO(%a0)
    217	bne	slog10
    218	fmovex	PZERO,%fp0
    219	rts
    220
    221	.global	sslog10d
    222sslog10d:
    223	btstb	#sign_bit,LOCAL_EX(%a0)
    224	beq	slog10d
    225	bra	t_operr		|take care of operands < 0
    226
    227|
    228|	FLOG2
    229|
    230	.global	sslog2
    231sslog2:
    232	btstb	#sign_bit,LOCAL_EX(%a0)
    233	bne	t_operr		|take care of operands < 0
    234	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
    235	bne	slog2
    236	cmpil	#0x80000000,LOCAL_HI(%a0)
    237	bne	slog2
    238	tstl	LOCAL_LO(%a0)
    239	bne	slog2
    240	fmovex	PZERO,%fp0
    241	rts
    242
    243	.global	sslog2d
    244sslog2d:
    245	btstb	#sign_bit,LOCAL_EX(%a0)
    246	beq	slog2d
    247	bra	t_operr		|take care of operands < 0
    248
    249|
    250|	FMOD
    251|
    252pmodt:
    253|				;$21 fmod
    254|				;dtag,stag
    255	.long	smod		|  00,00  norm,norm = normal
    256	.long	smod_oper	|  00,01  norm,zero = nan with operr
    257	.long	smod_fpn	|  00,10  norm,inf  = fpn
    258	.long	smod_snan	|  00,11  norm,nan  = nan
    259	.long	smod_zro	|  01,00  zero,norm = +-zero
    260	.long	smod_oper	|  01,01  zero,zero = nan with operr
    261	.long	smod_zro	|  01,10  zero,inf  = +-zero
    262	.long	smod_snan	|  01,11  zero,nan  = nan
    263	.long	smod_oper	|  10,00  inf,norm  = nan with operr
    264	.long	smod_oper	|  10,01  inf,zero  = nan with operr
    265	.long	smod_oper	|  10,10  inf,inf   = nan with operr
    266	.long	smod_snan	|  10,11  inf,nan   = nan
    267	.long	smod_dnan	|  11,00  nan,norm  = nan
    268	.long	smod_dnan	|  11,01  nan,zero  = nan
    269	.long	smod_dnan	|  11,10  nan,inf   = nan
    270	.long	smod_dnan	|  11,11  nan,nan   = nan
    271
    272	.global	pmod
    273pmod:
    274	clrb	FPSR_QBYTE(%a6) | clear quotient field
    275	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
    276	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
    277
    278|
    279| Alias extended denorms to norms for the jump table.
    280|
    281	bclrl	#2,%d0
    282	bclrl	#2,%d1
    283
    284	lslb	#2,%d1
    285	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
    286|				;Tag values:
    287|				;00 = norm or denorm
    288|				;01 = zero
    289|				;10 = inf
    290|				;11 = nan
    291	lea	pmodt,%a1
    292	movel	(%a1,%d1.w*4),%a1
    293	jmp	(%a1)
    294
    295smod_snan:
    296	bra	src_nan
    297smod_dnan:
    298	bra	dst_nan
    299smod_oper:
    300	bra	t_operr
    301smod_zro:
    302	moveb	ETEMP(%a6),%d1	|get sign of src op
    303	moveb	FPTEMP(%a6),%d0	|get sign of dst op
    304	eorb	%d0,%d1		|get exor of sign bits
    305	btstl	#7,%d1		|test for sign
    306	beqs	smod_zsn	|if clr, do not set sign big
    307	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
    308smod_zsn:
    309	btstl	#7,%d0		|test if + or -
    310	beq	ld_pzero	|if pos then load +0
    311	bra	ld_mzero	|else neg load -0
    312
    313smod_fpn:
    314	moveb	ETEMP(%a6),%d1	|get sign of src op
    315	moveb	FPTEMP(%a6),%d0	|get sign of dst op
    316	eorb	%d0,%d1		|get exor of sign bits
    317	btstl	#7,%d1		|test for sign
    318	beqs	smod_fsn	|if clr, do not set sign big
    319	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
    320smod_fsn:
    321	tstb	DTAG(%a6)	|filter out denormal destination case
    322	bpls	smod_nrm	|
    323	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
    324	bra	t_resdnrm	|force UNFL(but exact) result
    325smod_nrm:
    326	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
    327	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
    328	rts
    329
    330|
    331|	FREM
    332|
    333premt:
    334|				;$25 frem
    335|				;dtag,stag
    336	.long	srem		|  00,00  norm,norm = normal
    337	.long	srem_oper	|  00,01  norm,zero = nan with operr
    338	.long	srem_fpn	|  00,10  norm,inf  = fpn
    339	.long	srem_snan	|  00,11  norm,nan  = nan
    340	.long	srem_zro	|  01,00  zero,norm = +-zero
    341	.long	srem_oper	|  01,01  zero,zero = nan with operr
    342	.long	srem_zro	|  01,10  zero,inf  = +-zero
    343	.long	srem_snan	|  01,11  zero,nan  = nan
    344	.long	srem_oper	|  10,00  inf,norm  = nan with operr
    345	.long	srem_oper	|  10,01  inf,zero  = nan with operr
    346	.long	srem_oper	|  10,10  inf,inf   = nan with operr
    347	.long	srem_snan	|  10,11  inf,nan   = nan
    348	.long	srem_dnan	|  11,00  nan,norm  = nan
    349	.long	srem_dnan	|  11,01  nan,zero  = nan
    350	.long	srem_dnan	|  11,10  nan,inf   = nan
    351	.long	srem_dnan	|  11,11  nan,nan   = nan
    352
    353	.global	prem
    354prem:
    355	clrb	FPSR_QBYTE(%a6)   |clear quotient field
    356	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
    357	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
    358|
    359| Alias extended denorms to norms for the jump table.
    360|
    361	bclr	#2,%d0
    362	bclr	#2,%d1
    363
    364	lslb	#2,%d1
    365	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
    366|				;Tag values:
    367|				;00 = norm or denorm
    368|				;01 = zero
    369|				;10 = inf
    370|				;11 = nan
    371	lea	premt,%a1
    372	movel	(%a1,%d1.w*4),%a1
    373	jmp	(%a1)
    374
    375srem_snan:
    376	bra	src_nan
    377srem_dnan:
    378	bra	dst_nan
    379srem_oper:
    380	bra	t_operr
    381srem_zro:
    382	moveb	ETEMP(%a6),%d1	|get sign of src op
    383	moveb	FPTEMP(%a6),%d0	|get sign of dst op
    384	eorb	%d0,%d1		|get exor of sign bits
    385	btstl	#7,%d1		|test for sign
    386	beqs	srem_zsn	|if clr, do not set sign big
    387	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
    388srem_zsn:
    389	btstl	#7,%d0		|test if + or -
    390	beq	ld_pzero	|if pos then load +0
    391	bra	ld_mzero	|else neg load -0
    392
    393srem_fpn:
    394	moveb	ETEMP(%a6),%d1	|get sign of src op
    395	moveb	FPTEMP(%a6),%d0	|get sign of dst op
    396	eorb	%d0,%d1		|get exor of sign bits
    397	btstl	#7,%d1		|test for sign
    398	beqs	srem_fsn	|if clr, do not set sign big
    399	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
    400srem_fsn:
    401	tstb	DTAG(%a6)	|filter out denormal destination case
    402	bpls	srem_nrm	|
    403	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
    404	bra	t_resdnrm	|force UNFL(but exact) result
    405srem_nrm:
    406	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
    407	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
    408	rts
    409|
    410|	FSCALE
    411|
    412pscalet:
    413|				;$26 fscale
    414|				;dtag,stag
    415	.long	sscale		|  00,00  norm,norm = result
    416	.long	sscale		|  00,01  norm,zero = fpn
    417	.long	scl_opr		|  00,10  norm,inf  = nan with operr
    418	.long	scl_snan	|  00,11  norm,nan  = nan
    419	.long	scl_zro		|  01,00  zero,norm = +-zero
    420	.long	scl_zro		|  01,01  zero,zero = +-zero
    421	.long	scl_opr		|  01,10  zero,inf  = nan with operr
    422	.long	scl_snan	|  01,11  zero,nan  = nan
    423	.long	scl_inf		|  10,00  inf,norm  = +-inf
    424	.long	scl_inf		|  10,01  inf,zero  = +-inf
    425	.long	scl_opr		|  10,10  inf,inf   = nan with operr
    426	.long	scl_snan	|  10,11  inf,nan   = nan
    427	.long	scl_dnan	|  11,00  nan,norm  = nan
    428	.long	scl_dnan	|  11,01  nan,zero  = nan
    429	.long	scl_dnan	|  11,10  nan,inf   = nan
    430	.long	scl_dnan	|  11,11  nan,nan   = nan
    431
    432	.global	pscale
    433pscale:
    434	bfextu	STAG(%a6){#0:#3},%d0 |stag in d0
    435	bfextu	DTAG(%a6){#0:#3},%d1 |dtag in d1
    436	bclrl	#2,%d0		|alias  denorm into norm
    437	bclrl	#2,%d1		|alias  denorm into norm
    438	lslb	#2,%d1
    439	orb	%d0,%d1		|d1{4:2} = dtag, d1{1:0} = stag
    440|				;dtag values     stag values:
    441|				;000 = norm      00 = norm
    442|				;001 = zero	 01 = zero
    443|				;010 = inf	 10 = inf
    444|				;011 = nan	 11 = nan
    445|				;100 = dnrm
    446|
    447|
    448	leal	pscalet,%a1	|load start of jump table
    449	movel	(%a1,%d1.w*4),%a1	|load a1 with label depending on tag
    450	jmp	(%a1)		|go to the routine
    451
    452scl_opr:
    453	bra	t_operr
    454
    455scl_dnan:
    456	bra	dst_nan
    457
    458scl_zro:
    459	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
    460	beq	ld_pzero		|if pos then load +0
    461	bra	ld_mzero		|if neg then load -0
    462scl_inf:
    463	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
    464	beq	ld_pinf			|if pos then load +inf
    465	bra	ld_minf			|else neg load -inf
    466scl_snan:
    467	bra	src_nan
    468|
    469|	FSINCOS
    470|
    471	.global	ssincosz
    472ssincosz:
    473	btstb	#sign_bit,ETEMP(%a6)	|get sign
    474	beqs	sincosp
    475	fmovex	MZERO,%fp0
    476	bras	sincoscom
    477sincosp:
    478	fmovex PZERO,%fp0
    479sincoscom:
    480	fmovemx PONE,%fp1-%fp1	|do not allow FPSR to be affected
    481	bra	sto_cos		|store cosine result
    482
    483	.global	ssincosi
    484ssincosi:
    485	fmovex QNAN,%fp1	|load NAN
    486	bsr	sto_cos		|store cosine result
    487	fmovex QNAN,%fp0	|load NAN
    488	bra	t_operr
    489
    490	.global	ssincosnan
    491ssincosnan:
    492	movel	ETEMP_EX(%a6),FP_SCR1(%a6)
    493	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
    494	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
    495	bsetb	#signan_bit,FP_SCR1+4(%a6)
    496	fmovemx FP_SCR1(%a6),%fp1-%fp1
    497	bsr	sto_cos
    498	bra	src_nan
    499|
    500| This code forces default values for the zero, inf, and nan cases
    501| in the transcendentals code.  The CC bits must be set in the
    502| stacked FPSR to be correctly reported.
    503|
    504|**Returns +PI/2
    505	.global	ld_ppi2
    506ld_ppi2:
    507	fmovex PPIBY2,%fp0		|load +pi/2
    508	bra	t_inx2			|set inex2 exc
    509
    510|**Returns -PI/2
    511	.global	ld_mpi2
    512ld_mpi2:
    513	fmovex MPIBY2,%fp0		|load -pi/2
    514	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
    515	bra	t_inx2			|set inex2 exc
    516
    517|**Returns +inf
    518	.global	ld_pinf
    519ld_pinf:
    520	fmovex PINF,%fp0		|load +inf
    521	orl	#inf_mask,USER_FPSR(%a6)	|set I bit
    522	rts
    523
    524|**Returns -inf
    525	.global	ld_minf
    526ld_minf:
    527	fmovex MINF,%fp0		|load -inf
    528	orl	#neg_mask+inf_mask,USER_FPSR(%a6)	|set N and I bits
    529	rts
    530
    531|**Returns +1
    532	.global	ld_pone
    533ld_pone:
    534	fmovex PONE,%fp0		|load +1
    535	rts
    536
    537|**Returns -1
    538	.global	ld_mone
    539ld_mone:
    540	fmovex MONE,%fp0		|load -1
    541	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
    542	rts
    543
    544|**Returns +0
    545	.global	ld_pzero
    546ld_pzero:
    547	fmovex PZERO,%fp0		|load +0
    548	orl	#z_mask,USER_FPSR(%a6)	|set Z bit
    549	rts
    550
    551|**Returns -0
    552	.global	ld_mzero
    553ld_mzero:
    554	fmovex MZERO,%fp0		|load -0
    555	orl	#neg_mask+z_mask,USER_FPSR(%a6)	|set N and Z bits
    556	rts
    557
    558	|end