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