( ----- 000 ) 6502 MASTER INDEX 301 6502 macros and consts 302 6502 assembler 310 6502 boot code 330 6502 disassembler 335 6502 emulator 350 Virgil's workspace 360 Apple IIe drivers ( ----- 001 ) \ 6502 macros and constants. See doc/code/6502.txt : 6502A 302 305 LOADR 7 LOAD ( flow ) ; : 6502M 309 LOAD ; : 6502C 310 320 LOADR ; : 6502D 330 334 LOADR ; : 6502E 335 342 LOADR ; \ ZP assignments $06 CONSTANT 'A $08 CONSTANT 'N 0 VALUE IPL 2 VALUE INDJ : IPH IPL 1+ ; : INDL INDJ 1+ ; : INDH INDL 1+ ; ( ----- 002 ) \ 6502 assembler, Addressing modes. \ output: n n-is-2b opoff : # ( n ) 0 $09 ; \ Immediate : <> ( n ) 0 $05 ; \ ZeroPage : ( n ) 0 $15 ; \ ZeroPage+X : ( n ) 0 $15 ; \ Only for LDX : () ( n ) 1 $0d ; \ Absolute : (X+) ( n ) 1 $1d ; \ Absolute+X : (Y+) ( n ) 1 $19 ; \ Absolute+Y : [X+] ( n ) 0 $01 ; \ Indirect+X : []Y+ ( n ) 0 $11 ; \ Indirect+Y : ?, ( n n-is-2b -- ) IF L, ELSE C, THEN ; ( ----- 003 ) \ 6502 asm, Groups 1 and 2, 3-with-AM : OPG1 DOER C, DOES> C@ OR C, ?, ; $60 OPG1 ADC, $20 OPG1 AND, $c0 OPG1 CMP, $40 OPG1 EOR, $a0 OPG1 LDA, $00 OPG1 ORA, $e0 OPG1 SBC, $80 OPG1 STA, : _09repl DUP $09 = IF DROP 1 THEN ; : OPG2 DOER C, DOES> C@ SWAP _09repl OR 1+ C, ?, ; $00 OPG2 ASL, $c0 OPG2 DEC, $e0 OPG2 INC, $a0 OPG2 LDX, $40 OPG2 LSR, $20 OPG2 ROL, $60 OPG2 ROR, $80 OPG2 STX, : OPG3 DOER C, DOES> C@ SWAP _09repl OR 1- C, ?, ; $20 OPG3 BIT, $e0 OPG3 CPX, $c0 OPG3 CPY, $a0 OPG3 LDY, $80 OPG3 STY, ( ----- 004 ) \ 6502 asm, implied, branching : OP DOER C, DOES> C@ C, ; $0a OP ASLA, $00 OP BRK, $18 OP CLC, $d8 OP CLD, $58 OP CLI, $b8 OP CLV, $ca OP DEX, $88 OP DEY, $e8 OP INX, $c8 OP INY, $4a OP LSRA, $ea OP NOP, $48 OP PHA, $08 OP PHP, $68 OP PLA, $28 OP PLP, $2a OP ROLA, $6a OP RORA, $40 OP RTI, $60 OP RTS, $38 OP SEC, $f8 OP SED, $78 OP SEI, $aa OP TAX, $a8 OP TAY, $98 OP TYA, $ba OP TSX, $8a OP TXA, $9a OP TXS, : OPBR DOER C, DOES> C@ C, C, ; $90 OPBR BCC, $b0 OPBR BCS, $f0 OPBR BEQ, $30 OPBR BMI, $d0 OPBR BNE, $10 OPBR BPL, $50 OPBR BVC, $70 OPBR BVS, : OPBR2 DOER C, DOES> C@ C, L, ; $20 OPBR2 JSR, $4c OPBR2 JMP, $6c OPBR2 JMP[], ( ----- 005 ) \ 6502 HAL ALIAS JMP, JMPi, ALIAS JMP[], JMP(i), ALIAS JSR, CALLi, : JRi, CLV, BVC, ; \ no BRA! ALIAS BEQ, JRZi, ALIAS BNE, JRNZi, ALIAS BCS, JRCi, ALIAS BCC, JRNCi, : i>, DEX, DEX, DUP # LDA, 0 STA, >>8 # LDA, 1 STA, ; : (i)>, DEX, DEX, DUP () LDA, 0 STA, 1+ () LDA, 1 STA, ; ( ----- 009 ) \ 6502 port macros \ helpers : PS<>, ( src dst ) SWAP LDA, STA, ; : PSCLR16, 0 # LDA, DUP STA, 1+ STA, ; : A>IND+, INDL []Y+ STA, INY, ; : PS>A, LDA, ; : A>PS, STA, ; : PSINC, 0 INC, IFZ, 1 INC, THEN, ; : IP+, IPL <> INC, 2 BNE, IPH <> INC, ; ( ----- 010 ) \ 6502 boot code PS=X RS=S 0 JMP, 9 ALLOT0 \ STABLE ABI PC XORG $01 ( main jmp ) + T! $6c # LDA, INDJ <> STA, $ff # LDX, TXS, BIN( $04 + JMP[], \ BOOT LSET lblcell DEX, DEX, PLA, 0 A>PS, PLA, 1 A>PS, PSINC, \ next LSET lblnext IPH <> LDY, IPL <> LDA, INDH <> STY, INDL <> STA, LSET L1 CLC, 2 # ADC, IFC, INY, THEN, IPL <> STA, IPH <> STY, INDJ JMP, LSET lblxt PLA, INDL <> STA, PLA, INDH <> STA, IPH <> LDA, PHA, IPL <> LDA, PHA, INDL <> INC, IFZ, INDH <> INC, THEN, INDL <> LDA, INDH <> LDY, L1 JMP, LSET lbldoes CLC, PLA, TAY, PLA, INY, IFZ, 1 # ADC, THEN, INDL <> STY, INDH <> STA, DEX, DEX, 1 STA, TYA, 2 # ADC, IFC, 1 INC, THEN, 0 STA, INDJ JMP, ( ----- 011 ) CODE BYE BRK, CODE QUIT TXA, $ff # LDX, TXS, TAX, BIN( $0a ( main ) + JMP[], CODE ABORT $ff # LDX, X' QUIT BR BNE, CODE EXIT PLA, IPL <> STA, PLA, IPH <> STA, ;CODE CODE EXECUTE 0 LDA, INDL <> STA, 1 LDA, INDH <> STA, INX, INX, INDL JMP[], CODE SCNT INDL <> STX, DEX, DEX, 0 # LDA, 1 STA, $ff # LDA, SEC, INDL <> SBC, 0 STA, ;CODE CODE RCNT TXA, TSX, INDL <> STX, TAX, DEX, DEX, 0 # LDA, 1 STA, $ff # LDA, SEC, INDL <> SBC, 0 STA, ;CODE ( ----- 012 ) CODE (b) 0 # LDY, IPL []Y+ LDA, DEX, DEX, 0 A>PS, 0 # LDA, 1 A>PS, IP+, ;CODE CODE (n) 0 # LDY, IPL []Y+ LDA, DEX, DEX, 0 A>PS, INY, IPL []Y+ LDA, 1 A>PS, IP+, IP+, ;CODE CODE (br) 0 # LDY, IPL []Y+ LDA, FJR BPL, IPH <> DEC, THEN, CLC, IPL <> ADC, IFC, IPH <> INC, THEN, IPL <> STA, ;CODE CODE (?br) 0 LDA, 1 ORA, INX, INX, 0 # ORA, X' (br) BR BEQ, IP+, ;CODE CODE (next) PLA, TAY, IFZ, \ ovfl, always jump PLA, SEC, 1 # SBC, PHA, $ff # LDA, PHA, X' (br) JMP, THEN, DEY, IFNZ, ( no zero, jump ) TYA, PHA, X' (br) JMP, THEN, PLA, IFNZ, PHA, 0 # LDA, PHA, X' (br) JMP, THEN, ( finished! ) IP+, ;CODE ( ----- 013 ) CODE C@ 0 [X+] LDA, 0 STA, 0 # LDA, 1 STA, ;CODE CODE @ LSET L1 0 [X+] LDA, TAY, PSINC, 0 [X+] LDA, 0 STY, 1 STA, ;CODE LSET lblval DEX, DEX, PLA, 0 A>PS, PLA, 1 A>PS, PSINC, L1 JMP, CODE C! 2 LDA, 0 [X+] STA, INX, INX, INX, INX, ;CODE CODE ! 2 LDA, 0 [X+] STA, PSINC, 3 LDA, 0 [X+] STA, INX, INX, INX, INX, ;CODE CODE 1+ PSINC, ;CODE CODE 1- 0 LDA, IFZ, 1 DEC, THEN, 0 DEC, ;CODE CODE + CLC, 2 LDA, 0 ADC, 2 STA, 3 LDA, 1 ADC, 3 STA, INX, INX, ;CODE CODE - 2 LDA, SEC, 0 SBC, 2 STA, 3 LDA, 1 SBC, 3 STA, INX, INX, ;CODE CODE < 3 PS>A, 1 CMP, IFZ, 2 PS>A, 0 CMP, THEN, INX, INX, 0 # LDA, 1 A>PS, 0 # ADC, 1 # EOR, 0 A>PS, ;CODE ( ----- 014 ) CODE << 0 ASL, 1 ROL, ;CODE CODE >> 1 LSR, 0 ROR, ;CODE CODE <<8 0 1 PS<>, 0 # LDA, 0 STA, ;CODE CODE >>8 1 0 PS<>, 0 # LDA, 1 STA, ;CODE CODE AND 0 LDA, 2 AND, 2 STA, 1 LDA, 3 AND, 3 STA, INX, INX, ;CODE CODE OR 0 LDA, 2 ORA, 2 STA, 1 LDA, 3 ORA, 3 STA, INX, INX, ;CODE CODE XOR 0 LDA, 2 EOR, 2 STA, 1 LDA, 3 EOR, 3 STA, INX, INX, ;CODE CODE NOT 0 # LDY, 0 LDA, 1 ORA, 1 STY, IFZ, INY, THEN, 0 STY, ;CODE ( ----- 015 ) CODE * DEX, DEX, 16 # LDY, 0 PSCLR16, BEGIN, 0 ASL, 1 ROL, 4 ASL, 5 ROL, IFC, CLC, 2 LDA, 0 ADC, 0 STA, 3 LDA, 1 ADC, 1 STA, THEN, DEY, BR BNE, 0 4 PS<>, 1 5 PS<>, INX, INX, INX, INX, ;CODE CODE /MOD \ a b -- r q DEX, DEX, DEX, 16 # LDA, 0 STA, ( cnt ) 1 PSCLR16, ( remaining ) \ 3-4 = divisor 5-6 = dividend BEGIN, 5 ASL, 6 ROL, 1 ROL, 2 ROL, 1 LDA, SEC, 3 SBC, TAY, 2 LDA, 4 SBC, IFC, 2 STA, 1 STY, 5 INC, THEN, 0 DEC, BR BNE, 5 3 PS<>, 6 4 PS<>, 1 5 PS<>, 2 6 PS<>, INX, INX, INX, ;CODE ( ----- 016 ) CODE DUP LSET L1 DEX, DEX, 2 0 PS<>, 3 1 PS<>, ;CODE CODE ?DUP 0 LDA, 1 ORA, L1 BR BNE, ;CODE CODE DROP INX, INX, ;CODE CODE SWAP 0 LDA, 2 LDY, 0 STY, 2 STA, 1 LDA, 3 LDY, 1 STY, 3 STA, ;CODE CODE OVER DEX, DEX, 4 0 PS<>, 5 1 PS<>, ;CODE CODE ROT ( a b c -- b c a ) 5 LDY, 3 5 PS<>, 1 3 PS<>, 1 STY, 4 LDY, 2 4 PS<>, 0 2 PS<>, 0 STY, ;CODE CODE ROT> ( a b c -- c a b ) 1 LDY, 3 1 PS<>, 5 3 PS<>, 5 STY, 0 LDY, 2 0 PS<>, 4 2 PS<>, 4 STY, ;CODE CODE R@ DEX, DEX, PLA, 0 STA, TAY, PLA, 1 STA, PHA, TYA, PHA, ;CODE CODE >R 1 LDA, PHA, 0 LDA, PHA, INX, INX, ;CODE CODE R> DEX, DEX, PLA, 0 STA, PLA, 1 STA, ;CODE CODE R~ PLA, PLA, ;CODE ( ----- 017 ) CODE [C]? ( c a u -- i ) $ff # LDY, 0 PS>A, 'N <> STA, 2 PS>A, INDL <> STA, 3 PS>A, INDH <> STA, 4 PS>A, INX, INX, INX, INX, BEGIN, INY, 'N <> CPY, IFZ, $ff # LDA, 0 A>PS, 1 A>PS, ;CODE THEN, INDL []Y+ CMP, BR BNE, ( match! ) 0 STY, ;CODE CODE JMPi! ( pc a -- len ) $4c # LDA, PHA, LSET L1 0 PS>A, INDL <> STA, 1 PS>A, INDH <> STA, 0 # LDY, PLA, A>IND+, 2 PS>A, A>IND+, 3 PS>A, A>IND+, INX, INX, 0 STY, 0 # LDA, 1 A>PS, ;CODE CODE CALLi! $20 # LDA, PHA, L1 BR BNE, CODE i>! ( i a -- len ) 0 PS>A, INDL <> STA, 1 PS>A, INDH <> STA, 0 # LDY, $ca # LDA, A>IND+, A>IND+, $a9 # LDA, A>IND+, 3 PS>A, A>IND+, $95 # LDA, A>IND+, 1 # LDA, A>IND+, $a9 # LDA, A>IND+, 2 PS>A, A>IND+, $95 # LDA, A>IND+, 0 # LDA, A>IND+, INX, INX, 1 A>PS, 10 # LDA, 0 A>PS, ;CODE ( ----- 018 ) LSET L1 \ cmp strs at [INDL] and ['N] with cnt 0 # LDY, BEGIN, INDL []Y+ LDA, 'N []Y+ CMP, IFNZ, RTS, THEN, INY, 0 DEC, BR BNE, RTS, CODE []= ( a1 a2 u -- f ) 2 LDA, INDL <> STA, 3 LDA, INDH <> STA, 4 LDA, 'N <> STA, 5 LDA, 'N 1+ <> STA, 0 4 PS<>, 1 LDY, INY, 5 STY, INX, INX, INX, INX, BEGIN, L1 JSR, IFNZ, ( fail ) 0 PSCLR16, ;CODE THEN, 1 DEC, BR BNE, ( success ) 0 INC, ;CODE ( ----- 019 ) CODE FIND ( sa sl -- w? f ) \ 0=cnt 1=sl 2-3=curword N=sa 2 LDA, 'N <> STA, 3 LDA, 'N 1+ <> STA, 0 1 PS<>, SYSVARS $02 + DUP () LDA, 2 STA, 1+ () LDA, 3 STA, BEGIN, 3 LDA, INDH <> STA, 2 LDA, SEC, 3 # SBC, IFNC, INDH <> DEC, THEN, INDL <> STA, 0 # LDY, INDL []Y+ LDA, PHA, INY, INDL []Y+ LDA, PHA, \ prev INY, INDL []Y+ LDA, $7f # AND, 1 CMP, IFZ, 0 STA, INDL <> LDA, SEC, 0 SBC, INDL <> STA, IFNC, INDH <> DEC, THEN, L1 JSR, IFZ, \ match PLA, PLA, 0 # LDY, 1 STY, INY, 0 STY, ;CODE THEN, THEN, PLA, 3 STA, PLA, 2 STA, 3 ORA, IFZ, \ end INX, INX, 0 STA, 1 STA, ;CODE THEN, JMP, ( ----- 020 ) CODE A> DEX, DEX, 'A <> LDA, 0 A>PS, 'A 1+ <> LDA, 1 A>PS, ;CODE CODE >A 0 PS>A, 'A <> STA, 1 PS>A, 'A 1+ <> STA, INX, INX, ;CODE CODE A>R 'A 1+ <> LDA, PHA, 'A <> LDA, PHA, ;CODE CODE R>A PLA, 'A <> STA, PLA, 'A 1+ <> STA, ;CODE CODE A+ 'A <> INC, IFZ, 'A 1+ <> INC, THEN, ;CODE CODE A- 'A <> LDA, IFZ, 'A 1+ <> DEC, THEN, 'A <> DEC, ;CODE CODE AC@ DEX, DEX, 0 # LDY, 1 STY, 'A []Y+ LDA, 0 A>PS, ;CODE CODE AC! 0 # LDY, 0 PS>A, 'A []Y+ STA, INX, INX, ;CODE ( ----- 030 ) \ 6502 disassembler \ order below represent "opid", also used in emulator CREATE OPNAME ," ORAANDEORADCSTALDACMPSBC" \ 1/5/9/d x8 ," ASLROLLSRRORSTXLDXDECINC" \ 6/a/e x8 ," BITJMPSTYLDYCPYCPX" \ 4/c x6 ," BRKBPLJSRBMIRTIBVCRTSBVSBCCLDYBCSCPYBNECPXBEQ" \ 0 x15 ," PHPCLCPLPSECPHACLIPLASEIDEYTYATAYCLVINYCLDINXSED" \ 8 x16 ," TXATXSTAXTSXDEXNOP" \ a x6 59 CONSTANT OPCNT $ff CONSTANT NUL 20 VALUE DISCNT : >>4 >> >> >> >> ; : opid. DUP OPCNT < IF 3 * OPNAME + 3 STYPE ELSE DROP ." ???" THEN ; : WORDTBL ( n -- ) CREATE >R BEGIN ' , NEXT ; : spcs ( n -- ) >R BEGIN SPC> NEXT ; ( ----- 031 ) : id159d ( opcode -- opid ) DUP $89 = IF DROP NUL ELSE >>4 >> THEN ; CREATE _ 24 nC, $c $c $d $d $e $e $f $f $35 $36 $37 $38 $39 NUL $3a NUL $c NUL $d $d $e $e $f $f : id6ae DUP $80 < IF ( ASL/ROL/LSR/ROR ) DUP $1f AND $1a = IF DROP NUL EXIT THEN >>4 >> 8 + EXIT THEN DUP >> >> 1- 3 AND 8 * _ + ( op tbl ) SWAP >>4 7 AND + C@ ; CREATE _ 32 nC, NUL NUL $10 NUL NUL NUL NUL NUL $12 $12 $13 $13 $14 $14 $15 NUL NUL NUL $10 NUL $11 NUL $11 NUL $12 NUL $13 $13 $14 NUL $15 NUL : id4c _ OVER $8 AND IF $10 + THEN SWAP >>4 + C@ ; : idnul DROP NUL ; : id0 >>4 DUP 8 = IF DROP NUL EXIT THEN DUP 8 > IF 1- THEN 22 + ; : id8 >>4 37 + ; ( ----- 032 ) : id2 $a2 = IF $0d ELSE NUL THEN ; 16 WORDTBL _ id0 id159d id2 idnul id4c id159d id6ae idnul id8 id159d id6ae idnul id4c id159d id6ae idnul : opid DUP $f AND << _ + @ EXECUTE ; \ 0=inh 1=imm 2=acc 3=zp 4=zp,X 5=zp,Y 6=abs 7=abs,X 8=abs,Y \ 9=ind 10=ind,X 11=ind,Y 12=rel CREATE _ $40 nC, 0 10 1 0 3 3 3 0 0 1 2 0 6 6 6 0 12 11 0 0 4 4 4 0 0 8 0 0 7 7 7 0 1 10 1 0 3 3 3 0 0 1 0 0 6 6 6 0 12 11 0 0 4 4 4 0 0 8 0 0 7 7 7 0 : modeid ( opcode -- id ) DUP $20 = IF DROP 6 EXIT THEN DUP $6c = IF DROP 9 EXIT THEN DUP $be = IF DROP 8 EXIT THEN DUP $80 AND >> >> SWAP $1f AND OR _ + C@ ; ( ----- 033 ) : inh. ( a -- a ) 7 spcs ; : byte. C@+ .x ; : $. '$' EMIT byte. ; : zp. $. 4 spcs ; ALIAS zp. rel. : imm. '#' EMIT byte. 4 spcs ; : $$. '$' EMIT C@+ SWAP C@+ .x SWAP .x ; : abs. $$. 2 spcs ; : ind. '(' EMIT $$. ')' EMIT ; : acc. 'A' EMIT 6 spcs ; : ,X. ',' EMIT 'X' EMIT ; : ,Y. ',' EMIT 'Y' EMIT ; : zp,X. $. ,X. 2 spcs ; : zp,Y. $. ,Y. 2 spcs ; : abs,X. $$. ,X. ; : abs,Y. $$. ,Y. ; : ind,X. '(' EMIT $. ,X. ')' EMIT ; : ind,Y. '(' EMIT $. ')' EMIT ,Y. ; 13 WORDTBL _ inh. imm. acc. zp. zp,X. zp,Y. abs. abs,X. abs,Y. ind. ind,X. ind,Y. rel. ( ----- 034 ) : mode. ( a opcode -- a ) modeid << _ + @ EXECUTE ; : op. ( a -- a ) C@+ DUP opid DUP opid. SPC> OPCNT < IF mode. ELSE DROP THEN ; : dump ( a u -- ) >R BEGIN C@+ .x SPC> NEXT DROP ; : dis ( a -- ) DISCNT >R BEGIN DUP ORG - BIN( + .X SPC> DUP op. SPC> TUCK OVER - dump NL> NEXT DROP ; ( ----- 035 ) \ 6502 emulator CREATE 'A 7 ALLOT 'A 1+ CONSTANT 'X 'X 1+ CONSTANT 'Y 'Y 1+ CONSTANT 'S 'S 1+ CONSTANT 'P 'P 1+ CONSTANT 'PC 0 VALUE EA \ effective addr in *target*. ffff means accumulator $800 CONSTANT MEMSZ \ 2k ought to be enough for anybody CREATE MEM MEMSZ ALLOT : 6502E$ 0 'P C! $200 'PC ! ; : oor? ( pc -- pc ) DUP MEMSZ >= IF .X ABORT" addr out of range" THEN ; : mem+ oor? MEM + ; : ea@ EA $ffff = IF 'A ELSE EA mem+ THEN ; : mc@ mem+ C@ ; : mc@+ DUP mc@ SWAP 1+ SWAP ; : mc! mem+ C! ; : m@ mem+ @ ; : m@+ DUP m@ SWAP 1+ 1+ SWAP ; : X+ 'X C@ + ; : Y+ 'Y C@ + ; : a@ 'A C@ ; : a! 'A C! ; : pc@ 'PC @ ; : mpc@ pc@ mem+ ; ( ----- 036 ) : ea! ( pc -- ) oor? [TO] EA ; : inh ( pc -- pc+? ) 0 ea! ; ALIAS inh acc : zp mc@+ ea! ; : imm DUP ea! 1+ ; : abs m@+ ea! ; : ind m@+ m@ ea! ; : zp,X mc@+ X+ <<8 >>8 ea! ; : zp,Y mc@+ Y+ <<8 >>8 ea! ; : abs,X m@+ X+ oor? ea! ; : abs,Y m@+ Y+ oor? ea! ; : ind,X mc@+ X+ m@ ea! ; : ind,Y mc@+ m@ Y+ ea! ; 13 WORDTBL _ inh imm acc zp zp,X zp,Y abs abs,X abs,Y ind ind,X ind,Y imm : eard ( pc opcode -- pc+? ) modeid << _ + @ EXECUTE ; ( ----- 037 ) : p! ( n mask -- ) 'P C@ AND OR 'P C! ; : carry! ( n -- n ) L|M NOT NOT ( n cf ) $fe p! ; : carry? ( -- f ) 'P C@ 1 AND ; : nz! ( n -- ) DUP NOT << SWAP $80 AND OR $7d p! ; : v! ( n -- ) $80 AND a@ $80 AND XOR >> $bf p! ; : a!nz DUP a! nz! ; : a!nzv DUP v! a!nz ; : ora EA mc@ a@ OR a!nz ; : and EA mc@ a@ AND a!nz ; : eor EA mc@ a@ XOR a!nz ; : adc EA mc@ carry? + a@ + carry! a!nzv ; : sbc a@ EA mc@ carry? + - carry! a!nzv ; : asl ea@ DUP C@ << carry! DUP nz! SWAP C! ; : rol ea@ DUP C@ << carry? OR carry! DUP nz! SWAP C! ; ( ----- 038 ) : lsr ea@ DUP C@ DUP 1 AND $fe p! >> DUP nz! SWAP C! ; : ror ea@ DUP C@ carry? <<8 OR DUP 1 AND $fe p! >> DUP nz! SWAP C! ; : _ DOER , DOES> @ C@ ea@ C! ; 'A _ sta 'X _ stx 'Y _ sty : _ DOER , DOES> @ EA mc@ DUP nz! SWAP C! ; 'A _ lda 'X _ ldx 'Y _ ldy : _ DOER , DOES> @ C@ EA mc@ - carry! DUP v! nz! ; 'A _ cmp 'X _ cpx 'Y _ cpy : pc+ea EA mc@ DUP $7f > IF $ff00 OR THEN 'PC @ + 'PC ! ; : _ DOER C, DOES> C@ 'P C@ AND IF pc+ea THEN ; $01 _ bcs $02 _ beq $40 _ bvs $80 _ bmi : _ DOER C, DOES> C@ 'P C@ AND NOT IF pc+ea THEN ; $01 _ bcc $02 _ bne $40 _ bvc $80 _ bpl ( ----- 039 ) : _ DOER C, DOES> C@ 'P C@ OR 'P C! ; $01 _ sec $08 _ sed $04 _ sei $10 _ brk : _ DOER C, DOES> C@ 'P C@ AND 'P C! ; $fe _ clc $f7 _ cld $fb _ cli $bf _ clv : pull ( -- b ) 'S C@ $100 OR mc@+ SWAP 'S C! ; : push ( b -- ) 'S C@ 1- <<8 >>8 DUP 'S C! $100 OR mc! ; : pla pull 'A C! ; : plp pull 'P C! ; : pha a@ push ; : php 'P C@ push ; : rti plp pull pull <<8 OR 'PC ! ; : rts pull pull <<8 OR 1+ 'PC ! ; : jmp EA 'PC ! ; : jsr pc@ 1- L|M push push jmp ; : bit EA mc@ DUP a@ AND NOT << OR $cd p! ; ( ----- 040 ) : inc EA mc@ 1+ DUP nz! EA mc! ; : dec EA mc@ 1- DUP nz! EA mc! ; : dex 'X C@ 1- DUP nz! 'X C! ; : dey 'Y C@ 1- DUP nz! 'Y C! ; : inx 'X C@ 1+ DUP nz! 'X C! ; : iny 'Y C@ 1+ DUP nz! 'Y C! ; : txa 'X C@ 'A C! ; : tax 'A C@ 'X C! ; : tya 'Y C@ 'A C! ; : tay 'A C@ 'Y C! ; : txs 'X C@ 'S C! ; : tsx 'S C@ 'X C! ; ALIAS NOOP nop ( ----- 041 ) \ opid same as in disassembler OPCNT WORDTBL _ ora and eor adc sta lda cmp sbc asl rol lsr ror stx ldx dec inc bit jmp sty ldy cpy cpx brk bpl jsr bmi rti bvc rts bvs bcc ldy bcs cpy bne cpx beq php clc plp sec pha cli pla sei dey tya tay clv iny cld inx sed txa txs tax tsx dex nop : nulop ( op -- ) .x ABORT" invalid opcode" ; : oprun ( opcode -- ) opid DUP OPCNT < IF << _ + @ EXECUTE ELSE nulop THEN ; CREATE _ ," AXYSP" : cpu. _ >A 'A >B 5 >R BEGIN AC@+ EMIT SPC> B> C@ .x B+ SPC> NEXT ." PC " 'PC @ .X NL> ; ( ----- 042 ) 2 VALUES VERBOSE 'BRK? : BRK? 'BRK? DUP IF EXECUTE THEN ; : run1 ( -- ) 'P C@ $10 AND IF ABORT" CPU halted" THEN 'PC @ mc@+ TUCK eard 'PC ! oprun VERBOSE IF cpu. THEN BRK? IF ABORT" breakpoint reached" THEN ; : runN >R BEGIN run1 NEXT ; : run BEGIN run1 AGAIN ; ( ----- 050 ) \ play around with emulator: ARCHM 6502A 6502D 6502E 6502E$ 1 TO VERBOSE HERE MEM $200 + 'HERE ! $203 JMP, $02 # LDA, TAY, $12 # ADC, 1 <> SBC, BRK, 'HERE ! ( ----- 051 ) \ xcomp for emulated 6502 machine $200 TO BIN( ( ----- 052 ) \ extra words for emulating COS. Load after 6502E : pullX ( -- b ) 'X C@ mc@+ SWAP 'X C! ; : pushX ( b -- ) 'X C@ 1- <<8 >>8 DUP 'X C! mc! ; ( ----- 053 ) \ test 6502 bare native words under emulator \ do regular xcomp until *before* blk containing BOOT. \ then load this. Copy to emul's MEM+$200 then run. \ toPC with ORG+04 will get you to BOOT. then, toBRK CODE BOOT 42 i>, $1234 i>, INLINE + BRK, XCURRENT XORG $04 + T! ( ----- 054 ) \ same as prev block, but BOOT is a XT word : BOOT INIT 'X' (emit) 'Y' (emit) BYE ; XCURRENT XORG $04 + T! ( ----- 055 ) \ drivers for 6502 emulator. simply emit in memory at page $700 \ $7ff contains the current emit position. CODE (emit) 0 LDA, INX, INX, $7ff () LDY, $700 (Y+) STA, $7ff () INC, ;CODE CODE INIT 0 # LDA, $7ff () STA, ;CODE ( ----- 060 ) \ Apple IIe drivers, (key?) CODE (key?) ( -- c? f ) DEX, DEX, 0 # LDA, 0 A>PS, 1 A>PS, $c000 () LDA, FJR BPL, $7f # AND, 0 A>PS, DEX, DEX, 0 # LDA, 1 A>PS, 1 # LDA, 0 A>PS, $c010 () STA, THEN, ;CODE ( ----- 061 ) \ Apple IIe drivers, grid 2 CONSTS 80 COLS 24 LINES CODE 80col $c300 JSR, ;CODE : pos2yx ( pos -- yx ) COLS /MOD ( x y ) <<8 OR ; CODE yx2a ( yx -- a ) $c054 () STA, 1 PS>A, CLC, RORA, 0 ROR, IFNC, $c055 () STA, THEN, PHA, 3 # AND, 4 # ORA, 1 A>PS, PLA, $0c # AND, IFNZ, 8 # CMP, 40 # LDA, IFC, CLC, ROLA, THEN, 0 ADC, 0 A>PS, THEN, ;CODE CODE hi ( c pos ) 2 PS>A, $7f # AND, 2 A>PS, ;CODE CODE lo ( c pos ) 2 PS>A, $80 # ORA, 2 A>PS, ;CODE : CELL! ( c pos ) pos2yx yx2a lo C! ; : CURSOR! ( new old -- ) pos2yx yx2a DUP C@ SWAP lo C! pos2yx yx2a DUP C@ SWAP hi C! ; ( ----- 062 ) \ Apple IIe drivers, Floppy Drive \ NOTE: this write 3 bytes over allocated space after N. This \ might be a problem depending on how variables are arranged. CODE _p ( blkno addr -- ) \ blkno = ProDOS 512b blk! 3 # LDA, 'N <> STA, $60 # LDA, 'N 1+ <> STA, 0 LDA, 'N 2 + <> STA, 1 LDA, 'N 3 + <> STA, 2 LDA, 'N 4 + <> STA, 3 LDA, 'N 5 + <> STA, INX, INX, INX, INX, ;CODE : _e LIT" FDErr " STYPE .x ABORT ; LSET L1 DEX, DEX, 0 STA, 0 # LDA, 1 STA, X' _e JMP, CODE _r $bf00 JSR, $80 C, 'N L, L1 BR BCS, ;CODE CODE _w $bf00 JSR, $81 C, 'N L, L1 BR BCS, ;CODE : FD@ ( blk blk( -- ) SWAP << TUCK 1+ OVER $200 + _p _r _p _r ; : FD! ( blk blk( -- ) SWAP << TUCK 1+ OVER $200 + _p _w _p _w ;