10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160 ON ERROR PRINT "Error: ";REPORT$;" at ";ERL:END
170
180 DIM Patch_Off(100)
190
200 Data_Size% = 256 * 1024
210
220 DIM Data% Data_Size% + 4
230
240 Source% = FNwhich_source
250
260 CASE Source% OF
270
280 WHEN 105 : PROCdoing_105
290 WHEN 116 : PROCdoing_116
300 WHEN 119 : PROCdoing_119
310 WHEN 120 : PROCdoing_120
320 WHEN 920 : PROCdoing_120x
330 WHEN 128 : PROCdoing_128
340 WHEN 129 : PROCdoing_129
350
360 ENDCASE
370
380 PROCpatch_code
390
400 PRINT "Total size ";Size%;" bytes"
410
420 out_file$ = "6502_" + Which$
430
440 SYS "OS_File", 10, out_file$, &FFA,, Data%, Data% + Size%
450
460 PRINT '"Saved to ";out_file$'
470
480 END
490
500
510
520 DEFFNwhich_source
530
540 LOCAL choice%
550 LOCAL source%
560
570 CLS
580
590 PRINT "Possible sources:"'
600 PRINT "1. Local RISC OS ROM"
610 PRINT "2. RISC OS ROM image file"
620 PRINT "3. BASIC module image file"
630
640 PRINT '"Your source: ";
650
660 SYS "OS_Byte", 15, 0
670
680 REPEAT choice% = GET - ASC("0"):UNTIL choice% >= 1 AND choice% <= 3
690
700 PRINT ;choice%'
710
720 FOR A% = Data% TO Data% + Data_Size% - 1 STEP 4
730
740 !A% = 0
750
760 NEXT
770
780 CASE choice% OF
790
800 WHEN 1 : PROCsrc_local
810 WHEN 2 : PROCsrc_riscos
820 WHEN 3 : PROCsrc_module
830
840 ENDCASE
850
860 source% = 0
870
880 IF source% = 0 THEN IF FNtest_module(52308, &70AD) THEN source% = 105 :
890 IF source% = 0 THEN IF FNtest_module(52628, &5EF2) THEN source% = 116
900 IF source% = 0 THEN IF FNtest_module(55392, &58E4) THEN source% = 119
910 IF source% = 0 THEN IF FNtest_module(55440, &71CA) THEN source% = 120
920 IF source% = 0 THEN IF FNtest_module(55532, &45DF) THEN source% = 920
930 IF source% = 0 THEN IF FNtest_module(55632, &EB77) THEN source% = 128
940 IF source% = 0 THEN IF FNtest_module(55636, &8A16) THEN source% = 129
950
960 IF source% = 0 THEN ERROR 64, "BASIC module not recognized"
970
980 = source%
990
1000
1010
1020 DEFPROCsrc_local
1030
1040 LOCAL base%
1050
1060 SYS "OS_Module", 18, "Basic" TO ,,, base%
1070
1080 Size% = base%!-4 - 4
1090
1100 FOR A% = 0 TO Size% - 1 STEP 4
1110
1120 Data%!A% = base%!A%
1130
1140 NEXT
1150
1160 ENDPROC
1170
1180
1190
1200 DEFPROCsrc_riscos
1210
1220 LOCAL in
1230 LOCAL riscos%
1240 LOCAL file_name$
1250
1260 INPUT "Filename: " file_name$'
1270
1280 Size% = FNfile_size(file_name$)
1290
1300 in = OPENIN(file_name$)
1310
1320 riscos% = 0
1330
1340 IF riscos% = 0 THEN IF FNtest_riscos(in, &119D54, &000000DC) THEN riscos% = 370
1350 IF riscos% = 0 THEN IF FNtest_riscos(in, &11D7A4, &000000DC) THEN riscos% = 371
1360 IF riscos% = 0 THEN IF FNtest_riscos(in, &18F5FC, &000000F4) THEN riscos% = 402
1370 IF riscos% = 0 THEN IF FNtest_riscos(in, &18FFAC, &00000138) THEN riscos% = 403
1380
1390 IF riscos% = 0 THEN ERROR 65, "RISC OS ROM not recognized (knows 3.70, 3.71, 4.02, 4.03)"
1400
1410 PTR#in = PTR#in - 8
1420
1430 SYS "OS_GBPB", 4, in, Data%, 4
1440
1450 Size% = !Data% - 4
1460
1470 SYS "OS_GBPB", 4, in, Data%, Size%
1480
1490 CLOSE#in
1500
1510 ENDPROC
1520
1530
1540
1550 DEFPROCsrc_module
1560
1570 LOCAL file_name$
1580
1590 INPUT "Filename: " file_name$'
1600
1610 Size% = FNfile_size(file_name$)
1620
1630 SYS "OS_File", 16, file_name$, Data%
1640
1650 ENDPROC
1660
1670
1680
1690 DEFFNfile_size(file_name$)
1700
1710 LOCAL size%
1720 LOCAL object%
1730
1740 SYS "OS_File", 17, file_name$ TO object% ,,,, size%
1750
1760 IF object% <> 1 THEN ERROR 214, "File not found"
1770
1780 = size%
1790
1800
1810
1820 DEFFNtest_riscos(in, offset%, word%)
1830
1840 SYS "OS_GBPB", 3, in, Data%, 4, offset%
1850
1860 = (!Data% = word%)
1870
1880
1890
1900 DEFFNtest_module(actual_size%, actual_crc%)
1910
1920 LOCAL crc%
1930
1940 SYS "OS_CRC", 0, Data%, Data% + actual_size%, 1 TO crc%
1950
1960 IF crc% <> actual_crc% THEN = FALSE
1970
1980 Size% = actual_size%
1990
2000 = TRUE
2010
2020
2030
2040 DEFPROCpatch_code
2050
2060 token_AND = &80
2070 token_EOR = &82
2080 token_OR = &84
2090
2100 Size% = (Size% + 3) AND NOT 3
2110
2120
2130
2140
2150
2160 FOR A%=Data% TO Data%+Size%-1
2170 IF !A%=&49534142 AND A%?4=&43 THEN
2180 IF A%!-4<>&20434242 AND A%?5<>ASC"$" AND A%?5<>ASC"T" AND A%?5<>ASC"." THEN
2190 A%!1=&32303536:
2200 ENDIF
2210 ENDIF
2220 NEXT A%
2230
2240 FOR `P = %0000 TO %0010 STEP %0010
2250
2260
2270
2280
2290
2300 PROCprime(1, &E3A0400A)
2310
2320 [OPT `P
2330
2340 MOV r4,#1
2350 MOV r5,#1
2360
2370 ]
2380
2390
2400
2410
2420
2430 IF Source% = 105 OR Source% = 116 THEN word% = &E28F1014 ELSE word% = &E28F103C
2440 PROCprime(2, word%)
2450
2460 [OPT `P
2470
2480 BL patch_6502_1
2490
2500 ]
2510
2520 PROCprim4(3, &E202140F)
2530
2540 [OPT `P
2550
2560 B patch_6502_2
2570
2580 ]
2590
2600 IF Source%=105 OR Source% = 116 THEN
2610
2620 IF Source%=105 THEN Dest%=&A864
2630 IF Source%=116 THEN Dest%=&A9A4
2640
2650 P% -= 6 * 4
2660
2670 [OPT `P
2680
2690 SUB r2,r2,#&F0000000-&C0000000
2700 BCS Data%+Dest%
2710 ADD r11,r11,#2
2720 CMP r2,#&F0000000
2730 BCS P% - 4 * 4
2740
2750 ]
2760
2770 PROCprime(5, &E200000F)
2780
2790 [OPT `P
2800
2810 AND r0,r0,#%11111
2820
2830 ]
2840
2850 ENDIF
2860
2870 PROCprime(5, &E200001F)
2880
2890 [OPT `P
2900
2910 AND r0,r0,#%11111111
2920
2930 ]
2940
2950 IF Source% = 105 OR Source% = 116 THEN word% = &E35A0080 ELSE word% = &E35A007F
2960 PROCprime(4, word%)
2970
2980 [OPT `P
2990
3000 B patch_6502_0
3010
3020 ]
3030
3040
3050
3060
3070
3080 PROCprim4(50, &E51830C0)
3090 PROCprime(51, &E92D4002)
3100 PROCprime(52, &E1A00400)
3110
3120
3130
3140
3150
3160 P% = Data% + Size%
3170
3180 [OPT `P
3190
3200
3210
3220 .patch_6502_0
3230
3240 TEQ r10,#token_OR
3250 LDREQB r1,[r11]
3260 BICEQ r1,r1,#&20
3270 TEQEQ r1,#ASC"A"
3280 SUBEQ r11,r11,#1
3290 LDREQ r0,mnem_ORA
3300 BEQ Data%+Patch_Off(52)
3310 ;
3320 TEQ r10,#token_AND
3330 SUBEQ r11,r11,#2
3340 LDREQ r0,mnem_AND
3350 BEQ Data%+Patch_Off(52)
3360 ;
3370 TEQ r10,#token_EOR
3380 SUBEQ r11,r11,#2
3390 LDREQ r0,mnem_EOR
3400 BEQ Data%+Patch_Off(52)
3410 ;
3420 BIC r0,r10,#&20 ; Build 'mnemonic word'
3430 ;
3440 LDRB r1,[r11,#0]
3450 BIC r1,r1,#&20
3460 ORR r0,r0,r1,LSL#8
3470 ;
3480 LDRB r1,[r11,#1]
3490 BIC r1,r1,#&20
3500 ORR r0,r0,r1,LSL#16
3510 ;
3520 B Data%+Patch_Off(52)
3530 ;
3540 .mnem_ORA
3550 ;
3560 EQUS "ORA "
3570 ;
3580 .mnem_AND
3590 ;
3600 EQUS "AND "
3610 ;
3620 .mnem_EOR
3630 ;
3640 EQUS "EOR "
3650
3660
3670
3680 .patch_6502_1
3690 ;
3700 ADR r1,table_mnem_65xxx ; Use 65xxx mnemonic table instead of ARM one
3710 ;
3720 MOV pc,r14 ; Return
3730
3740
3750
3760 .table_mnem_65xxx
3770 ;
3780 EQUS "ORA":EQUB &00
3790 EQUS "AND":EQUB &02
3800 EQUS "EOR":EQUB &04
3810 EQUS "ADC":EQUB &06
3820 EQUS "STA":EQUB &08
3830 EQUS "LDA":EQUB &0A
3840 EQUS "CMP":EQUB &0C
3850 EQUS "SBC":EQUB &0E
3860 ;
3870 EQUS "ASL":EQUB &10
3880 EQUS "ROL":EQUB &12
3890 EQUS "LSR":EQUB &14
3900 EQUS "ROR":EQUB &16
3910 ;
3920 EQUS "BRL":EQUB &20
3930 EQUS "BPL":EQUB &21
3940 EQUS "BMI":EQUB &23
3950 EQUS "BVC":EQUB &25
3960 EQUS "BVS":EQUB &27
3970 EQUS "BRA":EQUB &28
3980 EQUS "BCC":EQUB &29
3990 EQUS "BCS":EQUB &2B
4000 EQUS "BNE":EQUB &2D
4010 EQUS "BEQ":EQUB &2F
4020 ;
4030 EQUS "BIT":EQUB &30
4040 ;
4050 EQUS "CPX":EQUB &4E
4060 EQUS "CPY":EQUB &4C
4070 ;
4080 EQUS "DEC":EQUB &5C
4090 EQUS "INC":EQUB &5E
4100 ;
4110 EQUS "JMP":EQUB &60
4120 ;
4130 EQUS "JSR":EQUB &70
4140 ;
4150 EQUS "LDX":EQUB &82
4160 EQUS "LDY":EQUB &80
4170 ;
4180 EQUS "STX":EQUB &92
4190 EQUS "STY":EQUB &90
4200 ;
4210 EQUS "TRB":EQUB &A0
4220 EQUS "TSB":EQUB &A1
4230 EQUS "RMB":EQUB &A2
4240 EQUS "SMB":EQUB &A3
4250 EQUS "BBR":EQUB &A4
4260 EQUS "BBS":EQUB &A5
4270 EQUS "CLR":EQUB &A6
4280 EQUS "STZ":EQUB &A6
4290 EQUS "REP":EQUB &A8
4300 EQUS "SEP":EQUB &A9
4310 EQUS "MVN":EQUB &AA
4320 EQUS "MVP":EQUB &AB
4330 EQUS "PEA":EQUB &AC
4340 EQUS "PEI":EQUB &AD
4350 EQUS "PER":EQUB &AE
4360 EQUS "COP":EQUB &AF
4370 ;
4380 EQUS "BRK":EQUB &B0
4390 EQUS "CLC":EQUB &B1
4400 EQUS "CLD":EQUB &B2
4410 EQUS "CLI":EQUB &B3
4420 EQUS "CLV":EQUB &B4
4430 EQUS "DEX":EQUB &B5
4440 EQUS "DEY":EQUB &B6
4450 EQUS "INX":EQUB &B7
4460 EQUS "INY":EQUB &B8
4470 EQUS "NOP":EQUB &B9
4480 EQUS "PHA":EQUB &BA
4490 EQUS "PHP":EQUB &BB
4500 EQUS "PLA":EQUB &BC
4510 EQUS "PLP":EQUB &BD
4520 EQUS "RTI":EQUB &BE
4530 EQUS "RTS":EQUB &BF
4540 EQUS "SEC":EQUB &C0
4550 EQUS "SED":EQUB &C1
4560 EQUS "SEI":EQUB &C2
4570 EQUS "TAX":EQUB &C3
4580 EQUS "TAY":EQUB &C4
4590 EQUS "TSX":EQUB &C5
4600 EQUS "TXA":EQUB &C6
4610 EQUS "TXS":EQUB &C7
4620 EQUS "TYA":EQUB &C8
4630 EQUS "DEA":EQUB &C9
4640 EQUS "INA":EQUB &CA
4650 EQUS "PHX":EQUB &CB
4660 EQUS "PHY":EQUB &CC
4670 EQUS "PLX":EQUB &CD
4680 EQUS "PLY":EQUB &CE
4690 EQUS "WAI":EQUB &CF
4700 EQUS "STP":EQUB &D0
4710 EQUS "PHB":EQUB &D1
4720 EQUS "PHD":EQUB &D2
4730 EQUS "PHK":EQUB &D3
4740 EQUS "PLB":EQUB &D4
4750 EQUS "PLD":EQUB &D5
4760 EQUS "RTL":EQUB &D6
4770 EQUS "TCD":EQUB &D7
4780 EQUS "TAD":EQUB &D7
4790 EQUS "TCS":EQUB &D8
4800 EQUS "TAS":EQUB &D8
4810 EQUS "TDC":EQUB &D9
4820 EQUS "TDA":EQUB &D9
4830 EQUS "TSC":EQUB &DA
4840 EQUS "TSA":EQUB &DA
4850 EQUS "TXY":EQUB &DB
4860 EQUS "TYX":EQUB &DC
4870 EQUS "XBA":EQUB &DD
4880 EQUS "SWA":EQUB &DD
4890 EQUS "XCE":EQUB &DE
4900 ;
4910 EQUS "OPT":EQUB &F0 ; (pass the other relevant ones)
4920 EQUS "EQU":EQUB &F1
4930 EQUS "DCB":EQUB &F2
4940 EQUS "DCW":EQUB &F3
4950 EQUS "DCD":EQUB &F4
4960 ;
4970 EQUD 0 ; (end of table)
4980
4990
5000
5010 .supported_opcodes
5020 ;
5030 ; 0 1 2 3 4 5 6 7 8 9 A B C D E F
5040 ;
5050 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110 ; 0
5060 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110 ; 1
5070 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; 2
5080 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110 ; 3
5090 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; 4
5100 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110 ; 5
5110 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; 6
5120 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %110:EQUB %111:EQUB %111:EQUB %110 ; 7
5130 EQUB %110:EQUB %111:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %110:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; 8
5140 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %110:EQUB %111:EQUB %110:EQUB %110 ; 9
5150 EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; A
5160 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; B
5170 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; C
5180 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %110:EQUB %100:EQUB %111:EQUB %111:EQUB %110 ; D
5190 EQUB %111:EQUB %111:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %111:EQUB %100:EQUB %111:EQUB %111:EQUB %111:EQUB %110 ; E
5200 EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110:EQUB %111:EQUB %111:EQUB %110:EQUB %100:EQUB %100:EQUB %111:EQUB %111:EQUB %110 ; F
5210
5220
5230
5240 .instr_6502
5250 ;
5260 EQUD 0
5270
5280
5290
5300 .patch_6502_2
5310 ;
5320 MOV r3,r2,LSR#24 ; Initialise processing flags
5330 ;
5340 LDRB r10,[r11],#1 ; To next character
5350 ;
5360 CMP r3,#&A2 ; Is this a 4-char mnemonic ?
5370 RSBCSS r14,r3,#&A5
5380 BCS class_nobn ; Yes, don't skip spaces
5390 ;
5400 BL skip_spaces ; Skip spaces
5410 ;
5420 .class_nobn
5430 ;
5440 ADR r2,instr_6502+1 ; Buffer for instruction
5450 ;
5460 MOV r0,#0 ; Wipe it
5470 STR r0,[r2]
5480 ;
5490 ADR r14,class_done ; Call 'class' handler
5500 STMFD r13!,{r14}
5510 AND r0,r3,#%11110000
5520 ADD pc,pc,r0,LSR#4-2
5530 MOV r0,r0
5540 ;
5550 B class_ORA
5560 B class_ASL
5570 B class_BPL
5580 B class_BIT
5590 B class_CPX
5600 B class_DEC
5610 B class_JMP
5620 B class_JSR
5630 B class_LDX
5640 B class_STX
5650 B class_TRB
5660 B class_BRK
5670 B class_BRK
5680 B class_BRK
5690 B class_BRK
5700 EQUD 0
5710 ;
5720 .class_done
5730 ;
5740 BL skip_spaces ; Skip spaces
5750 ;
5760 MOV r0,r3,LSR#24 ; Buffer final opcode
5770 STRB r0,instr_6502
5780 ;
5790 MOV r1,#0 ; Processor code
5800 BL opt_16
5810 MOVNE r1,#1
5820 BL opt_32
5830 MOVNE r1,#2
5840 ;
5850 ADR r14,supported_opcodes ; Instruction supported by processor ?
5860 LDRB r14,[r14,r0]
5870 MOV r14,r14,LSR r1
5880 TST r14,#1
5890 BEQ badop_error ; No, generate error
5900 ;
5910 AND r0,r0,#%00000111 ; 65C02/65C816 conflict area ?
5920 TEQ r0,#%00000111
5930 BNE badop_nconf ; No
5940 ;
5950 AND r0,r3,#%11111111 ; Actual 'Rockwell' conflict ?
5960 CMP r0,#&A2
5970 RSBCSS r0,r0,#&A5
5980 MOVCS r0,#1
5990 MOVCC r0,#2
6000 ;
6010 TEQ r0,r1
6020 BNE badop_error ; Yes, generate error
6030 ;
6040 .badop_nconf
6050 ;
6060 ADR r1,instr_6502 ; Return number of bytes
6070 SUB r2,r2,r1
6080 ;
6090 LDR r1,instr_6502 ; Return bytes to output
6100 ;
6110 B Data%+Patch_Off(50) ; Join '0..4 bytes' code
6120 ;
6130 .badop_error
6140 ;
6150 CMP r1,#1
6160 BLO badop_error_6502
6170 BEQ badop_error_65C02
6180 BHI badop_error_65C816
6190 ;
6200 .badop_error_6502
6210 ;
6220 FNgenerate_error_message(4, "Instruction not supported by 6502")
6230 ;
6240 .badop_error_65C02
6250 ;
6260 FNgenerate_error_message(4, "Instruction not supported by 65C02")
6270 ;
6280 .badop_error_65C816
6290 ;
6300 FNgenerate_error_message(4, "Instruction not supported by 65C816")
6310 ;
6320 ;
6330 ;
6340 .eval_expr_prev
6350 ;
6360 SUB r11,r11,#1 ; Step back one character
6370 LDRB r10,[r11,#-1]
6380 ;
6390 .eval_expr_curr
6400 ;
6410 STMFD r13!,{r1-r3,r14} ; Evaluate expression
6420 ;
6430 BL Data%+Patch_Off(51)
6440 ;
6450 LDMFD r13!,{r1-r3,pc}^
6460 ;
6470 .eval_expr_prev_sized
6480 ;
6490 SUB r11,r11,#1 ; Step back one character
6500 LDRB r10,[r11,#-1]
6510 ;
6520 .eval_expr_curr_sized
6530 ;
6540 .evxcs_skspc
6550 ;
6560 LDRB r10,[r11],#1 ; Skip any spaces
6570 TEQ r10,#ASC" "
6580 BEQ evxcs_skspc
6590 ;
6600 TEQ r10,#ASC"<" ; Size indicator present ?
6610 TEQNE r10,#ASC">"
6620 TEQNE r10,#ASC"^"
6630 ;
6640 BNE eval_expr_prev ; No, nothing to skip
6650 ;
6660 CMP r10,#ASC">" ; Flag size indicator
6670 ORRLO r3,r3,#1<<16
6680 ORREQ r3,r3,#2<<16
6690 ORRHI r3,r3,#3<<16
6700 ;
6710 B eval_expr_curr ; And skip indicator
6720 ;
6730 ;
6740 ;
6750 .hop_skip_spaces
6760 ;
6770 LDRB r10,[r11],#1 ; Skip character
6780 ;
6790 .skip_spaces
6800 ;
6810 TEQ r10,#ASC" " ; Scan to non-space
6820 LDREQB r10,[r11],#1
6830 BEQ skip_spaces
6840 ;
6850 MOVS pc,r14
6860 ;
6870 ;
6880 ;
6890 .not_a_variable
6900 ;
6910 STMFD r13!,{r14}
6920 ;
6930 LDRB r14,[r11]
6940 ;
6950 CMP r14,#ASC"A"
6960 BLO notav_chelo
6970 CMP r14,#ASC"Z"
6980 BLS notav_isvar
6990 ;
7000 .notav_chelo
7010 ;
7020 CMP r14,#ASC"a"
7030 BLO notav_chedi
7040 CMP r14,#ASC"z"
7050 BLS notav_isvar
7060 ;
7070 .notav_chedi
7080 ;
7090 CMP r14,#ASC"0"
7100 BLO notav_cheot
7110 CMP r14,#ASC"9"
7120 BLS notav_isvar
7130 ;
7140 .notav_cheot
7150 ;
7160 TEQ r14,#ASC"`"
7170 TEQNE r14,#ASC"_"
7180 TEQNE r14,#ASC"$"
7190 TEQNE r14,#ASC"%"
7200 TEQNE r14,#ASC"("
7210 BEQ notav_isvar
7220 ;
7230 TEQ r14,r14
7240 ;
7250 LDMFD r13!,{pc}
7260 ;
7270 .notav_isvar
7280 ;
7290 CMN r14,#1
7300 ;
7310 LDMFD r13!,{pc}
7320 ;
7330 ;
7340 ;
7350 .opt_2
7360 ;
7370 STMFD r13!,{r0,r14}
7380 ;
7390 LDRB r0,[r8,#basoff_opt%]
7400 TST r0,#2
7410 ;
7420 LDMFD r13!,{r0,pc}
7430 ;
7440 ;
7450 ;
7460 .opt_16
7470 ;
7480 STMFD r13!,{r0,r14}
7490 ;
7500 LDRB r0,[r8,#basoff_opt%]
7510 TST r0,#16
7520 ;
7530 LDMFD r13!,{r0,pc}
7540 ;
7550 ;
7560 ;
7570 .opt_32
7580 ;
7590 STMFD r13!,{r0,r14}
7600 ;
7610 LDRB r0,[r8,#basoff_opt%]
7620 TST r0,#32
7630 ;
7640 LDMFD r13!,{r0,pc}
7650 ;
7660 ;
7670 ;
7680 .mnem_bit_number
7690 ;
7700 CMP r10,#ASC"0" ; '0' .. '7', as expected ?
7710 BLO mnebn_error ; No, error
7720 CMP r10,#ASC"7"
7730 BHI mnebn_error ; No, error
7740 ;
7750 SUB r0,r10,#ASC"0" ; Return bit number
7760 ;
7770 B hop_skip_spaces ; Skip bit number and spaces
7780 ;
7790 .mnebn_error
7800 ;
7810 FNgenerate_error_message(2, "Expected bit number (0-7) attached to mnemonic")
7820 ;
7830 ;
7840 ;
7850 .is_left_bracket
7860 ;
7870 TEQ r10,#ASC"(" ; Round bracket ?
7880 BEQ isleb_match ; Yes (default)
7890 ;
7900 TEQ r10,#ASC"[" ; Square bracket ?
7910 ORREQ r3,r3,#1<<23 ; Yes (flag it)
7920 ;
7930 .isleb_match
7940 ;
7950 MOV pc,r14 ; Return (with flags !)
7960 ;
7970 ;
7980 ;
7990 .is_right_bracket
8000 ;
8010 STMFD r13!,{r14} ; Save link
8020 ;
8030 TST r3,#1<<23 ; Which bracket type ?
8040 MOVEQ r14,#ASC")"
8050 MOVNE r14,#ASC"]"
8060 ;
8070 TEQ r10,r14 ; Correct right bracket ?
8080 ;
8090 LDMFD r13!,{pc} ; Return (with flags !)
8100 ;
8110 ;
8120 ;
8130 .is_comma_Y
8140 ;
8150 STMFD r13!,{r10,r11,r14} ; Save used registers
8160 ;
8170 TEQ r10,#ASC"," ; Expected ',' ?
8180 BNE iscoy_done ; No, no match
8190 ;
8200 BL hop_skip_spaces ; Skip ',', skip spaces
8210 ;
8220 TEQ r10,#ASC"Y" ; Expected 'Y' ?
8230 TEQNE r10,#ASC"y"
8240 ;
8250 .iscoy_done
8260 ;
8270 LDMFD r13!,{r10,r11,pc} ; Return (with flags !)
8280 ;
8290 ;
8300 ;
8310 .is_comma_S
8320 ;
8330 STMFD r13!,{r10,r11,r14} ; Save used registers
8340 ;
8350 TEQ r10,#ASC"," ; Expected ',' ?
8360 BNE iscos_done ; No, no match
8370 ;
8380 BL hop_skip_spaces ; Skip ',', skip spaces
8390 ;
8400 TEQ r10,#ASC"S" ; Expected 'S' ?
8410 TEQNE r10,#ASC"s"
8420 ;
8430 .iscos_done
8440 ;
8450 LDMFD r13!,{r10,r11,pc} ; Return (with flags !)
8460 ;
8470 ;
8480 ;
8490 .error_or_immediate_ha
8500 ;
8510 TEQ r10,#ASC"#" ; Expected character(s) ?
8520 MOVEQS pc,r14 ; Yes, return
8530 ;
8540 FNgenerate_error_message(2, "Immediate addressing: expected #")
8550 ;
8560 ;
8570 ;
8580 .error_or_zeropagex_X
8590 ;
8600 TEQ r10,#ASC"X" ; Expected character(s) ?
8610 TEQNE r10,#ASC"x"
8620 MOVEQS pc,r14 ; Yes, return
8630 ;
8640 FNgenerate_error_message(3, "Zero-page,X addressing: expected X")
8650 ;
8660 ;
8670 ;
8680 .error_or_zeropagey_Y
8690 ;
8700 TEQ r10,#ASC"Y" ; Expected character(s) ?
8710 TEQNE r10,#ASC"y"
8720 MOVEQS pc,r14 ; Yes, return
8730 ;
8740 FNgenerate_error_message(3, "Zero-page,Y addressing: expected Y")
8750 ;
8760 ;
8770 ;
8780 .error_or_absolutex_X
8790 ;
8800 TEQ r10,#ASC"X" ; Expected character(s) ?
8810 TEQNE r10,#ASC"x"
8820 MOVEQS pc,r14 ; Yes, return
8830 ;
8840 FNgenerate_error_message(3, "Absolute,X addressing: expected X")
8850 ;
8860 ;
8870 ;
8880 .error_or_absolutey_Y
8890 ;
8900 TEQ r10,#ASC"Y" ; Expected character(s) ?
8910 TEQNE r10,#ASC"y"
8920 MOVEQS pc,r14 ; Yes, return
8930 ;
8940 FNgenerate_error_message(3, "Absolute,Y addressing: expected Y")
8950 ;
8960 ;
8970 ;
8980 .error_or_absolute_X_Y
8990 ;
9000 TEQ r10,#ASC"X" ; Expected character(s) ?
9010 TEQNE r10,#ASC"x"
9020 TEQNE r10,#ASC"Y"
9030 TEQNE r10,#ASC"y"
9040 MOVEQS pc,r14 ; Yes, return
9050 ;
9060 FNgenerate_error_message(3, "Absolute,X/Y addressing: expected X or Y")
9070 ;
9080 ;
9090 ;
9100 .error_or_absolongx_X
9110 ;
9120 TEQ r10,#ASC"X" ; Expected character(s) ?
9130 TEQNE r10,#ASC"x"
9140 MOVEQS pc,r14 ; Yes, return
9150 ;
9160 FNgenerate_error_message(3, "Absolute Long,X addressing: expected X")
9170 ;
9180 ;
9190 ;
9200 .error_or_indirect_ls
9210 ;
9220 TEQ r10,#ASC"(" ; Expected character(s) ?
9230 MOVEQS pc,r14 ; Yes, return
9240 ;
9250 FNgenerate_error_message(3, "Indirect addressing: expected (")
9260 ;
9270 ;
9280 ;
9290 .error_or_indirect_co_rb
9300 ;
9310 STMFD r13!,{r14} ; Save link
9320 ;
9330 TEQ r10,#ASC"," ; Expected character(s) ?
9340 BLNE is_right_bracket
9350 LDMEQFD r13!,{pc}^ ; Yes, return
9360 ;
9370 TST r3,#1<<23
9380 BNE ermsg_indirect_co_rh
9390 ;
9400 .ermsg_indirect_co_rs
9410 ;
9420 FNgenerate_error_message(3, "Indirect addressing: expected , or )")
9430 ;
9440 .ermsg_indirect_co_rh
9450 ;
9460 FNgenerate_error_message(3, "Indirect addressing: expected , or ]")
9470 ;
9480 ;
9490 ;
9500 .error_or_indirect_X_S
9510 ;
9520 TEQ r10,#ASC"X" ; Expected character(s) ?
9530 TEQNE r10,#ASC"x"
9540 TEQNE r10,#ASC"S"
9550 TEQNE r10,#ASC"s"
9560 MOVEQS pc,r14 ; Yes, return
9570 ;
9580 FNgenerate_error_message(3, "Indirect addressing: expected X or S")
9590 ;
9600 ;
9610 ;
9620 .error_or_indirect_rb
9630 ;
9640 STMFD r13!,{r14} ; Save link
9650 ;
9660 BL is_right_bracket ; Expected character(s) ?
9670 LDMEQFD r13!,{pc}^ ; Yes, return
9680 ;
9690 TST r3,#1<<23
9700 BNE ermsg_indirect_rh
9710 ;
9720 .ermsg_indirect_rs
9730 ;
9740 FNgenerate_error_message(3, "Indirect addressing: expected )")
9750 ;
9760 .ermsg_indirect_rh
9770 ;
9780 FNgenerate_error_message(3, "Indirect addressing: expected ]")
9790 ;
9800 ;
9810 ;
9820 .error_or_indirectx_co
9830 ;
9840 TEQ r10,#ASC"," ; Expected character(s) ?
9850 MOVEQS pc,r14 ; Yes, return
9860 ;
9870 FNgenerate_error_message(3, "Indirect,X addressing: expected ,")
9880 ;
9890 ;
9900 ;
9910 .error_or_indirectx_X
9920 ;
9930 TEQ r10,#ASC"X" ; Expected character(s) ?
9940 TEQNE r10,#ASC"x"
9950 MOVEQS pc,r14 ; Yes, return
9960 ;
9970 FNgenerate_error_message(3, "Indirect,X addressing: expected X")
9980 ;
9990 ;
10000 ;
10010 .error_or_indirectx_rb
10020 ;
10030 STMFD r13!,{r14} ; Save link
10040 ;
10050 BL is_right_bracket ; Expected character(s) ?
10060 LDMEQFD r13!,{pc}^ ; Yes, return
10070 ;
10080 TST r3,#1<<23
10090 BNE ermsg_indirectx_rh
10100 ;
10110 .ermsg_indirectx_rs
10120 ;
10130 FNgenerate_error_message(3, "Indirect,X addressing: expected )")
10140 ;
10150 .ermsg_indirectx_rh
10160 ;
10170 FNgenerate_error_message(3, "Indirect,X addressing: expected ]")
10180 ;
10190 ;
10200 ;
10210 .error_or_indirecty_Y
10220 ;
10230 TEQ r10,#ASC"Y" ; Expected character(s) ?
10240 TEQNE r10,#ASC"y"
10250 MOVEQS pc,r14 ; Yes, return
10260 ;
10270 FNgenerate_error_message(3, "Indirect,Y addressing: expected Y")
10280 ;
10290 ;
10300 ;
10310 .error_or_indirects_co
10320 ;
10330 TEQ r10,#ASC"," ; Expected character(s) ?
10340 MOVEQS pc,r14 ; Yes, return
10350 ;
10360 FNgenerate_error_message(3, "Indirect,S addressing: expected ,")
10370 ;
10380 ;
10390 ;
10400 .error_or_indirects_Y
10410 ;
10420 TEQ r10,#ASC"Y" ; Expected character(s) ?
10430 TEQNE r10,#ASC"y"
10440 MOVEQS pc,r14 ; Yes, return
10450 ;
10460 FNgenerate_error_message(3, "Indirect,S addressing: expected Y")
10470 ;
10480 ;
10490 ;
10500 .error_or_indirects_rb
10510 ;
10520 STMFD r13!,{r14} ; Save link
10530 ;
10540 BL is_right_bracket ; Expected character(s) ?
10550 LDMEQFD r13!,{pc}^ ; Yes, return
10560 ;
10570 TST r3,#1<<23
10580 BNE ermsg_indirects_rh
10590 ;
10600 .ermsg_indirects_rs
10610 ;
10620 FNgenerate_error_message(3, "Indirect,S addressing: expected )")
10630 ;
10640 .ermsg_indirects_rh
10650 ;
10660 FNgenerate_error_message(3, "Indirect,S addressing: expected ]")
10670 ;
10680 ;
10690 ;
10700 .error_or_BBx_co
10710 ;
10720 TEQ r10,#ASC"," ; Expected character(s) ?
10730 MOVEQS pc,r14 ; Yes, return
10740 ;
10750 FNgenerate_error_message(3, "BBR/BBS Zero-page,Relative addressing: expected ,")
10760 ;
10770 ;
10780 ;
10790 .error_or_MVx_co
10800 ;
10810 TEQ r10,#ASC"," ; Expected character(s) ?
10820 MOVEQS pc,r14 ; Yes, return
10830 ;
10840 FNgenerate_error_message(3, "MVN/MVP Bank,Bank addressing: expected ,")
10850 ;
10860 ;
10870 ;
10880 .error_if_constoverflowB
10890 ;
10900 STMFD r13!,{r1,r14} ; Save registers and link
10910 ;
10920 ADR r1,ermsg_constoverflowB
10930 ;
10940 B error_if_byteoverflow
10950 ;
10960 .error_if_constoverflowS
10970 ;
10980 STMFD r13!,{r1,r14} ; Save registers and link
10990 ;
11000 ADR r1,ermsg_constoverflowS
11010 ;
11020 B error_if_shortoverflow
11030 ;
11040 .error_if_zpaddroverflow
11050 ;
11060 STMFD r13!,{r1,r14} ; Save registers and link
11070 ;
11080 ADR r1,ermsg_zpaddroverflow
11090 ;
11100 B error_if_byteoverflow
11110 ;
11120 .error_if_banknroverflow
11130 ;
11140 STMFD r13!,{r1,r14} ; Save registers and link
11150 ;
11160 ADR r1,ermsg_banknroverflow
11170 ;
11180 B error_if_byteoverflow
11190 ;
11200 .error_if_codebyteoverflow
11210 ;
11220 STMFD r13!,{r1,r14} ; Save registers and link
11230 ;
11240 ADR r1,ermsg_codebyteoverflow
11250 ;
11260 B error_if_byteoverflow
11270 ;
11280 .error_if_shortoverflow
11290 ;
11300 CMP r0,#&10000 ; In range ?
11310 LDMLOFD r13!,{r1,pc}^ ; Yes, return
11320 ;
11330 MVN r14,#0 ; Force in range
11340 BIC r0,r0,r14,LSL#16
11350 ;
11360 B eiovr_chopt ; Continue
11370 ;
11380 .error_if_byteoverflow
11390 ;
11400 CMP r0,#&100 ; In range ?
11410 LDMLOFD r13!,{r1,pc}^ ; Yes, return
11420 ;
11430 AND r0,r0,#&FF ; Force in range
11440 ;
11450 .eiovr_chopt
11460 ;
11470 BL opt_2 ; Errors fatal ?
11480 ;
11490 LDMEQFD r13!,{r1,pc}^ ; No, return
11500 ;
11510 MOV r0,r1 ; Yes, generate error
11520 ;
11530 B error_generate
11540 ;
11550 .ermsg_constoverflowB
11560 ;
11570 FNerror_message(2, "Immediate value out of range [0..255]")
11580 ;
11590 .ermsg_constoverflowS
11600 ;
11610 FNerror_message(2, "Immediate value out of range [0..65535]")
11620 ;
11630 .ermsg_zpaddroverflow
11640 ;
11650 FNerror_message(2, "Zero-page address out of range [0..255]")
11660 ;
11670 .ermsg_banknroverflow
11680 ;
11690 FNerror_message(1, "Bank number out of range [0..255]")
11700 ;
11710 .ermsg_codebyteoverflow
11720 ;
11730 FNerror_message(2, "Code byte out of range [0..255]")
11740 ;
11750 ;
11760 ;
11770 .error_if_offsetoutofrange
11780 ;
11790 STMFD r13!,{r2-r3,r14} ; Save registers and link
11800 ;
11810 LDR r2,[r8,#basoff_p%] ; Branch offset
11820 ADD r2,r2,r1,LSR#30
11830 SUB r0,r0,r2
11840 ;
11850 MOV r3,#1 ; In range ?
11860 MOV r3,r3,LSL r1
11870 ADD r2,r0,r3,LSR#1
11880 CMP r2,r3
11890 LDMLOFD r13!,{r2-r3,pc}^ ; Yes, return
11900 ;
11910 BL opt_2 ; Errors fatal ?
11920 ;
11930 LDMEQFD r13!,{r2-r3,pc}^ ; No, return
11940 ;
11950 TEQ r1,#2<<30 OR 8 ; Yes, generate error
11960 ADREQ r0,ermsg_offsetoutofrange_Bxx
11970 TEQ r1,#3<<30 OR 8
11980 ADREQ r0,ermsg_offsetoutofrange_BBx
11990 TEQ r1,#3<<30 OR 16
12000 ADREQ r0,ermsg_offsetoutofrange_BRL
12010 ;
12020 B error_generate
12030 ;
12040 .ermsg_offsetoutofrange_Bxx
12050 ;
12060 FNerror_message(1, "Branch target out of range [P%-126,P%+129]")
12070 ;
12080 .ermsg_offsetoutofrange_BBx
12090 ;
12100 FNerror_message(1, "Branch target out of range [P%-125,P%+130]")
12110 ;
12120 .ermsg_offsetoutofrange_BRL
12130 ;
12140 FNerror_message(1, "Branch target out of range [P%-32765,P%+32770]")
12150 ;
12160 ;
12170 ;
12180 .error_generate
12190 ;
12200 SWI "OS_GenerateError"
12210 ;
12220 ;
12230 ;
12240 .which_address_size
12250 ;
12260 STMFD r13!,{r1,r14} ; Save registers and link
12270 ;
12280 CMP r0,#256 ; Address size in bytes
12290 MOVLO r14,#1
12300 MOVHS r14,#2
12310 ;
12320 MOV r1,#%11
12330 ANDS r1,r1,r3,LSR#16
12340 MOVEQ r1,r14
12350 ;
12360 CMP r1,#2 ; Which address size ?
12370 ;
12380 LDMFD r13!,{r1,pc} ; Return (with flags !)
12390 ;
12400 ;
12410 ;
12420 .try_immediate
12430 ;
12440 TEQ r10,#ASC"#" ; Immediate indicated ?
12450 TEQNE r10,#ASC"%"
12460 MOVNES pc,r14 ; No, so not immediate
12470 ;
12480 ORR r3,r3,r1,LSL#24 ; Finish opcode
12490 ;
12500 MOV r1,r10 ; Remember value size
12510 ;
12520 BL eval_expr_curr ; Past '#'/'%', immediate value
12530 ;
12540 TEQ r1,#ASC"%" ; Large size ?
12550 BEQ trim_large ; Yes, 16 bit
12560 ;
12570 BL error_if_constoverflowB ; Error if not in range
12580 ;
12590 B finish_byte ; End with 1 argument byte
12600 ;
12610 .trim_large
12620 ;
12630 BL error_if_constoverflowS ; Error if not in range
12640 ;
12650 B finish_dble ; End with 2 argument bytes
12660 ;
12670 ;
12680 ;
12690 .try_zeropage
12700 ;
12710 TEQ r10,#ASC"," ; Zero-page indicated ?
12720 MOVEQS pc,r14 ; No (an indexed version)
12730 ;
12740 AND r14,r1,#%11111111 ; Finish opcode
12750 ORR r3,r3,r14,LSL#24
12760 ;
12770 B finish_byte ; End with 1 argument byte
12780 ;
12790 ;
12800 ;
12810 .try_absolute
12820 ;
12830 TEQ r10,#ASC"," ; Absolute indicated ?
12840 MOVEQS pc,r14 ; No (an indexed version)
12850 ;
12860 AND r14,r1,#%11111111 ; Finish opcode
12870 ORR r3,r3,r14,LSL#24
12880 ;
12890 B finish_dble ; End with 2 argument bytes
12900 ;
12910 ;
12920 ;
12930 .try_absolong
12940 ;
12950 TEQ r10,#ASC"," ; Absolute long indicated ?
12960 MOVEQS pc,r14 ; No (an indexed version)
12970 ;
12980 AND r14,r1,#%11111111 ; Finish opcode
12990 ORR r3,r3,r14,LSL#24
13000 ;
13010 B finish_trip ; End with 3 argument bytes
13020 ;
13030 ;
13040 ;
13050 .try_indirect
13060 ;
13070 MOV r1,r14 ; Indirect indicated ?
13080 BL is_left_bracket
13090 MOVNES pc,r1 ; No, so not indirect
13100 ;
13110 BL eval_expr_curr ; Past '('/'[', zero-page address
13120
13130 BL error_if_zpaddroverflow
13140
13150 TST r3,#1<<23
13160 BNE trind_plory
13170
13180 BL error_or_indirect_co_rb
13190
13200 TEQ r10,#ASC","
13210 BNE trind_plory
13220
13230 BL hop_skip_spaces
13240
13250 BL error_or_indirect_X_S
13260
13270 TEQ r10,#ASC"S"
13280 TEQNE r10,#ASC"s"
13290 BEQ trind_strel
13300
13310 ORR r3,r3,#%00000001<<24
13320
13330 BL hop_skip_spaces
13340
13350 BL error_or_indirectx_rb
13360
13370 B finish_hop_byte
13380
13390 .trind_plory
13400
13410 BL error_or_indirect_rb
13420
13430 TST r3,#1<<23
13440 ORREQ r3,r3,#%00010001<<24
13450 ORRNE r3,r3,#%00010111<<24
13460
13470 BL hop_skip_spaces
13480
13490 TEQ r10,#ASC","
13500 BNE trind_plain
13510
13520 BL hop_skip_spaces
13530
13540 BL error_or_indirecty_Y
13550
13560 B finish_hop_byte
13570
13580 .trind_plain
13590
13600 TST r3,#1<<23
13610 EOREQ r3,r3,#%00000011<<24
13620 EORNE r3,r3,#%00010000<<24
13630
13640 B finish_byte
13650
13660 .trind_strel
13670
13680 ORR r3,r3,#%00010011<<24
13690
13700 BL hop_skip_spaces
13710
13720 BL error_or_indirects_rb
13730
13740 BL hop_skip_spaces
13750
13760 BL error_or_indirects_co
13770
13780 BL hop_skip_spaces
13790
13800 BL error_or_indirects_Y
13810
13820 B finish_hop_byte
13830
13840
13850
13860 .do_zeropage_Xopt
13870
13880 BL try_zeropage
13890
13900 BL hop_skip_spaces
13910
13920 BL error_or_zeropagex_X
13930
13940 MOV r14,r1,LSR#8
13950 ORR r3,r3,r14,LSL#24
13960
13970 B finish_hop_byte
13980
13990
14000
14010 .do_zeropage_XorYopt
14020
14030 BL try_zeropage
14040
14050 BL hop_skip_spaces
14060
14070 TST r3,#%1111
14080 BLEQ error_or_zeropagex_X
14090 BLNE error_or_zeropagey_Y
14100
14110 MOV r14,r1,LSR#8
14120 ORR r3,r3,r14,LSL#24
14130
14140 B finish_hop_byte
14150
14160
14170
14180 .do_absolute_Xopt
14190
14200 BL try_absolute
14210
14220 BL hop_skip_spaces
14230
14240 BL error_or_absolutex_X
14250
14260 MOV r14,r1,LSR#8
14270 ORR r3,r3,r14,LSL#24
14280
14290 B finish_hop_dble
14300
14310
14320
14330 .do_absolute_XorYopt
14340
14350 BL try_absolute
14360
14370 BL hop_skip_spaces
14380
14390 TST r3,#%1111
14400 BLEQ error_or_absolutex_X
14410 BLNE error_or_absolutey_Y
14420
14430 MOV r14,r1,LSR#8
14440 ORR r3,r3,r14,LSL#24
14450
14460 B finish_hop_dble
14470
14480
14490
14500 .do_absolong_Xopt
14510
14520 BL try_absolong
14530
14540 BL hop_skip_spaces
14550
14560 BL error_or_absolongx_X
14570
14580 MOV r14,r1,LSR#8
14590 ORR r3,r3,r14,LSL#24
14600
14610 B finish_hop_trip
14620
14630
14640
14650 .finish_hop_implied
14660
14670 LDRB r10,[r11],#1 ; Consume current character
14680 ;
14690 B finish_implied
14700 ;
14710 .finish_hop_byte
14720 ;
14730 LDRB r10,[r11],#1 ; Consume current character
14740 ;
14750 B finish_byte
14760 ;
14770 .finish_hop_dble
14780 ;
14790 LDRB r10,[r11],#1 ; Consume current character
14800 ;
14810 B finish_dble
14820 ;
14830 .finish_hop_trip
14840 ;
14850 LDRB r10,[r11],#1 ; Consume current character
14860 ;
14870 .finish_trip
14880 ;
14890 STRB r0,[r2],#1 ; Buffer opcode argument
14900 MOV r0,r0,LSR#8
14910 ;
14920 .finish_dble
14930 ;
14940 STRB r0,[r2],#1
14950 MOV r0,r0,LSR#8
14960 ;
14970 .finish_byte
14980 ;
14990 STRB r0,[r2],#1
15000 ;
15010 .finish_implied
15020 ;
15030 LDMFD r13!,{pc}
15040 ;
15050 ;
15060 ;
15070 .class_BRK
15080 ;
15090 ADR r0,table_implieds-&B0 ; Make opcode
15100 LDRB r0,[r0,r3]
15110 ORR r3,r3,r0,LSL#24
15120 ;
15130 B finish_implied ; End with 0 argument bytes
15140 ;
15150 ;
15160 ;
15170 .table_implieds
15180 ;
15190 EQUB &00
15200 EQUB &18
15210 EQUB &D8
15220 EQUB &58
15230 EQUB &B8
15240 EQUB &CA
15250 EQUB &88
15260 EQUB &E8
15270 EQUB &C8
15280 EQUB &EA
15290 EQUB &48
15300 EQUB &08
15310 EQUB &68
15320 EQUB &28
15330 EQUB &40
15340 EQUB &60
15350 EQUB &38
15360 EQUB &F8
15370 EQUB &78
15380 EQUB &AA
15390 EQUB &A8
15400 EQUB &BA
15410 EQUB &8A
15420 EQUB &9A
15430 EQUB &98
15440 ;
15450 EQUB &3A
15460 EQUB &1A
15470 EQUB &DA
15480 EQUB &5A
15490 EQUB &FA
15500 EQUB &7A
15510 EQUB &CB
15520 EQUB &DB
15530 ;
15540 EQUB &8B
15550 EQUB &0B
15560 EQUB &4B
15570 EQUB &AB
15580 EQUB &2B
15590 EQUB &6B
15600 EQUB &5B
15610 ; dup ^
15620 EQUB &1B
15630 ; dup ^
15640 EQUB &7B
15650 ; dup ^
15660 EQUB &3B
15670 ; dup ^
15680 EQUB &9B
15690 EQUB &BB
15700 EQUB &EB
15710 ; dup ^
15720 EQUB &FB
15730 ;
15740 ALIGN
15750 ;
15760 ;
15770 ;
15780 .class_BPL
15790 ;
15800 TEQ r3,#&20 ; BRL ?
15810 BEQ class_BRL ; Yes
15820 ;
15830 ORR r3,r3,r3,LSL#28 ; Make opcode
15840 ;
15850 BL eval_expr_prev ; Absolute address
15860 ;
15870 MOV r1,#2<<30 OR 8 ; Error if resulting branch offset out of range
15880 BL error_if_offsetoutofrange
15890 ;
15900 B finish_byte ; End with 1 argument byte
15910 ;
15920 ;
15930 ;
15940 .class_BRL
15950 ;
15960 ORR r3,r3,#%10000010<<24 ; Make opcode
15970 ;
15980 BL eval_expr_prev ; Absolute address
15990 ;
16000 MOV r1,#3<<30 OR 16 ; Error if resulting branch offset out of range
16010 BL error_if_offsetoutofrange
16020 ;
16030 B finish_dble ; End with 2 argument bytes
16040 ;
16050 ;
16060 ;
16070 .class_JMP
16080 ;
16090 BL is_left_bracket ; Indirect indicated ?
16100 BEQ cljmp_ind ; Yes, handle as such
16110 ;
16120 BL eval_expr_prev_sized ; Absolute address (with size)
16130 ;
16140 MOV r1,#%11 ; Address size in bytes
16150 ANDS r1,r1,r3,LSR#16
16160 MOVEQ r1,#2
16170 ;
16180 CMP r1,#2 ; Which address size ?
16190 ;
16200 ORRLS r3,r3,#%01001100<<24 ; Make opcode
16210 ORRHI r3,r3,#%01011100<<24
16220 ;
16230 BLS finish_dble ; End with 2/3 argument bytes
16240 BHI finish_trip
16250 ;
16260 .cljmp_ind
16270 ;
16280 BL eval_expr_curr ; Past '('/'[', absolute address
16290
16300 TST r3,#1<<23
16310 BNE cljmp_noc
16320
16330 BL error_or_indirect_co_rb
16340
16350 TEQ r10,#ASC","
16360 BNE cljmp_noc
16370
16380 BL hop_skip_spaces
16390
16400 BL error_or_indirectx_X
16410
16420 BL hop_skip_spaces
16430
16440 BL error_or_indirectx_rb
16450
16460 ORR r3,r3,#%01111100<<24
16470
16480 B finish_hop_dble
16490
16500 .cljmp_noc
16510
16520 BL error_or_indirect_rb
16530
16540 TST r3,#1<<23
16550 ORREQ r3,r3,#%01101100<<24
16560 ORRNE r3,r3,#%11011100<<24
16570
16580 B finish_hop_dble
16590
16600
16610
16620 .class_JSR
16630
16640 TEQ r10,#ASC"("
16650 BEQ cljsr_ind
16660
16670 BL eval_expr_prev_sized
16680
16690 MOV r1,#%11
16700 ANDS r1,r1,r3,LSR#16
16710 MOVEQ r1,#2
16720
16730 CMP r1,#2
16740
16750 ORRLS r3,r3,#%00100000<<24
16760 ORRHI r3,r3,#%00100010<<24
16770
16780 BLS finish_dble
16790 BHI finish_trip
16800
16810 .cljsr_ind
16820
16830 BL eval_expr_curr
16840
16850 BL error_or_indirectx_co
16860
16870 BL hop_skip_spaces
16880
16890 BL error_or_indirectx_X
16900
16910 BL hop_skip_spaces
16920
16930 BL error_or_indirectx_rb
16940
16950 ORR r3,r3,#%11111100<<24
16960
16970 B finish_hop_dble
16980
16990
17000
17010 .class_ORA
17020
17030 TEQ r3,#&08
17040
17050 ORR r3,r3,r3,LSL#28
17060
17070 BEQ clora_sta
17080
17090 MOV r1,#%00001001
17100 BL try_immediate
17110
17120 .clora_sta
17130
17140 BL try_indirect
17150
17160 BL eval_expr_prev_sized
17170
17180 BL which_address_size
17190
17200 BHI clora_alo
17210 BEQ clora_abs
17220
17230 BL is_comma_Y
17240 BEQ clora_abs
17250
17260 BL is_comma_S
17270 BEQ clora_sre
17280
17290 MOV r1,#%00000101
17300 ORR r1,r1,#%0010101<<8
17310
17320 B do_zeropage_Xopt
17330
17340 .clora_sre
17350
17360 ORR r3,r3,#%00000011<<24
17370
17380 BL hop_skip_spaces
17390
17400 B finish_hop_byte
17410
17420 .clora_abs
17430
17440 MOV r1,#%00001101
17450 BL try_absolute
17460
17470 BL hop_skip_spaces
17480
17490 BL error_or_absolute_X_Y
17500
17510 TEQ r10,#ASC"X"
17520 TEQNE r10,#ASC"x"
17530 ORREQ r3,r3,#%00011101<<24
17540 ORRNE r3,r3,#%00011001<<24
17550
17560 B finish_hop_dble
17570
17580 .clora_alo
17590
17600 MOV r1,#%00001111
17610 ORR r1,r1,#%00011111<<8
17620
17630 B do_absolong_Xopt
17640
17650
17660
17670 .class_ASL
17680
17690 ORR r3,r3,r3,LSL#28
17700
17710 TEQ r10,#ASC"A"
17720 TEQNE r10,#ASC"a"
17730 BLEQ not_a_variable
17740 ORREQ r3,r3,#%00001010<<24
17750 BEQ finish_hop_implied
17760
17770 BL eval_expr_prev_sized
17780
17790 BL which_address_size
17800
17810 MOV r1,#%00000110
17820 ORR r1,r1,#%00010110<<8
17830 BLO do_zeropage_Xopt
17840 ORR r1,r1,#%00001000
17850 ORR r1,r1,#%00001000<<8
17860 BHS do_absolute_Xopt
17870
17880
17890
17900 .class_DEC
17910
17920 TEQ r3,#&5C
17930 MOVEQ r1,#%00111010
17940 MOVNE r1,#%00011010
17950
17960 TEQ r10,#ASC"A"
17970 TEQNE r10,#ASC"a"
17980 BLEQ not_a_variable
17990 ORREQ r3,r3,r1,LSL#24
18000 BEQ finish_hop_implied
18010
18020 ORR r3,r3,r3,LSL#28
18030
18040 BL eval_expr_prev_sized
18050
18060 BL which_address_size
18070
18080 MOV r1,#%00000110
18090 ORR r1,r1,#%00010110<<8
18100 BLO do_zeropage_Xopt
18110 ORR r1,r1,#%00001000
18120 ORR r1,r1,#%00001000<<8
18130 BHS do_absolute_Xopt
18140
18150
18160
18170 .class_CPX
18180
18190 ORR r3,r3,r3,LSL#28
18200
18210 MOV r1,#%00000000
18220 BL try_immediate
18230
18240 BL eval_expr_prev_sized
18250
18260 BL which_address_size
18270
18280 ORR r3,r3,#%00000100<<24
18290 BLO finish_byte
18300 ORR r3,r3,#%00001000<<24
18310 BHS finish_dble
18320
18330
18340
18350 .class_BIT
18360
18370 MOV r1,#%10001001
18380 BL try_immediate
18390
18400 BL eval_expr_prev_sized
18410
18420 BL which_address_size
18430
18440 MOV r1,#%00100100
18450 ORR r1,r1,#%00110100<<8
18460 BLO do_zeropage_Xopt
18470 ORR r1,r1,#%00001000
18480 ORR r1,r1,#%00001000<<8
18490 BHS do_absolute_Xopt
18500
18510
18520
18530 .class_LDX
18540
18550 AND r0,r3,#%00001111
18560 ORR r0,r0,#%10100000
18570 ORR r3,r3,r0,LSL#24
18580
18590 MOV r1,#%00000000
18600 BL try_immediate
18610
18620 BL eval_expr_prev_sized
18630
18640 BL which_address_size
18650
18660 MOV r1,#%00000100
18670 ORR r1,r1,#%00010100<<8
18680 BLO do_zeropage_XorYopt
18690 ORR r1,r1,#%00001000
18700 ORR r1,r1,#%00001000<<8
18710 BHS do_absolute_XorYopt
18720
18730
18740
18750 .class_STX
18760
18770 AND r0,r3,#%00001111
18780 ORR r0,r0,#%10000000
18790 ORR r3,r3,r0,LSL#24
18800
18810 BL eval_expr_prev_sized
18820
18830 BL which_address_size
18840
18850 ORRHS r3,r3,#%00001100<<24
18860 BHS finish_dble
18870
18880 MOV r1,#%00000100
18890 ORR r1,r1,#%00010100<<8
18900
18910 B do_zeropage_XorYopt
18920
18930
18940
18950 .class_TRB
18960
18970 CMP r3,#&AF
18980 BEQ class_COP
18990 CMP r3,#&AE
19000 BEQ class_PER
19010 CMP r3,#&AD
19020 BEQ class_PEI
19030 CMP r3,#&AC
19040 BEQ class_PEA
19050 CMP r3,#&AA
19060 BHS class_MVN
19070 CMP r3,#&A8
19080 BHS class_REP
19090 CMP r3,#&A6
19100 BHS class_CLR
19110 CMP r3,#&A4
19120 BHS class_BBR
19130 CMP r3,#&A2
19140 BHS class_RMB
19150
19160 TEQ r3,#&A0
19170 ORREQ r3,r3,#%00010000<<24
19180 ORRNE r3,r3,#%00000000<<24
19190
19200 BL eval_expr_prev_sized
19210
19220 BL which_address_size
19230
19240 ORR r3,r3,#%00000100<<24
19250 BLO finish_byte
19260 ORR r3,r3,#%00001000<<24
19270 BHS finish_dble
19280
19290
19300
19310 .class_RMB
19320
19330 TEQ r3,#&A2
19340 ORREQ r3,r3,#%00000111<<24
19350 ORRNE r3,r3,#%10000111<<24
19360
19370 BL mnem_bit_number
19380
19390 ORR r3,r3,r0,LSL#28
19400
19410 BL eval_expr_prev
19420
19430 BL error_if_zpaddroverflow
19440
19450 B finish_byte
19460
19470
19480
19490 .class_BBR
19500
19510 TEQ r3,#&A4
19520 ORREQ r3,r3,#%00001111<<24
19530 ORRNE r3,r3,#%10001111<<24
19540
19550 BL mnem_bit_number
19560
19570 ORR r3,r3,r0,LSL#28
19580
19590 BL eval_expr_prev
19600
19610 BL error_if_zpaddroverflow
19620
19630 STMFD r13!,{r0}
19640
19650 BL error_or_BBx_co
19660
19670 BL hop_skip_spaces
19680
19690 BL eval_expr_prev
19700
19710 MOV r1,#3<<30 OR 8
19720 BL error_if_offsetoutofrange
19730
19740 LDMFD r13!,{r1}
19750 ORR r0,r1,r0,LSL#8
19760
19770 B finish_dble
19780
19790
19800
19810 .class_CLR
19820
19830 BL eval_expr_prev_sized
19840
19850 BL which_address_size
19860
19870 MOV r1,#%01100100
19880 ORR r1,r1,#%01110100<<8
19890 BLO do_zeropage_Xopt
19900 MOV r1,#%10011100
19910 ORR r1,r1,#%10011110<<8
19920 BHS do_absolute_Xopt
19930
19940
19950
19960 .class_REP
19970
19980 TEQ r3,#&A8
19990 ORREQ r3,r3,#%11000010<<24
20000 ORRNE r3,r3,#%11100010<<24
20010
20020 BL error_or_immediate_ha
20030
20040 BL eval_expr_curr
20050
20060 BL error_if_constoverflowB
20070
20080 B finish_byte
20090
20100
20110
20120 .class_MVN
20130
20140 TEQ r3,#&AA
20150 ORREQ r3,r3,#%01010100<<24
20160 ORRNE r3,r3,#%01000100<<24
20170
20180 BL eval_expr_prev
20190
20200 BL error_if_banknroverflow
20210
20220 STMFD r13!,{r0}
20230
20240 BL error_or_MVx_co
20250
20260 BL hop_skip_spaces
20270
20280 BL eval_expr_prev
20290
20300 BL error_if_banknroverflow
20310
20320 LDMFD r13!,{r1}
20330 ORR r0,r0,r1,LSL#8
20340
20350 B finish_dble
20360
20370
20380
20390 .class_PEA
20400
20410 ORR r3,r3,#%11110100<<24
20420
20430 BL eval_expr_prev
20440
20450 B finish_dble
20460
20470
20480
20490 .class_PEI
20500
20510 ORR r3,r3,#%11010100<<24
20520
20530 BL error_or_indirect_ls
20540
20550 BL hop_skip_spaces
20560
20570 BL eval_expr_prev
20580
20590 BL error_if_zpaddroverflow
20600
20610 BL error_or_indirect_rb
20620
20630 B finish_hop_byte
20640
20650
20660
20670 .class_PER
20680
20690 ORR r3,r3,#%01100010<<24
20700
20710 BL eval_expr_prev
20720
20730 MOV r1,#3<<30 OR 16
20740 BL error_if_offsetoutofrange
20750
20760 B finish_dble
20770
20780
20790
20800 .class_COP
20810
20820 ORR r3,r3,#%00000010<<24
20830
20840 BL eval_expr_prev
20850
20860 BL error_if_codebyteoverflow
20870
20880 B finish_byte
20890
20900
20910
20920 ]
20930
20940 NEXT
20950
20960 Size% = P% - Data%
20970
20980 ENDPROC
20990
21000
21010
21020 DEFFNerror_message(asm_err%, error_message$)
21030
21040 [OPT `P
21050
21060 EQUD asm_err%
21070 EQUS error_message$
21080 EQUB 0
21090
21100 ALIGN
21110
21120 ]
21130
21140 = 0
21150
21160
21170
21180 DEFFNgenerate_error_message(asm_err%, error_message$)
21190
21200 [OPT `P
21210
21220 ADR r0,P%+2*4
21230
21240 B error_generate
21250
21260 FNerror_message(asm_err%, error_message$)
21270
21280 ]
21290
21300 = 0
21310
21320
21330
21340 DEFPROCdoing_105
21350
21360
21370
21380
21390 Patch_Off(1) = &B994:
21400 Patch_Off(2) = &A044:
21410 Patch_Off(3) = &A0E8:
21420 Patch_Off(4) = &9FE8:
21430 Patch_Off(5) = &A87C:
21440
21450 Patch_Off(50) = &A668
21460 Patch_Off(51) = &AA18
21470 Patch_Off(52) = &A040:
21480
21490 basoff_p% = -&C0
21500 basoff_opt% = -&26
21510
21520 Which$ = "BASIC105"
21530
21540 ENDPROC
21550
21560
21570
21580 DEFPROCdoing_116
21590
21600
21610
21620 Patch_Off(1) = &BAD4
21630 Patch_Off(2) = &A184
21640 Patch_Off(3) = &A228
21650 Patch_Off(4) = &A128
21660 Patch_Off(5) = &A9BC
21670
21680 Patch_Off(50) = &A7A8
21690 Patch_Off(51) = &AB58
21700 Patch_Off(52) = &A180
21710
21720 basoff_p% = -&C0
21730 basoff_opt% = -&1E
21740
21750 Which$ = "BASIC116"
21760
21770 ENDPROC
21780
21790
21800
21810 DEFPROCdoing_119
21820
21830
21840
21850 Patch_Off(1) = &C588
21860 Patch_Off(2) = &A198
21870 Patch_Off(3) = &A35C
21880 Patch_Off(4) = &A14C
21890 Patch_Off(5) = &B204
21900
21910 Patch_Off(50) = &AFF0
21920 Patch_Off(51) = &B498
21930 Patch_Off(52) = &A194
21940
21950 basoff_p% = -&C0
21960 basoff_opt% = -&1E
21970
21980 Which$ = "BASIC119"
21990
22000 ENDPROC
22010
22020
22030
22040 DEFPROCdoing_120
22050
22060
22070
22080 Patch_Off(1) = &C5B8
22090 Patch_Off(2) = &A1CC
22100 Patch_Off(3) = &A390
22110 Patch_Off(4) = &A180
22120 Patch_Off(5) = &B238
22130
22140 Patch_Off(50) = &B024
22150 Patch_Off(51) = &B4CC
22160 Patch_Off(52) = &A1C8
22170
22180 basoff_p% = -&C0
22190 basoff_opt% = -&1E
22200
22210 Which$ = "BASIC120"
22220
22230 ENDPROC
22240
22250
22260
22270 DEFPROCdoing_120x
22280
22290
22300
22310 Patch_Off(1) = &C5D4
22320 Patch_Off(2) = &A1E0
22330 Patch_Off(3) = &A3A4
22340 Patch_Off(4) = &A194
22350 Patch_Off(5) = &B24C
22360
22370 Patch_Off(50) = &B038
22380 Patch_Off(51) = &B4E0
22390 Patch_Off(52) = &A1DC
22400
22410 basoff_p% = -&C0
22420 basoff_opt% = -&1E
22430
22440 Which$ = "BASIC120X"
22450
22460 ENDPROC
22470
22480
22490
22500 DEFPROCdoing_128
22510
22520
22530
22540 Patch_Off(1) = &C678
22550 Patch_Off(2) = &A244
22560 Patch_Off(3) = &A408
22570 Patch_Off(4) = &A1F8
22580 Patch_Off(5) = &B300
22590
22600 Patch_Off(50) = &B0EC
22610 Patch_Off(51) = &B594
22620 Patch_Off(52) = &A240
22630
22640 basoff_p% = -&C0
22650 basoff_opt% = -&1A
22660
22670 Which$ = "BASIC128"
22680
22690 ENDPROC
22700
22710
22720
22730 DEFPROCdoing_129
22740
22750
22760
22770 Patch_Off(1) = &C678
22780 Patch_Off(2) = &A244
22790 Patch_Off(3) = &A408
22800 Patch_Off(4) = &A1F8
22810 Patch_Off(5) = &B300
22820
22830 Patch_Off(50) = &B0EC
22840 Patch_Off(51) = &B594
22850 Patch_Off(52) = &A240
22860
22870 basoff_p% = -&C0
22880 basoff_opt% = -&1A
22890
22900 Which$ = "BASIC129"
22910
22920 ENDPROC
22930
22940
22950
22960 DEFPROCprime(code%, old%)
22970
22980 PROCcheck(code%, old%, 0)
22990
23000 ENDPROC
23010
23020
23030
23040 DEFPROCprim4(code%, old%)
23050
23060 PROCcheck(code%, old%, 4)
23070
23080 ENDPROC
23090
23100
23110
23120 DEFPROCcheck(code%, old%, choff%)
23130
23140 P% = Data% + Patch_Off(code%)
23150
23160 IF `P = %0000 ELSE ENDPROC
23170
23180 IF P%!choff% <> old% THEN ERROR 66, "Old doesn't match (code " + STR$(code%) + ")"
23190
23200 ENDPROC