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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
TTL => NewIRQs
; *****************************************************************************
;
; Main IRQ routine:
; Push workregs,lr
; IRQsema -> TOS
; stack -> IRQsema
; call IRQ1V
; IRQs off
; TOS ->IRQsema
; process callback, pulling workregs,pc at some point
;
; *****************************************************************************
ALIGN 32
Initial_IRQ_Code ROUT
SUB lr, lr, #4
Push "r0, lr"
MRS lr, SPSR
Push "r1-r3, r11, r12, lr"
; ** For Pete's sake remember to change the heap manager if you change the above
; ** register list!!!!!!! And the [sp_irq, #4*5] below
[ :LNOT:No26bitCode
BIC r0, lr, #&1F ; clear out foreground mode bits
ORR r0, r0, #I32_bit + IRQ26_mode ; force IRQ_26 mode and I bit set
MSR CPSR_c, r0
]
LDR r12, =ZeroPage
LDR r0, [r12, #IRQsema]
Push r0
STR sp_irq, [r12, #IRQsema]
MOV lr, pc
LDR pc, [r12, #IRQ1V]
; IRQ1V called with r0-r3,r11,r12 trashable. r12=0
; Stu has a theory that 1N cycle can be saved by the default IRQ1V pointing
; at a location containing a branch to our code; we then do something like
; LDR R0, [R12, #IRQ1V]
; CMP R0, #OurIRQ1V
; BNE somebodysonIRQ1V
; .... fall into default IRQ1V code
Push "r10"
MOV r10, #UnthreadV
BL CallVector
Pull "r10"
LDR r11, =ZeroPage
Pull r0
STR r0, [r11, #IRQsema]
[ :LNOT:No26bitCode
MRS r0, CPSR
ORR r0, r0, #&10
MSR CPSR_c, r0 ; switch back to IRQ32 mode
]
LDRB r11, [r11, #CallBack_Flag]
TEQ r11, #0
Pull "r1-r3, r11, r12, lr", EQ
MSREQ SPSR_cxsf, lr
Pull "r0, pc", EQ, ^
TST r11, #CBack_Postpone
LDREQ lr, [sp_irq, #4*5] ; get SPSR off stack
TSTEQ lr, #I32_bit :OR: &0F ; check we came from USR26 or USR32 mode, with IRQs enabled
Pull "r1-r3, r11, r12, lr", NE
MSRNE SPSR_cxsf, lr
Pull "r0, pc", NE, ^
; Do a CallBack: asked for, not postponed, and we're returning into USR26/32 mode.
ASSERT IRQ32_mode :AND: SVC32_mode = IRQ32_mode ; so the following dodgy ops work
Pull "r1-r3, r11, r12"
MRS r0, CPSR
ORR r0, r0, #SVC32_mode
MSR CPSR_c, r0
Push "r10-r12" ; push r10-r12 onto the SVC stack
BIC r0, r0, #IRQ32_mode :EOR: SVC32_mode
MSR CPSR_c, r0
Pull "r10-r12" ; SPSR, R0, LR really
[ No26bitCode :LOR: FixCallBacks
ORR r0, r0, #SVC32_mode
|
BIC r0, r0, #&1F
ORR r0, r0, #SVC26_mode
]
MSR CPSR_c, r0
Push r12 ; Save the return address
MOV r14, r10 ; SPSR into R14
MOV r0, r11 ; restore original R0
LDR r10, =ZeroPage
LDRB r11, [r10, #CallBack_Flag]
[ FixCallBacks
B Do_CallBack_postpone_already_clear
|
B Do_CallBack
]
LTORG
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Default IRQ1V: despatch on interrupting device
; Now copied to RAM, together with vector entries and device tables
^ 0
[ HAL
IRQDesp_Link # 4
IRQDesp_R12Val # 4
IRQDesp_CallAddr # 4
IRQDesp_Link_Unshared * 1 ; flag in Link (for _this_ node)
|
IRQDesp_R12Val # 4
IRQDesp_CallAddr # 4
IRQDesp_Link # 4
]
ASSERT IRQDesp_CallAddr = IRQDesp_R12Val + 4
ALIGN 32
DefaultIRQ1Vcode ROUT
[ HAL
Push "r9,lr"
[ ZeroPage = 0
MOV r9, #0
|
LDR r9, %FT02
]
AddressHAL r9 ; modifies r9
; MOV r11, r14 ; r11 trashable
CallHAL HAL_IRQSource
Pull "r9"
ADR r2, Devices
ADD r1, r0, r0, LSL #1 ; multiply by 3
; MOV r14, r11
ADD r11, r2, r1, LSL #2 ; so table contains DevNo * 3
; ASSERT IRQDesp_R12Val = 4
; LDMIB r1, {r12, pc}
01 MOV lr, pc
LDMIA r11, {r11, r12, pc}
TST r11, #IRQDesp_Link_Unshared
BEQ %BT01
Pull pc
[ ZeroPage <> 0
02
DCD ZeroPage
]
|
MOV r3, #IOC ; base for IOC and IOMD
LDRB r0, [r3, #IOMD_DMAREQ]
TEQ r0, #0
ADRNE r1, IrqDMADevnos
LDREQB r0, [r3, #IOCIRQREQB] ; if not DMA then assume IRQB until we know otherwise
ADREQ r1, IrqReqBDevnos
[ MorrisSupport
;>>>RCM Says should we use separate Morris specific code, cos Morris doesn't support
;>>>RCM all IOMD_DMAREQ bits and non Morris machines don't have IOMD_IRQRQD.
;>>>RCM Look at use of NoInterrupt.
ADREQ r12, DeviceTables ; can't reach these tables with ADR
TEQEQ r0, #0
LDREQB r0, [r3, #IOMD_IRQRQD]
ADDEQ r1, r12, #IrqReqDDevnos-DeviceTables
TEQEQ r0, #0
LDREQB r0, [r3, #IOMD_IRQRQC]
ADDEQ r1, r12, #IrqReqCDevnos-DeviceTables
] ; MorrisSupport
TEQEQ r0, #0
LDREQB r0, [r3, #IOCIRQREQA] ; not DMA and not IRQB so assume IRQA
ADREQ r1, IrqReqADevnos
LDRB r0, [r1, r0] ; pick up offset in device despatcher
ADD r1, pc, r0, LSL #2 ; so table contains DevNo * 3
ASSERT IRQDesp_R12Val = 0
LDMIA r1, {r12, pc}
] ; HAL
; ******* IRQ device handlers entered with r0-r3,r11,r12,r14 trashable *******
; r0 = device number (if HAL)
; r3 -> IOC (not in HAL world, unless IOMD HAL is helpful)
; r12 = what they asked for
; r14 = return address to MOS IRQ exit sequence
[ HAL
DefaultIRQ1Vcode_end
Devices * DefaultIRQ1Vcode_end + 12
NoInterrupt * -1
[ M_CortexA9
MaxInterrupts * 160
|
MaxInterrupts * 96
] ; M_CortexA9
DevicesEnd * Devices + MaxInterrupts * 12
ASSERT DevicesEnd - DefaultIRQ1Vcode <= DefIRQ1Vspace
| ; HAL
[ MorrisSupport
NoInterrupt * 38 ; Morris has IOMD's extra interrupts plus 16 of its own
|
NoInterrupt * 22 ; IOMD has 6 more interrupts for DMA
]
Devices
; Register A devices
; pbusy handler
& 0 ; R12 value
& IRQ ; call address
& 0 ; link
; ringing handler
& 0
& IRQ
& 0
; printer acknowledge
& 0
& IRQ
& 0
; vsync handler
& OsbyteVars
& VsyncIRQ
& 0
; power on reset: this can't happen, but call IRQ2V if it does.
& 0
& IRQ
& 0
; timer0
& OsbyteVars
& TickOne
& 0
; timer1
& 0
& IRQ
& 0
; FIQ downgrade
& 0
& IRQ
& 0
; register B devices
; PFIQ downgrade
& PFIQasIRQ_Chain - (PodDesp_Link-PodDesp_R12Val)
& PFIQasIRQ_Despatch
& 0
; sound
& 0
& IRQ
& 0
; serial
& 0
& IRQ
& 0
; winnie IRQ
& 0
& IRQ
& 0
; Disc changed
& 0
& IRQ
& 0
; podule IRQ
& PIRQ_Chain - (PodDesp_Link-PodDesp_R12Val)
& PIRQ_Despatch
& 0
; serial TX (Keyboard serial transmit register empty)
& IOC
[ Keyboard_Type = "A1A500"
& IrqTx
|
& IRQ
]
& 0
; serial RX (Keyboard serial receive register full)
& IOC
[ Keyboard_Type = "A1A500"
& IrqRx
|
& IRQ
]
& 0
; IOMD DMA devices
; DMA channel 0
& 0
& IRQ
& 0
; DMA channel 1
& 0
& IRQ
& 0
; DMA channel 2
& 0
& IRQ
& 0
; DMA channel 3
& 0
& IRQ
& 0
; Sound DMA channel 0
& 0
& IRQ
& 0
; Sound DMA channel 1
& 0
& IRQ
& 0
[ MorrisSupport
; register D devices
; Mouse port Rx full
& IOC
& IRQ
& 0
; Mouse port Tx empty
& IOC
& IRQ
& 0
; AtoD (Joystick)
& 0
& IRQ
& 0
; Nevent1
& 0
& IRQ
& 0
; Nevent2
& 0
& IRQ
& 0
; The following are just place fillers in case IRQD bits 5 to 7 are ever used.
; NoInterrupt
& 0
& IRQ
& 0
; NoInterrupt
& 0
& IRQ
& 0
; NoInterrupt
& 0
& IRQ
& 0
; register C devices
; Bit0
& 0
& IRQ
& 0
; Bit1
& 0
& IRQ
& 0
; Bit2
& 0
& IRQ
& 0
; Bit3
& 0
& IRQ
& 0
; Bit4
& 0
& IRQ
& 0
; Bit5
& 0
& IRQ
& 0
; Bit6
& 0
& IRQ
& 0
; Bit7
& 0
& IRQ
& 0
]
; Neither A or B is interrupting, which is impossible: just call IRQ2V anyway
& 0
& IRQ
& 0
DevicesEnd
; Following tables encode the priority of the devices within each register
;
DeviceTables
; Prioritised IOMD DMA device numbers
IrqDMAPrio0 * 1:SHL:5
IrqDMADev0 * IOMD_DMASound1_DevNo
IrqDMAPrio1 * 1:SHL:4
IrqDMADev1 * IOMD_DMASound0_DevNo
IrqDMAPrio2 * 1:SHL:3
IrqDMADev2 * IOMD_DMAChannel3_DevNo
IrqDMAPrio3 * 1:SHL:2
IrqDMADev3 * IOMD_DMAChannel2_DevNo
IrqDMAPrio4 * 1:SHL:1
IrqDMADev4 * IOMD_DMAChannel1_DevNo
IrqDMAPrio5 * 1:SHL:0
IrqDMADev5 * IOMD_DMAChannel0_DevNo
GBLA DTabC
DTabC SETA 1
IrqDMADevnos
= NoInterrupt*3
; Top 2 bits are always 0 so table need only be 64 bytes
WHILE DTabC <64
[ (DTabC:AND:IrqDMAPrio5)<>0
= IrqDMADev5*3
|
[ (DTabC:AND:IrqDMAPrio4)<>0
= IrqDMADev4*3
|
[ (DTabC:AND:IrqDMAPrio3)<>0
= IrqDMADev3*3
|
[ (DTabC:AND:IrqDMAPrio2)<>0
= IrqDMADev2*3
|
[ (DTabC:AND:IrqDMAPrio1)<>0
= IrqDMADev1*3
|
[ (DTabC:AND:IrqDMAPrio0)<>0
= IrqDMADev0*3
]
]
]
]
]
]
DTabC SETA DTabC+1
WEND
; generic IRQA bits
IrqReqAPrio0 * por_bit
IrqReqADev0 * PowerOn_DevNo
IrqReqAPrio4 * timer1_bit
IrqReqADev4 * Timer1_DevNo
IrqReqAPrio5 * vsync_bit
IrqReqADev5 * VSync_DevNo
IrqReqAPrio6 * timer0_bit
IrqReqADev6 * Timer0_DevNo
IrqReqAPrio7 * force_bit
IrqReqADev7 * FIQDowngrade_DevNo
; Machine specific IRQB bits (devices 0-2)
IrqReqAPrio1 * 1:SHL:1 ; not used
IrqReqADev1 * 1
[ ReassignedIOMDInterrupts
ASSERT IOMDr_PrinterIRQ_DevNo = 2
IrqReqAPrio2 * IOMDr_printer_IRQ_bit
IrqReqADev2 * IOMDr_PrinterIRQ_DevNo
IrqReqAPrio3 * 1:SHL:0 ; not used
IrqReqADev3 * 0
|
ASSERT IOMD_PrinterIRQ_DevNo = 0
ASSERT IOMD_FloppyIndex_DevNo = 2
IrqReqAPrio2 * IOMD_printer_IRQ_bit
IrqReqADev2 * IOMD_PrinterIRQ_DevNo
IrqReqAPrio3 * IOMD_floppy_index_bit
IrqReqADev3 * IOMD_FloppyIndex_DevNo
]
DTabC SETA 1
IrqReqADevnos
= NoInterrupt*3
WHILE DTabC <256
[ (DTabC:AND:IrqReqAPrio7)<>0
= IrqReqADev7*3
|
[ (DTabC:AND:IrqReqAPrio6)<>0
= IrqReqADev6*3
|
[ (DTabC:AND:IrqReqAPrio5)<>0
= IrqReqADev5*3
|
[ (DTabC:AND:IrqReqAPrio4)<>0
= IrqReqADev4*3
|
[ (DTabC:AND:IrqReqAPrio3)<>0
= IrqReqADev3*3
|
[ (DTabC:AND:IrqReqAPrio2)<>0
= IrqReqADev2*3
|
[ (DTabC:AND:IrqReqAPrio1)<>0
= IrqReqADev1*3
|
[ (DTabC:AND:IrqReqAPrio0)<>0
= IrqReqADev0*3
]
]
]
]
]
]
]
]
DTabC SETA DTabC+1
WEND
; generic IRQB bits
IrqReqBPrio2 * podule_FIQ_as_IRQ_bit
IrqReqBDev2 * PFIQasIRQ_DevNo
IrqReqBPrio3 * serial_Tx_bit
IrqReqBDev3 * SerialTx_DevNo
IrqReqBPrio4 * serial_Rx_bit
IrqReqBDev4 * SerialRx_DevNo
IrqReqBPrio5 * podule_IRQ_bit
IrqReqBDev5 * Podule_DevNo
; Machine specific IRQB bits
[ ReassignedIOMDInterrupts
IrqReqBPrio0 * IOMDr_MPEGAudio_IRQ_bit
IrqReqBDev0 * IOMDr_MPEGAudio_DevNo
IrqReqBPrio1 * IOMDr_MPEGVideo_IRQ_bit
IrqReqBDev1 * IOMDr_MPEGVideo_DevNo
IrqReqBPrio6 * IOMDr_Network_IRQ_bit
IrqReqBDev6 * IOMDr_Network_DevNo
IrqReqBPrio7 * IOMDr_serial_IRQ_bit
IrqReqBDev7 * IOMDr_Serial_DevNo
|
IrqReqBPrio0 * IOMD_floppy_IRQ_bit
IrqReqBDev0 * DiscChanged_DevNo
IrqReqBPrio1 * IOMD_HardDisc_IRQ_bit
IrqReqBDev1 * Sound_DevNo
IrqReqBPrio6 * IOMD_Network_IRQ_bit
IrqReqBDev6 * WinnieIRQ_DevNo
IrqReqBPrio7 * IOMD_serial_IRQ_bit
IrqReqBDev7 * IOMD_Serial_DevNo
]
DTabC SETA 1
IrqReqBDevnos
= NoInterrupt*3
WHILE DTabC <256
[ (DTabC:AND:IrqReqBPrio7)<>0
= IrqReqBDev7*3
|
[ (DTabC:AND:IrqReqBPrio6)<>0
= IrqReqBDev6*3
|
[ (DTabC:AND:IrqReqBPrio5)<>0
= IrqReqBDev5*3
|
[ (DTabC:AND:IrqReqBPrio4)<>0
= IrqReqBDev4*3
|
[ (DTabC:AND:IrqReqBPrio3)<>0
= IrqReqBDev3*3
|
[ (DTabC:AND:IrqReqBPrio2)<>0
= IrqReqBDev2*3
|
[ (DTabC:AND:IrqReqBPrio1)<>0
= IrqReqBDev1*3
|
[ (DTabC:AND:IrqReqBPrio0)<>0
= IrqReqBDev0*3
]
]
]
]
]
]
]
]
DTabC SETA DTabC+1
WEND
[ MorrisSupport
; Prioritised IRQD device numbers
IrqReqDPrio0 * 1:SHL:4
IrqReqDDev0 * IOMD_Event2_DevNo
IrqReqDPrio1 * 1:SHL:3
IrqReqDDev1 * IOMD_Event1_DevNo
IrqReqDPrio2 * 1:SHL:2
IrqReqDDev2 * IOMD_AtoD_DevNo
IrqReqDPrio3 * 1:SHL:1
IrqReqDDev3 * IOMD_MouseTxEmpty_DevNo
IrqReqDPrio4 * 1:SHL:0
IrqReqDDev4 * IOMD_MouseRxFull_DevNo
DTabC SETA 1
IrqReqDDevnos
= NoInterrupt*3
; Top 3 bits are always 0 so table need only be 32 bytes (this will
; need to change if bits 5 to 7 are ever used).
WHILE DTabC <32
[ (DTabC:AND:IrqReqDPrio4)<>0
= IrqReqDDev4*3
|
[ (DTabC:AND:IrqReqDPrio3)<>0
= IrqReqDDev3*3
|
[ (DTabC:AND:IrqReqDPrio2)<>0
= IrqReqDDev2*3
|
[ (DTabC:AND:IrqReqDPrio1)<>0
= IrqReqDDev1*3
|
[ (DTabC:AND:IrqReqDPrio0)<>0
= IrqReqDDev0*3
]
]
]
]
]
DTabC SETA DTabC+1
WEND
; Prioritised IRQC device numbers. We have to handle ALL interrupts
; using specific device numbers as we don't know what the IO pins
; are connected to and the NOIRQ code has to know what bit to clear
; when an unknown interrupt is triggered.
IrqReqCPrio0 * 1:SHL:0
IrqReqCDev0 * IOMD_C_Bit0_DevNo
IrqReqCPrio1 * 1:SHL:1
IrqReqCDev1 * IOMD_C_Bit1_DevNo
IrqReqCPrio2 * 1:SHL:2
IrqReqCDev2 * IOMD_C_Bit2_DevNo
IrqReqCPrio3 * 1:SHL:3
IrqReqCDev3 * IOMD_C_Bit3_DevNo
IrqReqCPrio4 * 1:SHL:4
IrqReqCDev4 * IOMD_C_Bit4_DevNo
IrqReqCPrio5 * 1:SHL:5
IrqReqCDev5 * IOMD_C_Bit5_DevNo
IrqReqCPrio6 * 1:SHL:6
IrqReqCDev6 * IOMD_C_Bit6_DevNo
IrqReqCPrio7 * 1:SHL:7
IrqReqCDev7 * IOMD_C_Bit7_DevNo
DTabC SETA 1
IrqReqCDevnos
= NoInterrupt*3
WHILE DTabC <256
[ (DTabC:AND:IrqReqCPrio7)<>0
= IrqReqCDev7*3
|
[ (DTabC:AND:IrqReqCPrio6)<>0
= IrqReqCDev6*3
|
[ (DTabC:AND:IrqReqCPrio5)<>0
= IrqReqCDev5*3
|
[ (DTabC:AND:IrqReqCPrio4)<>0
= IrqReqCDev4*3
|
[ (DTabC:AND:IrqReqCPrio3)<>0
= IrqReqCDev3*3
|
[ (DTabC:AND:IrqReqCPrio2)<>0
= IrqReqCDev2*3
|
[ (DTabC:AND:IrqReqCPrio1)<>0
= IrqReqCDev1*3
|
[ (DTabC:AND:IrqReqCPrio0)<>0
= IrqReqCDev0*3
]
]
]
]
]
]
]
]
DTabC SETA DTabC+1
WEND
]
DefaultIRQ1Vcode_end
ASSERT DefaultIRQ1Vcode_end - DefaultIRQ1Vcode <= DefIRQ1Vspace
] ; :LNOT: HAL
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
InitialiseIRQ1Vtable
Push "v1-v3,sb,lr"
; copy IRQ handler: not done with rest of copying
; because soft break needs the info to free any claimed blocks.
LDR a1, =DefaultIRQ1V
ADRL a2, DefaultIRQ1Vcode
ADRL a3, DefaultIRQ1Vcode_end
CopyDefaultIRQ1V
LDR a4, [a2], #4
STR a4, [a1], #4
CMP a2, a3
BNE CopyDefaultIRQ1V
[ HAL
AddressHAL
ADD v1, a1, #12
ADD a3, v1, #MaxInterrupts*12
MOV a2, #0
MOV a4, #-1
LDR ip, =IRQ
FillInDefaultIRQ1VDevices
STMIA a1!, {a2, a4, ip}
ADD a4, a4, #1
CMP a1, a3
BNE FillInDefaultIRQ1VDevices
; Now fill in our basic device handlers. First the timer.
MOV a1, #0
CallHAL HAL_TimerDevice
LDR a2, =ZeroPage+OsbyteVars
LDR a3, =TickOne
ADD a1, a1, a1, LSL #1
ADD a1, v1, a1, LSL #2
STMIB a1, {a2, a3}
; Now the VSync
MOV a1, #0
CallHAL HAL_VideoFlybackDevice
CMP a1, #-1
LDRNE a2, =ZeroPage+OsbyteVars
LDRNE a3, =VsyncIRQ
ADDNE a1, a1, a1, LSL #1
ADDNE a1, v1, a1, LSL #2
STMNEIB a1, {a2, a3}
; BNE %ft1
; ; here if no vsync handler .. fudge it from tickerv
; MOV a1, #TickerV
; LDR a2, =FalseVsyncIRQ
; LDR a3, =OsbyteVars
; SWI XOS_Claim
1
[ CDVPoduleIRQs
; Now Podule bits
MOV a1, #IRQDesp_Link_Unshared
LDR a2, =ZeroPage+PFIQasIRQ_Chain - (PodDesp_Link-PodDesp_R12Val)
ADR a3, PFIQasIRQ_Despatch
ADD lr, v1, #8*12
STMIA lr, {a1, a2, a3}
LDR a2, =ZeroPage+PIRQ_Chain - (PodDesp_Link-PodDesp_R12Val)
ADR a3, PIRQ_Despatch
ADD lr, v1, #13*12
STMIA lr, {a1, a2, a3}
]
; Now IIC - if any
LDR v2, =ZeroPage+IICBus_Base
MOV v3, #0
80
LDR a1, [v2, #IICBus_Type]
TST a1, #IICFlag_HighLevel
TSTNE a1, #IICFlag_Background
BEQ %FT90
SUB sp, sp, #12
MOV a1, sp
MOV a2, v3
CallHAL HAL_IICDevice
; I think it's safe to call A SWI here...
LDMIA sp!, {r0, r3, r4}
LDR r1, =IICIRQ
MOV r2, v3
SWI XOS_ClaimDeviceVector
90
ADD v2, v2, #IICBus_Size
ADD v3, v3, #1
CMP v3, #IICBus_Count
BNE %BT80
]
Pull "v1-v3,sb,pc"
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Specialist despatchers for podules
^ 0
PodDesp_Address # 4 ; address of IRQ status byte
PodDesp_Mask # 4 ; for use on above
PodDesp_R12Val # 4
PodDesp_CallAddr # 4 ; address to call if (?Address EOR (Mask>>8)) AND Mask <> 0
PodDesp_Link # 4 ; next node
PodDesp_NodeSize # 0
[ HAL:LAND:{FALSE}
ROUT
; In r1 -> top level node
; r12 = sub chain
01 LDR r12, [r12, #PodDesp_Link-PodDesp_R12Val]
SubInterrupt_Despatch
LDMIA r12!, {r2, r3} ; address and mask
CMP r3, #&10000
LDRLOB r2, [r2]
BHS %FT02
EOR r2, r2, r3, LSR #8 ; polarity inversion
TST r2, r3 ; check against mask
BEQ %BT01
LDMIA r12, {r12, pc}
02
Push "r0,r1,r12,lr"
MOV r0, r3
MOV r12, r3
[ NoARMv5
MOV lr, pc
MOV pc, r2
|
BLX r2
]
TEQ r0, #0
Pull "r0,r1,r12,lr"
BEQ %BT01
LDMIA r12, {r12, pc}
NotSubInterrupt
LDR r1, [r1, #8] ; call next (full) handler
LDMIA r1, {r12, pc}
|
; In r12 = PFIQasIRQ_Chain - (PodDesp_Link-PodDesp_R12Val)
; or PIRQ_Chain - (PodDesp_Link-PodDesp_R12Val) from despatcher
PFIQasIRQ_Despatch ROUT
PIRQ_Despatch ; All the same thing now
01 LDR r12, [r12, #PodDesp_Link-PodDesp_R12Val]
LDMIA r12!, {r1, r2} ; address and mask
; TMD 09-Jun-89: Don't corrupt r0 - it's needed by the default IRQ2 routine
LDRB r1, [r1]
EOR r1, r1, r2, LSR #8
ANDS r1, r1, r2
BEQ %BT01
LDMIA r12, {r12, pc}
]
Default_SubInterruptHandler_Node
Default_PIRQHandler_Node
Default_PFIQasIRQHandler_Node
& .+4 ; address we know has non-zero value!
& -1 ; mask
& 0 ; handler r12
[ HAL:LAND:{FALSE}
& NotSubInterrupt ; handler code
|
& IRQ ; handler code
]
& 0 ; null link for naff release checking
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Claim of device vectors
; r0 = Device number
; r1 = call address
; r2 = r12 value
[ HAL
; r3 = interrupt location or r3 = 0 or (if r4 > 64K) r3 = routine
; r4 = interrupt mask/polarity r4 = workspace
|
[ CDVPoduleIRQs
; r0 = PFIQ|PIRQ devno -> r3 = interrupt location
; r4 = interrupt mask
]
]
CDV_Flags * &FF000000
CDV_Shared * 1:SHL:31
DeviceVector_Claim ROUT
Push "r0-r3, lr"
01 SWI XOS_ReleaseDeviceVector ; Release until bored
BVC %BT01
LDR r0, [sp]
[ HAL
BIC r0, r0, #CDV_Flags
]
CMP r0, #MaxInterrupts
BHS DV_Fail_NaffDevNo
[ HAL:LAND:{FALSE}
; TEQ r3, #0
; BNE SubInterruptClaim
|
[ CDVPoduleIRQs
CMP r0, #Podule_DevNo
CMPNE r0, #PFIQasIRQ_DevNo
BEQ PoduleChainClaim
]
]
MOV r3, #12
BL ClaimSysHeapNode
BVS DV_Exit
LDR r11, [sp]
BIC r0, r11, #CDV_Flags
ADD r0, r0, r0, LSL #1 ; *3
LDR r1, =DefaultIRQ1V-DefaultIRQ1Vcode+Devices
ADD r1, r1, r0, LSL #2
WritePSRc SVC_mode+I_bit, r10 ; IRQs off for update (on again on SWI exit)
LDMIA r1, {r0, r3, r10}
STMIA r2, {r0, r3, r10} ; copy current head into node
[ HAL
MOV r10, r2
TST r11, #CDV_Shared
ORREQ r10, r10, #IRQDesp_Link_Unshared
LDR r11, [sp, #4*2] ; r12 value
LDR r12, [sp, #4*1] ; call address
|
LDR r10, [sp, #4*2] ; r12 value
LDR r11, [sp, #4*1] ; call address
MOV r12, r2
]
STMIA r1, {r10-r12} ; copy given info into head
DV_Exit STRVS r0, [sp] ; Common exit for both claim + release
Pull "r0-r3, lr"
B SLVK_TestV
DV_Fail_NaffDevNo
ADR r0, ErrorBlock_NaffDevNo
[ International
BL TranslateError
|
SETV
]
B DV_Exit
MakeErrorBlock NaffDevNo
[ HAL:LAND:{FALSE}
SubInterruptClaim
Push "r5"
ADD r0, r0, r0, LSL #1 ; *3
LDR r5, =DefaultIRQ1V-DefaultIRQ1Vcode+Devices
ADD r5, r5, r0, LSL #2
LDR r2, [r5, #IRQDesp_CallAddr]
ADR r3, SubInterrupt_Despatch
TEQ r2, r3
BEQ AlreadySubbed
; Need to claim the top-level interrupt.
MOV r3, #12
BL ClaimSysHeapNode
Pull "r5",VS
BVS DV_Exit
WritePSRc SVC_mode+I_bit, r10 ; IRQs off for update (on again on SWI exit)
LDMIA r5, {r0, r3, r10}
STMIA r2, {r0, r3, r10} ; copy current head into node
ADR r0, Default_SubInterruptHandler_Node
ADR r3, SubInterrupt_Despatch
STR r0, [r5, #IRQDesp_R12Val]
STR r3, [r5, #IRQDesp_CallAddr]
STR r2, [r5, #IRQDesp_Link]
AlreadySubbed
; r1 -> top level interrupt entry
MOV r3, #PodDesp_NodeSize
BL ClaimSysHeapNode
Pull "r5",VS
BVS DV_Exit
MOV r10, r2
ADD r1, sp, #8
LDMFD r1, {r1-r3}
STR r1, [r10, #PodDesp_CallAddr]
STR r2, [r10, #PodDesp_R12Val]
STR r3, [r10, #PodDesp_Address]
STR r4, [r10, #PodDesp_Mask]
WritePSRc SVC_mode+I_bit, r2 ; IRQs off for update
LDR r0, [r5, #IRQDesp_R12Val]
STR r0, [r10, #PodDesp_Link]
STR r10, [r5, #IRQDesp_R12Val]
Pull "r5"
B DV_Exit
]
[ CDVPoduleIRQs
PoduleChainClaim
MOV r3, #PodDesp_NodeSize
BL ClaimSysHeapNode
BVS DV_Exit
MOV r10, r2
LDMFD sp, {r0-r3}
STR r1, [r10, #PodDesp_CallAddr]
STR r2, [r10, #PodDesp_R12Val]
STR r3, [r10, #PodDesp_Address]
STR r4, [r10, #PodDesp_Mask]
CMP r0, #Podule_DevNo
LDREQ r0, =ZeroPage+PIRQ_Chain
LDRNE r0, =ZeroPage+PFIQasIRQ_Chain
WritePSRc SVC_mode+I_bit, r1 ; IRQs off for update
LDR r1, [r0]
STR r1, [r10, #PodDesp_Link]
STR r10, [r0]
B DV_Exit
]
; .............................................................................
; Release of device vectors
; r0 = Device number
; r1 = call address
; r2 = r12 value
; r0 = PFIQ|PIRQ devno -> r3 = interrupt location (LDRB always used)
; r4 = interrupt mask
DeviceVector_Release ROUT
Push "r0-r3, lr" ; Ensure same regset as above
[ HAL
BIC r0, r0, #CDV_Flags
]
CMP r0, #MaxInterrupts
BHS DV_Fail_NaffDevNo
WritePSRc SVC_mode + I_bit, r12 ; IRQs off while holding context
[ CDVPoduleIRQs
CMP r0, #Podule_DevNo
CMPNE r0, #PFIQasIRQ_DevNo
BEQ PoduleChainRelease
]
ADD r0, r0, r0, LSL #1 ; *3
LDR r12, =DefaultIRQ1V-DefaultIRQ1Vcode+Devices
ADD r12, r12, r0, LSL #2 ; address of node
MOV r11, #-1 ; "fudge" predecessor node
[ HAL
; TEQ r3, #0
; BNE SubInterruptRelease
]
[ HAL
01 LDMIB r12, {r3, r10}
|
01 LDMIA r12, {r3, r10}
]
CMP r3, r2
CMPEQ r10, r1
BEQ %FT02 ; found it
MOV r11, r12
LDR r12, [r12, #IRQDesp_Link]
[ HAL
BICS r12, r12, #IRQDesp_Link_Unshared
|
CMP r12, #0
]
BNE %BT01
11 ADR r0, ErrorBlock_BadDevVecRel
[ International
BL TranslateError
|
SETV
]
B DV_Exit
MakeErrorBlock BadDevVecRel
02 CMP r11, #-1
BEQ %FT03
MOV r2, r12
LDR r12, [r2, #IRQDesp_Link]
[ HAL
LDR r14, [r11, #IRQDesp_Link] ; preserve r11's "unshared" flag
BIC r12, r12, #IRQDesp_Link_Unshared
AND r14, r14, #IRQDesp_Link_Unshared
ORR r12, r12, r14
]
STR r12, [r11, #IRQDesp_Link] ; node delinked
B %FT04
03 LDR r2, [r12, #IRQDesp_Link]; freeable = nextnode
[ HAL
BIC r2, r2, #IRQDesp_Link_Unshared
]
LDMIA r2, {r0, r1, r3} ; copy next node into head posn
STMIA r12, {r0, r1, r3}
04
BL FreeSysHeapNode ; free block
B DV_Exit
[ HAL:LAND:{FALSE}
SubInterruptRelease
ADR r10, SubInterrupt_Despatch
10 LDR r0, [r12, #IRQDesp_CallAddr]
TEQ r0, r10
BEQ %FT15
13 MOV r11, r12
LDR r12, [r12, #IRQDesp_Link]
TEQ r12, #0
BEQ %BT11
B %BT10
15 SUB r0, r12, #PodDesp_Link
17 LDR r14, [r0, #PodDesp_Link]
TEQ r14, #0
BEQ %BT13
LDR r10, [r14, #PodDesp_Address]
CMP r10, r3
LDREQ r10, [r14, #PodDesp_Mask]
CMPEQ r10, r4
LDREQ r10, [r14, #PodDesp_CallAddr]
CMPEQ r10, r1
LDREQ r10, [r14, #PodDesp_R12Val]
CMPEQ r10, r2
MOVNE r0, r14
BNE %BT17
LDR r10, [r14, #PodDesp_Link]
STR r10, [r0, #PodDesp_Link]!
LDR r0, [r12, #IRQDesp_R12Val]
MOV r2, r14
ADR r14, Default_SubInterruptHandler_Node
TEQ r0, r14 ; last sub-interrupt gone?
BNE %BT04
BL FreeSysHeapNode ; free sub-interrupt
BVS DV_Exit
B %BT02 ; then go back to delink top level
]
[ CDVPoduleIRQs
PoduleChainRelease
CMP r0, #Podule_DevNo
LDREQ r0, =ZeroPage+PIRQ_Chain-PodDesp_Link
LDRNE r0, =ZeroPage+PFIQasIRQ_Chain-PodDesp_Link
10 LDR r12, [r0, #PodDesp_Link]
CMP r12, #0
BEQ %BT11
LDR r11, [r12, #PodDesp_Address]
CMP r11, r3
LDREQ r11, [r12, #PodDesp_Mask]
CMPEQ r11, r4
LDREQ r11, [r12, #PodDesp_CallAddr]
CMPEQ r11, r1
LDREQ r11, [r12, #PodDesp_R12Val]
CMPEQ r11, r2
MOVNE r0, r12
BNE %BT10
LDR r11, [r12, #PodDesp_Link]
STR r11, [r0, #PodDesp_Link]
MOV r2, r12
B %BT04
]
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Default device owner for IRQ not recognised by system: pass to IRQ2V
IRQ ROUT
Push "r10, lr"
MOV r10, #IrqV
BL CallVector
[ HAL
Pull "r10, lr"
Pull "pc" ; new-style CDV - pull return address
|
Pull "r10, pc" ; return: someone will always claim it.
]
; *****************************************************************************
; Default IRQ2V:
[ HAL
; r0 must still have devno in it
; r12 is 0 (from vector)
|
; r0 must still have devno*3 in it
; r12 is 0 (from vector)
]
; Clear mask, clear IRQ as appropriate/possible
; NB. a cheap way of dividing by ~3 is *11,/32: accurate for 0..31 result ...
NOIRQ ROUT
[ HAL
TEQ r0, #0
Pull pc, MI
MOV r11, r9
AddressHAL
CallHAL HAL_IRQDisable
MOV r9, r11
|
01 SUBS r0, r0, #3
ADDGE r12, r12, #1
BGT %BT01 ; r12 := r0 DIV 3
CMP R12, #8
MOVLO R0, #IOCIRQMSKA
BLO %FT03
CMP R12, #16
SUBLO R12, R12, #8
MOVLO R0, #IOCIRQMSKB
BLO %FT03
CMP R12, #IOMD_MouseRxFull_DevNo
SUBLO R12, R12, #IOMD_DMAChannel0_DevNo
MOVLO R0, #IOMD_DMAMSK
BLO %FT03
[ MorrisSupport
CMP R12, #IOMD_C_Bit0_DevNo
SUBLO R12, R12, #IOMD_MouseRxFull_DevNo ;reduce to bit number 0..7
MOVLO R0, #IOMD_IRQMSKD ; in IRQ D interrupt register
SUBHS R12, R12, #IOMD_C_Bit0_DevNo
MOVHS R0, #IOMD_IRQMSKC
]
03
ADD r0, r0, #IOC
MOV r1, #1
MOV r1, r1, LSL r12 ; bit to clear
MRS lr, CPSR
BIC r12, lr, #&0F
ORR r12, r12, #I32_bit+F32_bit+IRQ_mode
MSR CPSR_c, r12
LDRB r12, [r0] ; FIQs off for updating IOCIRQMSKA
BIC r12, r12, r1
STRB r12, [r0] ; relevant IRQ disabled
MSR CPSR_c, lr ; absolute minimum FIQ disable period
STRB r1, [r0, #IOCIRQCLRA-IOCIRQMSKA] ; Clear IRQ
]
Pull pc ; claim vector
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; The following bits have been appropriated from source.pmf.oseven to make
; sure Tim's old code doesn't overwrite us when he gets back!
; SWI OS_GenerateEvent: call event vector if enabled
GenEvent ROUT
Push lr
WritePSRc SVC_mode+I_bit, lr ; Disable IRQs. MUST call these ones
BL OSEVEN ; in SVC mode as people expect it
Pull lr
B SLVK
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Subroutine call version
; In r0 = event type
; r1,r2 parameters
; Out C=0 => event was enabled, or was >= 32 anyway
; C=1 => event was disabled, so vector not called
OSEVEN ROUT
Push lr
CMP r0, #31 ; Events >= 32 are ALWAYS raised. SKS
; flags are HI if so, ie. NE
[ ZeroPage = 0
LDRLSB r14, [r0, #OsbyteVars + :INDEX: EventSemaphores]
|
LDRLS r14, =ZeroPage+OsbyteVars+:INDEX:EventSemaphores
LDRLSB r14, [r0, r14]
]
; get semaphore for this event 0..31
CMPLS r14, #0 ; non-zero => enabled
Pull pc, EQ ; if disabled, exit with C=1
Push "r0-r3, r10-r12" ; r3 excessive ???
MOV r10, #EventV ; call event vector
BL CallVector
CLC ; indicate event enabled
Pull "r0-r3, r10-r12, pc"
; ...................... default owner of EventV ..............................
; Call Event handler
; In r12 = EvtHan_ws
DefEvent ROUT
MOV lr, pc ; link with all the bits
LDMIA r12, {r12, pc} ; call EventHandler, returns to ...
TEQ r12, #1
Pull pc,NE
[ ZeroPage = 0
LDRB r14, [r12, #CallBack_Flag-1] ; IRQs are still disabled
ORR r14, r14, #CBack_OldStyle
STRB r14, [r12, #CallBack_Flag-1]
|
LDR r12, =ZeroPage
LDRB r14, [r12, #CallBack_Flag] ; IRQs are still disabled
ORR r14, r14, #CBack_OldStyle
STRB r14, [r12, #CallBack_Flag]
]
Pull pc ; claim EventV
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Process timer zero IRQ device (100Hz clock)
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALIGN 32
TickOne ROUT
[ HAL
; Don't push r14 - we're using new interface, and claim the vector
Push "r0,r9,r12"
AddressHAL
; In some chips, Timer0 is latched in the timer block instead of,
; or as well as in the interrupt controller
MOV R0, #0 ; clear latch for Timer0
CallHAL HAL_TimerIRQClear
Pull "r0" ; get device number back
CallHAL HAL_IRQClear
Pull "r9,r12"
|
Push r14
MOV R0, #timer0_bit
STRB R0, [R3, #IOCIRQCLRA] ; clear timer 0 interrupt
]
LDR R1, =ZeroPage
LDR R0, [R1, #MetroGnome]
ADD R0, R0, #1
STR R0, [R1, #MetroGnome]
LDRB R0, CentiCounter ; Counter for VDU CTRL timing
SUBS R0, R0, #1
STRCSB R0, CentiCounter ; decrement if not zero
LDR R0, IntervalTimer +0
ADDS R0, R0, #1 ; Increment the low 4 bytes
STR R0, IntervalTimer +0
LDREQB R0, IntervalTimer +4
ADDEQ R0, R0, #1 ; and carry into 5th byte if necessary
STREQB R0, IntervalTimer +4
Push "R4,R12" ; R0-R3 already pushed
TEQEQ R0, #&100 ; has interval timer crossed zero ?
MOVEQ R0, #Event_IntervalTimer ; Event ITCZ
BLEQ OSEVEN
BL CentiSecondTick ; Notify keyboard of a centisecond
Pull "R4,R12"
LDR R0, RealTime +0 ; Increment 5-byte real time
ADDS R0, R0, #1
STR R0, RealTime +0
LDRCSB R0, RealTime +4
ADDCS R0, R0, #1 ; Won't wrap until 2248 and then it
STRCSB R0, RealTime +4 ; all falls over anyway
LDRB R0, TimerState ; get switch state
TEQ R0, #5 ; toggles between 5 and 10
LDREQ R1, TimerAlpha +0 ; either load from one
LDREQB R2, TimerAlpha +4
LDRNE R1, TimerBeta +0 ; or the other
LDRNEB R2, TimerBeta +4
ADREQ R3, TimerBeta +0 ; and point to t'other
ADRNE R3, TimerAlpha +0
ADDS R1, R1, #1 ; increment
ADC R2, R2, #0 ; with carry
STR R1, [R3] ; and store back
STRB R2, [R3, #4]
EOR R0, R0, #&0F ; 5 <-> 10
STRB R0, TimerState
Push R10
[ TickIrqReenter
MOV R10, #TickerV ; call 100Hz vector
BL CallVector ; IRQ's still disabled
BL ProcessTickEventChain ; Re-enables IRQs
|
BL ProcessTickEventChain
MOV R10, #TickerV ; call 100Hz vector
BL CallVector
]
Pull "R10,PC"
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Process VSync IRQ device
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALIGN 32
FalseVsyncIRQ ROUT
LDR R1, =ZeroPage
LDR R0, [R1, #MetroGnome]
TST R0, #1
MOVEQ pc, lr
Push "lr"
B VsyncIRQ_ExtEntry
VsyncIRQ ROUT
[ HAL
; Don't push r14 - we're using new interface, and claim the vector
Push "r9,r12"
AddressHAL
CallHAL HAL_IRQClear
Pull "r9,r12"
|
Push r14
MOV R0, #vsync_bit
STRB R0, [R3, #IOCIRQCLRA] ; Clear the vsync interrupt
]
VsyncIRQ_ExtEntry
LDRB R0, CFStime ; decrement 'CFS' timer !
SUB R0, R0, #1
STRB R0, CFStime
VDWS WsPtr ; Do our stuff before issuing VSYNC event
BL VsyncCall
BYTEWS WsPtr
MOV R0, #Event_VSync ; VSYNC event number
BL OSEVEN
LDRB R1, FlashCount
SUBS R1, R1, #1
Pull PC, CC ; was zero, so frozen
STRNEB R1, FlashCount ; else if now non-zero, store it back
Pull PC, NE ; not time to flash yet
LDRB R1, FlashState ; Get the state and
EORS R1, R1, #1 ; flip to the other one (setting flags)
STRB R1, FlashState
LDREQB R2, SpacPeriod ; get appropriate new period
LDRNEB R2, MarkPeriod
STRB R2, FlashCount ; and put into counter
VDWS WsPtr
Push R4
BEQ dothesecondflash
dothefirstflash
BL DoFirstFlash
Pull "R4, PC"
dothesecondflash
BL DoSecondFlash
Pull "R4, PC"
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
END