10 REM >Basic6502
   20 REM
   30 REM
   40 REM Patches BASIC V module to assemble 6502/65C02/65C816 code
   50 REM
   60 REM
   70 REM Version 1.30 (15 Dec 2009)
   80 REM by John Kortink, (c) Zeridajh 2005..2009
   90 REM
  100 REM Version 1.30-jgh (21 Feb 2010)
  110 REM J.G.Harston - Also patches BASIC v1.05, corrected assembler error numbers
  120 REM
  130 REM
  140 REM
  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 :REM JGH
  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 REM
 2130 REM Change module name
 2140 REM
 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:REM "6502"
 2200         ENDIF
 2210     ENDIF
 2220 NEXT A%
 2230 
 2240 FOR `P = %0000 TO %0010 STEP %0010
 2250   
 2260   REM
 2270   REM On TEXTLOAD, RENUMBER 1,1 instead of 10,10
 2280   REM
 2290   
 2300   PROCprime(1, &E3A0400A)
 2310   
 2320   [OPT `P
 2330   ;
 2340    MOV r4,#1
 2350    MOV r5,#1
 2360   ;
 2370   ]
 2380   
 2390   REM
 2400   REM 6502 assembler
 2410   REM
 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 ; change to match patch outside Í
 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   REM
 3050   REM Other code points
 3060   REM
 3070   
 3080   PROCprim4(50, &E51830C0)
 3090   PROCprime(51, &E92D4002)
 3100   PROCprime(52, &E1A00400)
 3110   
 3120   REM
 3130   REM Extra code
 3140   REM
 3150   
 3160   P% = Data% + Size%
 3170   
 3180   [OPT `P
 3190   
 3200   
 3210   
 3220   .patch_6502_0
 3230   ;
 3240    TEQ r10,#token_OR                  ; 'Expand' tokenised mnemonics
 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         ; Error if not in range
13140   ;
13150    TST r3,#1<<23                      ; Square bracket ?
13160    BNE trind_plory                    ; Yes (no [Zp,X])
13170   ;
13180    BL error_or_indirect_co_rb         ; Match ',' or ')'/']'
13190   ;
13200    TEQ r10,#ASC","                    ; Was it the ',' ?
13210    BNE trind_plory                    ; No (not (Zp,X))
13220   ;
13230    BL hop_skip_spaces                 ; Skip ',', skip spaces
13240   ;
13250    BL error_or_indirect_X_S           ; Match 'X' or 'S'
13260   ;
13270    TEQ r10,#ASC"S"                    ; Following is 'S' ?
13280    TEQNE r10,#ASC"s"
13290    BEQ trind_strel                    ; Yes (is (Zp,S),Y)
13300   ;
13310    ORR r3,r3,#%00000001<<24           ; Finish opcode
13320   ;
13330    BL hop_skip_spaces                 ; Skip 'X', skip spaces
13340   ;
13350    BL error_or_indirectx_rb           ; Match ')'/']'
13360   ;
13370    B finish_hop_byte                  ; Skip ')'/']', end with 1 argument byte
13380   ;
13390   .trind_plory
13400   ;
13410    BL error_or_indirect_rb            ; Match ')'/']'
13420   ;
13430    TST r3,#1<<23                      ; Finish opcode (for ,Y)
13440    ORREQ r3,r3,#%00010001<<24
13450    ORRNE r3,r3,#%00010111<<24
13460   ;
13470    BL hop_skip_spaces                 ; Skip ')'/']', skip spaces
13480   ;
13490    TEQ r10,#ASC","                    ; Following is ',' ?
13500    BNE trind_plain                    ; No (not (Zp),Y)
13510   ;
13520    BL hop_skip_spaces                 ; Skip ',', skip spaces
13530   ;
13540    BL error_or_indirecty_Y            ; Match 'Y'
13550   ;
13560    B finish_hop_byte                  ; Skip 'Y', end with 1 argument byte
13570   ;
13580   .trind_plain
13590   ;
13600    TST r3,#1<<23                      ; Finish opcode (for plain)
13610    EOREQ r3,r3,#%00000011<<24
13620    EORNE r3,r3,#%00010000<<24
13630   ;
13640    B finish_byte                      ; End with 1 argument byte
13650   ;
13660   .trind_strel
13670   ;
13680    ORR r3,r3,#%00010011<<24           ; Finish opcode
13690   ;
13700    BL hop_skip_spaces                 ; Skip 'S', skip spaces
13710   ;
13720    BL error_or_indirects_rb           ; Match ')'/']'
13730   ;
13740    BL hop_skip_spaces                 ; Skip ')'/']', skip spaces
13750   ;
13760    BL error_or_indirects_co           ; Match ','
13770   ;
13780    BL hop_skip_spaces                 ; Skip ',', skip spaces
13790   ;
13800    BL error_or_indirects_Y            ; Match 'Y'
13810   ;
13820    B finish_hop_byte                  ; Skip 'Y', end with 1 argument byte
13830   ;
13840   ;
13850   ;
13860   .do_zeropage_Xopt
13870   ;
13880    BL try_zeropage                    ; Try (plain) zero-page mode
13890   ;
13900    BL hop_skip_spaces                 ; Skip ',', skip spaces
13910   ;
13920    BL error_or_zeropagex_X            ; Match 'X'
13930   ;
13940    MOV r14,r1,LSR#8                   ; Finish opcode
13950    ORR r3,r3,r14,LSL#24
13960   ;
13970    B finish_hop_byte                  ; Skip 'X', end with 1 argument byte
13980   ;
13990   ;
14000   ;
14010   .do_zeropage_XorYopt
14020   ;
14030    BL try_zeropage                    ; Try (plain) zero-page mode
14040   ;
14050    BL hop_skip_spaces                 ; Skip ',', skip spaces
14060   ;
14070    TST r3,#%1111                      ; Match 'X' or 'Y'
14080    BLEQ error_or_zeropagex_X
14090    BLNE error_or_zeropagey_Y
14100   ;
14110    MOV r14,r1,LSR#8                   ; Finish opcode
14120    ORR r3,r3,r14,LSL#24
14130   ;
14140    B finish_hop_byte                  ; Skip 'X' or 'Y', end with 1 argument byte
14150   ;
14160   ;
14170   ;
14180   .do_absolute_Xopt
14190   ;
14200    BL try_absolute                    ; Try (plain) absolute mode
14210   ;
14220    BL hop_skip_spaces                 ; Skip ',', skip spaces
14230   ;
14240    BL error_or_absolutex_X            ; Match 'X'
14250   ;
14260    MOV r14,r1,LSR#8                   ; Finish opcode
14270    ORR r3,r3,r14,LSL#24
14280   ;
14290    B finish_hop_dble                  ; Skip 'X', end with 2 argument bytes
14300   ;
14310   ;
14320   ;
14330   .do_absolute_XorYopt
14340   ;
14350    BL try_absolute                    ; Try (plain) absolute mode
14360   ;
14370    BL hop_skip_spaces                 ; Skip ',', skip spaces
14380   ;
14390    TST r3,#%1111                      ; Match 'X' or 'Y'
14400    BLEQ error_or_absolutex_X
14410    BLNE error_or_absolutey_Y
14420   ;
14430    MOV r14,r1,LSR#8                   ; Finish opcode
14440    ORR r3,r3,r14,LSL#24
14450   ;
14460    B finish_hop_dble                  ; Skip 'X' or 'Y', end with 2 argument bytes
14470   ;
14480   ;
14490   ;
14500   .do_absolong_Xopt
14510   ;
14520    BL try_absolong                    ; Try (plain) absolute long mode
14530   ;
14540    BL hop_skip_spaces                 ; Skip ',', skip spaces
14550   ;
14560    BL error_or_absolongx_X            ; Match 'X'
14570   ;
14580    MOV r14,r1,LSR#8                   ; Finish opcode
14590    ORR r3,r3,r14,LSL#24
14600   ;
14610    B finish_hop_trip                  ; Skip 'X', end with 3 argument bytes
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                      ; Square bracket ?
16310    BNE cljmp_noc                      ; Yes (no '[Abs,X]')
16320   ;
16330    BL error_or_indirect_co_rb         ; Match ',' or ')'/']'
16340   ;
16350    TEQ r10,#ASC","                    ; Was it the ',' ?
16360    BNE cljmp_noc                      ; No, (not (Abs,X))
16370   ;
16380    BL hop_skip_spaces                 ; Skip ',', skip spaces
16390   ;
16400    BL error_or_indirectx_X            ; Match 'X'
16410   ;
16420    BL hop_skip_spaces                 ; Skip 'X', skip spaces
16430   ;
16440    BL error_or_indirectx_rb           ; Match ')'/']'
16450   ;
16460    ORR r3,r3,#%01111100<<24           ; Make opcode
16470   ;
16480    B finish_hop_dble                  ; Skip ')'/']', end with 2 argument bytes
16490   ;
16500   .cljmp_noc
16510   ;
16520    BL error_or_indirect_rb            ; Match ')'/']'
16530   ;
16540    TST r3,#1<<23                      ; Make opcode
16550    ORREQ r3,r3,#%01101100<<24
16560    ORRNE r3,r3,#%11011100<<24
16570   ;
16580    B finish_hop_dble                  ; Skip ')'/']', end with 2 argument bytes
16590   ;
16600   ;
16610   ;
16620   .class_JSR
16630   ;
16640    TEQ r10,#ASC"("                    ; Indirect indicated ?
16650    BEQ cljsr_ind                      ; Yes, handle as such
16660   ;
16670    BL eval_expr_prev_sized            ; Absolute address (with size)
16680   ;
16690    MOV r1,#%11                        ; Address size in bytes
16700    ANDS r1,r1,r3,LSR#16
16710    MOVEQ r1,#2
16720   ;
16730    CMP r1,#2                          ; Which address size ?
16740   ;
16750    ORRLS r3,r3,#%00100000<<24         ; Make opcode
16760    ORRHI r3,r3,#%00100010<<24
16770   ;
16780    BLS finish_dble                    ; End with 2/3 argument bytes
16790    BHI finish_trip
16800   ;
16810   .cljsr_ind
16820   ;
16830    BL eval_expr_curr                  ; Past '(', absolute address
16840   ;
16850    BL error_or_indirectx_co           ; Match ','
16860   ;
16870    BL hop_skip_spaces                 ; Skip ',', skip spaces
16880   ;
16890    BL error_or_indirectx_X            ; Match 'X'
16900   ;
16910    BL hop_skip_spaces                 ; Skip 'X', skip spaces
16920   ;
16930    BL error_or_indirectx_rb           ; Match ')'
16940   ;
16950    ORR r3,r3,#%11111100<<24           ; Make opcode
16960   ;
16970    B finish_hop_dble                  ; Skip ')', end with 2 argument bytes
16980   ;
16990   ;
17000   ;
17010   .class_ORA
17020   ;
17030    TEQ r3,#&08                        ; STA ?
17040   ;
17050    ORR r3,r3,r3,LSL#28                ; Start opcode
17060   ;
17070    BEQ clora_sta                      ; STA has no immediate mode
17080   ;
17090    MOV r1,#%00001001                  ; Try immediate mode
17100    BL try_immediate
17110   ;
17120   .clora_sta
17130   ;
17140    BL try_indirect                    ; Try indirect mode
17150   ;
17160    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
17170   ;
17180    BL which_address_size              ; Which address size ?
17190   ;
17200    BHI clora_alo                      ; 3-byte
17210    BEQ clora_abs                      ; 2-byte
17220   ;
17230    BL is_comma_Y                      ; Zero-page,Y (unavailable) ?
17240    BEQ clora_abs                      ; Yes, turn it into absolute,Y
17250   ;
17260    BL is_comma_S                      ; Stack-relative,S ?
17270    BEQ clora_sre                      ; Yes, special handling
17280   ;
17290    MOV r1,#%00000101                  ; Handle zero-page(,X) mode
17300    ORR r1,r1,#%0010101<<8
17310   ;
17320    B do_zeropage_Xopt
17330   ;
17340   .clora_sre
17350   ;
17360    ORR r3,r3,#%00000011<<24           ; Finish opcode
17370   ;
17380    BL hop_skip_spaces                 ; Skip ',', skip spaces
17390   ;
17400    B finish_hop_byte                  ; Skip 'S', end with 1 argument byte
17410   ;
17420   .clora_abs
17430   ;
17440    MOV r1,#%00001101                  ; Try (plain) absolute mode
17450    BL try_absolute
17460   ;
17470    BL hop_skip_spaces                 ; Skip ',', skip spaces
17480   ;
17490    BL error_or_absolute_X_Y           ; Match 'X' or 'Y'
17500   ;
17510    TEQ r10,#ASC"X"                    ; Finish opcode
17520    TEQNE r10,#ASC"x"
17530    ORREQ r3,r3,#%00011101<<24
17540    ORRNE r3,r3,#%00011001<<24
17550   ;
17560    B finish_hop_dble                  ; Skip 'X' or 'Y', end with 2 argument bytes
17570   ;
17580   .clora_alo
17590   ;
17600    MOV r1,#%00001111                  ; Handle absolute long(,X) mode
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                ; Start opcode
17700   ;
17710    TEQ r10,#ASC"A"                    ; Accu ?
17720    TEQNE r10,#ASC"a"
17730    BLEQ not_a_variable
17740    ORREQ r3,r3,#%00001010<<24         ; Yes, finish opcode
17750    BEQ finish_hop_implied             ; And skip 'A', and end with 0 argument bytes
17760   ;
17770    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
17780   ;
17790    BL which_address_size              ; Which address size ?
17800   ;
17810    MOV r1,#%00000110                  ; Handle zero-page/absolute(,X/Y) mode
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                        ; Opcode for DEA/INA
17930    MOVEQ r1,#%00111010
17940    MOVNE r1,#%00011010
17950   ;
17960    TEQ r10,#ASC"A"                    ; Accu ?
17970    TEQNE r10,#ASC"a"
17980    BLEQ not_a_variable
17990    ORREQ r3,r3,r1,LSL#24              ; Yes, finish opcode
18000    BEQ finish_hop_implied             ; And skip 'A', and end with 0 argument bytes
18010   ;
18020    ORR r3,r3,r3,LSL#28                ; Start opcode
18030   ;
18040    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
18050   ;
18060    BL which_address_size              ; Which address size ?
18070   ;
18080    MOV r1,#%00000110                  ; Handle zero-page/absolute(,X/Y) mode
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                ; Start opcode
18200   ;
18210    MOV r1,#%00000000                  ; Try immediate mode
18220    BL try_immediate
18230   ;
18240    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
18250   ;
18260    BL which_address_size              ; Which address size ?
18270   ;
18280    ORR r3,r3,#%00000100<<24           ; Handle zero-page/absolute mode
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                  ; Try immediate mode
18380    BL try_immediate
18390   ;
18400    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
18410   ;
18420    BL which_address_size              ; Which address size ?
18430   ;
18440    MOV r1,#%00100100                  ; Handle zero-page/absolute(,X/Y) mode
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               ; Start opcode
18560    ORR r0,r0,#%10100000
18570    ORR r3,r3,r0,LSL#24
18580   ;
18590    MOV r1,#%00000000                  ; Try immediate mode
18600    BL try_immediate
18610   ;
18620    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
18630   ;
18640    BL which_address_size              ; Which address size ?
18650   ;
18660    MOV r1,#%00000100                  ; Handle zero-page/absolute(,X/Y) mode
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               ; Start opcode
18780    ORR r0,r0,#%10000000
18790    ORR r3,r3,r0,LSL#24
18800   ;
18810    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
18820   ;
18830    BL which_address_size              ; Which address size ?
18840   ;
18850    ORRHS r3,r3,#%00001100<<24         ; Absolute, finish opcode
18860    BHS finish_dble                    ; And end with 2 argument bytes
18870   ;
18880    MOV r1,#%00000100                  ; Handle zero-page(,X/Y) mode
18890    ORR r1,r1,#%00010100<<8
18900   ;
18910    B do_zeropage_XorYopt
18920   ;
18930   ;
18940   ;
18950   .class_TRB
18960   ;
18970    CMP r3,#&AF                        ; Dispatch instn code
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                        ; Start opcode
19170    ORREQ r3,r3,#%00010000<<24
19180    ORRNE r3,r3,#%00000000<<24
19190   ;
19200    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
19210   ;
19220    BL which_address_size              ; Which address size ?
19230   ;
19240    ORR r3,r3,#%00000100<<24           ; Handle zero-page/absolute mode
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                        ; Start opcode
19340    ORREQ r3,r3,#%00000111<<24
19350    ORRNE r3,r3,#%10000111<<24
19360   ;
19370    BL mnem_bit_number                 ; Check for bit number
19380   ;
19390    ORR r3,r3,r0,LSL#28                ; Add bit number to opcode
19400   ;
19410    BL eval_expr_prev                  ; Zero-page address
19420   ;
19430    BL error_if_zpaddroverflow         ; Error if not in range
19440   ;
19450    B finish_byte                      ; End with 1 argument byte
19460   ;
19470   ;
19480   ;
19490   .class_BBR
19500   ;
19510    TEQ r3,#&A4                        ; Start opcode
19520    ORREQ r3,r3,#%00001111<<24
19530    ORRNE r3,r3,#%10001111<<24
19540   ;
19550    BL mnem_bit_number                 ; Check for bit number
19560   ;
19570    ORR r3,r3,r0,LSL#28                ; Add bit number to opcode
19580   ;
19590    BL eval_expr_prev                  ; Zero-page address
19600   ;
19610    BL error_if_zpaddroverflow         ; Error if not in range
19620   ;
19630    STMFD r13!,{r0}                    ; Remember zero-page address
19640   ;
19650    BL error_or_BBx_co                 ; Match ','
19660   ;
19670    BL hop_skip_spaces                 ; Skip ',', skip spaces
19680   ;
19690    BL eval_expr_prev                  ; Absolute address
19700   ;
19710    MOV r1,#3<<30 OR 8                 ; Error if resulting branch offset out of range
19720    BL error_if_offsetoutofrange
19730   ;
19740    LDMFD r13!,{r1}                    ; Merge argument bytes
19750    ORR r0,r1,r0,LSL#8
19760   ;
19770    B finish_dble                      ; End with 2 argument bytes
19780   ;
19790   ;
19800   ;
19810   .class_CLR
19820   ;
19830    BL eval_expr_prev_sized            ; Zero-page or absolute address (with size)
19840   ;
19850    BL which_address_size              ; Which address size ?
19860   ;
19870    MOV r1,#%01100100                  ; Handle zero-page/absolute(,X/Y) mode
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                        ; Make opcode
19990    ORREQ r3,r3,#%11000010<<24
20000    ORRNE r3,r3,#%11100010<<24
20010   ;
20020    BL error_or_immediate_ha           ; Match '#'
20030   ;
20040    BL eval_expr_curr                  ; Past '#', immediate value
20050   ;
20060    BL error_if_constoverflowB         ; Error if not in range
20070   ;
20080    B finish_byte                      ; End with 1 argument byte
20090   ;
20100   ;
20110   ;
20120   .class_MVN
20130   ;
20140    TEQ r3,#&AA                        ; Make opcode
20150    ORREQ r3,r3,#%01010100<<24
20160    ORRNE r3,r3,#%01000100<<24
20170   ;
20180    BL eval_expr_prev                  ; Bank number (src)
20190   ;
20200    BL error_if_banknroverflow         ; Error if not in range
20210   ;
20220    STMFD r13!,{r0}                    ; Remember bank number
20230   ;
20240    BL error_or_MVx_co                 ; Match ','
20250   ;
20260    BL hop_skip_spaces                 ; Skip ',', skip spaces
20270   ;
20280    BL eval_expr_prev                  ; Bank number (dst)
20290   ;
20300    BL error_if_banknroverflow         ; Error if not in range
20310   ;
20320    LDMFD r13!,{r1}                    ; Merge argument bytes
20330    ORR r0,r0,r1,LSL#8
20340   ;
20350    B finish_dble                      ; End with 2 argument bytes
20360   ;
20370   ;
20380   ;
20390   .class_PEA
20400   ;
20410    ORR r3,r3,#%11110100<<24           ; Make opcode
20420   ;
20430    BL eval_expr_prev                  ; Absolute address
20440   ;
20450    B finish_dble                      ; End with 2 argument bytes
20460   ;
20470   ;
20480   ;
20490   .class_PEI
20500   ;
20510    ORR r3,r3,#%11010100<<24           ; Make opcode
20520   ;
20530    BL error_or_indirect_ls            ; Match '('
20540   ;
20550    BL hop_skip_spaces                 ; Skip '(', skip spaces
20560   ;
20570    BL eval_expr_prev                  ; Zero-page address
20580   ;
20590    BL error_if_zpaddroverflow         ; Error if not in range
20600   ;
20610    BL error_or_indirect_rb            ; Match ')'
20620   ;
20630    B finish_hop_byte                  ; Skip ')', end with 1 argument byte
20640   ;
20650   ;
20660   ;
20670   .class_PER
20680   ;
20690    ORR r3,r3,#%01100010<<24           ; Make opcode
20700   ;
20710    BL eval_expr_prev                  ; Absolute address
20720   ;
20730    MOV r1,#3<<30 OR 16                ; Error if resulting branch offset out of range
20740    BL error_if_offsetoutofrange
20750   ;
20760    B finish_dble                      ; End with 2 argument bytes
20770   ;
20780   ;
20790   ;
20800   .class_COP
20810   ;
20820    ORR r3,r3,#%00000010<<24           ; Make opcode
20830   ;
20840    BL eval_expr_prev                  ; Code byte
20850   ;
20860    BL error_if_codebyteoverflow       ; Error if not in range
20870   ;
20880    B finish_byte                      ; End with 1 argument 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 REM RISC OS 3.1x BASIC 1.05
21370 REM Address data for v1.05 added by J.G.Harston
21380 
21390 Patch_Off(1) = &B994:REM TEXTLOAD renumber 1,1
21400 Patch_Off(2) = &A044:REM Point to mnemonic table
21410 Patch_Off(3) = &A0E8:REM B patch_6502_2
21420 Patch_Off(4) = &9FE8:REM B patch_6502_0
21430 Patch_Off(5) = &A87C:REM AND R0,R0,#15; mask OPT
21440 
21450 Patch_Off(50) = &A668
21460 Patch_Off(51) = &AA18
21470 Patch_Off(52) = &A040:REM Search mnemonic table
21480 
21490 basoff_p%   = -&C0
21500 basoff_opt% = -&26
21510 
21520 Which$ = "BASIC105"
21530 
21540 ENDPROC
21550 
21560 
21570 
21580 DEFPROCdoing_116
21590 
21600 REM RISC OS 3.70 BASIC 1.16
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 REM RISC OS 4.02 BASIC 1.19
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 REM RISC OS 4.03 BASIC 1.20
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 REM RISC OS 4.02 'mystery' BASIC 1.20
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 REM RISC OS 4.37 BASIC 1.28
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 REM RISC OS 4.39 BASIC 1.29
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