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