-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfpsp.asm.old
24758 lines (21240 loc) · 743 KB
/
fpsp.asm.old
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#
# freal.s:
# This file is appended to the top of the 060FPSP package
# and contains the entry points into the package. The user, in
# effect, branches to one of the branch table entries located
# after _060FPSP_TABLE.
# Also, subroutine stubs exist in this file (_fpsp_done for
# example) that are referenced by the FPSP package itself in order
# to call a given routine. The stub routine actually performs the
# callout. The FPSP code does a "bsr" to the stub routine. This
# extra layer of hierarchy adds a slight performance penalty but
# it makes the FPSP code easier to read and more mainatinable.
#
set _off_bsun, 0x00
set _off_snan, 0x04
set _off_operr, 0x08
set _off_ovfl, 0x0c
set _off_unfl, 0x10
set _off_dz, 0x14
set _off_inex, 0x18
set _off_fline, 0x1c
set _off_fpu_dis, 0x20
set _off_trap, 0x24
set _off_trace, 0x28
set _off_access, 0x2c
set _off_done, 0x30
set _off_imr, 0x40
set _off_dmr, 0x44
set _off_dmw, 0x48
set _off_irw, 0x4c
set _off_irl, 0x50
set _off_drb, 0x54
set _off_drw, 0x58
set _off_drl, 0x5c
set _off_dwb, 0x60
set _off_dww, 0x64
set _off_dwl, 0x68
_060FPSP_TABLE:
###############################################################
# Here's the table of ENTRY POINTS for those linking the package.
bra.l _fpsp_snan
short 0x0000
bra.l _fpsp_operr
short 0x0000
bra.l _fpsp_ovfl
short 0x0000
bra.l _fpsp_unfl
short 0x0000
bra.l _fpsp_dz
short 0x0000
bra.l _fpsp_inex
short 0x0000
bra.l _fpsp_fline
short 0x0000
bra.l _fpsp_unsupp
short 0x0000
bra.l _fpsp_effadd
short 0x0000
space 56
###############################################################
global _fpsp_done
_fpsp_done:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_ovfl
_real_ovfl:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_unfl
_real_unfl:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_inex
_real_inex:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_bsun
_real_bsun:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_operr
_real_operr:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_snan
_real_snan:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_dz
_real_dz:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_fline
_real_fline:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_fpu_disabled
_real_fpu_disabled:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_trap
_real_trap:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_trace
_real_trace:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_access
_real_access:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
#######################################
global _imem_read
_imem_read:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read
_dmem_read:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write
_dmem_write:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _imem_read_word
_imem_read_word:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _imem_read_long
_imem_read_long:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_byte
_dmem_read_byte:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_word
_dmem_read_word:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_long
_dmem_read_long:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_byte
_dmem_write_byte:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_word
_dmem_write_word:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_long
_dmem_write_long:
mov.l %d0,-(%sp)
mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
#
# This file contains a set of define statements for constants
# in order to promote readability within the corecode itself.
#
set LOCAL_SIZE, 192 # stack frame size(bytes)
set LV, -LOCAL_SIZE # stack offset
set EXC_SR, 0x4 # stack status register
set EXC_PC, 0x6 # stack pc
set EXC_VOFF, 0xa # stacked vector offset
set EXC_EA, 0xc # stacked <ea>
set EXC_FP, 0x0 # frame pointer
set EXC_AREGS, -68 # offset of all address regs
set EXC_DREGS, -100 # offset of all data regs
set EXC_FPREGS, -36 # offset of all fp regs
set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
set EXC_A5, EXC_AREGS+(5*4)
set EXC_A4, EXC_AREGS+(4*4)
set EXC_A3, EXC_AREGS+(3*4)
set EXC_A2, EXC_AREGS+(2*4)
set EXC_A1, EXC_AREGS+(1*4)
set EXC_A0, EXC_AREGS+(0*4)
set EXC_D7, EXC_DREGS+(7*4)
set EXC_D6, EXC_DREGS+(6*4)
set EXC_D5, EXC_DREGS+(5*4)
set EXC_D4, EXC_DREGS+(4*4)
set EXC_D3, EXC_DREGS+(3*4)
set EXC_D2, EXC_DREGS+(2*4)
set EXC_D1, EXC_DREGS+(1*4)
set EXC_D0, EXC_DREGS+(0*4)
set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
set FP_SCR1, LV+80 # fp scratch 1
set FP_SCR1_EX, FP_SCR1+0
set FP_SCR1_SGN, FP_SCR1+2
set FP_SCR1_HI, FP_SCR1+4
set FP_SCR1_LO, FP_SCR1+8
set FP_SCR0, LV+68 # fp scratch 0
set FP_SCR0_EX, FP_SCR0+0
set FP_SCR0_SGN, FP_SCR0+2
set FP_SCR0_HI, FP_SCR0+4
set FP_SCR0_LO, FP_SCR0+8
set FP_DST, LV+56 # fp destination operand
set FP_DST_EX, FP_DST+0
set FP_DST_SGN, FP_DST+2
set FP_DST_HI, FP_DST+4
set FP_DST_LO, FP_DST+8
set FP_SRC, LV+44 # fp source operand
set FP_SRC_EX, FP_SRC+0
set FP_SRC_SGN, FP_SRC+2
set FP_SRC_HI, FP_SRC+4
set FP_SRC_LO, FP_SRC+8
set USER_FPIAR, LV+40 # FP instr address register
set USER_FPSR, LV+36 # FP status register
set FPSR_CC, USER_FPSR+0 # FPSR condition codes
set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
set USER_FPCR, LV+32 # FP control register
set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
set L_SCR3, LV+28 # integer scratch 3
set L_SCR2, LV+24 # integer scratch 2
set L_SCR1, LV+20 # integer scratch 1
set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
set EXC_TEMP2, LV+24 # temporary space
set EXC_TEMP, LV+16 # temporary space
set DTAG, LV+15 # destination operand type
set STAG, LV+14 # source operand type
set SPCOND_FLG, LV+10 # flag: special case (see below)
set EXC_CC, LV+8 # saved condition codes
set EXC_EXTWPTR, LV+4 # saved current PC (active)
set EXC_EXTWORD, LV+2 # saved extension word
set EXC_CMDREG, LV+2 # saved extension word
set EXC_OPWORD, LV+0 # saved operation word
################################
# Helpful macros
set FTEMP, 0 # offsets within an
set FTEMP_EX, 0 # extended precision
set FTEMP_SGN, 2 # value saved in memory.
set FTEMP_HI, 4
set FTEMP_LO, 8
set FTEMP_GRS, 12
set LOCAL, 0 # offsets within an
set LOCAL_EX, 0 # extended precision
set LOCAL_SGN, 2 # value saved in memory.
set LOCAL_HI, 4
set LOCAL_LO, 8
set LOCAL_GRS, 12
set DST, 0 # offsets within an
set DST_EX, 0 # extended precision
set DST_HI, 4 # value saved in memory.
set DST_LO, 8
set SRC, 0 # offsets within an
set SRC_EX, 0 # extended precision
set SRC_HI, 4 # value saved in memory.
set SRC_LO, 8
set SGL_LO, 0x3f81 # min sgl prec exponent
set SGL_HI, 0x407e # max sgl prec exponent
set DBL_LO, 0x3c01 # min dbl prec exponent
set DBL_HI, 0x43fe # max dbl prec exponent
set EXT_LO, 0x0 # min ext prec exponent
set EXT_HI, 0x7ffe # max ext prec exponent
set EXT_BIAS, 0x3fff # extended precision bias
set SGL_BIAS, 0x007f # single precision bias
set DBL_BIAS, 0x03ff # double precision bias
set NORM, 0x00 # operand type for STAG/DTAG
set ZERO, 0x01 # operand type for STAG/DTAG
set INF, 0x02 # operand type for STAG/DTAG
set QNAN, 0x03 # operand type for STAG/DTAG
set DENORM, 0x04 # operand type for STAG/DTAG
set SNAN, 0x05 # operand type for STAG/DTAG
set UNNORM, 0x06 # operand type for STAG/DTAG
##################
# FPSR/FPCR bits #
##################
set neg_bit, 0x3 # negative result
set z_bit, 0x2 # zero result
set inf_bit, 0x1 # infinite result
set nan_bit, 0x0 # NAN result
set q_sn_bit, 0x7 # sign bit of quotient byte
set bsun_bit, 7 # branch on unordered
set snan_bit, 6 # signalling NAN
set operr_bit, 5 # operand error
set ovfl_bit, 4 # overflow
set unfl_bit, 3 # underflow
set dz_bit, 2 # divide by zero
set inex2_bit, 1 # inexact result 2
set inex1_bit, 0 # inexact result 1
set aiop_bit, 7 # accrued inexact operation bit
set aovfl_bit, 6 # accrued overflow bit
set aunfl_bit, 5 # accrued underflow bit
set adz_bit, 4 # accrued dz bit
set ainex_bit, 3 # accrued inexact bit
#############################
# FPSR individual bit masks #
#############################
set neg_mask, 0x08000000 # negative bit mask (lw)
set inf_mask, 0x02000000 # infinity bit mask (lw)
set z_mask, 0x04000000 # zero bit mask (lw)
set nan_mask, 0x01000000 # nan bit mask (lw)
set neg_bmask, 0x08 # negative bit mask (byte)
set inf_bmask, 0x02 # infinity bit mask (byte)
set z_bmask, 0x04 # zero bit mask (byte)
set nan_bmask, 0x01 # nan bit mask (byte)
set bsun_mask, 0x00008000 # bsun exception mask
set snan_mask, 0x00004000 # snan exception mask
set operr_mask, 0x00002000 # operr exception mask
set ovfl_mask, 0x00001000 # overflow exception mask
set unfl_mask, 0x00000800 # underflow exception mask
set dz_mask, 0x00000400 # dz exception mask
set inex2_mask, 0x00000200 # inex2 exception mask
set inex1_mask, 0x00000100 # inex1 exception mask
set aiop_mask, 0x00000080 # accrued illegal operation
set aovfl_mask, 0x00000040 # accrued overflow
set aunfl_mask, 0x00000020 # accrued underflow
set adz_mask, 0x00000010 # accrued divide by zero
set ainex_mask, 0x00000008 # accrued inexact
######################################
# FPSR combinations used in the FPSP #
######################################
set dzinf_mask, inf_mask+dz_mask+adz_mask
set opnan_mask, nan_mask+operr_mask+aiop_mask
set nzi_mask, 0x01ffffff #clears N, Z, and I
set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
set inx1a_mask, inex1_mask+ainex_mask
set inx2a_mask, inex2_mask+ainex_mask
set snaniop_mask, nan_mask+snan_mask+aiop_mask
set snaniop2_mask, snan_mask+aiop_mask
set naniop_mask, nan_mask+aiop_mask
set neginf_mask, neg_mask+inf_mask
set infaiop_mask, inf_mask+aiop_mask
set negz_mask, neg_mask+z_mask
set opaop_mask, operr_mask+aiop_mask
set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
#########
# misc. #
#########
set rnd_stky_bit, 29 # stky bit pos in longword
set sign_bit, 0x7 # sign bit
set signan_bit, 0x6 # signalling nan bit
set sgl_thresh, 0x3f81 # minimum sgl exponent
set dbl_thresh, 0x3c01 # minimum dbl exponent
set x_mode, 0x0 # extended precision
set s_mode, 0x4 # single precision
set d_mode, 0x8 # double precision
set rn_mode, 0x0 # round-to-nearest
set rz_mode, 0x1 # round-to-zero
set rm_mode, 0x2 # round-tp-minus-infinity
set rp_mode, 0x3 # round-to-plus-infinity
set mantissalen, 64 # length of mantissa in bits
set BYTE, 1 # len(byte) == 1 byte
set WORD, 2 # len(word) == 2 bytes
set LONG, 4 # len(longword) == 2 bytes
set BSUN_VEC, 0xc0 # bsun vector offset
set INEX_VEC, 0xc4 # inexact vector offset
set DZ_VEC, 0xc8 # dz vector offset
set UNFL_VEC, 0xcc # unfl vector offset
set OPERR_VEC, 0xd0 # operr vector offset
set OVFL_VEC, 0xd4 # ovfl vector offset
set SNAN_VEC, 0xd8 # snan vector offset
###########################
# SPecial CONDition FLaGs #
###########################
set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
set fbsun_flg, 0x02 # flag bit: bsun exception
set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
set mda7_flg, 0x08 # flag bit: -(a7) <ea>
set fmovm_flg, 0x40 # flag bit: fmovm instruction
set immed_flg, 0x80 # flag bit: &<data> <ea>
set ftrapcc_bit, 0x0
set fbsun_bit, 0x1
set mia7_bit, 0x2
set mda7_bit, 0x3
set immed_bit, 0x7
##################################
# TRANSCENDENTAL "LAST-OP" FLAGS #
##################################
set FMUL_OP, 0x0 # fmul instr performed last
set FDIV_OP, 0x1 # fdiv performed last
set FADD_OP, 0x2 # fadd performed last
set FMOV_OP, 0x3 # fmov performed last
#############
# CONSTANTS #
#############
T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
TWOBYPI:
long 0x3FE45F30,0x6DC9C883
#########################################################################
# XDEF **************************************************************** #
# _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
# #
# This handler should be the first code executed upon taking the #
# FP Overflow exception in an operating system. #
# #
# XREF **************************************************************** #
# _imem_read_long() - read instruction longword #
# fix_skewed_ops() - adjust src operand in fsave frame #
# set_tag_x() - determine optype of src/dst operands #
# store_fpreg() - store opclass 0 or 2 result to FP regfile #
# unnorm_fix() - change UNNORM operands to NORM or ZERO #
# load_fpn2() - load dst operand from FP regfile #
# fout() - emulate an opclass 3 instruction #
# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
# _real_ovfl() - "callout" for Overflow exception enabled code #
# _real_inex() - "callout" for Inexact exception enabled code #
# _real_trace() - "callout" for Trace exception code #
# #
# INPUT *************************************************************** #
# - The system stack contains the FP Ovfl exception stack frame #
# - The fsave frame contains the source operand #
# #
# OUTPUT ************************************************************** #
# Overflow Exception enabled: #
# - The system stack is unchanged #
# - The fsave frame contains the adjusted src op for opclass 0,2 #
# Overflow Exception disabled: #
# - The system stack is unchanged #
# - The "exception present" flag in the fsave frame is cleared #
# #
# ALGORITHM *********************************************************** #
# On the 060, if an FP overflow is present as the result of any #
# instruction, the 060 will take an overflow exception whether the #
# exception is enabled or disabled in the FPCR. For the disabled case, #
# This handler emulates the instruction to determine what the correct #
# default result should be for the operation. This default result is #
# then stored in either the FP regfile, data regfile, or memory. #
# Finally, the handler exits through the "callout" _fpsp_done() #
# denoting that no exceptional conditions exist within the machine. #
# If the exception is enabled, then this handler must create the #
# exceptional operand and plave it in the fsave state frame, and store #
# the default result (only if the instruction is opclass 3). For #
# exceptions enabled, this handler must exit through the "callout" #
# _real_ovfl() so that the operating system enabled overflow handler #
# can handle this case. #
# Two other conditions exist. First, if overflow was disabled #
# but the inexact exception was enabled, this handler must exit #
# through the "callout" _real_inex() regardless of whether the result #
# was inexact. #
# Also, in the case of an opclass three instruction where #
# overflow was disabled and the trace exception was enabled, this #
# handler must exit through the "callout" _real_trace(). #
# #
#########################################################################
global _fpsp_ovfl
_fpsp_ovfl:
#$# sub.l &24,%sp # make room for src/dst
link.w %a6,&-LOCAL_SIZE # init stack frame
fsave FP_SRC(%a6) # grab the "busy" frame
movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
# the FPIAR holds the "current PC" of the faulting instruction
mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
bsr.l _imem_read_long # fetch the instruction words
mov.l %d0,EXC_OPWORD(%a6)
##############################################################################
btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
bne.w fovfl_out
lea FP_SRC(%a6),%a0 # pass: ptr to src op
bsr.l fix_skewed_ops # fix src op
# since, I believe, only NORMs and DENORMs can come through here,
# maybe we can avoid the subroutine call.
lea FP_SRC(%a6),%a0 # pass: ptr to src op
bsr.l set_tag_x # tag the operand type
mov.b %d0,STAG(%a6) # maybe NORM,DENORM
# bit five of the fp extension word separates the monadic and dyadic operations
# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
# will never take this exception.
btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
beq.b fovfl_extract # monadic
bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
bsr.l load_fpn2 # load dst into FP_DST
lea FP_DST(%a6),%a0 # pass: ptr to dst op
bsr.l set_tag_x # tag the operand type
cmpi.b %d0,&UNNORM # is operand an UNNORM?
bne.b fovfl_op2_done # no
bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
fovfl_op2_done:
mov.b %d0,DTAG(%a6) # save dst optype tag
fovfl_extract:
#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
clr.l %d0
mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
mov.b 1+EXC_CMDREG(%a6),%d1
andi.w &0x007f,%d1 # extract extension
andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
fmov.l &0x0,%fpcr # zero current control regs
fmov.l &0x0,%fpsr
lea FP_SRC(%a6),%a0
lea FP_DST(%a6),%a1
# maybe we can make these entry points ONLY the OVFL entry points of each routine.
mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
jsr (tbl_unsupp.l,%pc,%d1.l*1)
# the operation has been emulated. the result is in fp0.
# the EXOP, if an exception occurred, is in fp1.
# we must save the default result regardless of whether
# traps are enabled or disabled.
bfextu EXC_CMDREG(%a6){&6:&3},%d0
bsr.l store_fpreg
# the exceptional possibilities we have left ourselves with are ONLY overflow
# and inexact. and, the inexact is such that overflow occurred and was disabled
# but inexact was enabled.
btst &ovfl_bit,FPCR_ENABLE(%a6)
bne.b fovfl_ovfl_on
btst &inex2_bit,FPCR_ENABLE(%a6)
bne.b fovfl_inex_on
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
unlk %a6
#$# add.l &24,%sp
bra.l _fpsp_done
# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
# in fp1. now, simply jump to _real_ovfl()!
fovfl_ovfl_on:
fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
mov.w &0xe005,2+FP_SRC(%a6) # save exc status
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
unlk %a6
bra.l _real_ovfl
# overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
# we must jump to real_inex().
fovfl_inex_on:
fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
mov.w &0xe001,2+FP_SRC(%a6) # save exc status
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
unlk %a6
bra.l _real_inex
########################################################################
fovfl_out:
#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
# the src operand is definitely a NORM(!), so tag it as such
mov.b &NORM,STAG(%a6) # set src optype tag
clr.l %d0
mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
fmov.l &0x0,%fpcr # zero current control regs
fmov.l &0x0,%fpsr
lea FP_SRC(%a6),%a0 # pass ptr to src operand
bsr.l fout
btst &ovfl_bit,FPCR_ENABLE(%a6)
bne.w fovfl_ovfl_on
btst &inex2_bit,FPCR_ENABLE(%a6)
bne.w fovfl_inex_on
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
unlk %a6
#$# add.l &24,%sp
btst &0x7,(%sp) # is trace on?
beq.l _fpsp_done # no
fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
bra.l _real_trace
#########################################################################
# XDEF **************************************************************** #
# _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
# #
# This handler should be the first code executed upon taking the #
# FP Underflow exception in an operating system. #
# #
# XREF **************************************************************** #
# _imem_read_long() - read instruction longword #
# fix_skewed_ops() - adjust src operand in fsave frame #
# set_tag_x() - determine optype of src/dst operands #
# store_fpreg() - store opclass 0 or 2 result to FP regfile #
# unnorm_fix() - change UNNORM operands to NORM or ZERO #
# load_fpn2() - load dst operand from FP regfile #
# fout() - emulate an opclass 3 instruction #
# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
# _real_ovfl() - "callout" for Overflow exception enabled code #
# _real_inex() - "callout" for Inexact exception enabled code #
# _real_trace() - "callout" for Trace exception code #
# #
# INPUT *************************************************************** #
# - The system stack contains the FP Unfl exception stack frame #
# - The fsave frame contains the source operand #
# #
# OUTPUT ************************************************************** #
# Underflow Exception enabled: #
# - The system stack is unchanged #
# - The fsave frame contains the adjusted src op for opclass 0,2 #
# Underflow Exception disabled: #
# - The system stack is unchanged #
# - The "exception present" flag in the fsave frame is cleared #
# #
# ALGORITHM *********************************************************** #
# On the 060, if an FP underflow is present as the result of any #
# instruction, the 060 will take an underflow exception whether the #
# exception is enabled or disabled in the FPCR. For the disabled case, #
# This handler emulates the instruction to determine what the correct #
# default result should be for the operation. This default result is #
# then stored in either the FP regfile, data regfile, or memory. #
# Finally, the handler exits through the "callout" _fpsp_done() #
# denoting that no exceptional conditions exist within the machine. #
# If the exception is enabled, then this handler must create the #
# exceptional operand and plave it in the fsave state frame, and store #
# the default result (only if the instruction is opclass 3). For #
# exceptions enabled, this handler must exit through the "callout" #
# _real_unfl() so that the operating system enabled overflow handler #
# can handle this case. #
# Two other conditions exist. First, if underflow was disabled #
# but the inexact exception was enabled and the result was inexact, #
# this handler must exit through the "callout" _real_inex(). #
# was inexact. #
# Also, in the case of an opclass three instruction where #
# underflow was disabled and the trace exception was enabled, this #
# handler must exit through the "callout" _real_trace(). #
# #
#########################################################################
global _fpsp_unfl
_fpsp_unfl:
#$# sub.l &24,%sp # make room for src/dst
link.w %a6,&-LOCAL_SIZE # init stack frame
fsave FP_SRC(%a6) # grab the "busy" frame
movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
# the FPIAR holds the "current PC" of the faulting instruction
mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
bsr.l _imem_read_long # fetch the instruction words
mov.l %d0,EXC_OPWORD(%a6)
##############################################################################
btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
bne.w funfl_out
lea FP_SRC(%a6),%a0 # pass: ptr to src op
bsr.l fix_skewed_ops # fix src op
lea FP_SRC(%a6),%a0 # pass: ptr to src op
bsr.l set_tag_x # tag the operand type
mov.b %d0,STAG(%a6) # maybe NORM,DENORM
# bit five of the fp ext word separates the monadic and dyadic operations
# that can pass through fpsp_unfl(). remember that fcmp, and ftst
# will never take this exception.
btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
beq.b funfl_extract # monadic
# now, what's left that's not dyadic is fsincos. we can distinguish it
# from all dyadics by the '0110xxx pattern
btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
bne.b funfl_extract # yes
bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
bsr.l load_fpn2 # load dst into FP_DST
lea FP_DST(%a6),%a0 # pass: ptr to dst op
bsr.l set_tag_x # tag the operand type
cmpi.b %d0,&UNNORM # is operand an UNNORM?
bne.b funfl_op2_done # no
bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
funfl_op2_done:
mov.b %d0,DTAG(%a6) # save dst optype tag
funfl_extract:
#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
clr.l %d0
mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
mov.b 1+EXC_CMDREG(%a6),%d1
andi.w &0x007f,%d1 # extract extension
andi.l &0x00ff01ff,USER_FPSR(%a6)
fmov.l &0x0,%fpcr # zero current control regs
fmov.l &0x0,%fpsr
lea FP_SRC(%a6),%a0
lea FP_DST(%a6),%a1
# maybe we can make these entry points ONLY the OVFL entry points of each routine.
mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
jsr (tbl_unsupp.l,%pc,%d1.l*1)
bfextu EXC_CMDREG(%a6){&6:&3},%d0
bsr.l store_fpreg
# The `060 FPU multiplier hardware is such that if the result of a
# multiply operation is the smallest possible normalized number
# (0x00000000_80000000_00000000), then the machine will take an
# underflow exception. Since this is incorrect, we need to check
# if our emulation, after re-doing the operation, decided that
# no underflow was called for. We do these checks only in
# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
# special case will simply exit gracefully with the correct result.
# the exceptional possibilities we have left ourselves with are ONLY overflow
# and inexact. and, the inexact is such that overflow occurred and was disabled
# but inexact was enabled.
btst &unfl_bit,FPCR_ENABLE(%a6)
bne.b funfl_unfl_on
funfl_chkinex:
btst &inex2_bit,FPCR_ENABLE(%a6)
bne.b funfl_inex_on
funfl_exit:
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
unlk %a6
#$# add.l &24,%sp
bra.l _fpsp_done
# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
# in fp1 (don't forget to save fp0). what to do now?
# well, we simply have to get to go to _real_unfl()!
funfl_unfl_on:
# The `060 FPU multiplier hardware is such that if the result of a
# multiply operation is the smallest possible normalized number
# (0x00000000_80000000_00000000), then the machine will take an
# underflow exception. Since this is incorrect, we check here to see
# if our emulation, after re-doing the operation, decided that
# no underflow was called for.
btst &unfl_bit,FPSR_EXCEPT(%a6)
beq.w funfl_chkinex
funfl_unfl_on2:
fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
mov.w &0xe003,2+FP_SRC(%a6) # save exc status
fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
unlk %a6
bra.l _real_unfl
# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
# we must jump to real_inex().
funfl_inex_on:
# The `060 FPU multiplier hardware is such that if the result of a
# multiply operation is the smallest possible normalized number
# (0x00000000_80000000_00000000), then the machine will take an
# underflow exception.
# But, whether bogus or not, if inexact is enabled AND it occurred,
# then we have to branch to real_inex.