>Basic6502   (? Patches BASIC V module to assemble 6502/65C02/65C816 code 2 < F Version 1.30 (15 Dec 2009) P. by John Kortink, (c) Zeridajh 2005..2009 Z d$ Version 1.30-jgh (21 Feb 2010) nO J.G.Harston - Also patches BASIC v1.05, corrected assembler error numbers x    ! "Error: ";$;" at ";:   Patch_Off(100)  Data_Size% = 256 * 1024   Data% Data_Size% + 4  Source% = which_source  Ȏ Source%   105 : doing_105 " 116 : doing_116 , 119 : doing_119 6 120 : doing_120 @ 920 : doing_120x J 128 : doing_128 T 129 : doing_129 ^ h r |patch_code  " "Total size ";Size%;" bytes"   out_file$ = "6502_" + Which$  <ș "OS_File", 10, out_file$, &FFA,, Data%, Data% + Size%   '"Saved to ";out_file$'      ݤwhich_source   choice% & source% 0 : D N "Possible sources:"' X "1. Local RISC OS ROM" b! "2. RISC OS ROM image file" l" "3. BASIC module image file" v  '"Your source: ";  ș "OS_Byte", 15, 0  8 choice% = - ("0"): choice% >= 1 choice% <= 3   ;choice%'  - A% = Data% Data% + Data_Size% - 1 4   !A% = 0     Ȏ choice%    1 : src_local * 2 : src_riscos 4 3 : src_module > H R \source% = 0 f pG source% = 0 test_module(52308, &70AD) source% = 105 : JGH z@ source% = 0 test_module(52628, &5EF2) source% = 116 @ source% = 0 test_module(55392, &58E4) source% = 119 @ source% = 0 test_module(55440, &71CA) source% = 120 @ source% = 0 test_module(55532, &45DF) source% = 920 @ source% = 0 test_module(55632, &EB77) source% = 128 @ source% = 0 test_module(55636, &8A16) source% = 129  7 source% = 0 64, "BASIC module not recognized"   = source%    src_local   base%  $+ș "OS_Module", 18, "Basic" ,,, base% . 8Size% = base%!-4 - 4 B L A% = 0 Size% - 1 4 V ` Data%!A% = base%!A% j t ~     src_riscos   in  riscos%  file_name$   "Filename: " file_name$'  "Size% = file_size(file_name$)   in = (file_name$)  (riscos% = 0 2  1 214, "File not found"   = size%    %ݤtest_riscos(in, offset%, word%) & 0*ș "OS_GBPB", 3, in, Data%, 4, offset% : D= (!Data% = word%) N X b l,ݤtest_module(actual_size%, actual_crc%) v  crc%  9ș "OS_CRC", 0, Data%, Data% + actual_size%, 1 crc%   crc% <> actual_crc% =  Size% = actual_size%  =    patch_code   token_AND = &80 token_EOR = &82  token_OR = &84 * 4Size% = (Size% + 3) 3 > H R Change module name \ f p A%=Data% Data%+Size%-1 z" !A%=&49534142 A%?4=&43 C A%!-4<>&20434242 A%?5<>"$" A%?5<>"T" A%?5<>"." ! A%!1=&32303536: "6502"    A%   `P = %0000 %0010 %0010   0 On TEXTLOAD, RENUMBER 1,1 instead of 10,10   prime(1, &E3A0400A)   [OPT `P ; $ MOV r4,#1 . MOV r5,#1 8; B] L V ` 6502 assembler j t ~K Source% = 105 Source% = 116 word% = &E28F1014 word% = &E28F103C prime(2, word%)  [OPT `P ;  BL patch_6502_1 ; ]  prim4(3, &E202140F)  [OPT `P ;  B patch_6502_2 ; ]  (# Source%=105 Source% = 116 2 < Source%=105 Dest%=&A864 F Source%=116 Dest%=&A9A4 P ZP% -= 6 * 4 d n [OPT `P x; # SUB r2,r2,#&F0000000-&C0000000  BCS Data%+Dest%  ADD r11,r11,#2  CMP r2,#&F0000000  BCS P% - 4 * 4 ; ]  prime(5, &E200000F)  [OPT `P ; 6 r0,r0,#%11111 ; change to match patch outside ; ]  " , 6prime(5, &E200001F) @ J [OPT `P T; ^ r0,r0,#%11111111 h; r] | K Source% = 105 Source% = 116 word% = &E35A0080 word% = &E35A007F prime(4, word%)  [OPT `P ;  B patch_6502_0 ; ]    Other code points   prim4(50, &E51830C0) prime(51, &E92D4002) prime(52, &E1A00400) & 0 : Extra code D N XP% = Data% + Size% b l [OPT `P v   .patch_6502_0 ; F TEQ r10,#token_OR ; 'Expand' tokenised mnemonics  LDREQB r1,[r11]  BICEQ r1,r1,#&20  TEQEQ r1,#"A"  SUBEQ r11,r11,#1  LDREQ r0,mnem_ORA  BEQ Data%+Patch_Off(52) ;  TEQ r10,#token_AND  SUBEQ r11,r11,#2  LDREQ r0,mnem_AND  BEQ Data%+Patch_Off(52) ; * TEQ r10,#token_EOR 4 SUBEQ r11,r11,#2 > LDREQ r0,mnem_EOR H BEQ Data%+Patch_Off(52) R; \? BIC r0,r10,#&20 ; Build 'mnemonic word' f; p LDRB r1,[r11,#0] z BIC r1,r1,#&20  R r0,r0,r1,LSL#8 ;  LDRB r1,[r11,#1]  BIC r1,r1,#&20  R r0,r0,r1,LSL#16 ;  B Data%+Patch_Off(52) ; .mnem_ORA ;  EQUS "ORA " ; .mnem_AND ;  EQUS "AND " ; $ .mnem_EOR .; 8 EQUS "EOR " B L V `.patch_6502_1 j; tU ADR r1,table_mnem_65xxx ; Use 65xxx mnemonic table instead of ARM one ~; 0 MOV pc,r14 ; Return    .table_mnem_65xxx ;  EQUS "ORA":EQUB &00  EQUS "AND":EQUB &02  EQUS "EOR":EQUB &04  EQUS "ADC":EQUB &06  EQUS "STA":EQUB &08  EQUS "LDA":EQUB &0A  EQUS "CMP":EQUB &0C   EQUS "SBC":EQUB &0E ;  EQUS "ASL":EQUB &10 ( EQUS "ROL":EQUB &12 2 EQUS "LSR":EQUB &14 < EQUS "ROR":EQUB &16 F; P EQUS "BRL":EQUB &20 Z EQUS "BPL":EQUB &21 d EQUS "BMI":EQUB &23 n EQUS "BVC":EQUB &25 x EQUS "BVS":EQUB &27  EQUS "BRA":EQUB &28  EQUS "BCC":EQUB &29  EQUS "BCS":EQUB &2B  EQUS "BNE":EQUB &2D  EQUS "BEQ":EQUB &2F ;  EQUS "BIT":EQUB &30 ;  EQUS "CPX":EQUB &4E  EQUS "CPY":EQUB &4C ;  EQUS "DEC":EQUB &5C  EQUS "INC":EQUB &5E ;  EQUS "JMP":EQUB &60 ; " EQUS "JSR":EQUB &70 ,; 6 EQUS "LDX":EQUB &82 @ EQUS "LDY":EQUB &80 J; T EQUS "STX":EQUB &92 ^ EQUS "STY":EQUB &90 h; r EQUS "TRB":EQUB &A0 | EQUS "TSB":EQUB &A1  EQUS "RMB":EQUB &A2  EQUS "SMB":EQUB &A3  EQUS "BBR":EQUB &A4  EQUS "BBS":EQUB &A5  EQUS "CLR":EQUB &A6  EQUS "STZ":EQUB &A6  EQUS "REP":EQUB &A8  EQUS "SEP":EQUB &A9  EQUS "MVN":EQUB &AA  EQUS "MVP":EQUB &AB  EQUS "PEA":EQUB &AC  EQUS "PEI":EQUB &AD  EQUS "PER":EQUB &AE  EQUS "COP":EQUB &AF ;  EQUS "BRK":EQUB &B0 & EQUS "CLC":EQUB &B1 0 EQUS "CLD":EQUB &B2 : EQUS "CLI":EQUB &B3 D EQUS "CLV":EQUB &B4 N EQUS "DEX":EQUB &B5 X EQUS "DEY":EQUB &B6 b EQUS "INX":EQUB &B7 l EQUS "INY":EQUB &B8 v EQUS "NOP":EQUB &B9  EQUS "PHA":EQUB &BA  EQUS "PHP":EQUB &BB  EQUS "PLA":EQUB &BC  EQUS "PLP":EQUB &BD  EQUS "RTI":EQUB &BE  EQUS "RTS":EQUB &BF  EQUS "SEC":EQUB &C0  EQUS "SED":EQUB &C1  EQUS "SEI":EQUB &C2  EQUS "TAX":EQUB &C3  EQUS "TAY":EQUB &C4  EQUS "TSX":EQUB &C5  EQUS "TXA":EQUB &C6  EQUS "TXS":EQUB &C7   EQUS "TYA":EQUB &C8  EQUS "DEA":EQUB &C9   EQUS "INA":EQUB &CA * EQUS "PHX":EQUB &CB 4 EQUS "PHY":EQUB &CC > EQUS "PLX":EQUB &CD H EQUS "PLY":EQUB &CE R EQUS "WAI":EQUB &CF \ EQUS "STP":EQUB &D0 f EQUS "PHB":EQUB &D1 p EQUS "PHD":EQUB &D2 z EQUS "PHK":EQUB &D3  EQUS "PLB":EQUB &D4  EQUS "PLD":EQUB &D5  EQUS "RTL":EQUB &D6  EQUS "TCD":EQUB &D7  EQUS "TAD":EQUB &D7  EQUS "TCS":EQUB &D8  EQUS "TAS":EQUB &D8  EQUS "TDC":EQUB &D9  EQUS "TDA":EQUB &D9  EQUS "TSC":EQUB &DA  EQUS "TSA":EQUB &DA  EQUS "TXY":EQUB &DB  EQUS "TYX":EQUB &DC  EQUS "XBA":EQUB &DD  EQUS "SWA":EQUB &DD  EQUS "XCE":EQUB &DE $; .H EQUS "OPT":EQUB &F0 ; (pass the other relevant ones) 8 EQUS "EQU":EQUB &F1 B EQUS "DCB":EQUB &F2 L EQUS "DCW":EQUB &F3 V EQUS "DCD":EQUB &F4 `; j8 EQUD 0 ; (end of table) t ~  .supported_opcodes ; ; 0 1 2 3 4 5 6 7 8 9 A B C D E F ;  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 ī 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 Ϋ 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 ث 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  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  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  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  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  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  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  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 ( 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 2 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 < 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 F 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 P 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 Z d n x.instr_6502 ;  EQUD 0    .patch_6502_2 ; E MOV r3,r2,LSR#24 ; Initialise processing flags ; ; LDRB r10,[r11],#1 ; To next character ; E CMP r3,#&A2 ; Is this a 4-char mnemonic ?  RSBCSS r14,r3,#&A5 @ BCS class_nobn ; Yes, don't skip spaces ; 5 BL skip_spaces ; Skip spaces "; ,.class_nobn 6; @@ ADR r2,instr_6502+1 ; Buffer for instruction J; T1 MOV r0,#0 ; Wipe it ^ STR r0,[r2] h; r> ADR r14,class_done ; Call 'class' handler | STMFD r13!,{r14}  r0,r3,#%11110000  ADD pc,pc,r0,LSR#4-2  MOV r0,r0 ;  B class_ORA  B class_ASL  B class_BPL  B class_BIT  B class_CPX  B class_DEC  B class_JMP  B class_JSR  B class_LDX  B class_STX  B class_TRB  B class_BRK & B class_BRK 0 B class_BRK : B class_BRK D EQUD 0 N; X.class_done b; l5 BL skip_spaces ; Skip spaces v; = MOV r0,r3,LSR#24 ; Buffer final opcode  STRB r0,instr_6502 ; 8 MOV r1,#0 ; Processor code  BL opt_16  MOVNE r1,#1  BL opt_32  MOVNE r1,#2 ; N ADR r14,supported_opcodes ; Instruction supported by processor ?  LDRB r14,[r14,r0]  MOV r14,r14,LSR r1  TST r14,#1 < BEQ badop_error ; No, generate error  ; D r0,r0,#%00000111 ; 65C02/65C816 conflict area ?   TEQ r0,#%00000111 *, BNE badop_nconf ; No 4; >D r0,r3,#%11111111 ; Actual 'Rockwell' conflict ? H CMP r0,#&A2 R RSBCSS r0,r0,#&A5 \ MOVCS r0,#1 f MOVCC r0,#2 p; z TEQ r0,r1 = BNE badop_error ; Yes, generate error ; .badop_nconf ; @ ADR r1,instr_6502 ; Return number of bytes  SUB r2,r2,r1 ; @ LDR r1,instr_6502 ; Return bytes to output ; @ B Data%+Patch_Off(50) ; Join '0..4 bytes' code ; .badop_error ;  CMP r1,#1  BLO badop_error_6502  BEQ badop_error_65C02 $ BHI badop_error_65C816 .; 8.badop_error_6502 B; LD generate_error_message(4, "Instruction not supported by 6502") V; `.badop_error_65C02 j; tE generate_error_message(4, "Instruction not supported by 65C02") ~; .badop_error_65C816 ; F generate_error_message(4, "Instruction not supported by 65C816") ; ; ; .eval_expr_prev ; A SUB r11,r11,#1 ; Step back one character  LDRB r10,[r11,#-1] ; .eval_expr_curr ;  = STMFD r13!,{r1-r3,r14} ; Evaluate expression ;  BL Data%+Patch_Off(51) (; 2 LDMFD r13!,{r1-r3,pc}^ <; F.eval_expr_prev_sized P; ZA SUB r11,r11,#1 ; Step back one character d LDRB r10,[r11,#-1] n; x.eval_expr_curr_sized ; .evxcs_skspc ; 9 LDRB r10,[r11],#1 ; Skip any spaces  TEQ r10,#" "  BEQ evxcs_skspc ; @ TEQ r10,#"<" ; Size indicator present ?  TEQNE r10,#">"  TEQNE r10,#"^" ; = BNE eval_expr_prev ; No, nothing to skip ; ; CMP r10,#">" ; Flag size indicator  RLO r3,r3,#1<<16  REQ r3,r3,#2<<16 " RHI r3,r3,#3<<16 ,; 6< B eval_expr_curr ; And skip indicator @; J; T; ^.hop_skip_spaces h; r8 LDRB r10,[r11],#1 ; Skip character |; .skip_spaces ; 9 TEQ r10,#" " ; Scan to non-space  LDREQB r10,[r11],#1  BEQ skip_spaces ;  MOVS pc,r14 ; ; ; .not_a_variable ;  STMFD r13!,{r14} ;  LDRB r14,[r11] ; & CMP r14,#"A" 0 BLO notav_chelo : CMP r14,#"Z" D BLS notav_isvar N; X.notav_chelo b; l CMP r14,#"a" v BLO notav_chedi  CMP r14,#"z"  BLS notav_isvar ; .notav_chedi ;  CMP r14,#"0"  BLO notav_cheot  CMP r14,#"9"  BLS notav_isvar ; .notav_cheot ;  TEQ r14,#"`"  TEQNE r14,#"_"   TEQNE r14,#"$"  TEQNE r14,#"%"   TEQNE r14,#"(" * BEQ notav_isvar 4; > TEQ r14,r14 H; R LDMFD r13!,{pc} \; f.notav_isvar p; z CMN r14,#1 ;  LDMFD r13!,{pc} ; ; ;  .opt_2 ;  STMFD r13!,{r0,r14} ;  LDRB r0,[r8,#basoff_opt%]  TST r0,#2 ;  LDMFD r13!,{r0,pc} ; ; ; $ .opt_16 .; 8 STMFD r13!,{r0,r14} B; L LDRB r0,[r8,#basoff_opt%] V TST r0,#16 `; j LDMFD r13!,{r0,pc} t; ~; ;  .opt_32 ;  STMFD r13!,{r0,r14} ;  LDRB r0,[r8,#basoff_opt%]  TST r0,#32 ;  LDMFD r13!,{r0,pc} ; ; ; .mnem_bit_number  ; A CMP r10,#"0" ; '0' .. '7', as expected ? 3 BLO mnebn_error ; No, error ( CMP r10,#"7" 23 BHI mnebn_error ; No, error <; F9 SUB r0,r10,#"0" ; Return bit number P; ZD B hop_skip_spaces ; Skip bit number and spaces d; n.mnebn_error x; Q generate_error_message(2, "Expected bit number (0-7) attached to mnemonic") ; ; ; .is_left_bracket ; 7 TEQ r10,#"(" ; Round bracket ? 7 BEQ isleb_match ; Yes (default) ; 8 TEQ r10,#"[" ; Square bracket ? 6 REQ r3,r3,#1<<23 ; Yes (flag it) ; .isleb_match ; ? MOV pc,r14 ; Return (with flags !) ; "; ,; 6.is_right_bracket @; J3 STMFD r13!,{r14} ; Save link T; ^> TST r3,#1<<23 ; Which bracket type ? h Q r14,#")" r MOVNE r14,#"]" |; A TEQ r10,r14 ; Correct right bracket ? ; ? LDMFD r13!,{pc} ; Return (with flags !) ; ; ; .is_comma_Y ; = STMFD r13!,{r10,r11,r14} ; Save used registers ; 6 TEQ r10,#"," ; Expected ',' ? 6 BNE iscoy_done ; No, no match ; ? BL hop_skip_spaces ; Skip ',', skip spaces ; 6 TEQ r10,#"Y" ; Expected 'Y' ? & TEQNE r10,#"y" 0; :.iscoy_done D; N? LDMFD r13!,{r10,r11,pc} ; Return (with flags !) X; b; l; v.is_comma_S ; = STMFD r13!,{r10,r11,r14} ; Save used registers ; 6 TEQ r10,#"," ; Expected ',' ? 6 BNE iscos_done ; No, no match ; ? BL hop_skip_spaces ; Skip ',', skip spaces ; 6 TEQ r10,#"S" ; Expected 'S' ?  TEQNE r10,#"s" ; .iscos_done ; !? LDMFD r13!,{r10,r11,pc} ; Return (with flags !) ! ; !; ! ; !*.error_or_immediate_ha !4; !>? TEQ r10,#"#" ; Expected character(s) ? !H2 QS pc,r14 ; Yes, return !R; !\C generate_error_message(2, "Immediate addressing: expected #") !f; !p; !z; !.error_or_zeropagex_X !; !? TEQ r10,#"X" ; Expected character(s) ? ! TEQNE r10,#"x" !2 QS pc,r14 ; Yes, return !; !E generate_error_message(3, "Zero-page,X addressing: expected X") !; !; !; !.error_or_zeropagey_Y !; !? TEQ r10,#"Y" ; Expected character(s) ? " TEQNE r10,#"y" "2 QS pc,r14 ; Yes, return "; "$E generate_error_message(3, "Zero-page,Y addressing: expected Y") ".; "8; "B; "L.error_or_absolutex_X "V; "`? TEQ r10,#"X" ; Expected character(s) ? "j TEQNE r10,#"x" "t2 QS pc,r14 ; Yes, return "~; "D generate_error_message(3, "Absolute,X addressing: expected X") "; "; "; ".error_or_absolutey_Y "; "? TEQ r10,#"Y" ; Expected character(s) ? " TEQNE r10,#"y" "2 QS pc,r14 ; Yes, return "; "D generate_error_message(3, "Absolute,Y addressing: expected Y") "; #; # ; #.error_or_absolute_X_Y #; #(? TEQ r10,#"X" ; Expected character(s) ? #2 TEQNE r10,#"x" #< TEQNE r10,#"Y" #F TEQNE r10,#"y" #P2 QS pc,r14 ; Yes, return #Z; #dK generate_error_message(3, "Absolute,X/Y addressing: expected X or Y") #n; #x; #; #.error_or_absolongx_X #; #? TEQ r10,#"X" ; Expected character(s) ? # TEQNE r10,#"x" #2 QS pc,r14 ; Yes, return #; #I generate_error_message(3, "Absolute Long,X addressing: expected X") #; #; #; #.error_or_indirect_ls #; $? TEQ r10,#"(" ; Expected character(s) ? $2 QS pc,r14 ; Yes, return $; $"B generate_error_message(3, "Indirect addressing: expected (") $,; $6; $@; $J.error_or_indirect_co_rb $T; $^3 STMFD r13!,{r14} ; Save link $h; $r? TEQ r10,#"," ; Expected character(s) ? $| BLNE is_right_bracket $5 LDMEQFD r13!,{pc}^ ; Yes, return $; $ TST r3,#1<<23 $ BNE ermsg_indirect_co_rh $; $.ermsg_indirect_co_rs $; $G generate_error_message(3, "Indirect addressing: expected , or )") $; $.ermsg_indirect_co_rh $; $G generate_error_message(3, "Indirect addressing: expected , or ]") $; %; %; %.error_or_indirect_X_S %&; %0? TEQ r10,#"X" ; Expected character(s) ? %: TEQNE r10,#"x" %D TEQNE r10,#"S" %N TEQNE r10,#"s" %X2 QS pc,r14 ; Yes, return %b; %lG generate_error_message(3, "Indirect addressing: expected X or S") %v; %; %; %.error_or_indirect_rb %; %3 STMFD r13!,{r14} ; Save link %; %A BL is_right_bracket ; Expected character(s) ? %5 LDMEQFD r13!,{pc}^ ; Yes, return %; % TST r3,#1<<23 % BNE ermsg_indirect_rh %; %.ermsg_indirect_rs &; & B generate_error_message(3, "Indirect addressing: expected )") &; & .ermsg_indirect_rh &*; &4B generate_error_message(3, "Indirect addressing: expected ]") &>; &H; &R; &\.error_or_indirectx_co &f; &p? TEQ r10,#"," ; Expected character(s) ? &z2 QS pc,r14 ; Yes, return &; &D generate_error_message(3, "Indirect,X addressing: expected ,") &; &; &; &.error_or_indirectx_X &; &? TEQ r10,#"X" ; Expected character(s) ? & TEQNE r10,#"x" &2 QS pc,r14 ; Yes, return &; &D generate_error_message(3, "Indirect,X addressing: expected X") &; '; '; '.error_or_indirectx_rb '$; '.3 STMFD r13!,{r14} ; Save link '8; 'BA BL is_right_bracket ; Expected character(s) ? 'L5 LDMEQFD r13!,{pc}^ ; Yes, return 'V; '` TST r3,#1<<23 'j BNE ermsg_indirectx_rh 't; '~.ermsg_indirectx_rs '; 'D generate_error_message(3, "Indirect,X addressing: expected )") '; '.ermsg_indirectx_rh '; 'D generate_error_message(3, "Indirect,X addressing: expected ]") '; '; '; '.error_or_indirecty_Y '; '? TEQ r10,#"Y" ; Expected character(s) ? ( TEQNE r10,#"y" ( 2 QS pc,r14 ; Yes, return (; (D generate_error_message(3, "Indirect,Y addressing: expected Y") ((; (2; (<; (F.error_or_indirects_co (P; (Z? TEQ r10,#"," ; Expected character(s) ? (d2 QS pc,r14 ; Yes, return (n; (xD generate_error_message(3, "Indirect,S addressing: expected ,") (; (; (; (.error_or_indirects_Y (; (? TEQ r10,#"Y" ; Expected character(s) ? ( TEQNE r10,#"y" (2 QS pc,r14 ; Yes, return (; (D generate_error_message(3, "Indirect,S addressing: expected Y") (; (; (; ).error_or_indirects_rb ); )3 STMFD r13!,{r14} ; Save link )"; ),A BL is_right_bracket ; Expected character(s) ? )65 LDMEQFD r13!,{pc}^ ; Yes, return )@; )J TST r3,#1<<23 )T BNE ermsg_indirects_rh )^; )h.ermsg_indirects_rs )r; )|D generate_error_message(3, "Indirect,S addressing: expected )") ); ).ermsg_indirects_rh ); )D generate_error_message(3, "Indirect,S addressing: expected ]") ); ); ); ).error_or_BBx_co ); )? TEQ r10,#"," ; Expected character(s) ? )2 QS pc,r14 ; Yes, return ); )T generate_error_message(3, "BBR/BBS Zero-page,Relative addressing: expected ,") *; *; *; *&.error_or_MVx_co *0; *:? TEQ r10,#"," ; Expected character(s) ? *D2 QS pc,r14 ; Yes, return *N; *XK generate_error_message(3, "MVN/MVP Bank,Bank addressing: expected ,") *b; *l; *v; *.error_if_constoverflowB *; *A STMFD r13!,{r1,r14} ; Save registers and link *; * ADR r1,ermsg_constoverflowB *; * B error_if_byteoverflow *; *.error_if_constoverflowS *; *A STMFD r13!,{r1,r14} ; Save registers and link *; * ADR r1,ermsg_constoverflowS +; +  B error_if_shortoverflow +; + .error_if_zpaddroverflow +*; +4A STMFD r13!,{r1,r14} ; Save registers and link +>; +H ADR r1,ermsg_zpaddroverflow +R; +\ B error_if_byteoverflow +f; +p.error_if_banknroverflow +z; +A STMFD r13!,{r1,r14} ; Save registers and link +; + ADR r1,ermsg_banknroverflow +; + B error_if_byteoverflow +; +.error_if_codebyteoverflow +; +A STMFD r13!,{r1,r14} ; Save registers and link +; +" ADR r1,ermsg_codebyteoverflow +; + B error_if_byteoverflow ,; ,.error_if_shortoverflow ,; ,$4 CMP r0,#&10000 ; In range ? ,.5 LDMLOFD r13!,{r1,pc}^ ; Yes, return ,8; ,B8 MVN r14,#0 ; Force in range ,L BIC r0,r0,r14,LSL#16 ,V; ,`2 B eiovr_chopt ; Continue ,j; ,t.error_if_byteoverflow ,~; ,4 CMP r0,#&100 ; In range ? ,5 LDMLOFD r13!,{r1,pc}^ ; Yes, return ,; ,6 r0,r0,#&FF ; Force in range ,; ,.eiovr_chopt ,; ,8 BL opt_2 ; Errors fatal ? ,; ,4 LDMEQFD r13!,{r1,pc}^ ; No, return ,; ,= MOV r0,r1 ; Yes, generate error -; -  B error_generate -; -.ermsg_constoverflowB -(; -2? error_message(2, "Immediate value out of range [0..255]") -<; -F.ermsg_constoverflowS -P; -ZA error_message(2, "Immediate value out of range [0..65535]") -d; -n.ermsg_zpaddroverflow -x; -A error_message(2, "Zero-page address out of range [0..255]") -; -.ermsg_banknroverflow -; -; error_message(1, "Bank number out of range [0..255]") -; -.ermsg_codebyteoverflow -; -9 error_message(2, "Code byte out of range [0..255]") -; -; -; -.error_if_offsetoutofrange .; .A STMFD r13!,{r2-r3,r14} ; Save registers and link .; ."7 LDR r2,[r8,#basoff_p%] ; Branch offset ., ADD r2,r2,r1,LSR#30 .6 SUB r0,r0,r2 .@; .J4 MOV r3,#1 ; In range ? .T MOV r3,r3,LSL r1 .^ ADD r2,r0,r3,LSR#1 .h CMP r2,r3 .r5 LDMLOFD r13!,{r2-r3,pc}^ ; Yes, return .|; .8 BL opt_2 ; Errors fatal ? .; .4 LDMEQFD r13!,{r2-r3,pc}^ ; No, return .; .< TEQ r1,#2<<30 8 ; Yes, generate error .( ADREQ r0,ermsg_offsetoutofrange_Bxx . TEQ r1,#3<<30 8 .( ADREQ r0,ermsg_offsetoutofrange_BBx . TEQ r1,#3<<30 16 .( ADREQ r0,ermsg_offsetoutofrange_BRL .; . B error_generate .; /.ermsg_offsetoutofrange_Bxx /; /D error_message(1, "Branch target out of range [P%-126,P%+129]") /&; /0.ermsg_offsetoutofrange_BBx /:; /DD error_message(1, "Branch target out of range [P%-125,P%+130]") /N; /X.ermsg_offsetoutofrange_BRL /b; /lH error_message(1, "Branch target out of range [P%-32765,P%+32770]") /v; /; /; /.error_generate /; / SWI "OS_GenerateError" /; /; /; /.which_address_size /; /A STMFD r13!,{r1,r14} ; Save registers and link /; /? CMP r0,#256 ; Address size in bytes 0 MOVLO r14,#1 0  MOVHS r14,#2 0; 0  MOV r1,#%11 0* S r1,r1,r3,LSR#16 04 Q r1,r14 0>; 0H> CMP r1,#2 ; Which address size ? 0R; 0\? LDMFD r13!,{r1,pc} ; Return (with flags !) 0f; 0p; 0z; 0.try_immediate 0; 0= TEQ r10,#"#" ; Immediate indicated ? 0 TEQNE r10,#"%" 0> MOVNES pc,r14 ; No, so not immediate 0; 06 R r3,r3,r1,LSL#24 ; Finish opcode 0; 0= MOV r1,r10 ; Remember value size 0; 0G BL eval_expr_curr ; Past '#'/'%', immediate value 0; 04 TEQ r1,#"%" ; Large size ? 15 BEQ trim_large ; Yes, 16 bit 1; 1? BL error_if_constoverflowB ; Error if not in range 1$; 1.B B finish_byte ; End with 1 argument byte 18; 1B.trim_large 1L; 1V? BL error_if_constoverflowS ; Error if not in range 1`; 1jC B finish_dble ; End with 2 argument bytes 1t; 1~; 1; 1.try_zeropage 1; 1= TEQ r10,#"," ; Zero-page indicated ? 1> QS pc,r14 ; No (an indexed version) 1; 15 r14,r1,#%11111111 ; Finish opcode 1 R r3,r3,r14,LSL#24 1; 1B B finish_byte ; End with 1 argument byte 1; 1; 2; 2 .try_absolute 2; 2< TEQ r10,#"," ; Absolute indicated ? 2(> QS pc,r14 ; No (an indexed version) 22; 2<5 r14,r1,#%11111111 ; Finish opcode 2F R r3,r3,r14,LSL#24 2P; 2ZC B finish_dble ; End with 2 argument bytes 2d; 2n; 2x; 2.try_absolong 2; 2A TEQ r10,#"," ; Absolute long indicated ? 2> QS pc,r14 ; No (an indexed version) 2; 25 r14,r1,#%11111111 ; Finish opcode 2 R r3,r3,r14,LSL#24 2; 2C B finish_trip ; End with 3 argument bytes 2; 2; 2; 2.try_indirect 3; 3> MOV r1,r14 ; Indirect indicated ? 3 BL is_left_bracket 3"= MOVNES pc,r1 ; No, so not indirect 3,; 36I BL eval_expr_curr ; Past '('/'[', zero-page address 3@; 3J? BL error_if_zpaddroverflow ; Error if not in range 3T; 3^: TST r3,#1<<23 ; Square bracket ? 3h9 BNE trind_plory ; Yes (no [Zp,X]) 3r; 3|> BL error_or_indirect_co_rb ; Match ',' or ')'/']' 3; 38 TEQ r10,#"," ; Was it the ',' ? 39 BNE trind_plory ; No (not (Zp,X)) 3; 3? BL hop_skip_spaces ; Skip ',', skip spaces 3; 3: BL error_or_indirect_X_S ; Match 'X' or 'S' 3; 3: TEQ r10,#"S" ; Following is 'S' ? 3 TEQNE r10,#"s" 3; BEQ trind_strel ; Yes (is (Zp,S),Y) 3; 36 R r3,r3,#%00000001<<24 ; Finish opcode 4; 4? BL hop_skip_spaces ; Skip 'X', skip spaces 4; 4&7 BL error_or_indirectx_rb ; Match ')'/']' 40; 4:P B finish_hop_byte ; Skip ')'/']', end with 1 argument byte 4D; 4N.trind_plory 4X; 4b7 BL error_or_indirect_rb ; Match ')'/']' 4l; 4v@ TST r3,#1<<23 ; Finish opcode (for ,Y) 4 REQ r3,r3,#%00010001<<24 4 RNE r3,r3,#%00010111<<24 4; 4C BL hop_skip_spaces ; Skip ')'/']', skip spaces 4; 4: TEQ r10,#"," ; Following is ',' ? 49 BNE trind_plain ; No (not (Zp),Y) 4; 4? BL hop_skip_spaces ; Skip ',', skip spaces 4; 43 BL error_or_indirecty_Y ; Match 'Y' 4; 4L B finish_hop_byte ; Skip 'Y', end with 1 argument byte 5; 5 .trind_plain 5; 5 C TST r3,#1<<23 ; Finish opcode (for plain) 5* EQ r3,r3,#%00000011<<24 54 NE r3,r3,#%00010000<<24 5>; 5HB B finish_byte ; End with 1 argument byte 5R; 5\.trind_strel 5f; 5p6 R r3,r3,#%00010011<<24 ; Finish opcode 5z; 5? BL hop_skip_spaces ; Skip 'S', skip spaces 5; 57 BL error_or_indirects_rb ; Match ')'/']' 5; 5C BL hop_skip_spaces ; Skip ')'/']', skip spaces 5; 53 BL error_or_indirects_co ; Match ',' 5; 5? BL hop_skip_spaces ; Skip ',', skip spaces 5; 53 BL error_or_indirects_Y ; Match 'Y' 5; 5L B finish_hop_byte ; Skip 'Y', end with 1 argument byte 6; 6; 6; 6$.do_zeropage_Xopt 6.; 68D BL try_zeropage ; Try (plain) zero-page mode 6B; 6L? BL hop_skip_spaces ; Skip ',', skip spaces 6V; 6`3 BL error_or_zeropagex_X ; Match 'X' 6j; 6t7 MOV r14,r1,LSR#8 ; Finish opcode 6~ R r3,r3,r14,LSL#24 6; 6L B finish_hop_byte ; Skip 'X', end with 1 argument byte 6; 6; 6; 6.do_zeropage_XorYopt 6; 6D BL try_zeropage ; Try (plain) zero-page mode 6; 6? BL hop_skip_spaces ; Skip ',', skip spaces 6; 6: TST r3,#%1111 ; Match 'X' or 'Y' 7 BLEQ error_or_zeropagex_X 7  BLNE error_or_zeropagey_Y 7; 77 MOV r14,r1,LSR#8 ; Finish opcode 7( R r3,r3,r14,LSL#24 72; 7; :H.finish_dble :R; :\ STRB r0,[r2],#1 :f MOV r0,r0,LSR#8 :p; :z.finish_byte :; : STRB r0,[r2],#1 :; :.finish_implied :; : LDMFD r13!,{pc} :; :; :; :.class_BRK :; :5 ADR r0,table_implieds-&B0 ; Make opcode : LDRB r0,[r0,r3] ; R r3,r3,r0,LSL#24 ;; ;C B finish_implied ; End with 0 argument bytes ;$; ;.; ;8; ;B.table_implieds ;L; ;V EQUB &00 ;` EQUB &18 ;j EQUB &D8 ;t EQUB &58 ;~ EQUB &B8 ; EQUB &CA ; EQUB &88 ; EQUB &E8 ; EQUB &C8 ; EQUB &EA ; EQUB &48 ; EQUB &08 ; EQUB &68 ; EQUB &28 ; EQUB &40 ; EQUB &60 ; EQUB &38 < EQUB &F8 < EQUB &78 < EQUB &AA < EQUB &A8 <( EQUB &BA <2 EQUB &8A << EQUB &9A CMP r1,#2 ; Which address size ? Ad; An4 RLS r3,r3,#%00100000<<24 ; Make opcode Ax RHI r3,r3,#%00100010<<24 A; AE BLS finish_dble ; End with 2/3 argument bytes A BHI finish_trip A; A.cljsr_ind A; AD BL eval_expr_curr ; Past '(', absolute address A; A3 BL error_or_indirectx_co ; Match ',' A; A? BL hop_skip_spaces ; Skip ',', skip spaces A; A3 BL error_or_indirectx_X ; Match 'X' B; B? BL hop_skip_spaces ; Skip 'X', skip spaces B; B"3 BL error_or_indirectx_rb ; Match ')' B,; B64 R r3,r3,#%11111100<<24 ; Make opcode B@; BJM B finish_hop_dble ; Skip ')', end with 2 argument bytes BT; B^; Bh; Br.class_ORA B|; B/ TEQ r3,#&08 ; STA ? B; B5 R r3,r3,r3,LSL#28 ; Start opcode B; BC BEQ clora_sta ; STA has no immediate mode B; B< MOV r1,#%00001001 ; Try immediate mode B BL try_immediate B; B.clora_sta B; B; BL try_indirect ; Try indirect mode B; CS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) C; C> BL which_address_size ; Which address size ? C&; C00 BHI clora_alo ; 3-byte C:0 BEQ clora_abs ; 2-byte CD; CNE BL is_comma_Y ; Zero-page,Y (unavailable) ? CXF BEQ clora_abs ; Yes, turn it into absolute,Y Cb; Cl< BL is_comma_S ; Stack-relative,S ? Cv? BEQ clora_sre ; Yes, special handling C; CC MOV r1,#%00000101 ; Handle zero-page(,X) mode C R r1,r1,#%0010101<<8 C; C B do_zeropage_Xopt C; C.clora_sre C; C6 R r3,r3,#%00000011<<24 ; Finish opcode C; C? BL hop_skip_spaces ; Skip ',', skip spaces C; CL B finish_hop_byte ; Skip 'S', end with 1 argument byte D; D .clora_abs D; D C MOV r1,#%00001101 ; Try (plain) absolute mode D* BL try_absolute D4; D>? BL hop_skip_spaces ; Skip ',', skip spaces DH; DR: BL error_or_absolute_X_Y ; Match 'X' or 'Y' D\; Df5 TEQ r10,#"X" ; Finish opcode Dp TEQNE r10,#"x" Dz REQ r3,r3,#%00011101<<24 D RNE r3,r3,#%00011001<<24 D; DT B finish_hop_dble ; Skip 'X' or 'Y', end with 2 argument bytes D; D.clora_alo D; DG MOV r1,#%00001111 ; Handle absolute long(,X) mode D R r1,r1,#%00011111<<8 D; D B do_absolong_Xopt D; D; D; E.class_ASL E; E5 R r3,r3,r3,LSL#28 ; Start opcode E$; E.. TEQ r10,#"A" ; Accu ? E8 TEQNE r10,#"a" EB BLEQ not_a_variable EL; REQ r3,r3,#%00001010<<24 ; Yes, finish opcode EVU BEQ finish_hop_implied ; And skip 'A', and end with 0 argument bytes E`; EjS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) Et; E~> BL which_address_size ; Which address size ? E; EN MOV r1,#%00000110 ; Handle zero-page/absolute(,X/Y) mode E R r1,r1,#%00010110<<8 E BLO do_zeropage_Xopt E R r1,r1,#%00001000 E R r1,r1,#%00001000<<8 E BHS do_absolute_Xopt E; E; E; E.class_DEC E; F< TEQ r3,#&5C ; Opcode for DEA/INA F  Q r1,#%00111010 F MOVNE r1,#%00011010 F; F(. TEQ r10,#"A" ; Accu ? F2 TEQNE r10,#"a" F< BLEQ not_a_variable FF; REQ r3,r3,r1,LSL#24 ; Yes, finish opcode FPU BEQ finish_hop_implied ; And skip 'A', and end with 0 argument bytes FZ; Fd5 R r3,r3,r3,LSL#28 ; Start opcode Fn; FxS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) F; F> BL which_address_size ; Which address size ? F; FN MOV r1,#%00000110 ; Handle zero-page/absolute(,X/Y) mode F R r1,r1,#%00010110<<8 F BLO do_zeropage_Xopt F R r1,r1,#%00001000 F R r1,r1,#%00001000<<8 F BHS do_absolute_Xopt F; F; F; F.class_CPX G; G5 R r3,r3,r3,LSL#28 ; Start opcode G; G"< MOV r1,#%00000000 ; Try immediate mode G, BL try_immediate G6; G@S BL eval_expr_prev_sized ; Zero-page or absolute address (with size) GJ; GT> BL which_address_size ; Which address size ? G^; GhG R r3,r3,#%00000100<<24 ; Handle zero-page/absolute mode Gr BLO finish_byte G| R r3,r3,#%00001000<<24 G BHS finish_dble G; G; G; G.class_BIT G; G< MOV r1,#%10001001 ; Try immediate mode G BL try_immediate G; GS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) G; G> BL which_address_size ; Which address size ? G; HN MOV r1,#%00100100 ; Handle zero-page/absolute(,X/Y) mode H R r1,r1,#%00110100<<8 H BLO do_zeropage_Xopt H& R r1,r1,#%00001000 H0 R r1,r1,#%00001000<<8 H: BHS do_absolute_Xopt HD; HN; HX; Hb.class_LDX Hl; Hv4 r0,r3,#%00001111 ; Start opcode H R r0,r0,#%10100000 H R r3,r3,r0,LSL#24 H; H< MOV r1,#%00000000 ; Try immediate mode H BL try_immediate H; HS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) H; H> BL which_address_size ; Which address size ? H; HN MOV r1,#%00000100 ; Handle zero-page/absolute(,X/Y) mode H R r1,r1,#%00010100<<8 H BLO do_zeropage_XorYopt I R r1,r1,#%00001000 I  R r1,r1,#%00001000<<8 I BHS do_absolute_XorYopt I ; I*; I4; I>.class_STX IH; IR4 r0,r3,#%00001111 ; Start opcode I\ R r0,r0,#%10000000 If R r3,r3,r0,LSL#24 Ip; IzS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) I; I> BL which_address_size ; Which address size ? I; I@ RHS r3,r3,#%00001100<<24 ; Absolute, finish opcode IG BHS finish_dble ; And end with 2 argument bytes I; IE MOV r1,#%00000100 ; Handle zero-page(,X/Y) mode I R r1,r1,#%00010100<<8 I; I B do_zeropage_XorYopt I; I; I; J.class_TRB J; J= CMP r3,#&AF ; Dispatch instn code J$ BEQ class_COP J. CMP r3,#&AE J8 BEQ class_PER JB CMP r3,#&AD JL BEQ class_PEI JV CMP r3,#&AC J` BEQ class_PEA Jj CMP r3,#&AA Jt BHS class_MVN J~ CMP r3,#&A8 J BHS class_REP J CMP r3,#&A6 J BHS class_CLR J CMP r3,#&A4 J BHS class_BBR J CMP r3,#&A2 J BHS class_RMB J; J6 TEQ r3,#&A0 ; Start opcode J REQ r3,r3,#%00010000<<24 J RNE r3,r3,#%00000000<<24 J; KS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) K ; K> BL which_address_size ; Which address size ? K; K(G R r3,r3,#%00000100<<24 ; Handle zero-page/absolute mode K2 BLO finish_byte K< R r3,r3,#%00001000<<24 KF BHS finish_dble KP; KZ; Kd; Kn.class_RMB Kx; K6 TEQ r3,#&A2 ; Start opcode K REQ r3,r3,#%00000111<<24 K RNE r3,r3,#%10000111<<24 K; K> BL mnem_bit_number ; Check for bit number K; KA R r3,r3,r0,LSL#28 ; Add bit number to opcode K; K; BL eval_expr_prev ; Zero-page address K; K? BL error_if_zpaddroverflow ; Error if not in range K; KB B finish_byte ; End with 1 argument byte L; L; L; L".class_BBR L,; L66 TEQ r3,#&A4 ; Start opcode L@ REQ r3,r3,#%00001111<<24 LJ RNE r3,r3,#%10001111<<24 LT; L^> BL mnem_bit_number ; Check for bit number Lh; LrA R r3,r3,r0,LSL#28 ; Add bit number to opcode L|; L; BL eval_expr_prev ; Zero-page address L; L? BL error_if_zpaddroverflow ; Error if not in range L; LD STMFD r13!,{r0} ; Remember zero-page address L; L3 BL error_or_BBx_co ; Match ',' L; L? BL hop_skip_spaces ; Skip ',', skip spaces L; L: BL eval_expr_prev ; Absolute address L; LV MOV r1,#3<<30 8 ; Error if resulting branch offset out of range M! BL error_if_offsetoutofrange M; M> LDMFD r13!,{r1} ; Merge argument bytes M& R r0,r1,r0,LSL#8 M0; M:C B finish_dble ; End with 2 argument bytes MD; MN; MX; Mb.class_CLR Ml; MvS BL eval_expr_prev_sized ; Zero-page or absolute address (with size) M; M> BL which_address_size ; Which address size ? M; MN MOV r1,#%01100100 ; Handle zero-page/absolute(,X/Y) mode M R r1,r1,#%01110100<<8 M BLO do_zeropage_Xopt M MOV r1,#%10011100 M R r1,r1,#%10011110<<8 M BHS do_absolute_Xopt M; M; M; M.class_REP N; N 5 TEQ r3,#&A8 ; Make opcode N REQ r3,r3,#%11000010<<24 N  RNE r3,r3,#%11100010<<24 N*; N43 BL error_or_immediate_ha ; Match '#' N>; NHC BL eval_expr_curr ; Past '#', immediate value NR; N\? BL error_if_constoverflowB ; Error if not in range Nf; NpB B finish_byte ; End with 1 argument byte Nz; N; N; N.class_MVN N; N5 TEQ r3,#&AA ; Make opcode N REQ r3,r3,#%01010100<<24 N RNE r3,r3,#%01000100<<24 N; N; BL eval_expr_prev ; Bank number (src) N; N? BL error_if_banknroverflow ; Error if not in range N; N> STMFD r13!,{r0} ; Remember bank number O; O3 BL error_or_MVx_co ; Match ',' O; O$? BL hop_skip_spaces ; Skip ',', skip spaces O.; O8; BL eval_expr_prev ; Bank number (dst) OB; OL? BL error_if_banknroverflow ; Error if not in range OV; O`> LDMFD r13!,{r1} ; Merge argument bytes Oj R r0,r0,r1,LSL#8 Ot; O~C B finish_dble ; End with 2 argument bytes O; O; O; O.class_PEA O; O4 R r3,r3,#%11110100<<24 ; Make opcode O; O: BL eval_expr_prev ; Absolute address O; OC B finish_dble ; End with 2 argument bytes O; O; P; P .class_PEI P; P4 R r3,r3,#%11010100<<24 ; Make opcode P(; P23 BL error_or_indirect_ls ; Match '(' P<; PF? BL hop_skip_spaces ; Skip '(', skip spaces PP; PZ; BL eval_expr_prev ; Zero-page address Pd; Pn? BL error_if_zpaddroverflow ; Error if not in range Px; P3 BL error_or_indirect_rb ; Match ')' P; PL B finish_hop_byte ; Skip ')', end with 1 argument byte P; P; P; P.class_PER P; P4 R r3,r3,#%01100010<<24 ; Make opcode P; P: BL eval_expr_prev ; Absolute address P; PV MOV r1,#3<<30 16 ; Error if resulting branch offset out of range Q! BL error_if_offsetoutofrange Q; QC B finish_dble ; End with 2 argument bytes Q"; Q,; Q6; Q@.class_COP QJ; QT4 R r3,r3,#%00000010<<24 ; Make opcode Q^; Qh3 BL eval_expr_prev ; Code byte Qr; Q|? BL error_if_codebyteoverflow ; Error if not in range Q; QB B finish_byte ; End with 1 argument byte Q Q Q Q] Q Q Q QSize% = P% - Data% Q Q Q R R R-ݤerror_message(asm_err%, error_message$) R& R0 [OPT `P R:; RD EQUD asm_err% RN EQUS error_message$ RX EQUB 0 Rb; Rl ALIGN Rv; R] R R= 0 R R R R6ݤgenerate_error_message(asm_err%, error_message$) R R [OPT `P R; R ADR r0,P%+2*4 R; R B error_generate S; S - error_message(asm_err%, error_message$) S; S ] S* S4= 0 S> SH SR S\doing_105 Sf Sp RISC OS 3.1x BASIC 1.05 Sz1 Address data for v1.05 added by J.G.Harston S S0Patch_Off(1) = &B994: TEXTLOAD renumber 1,1 S2Patch_Off(2) = &A044: Point to mnemonic table S)Patch_Off(3) = &A0E8: B patch_6502_2 S)Patch_Off(4) = &9FE8: B patch_6502_0 S2Patch_Off(5) = &A87C: AND R0,R0,#15; mask OPT S SPatch_Off(50) = &A668 SPatch_Off(51) = &AA18 S1Patch_Off(52) = &A040: Search mnemonic table S Sbasoff_p% = -&C0 Sbasoff_opt% = -&26 T TWhich$ = "BASIC105" T T$ T. T8 TB TLdoing_116 TV T` RISC OS 3.70 BASIC 1.16 Tj TtPatch_Off(1) = &BAD4 T~Patch_Off(2) = &A184 TPatch_Off(3) = &A228 TPatch_Off(4) = &A128 TPatch_Off(5) = &A9BC T TPatch_Off(50) = &A7A8 TPatch_Off(51) = &AB58 TPatch_Off(52) = &A180 T Tbasoff_p% = -&C0 Tbasoff_opt% = -&1E T TWhich$ = "BASIC116" U U  U U U( U2doing_119 U< UF RISC OS 4.02 BASIC 1.19 UP UZPatch_Off(1) = &C588 UdPatch_Off(2) = &A198 UnPatch_Off(3) = &A35C UxPatch_Off(4) = &A14C UPatch_Off(5) = &B204 U UPatch_Off(50) = &AFF0 UPatch_Off(51) = &B498 UPatch_Off(52) = &A194 U Ubasoff_p% = -&C0 Ubasoff_opt% = -&1E U UWhich$ = "BASIC119" U U U V V Vdoing_120 V" V, RISC OS 4.03 BASIC 1.20 V6 V@Patch_Off(1) = &C5B8 VJPatch_Off(2) = &A1CC VTPatch_Off(3) = &A390 V^Patch_Off(4) = &A180 VhPatch_Off(5) = &B238 Vr V|Patch_Off(50) = &B024 VPatch_Off(51) = &B4CC VPatch_Off(52) = &A1C8 V Vbasoff_p% = -&C0 Vbasoff_opt% = -&1E V VWhich$ = "BASIC120" V V V V V Vdoing_120x W W' RISC OS 4.02 'mystery' BASIC 1.20 W W&Patch_Off(1) = &C5D4 W0Patch_Off(2) = &A1E0 W:Patch_Off(3) = &A3A4 WDPatch_Off(4) = &A194 WNPatch_Off(5) = &B24C WX WbPatch_Off(50) = &B038 WlPatch_Off(51) = &B4E0 WvPatch_Off(52) = &A1DC W Wbasoff_p% = -&C0 Wbasoff_opt% = -&1E W WWhich$ = "BASIC120X" W W W W W Wdoing_128 W W RISC OS 4.37 BASIC 1.28 X X Patch_Off(1) = &C678 XPatch_Off(2) = &A244 X Patch_Off(3) = &A408 X*Patch_Off(4) = &A1F8 X4Patch_Off(5) = &B300 X> XHPatch_Off(50) = &B0EC XRPatch_Off(51) = &B594 X\Patch_Off(52) = &A240 Xf Xpbasoff_p% = -&C0 Xzbasoff_opt% = -&1A X XWhich$ = "BASIC128" X X X X X Xdoing_129 X X RISC OS 4.39 BASIC 1.29 X XPatch_Off(1) = &C678 XPatch_Off(2) = &A244 YPatch_Off(3) = &A408 YPatch_Off(4) = &A1F8 YPatch_Off(5) = &B300 Y$ Y.Patch_Off(50) = &B0EC Y8Patch_Off(51) = &B594 YBPatch_Off(52) = &A240 YL YVbasoff_p% = -&C0 Y`basoff_opt% = -&1A Yj YtWhich$ = "BASIC129" Y~ Y Y Y Y Yprime(code%, old%) Y Ycheck(code%, old%, 0) Y Y Y Y Y Zprim4(code%, old%) Z  Zcheck(code%, old%, 4) Z Z( Z2 Z< ZF ZP check(code%, old%, choff%) ZZ Zd!P% = Data% + Patch_Off(code%) Zn Zx `P = %0000 Z ZK P%!choff% <> old% 66, "Old doesn't match (code " + (code%) + ")" Z Z