-
Notifications
You must be signed in to change notification settings - Fork 54.9k
/
Copy pathisp.S
4299 lines (3627 loc) · 124 KB
/
isp.S
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
M68000 Hi-Performance Microprocessor Division
M68060 Software Package
Production Release P1.00 -- October 10, 1994
M68060 Software Package Copyright © 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.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ireal.s:
# This file is appended to the top of the 060ISP package
# and contains the entry points into the package. The user, in
# effect, branches to one of the branch table entries located
# after _060ISP_TABLE.
# Also, subroutine stubs exist in this file (_isp_done for
# example) that are referenced by the ISP package itself in order
# to call a given routine. The stub routine actually performs the
# callout. The ISP code does a "bsr" to the stub routine. This
# extra layer of hierarchy adds a slight performance penalty but
# it makes the ISP code easier to read and more mainatinable.
#
set _off_chk, 0x00
set _off_divbyzero, 0x04
set _off_trace, 0x08
set _off_access, 0x0c
set _off_done, 0x10
set _off_cas, 0x14
set _off_cas2, 0x18
set _off_lock, 0x1c
set _off_unlock, 0x20
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
_060ISP_TABLE:
# Here's the table of ENTRY POINTS for those linking the package.
bra.l _isp_unimp
short 0x0000
bra.l _isp_cas
short 0x0000
bra.l _isp_cas2
short 0x0000
bra.l _isp_cas_finish
short 0x0000
bra.l _isp_cas2_finish
short 0x0000
bra.l _isp_cas_inrange
short 0x0000
bra.l _isp_cas_terminate
short 0x0000
bra.l _isp_cas_restart
short 0x0000
space 64
#############################################################
global _real_chk
_real_chk:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_divbyzero
_real_divbyzero:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_trace
_real_trace:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_access
_real_access:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _isp_done
_isp_done:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
#######################################
global _real_cas
_real_cas:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_cas2
_real_cas2:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_lock_page
_real_lock_page:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _real_unlock_page
_real_unlock_page:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
#######################################
global _imem_read
_imem_read:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read
_dmem_read:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write
_dmem_write:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _imem_read_word
_imem_read_word:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _imem_read_long
_imem_read_long:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_byte
_dmem_read_byte:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_word
_dmem_read_word:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_read_long
_dmem_read_long:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_byte
_dmem_write_byte:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_word
_dmem_write_word:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
global _dmem_write_long
_dmem_write_long:
mov.l %d0,-(%sp)
mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
pea.l (_060ISP_TABLE-0x80,%pc,%d0)
mov.l 0x4(%sp),%d0
rtd &0x4
#
# This file contains a set of define statements for constants
# in oreder to promote readability within the core code itself.
#
set LOCAL_SIZE, 96 # stack frame size(bytes)
set LV, -LOCAL_SIZE # stack offset
set EXC_ISR, 0x4 # stack status register
set EXC_IPC, 0x6 # stack pc
set EXC_IVOFF, 0xa # stacked vector offset
set EXC_AREGS, LV+64 # offset of all address regs
set EXC_DREGS, LV+32 # offset of all data regs
set EXC_A7, EXC_AREGS+(7*4) # offset of a7
set EXC_A6, EXC_AREGS+(6*4) # offset of a6
set EXC_A5, EXC_AREGS+(5*4) # offset of a5
set EXC_A4, EXC_AREGS+(4*4) # offset of a4
set EXC_A3, EXC_AREGS+(3*4) # offset of a3
set EXC_A2, EXC_AREGS+(2*4) # offset of a2
set EXC_A1, EXC_AREGS+(1*4) # offset of a1
set EXC_A0, EXC_AREGS+(0*4) # offset of a0
set EXC_D7, EXC_DREGS+(7*4) # offset of d7
set EXC_D6, EXC_DREGS+(6*4) # offset of d6
set EXC_D5, EXC_DREGS+(5*4) # offset of d5
set EXC_D4, EXC_DREGS+(4*4) # offset of d4
set EXC_D3, EXC_DREGS+(3*4) # offset of d3
set EXC_D2, EXC_DREGS+(2*4) # offset of d2
set EXC_D1, EXC_DREGS+(1*4) # offset of d1
set EXC_D0, EXC_DREGS+(0*4) # offset of d0
set EXC_TEMP, LV+16 # offset of temp stack space
set EXC_SAVVAL, LV+12 # offset of old areg value
set EXC_SAVREG, LV+11 # offset of old areg index
set SPCOND_FLG, LV+10 # offset of spc condition flg
set EXC_CC, LV+8 # offset of cc register
set EXC_EXTWPTR, LV+4 # offset of current PC
set EXC_EXTWORD, LV+2 # offset of current ext opword
set EXC_OPWORD, LV+0 # offset of current opword
###########################
# SPecial CONDition FLaGs #
###########################
set mia7_flg, 0x04 # (a7)+ flag
set mda7_flg, 0x08 # -(a7) flag
set ichk_flg, 0x10 # chk exception flag
set idbyz_flg, 0x20 # divbyzero flag
set restore_flg, 0x40 # restore -(an)+ flag
set immed_flg, 0x80 # immediate data flag
set mia7_bit, 0x2 # (a7)+ bit
set mda7_bit, 0x3 # -(a7) bit
set ichk_bit, 0x4 # chk exception bit
set idbyz_bit, 0x5 # divbyzero bit
set restore_bit, 0x6 # restore -(a7)+ bit
set immed_bit, 0x7 # immediate data bit
#########
# Misc. #
#########
set BYTE, 1 # len(byte) == 1 byte
set WORD, 2 # len(word) == 2 bytes
set LONG, 4 # len(longword) == 4 bytes
#########################################################################
# XDEF **************************************************************** #
# _isp_unimp(): 060ISP entry point for Unimplemented Instruction #
# #
# This handler should be the first code executed upon taking the #
# "Unimplemented Integer Instruction" exception in an operating #
# system. #
# #
# XREF **************************************************************** #
# _imem_read_{word,long}() - read instruction word/longword #
# _mul64() - emulate 64-bit multiply #
# _div64() - emulate 64-bit divide #
# _moveperipheral() - emulate "movep" #
# _compandset() - emulate misaligned "cas" #
# _compandset2() - emulate "cas2" #
# _chk2_cmp2() - emulate "cmp2" and "chk2" #
# _isp_done() - "callout" for normal final exit #
# _real_trace() - "callout" for Trace exception #
# _real_chk() - "callout" for Chk exception #
# _real_divbyzero() - "callout" for DZ exception #
# _real_access() - "callout" for access error exception #
# #
# INPUT *************************************************************** #
# - The system stack contains the Unimp Int Instr stack frame #
# #
# OUTPUT ************************************************************** #
# If Trace exception: #
# - The system stack changed to contain Trace exc stack frame #
# If Chk exception: #
# - The system stack changed to contain Chk exc stack frame #
# If DZ exception: #
# - The system stack changed to contain DZ exc stack frame #
# If access error exception: #
# - The system stack changed to contain access err exc stk frame #
# Else: #
# - Results saved as appropriate #
# #
# ALGORITHM *********************************************************** #
# This handler fetches the first instruction longword from #
# memory and decodes it to determine which of the unimplemented #
# integer instructions caused this exception. This handler then calls #
# one of _mul64(), _div64(), _moveperipheral(), _compandset(), #
# _compandset2(), or _chk2_cmp2() as appropriate. #
# Some of these instructions, by their nature, may produce other #
# types of exceptions. "div" can produce a divide-by-zero exception, #
# and "chk2" can cause a "Chk" exception. In both cases, the current #
# exception stack frame must be converted to an exception stack frame #
# of the correct exception type and an exit must be made through #
# _real_divbyzero() or _real_chk() as appropriate. In addition, all #
# instructions may be executing while Trace is enabled. If so, then #
# a Trace exception stack frame must be created and an exit made #
# through _real_trace(). #
# Meanwhile, if any read or write to memory using the #
# _mem_{read,write}() "callout"s returns a failing value, then an #
# access error frame must be created and an exit made through #
# _real_access(). #
# If none of these occur, then a normal exit is made through #
# _isp_done(). #
# #
# This handler, upon entry, saves almost all user-visible #
# address and data registers to the stack. Although this may seem to #
# cause excess memory traffic, it was found that due to having to #
# access these register files for things like data retrieval and <ea> #
# calculations, it was more efficient to have them on the stack where #
# they could be accessed by indexing rather than to make subroutine #
# calls to retrieve a register of a particular index. #
# #
#########################################################################
global _isp_unimp
_isp_unimp:
link.w %a6,&-LOCAL_SIZE # create room for stack frame
movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5
mov.l (%a6),EXC_A6(%a6) # store a6
btst &0x5,EXC_ISR(%a6) # from s or u mode?
bne.b uieh_s # supervisor mode
uieh_u:
mov.l %usp,%a0 # fetch user stack pointer
mov.l %a0,EXC_A7(%a6) # store a7
bra.b uieh_cont
uieh_s:
lea 0xc(%a6),%a0
mov.l %a0,EXC_A7(%a6) # store corrected sp
###############################################################################
uieh_cont:
clr.b SPCOND_FLG(%a6) # clear "special case" flag
mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
#
# fetch the opword and first extension word pointed to by the stacked pc
# and store them to the stack for now
#
mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
bsr.l _imem_read_long # fetch opword & extword
mov.l %d0,EXC_OPWORD(%a6) # store extword on stack
#########################################################################
# muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** #
# mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** #
# #
# divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** #
# divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** #
# #
# movep.w m2r 0000 ***1 00 001*** | <displacement> | #
# movep.l m2r 0000 ***1 01 001*** | <displacement> | #
# movep.w r2m 0000 ***1 10 001*** | <displacement> | #
# movep.l r2m 0000 ***1 11 001*** | <displacement> | #
# #
# cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** #
# cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** #
# #
# cas2.w 0000 1100 11 111100 **** 000* **00 0*** #
# **** 000* **00 0*** #
# cas2.l 0000 1110 11 111100 **** 000* **00 0*** #
# **** 000* **00 0*** #
# #
# chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 #
# chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 #
# chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 #
# #
# cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 #
# cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 #
# cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 #
#########################################################################
#
# using bit 14 of the operation word, separate into 2 groups:
# (group1) mul64, div64
# (group2) movep, chk2, cmp2, cas2, cas
#
btst &0x1e,%d0 # group1 or group2
beq.b uieh_group2 # go handle group2
#
# now, w/ group1, make mul64's decode the fastest since it will
# most likely be used the most.
#
uieh_group1:
btst &0x16,%d0 # test for div64
bne.b uieh_div64 # go handle div64
uieh_mul64:
# mul64() may use ()+ addressing and may, therefore, alter a7
bsr.l _mul64 # _mul64()
btst &0x5,EXC_ISR(%a6) # supervisor mode?
beq.w uieh_done
btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
beq.w uieh_done # no
btst &0x7,EXC_ISR(%a6) # is trace enabled?
bne.w uieh_trace_a7 # yes
bra.w uieh_a7 # no
uieh_div64:
# div64() may use ()+ addressing and may, therefore, alter a7.
# div64() may take a divide by zero exception.
bsr.l _div64 # _div64()
# here, we sort out all of the special cases that may have happened.
btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
bne.b uieh_div64_a7 # yes
uieh_div64_dbyz:
btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
bne.w uieh_divbyzero # yes
bra.w uieh_done # no
uieh_div64_a7:
btst &0x5,EXC_ISR(%a6) # supervisor mode?
beq.b uieh_div64_dbyz # no
# here, a7 has been incremented by 4 bytes in supervisor mode. we still
# may have the following 3 cases:
# (i) (a7)+
# (ii) (a7)+; trace
# (iii) (a7)+; divide-by-zero
#
btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
bne.w uieh_divbyzero_a7 # yes
tst.b EXC_ISR(%a6) # no; is trace enabled?
bmi.w uieh_trace_a7 # yes
bra.w uieh_a7 # no
#
# now, w/ group2, make movep's decode the fastest since it will
# most likely be used the most.
#
uieh_group2:
btst &0x18,%d0 # test for not movep
beq.b uieh_not_movep
bsr.l _moveperipheral # _movep()
bra.w uieh_done
uieh_not_movep:
btst &0x1b,%d0 # test for chk2,cmp2
beq.b uieh_chk2cmp2 # go handle chk2,cmp2
swap %d0 # put opword in lo word
cmpi.b %d0,&0xfc # test for cas2
beq.b uieh_cas2 # go handle cas2
uieh_cas:
bsr.l _compandset # _cas()
# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
# mode are simply not considered valid and therefore are not handled.
bra.w uieh_done
uieh_cas2:
mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
bsr.l _imem_read_word # read extension word
tst.l %d1 # ifetch error?
bne.w isp_iacc # yes
bsr.l _compandset2 # _cas2()
bra.w uieh_done
uieh_chk2cmp2:
# chk2 may take a chk exception
bsr.l _chk2_cmp2 # _chk2_cmp2()
# here we check to see if a chk trap should be taken
cmpi.b SPCOND_FLG(%a6),&ichk_flg
bne.w uieh_done
bra.b uieh_chk_trap
###########################################################################
#
# the required emulation has been completed. now, clean up the necessary stack
# info and prepare for rte
#
uieh_done:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
# if exception occurred in user mode, then we have to restore a7 in case it
# changed. we don't have to update a7 for supervisor mose because that case
# doesn't flow through here
btst &0x5,EXC_ISR(%a6) # user or supervisor?
bne.b uieh_finish # supervisor
mov.l EXC_A7(%a6),%a0 # fetch user stack pointer
mov.l %a0,%usp # restore it
uieh_finish:
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
btst &0x7,EXC_ISR(%a6) # is trace mode on?
bne.b uieh_trace # yes;go handle trace mode
mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink
unlk %a6 # unlink stack frame
bra.l _isp_done
#
# The instruction that was just emulated was also being traced. The trace
# trap for this instruction will be lost unless we jump to the trace handler.
# So, here we create a Trace Exception format number two exception stack
# frame from the Unimplemented Integer Intruction Exception stack frame
# format number zero and jump to the user supplied hook "_real_trace()".
#
# UIEH FRAME TRACE FRAME
# ***************** *****************
# * 0x0 * 0x0f4 * * Current *
# ***************** * PC *
# * Current * *****************
# * PC * * 0x2 * 0x024 *
# ***************** *****************
# * SR * * Next *
# ***************** * PC *
# ->* Old * *****************
# from link -->* A6 * * SR *
# ***************** *****************
# /* A7 * * New * <-- for final unlink
# / * * * A6 *
# link frame < ***************** *****************
# \ ~ ~ ~ ~
# \***************** *****************
#
uieh_trace:
mov.l EXC_A6(%a6),-0x4(%a6)
mov.w EXC_ISR(%a6),0x0(%a6)
mov.l EXC_IPC(%a6),0x8(%a6)
mov.l EXC_EXTWPTR(%a6),0x2(%a6)
mov.w &0x2024,0x6(%a6)
sub.l &0x4,%a6
unlk %a6
bra.l _real_trace
#
# UIEH FRAME CHK FRAME
# ***************** *****************
# * 0x0 * 0x0f4 * * Current *
# ***************** * PC *
# * Current * *****************
# * PC * * 0x2 * 0x018 *
# ***************** *****************
# * SR * * Next *
# ***************** * PC *
# (4 words) *****************
# * SR *
# *****************
# (6 words)
#
# the chk2 instruction should take a chk trap. so, here we must create a
# chk stack frame from an unimplemented integer instruction exception frame
# and jump to the user supplied entry point "_real_chk()".
#
uieh_chk_trap:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
mov.w &0x2018,0x6(%a6) # put Vector Offset on stack
mov.l EXC_A6(%a6),%a6 # restore a6
add.l &LOCAL_SIZE,%sp # clear stack frame
bra.l _real_chk
#
# UIEH FRAME DIVBYZERO FRAME
# ***************** *****************
# * 0x0 * 0x0f4 * * Current *
# ***************** * PC *
# * Current * *****************
# * PC * * 0x2 * 0x014 *
# ***************** *****************
# * SR * * Next *
# ***************** * PC *
# (4 words) *****************
# * SR *
# *****************
# (6 words)
#
# the divide instruction should take an integer divide by zero trap. so, here
# we must create a divbyzero stack frame from an unimplemented integer
# instruction exception frame and jump to the user supplied entry point
# "_real_divbyzero()".
#
uieh_divbyzero:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
mov.w &0x2014,0x6(%a6) # put Vector Offset on stack
mov.l EXC_A6(%a6),%a6 # restore a6
add.l &LOCAL_SIZE,%sp # clear stack frame
bra.l _real_divbyzero
#
# DIVBYZERO FRAME
# *****************
# * Current *
# UIEH FRAME * PC *
# ***************** *****************
# * 0x0 * 0x0f4 * * 0x2 * 0x014 *
# ***************** *****************
# * Current * * Next *
# * PC * * PC *
# ***************** *****************
# * SR * * SR *
# ***************** *****************
# (4 words) (6 words)
#
# the divide instruction should take an integer divide by zero trap. so, here
# we must create a divbyzero stack frame from an unimplemented integer
# instruction exception frame and jump to the user supplied entry point
# "_real_divbyzero()".
#
# However, we must also deal with the fact that (a7)+ was used from supervisor
# mode, thereby shifting the stack frame up 4 bytes.
#
uieh_divbyzero_a7:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
mov.w &0x2014,0xa(%a6) # put Vector Offset on stack
mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
mov.l EXC_A6(%a6),%a6 # restore a6
add.l &4+LOCAL_SIZE,%sp # clear stack frame
bra.l _real_divbyzero
#
# TRACE FRAME
# *****************
# * Current *
# UIEH FRAME * PC *
# ***************** *****************
# * 0x0 * 0x0f4 * * 0x2 * 0x024 *
# ***************** *****************
# * Current * * Next *
# * PC * * PC *
# ***************** *****************
# * SR * * SR *
# ***************** *****************
# (4 words) (6 words)
#
#
# The instruction that was just emulated was also being traced. The trace
# trap for this instruction will be lost unless we jump to the trace handler.
# So, here we create a Trace Exception format number two exception stack
# frame from the Unimplemented Integer Intruction Exception stack frame
# format number zero and jump to the user supplied hook "_real_trace()".
#
# However, we must also deal with the fact that (a7)+ was used from supervisor
# mode, thereby shifting the stack frame up 4 bytes.
#
uieh_trace_a7:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
mov.w &0x2024,0xa(%a6) # put Vector Offset on stack
mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
mov.l EXC_A6(%a6),%a6 # restore a6
add.l &4+LOCAL_SIZE,%sp # clear stack frame
bra.l _real_trace
#
# UIEH FRAME
# *****************
# * 0x0 * 0x0f4 *
# UIEH FRAME *****************
# ***************** * Next *
# * 0x0 * 0x0f4 * * PC *
# ***************** *****************
# * Current * * SR *
# * PC * *****************
# ***************** (4 words)
# * SR *
# *****************
# (4 words)
uieh_a7:
mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack
mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack
mov.l EXC_A6(%a6),%a6 # restore a6
add.l &8+LOCAL_SIZE,%sp # clear stack frame
bra.l _isp_done
##########
# this is the exit point if a data read or write fails.
# a0 = failing address
# d0 = fslw
isp_dacc:
mov.l %a0,(%a6) # save address
mov.l %d0,-0x4(%a6) # save partial fslw
lea -64(%a6),%sp
movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6
mov.l 0xc(%sp),-(%sp) # move voff,hi(pc)
mov.l 0x4(%sp),0x10(%sp) # store fslw
mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc)
mov.l 0x8(%sp),0xc(%sp) # store address
mov.l (%sp)+,0x4(%sp) # store voff,hi(pc)
mov.w &0x4008,0x6(%sp) # store new voff
bra.b isp_acc_exit
# this is the exit point if an instruction word read fails.
# FSLW:
# misaligned = true
# read = true
# size = word
# instruction = true
# software emulation error = true
isp_iacc:
movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
unlk %a6 # unlink frame
sub.w &0x8,%sp # make room for acc frame
mov.l 0x8(%sp),(%sp) # store sr,lo(pc)
mov.w 0xc(%sp),0x4(%sp) # store hi(pc)
mov.w &0x4008,0x6(%sp) # store new voff
mov.l 0x2(%sp),0x8(%sp) # store address (=pc)
mov.l &0x09428001,0xc(%sp) # store fslw
isp_acc_exit:
btst &0x5,(%sp) # user or supervisor?
beq.b isp_acc_exit2 # user
bset &0x2,0xd(%sp) # set supervisor TM bit
isp_acc_exit2:
bra.l _real_access
# if the addressing mode was (an)+ or -(an), the address register must
# be restored to its pre-exception value before entering _real_access.
isp_restore:
cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore?
bne.b isp_restore_done # no
clr.l %d0
mov.b EXC_SAVREG(%a6),%d0 # regno to restore
mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
isp_restore_done:
rts
#########################################################################
# XDEF **************************************************************** #
# _calc_ea(): routine to calculate effective address #
# #
# XREF **************************************************************** #
# _imem_read_word() - read instruction word #
# _imem_read_long() - read instruction longword #
# _dmem_read_long() - read data longword (for memory indirect) #
# isp_iacc() - handle instruction access error exception #
# isp_dacc() - handle data access error exception #
# #
# INPUT *************************************************************** #
# d0 = number of bytes related to effective address (w,l) #
# #
# OUTPUT ************************************************************** #
# If exiting through isp_dacc... #
# a0 = failing address #
# d0 = FSLW #
# elsif exiting though isp_iacc... #
# none #
# else #
# a0 = effective address #
# #
# ALGORITHM *********************************************************** #
# The effective address type is decoded from the opword residing #
# on the stack. A jump table is used to vector to a routine for the #
# appropriate mode. Since none of the emulated integer instructions #
# uses byte-sized operands, only handle word and long operations. #
# #
# Dn,An - shouldn't enter here #
# (An) - fetch An value from stack #
# -(An) - fetch An value from stack; return decr value; #
# place decr value on stack; store old value in case of #
# future access error; if -(a7), set mda7_flg in #
# SPCOND_FLG #
# (An)+ - fetch An value from stack; return value; #
# place incr value on stack; store old value in case of #
# future access error; if (a7)+, set mia7_flg in #
# SPCOND_FLG #
# (d16,An) - fetch An value from stack; read d16 using #
# _imem_read_word(); fetch may fail -> branch to #
# isp_iacc() #
# (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch #
# address; fetch may fail #
# #<data> - return address of immediate value; set immed_flg #
# in SPCOND_FLG #
# (d16,PC) - fetch stacked PC value; read d16 using #
# _imem_read_word(); fetch may fail -> branch to #
# isp_iacc() #
# everything else - read needed displacements as appropriate w/ #
# _imem_read_{word,long}(); read may fail; if memory #
# indirect, read indirect address using #
# _dmem_read_long() which may also fail #
# #
#########################################################################
global _calc_ea
_calc_ea:
mov.l %d0,%a0 # move # bytes to a0
# MODE and REG are taken from the EXC_OPWORD.
mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
mov.w %d0,%d1 # make a copy
andi.w &0x3f,%d0 # extract mode field
andi.l &0x7,%d1 # extract reg field
# jump to the corresponding function for each {MODE,REG} pair.
mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
swbeg &64
tbl_ea_mode:
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short addr_ind_a0 - tbl_ea_mode
short addr_ind_a1 - tbl_ea_mode
short addr_ind_a2 - tbl_ea_mode
short addr_ind_a3 - tbl_ea_mode
short addr_ind_a4 - tbl_ea_mode
short addr_ind_a5 - tbl_ea_mode
short addr_ind_a6 - tbl_ea_mode
short addr_ind_a7 - tbl_ea_mode
short addr_ind_p_a0 - tbl_ea_mode
short addr_ind_p_a1 - tbl_ea_mode
short addr_ind_p_a2 - tbl_ea_mode
short addr_ind_p_a3 - tbl_ea_mode
short addr_ind_p_a4 - tbl_ea_mode
short addr_ind_p_a5 - tbl_ea_mode
short addr_ind_p_a6 - tbl_ea_mode
short addr_ind_p_a7 - tbl_ea_mode
short addr_ind_m_a0 - tbl_ea_mode
short addr_ind_m_a1 - tbl_ea_mode
short addr_ind_m_a2 - tbl_ea_mode
short addr_ind_m_a3 - tbl_ea_mode
short addr_ind_m_a4 - tbl_ea_mode
short addr_ind_m_a5 - tbl_ea_mode
short addr_ind_m_a6 - tbl_ea_mode
short addr_ind_m_a7 - tbl_ea_mode
short addr_ind_disp_a0 - tbl_ea_mode
short addr_ind_disp_a1 - tbl_ea_mode
short addr_ind_disp_a2 - tbl_ea_mode
short addr_ind_disp_a3 - tbl_ea_mode
short addr_ind_disp_a4 - tbl_ea_mode
short addr_ind_disp_a5 - tbl_ea_mode
short addr_ind_disp_a6 - tbl_ea_mode
short addr_ind_disp_a7 - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short _addr_ind_ext - tbl_ea_mode
short abs_short - tbl_ea_mode
short abs_long - tbl_ea_mode
short pc_ind - tbl_ea_mode
short pc_ind_ext - tbl_ea_mode
short immediate - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode
short tbl_ea_mode - tbl_ea_mode