From 7aa99412baedc9da0b297113ec2ec813ac9190f6 Mon Sep 17 00:00:00 2001 From: Redo Date: Wed, 26 Jun 2024 11:37:29 -0600 Subject: [PATCH] remake assembler with customasm, misc, need to clean up --- arch-8608-template.asm | 5 + arch-8608.asm | 792 +++++++++++++++++++++++++++++ assembler-8608-deprecated.lua | 723 ++++++++++++++++++++++++++ assembler-8608.lua | 588 ++++----------------- bin-builder.lua | 70 +++ emulator/8608emulator.c | 15 +- emulator/8608emulator.dll | Bin 164507 -> 151643 bytes emulator/8608emulator.lua | 12 +- emulator/instructions_gen.c | 114 ++++- emulator/keycodes.lua | 2 + fullPath.bat | 1 + instructionList.txt | 58 ++- rom-8608.lua => rom-8608-build.lua | 85 +++- rom-8608-defs.lua | 486 +++++++++--------- 14 files changed, 2173 insertions(+), 778 deletions(-) create mode 100644 arch-8608-template.asm create mode 100644 arch-8608.asm create mode 100644 assembler-8608-deprecated.lua create mode 100644 bin-builder.lua create mode 100644 fullPath.bat rename rom-8608.lua => rom-8608-build.lua (69%) diff --git a/arch-8608-template.asm b/arch-8608-template.asm new file mode 100644 index 0000000..286747e --- /dev/null +++ b/arch-8608-template.asm @@ -0,0 +1,5 @@ + +; Instruction list (Auto-generated from rom-8608-defs.lua by rom-8608-build.lua) +#ruledef { + %s +} diff --git a/arch-8608.asm b/arch-8608.asm new file mode 100644 index 0000000..ff43bef --- /dev/null +++ b/arch-8608.asm @@ -0,0 +1,792 @@ + +; Instruction list (Auto-generated from rom-8608-defs.lua by rom-8608-build.lua) +#ruledef { + rst => $00 + hlt => $F0 + run => $F1 + int => $F2 + brk => $F3 + irt => $F4 + nop => $FF + ien => $F5 + idi => $F6 + inc p => $12 + dec p => $15 + inc q => $13 + dec q => $16 + inc a => $10 + dec a => $11 + icc a => $1B + inc b => $19 + dec b => $1A + icc b => $1C + inc c => $17 + dec c => $18 + icc c => $1D + tst a => $14 + tst b => $1E + tst c => $1F + inc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $2B @ value`8 + } + inc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $2B @ mvalue`8 + } + dec *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $2C @ value`8 + } + dec *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $2C @ mvalue`8 + } + icc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $2D @ value`8 + } + icc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $2D @ mvalue`8 + } + tst *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $2E @ value`8 + } + tst *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $2E @ mvalue`8 + } + adp {value: i8} => $4A @ value + adq {value: i8} => $4B @ value + ads {value: i8} => $4C @ value + adp b => $E6 + adq b => $E7 + ads b => $E8 + add {value: i8} => $24 @ value + adb {value: i8} => $72 @ value + adc {value: i8} => $73 @ value + sub {value: i8} => $70 @ value + sbb {value: i8} => $99 @ value + sbc {value: i8} => $9A @ value + acc {value: i8} => $78 @ value + scc {value: i8} => $79 @ value + cmp {value: i8} => $71 @ value + and {value: i8} => $74 @ value + ior {value: i8} => $75 @ value + xor {value: i8} => $76 @ value + ann {value: i8} => $77 @ value + shl {value: i8} => $D0 @ value + shr {value: i8} => $D1 @ value + rol {value: i8} => $D2 @ value + ror {value: i8} => $D3 @ value + sra {value: i8} => $D4 @ value + add *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $AE @ value`8 + } + add *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $AE @ mvalue`8 + } + adb *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $9B @ value`8 + } + adb *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $9B @ mvalue`8 + } + adc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $9C @ value`8 + } + adc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $9C @ mvalue`8 + } + sub *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $AF @ value`8 + } + sub *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $AF @ mvalue`8 + } + sbb *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $9D @ value`8 + } + sbb *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $9D @ mvalue`8 + } + sbc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $9E @ value`8 + } + sbc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $9E @ mvalue`8 + } + acc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B5 @ value`8 + } + acc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B5 @ mvalue`8 + } + scc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B7 @ value`8 + } + scc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B7 @ mvalue`8 + } + cmp *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B0 @ value`8 + } + cmp *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B0 @ mvalue`8 + } + and *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B1 @ value`8 + } + and *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B1 @ mvalue`8 + } + ior *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B2 @ value`8 + } + ior *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B2 @ mvalue`8 + } + xor *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B3 @ value`8 + } + xor *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B3 @ mvalue`8 + } + ann *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $B4 @ value`8 + } + ann *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $B4 @ mvalue`8 + } + shl *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $D5 @ value`8 + } + shl *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $D5 @ mvalue`8 + } + shr *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $D6 @ value`8 + } + shr *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $D6 @ mvalue`8 + } + rol *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $D7 @ value`8 + } + rol *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $D7 @ mvalue`8 + } + ror *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $D8 @ value`8 + } + ror *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $D8 @ mvalue`8 + } + sra *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $D9 @ value`8 + } + sra *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $D9 @ mvalue`8 + } + add b => $A0 + adc b => $9F + sub b => $A1 + sbc b => $B6 + acc b => $B8 + scc b => $B9 + cmp b => $A2 + and b => $A3 + ior b => $A4 + xor b => $A5 + ann b => $A6 + shl b => $DA + shr b => $DB + rol b => $DC + ror b => $DD + sra b => $DE + add c => $A7 + adb c => $BD + sub c => $A8 + sbb c => $BC + acc c => $BA + scc c => $BB + cmp c => $A9 + and c => $AA + ior c => $AB + xor c => $AC + ann c => $AD + shl c => $DF + shr c => $4D + rol c => $3E + ror c => $3F + sra c => $2F + adb a => $BE + sbb a => $BF + adc a => $4E + sbc a => $4F + jmp {value: i16} => $60 @ value + jsr {value: i16} => $63 @ value + jss {value: i16} => $E2 @ value + jmp p => $64 + jmp q => $66 + ret => $66 + jsr p => $65 + jsr q => $67 + jss p => $E4 + jss q => $E5 + rts => $E1 + jpr {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jpr: Relative jump target is too far away") + assert(reladdr >= -128, "jpr: Relative jump target is too far away") + $31 @ reladdr`8 + } + jnz {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jnz: Relative jump target is too far away") + assert(reladdr >= -128, "jnz: Relative jump target is too far away") + $30 @ reladdr`8 + } + jne {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jne: Relative jump target is too far away") + assert(reladdr >= -128, "jne: Relative jump target is too far away") + $30 @ reladdr`8 + } + jpz {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jpz: Relative jump target is too far away") + assert(reladdr >= -128, "jpz: Relative jump target is too far away") + $32 @ reladdr`8 + } + jeq {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jeq: Relative jump target is too far away") + assert(reladdr >= -128, "jeq: Relative jump target is too far away") + $32 @ reladdr`8 + } + jlt {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jlt: Relative jump target is too far away") + assert(reladdr >= -128, "jlt: Relative jump target is too far away") + $33 @ reladdr`8 + } + jge {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jge: Relative jump target is too far away") + assert(reladdr >= -128, "jge: Relative jump target is too far away") + $34 @ reladdr`8 + } + jgt {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jgt: Relative jump target is too far away") + assert(reladdr >= -128, "jgt: Relative jump target is too far away") + $35 @ reladdr`8 + } + jle {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "jle: Relative jump target is too far away") + assert(reladdr >= -128, "jle: Relative jump target is too far away") + $36 @ reladdr`8 + } + psh a => $40 + psh b => $44 + psh c => $45 + psh f => $E9 + psh p => $41 + psh q => $46 + pop a => $42 + pop b => $47 + pop c => $48 + pop f => $EA + pop p => $43 + pop q => $49 + psh {value: i8} => $3B @ value + phw {value: i16} => $3C @ value + lda {value: i8} => $20 @ value + ldb {value: i8} => $26 @ value + ldc {value: i8} => $27 @ value + lda *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $28 @ value`8 + } + lda *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $28 @ mvalue`8 + } + ldb *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $29 @ value`8 + } + ldb *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $29 @ mvalue`8 + } + ldc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $2A @ value`8 + } + ldc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $2A @ mvalue`8 + } + sta *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $96 @ value`8 + } + sta *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $96 @ mvalue`8 + } + stb *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $97 @ value`8 + } + stb *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $97 @ mvalue`8 + } + stc *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $98 @ value`8 + } + stc *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $98 @ mvalue`8 + } + lda *{value: i16} => $51 @ value + ldb *{value: i16} => $56 @ value + ldc *{value: i16} => $57 @ value + sta *{value: i16} => $50 @ value + stb *{value: i16} => $58 @ value + stc *{value: i16} => $59 @ value + lda *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $01 @ value`16 + } + lda *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $01 @ mvalue`16 + } + ldb *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $F7 @ value`16 + } + ldb *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $F7 @ mvalue`16 + } + ldc *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $FE @ value`16 + } + ldc *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $FE @ mvalue`16 + } + lda *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $EB @ value`16 + } + lda *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $EB @ mvalue`16 + } + ldb *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $08 @ value`16 + } + ldb *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $08 @ mvalue`16 + } + ldc *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $09 @ value`16 + } + ldc *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $09 @ mvalue`16 + } + sta *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0A @ value`16 + } + sta *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0A @ mvalue`16 + } + stb *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0B @ value`16 + } + stb *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0B @ mvalue`16 + } + stc *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0C @ value`16 + } + stc *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0C @ mvalue`16 + } + sta *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0D @ value`16 + } + sta *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0D @ mvalue`16 + } + stb *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0E @ value`16 + } + stb *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0E @ mvalue`16 + } + stc *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $0F @ value`16 + } + stc *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $0F @ mvalue`16 + } + lda *p => $53 + ldb *p => $5E + ldc *p => $5F + lda *q => $55 + ldb *q => $61 + ldc *q => $62 + sta *p => $52 + stb *p => $5A + stc *p => $5B + sta *q => $54 + stb *q => $5C + stc *q => $5D + lda *p++ => $C6 + ldb *p++ => $C7 + ldc *p++ => $C8 + lda *q++ => $C9 + ldb *q++ => $CA + ldc *q++ => $CB + sta *p++ => $C0 + stb *p++ => $C1 + stc *p++ => $C2 + sta *q++ => $C3 + stb *q++ => $C4 + stc *q++ => $C5 + ldp {value: i16} => $21 @ value + ldq {value: i16} => $23 @ value + lds {value: i16} => $25 @ value + ldv {value: i16} => $22 @ value + ldp *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $7A @ value`8 + } + ldp *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $7A @ mvalue`8 + } + ldq *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $7B @ value`8 + } + ldq *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $7B @ mvalue`8 + } + stp *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $7E @ value`8 + } + stp *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $7E @ mvalue`8 + } + stq *s+{value: i8} => { + assert(value <= 127, "Relative address is too far away") + assert(value >= -128, "Relative address is too far away") + $7F @ value`8 + } + stq *s-{value: i8} => { + mvalue = -value + assert(mvalue <= 127, "Relative address is too far away") + assert(mvalue >= -128, "Relative address is too far away") + $7F @ mvalue`8 + } + ldp *{value: i16} => $68 @ value + ldq *{value: i16} => $6A @ value + stp *{value: i16} => $6C @ value + stq *{value: i16} => $6E @ value + ldp *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $EC @ value`16 + } + ldp *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $EC @ mvalue`16 + } + ldq *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $EE @ value`16 + } + ldq *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $EE @ mvalue`16 + } + ldp *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $F8 @ value`16 + } + ldp *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $F8 @ mvalue`16 + } + ldq *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $FA @ value`16 + } + ldq *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $FA @ mvalue`16 + } + stq *p+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $06 @ value`16 + } + stq *p-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $06 @ mvalue`16 + } + stp *q+{value: i16} => { + assert(value <= 32767, "Relative address is too far away") + assert(value >= -32768, "Relative address is too far away") + $FC @ value`16 + } + stp *q-{value: i16} => { + mvalue = -value + assert(mvalue <= 32767, "Relative address is too far away") + assert(mvalue >= -32768, "Relative address is too far away") + $FC @ mvalue`16 + } + ldp *p => $92 + ldq *p => $93 + ldp *q => $94 + ldq *q => $95 + stp *q => $7C + stq *p => $7D + ldq *p++ => $CC + ldp *q++ => $CD + stp *q++ => $CE + stq *p++ => $CF + lda b => $80 + lda c => $81 + ldb a => $82 + ldb c => $83 + ldc a => $84 + ldc b => $85 + lda pl => $86 + lda ph => $87 + lda ql => $88 + lda qh => $89 + ldb pl => $37 + ldc ph => $38 + ldb ql => $39 + ldc qh => $3A + ldp q => $8A + ldp s => $8B + ldp v => $8C + ldp i => $8D + ldp cb => $91 + ldq cb => $E0 + ldq p => $8E + lds p => $8F + ldv p => $90 +} diff --git a/assembler-8608-deprecated.lua b/assembler-8608-deprecated.lua new file mode 100644 index 0000000..cdea5e0 --- /dev/null +++ b/assembler-8608-deprecated.lua @@ -0,0 +1,723 @@ + +local function loadutf8table(fn) + local tt = {} + for l in io.lines(fn) do if l~="" then + local c, d = l:match("^([^ ]+) (.+)$") + local t = {}; for v in d:gmatch("[^ ]+") do table.insert(t, tonumber(v, 16)) end; + tt[c] = t + end end + return tt +end +local utf8table = loadutf8table((RelPath or "./").."utf8table.txt") + +local function trim(s) return s:gsub("^ +", ""):gsub(" +$", "").."" end +local function getutf8len(c) + local d = c:byte() + if bit.band(d, 0xE0)==0xC0 then return 2 + elseif bit.band(d, 0xF0)==0xE0 then return 3 + elseif bit.band(d, 0xF8)==0xF0 then return 4 + else error("invalid utf8 first byte: "..string.format("%02X", d)) end +end +local function validWordsFromInstrs(instrs) + local words = {} + for mnem, _ in pairs(instrs) do + for word in mnem:gmatch("[^ ]+") do + words[word] = true + end + end + return words +end +local function lobyte(n) return n%256 end +local function hibyte(n) return math.floor(n/256) end +local function decodeNumber(n) + n = trim(n) + local sign = 1; if n:sub(1, 1)=="-" then sign = -1; n = n:sub(2, #n); end; + if n:sub(1, 1)=="$" then return sign*(tonumber(n:sub(2, #n ), 16) or error("invalid hex number "..n)), math.ceil((#n-1)/2) + elseif n:sub(1, 2)=="0x" then return sign*(tonumber(n:sub(3, #n ), 16) or error("invalid hex number "..n)), math.ceil((#n-2)/2) + elseif n:sub(#n, #n)=="h" and n:find("^[0-9a-fA-F]+h$") then return sign*(tonumber(n:sub(1, #n-1), 16) or error("invalid hex number "..n)), math.ceil((#n-1)/2) + elseif n:sub(1, 2)=="0b" then return sign*(tonumber(n:sub(3, #n ), 2) or error("invalid binary number "..n)), math.ceil((#n-2)/8) + elseif n:sub(#n, #n)=="b" and n:find("^[01]+b$") then return sign*(tonumber(n:sub(1, #n-1), 2) or error("invalid binary number "..n)), math.ceil((#n-1)/8) + elseif n:sub(1, 3)=="lo(" and n:sub(#n, #n)==")" then return lobyte(decodeNumber(n:sub(4, #n-1))), 1 + elseif n:sub(1, 3)=="hi(" and n:sub(#n, #n)==")" then return hibyte(decodeNumber(n:sub(4, #n-1))), 1 + elseif n:find("^[0-9]+$") then + local v = sign*(tonumber(n) or error("invalid decimal number "..n)) + if v>=-128 and v<=255 then return v, 1 + elseif v>=-32768 and v<=65535 then return v, 2 + else error("out-of-range number "..v) end + else + return nil + end +end +local function mnemFromLine(line, instrs, validWords) + local imms = {} + local function addNum(n) + n = trim(n) + local val, len = decodeNumber(n) + assert(val and len, "invalid number "..n) + local linei8 = line:gsub(n, "imm8", 1, true):lower() + local linei16 = line:gsub(n, "imm16", 1, true):lower() + if len==1 and (not instrs[linei8]) and instrs[linei16] then len = 2 end + table.insert(imms, { val = val, len = len } ) + return " imm"..(len*8).." " + end + local function addLabel(n) + n = trim(n) + local len = 2 + local linei8 = line:gsub(n, "imm8", 1, true):lower() + if instrs[linei8] then len = 1 end + table.insert(imms, { label = n, len = len } ) + return " imm"..(len*8).." " + end + + local mnem = " "..line:gsub(" ", " ").." " + mnem = mnem:gsub("%- *", " %+%-") + mnem = mnem:gsub("([%*%+])", " %1 ") + mnem = mnem:gsub(" %-?%$[0-9a-fA-F]+ " , function(n) return addNum (n) end) + mnem = mnem:gsub(" %-?0x[0-9a-fA-F]+ " , function(n) return addNum (n) end) + mnem = mnem:gsub(" %-?0b[01]+ " , function(n) return addNum (n) end) + mnem = mnem:gsub(" %-?[0-9a-fA-F]+h " , function(n) if not validWords[trim(n)] then return addNum (n) end end) + mnem = mnem:gsub(" %-?[01]+b " , function(n) if not validWords[trim(n)] then return addNum (n) end end) + mnem = mnem:gsub(" %-?[0-9]+ " , function(n) if not validWords[trim(n)] then return addNum (n) end end) + mnem = mnem:gsub(" [a-zA-Z_][a-zA-Z0-9_%.]* ", function(n) if not validWords[trim(n)] then return addLabel(n) end end) + mnem = trim(mnem):gsub(" +", " "):lower() + + if not instrs[mnem] then mnem = mnem:gsub("%+ imm", "imm") end + + return mnem, imms +end +local function addByte(state, val, code) + assert(val>=-128 and val<=255, "invalid byte "..val) + assert(state.memory[state.curAddr]==nil, "overwriting memory at $"..string.format("%04X", state.curAddr)) + state.memory[state.curAddr] = val%256 + if code then state.codeMap[state.curAddr] = true end + state.curAddr = state.curAddr + 1 +end +local function addWord(state, val, code) + assert(val>=0 and val<=65535, "invalid word "..val) + addByte(state, math.floor(val/256), code) + addByte(state, val%256, code) +end +local function addSpace(state, len) + for i = 1, len do + assert(state.memory[state.curAddr]==nil, "overwriting memory at $"..string.format("%04X", state.curAddr)) + state.memory[state.curAddr] = false + state.curAddr = state.curAddr + 1 + end +end +local function assembleInstruction(line, state, instrs, validWords) + local mnem, imms = mnemFromLine(line, instrs, validWords) + local opcode = instrs[mnem] or error("invalid instruction \""..line.."\" (mnem \""..mnem.."\")") + local writeimms = true + local padlen = 0 + local isInstr + if type(opcode)=="function" then + padlen, writeimms = opcode(imms) + addSpace(state, padlen) + elseif opcode>=0 then + isInstr = true + addByte(state, opcode, isInstr) + end + if writeimms then + for _, imm in ipairs(imms) do + if imm.val then + if imm.len==1 then addByte(state, imm.val, isInstr) + elseif imm.len==2 then addWord(state, imm.val, isInstr) + else error("invalid imm len") end + elseif imm.label then + table.insert(state.labelReplacements, { + name = imm.label, + addr = state.curAddr, + len = imm.len, + rel = imm.len==1, + isCode = isInstr, + }) + state.curAddr = state.curAddr + imm.len + else error("invalid imm") end + end + end +end +local directiveFunctions = { + fn = function(state, fn) state.fileName = fn end, + ln = function(state, ln) state.lineNum = tonumber(ln) end, + org = function(state, addr) state.curAddr = decodeNumber(addr) or error("Invalid origin \""..addr.."\"") end, + align = function(state, alns) local aln = decodeNumber(alns); if state.curAddr % aln ~= 0 then state.curAddr = state.curAddr + (aln - state.curAddr%aln) end end, + define = true, + space = function(state, amts) local amt = decodeNumber(amts); state.curAddr = state.curAddr + amt; end, +} +local function postEvaluateExpression(expr, labels) + +end +local function assembleCode(code, instrs, uexprs) + local validWords = validWordsFromInstrs(instrs) + + local state = { + lineNum = 0, + fileName = "", + curAddr = 0, + memory = {}, + codeMap = {}, + labelReplacements = {}, + labelAddrs = {}, + } + + for line in code:gmatch("[^\n]+") do + line = trim(line) + if line:sub(1, 1)=="." then -- directive + local dir, rest = line:match("^%.([^ ]+) *(.*)$") + assert(dir and rest, "no directive on line "..line) + local dirf = directiveFunctions[dir] or error("invalid directive "..dir) + dirf(state, rest) + elseif line:sub(#line, #line)==":" then -- label + local name = line:sub(1, #line-1) + assert(not state.labelAddrs[name], "redefinition of label "..name) + state.labelAddrs[name] = state.curAddr + elseif line:find("[^ ]") then + assembleInstruction(line, state, instrs, validWords) + end + end + + for _, rep in ipairs(state.labelReplacements) do + local expr = uexprs[rep.name] + if expr then + local val = postEvaluateExpression(expr, state.labelAddrs) + if rep.len==1 then addByte(state, val, rep.isCode) + elseif rep.len==2 then addWord(state, val, rep.isCode) + else error("invalid expr replace len "..rep.len) end + else + local labelAddr = state.labelAddrs[rep.name] or error("no label named "..rep.name) + state.curAddr = rep.addr + if rep.len==1 then addByte(state, labelAddr-(rep.addr+1), rep.isCode) + elseif rep.len==2 then addWord(state, labelAddr , rep.isCode) + else error("invalid labelreplace len "..rep.len) end + end + end + + return state.memory, state.codeMap +end + +local function readFile(fn) + local fi, err = io.open(fn, "r") + if not fi then error("could not open file "..fn..": "..err) end + local text = fi:read("*a") + fi:close() + return text +end + +local function separateCommas(l) + local c = {}; for a in l:gmatch("[^,]+") do table.insert(c, trim(a)) end; return c; +end +local function evaluateExpression(expr, uexprs) + expr = expr:gsub("[^%+%-%*%/]+", function(word) + local val = decodeNumber(word) or error("invalid number in expression: "..word) + return val + end) + assert(not expr:find("[^a-zA-Z0-9_%(%)%+%-%*%/ \t\r\n]"), "invalid char in expression: "..expr) + local exprf = loadstring("return "..expr) + local eval = exprf() or error("invalid expr: "..expr) + return eval +end +local function preprocessCode(code) + code = "\n"..code.."\n" + + -- apply brace labels and scoped labels + local curscope = "" + local codet = {} + local wordt = {} + local lastword = "" + local function addword(word) + lastword = word + if word:sub(1, 1)=="." and not directiveFunctions[word:sub(2, #word)] then word = curscope..word end + table.insert(codet, word) + end + for i = 1, #code do + local c = code:sub(i, i) + if c:find("[%.a-zA-Z0-9_]") then table.insert(wordt, c) + else + if #wordt>0 then + addword(table.concat(wordt)) + wordt = {} + end + if c==":" and lastword:sub(1, 1)~="." and not lastword:find("_BRACE_") then + curscope = lastword + end + table.insert(codet, c) + end + end + + code = "\n"..table.concat(codet).."\n" + + -- apply function macros + local funcmacros = {} + code = code:gsub(".define ([%.a-zA-Z0-9_]+)%(([^%)]+)%) ([^\n]+)", function(name, args, repl) + local argt = separateCommas(args) + for argidx, arg in ipairs(argt) do assert(not arg:find("[^a-zA-Z0-9_]"), "invalid character in macro arg name: "..name.." "..arg) end + repl = " "..repl.." " + local invoc = 0 + funcmacros[name] = function(b, callargs) + invoc = invoc + 1 + local callargt = separateCommas(callargs) + local callrepl = repl + for argidx, arg in ipairs(argt) do + local callarg = callargt[argidx] + callrepl = callrepl:gsub("([^a-zA-Z0-9_])"..arg.."([^a-zA-Z0-9_])", "%1"..callarg.."%2") + end + callrepl = callrepl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_") + return b..callrepl + end + return "" + end) + for name, replf in pairs(funcmacros) do code = code:gsub("([^a-zA-Z0-9_])"..name.." *%(([^%)]+)%)", replf) end + + -- apply simple macros + local simplemacros = {} + code = code:gsub("%.define +([%.a-zA-Z0-9_]+) +([^\n]+)", function(name, repl) + assert(not simplemacros[name], "Redefinition of macro "..name) + simplemacros[name] = repl + return "" + end) + --for name, repl in pairs(simplemacros) do code = code:gsub(name, repl, 1, true) end + for name, repl in pairs(simplemacros) do + local invoc = 0 + code = code:gsub("([^a-zA-Z0-9_])"..name.."([^a-zA-Z0-9_])", function(b, a) + invoc = invoc+1 + return b..(repl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_"))..a + end) + print(name, code) + end + + code = code:gsub("\\\\", "\n") + + local uexprs = {} + + local codet = {} + local exprt = {} + local parenLevel = 0 + for i = 1, #code do + local c = code:sub(i, i) + if c=="(" then + if parenLevel>0 then table.insert(exprt, c) end + parenLevel = parenLevel+1 + elseif c==")" then + parenLevel = parenLevel-1 + if parenLevel==0 then + table.insert(codet, evaluateExpression(table.concat(exprt), uexprs)) + exprt = {} + else + table.insert(exprt, c) + end + else + if parenLevel==0 then table.insert(codet, c) + else table.insert(exprt, c) end + end + end + code = table.concat(codet) + + return code, uexprs +end +local function fixCode(code) + code = code:gsub(",", " ") + code = code:gsub(":([^\\/])", ":\n%1") + code = code:gsub("[ \t]+:", ":") + code = code:gsub("%]", " %] ") + code = code:gsub("%[", " %[ ") + code = code:gsub("%*", " %* ") + code = code:gsub("\n[ \t\r\n]*", "\n") + code = code:gsub(" +", " ") + + return code +end +local stringEscapes = { ["\\"] = "\\", ["n"] = "\n", ["r"] = "\r", ["t"] = "\t", ["0"] = "\0", ["\""] = "\"", ["\'"] = "\'", } +local prefixIdx = 0 +local function prefixCode(code, fn) -- fix strings, add line numbers + prefixIdx = prefixIdx + 1 + + local outt = {} + local outnextnl = {} + local linenum = 1 + local skipnl = false + local function last() return outt[#outt] end + local function out(c) assert(type(c)=="string"); table.insert(outt, c); end + local function outn(n) out("$"..string.format("%02X", n)) out("\\") end + local function outnext(c) assert(type(c)=="string"); table.insert(outnextnl, c); end + local state = "code" -- code, comment, string, stringesc, commentml + + local lastbracelabel = 0 + local function bracelabel() lastbracelabel = lastbracelabel+1; return "_BRACE_"..string.format("%02d", prefixIdx)..lastbracelabel.."_"; end + local bracestack = {} + local bracehasmid = {} + local lastnl = false + + local utf8str = "" + local utf8len = 0 + + local function newline() + lastnl = true + for _, v in ipairs(outnextnl) do + if v=="\n" and skipnl then out("\\") + else out(v) end + end; outnextnl = {}; + end + + out(".ln 1"); out("\n"); + local i = 1 + while i <= #code do + local c = code:sub(i, i) + local cn = code:sub(i+1, i+1) + local cp = code:sub(i-1, i-1) + + if state=="code" then + if c=="\r" then + elseif c=="\n" then -- (c=="/" and cn~="/" and cn~="*") + linenum = linenum+1 + if not skipnl then out("\n") out(".ln "..linenum); out("\n"); end + newline() + skipnl = false + elseif c=="#" or c==";" or (c=="/" and cn=="/") then state = "comment" + elseif c=="/" and cn=="*" then state = "commentml" + elseif c=="\t" or c==" " then if (not lastnl) then out(" ") end + elseif c=="\"" then state = "string" lastnl = false + elseif c=="\\" then skipnl = true; out("\\"); + elseif c==":" then out(c); if skipnl then out("\\") else out("\n") end; lastnl = true; + elseif c:find("^[a-zA-Z0-9_%.%$%(%)%*,%[%]%+%-%*%/]$") then out(c); lastnl = false + elseif c=="{" then + table.insert(bracestack, bracelabel()) + if not lastnl then out(bracestack[#bracestack].."MID") end + outnext(bracestack[#bracestack].."START:"); outnext("\n"); + elseif c=="}" then + if not lastnl then out(bracestack[#bracestack].."START") end + if not bracehasmid[#bracestack] then outnext(bracestack[#bracestack].."MID:"); outnext("\n"); end + outnext(bracestack[#bracestack].."END:"); outnext("\n"); + bracehasmid[#bracestack] = nil + bracestack[#bracestack] = nil + elseif c=="|" then + if not lastnl then out(bracestack[#bracestack].."END") end + outnext(bracestack[#bracestack].."MID:"); outnext("\n"); + bracehasmid[#bracestack] = true + else error("invalid char "..c) end + elseif state=="comment" then + if c=="\n" then state = "code" out("\n") newline() end + elseif state=="commentml" then + if c=="/" and cp=="*" then state = "code" end + elseif state=="string" then + if c=="\\" then state = "stringesc" + elseif c=="\"" then state = "code" + elseif c:byte()>=128 then + utf8str = c + utf8len = getutf8len(c) + state = "stringutf8" + else outn(c:byte()) end + elseif state=="stringesc" then + outn(string.byte(stringEscapes[c] or error("invalid escape "..c))); state = "string"; + elseif state=="stringutf8" then + utf8str = utf8str..c + if #utf8str == utf8len then + local valt = utf8table[utf8str] + if not valt then local datastr = ""; for i = 1, #utf8str do datastr = datastr .. string.format("%02X ", utf8str:sub(i, i):byte()) end; + error("Unrecognized UTF-8 character: "..datastr); end + for i, v in ipairs(valt) do outn(v) end + state = "string" + end + end + + i = i+1 + end + assert(#bracestack==0, "unclosed brace") + local code2 = table.concat(outt) + + return code2 +end +local function fixFilename(fn) + fn = fn:gsub("[^a-zA-Z0-9_]", "_") + return fn +end +local function includeFile(fn) + local code = readFile(fn) + code = prefixCode(code, fn) + local fnf = fixFilename(fn) + code = ".fn "..fnf.."\n"..code + code = code:gsub(".include ([^\r\n]+)", function(fn2) + fn2 = fn:gsub("[^\\/]+$", "")..fn2 + return "\n"..includeFile(fn2).."\n"..".fn "..fnf.."\n" + end) + return code +end +local function instrsFromArch(arch) + local function arraySize(imms) local s = 1; for i = 1, #imms do s = s*(imms[i].val or error("invalid array size")) end; return s; end + local instrs = { + imm8 = function() return 0, true end, + imm16 = function() return 0, true end, + byte = function() return 1, false end, + word = function() return 2, false end, + ["byte imm8"] = function() return 0, true end, + ["word imm16"] = function() return 0, true end, + ["byte [ imm8 ]" ] = function(imms) return arraySize(imms) , false end, + ["byte [ imm16 ]"] = function(imms) return arraySize(imms) , false end, + ["word [ imm8 ]" ] = function(imms) return arraySize(imms)*2, false end, + ["word [ imm16 ]"] = function(imms) return arraySize(imms)*2, false end, + } + local function addMnem(mnem, opcode) + instrs[mnem] = opcode + if mnem:find("%*") then instrs[mnem:gsub("%*", "%[").." ]"] = opcode end + end + for _, instr in ipairs(arch.instructions) do + if instr.mnem then + local mnem = instr.mnem + mnem = mnem:gsub("([%*%+%-])", " %1 ") + mnem = trim(mnem):gsub(" +", " ") + addMnem(mnem, instr.opcode) + local alias = arch.aliases[trim(mnem)] + if alias then for _, v in ipairs(alias) do addMnem(v, instr.opcode) end end + end + end + return instrs +end +local function assembleFile(fn, arch) + local code = includeFile(fn) + code, uexprs = preprocessCode(code) + code = fixCode(code) + local instrs = instrsFromArch(arch) + local mem, code = assembleCode(code, instrs, uexprs) + return mem, code +end + +local function mnemsFromArch(arch) + local mnems = {} + for _, instr in ipairs(arch.instructions) do + if instr.mnem then + local len = 1 + for l in instr.mnem:gmatch("imm([0-9]+)") do len = len + tonumber(l)/8 end + mnems[instr.opcode] = { mnem = instr.mnem, rel = instr.rel, jmp = instr.jmp, len = len, } + end + end + return mnems +end +local function toSigned8(x) return x>=128 and x-256 or x end +local function disassembleMemory(mem, code, arch) + local mnems = mnemsFromArch(arch) + + local addr = 0 + local function nextByte(d) local b = mem[addr]; addr = addr+1; return b or d; end + local lastaddr = 0 + local jmpaddrs = {} + while addr<=0xFFFF do + local startaddr = addr + local opcode = nextByte() + if opcode and ((not code) or code[startaddr]) then + local mnem = mnems[opcode] + if mnem then + if mnem.jmp then + local jmpdest + if mnem.rel then jmpdest = toSigned8(nextByte(0)) + addr + else jmpdest = nextByte(0)*256 + nextByte(0) + end + if jmpdest then + if not jmpaddrs[jmpdest] then + jmpaddrs[jmpdest] = { rel = mnem.rel, from = {}, } + end + table.insert(jmpaddrs[jmpdest].from, startaddr) + jmpaddrs[jmpdest].rel = jmpaddrs[jmpdest].rel and mnem.rel + end + else + addr = addr + mnem.len - 1 + end + end + end + end + local labelnum, subnum = 0, 0 + for _, jmp in pairs(jmpaddrs) do + if jmp.rel then jmp.name = "label_" ..labelnum; labelnum = labelnum+1; + else jmp.name = "subroutine_"..subnum ; subnum = subnum +1; end + end + + local lines = {} + addr = 0 + while addr<=0xFFFF do + local startaddr = addr + local opcode = nextByte() + if opcode and ((not code) or code[startaddr]) then + local line = {} + local mnem = mnems[opcode].mnem or "???" + table.insert(line, trim(mnem:gsub("imm[0-9]+", ""))) + local tlen = 1 + for lens in mnem:gmatch("imm([0-9]+)") do local len = tonumber(lens)/8 + if len==1 then + local data = nextByte(0) + local jmp + if mnems[opcode].rel then + local jmpdest = (addr + toSigned8(data))%65536 + jmp = jmpaddrs[jmpdest] + if jmp then + table.insert(line, jmp.name) + --table.insert(line, ";") + --table.insert(line, "$"..string.format("%04X", jmpdest)..",") + end + end + if not jmp then table.insert(line, "$"..string.format("%02X", data)) end + elseif len==2 then + local data = nextByte(0)*256 + nextByte(0) + local jmp + if mnems[opcode].jmp then + local jmpdest = data + jmp = jmpaddrs[jmpdest] + if jmp then + table.insert(line, jmp.name) + --table.insert(line, ";") + end + end + if not jmp then table.insert(line, "$"..string.format("%04X", data)) end + else error("invalid imm len") end + tlen = tlen + len + end + local lineb = {} + for i = addr-tlen, addr-1 do + table.insert(lineb, string.format("%02X", mem[i] or 0)) + end + local label = "" + local jmp = jmpaddrs[startaddr] + if jmp then label = jmp.name..":" end + local lb = table.concat(lineb, " ") + if lastaddr~=addr-tlen then table.insert(lines, "...") end + table.insert(lines, string.format("%04X", addr-tlen).." | "..(" "):rep(8-#lb)..lb.." | "..(" "):rep(13-#label)..label.." "..table.concat(line, " ")) + lastaddr = addr + end + end + return table.concat(lines, "\n") +end +local function memToHex(hex) + local mem = {} + local addr = 0 + for d in hex:gmatch("[0-9a-fA-F][0-9a-fA-F]") do + mem[addr] = tonumber(d, 16) + addr = addr+1 + end + return mem +end +local function disassembleHex(hex, arch) + return disassembleMemory(memToHex(hex), arch) +end + +local printableCharsS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`-=[]\\;\',./~!@#$%^&*()_+{}|:\"<> " +local printableChars = {}; for i = 1, #printableCharsS do printableChars[printableCharsS:sub(i, i)] = true end; +local function toPrintableChar(n) + local c = string.char(n) + return printableChars[c] and c or "?" +end +local function printMemory(mem) + local anynonempty = false + local lastbase = -16 + local lastline = "" + local numreps = 0 + local lines = {} + local function closereps(base) + if numreps~=0 then + table.insert(lines, "(repeated "..numreps.." more times, up to "..string.format("%04X", base+15)..")") + numreps = 0 + end + end + for base = 0, 0xFFF0, 16 do + local line = {} + local strt = {} + local nonempty = false + for addr = base, base+15 do + if addr%4==0 then table.insert(line, " ") end + if mem[addr]==false then + nonempty = true + table.insert(line, "XX ") + table.insert(strt, "X") + elseif mem[addr] then + nonempty = true + table.insert(line, string.format("%02X", mem[addr]).." ") + table.insert(strt, toPrintableChar(mem[addr])) + else + table.insert(line, "-- ") + table.insert(strt, "-") + end + end + if nonempty then + local l = table.concat(line) + if l~=lastline or base~=lastbase+16 then + closereps(base-16) + if base ~= lastbase+16 then table.insert(lines, "...") end + table.insert(lines, string.format("%04X", base).." | "..l.." | "..table.concat(strt)) + else + numreps = numreps+1 + end + lastline = l + lastbase = base + anynonempty = true + end + end + closereps(lastbase) + if not anynonempty then table.insert(lines, "Empty") end + + return table.concat(lines, "\n") +end + +local HasTs = ts~=nil +local ts = ts or { + call = function() end, + eval = function() end, +} +ts.eval [[ + function commandShiftBrick(%x, %y, %z) { commandToServer('shiftBrick', %x, %y, %z); } + function commandPlantBrick() { commandToServer('plantBrick'); } +]] +local function plantBrickAt(brickpos, pos) + local dx, dy, dz = pos[1]-brickpos[1], pos[2]-brickpos[2], pos[3]-brickpos[3] + ts.call("commandShiftBrick", dy, -dx, dz) + ts.call("commandPlantBrick") + brickpos[1], brickpos[2], brickpos[3] = pos[1], pos[2], pos[3] +end +local function buildMemory(mem, romsize, offset, len) + offset = offset or 0 + + local rombytes = romsize[1]*romsize[2]*romsize[3]/8 + if len and len>rombytes then error("rom not big enough to hold "..len.." bytes (holds "..rombytes..")") end + if not len then + for i = 0, 0xFFFF do + if mem[i] and (i=offset+rombytes) then error("memory does not fit in rom at addr "..string.format("%04X", i)) end + end + end + + local brickpos = {0, 0, 0} + for x = 0, romsize[1]-1 do + for y = 0, romsize[2]-1 do + for z = 0, romsize[3]-1 do + local addr = offset + ((romsize[3]/8)*(x + y*romsize[1]) + math.floor(z/8)) + local pow = math.pow(2, z%8) + local data = (addr>=offset and ((not len) or addr=-128 and v<=255 then return v, 1 - elseif v>=-32768 and v<=65535 then return v, 2 - else error("out-of-range number "..v) end - else - return nil - end -end -local function mnemFromLine(line, instrs, validWords) - local imms = {} - local function addNum(n) - n = trim(n) - local val, len = decodeNumber(n) - assert(val and len, "invalid number "..n) - local linei8 = line:gsub(n, "imm8", 1, true):lower() - local linei16 = line:gsub(n, "imm16", 1, true):lower() - if len==1 and (not instrs[linei8]) and instrs[linei16] then len = 2 end - table.insert(imms, { val = val, len = len } ) - return " imm"..(len*8).." " - end - local function addLabel(n) - n = trim(n) - local len = 2 - local linei8 = line:gsub(n, "imm8", 1, true):lower() - if instrs[linei8] then len = 1 end - table.insert(imms, { label = n, len = len } ) - return " imm"..(len*8).." " - end - - local mnem = " "..line:gsub(" ", " ").." " - mnem = mnem:gsub("%- *", " %+%-") - mnem = mnem:gsub("([%*%+])", " %1 ") - mnem = mnem:gsub(" %-?%$[0-9a-fA-F]+ " , function(n) return addNum (n) end) - mnem = mnem:gsub(" %-?0x[0-9a-fA-F]+ " , function(n) return addNum (n) end) - mnem = mnem:gsub(" %-?0b[01]+ " , function(n) return addNum (n) end) - mnem = mnem:gsub(" %-?[0-9a-fA-F]+h " , function(n) if not validWords[trim(n)] then return addNum (n) end end) - mnem = mnem:gsub(" %-?[01]+b " , function(n) if not validWords[trim(n)] then return addNum (n) end end) - mnem = mnem:gsub(" %-?[0-9]+ " , function(n) if not validWords[trim(n)] then return addNum (n) end end) - mnem = mnem:gsub(" [a-zA-Z_][a-zA-Z0-9_%.]* ", function(n) if not validWords[trim(n)] then return addLabel(n) end end) - mnem = trim(mnem):gsub(" +", " "):lower() - - if not instrs[mnem] then mnem = mnem:gsub("%+ imm", "imm") end - - return mnem, imms -end -local function addByte(state, val, code) - assert(val>=-128 and val<=255, "invalid byte "..val) - assert(state.memory[state.curAddr]==nil, "overwriting memory at $"..string.format("%04X", state.curAddr)) - state.memory[state.curAddr] = val%256 - if code then state.codeMap[state.curAddr] = true end - state.curAddr = state.curAddr + 1 -end -local function addWord(state, val, code) - assert(val>=0 and val<=65535, "invalid word "..val) - addByte(state, math.floor(val/256), code) - addByte(state, val%256, code) -end -local function addSpace(state, len) - for i = 1, len do - assert(state.memory[state.curAddr]==nil, "overwriting memory at $"..string.format("%04X", state.curAddr)) - state.memory[state.curAddr] = false - state.curAddr = state.curAddr + 1 - end -end -local function assembleInstruction(line, state, instrs, validWords) - local mnem, imms = mnemFromLine(line, instrs, validWords) - local opcode = instrs[mnem] or error("invalid instruction \""..line.."\" (mnem \""..mnem.."\")") - local writeimms = true - local padlen = 0 - local isInstr - if type(opcode)=="function" then - padlen, writeimms = opcode(imms) - addSpace(state, padlen) - elseif opcode>=0 then - isInstr = true - addByte(state, opcode, isInstr) - end - if writeimms then - for _, imm in ipairs(imms) do - if imm.val then - if imm.len==1 then addByte(state, imm.val, isInstr) - elseif imm.len==2 then addWord(state, imm.val, isInstr) - else error("invalid imm len") end - elseif imm.label then - table.insert(state.labelReplacements, { - name = imm.label, - addr = state.curAddr, - len = imm.len, - rel = imm.len==1, - isCode = isInstr, - }) - state.curAddr = state.curAddr + imm.len - else error("invalid imm") end - end - end -end -local directiveFunctions = { - fn = function(state, fn) state.fileName = fn end, - ln = function(state, ln) state.lineNum = tonumber(ln) end, - org = function(state, addr) state.curAddr = decodeNumber(addr) or error("Invalid origin \""..addr.."\"") end, - align = function(state, alns) local aln = decodeNumber(alns); if state.curAddr % aln ~= 0 then state.curAddr = state.curAddr + (aln - state.curAddr%aln) end end, - define = true, - space = function(state, amts) local amt = decodeNumber(amts); state.curAddr = state.curAddr + amt; end, -} -local function postEvaluateExpression(expr, labels) - -end -local function assembleCode(code, instrs, uexprs) - local validWords = validWordsFromInstrs(instrs) - - local state = { - lineNum = 0, - fileName = "", - curAddr = 0, - memory = {}, - codeMap = {}, - labelReplacements = {}, - labelAddrs = {}, - } - - for line in code:gmatch("[^\n]+") do - line = trim(line) - if line:sub(1, 1)=="." then -- directive - local dir, rest = line:match("^%.([^ ]+) *(.*)$") - assert(dir and rest, "no directive on line "..line) - local dirf = directiveFunctions[dir] or error("invalid directive "..dir) - dirf(state, rest) - elseif line:sub(#line, #line)==":" then -- label - local name = line:sub(1, #line-1) - assert(not state.labelAddrs[name], "redefinition of label "..name) - state.labelAddrs[name] = state.curAddr - elseif line:find("[^ ]") then - assembleInstruction(line, state, instrs, validWords) - end - end - - for _, rep in ipairs(state.labelReplacements) do - local expr = uexprs[rep.name] - if expr then - local val = postEvaluateExpression(expr, state.labelAddrs) - if rep.len==1 then addByte(state, val, rep.isCode) - elseif rep.len==2 then addWord(state, val, rep.isCode) - else error("invalid expr replace len "..rep.len) end - else - local labelAddr = state.labelAddrs[rep.name] or error("no label named "..rep.name) - state.curAddr = rep.addr - if rep.len==1 then addByte(state, labelAddr-(rep.addr+1), rep.isCode) - elseif rep.len==2 then addWord(state, labelAddr , rep.isCode) - else error("invalid labelreplace len "..rep.len) end - end - end - - return state.memory, state.codeMap + +local function getCodeDir() + local f0 = arg[0]:gsub("/", "\\") + local d0 = f0:match("(.+)[\\][^\\]+$") or "." + return d0 end -local function readFile(fn) - local fi, err = io.open(fn, "r") - if not fi then error("could not open file "..fn..": "..err) end - local text = fi:read("*a") - fi:close() - return text +local function popenResult(cmd) + local fp = io.popen(cmd) + local out = fp:read("*a") + fp:close() + return out end -local function separateCommas(l) - local c = {}; for a in l:gmatch("[^,]+") do table.insert(c, trim(a)) end; return c; -end -local function evaluateExpression(expr, uexprs) - expr = expr:gsub("[^%+%-%*%/]+", function(word) - local val = decodeNumber(word) or error("invalid number in expression: "..word) - return val - end) - assert(not expr:find("[^a-zA-Z0-9_%(%)%+%-%*%/ \t\r\n]"), "invalid char in expression: "..expr) - local exprf = loadstring("return "..expr) - local eval = exprf() or error("invalid expr: "..expr) - return eval -end -local function preprocessCode(code) - code = "\n"..code.."\n" - - -- apply brace labels and scoped labels - local curscope = "" - local codet = {} - local wordt = {} - local lastword = "" - local function addword(word) - lastword = word - if word:sub(1, 1)=="." and not directiveFunctions[word:sub(2, #word)] then word = curscope..word end - table.insert(codet, word) - end - for i = 1, #code do - local c = code:sub(i, i) - if c:find("[%.a-zA-Z0-9_]") then table.insert(wordt, c) - else - if #wordt>0 then - addword(table.concat(wordt)) - wordt = {} - end - if c==":" and lastword:sub(1, 1)~="." and not lastword:find("_BRACE_") then - curscope = lastword - end - table.insert(codet, c) +local function memFromCustomasmHexstr(out) + local mem = {} + local addr = 0 + for hexS in out:gmatch("[0-9a-fA-F][0-9a-fA-F]") do + local val = tonumber(hexS, 16) + if val~=0 then + mem[addr] = val end + addr = addr + 1 end - - code = "\n"..table.concat(codet).."\n" - - -- apply function macros - local funcmacros = {} - code = code:gsub(".define ([%.a-zA-Z0-9_]+)%(([^%)]+)%) ([^\n]+)", function(name, args, repl) - local argt = separateCommas(args) - for argidx, arg in ipairs(argt) do assert(not arg:find("[^a-zA-Z0-9_]"), "invalid character in macro arg name: "..name.." "..arg) end - repl = " "..repl.." " - local invoc = 0 - funcmacros[name] = function(b, callargs) - invoc = invoc + 1 - local callargt = separateCommas(callargs) - local callrepl = repl - for argidx, arg in ipairs(argt) do - local callarg = callargt[argidx] - callrepl = callrepl:gsub("([^a-zA-Z0-9_])"..arg.."([^a-zA-Z0-9_])", "%1"..callarg.."%2") - end - callrepl = callrepl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_") - return b..callrepl - end - return "" - end) - for name, replf in pairs(funcmacros) do code = code:gsub("([^a-zA-Z0-9_])"..name.." *%(([^%)]+)%)", replf) end - - -- apply simple macros - local simplemacros = {} - code = code:gsub("%.define +([%.a-zA-Z0-9_]+) +([^\n]+)", function(name, repl) - assert(not simplemacros[name], "Redefinition of macro "..name) - simplemacros[name] = repl - return "" - end) - --for name, repl in pairs(simplemacros) do code = code:gsub(name, repl, 1, true) end - for name, repl in pairs(simplemacros) do - local invoc = 0 - code = code:gsub("([^a-zA-Z0-9_])"..name.."([^a-zA-Z0-9_])", function(b, a) - invoc = invoc+1 - return b..(repl:gsub("(_BRACE_[0-9]+_)", "%1"..invoc.."_"))..a - end) - print(name, code) + local code = nil + local symbols = nil + return mem, code, symbols +end + +local function toData(s) + local d = {} + for p in s:gmatch("[0-9a-zA-Z][0-9a-zA-Z]") do + table.insert(d, tonumber(p, 16)) end + return d +end +local function memFromCustomasmAnnotated(out) + local mem = {} + local code = {} + local symbols = {} - code = code:gsub("\\\\", "\n") + local lastLabel = {} - local uexprs = {} - - local codet = {} - local exprt = {} - local parenLevel = 0 - for i = 1, #code do - local c = code:sub(i, i) - if c=="(" then - if parenLevel>0 then table.insert(exprt, c) end - parenLevel = parenLevel+1 - elseif c==")" then - parenLevel = parenLevel-1 - if parenLevel==0 then - table.insert(codet, evaluateExpression(table.concat(exprt), uexprs)) - exprt = {} + for line in out:gmatch("[^\r\n]+") do + if not line:find("^ outp | addr | data %(base 16%)$") then + local addrS, dataS, comment = line:match("^[^|]+ | ([^|]+) | ([^;]+) ; (.+)$") + local addr = tonumber(addrS, 16) + local data = toData(dataS) + if comment:sub(#comment, #comment)==":" then + assert(#data==0) + local label = comment:sub(1, #comment-1) + local noDots = label:gsub("^%.+", "") + local numDots = #label - #noDots + local fullLabel = numDots>0 and lastLabel[numDots-1].."."..noDots or label + lastLabel[numDots] = fullLabel + symbols[addr] = fullLabel else - table.insert(exprt, c) - end - else - if parenLevel==0 then table.insert(codet, c) - else table.insert(exprt, c) end - end - end - code = table.concat(codet) - - return code, uexprs -end -local function fixCode(code) - code = code:gsub(",", " ") - code = code:gsub(":([^\\/])", ":\n%1") - code = code:gsub("[ \t]+:", ":") - code = code:gsub("%]", " %] ") - code = code:gsub("%[", " %[ ") - code = code:gsub("%*", " %* ") - code = code:gsub("\n[ \t\r\n]*", "\n") - code = code:gsub(" +", " ") - - return code -end -local stringEscapes = { ["\\"] = "\\", ["n"] = "\n", ["r"] = "\r", ["t"] = "\t", ["0"] = "\0", ["\""] = "\"", ["\'"] = "\'", } -local prefixIdx = 0 -local function prefixCode(code, fn) -- fix strings, add line numbers - prefixIdx = prefixIdx + 1 - - local outt = {} - local outnextnl = {} - local linenum = 1 - local skipnl = false - local function last() return outt[#outt] end - local function out(c) assert(type(c)=="string"); table.insert(outt, c); end - local function outn(n) out("$"..string.format("%02X", n)) out("\\") end - local function outnext(c) assert(type(c)=="string"); table.insert(outnextnl, c); end - local state = "code" -- code, comment, string, stringesc, commentml - - local lastbracelabel = 0 - local function bracelabel() lastbracelabel = lastbracelabel+1; return "_BRACE_"..string.format("%02d", prefixIdx)..lastbracelabel.."_"; end - local bracestack = {} - local bracehasmid = {} - local lastnl = false - - local utf8str = "" - local utf8len = 0 - - local function newline() - lastnl = true - for _, v in ipairs(outnextnl) do - if v=="\n" and skipnl then out("\\") - else out(v) end - end; outnextnl = {}; - end - - out(".ln 1"); out("\n"); - local i = 1 - while i <= #code do - local c = code:sub(i, i) - local cn = code:sub(i+1, i+1) - local cp = code:sub(i-1, i-1) - - if state=="code" then - if c=="\r" then - elseif c=="\n" then -- (c=="/" and cn~="/" and cn~="*") - linenum = linenum+1 - if not skipnl then out("\n") out(".ln "..linenum); out("\n"); end - newline() - skipnl = false - elseif c=="#" or c==";" or (c=="/" and cn=="/") then state = "comment" - elseif c=="/" and cn=="*" then state = "commentml" - elseif c=="\t" or c==" " then if (not lastnl) then out(" ") end - elseif c=="\"" then state = "string" lastnl = false - elseif c=="\\" then skipnl = true; out("\\"); - elseif c==":" then out(c); if skipnl then out("\\") else out("\n") end; lastnl = true; - elseif c:find("^[a-zA-Z0-9_%.%$%(%)%*,%[%]%+%-%*%/]$") then out(c); lastnl = false - elseif c=="{" then - table.insert(bracestack, bracelabel()) - if not lastnl then out(bracestack[#bracestack].."MID") end - outnext(bracestack[#bracestack].."START:"); outnext("\n"); - elseif c=="}" then - if not lastnl then out(bracestack[#bracestack].."START") end - if not bracehasmid[#bracestack] then outnext(bracestack[#bracestack].."MID:"); outnext("\n"); end - outnext(bracestack[#bracestack].."END:"); outnext("\n"); - bracehasmid[#bracestack] = nil - bracestack[#bracestack] = nil - elseif c=="|" then - if not lastnl then out(bracestack[#bracestack].."END") end - outnext(bracestack[#bracestack].."MID:"); outnext("\n"); - bracehasmid[#bracestack] = true - else error("invalid char "..c) end - elseif state=="comment" then - if c=="\n" then state = "code" out("\n") newline() end - elseif state=="commentml" then - if c=="/" and cp=="*" then state = "code" end - elseif state=="string" then - if c=="\\" then state = "stringesc" - elseif c=="\"" then state = "code" - elseif c:byte()>=128 then - utf8str = c - utf8len = getutf8len(c) - state = "stringutf8" - else outn(c:byte()) end - elseif state=="stringesc" then - outn(string.byte(stringEscapes[c] or error("invalid escape "..c))); state = "string"; - elseif state=="stringutf8" then - utf8str = utf8str..c - if #utf8str == utf8len then - local valt = utf8table[utf8str] - if not valt then local datastr = ""; for i = 1, #utf8str do datastr = datastr .. string.format("%02X ", utf8str:sub(i, i):byte()) end; - error("Unrecognized UTF-8 character: "..datastr); end - for i, v in ipairs(valt) do outn(v) end - state = "string" + if comment:match("^[a-z]+") then + for i, v in ipairs(data) do + mem [addr+i-1] = v + code[addr+i-1] = true + end + else + for i, v in ipairs(data) do + mem [addr+i-1] = v + end + end end end - - i = i+1 end - assert(#bracestack==0, "unclosed brace") - local code2 = table.concat(outt) - return code2 + return mem, code, symbols end -local function fixFilename(fn) - fn = fn:gsub("[^a-zA-Z0-9_]", "_") - return fn -end -local function includeFile(fn) - local code = readFile(fn) - code = prefixCode(code, fn) - local fnf = fixFilename(fn) - code = ".fn "..fnf.."\n"..code - code = code:gsub(".include ([^\r\n]+)", function(fn2) - fn2 = fn:gsub("[^\\/]+$", "")..fn2 - return "\n"..includeFile(fn2).."\n"..".fn "..fnf.."\n" - end) - return code -end -local function instrsFromArch(arch) - local function arraySize(imms) local s = 1; for i = 1, #imms do s = s*(imms[i].val or error("invalid array size")) end; return s; end - local instrs = { - imm8 = function() return 0, true end, - imm16 = function() return 0, true end, - byte = function() return 1, false end, - word = function() return 2, false end, - ["byte imm8"] = function() return 0, true end, - ["word imm16"] = function() return 0, true end, - ["byte [ imm8 ]" ] = function(imms) return arraySize(imms) , false end, - ["byte [ imm16 ]"] = function(imms) return arraySize(imms) , false end, - ["word [ imm8 ]" ] = function(imms) return arraySize(imms)*2, false end, - ["word [ imm16 ]"] = function(imms) return arraySize(imms)*2, false end, - } - local function addMnem(mnem, opcode) - instrs[mnem] = opcode - if mnem:find("%*") then instrs[mnem:gsub("%*", "%[").." ]"] = opcode end - end - for _, instr in ipairs(arch.instructions) do - if instr.mnem then - local mnem = instr.mnem - mnem = mnem:gsub("([%*%+%-])", " %1 ") - mnem = trim(mnem):gsub(" +", " ") - addMnem(mnem, instr.opcode) - local alias = arch.aliases[trim(mnem)] - if alias then for _, v in ipairs(alias) do addMnem(v, instr.opcode) end end - end - end - return instrs + +local function fullPath(fn) + return popenResult(getCodeDir().."\\fullPath.bat \""..fn.."\"") end + local function assembleFile(fn, arch) - local code = includeFile(fn) - code, uexprs = preprocessCode(code) - code = fixCode(code) - local instrs = instrsFromArch(arch) - local mem, code = assembleCode(code, instrs, uexprs) - return mem, code + local fnf = fullPath(fn) + --local out = popenResult("customasm -p -q --format hexstr \""..fnf.."\"") + --return memFromCustomasmHexstr(out) + local out = popenResult("customasm -p -q --format annotated,base:16,group:2 \""..fnf.."\"") + return memFromCustomasmAnnotated(out) end local function mnemsFromArch(arch) @@ -491,8 +97,11 @@ local function mnemsFromArch(arch) end return mnems end + +local function symbolCrunchDots(s) return s:gsub("[^%.]+%.", "%.").."" end + local function toSigned8(x) return x>=128 and x-256 or x end -local function disassembleMemory(mem, code, arch) +local function disassembleMemory(arch, mem, code, symbols) local mnems = mnemsFromArch(arch) local addr = 0 @@ -524,11 +133,13 @@ local function disassembleMemory(mem, code, arch) end end local labelnum, subnum = 0, 0 - for _, jmp in pairs(jmpaddrs) do - if jmp.rel then jmp.name = "label_" ..labelnum; labelnum = labelnum+1; - else jmp.name = "subroutine_"..subnum ; subnum = subnum +1; end + for dest, jmp in pairs(jmpaddrs) do + if symbols[dest] then jmp.name = symbolCrunchDots(symbols[dest]) + elseif jmp.rel then jmp.name = "label_" ..labelnum; labelnum = labelnum+1; + else jmp.name = "subroutine_"..subnum ; subnum = subnum +1; end end + local maxLabelLen = 20 local lines = {} addr = 0 while addr<=0xFFFF do @@ -574,11 +185,14 @@ local function disassembleMemory(mem, code, arch) end local label = "" local jmp = jmpaddrs[startaddr] - if jmp then label = jmp.name..":" end + if symbols[startaddr] then label = symbolCrunchDots(symbols[startaddr])..":" + elseif jmp then label = jmp.name..":" end local lb = table.concat(lineb, " ") if lastaddr~=addr-tlen then table.insert(lines, "...") end - table.insert(lines, string.format("%04X", addr-tlen).." | "..(" "):rep(8-#lb)..lb.." | "..(" "):rep(13-#label)..label.." "..table.concat(line, " ")) + table.insert(lines, string.format("%04X", addr-tlen).." | "..(" "):rep(8-#lb)..lb.." | "..(" "):rep(maxLabelLen-#label)..label.." "..table.concat(line, " ")) lastaddr = addr + elseif opcode and opcode~=0 then + table.insert(lines, "data: "..string.format("%02X", opcode)) end end return table.concat(lines, "\n") @@ -593,7 +207,7 @@ local function memToHex(hex) return mem end local function disassembleHex(hex, arch) - return disassembleMemory(memToHex(hex), arch) + return disassembleMemory(arch, memToHex(hex), nil, nil) end local printableCharsS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`-=[]\\;\',./~!@#$%^&*()_+{}|:\"<> " @@ -693,31 +307,15 @@ local function buildMemory(mem, romsize, offset, len) end end -local function strtovec(str) local v = {}; for word in str:gmatch("[^ \t\r\n]+") do table.insert(v, tonumber(word)) end; return v; end -if HasTs or (not AsmIncluded) then - function AssembleBuildFile(fn, romsizes, offsets, lens) local offset = tonumber(offsets); local len = tonumber(lens); local romsize = strtovec(romsizes); - local arch = require("rom-8608-defs") - local mem, code = assembleFile(fn, arch) - print(""..fn:match("[^/\\]+$").."\n") - - print("Memory Dump:") - print(printMemory(mem)) - print() - print("Disassembly:") - print(disassembleMemory(mem, code, arch)) - print() - - assert(#romsize==3, "incorrect rom size") - buildMemory(mem, romsize, offset, len) - end - ts.eval [[ - function AssembleBuildFile(%fn, %romsize, %offset, %len) { luacall("AssembleBuildFile", strReplace(%fn, "$", "Add-ons/_misc/rom/8608programs/"), %romsize, %offset, %len); } - ]] - if not HasTs then AssembleBuildFile(arg[1] or "../8608programs/test.asm", "16 16 8", "0", "256") end +if arg[1] then + local fn = arg[1] + local mem, code, symbols = assembleFile(fn) + local arch = dofile(getCodeDir().."\\rom-8608-defs.lua") + print(disassembleMemory(arch, mem, code, symbols)) +else + return { + assembleFile = assembleFile, + disassembleMemory = disassembleMemory, + printMemory = printMemory, + } end - -return { - assembleFile = assembleFile, - disassembleMemory = disassembleMemory, - printMemory = printMemory, -} diff --git a/bin-builder.lua b/bin-builder.lua new file mode 100644 index 0000000..e0092c7 --- /dev/null +++ b/bin-builder.lua @@ -0,0 +1,70 @@ + +local ts = ts or { + call = function() end, + eval = function() end, +} + +ts.eval [[ + function commandShiftBrick(%x, %y, %z) { commandToServer('shiftBrick', %x, %y, %z); } + function commandPlantBrick() { commandToServer('plantBrick'); } +]] +local function plantBrickAt(brickpos, pos) + local dx, dy, dz = pos[1]-brickpos[1], pos[2]-brickpos[2], pos[3]-brickpos[3] + ts.call("commandShiftBrick", dy, -dx, dz) + ts.call("commandPlantBrick") + brickpos[1], brickpos[2], brickpos[3] = pos[1], pos[2], pos[3] +end +local function buildMemory(mem, romsize, offset, len) + if type(romsize)~="table" or #romsize<3 then error("You must specify a ROM size.") end + offset = offset or 0 + + local rombytes = romsize[1]*romsize[2]*romsize[3]/8 + if len and len>rombytes then error("rom not big enough to hold "..len.." bytes (holds "..rombytes..")") end + if not len then + for i = 0, 0xFFFF do + if mem[i] and (i=offset+rombytes) then error("memory does not fit in rom at addr "..string.format("%04X", i)) end + end + end + + local brickpos = {0, 0, 0} + for x = 0, romsize[1]-1 do + for y = 0, romsize[2]-1 do + for z = 0, romsize[3]-1 do + local addr = offset + ((romsize[3]/8)*(x + y*romsize[1]) + math.floor(z/8)) + local pow = math.pow(2, z%8) + local data = (addr>=offset and ((not len) or addrp) -#define loadpinc readmemory(cpu->p++) -#define loadpp1 readmemory((cpu->p+1)%65536) #define loadq readmemory(cpu->q) -#define loadqinc readmemory(cpu->q++) +#define loadpinc readmemory((cpu->p++)%65536) +#define loadqinc readmemory((cpu->q++)%65536) +#define loadpp1 readmemory((cpu->p+1)%65536) #define loadqp1 readmemory((cpu->q+1)%65536) +#define loadput readmemory((cpu->p+wordut)%65536) +#define loadqut readmemory((cpu->q+wordut)%65536) #define signed8(x) (x>=128 ? x|0xFF00 : x) - #define setzf(x) cpu->nz=(x!=0); #define loadimmedt cpu->t = loadimmed; #define loadimm161 cpu->u = loadimmed; @@ -31,11 +32,13 @@ #define storeut(x) writememory(wordut, x); #define storeutp1(x) writememory((wordut+1)%65536, x); #define storep(x) writememory(cpu->p, x); -#define storepinc(x) writememory(cpu->p++, x); -#define storepp1(x) writememory((cpu->p+1)%65536, x); #define storeq(x) writememory(cpu->q, x); +#define storepinc(x) writememory(cpu->p++, x); #define storeqinc(x) writememory(cpu->q++, x); +#define storepp1(x) writememory((cpu->p+1)%65536, x); #define storeqp1(x) writememory((cpu->q+1)%65536, x); +#define storeput(x) writememory((cpu->p+wordut)%65536, x); +#define storequt(x) writememory((cpu->q+wordut)%65536, x); #define pushretaddr1 writememory(cpu->s++, hibyte((cpu->i-1)%65536)); #define pushretaddr2 writememory(cpu->s++, lobyte((cpu->i-1)%65536)); #define lni cpu->instr = readmemory(cpu->i++); cpu->cycle = 0; diff --git a/emulator/8608emulator.dll b/emulator/8608emulator.dll index 38a38150f2b6c1ee13edbb1c4b8e5ccbe554cb48..bc03b77aa5094810cf141b1086258e107b357520 100644 GIT binary patch literal 151643 zcmeEv3qV`d{r@>3l$53=w9sOuHr80FwlxXw0wp|KDuoF2p;iNh(1H{YLalEqtuu=_ zHg&)Gj;`CBI)~2H=NyzyTBi={rp|7Tx$5Ys4j-#^eenOBa}$z#NIC;1XuBgp9gyhq3a?y?t ztYj}GQ-cZVB~#9xMipm~XiCT}0F-N60TGAb&-HRXqqDze7N1p$kC#z1fmS~v=Hv?qMRo4!dL^BJILZO;fERC(>~7@Wmqa<}mn7-;Dq}Ufyn+QTzkwytawNK2sU!6#tNSjFqNHVSbXV(cme1A~&tuNIwZ$z*G>&YYZf8eR zgCkN6$(;voT-WjsY8d49XXmv3*-|h>)(4Xxj2!4VS>19(X+Jg)_GJ97Muh6HcQy4s z^aw6njw!-+ypPx+Js(cr%X28rsCbBVvxcLN z^-4z?i@ZOo)wYl%cZKcP2ZlS{w^^D4NOPW)X489ygRV4b*p3-6aPHgL5w_z=1oN<7 zhHvM=upJIYRh2S*ZPAVrT}*ejPKowG>?JxC{91d2Zm_52h`J@1l?8>yTyvM&a&Kju zyKp~84!eU{<`EV77S~RmW2yXJU`_Dws=>iQ$uCJBt_Gov<(Fxr={Z@AcvZ~dQL-?7 z*UqNo@M6d@5v3$T;PjP&A<4099G=7C-s-MjcMW8-&>x=~9PFRo=KZ&3o&9%fi|sGl z--M;?JYbJhnNL~XrjpG3lvj;I;gzCovCq#Z8O zZ@h^Qo*W#694t#=_^3OWMGfT!VTATRl;`DLm2G{GsVQmA8iXBeJ;yt2mK0&j@gVze zn!5V$aM_Euh{+wj?ICaSml0e$*yC?(O)bZ1(<6Pis63fqg~>F2-y;^b(*m_v9NxL? zlmtZbJ-*4mIKlIJIFe=XIE*?J7yW-^?Jv0AWfm|mUCY0zZLT9<7lSsZ?YjXrg5p4f zaObZ?r|$bAgc8WA``>OucqZsFGdn7w?>VLb+A*)jHTDl$jzlqb#EI&@*OBIacLV=5 zt1d~(Q{!uk5uF;5YaA={yO{*(Ht~w>Ht{jJ+oYC=d=}MhijaJK4%BUmmV8>tiIE&W z=69R;0M>2d19G=1iIsD=DOD2D@lyXb#&hDpuZHa0Z#&;{4{44f+m8>15pq*>Yuvjn zUDSR%!F;Rx7Nu*}W#=-Encb#r7L(mP7kKJ}JoTv7#m8H^sr{EMb^A`1 zx}EbKv?Vi}+B4NIdmXRzSU1Vq$549tEPv{--Ir>R$If0AvNiRcpv(w+SLgBho&6g6 z4$J5}t9MVb5I5RT$P^jCFZ;XG%4l ziJC?c_)EXWRUWG}uEN;Yn!l4c?q)N#od<2R91T&9YxC`&*`H%`$FSXB*bNRlArZ{- z&U5^d7s)AJ_h+Z5vs>!W&H>%(0eeEe1k4LVab0WDg#KQUB49{s!;^kmadDVCpda+M#~&%694 zhkn_ZOtbnm#{_BYZ-(tY;Hb}MUpQblFLs!9t(Q{!dY%1E*Rto` zuxAb|dbc(DyI*73a~GfDOUs^F-YZK#>kTjc%t~(s&Aj}^S;OJ&!&^UUezQu&w`ATt=ISdvdqiWr*7tG0$ani6wok=3ul|dhD#EUV=Y9^_ zTi9+)uh1c5QjAH&*cQRC`JR-1Bu`&8Vd+OraQ@F2@BF*>-#4)PN70T|n$~)1Z-}

w?_BpKz6{&Ff6xd>Hw=T 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 literal 164507 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

WzARi9%a2(_8n!dSN0rbomci7 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 Y^|)!WUY;a=0; cpu->b=0; cpu->c=0; cpu->u=0; cpu->t=0; cpu->p=0; cpu->q=0; cpu->s=0; cpu->v=0; cpu->i=0; cpu->cf=0; cpu->nz=0; cpu->irq=0; cpu->ifg=0; cpu->rfg=1; cpu->ien=0; lni; } +void cpu_instr_1_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_1_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_1_2(struct CPU* const cpu, struct Memory* const mem) { cpu->a=loadput; setzf(cpu->a); cpu->cycle++; } +void cpu_instr_1_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_6_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_6_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_6_2(struct CPU* const cpu, struct Memory* const mem) { storeut(hibyte(cpu->q)); cpu->cycle++; } +void cpu_instr_6_3(struct CPU* const cpu, struct Memory* const mem) { storeutp1(lobyte(cpu->q)); cpu->cycle++; } +void cpu_instr_6_4(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_8_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_8_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_8_2(struct CPU* const cpu, struct Memory* const mem) { cpu->b=loadqut; setzf(cpu->b); cpu->cycle++; } +void cpu_instr_8_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_9_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_9_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_9_2(struct CPU* const cpu, struct Memory* const mem) { cpu->c=loadqut; setzf(cpu->c); cpu->cycle++; } +void cpu_instr_9_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_10_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_10_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_10_2(struct CPU* const cpu, struct Memory* const mem) { storeput(cpu->a); cpu->cycle++; } +void cpu_instr_10_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_11_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_11_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_11_2(struct CPU* const cpu, struct Memory* const mem) { storeput(cpu->b); cpu->cycle++; } +void cpu_instr_11_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_12_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_12_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_12_2(struct CPU* const cpu, struct Memory* const mem) { storeput(cpu->c); cpu->cycle++; } +void cpu_instr_12_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_13_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_13_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_13_2(struct CPU* const cpu, struct Memory* const mem) { storequt(cpu->a); cpu->cycle++; } +void cpu_instr_13_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_14_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_14_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_14_2(struct CPU* const cpu, struct Memory* const mem) { storequt(cpu->b); cpu->cycle++; } +void cpu_instr_14_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_15_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_15_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_15_2(struct CPU* const cpu, struct Memory* const mem) { storequt(cpu->c); cpu->cycle++; } +void cpu_instr_15_3(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_16_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a, 1 ); lni; } void cpu_instr_17_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,-1 ); lni; } void cpu_instr_18_0(struct CPU* const cpu, struct Memory* const mem) { cpu->p++; lni; } @@ -440,6 +481,20 @@ void cpu_instr_233_0(struct CPU* const cpu, struct Memory* const mem) { int f = void cpu_instr_233_1(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_234_0(struct CPU* const cpu, struct Memory* const mem) { int f=popbyte; cpu->nz = f&1; cpu->cf = (f>>1)&1; cpu->cycle++; } void cpu_instr_234_1(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_235_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_235_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_235_2(struct CPU* const cpu, struct Memory* const mem) { cpu->a=loadqut; setzf(cpu->a); cpu->cycle++; } +void cpu_instr_235_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_236_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_236_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_236_2(struct CPU* const cpu, struct Memory* const mem) { cpu->p=wordut; cpu->u=loadut; cpu->cycle++; } +void cpu_instr_236_3(struct CPU* const cpu, struct Memory* const mem) { cpu->t=loadpp1; cpu->cycle++; } +void cpu_instr_236_4(struct CPU* const cpu, struct Memory* const mem) { cpu->p=wordut; lni; } +void cpu_instr_238_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_238_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_238_2(struct CPU* const cpu, struct Memory* const mem) { cpu->q=wordut; cpu->u=loadut; cpu->cycle++; } +void cpu_instr_238_3(struct CPU* const cpu, struct Memory* const mem) { cpu->t=loadqp1; cpu->cycle++; } +void cpu_instr_238_4(struct CPU* const cpu, struct Memory* const mem) { cpu->q=wordut; lni; } void cpu_instr_240_0(struct CPU* const cpu, struct Memory* const mem) { cpu->rfg=0; lni; } void cpu_instr_241_0(struct CPU* const cpu, struct Memory* const mem) { cpu->rfg=1; lni; } void cpu_instr_242_0(struct CPU* const cpu, struct Memory* const mem) { cpu->irq=0; cpu->ifg=1; int t=cpu->i; cpu->i=cpu->v; cpu->v=(t-1)%65536; lni; } @@ -447,25 +502,48 @@ void cpu_instr_243_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ifg void cpu_instr_244_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ifg=0; int t=cpu->i; cpu->i=cpu->v; cpu->v=t; lni; } void cpu_instr_245_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ien=1; lni; } void cpu_instr_246_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ien=0; lni; } +void cpu_instr_247_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_247_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_247_2(struct CPU* const cpu, struct Memory* const mem) { cpu->b=loadput; setzf(cpu->b); cpu->cycle++; } +void cpu_instr_247_3(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_248_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_248_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_248_2(struct CPU* const cpu, struct Memory* const mem) { cpu->p=wordut; cpu->u=loadut; cpu->cycle++; } +void cpu_instr_248_3(struct CPU* const cpu, struct Memory* const mem) { cpu->t=loadpp1; cpu->cycle++; } +void cpu_instr_248_4(struct CPU* const cpu, struct Memory* const mem) { cpu->p=wordut; lni; } +void cpu_instr_250_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_250_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_250_2(struct CPU* const cpu, struct Memory* const mem) { cpu->q=wordut; cpu->u=loadut; cpu->cycle++; } +void cpu_instr_250_3(struct CPU* const cpu, struct Memory* const mem) { cpu->t=loadqp1; cpu->cycle++; } +void cpu_instr_250_4(struct CPU* const cpu, struct Memory* const mem) { cpu->q=wordut; lni; } +void cpu_instr_252_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_252_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_252_2(struct CPU* const cpu, struct Memory* const mem) { storeut(hibyte(cpu->p)); cpu->cycle++; } +void cpu_instr_252_3(struct CPU* const cpu, struct Memory* const mem) { storeutp1(lobyte(cpu->p)); cpu->cycle++; } +void cpu_instr_252_4(struct CPU* const cpu, struct Memory* const mem) { lni; } +void cpu_instr_254_0(struct CPU* const cpu, struct Memory* const mem) { loadimm161 cpu->cycle++; } +void cpu_instr_254_1(struct CPU* const cpu, struct Memory* const mem) { loadimm162 cpu->cycle++; } +void cpu_instr_254_2(struct CPU* const cpu, struct Memory* const mem) { cpu->c=loadput; setzf(cpu->c); cpu->cycle++; } +void cpu_instr_254_3(struct CPU* const cpu, struct Memory* const mem) { lni; } void cpu_instr_255_0(struct CPU* const cpu, struct Memory* const mem) { lni; } CPUInstruction CPUInstructions[256][8] = { {cpu_instr_0_0,0,0,0,0,0,0,0}, + {cpu_instr_1_0,cpu_instr_1_1,cpu_instr_1_2,cpu_instr_1_3,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, + {cpu_instr_6_0,cpu_instr_6_1,cpu_instr_6_2,cpu_instr_6_3,cpu_instr_6_4,0,0,0}, {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, + {cpu_instr_8_0,cpu_instr_8_1,cpu_instr_8_2,cpu_instr_8_3,0,0,0,0}, + {cpu_instr_9_0,cpu_instr_9_1,cpu_instr_9_2,cpu_instr_9_3,0,0,0,0}, + {cpu_instr_10_0,cpu_instr_10_1,cpu_instr_10_2,cpu_instr_10_3,0,0,0,0}, + {cpu_instr_11_0,cpu_instr_11_1,cpu_instr_11_2,cpu_instr_11_3,0,0,0,0}, + {cpu_instr_12_0,cpu_instr_12_1,cpu_instr_12_2,cpu_instr_12_3,0,0,0,0}, + {cpu_instr_13_0,cpu_instr_13_1,cpu_instr_13_2,cpu_instr_13_3,0,0,0,0}, + {cpu_instr_14_0,cpu_instr_14_1,cpu_instr_14_2,cpu_instr_14_3,0,0,0,0}, + {cpu_instr_15_0,cpu_instr_15_1,cpu_instr_15_2,cpu_instr_15_3,0,0,0,0}, {cpu_instr_16_0,0,0,0,0,0,0,0}, {cpu_instr_17_0,0,0,0,0,0,0,0}, {cpu_instr_18_0,0,0,0,0,0,0,0}, @@ -685,10 +763,10 @@ CPUInstruction CPUInstructions[256][8] = { {cpu_instr_232_0,0,0,0,0,0,0,0}, {cpu_instr_233_0,cpu_instr_233_1,0,0,0,0,0,0}, {cpu_instr_234_0,cpu_instr_234_1,0,0,0,0,0,0}, + {cpu_instr_235_0,cpu_instr_235_1,cpu_instr_235_2,cpu_instr_235_3,0,0,0,0}, + {cpu_instr_236_0,cpu_instr_236_1,cpu_instr_236_2,cpu_instr_236_3,cpu_instr_236_4,0,0,0}, {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, + {cpu_instr_238_0,cpu_instr_238_1,cpu_instr_238_2,cpu_instr_238_3,cpu_instr_238_4,0,0,0}, {0,0,0,0,0,0,0,0}, {cpu_instr_240_0,0,0,0,0,0,0,0}, {cpu_instr_241_0,0,0,0,0,0,0,0}, @@ -697,13 +775,13 @@ CPUInstruction CPUInstructions[256][8] = { {cpu_instr_244_0,0,0,0,0,0,0,0}, {cpu_instr_245_0,0,0,0,0,0,0,0}, {cpu_instr_246_0,0,0,0,0,0,0,0}, + {cpu_instr_247_0,cpu_instr_247_1,cpu_instr_247_2,cpu_instr_247_3,0,0,0,0}, + {cpu_instr_248_0,cpu_instr_248_1,cpu_instr_248_2,cpu_instr_248_3,cpu_instr_248_4,0,0,0}, {0,0,0,0,0,0,0,0}, + {cpu_instr_250_0,cpu_instr_250_1,cpu_instr_250_2,cpu_instr_250_3,cpu_instr_250_4,0,0,0}, {0,0,0,0,0,0,0,0}, + {cpu_instr_252_0,cpu_instr_252_1,cpu_instr_252_2,cpu_instr_252_3,cpu_instr_252_4,0,0,0}, {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0}, + {cpu_instr_254_0,cpu_instr_254_1,cpu_instr_254_2,cpu_instr_254_3,0,0,0,0}, {cpu_instr_255_0,0,0,0,0,0,0,0}, }; diff --git a/emulator/keycodes.lua b/emulator/keycodes.lua index 1ff3625..d797e97 100644 --- a/emulator/keycodes.lua +++ b/emulator/keycodes.lua @@ -1,4 +1,6 @@ +-- copied from Brick_LuaLogic/bricks/input/keyboard-global.luas + return { ["backspace"] = 8, ["tab"] = 9, diff --git a/fullPath.bat b/fullPath.bat new file mode 100644 index 0000000..b1d7fba --- /dev/null +++ b/fullPath.bat @@ -0,0 +1 @@ +@echo %~dpnx1 diff --git a/instructionList.txt b/instructionList.txt index 0cddae1..37bf07c 100644 --- a/instructionList.txt +++ b/instructionList.txt @@ -129,10 +129,10 @@ rts E1 3 I=*(----S)+1 jpr imm8 31 2 I+=imm8 jnz imm8 30 2 I+=imm8 if !Zero jpz imm8 32 2 I+=imm8 if Zero -jge imm8 33 2 I+=imm8 if !Carry -jlt imm8 34 2 I+=imm8 if Carry -jgt imm8 35 2 I+=imm8 if !Zero & !Carry -jle imm8 36 2 I+=imm8 if Zero | Carry +jlt imm8 33 2 I+=imm8 if !Carry +jge imm8 34 2 I+=imm8 if Carry +jgt imm8 35 2 I+=imm8 if !Zero & Carry +jle imm8 36 2 I+=imm8 if Zero | !Carry Stack (S): psh a 40 2 *(S++)=A @@ -166,30 +166,42 @@ ldc *imm16 57 4 C=*imm16, update zero flag sta *imm16 50 4 *imm16=A stb *imm16 58 4 *imm16=B stc *imm16 59 4 *imm16=C -sta *p 52 2 *P=A -stb *p 5A 2 *P=B -stc *p 5B 2 *P=C -sta *q 54 2 *Q=A -stb *q 5C 2 *Q=B -stc *q 5D 2 *Q=C +lda *p+imm16 01 4 A=*P+imm16, update zero flag +ldb *p+imm16 F7 4 B=*P+imm16, update zero flag +ldc *p+imm16 FE 4 C=*P+imm16, update zero flag +lda *q+imm16 EB 4 A=*Q+imm16, update zero flag +ldb *q+imm16 08 4 B=*Q+imm16, update zero flag +ldc *q+imm16 09 4 C=*Q+imm16, update zero flag +sta *p+imm16 0A 4 *P+imm16=A +stb *p+imm16 0B 4 *P+imm16=B +stc *p+imm16 0C 4 *P+imm16=C +sta *q+imm16 0D 4 *Q+imm16=A +stb *q+imm16 0E 4 *Q+imm16=B +stc *q+imm16 0F 4 *Q+imm16=C lda *p 53 2 A=*P, update zero flag ldb *p 5E 2 B=*P, update zero flag ldc *p 5F 2 C=*P, update zero flag lda *q 55 2 A=*Q, update zero flag ldb *q 61 2 B=*Q, update zero flag ldc *q 62 2 C=*Q, update zero flag -sta *p++ C0 2 *P++=A -stb *p++ C1 2 *P++=B -stc *p++ C2 2 *P++=C -sta *q++ C3 2 *Q++=A -stb *q++ C4 2 *Q++=B -stc *q++ C5 2 *Q++=C +sta *p 52 2 *P=A +stb *p 5A 2 *P=B +stc *p 5B 2 *P=C +sta *q 54 2 *Q=A +stb *q 5C 2 *Q=B +stc *q 5D 2 *Q=C lda *p++ C6 2 A=*P++, update zero flag ldb *p++ C7 2 B=*P++, update zero flag ldc *p++ C8 2 C=*P++, update zero flag lda *q++ C9 2 A=*Q++, update zero flag ldb *q++ CA 2 B=*Q++, update zero flag ldc *q++ CB 2 C=*Q++, update zero flag +sta *p++ C0 2 *P++=A +stb *p++ C1 2 *P++=B +stc *p++ C2 2 *P++=C +sta *q++ C3 2 *Q++=A +stb *q++ C4 2 *Q++=B +stc *q++ C5 2 *Q++=C 16-bit Load/Store (W): ldp imm16 21 3 P=imm16 @@ -204,6 +216,12 @@ ldp *imm16 68 5 P=*imm16 ldq *imm16 6A 5 Q=*imm16 stp *imm16 6C 5 *imm16=P stq *imm16 6E 5 *imm16=Q +ldp *p+imm16 EC 5 P=*P+imm16 +ldq *p+imm16 EE 5 Q=*P+imm16 +ldp *q+imm16 F8 5 P=*Q+imm16 +ldq *q+imm16 FA 5 Q=*Q+imm16 +stq *p+imm16 06 5 *P+imm16=Q +stp *q+imm16 FC 5 *Q+imm16=P ldp *p 92 3 P=*P ldq *p 93 3 Q=*P ldp *q 94 3 P=*Q @@ -240,9 +258,9 @@ ldq p 8E 1 Q=P lds p 8F 1 S=P ldv p 90 1 V=P -Opcodes used: 228/255 +Opcodes used: 252/255 0123456789ABCDEF -00 | C--------------- +00 | CB----WWBBBBBBBB 10 | UUIIUIIUUUUUUUUU 20 | BWWWAWBBBBBUUUUA 30 | JJJJJJJMMMMSSSAA @@ -256,5 +274,5 @@ A0 | AAAAAAAAAAAAAAAA B0 | AAAAAAAAAAAAAAAA C0 | BBBBBBBBBBBBWWWW D0 | AAAAAAAAAAAAAAAA -E0 | MJJJJJXXXSS----- -F0 | CCCCCCC--------C +E0 | MJJJJJXXXSSBWWWW +F0 | CCCCCCCBWWWWWWBC diff --git a/rom-8608.lua b/rom-8608-build.lua similarity index 69% rename from rom-8608.lua rename to rom-8608-build.lua index 17964bb..180f25e 100644 --- a/rom-8608.lua +++ b/rom-8608-build.lua @@ -70,6 +70,70 @@ local function sigsFromRoms(roms) return sigs end +local relJmpStr = [[ +%s {addr} => { + reladdr = addr - $ - 2 + assert(reladdr <= 127, "%s: Relative jump target is too far away") + assert(reladdr >= -128, "%s: Relative jump target is too far away") + %s @ reladdr`8 + }]] +local wordRelStr = [[ +%s+{value: i%i} => { + assert(value <= %i, "Relative address is too far away") + assert(value >= %i, "Relative address is too far away") + %s @ value`%i + } + %s-{value: i%i} => { + mvalue = -value + assert(mvalue <= %i, "Relative address is too far away") + assert(mvalue >= %i, "Relative address is too far away") + %s @ mvalue`%i + }]] + +local function getAsmCode(mnem, instr) + local reljmp = instr.jmp and instr.rel + local opcodeS = string.format("$%02X", instr.opcode) + + if reljmp then + assert(mnem:find("imm8"), "relative jump without imm8") + local mnemPart = mnem:gsub(" imm8", "") + return string.format(relJmpStr, + mnemPart, mnemPart, mnemPart, + opcodeS + ) + elseif mnem:find("%+imm") then + local mnemPart, bitsS = mnem:match("^([^%+]+)%+imm([0-9]+)$") + local bits = tonumber(bitsS) + local maxVal = math.pow(2, bits-1)-1 + local minVal = -math.pow(2, bits-1) + return string.format(wordRelStr, + mnemPart, bits, maxVal, minVal, opcodeS, bits, + mnemPart, bits, maxVal, minVal, opcodeS, bits + ) + elseif mnem:find("imm8") then + mnem = mnem:gsub("imm8", "{value: i8}") + return mnem.." => "..opcodeS.." @ value" + elseif mnem:find("imm16") then + mnem = mnem:gsub("imm16", "{value: i16}") + return mnem.." => "..opcodeS.." @ value" + else + return mnem.." => "..opcodeS + end +end +local function getAsmsFromInstr(instr, aliases) + local mnem = instr.mnem + local t = {} + if mnem then + table.insert(t, getAsmCode(mnem, instr)) + if aliases[mnem] then + for _, mnem2 in ipairs(aliases[mnem]) do + table.insert(t, getAsmCode(mnem2, instr)) + end + end + end + return t +end + local function archToUcode(arch) local sigs = sigsFromRoms(arch.roms) local ops = arch.operations @@ -78,6 +142,7 @@ local function archToUcode(arch) local opcodesUsed = {} local numOpcodesUsed = 0 local infolines = {} + local asmlines = {} local catlet = "X" for _, instr in ipairs(arch.instructions) do if instr.category then @@ -105,6 +170,9 @@ local function archToUcode(arch) if instr.desc then table.insert(infolines, mnem..(" "):rep(13-#mnem)..hex(opcode).." "..ncycles.." "..instr.desc.."\n") end + + local asms = getAsmsFromInstr(instr, arch.aliases) + for _, a in ipairs(asms) do table.insert(asmlines, a) end end end @@ -120,15 +188,28 @@ local function archToUcode(arch) table.insert(lt, "\n") end + -- Output instruction list local info = table.concat(infolines).."\n"..table.concat(lt) - print(info) - + --print(info) local fo = io.open("instructionList.txt", "w") if fo then fo:write(info) fo:close() end + + -- Output customASM definitions + local fi = io.open("arch-8608-template.asm") + local asmDataStr = fi:read("*a") + fi:close() + + local asmTable = string.format(asmDataStr, table.concat(asmlines, "\n\t")) + local fo = io.open("arch-8608.asm", "w") + if fo then + fo:write(asmTable) + fo:close() + end + return ucode end diff --git a/rom-8608-defs.lua b/rom-8608-defs.lua index 9309b7b..366a301 100644 --- a/rom-8608-defs.lua +++ b/rom-8608-defs.lua @@ -72,14 +72,20 @@ operations = { load162 = {"adrInc","loadReg","memSaveT"}, store161 = { "storeReg"}, store162 = {"adrInc","storeReg"}, - loadUTU = {"adrrUT","loadReg","memSaveU"}, - storeUT = {"adrrUT","storeReg"}, + loadUTU = {"adrrUT", "loadReg","memSaveU"}, + loadUTUP = {"adrrUT","adrlP","loadReg","memSaveU"}, + loadUTUQ = {"adrrUT","adrlQ","loadReg","memSaveU"}, + storeUT = {"adrrUT", "storeReg"}, + storeUTP = {"adrrUT","adrlP","storeReg"}, + storeUTQ = {"adrrUT","adrlQ","storeReg"}, memSaveFlags = {"memSaveNZ"}, adwrUT = {"adwrhU","adwrlT"}, adrrUT = {"adrrhU","adrrlT"}, adwrCB = {"adwrhC","adwrlB"}, - adwIncUT = {"adwrUT","adwInc"}, + adwIncUT = {"adwrUT", "adwInc"}, + adwIncUTP = {"adwrUT","adwlP","adwInc"}, + adwIncUTQ = {"adwrUT","adwlQ","adwInc"}, adwP = {"adwlP","adwSaveP"}, adwQ = {"adwlQ","adwSaveQ"}, adwS = {"adwlS","adwSaveS"}, @@ -130,252 +136,270 @@ operations = { instructions = { { category = "Control", catlet="C" }, - { mnem="rst" , opcode=0x00, {"base","intFlgClk","irqFlgClk","runFlgClk","runFlgVal","clearRegs","loadInstr"}, desc="Clear all registers and set I=0", ccode={"cpu.a=0; cpu.b=0; cpu.c=0; cpu.u=0; cpu.t=0; cpu.p=0; cpu.q=0; cpu.s=0; cpu.v=0; cpu.i=0; cpu.cf=0; cpu.nz=0; cpu.irq=0; cpu.ifg=0; cpu.rfg=1; cpu.ien=0; lni;"} }, - { mnem="hlt" , opcode=0xF0, {"runFlgClk","instrNext"}, desc="Halt non-interrupt execution", ccode={"cpu.rfg=0; lni;"} }, - { mnem="run" , opcode=0xF1, {"runFlgClk","runFlgVal","instrNext"}, desc ="Resume non-interrupt execution", ccode={"cpu.rfg=1; lni;"} }, - { mnem="int" , opcode=0xF2, {"instrSwapIV","intFlgVal","intFlgClk","irqFlgClk"}, ccode={"cpu.irq=0; cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=(t-1)%65536; lni;"} }, - { mnem="brk" , opcode=0xF3, {"instrSwapIV","adwInc","intFlgVal","intFlgClk"}, desc="Trigger interrupt", ccode={"cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} }, - { mnem="irt" , opcode=0xF4, {"instrSwapIV","adwInc","intFlgClk"}, desc="Return from interrupt", ccode={"cpu.ifg=0; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} }, - { mnem="nop" , opcode=0xFF, {"instrNext"}, desc="Do nothing", ccode={"lni;"}, }, - { mnem="ien" , opcode=0xF5, {"instrNext"}, desc="Enbale interrupts", ccode={"cpu.ien=1; lni;"}, }, -- todo - { mnem="idi" , opcode=0xF6, {"instrNext"}, desc="Disable interrupts", ccode={"cpu.ien=0; lni;"}, }, -- todo + { mnem="rst" , opcode=0x00, {"base","intFlgClk","irqFlgClk","runFlgClk","runFlgVal","clearRegs","loadInstr"}, desc="Clear all registers and set I=0", ccode={"cpu.a=0; cpu.b=0; cpu.c=0; cpu.u=0; cpu.t=0; cpu.p=0; cpu.q=0; cpu.s=0; cpu.v=0; cpu.i=0; cpu.cf=0; cpu.nz=0; cpu.irq=0; cpu.ifg=0; cpu.rfg=1; cpu.ien=0; lni;"} }, + { mnem="hlt" , opcode=0xF0, {"runFlgClk","instrNext"}, desc="Halt non-interrupt execution", ccode={"cpu.rfg=0; lni;"} }, + { mnem="run" , opcode=0xF1, {"runFlgClk","runFlgVal","instrNext"}, desc ="Resume non-interrupt execution", ccode={"cpu.rfg=1; lni;"} }, + { mnem="int" , opcode=0xF2, {"instrSwapIV","intFlgVal","intFlgClk","irqFlgClk"}, ccode={"cpu.irq=0; cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=(t-1)%65536; lni;"} }, + { mnem="brk" , opcode=0xF3, {"instrSwapIV","adwInc","intFlgVal","intFlgClk"}, desc="Trigger interrupt", ccode={"cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} }, + { mnem="irt" , opcode=0xF4, {"instrSwapIV","adwInc","intFlgClk"}, desc="Return from interrupt", ccode={"cpu.ifg=0; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} }, + { mnem="nop" , opcode=0xFF, {"instrNext"}, desc="Do nothing", ccode={"lni;"}, }, + { mnem="ien" , opcode=0xF5, {"instrNext"}, desc="Enbale interrupts", ccode={"cpu.ien=1; lni;"}, }, -- todo + { mnem="idi" , opcode=0xF6, {"instrNext"}, desc="Disable interrupts", ccode={"cpu.ien=0; lni;"}, }, -- todo { category = "16-bit Inc/Dec", catlet="I" }, - { mnem="inc p" , opcode=0x12, {"adwlP","adwInc","adwSaveP","instrNext"}, desc="P++", ccode={"cpu.p++; lni;"} }, - { mnem="dec p" , opcode=0x15, {"adwlP","adwrm1","adwSaveP","instrNext"}, desc="P--", ccode={"cpu.p--; lni;"} }, - { mnem="inc q" , opcode=0x13, {"adwlQ","adwInc","adwSaveQ","instrNext"}, desc="Q++", ccode={"cpu.q++; lni;"} }, - { mnem="dec q" , opcode=0x16, {"adwlQ","adwrm1","adwSaveQ","instrNext"}, desc="Q--", ccode={"cpu.q--; lni;"} }, + { mnem="inc p" , opcode=0x12, {"adwlP","adwInc","adwSaveP","instrNext"}, desc="P++", ccode={"cpu.p++; lni;"} }, + { mnem="dec p" , opcode=0x15, {"adwlP","adwrm1","adwSaveP","instrNext"}, desc="P--", ccode={"cpu.p--; lni;"} }, + { mnem="inc q" , opcode=0x13, {"adwlQ","adwInc","adwSaveQ","instrNext"}, desc="Q++", ccode={"cpu.q++; lni;"} }, + { mnem="dec q" , opcode=0x16, {"adwlQ","adwrm1","adwSaveQ","instrNext"}, desc="Q--", ccode={"cpu.q--; lni;"} }, { category = "8-bit Unary", catlet="U" }, - { mnem="inc a" , opcode=0x10, {"aluA","alur1" ,"aluOpAdd" ,"instrNext"}, desc="A++, set flags" , ccode={"addf(cpu.a, 1 ); lni;"} }, - { mnem="dec a" , opcode=0x11, {"aluA","alurm1","aluOpAdd" ,"instrNext"}, desc="A--, set flags" , ccode={"addf(cpu.a,-1 ); lni;"} }, - { mnem="icc a" , opcode=0x1B, {"aluA", "aluOpAddC","instrNext"}, desc="A+=CF, set flags", ccode={"addf(cpu.a,cpu.cf); lni;"} }, - { mnem="inc b" , opcode=0x19, {"aluB","alur1" ,"aluOpAdd" ,"instrNext"}, desc="B++, set flags" , ccode={"addf(cpu.b, 1 ); lni;"} }, - { mnem="dec b" , opcode=0x1A, {"aluB","alurm1","aluOpAdd" ,"instrNext"}, desc="B--, set flags" , ccode={"addf(cpu.b,-1 ); lni;"} }, - { mnem="icc b" , opcode=0x1C, {"aluB", "aluOpAddC","instrNext"}, desc="B+=CF, set flags", ccode={"addf(cpu.b,cpu.cf); lni;"} }, - { mnem="inc c" , opcode=0x17, {"aluC","alur1" ,"aluOpAdd" ,"instrNext"}, desc="C++, set flags" , ccode={"addf(cpu.c, 1 ); lni;"} }, - { mnem="dec c" , opcode=0x18, {"aluC","alurm1","aluOpAdd" ,"instrNext"}, desc="C--, set flags" , ccode={"addf(cpu.c,-1 ); lni;"} }, - { mnem="icc c" , opcode=0x1D, {"aluC", "aluOpAddC","instrNext"}, desc="C+=CF, set flags", ccode={"addf(cpu.c,cpu.cf); lni;"} }, - { mnem="tst a" , opcode=0x14, {"alulA", "aluOpCmp" ,"instrNext"}, desc="Set flags according to A-0", ccode={"tst(cpu.a); lni;"} }, - { mnem="tst b" , opcode=0x1E, {"alulB", "aluOpCmp" ,"instrNext"}, desc="Set flags according to B-0", ccode={"tst(cpu.b); lni;"} }, - { mnem="tst c" , opcode=0x1F, {"alulC", "aluOpCmp" ,"instrNext"}, desc="Set flags according to C-0", ccode={"tst(cpu.c); lni;"} }, - { mnem="inc *s+imm8", opcode=0x2B, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU","alur1" ,"aluOpAdd" ,"instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)++, set flags" , ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u, 1 );","instrloadpre"} }, - { mnem="dec *s+imm8", opcode=0x2C, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU","alurm1","aluOpAdd" ,"instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)--, set flags" , ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u,-1 );","instrloadpre"} }, - { mnem="icc *s+imm8", opcode=0x2D, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU", "aluOpAddC","instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)+=CF, set flags", ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u,cpu.cf);","instrloadpre"} }, - { mnem="tst *s+imm8", opcode=0x2E, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"alulU", "aluOpCmp" ,"instrNext"}, desc="Set flags according to *(S+imm8)-0", ccode={"loadimmedt","loadstackrelu","tst(cpu.u); lni;"} }, + { mnem="inc a" , opcode=0x10, {"aluA","alur1" ,"aluOpAdd" ,"instrNext"}, desc="A++, set flags" , ccode={"addf(cpu.a, 1 ); lni;"} }, + { mnem="dec a" , opcode=0x11, {"aluA","alurm1","aluOpAdd" ,"instrNext"}, desc="A--, set flags" , ccode={"addf(cpu.a,-1 ); lni;"} }, + { mnem="icc a" , opcode=0x1B, {"aluA", "aluOpAddC","instrNext"}, desc="A+=CF, set flags", ccode={"addf(cpu.a,cpu.cf); lni;"} }, + { mnem="inc b" , opcode=0x19, {"aluB","alur1" ,"aluOpAdd" ,"instrNext"}, desc="B++, set flags" , ccode={"addf(cpu.b, 1 ); lni;"} }, + { mnem="dec b" , opcode=0x1A, {"aluB","alurm1","aluOpAdd" ,"instrNext"}, desc="B--, set flags" , ccode={"addf(cpu.b,-1 ); lni;"} }, + { mnem="icc b" , opcode=0x1C, {"aluB", "aluOpAddC","instrNext"}, desc="B+=CF, set flags", ccode={"addf(cpu.b,cpu.cf); lni;"} }, + { mnem="inc c" , opcode=0x17, {"aluC","alur1" ,"aluOpAdd" ,"instrNext"}, desc="C++, set flags" , ccode={"addf(cpu.c, 1 ); lni;"} }, + { mnem="dec c" , opcode=0x18, {"aluC","alurm1","aluOpAdd" ,"instrNext"}, desc="C--, set flags" , ccode={"addf(cpu.c,-1 ); lni;"} }, + { mnem="icc c" , opcode=0x1D, {"aluC", "aluOpAddC","instrNext"}, desc="C+=CF, set flags", ccode={"addf(cpu.c,cpu.cf); lni;"} }, + { mnem="tst a" , opcode=0x14, {"alulA", "aluOpCmp" ,"instrNext"}, desc="Set flags according to A-0", ccode={"tst(cpu.a); lni;"} }, + { mnem="tst b" , opcode=0x1E, {"alulB", "aluOpCmp" ,"instrNext"}, desc="Set flags according to B-0", ccode={"tst(cpu.b); lni;"} }, + { mnem="tst c" , opcode=0x1F, {"alulC", "aluOpCmp" ,"instrNext"}, desc="Set flags according to C-0", ccode={"tst(cpu.c); lni;"} }, + { mnem="inc *s+imm8" , opcode=0x2B, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU","alur1" ,"aluOpAdd" ,"instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)++, set flags" , ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u, 1 );","instrloadpre"} }, + { mnem="dec *s+imm8" , opcode=0x2C, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU","alurm1","aluOpAdd" ,"instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)--, set flags" , ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u,-1 );","instrloadpre"} }, + { mnem="icc *s+imm8" , opcode=0x2D, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"aluU", "aluOpAddC","instrSub3","instrPreload"}, {"storeStackRelU","instrNextPre"}, desc="*(S+imm8)+=CF, set flags", ccode={"loadimmedt","loadstackrelu","instrpreload; addf(cpu.u,cpu.cf);","instrloadpre"} }, + { mnem="tst *s+imm8" , opcode=0x2E, {"loadImmedT","instrSub1"}, {"loadStackRelU","instrSub2"}, {"alulU", "aluOpCmp" ,"instrNext"}, desc="Set flags according to *(S+imm8)-0", ccode={"loadimmedt","loadstackrelu","tst(cpu.u); lni;"} }, { category = "16-bit Arithmetic", catlet = "X"}, - { mnem="adp imm8" , opcode=0x4A, {"loadImmedT","instrSub1"}, {"adwP","adwrTX","instrNext"}, desc="P+=imm8 signed", ccode={"loadimmedt","cpu.p+=signed8(cpu.t); lni;"} }, - { mnem="adq imm8" , opcode=0x4B, {"loadImmedT","instrSub1"}, {"adwQ","adwrTX","instrNext"}, desc="Q+=imm8 signed", ccode={"loadimmedt","cpu.q+=signed8(cpu.t); lni;"} }, - { mnem="ads imm8" , opcode=0x4C, {"loadImmedT","instrSub1"}, {"adwS","adwrTX","instrNext"}, desc="S+=imm8 signed", ccode={"loadimmedt","cpu.s+=signed8(cpu.t); lni;"} }, - { mnem="adp b" , opcode=0xE6, {"adwP","adwrBX","instrNext"}, desc="P+=B signed", ccode={"cpu.p+=signed8(cpu.b); lni;"} }, - { mnem="adq b" , opcode=0xE7, {"adwQ","adwrBX","instrNext"}, desc="Q+=B signed", ccode={"cpu.q+=signed8(cpu.b); lni;"} }, - { mnem="ads b" , opcode=0xE8, {"adwS","adwrBX","instrNext"}, desc="S+=B signed", ccode={"cpu.s+=signed8(cpu.b); lni;"} }, + { mnem="adp imm8" , opcode=0x4A, {"loadImmedT","instrSub1"}, {"adwP","adwrTX","instrNext"}, desc="P+=imm8 signed", ccode={"loadimmedt","cpu.p+=signed8(cpu.t); lni;"} }, + { mnem="adq imm8" , opcode=0x4B, {"loadImmedT","instrSub1"}, {"adwQ","adwrTX","instrNext"}, desc="Q+=imm8 signed", ccode={"loadimmedt","cpu.q+=signed8(cpu.t); lni;"} }, + { mnem="ads imm8" , opcode=0x4C, {"loadImmedT","instrSub1"}, {"adwS","adwrTX","instrNext"}, desc="S+=imm8 signed", ccode={"loadimmedt","cpu.s+=signed8(cpu.t); lni;"} }, + { mnem="adp b" , opcode=0xE6, {"adwP","adwrBX","instrNext"}, desc="P+=B signed", ccode={"cpu.p+=signed8(cpu.b); lni;"} }, + { mnem="adq b" , opcode=0xE7, {"adwQ","adwrBX","instrNext"}, desc="Q+=B signed", ccode={"cpu.q+=signed8(cpu.b); lni;"} }, + { mnem="ads b" , opcode=0xE8, {"adwS","adwrBX","instrNext"}, desc="S+=B signed", ccode={"cpu.s+=signed8(cpu.b); lni;"} }, { category = "8-bit Arithmetic/Logic", catlet="A" }, - { mnem="add imm8" , opcode=0x24, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="A+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t); lni;"} }, - { mnem="adb imm8" , opcode=0x72, {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="B+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.b,cpu.t); lni;"} }, - { mnem="adc imm8" , opcode=0x73, {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="C+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.c,cpu.t); lni;"} }, - { mnem="sub imm8" , opcode=0x70, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSub" ,"instrNext"}, desc="A-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.a,cpu.t); lni;"} }, - { mnem="sbb imm8" , opcode=0x99, {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.b,cpu.t); lni;"} }, - { mnem="sbc imm8" , opcode=0x9A, {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.c,cpu.t); lni;"} }, - { mnem="acc imm8" , opcode=0x78, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="A+=imm8+CF, set flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t+cpu.cf); lni;"} }, - { mnem="scc imm8" , opcode=0x79, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="A-=imm8+CF, set flags" , ccode={"loadimmedt","addf(cpu.a,-cpu.t+cpu.cf); lni;"} }, - { mnem="cmp imm8" , opcode=0x71, {"loadImmedT","instrSub1"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="set flags according to A-imm8" , ccode={"loadimmedt","cmpf(cpu.a,cpu.t); lni;"} }, - { mnem="and imm8" , opcode=0x74, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="A&=imm8, set zero flag" , ccode={"loadimmedt","cpu.a&=cpu.t; setzf(cpu.a); lni;"} }, - { mnem="ior imm8" , opcode=0x75, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="A|=imm8, set zero flag" , ccode={"loadimmedt","cpu.a|=cpu.t; setzf(cpu.a); lni;"} }, - { mnem="xor imm8" , opcode=0x76, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpXor" ,"instrNext"}, desc="A^=imm8, set zero flag" , ccode={"loadimmedt","cpu.a^=cpu.t; setzf(cpu.a); lni;"} }, - { mnem="ann imm8" , opcode=0x77, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnn" ,"instrNext"}, desc="A&=~imm8, set zero flag" , ccode={"loadimmedt","cpu.a&=~cpu.t; setzf(cpu.a); lni;"} }, - { mnem="shl imm8" , opcode=0xD0, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpShl" ,"instrNext"}, desc="A<<=imm8, set zero flag" , ccode={"loadimmedt","cpu.a<<=cpu.t; setzf(cpu.a); lni;"} }, - { mnem="shr imm8" , opcode=0xD1, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpShr" ,"instrNext"}, desc="A>>=imm8, set zero flag" , ccode={"loadimmedt","cpu.a>>=cpu.t; setzf(cpu.a); lni;"} }, - { mnem="rol imm8" , opcode=0xD2, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpRol" ,"instrNext"}, desc="A<<<=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=rol(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, - { mnem="ror imm8" , opcode=0xD3, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpRor" ,"instrNext"}, desc="A>>>=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=ror(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, - { mnem="sra imm8" , opcode=0xD4, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSra" ,"instrNext"}, desc="A>>a=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=sra(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, - { mnem="add *s+imm8", opcode=0xAE, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="A+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u); lni;"} }, - { mnem="adb *s+imm8", opcode=0x9B, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="B+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.b,cpu.u); lni;"} }, - { mnem="adc *s+imm8", opcode=0x9C, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="C+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.c,cpu.u); lni;"} }, - { mnem="sub *s+imm8", opcode=0xAF, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSub" ,"instrNext"}, desc="A-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.a,cpu.u); lni;"} }, - { mnem="sbb *s+imm8", opcode=0x9D, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.b,cpu.u); lni;"} }, - { mnem="sbc *s+imm8", opcode=0x9E, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.c,cpu.u); lni;"} }, - { mnem="acc *s+imm8", opcode=0xB5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="A+=*(S+imm8)+CF, set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u+cpu.cf); lni;"} }, - { mnem="scc *s+imm8", opcode=0xB7, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="A-=*(S+imm8)+CF, set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,-cpu.u+cpu.cf); lni;"} }, - { mnem="cmp *s+imm8", opcode=0xB0, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="set flags according to A-*(S+imm8)", ccode={"loadimmedt","loadstackrelu","cmpf(cpu.a,cpu.u); lni;"} }, - { mnem="and *s+imm8", opcode=0xB1, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="A&=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a&=cpu.u; setzf(cpu.a); lni;"} }, - { mnem="ior *s+imm8", opcode=0xB2, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="A|=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a|=cpu.u; setzf(cpu.a); lni;"} }, - { mnem="xor *s+imm8", opcode=0xB3, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpXor" ,"instrNext"}, desc="A^=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a^=cpu.u; setzf(cpu.a); lni;"} }, - { mnem="ann *s+imm8", opcode=0xB4, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnn" ,"instrNext"}, desc="A&=~*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a&=~cpu.u; setzf(cpu.a); lni;"} }, - { mnem="shl *s+imm8", opcode=0xD5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpShl" ,"instrNext"}, desc="A<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a<<=cpu.u; setzf(cpu.a); lni;"} }, - { mnem="shr *s+imm8", opcode=0xD6, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpShr" ,"instrNext"}, desc="A<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a>>=cpu.u; setzf(cpu.a); lni;"} }, - { mnem="rol *s+imm8", opcode=0xD7, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpRol" ,"instrNext"}, desc="A<<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=rol(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, - { mnem="ror *s+imm8", opcode=0xD8, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpRor" ,"instrNext"}, desc="A>>>=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=ror(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, - { mnem="sra *s+imm8", opcode=0xD9, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSra" ,"instrNext"}, desc="A>>a=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=sra(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, - { mnem="add b" , opcode=0xA0, {"aluA", "alurB","aluOpAdd" ,"instrNext"}, desc="A+=B, set flags" , ccode={"addf(cpu.a,cpu.b); lni;"} }, - { mnem="adc b" , opcode=0x9F, {"aluC", "alurB","aluOpAdd" ,"instrNext"}, desc="C+=B, set flags" , ccode={"addf(cpu.c,cpu.b); lni;"} }, - { mnem="sub b" , opcode=0xA1, {"aluA", "alurB","aluOpSub" ,"instrNext"}, desc="A-=B, set flags" , ccode={"subf(cpu.a,cpu.b); lni;"} }, - { mnem="sbc b" , opcode=0xB6, {"aluC", "alurB","aluOpSub" ,"instrNext"}, desc="C-=B, set flags" , ccode={"subf(cpu.c,cpu.b); lni;"} }, - { mnem="acc b" , opcode=0xB8, {"aluA", "alurB","aluOpAddC","instrNext"}, desc="A+=B+CF, set flags" , ccode={"addf(cpu.a,cpu.b+cpu.cf); lni;"} }, - { mnem="scc b" , opcode=0xB9, {"aluA", "alurB","aluOpSubC","instrNext"}, desc="A-=B+CF, set flags" , ccode={"addf(cpu.a,-cpu.b+cpu.cf); lni;"} }, - { mnem="cmp b" , opcode=0xA2, {"alulA","alurB","aluOpSub" ,"instrNext"}, desc="set flags according to A-B" , ccode={"cmpf(cpu.a,cpu.b); lni;"} }, - { mnem="and b" , opcode=0xA3, {"aluA", "alurB","aluOpAnd" ,"instrNext"}, desc="A&=B, set zero flag" , ccode={"cpu.a&=cpu.b; setzf(cpu.a); lni;"} }, - { mnem="ior b" , opcode=0xA4, {"aluA", "alurB","aluOpIor" ,"instrNext"}, desc="A|=B, set zero flag" , ccode={"cpu.a|=cpu.b; setzf(cpu.a); lni;"} }, - { mnem="xor b" , opcode=0xA5, {"aluA", "alurB","aluOpXor" ,"instrNext"}, desc="A^=B, set zero flag" , ccode={"cpu.a^=cpu.b; setzf(cpu.a); lni;"} }, - { mnem="ann b" , opcode=0xA6, {"aluA", "alurB","aluOpAnn" ,"instrNext"}, desc="A&=~B, set zero flag" , ccode={"cpu.a&=~cpu.b; setzf(cpu.a); lni;"} }, - { mnem="shl b" , opcode=0xDA, {"aluA", "alurB","aluOpShl" ,"instrNext"}, desc="A<<=B, set zero flag" , ccode={"cpu.a<<=cpu.b; setzf(cpu.a); lni;"} }, - { mnem="shr b" , opcode=0xDB, {"aluA", "alurB","aluOpShr" ,"instrNext"}, desc="A>>=B, set zero flag" , ccode={"cpu.a>>=cpu.b; setzf(cpu.a); lni;"} }, - { mnem="rol b" , opcode=0xDC, {"aluA", "alurB","aluOpRol" ,"instrNext"}, desc="A<<<=B, set zero flag" , ccode={"cpu.a=rol(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, - { mnem="ror b" , opcode=0xDD, {"aluA", "alurB","aluOpRor" ,"instrNext"}, desc="A>>>=B, set zero flag" , ccode={"cpu.a=ror(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, - { mnem="sra b" , opcode=0xDE, {"aluA", "alurB","aluOpSra" ,"instrNext"}, desc="A>>a=B, set zero flag" , ccode={"cpu.a=sra(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, - { mnem="add c" , opcode=0xA7, {"aluA", "alurC","aluOpAdd" ,"instrNext"}, desc="A+=C, set flags" , ccode={"addf(cpu.a,cpu.c); lni;"} }, - { mnem="adb c" , opcode=0xBD, {"aluB", "alurC","aluOpAdd" ,"instrNext"}, desc="B+=C, set flags" , ccode={"addf(cpu.b,cpu.c); lni;"} }, - { mnem="sub c" , opcode=0xA8, {"aluA", "alurC","aluOpSub" ,"instrNext"}, desc="A-=C, set flags" , ccode={"subf(cpu.a,cpu.c); lni;"} }, - { mnem="sbb c" , opcode=0xBC, {"aluB", "alurC","aluOpSub" ,"instrNext"}, desc="B-=C, set flags" , ccode={"subf(cpu.b,cpu.c); lni;"} }, - { mnem="acc c" , opcode=0xBA, {"aluA", "alurC","aluOpAddC","instrNext"}, desc="A+=C+CF, set flags" , ccode={"addf(cpu.a,cpu.c+cpu.cf); lni;"} }, - { mnem="scc c" , opcode=0xBB, {"aluA", "alurC","aluOpSubC","instrNext"}, desc="A-=C+CF, set flags" , ccode={"addf(cpu.a,-cpu.c+cpu.cf); lni;"} }, - { mnem="cmp c" , opcode=0xA9, {"alulA","alurC","aluOpSub" ,"instrNext"}, desc="set flags according to A-C" , ccode={"cmpf(cpu.a,cpu.c); lni;"} }, - { mnem="and c" , opcode=0xAA, {"aluA", "alurC","aluOpAnd" ,"instrNext"}, desc="A&=C, set zero flag" , ccode={"cpu.a&=cpu.c; setzf(cpu.a); lni;"} }, - { mnem="ior c" , opcode=0xAB, {"aluA", "alurC","aluOpIor" ,"instrNext"}, desc="A|=C, set zero flag" , ccode={"cpu.a|=cpu.c; setzf(cpu.a); lni;"} }, - { mnem="xor c" , opcode=0xAC, {"aluA", "alurC","aluOpXor" ,"instrNext"}, desc="A^=C, set zero flag" , ccode={"cpu.a^=cpu.c; setzf(cpu.a); lni;"} }, - { mnem="ann c" , opcode=0xAD, {"aluA", "alurC","aluOpAnn" ,"instrNext"}, desc="A&=~C, set zero flag" , ccode={"cpu.a&=~cpu.c; setzf(cpu.a); lni;"} }, - { mnem="shl c" , opcode=0xDF, {"aluA", "alurC","aluOpShl" ,"instrNext"}, desc="A<<=C, set zero flag" , ccode={"cpu.a<<=cpu.c; setzf(cpu.a); lni;"} }, - { mnem="shr c" , opcode=0x4D, {"aluA", "alurC","aluOpShr" ,"instrNext"}, desc="A>>=C, set zero flag" , ccode={"cpu.a>>=cpu.c; setzf(cpu.a); lni;"} }, - { mnem="rol c" , opcode=0x3E, {"aluA", "alurC","aluOpRol" ,"instrNext"}, desc="A<<<=C, set zero flag" , ccode={"cpu.a=rol(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, - { mnem="ror c" , opcode=0x3F, {"aluA", "alurC","aluOpRor" ,"instrNext"}, desc="A>>>=C, set zero flag" , ccode={"cpu.a=ror(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, - { mnem="sra c" , opcode=0x2F, {"aluA", "alurC","aluOpSra" ,"instrNext"}, desc="A>>a=C, set zero flag" , ccode={"cpu.a=sra(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, - { mnem="adb a" , opcode=0xBE, {"aluB", "alurA","aluOpAdd" ,"instrNext"}, desc="B+=A, set flags" , ccode={"addf(cpu.b,cpu.a); lni;"} }, - { mnem="sbb a" , opcode=0xBF, {"aluB", "alurA","aluOpSub" ,"instrNext"}, desc="B-=A, set flags" , ccode={"subf(cpu.b,cpu.a); lni;"} }, - { mnem="adc a" , opcode=0x4E, {"aluC", "alurA","aluOpAdd" ,"instrNext"}, desc="C+=A, set flags" , ccode={"addf(cpu.c,cpu.a); lni;"} }, - { mnem="sbc a" , opcode=0x4F, {"aluC", "alurA","aluOpSub" ,"instrNext"}, desc="C-=A, set flags" , ccode={"subf(cpu.c,cpu.a); lni;"} }, + { mnem="add imm8" , opcode=0x24, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="A+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t); lni;"} }, + { mnem="adb imm8" , opcode=0x72, {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="B+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.b,cpu.t); lni;"} }, + { mnem="adc imm8" , opcode=0x73, {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="C+=imm8, set flags" , ccode={"loadimmedt","addf(cpu.c,cpu.t); lni;"} }, + { mnem="sub imm8" , opcode=0x70, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSub" ,"instrNext"}, desc="A-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.a,cpu.t); lni;"} }, + { mnem="sbb imm8" , opcode=0x99, {"loadImmedT","instrSub1"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.b,cpu.t); lni;"} }, + { mnem="sbc imm8" , opcode=0x9A, {"loadImmedT","instrSub1"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=imm8, set flags" , ccode={"loadimmedt","subf(cpu.c,cpu.t); lni;"} }, + { mnem="acc imm8" , opcode=0x78, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="A+=imm8+CF, set flags" , ccode={"loadimmedt","addf(cpu.a,cpu.t+cpu.cf); lni;"} }, + { mnem="scc imm8" , opcode=0x79, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="A-=imm8+CF, set flags" , ccode={"loadimmedt","addf(cpu.a,-cpu.t+cpu.cf); lni;"} }, + { mnem="cmp imm8" , opcode=0x71, {"loadImmedT","instrSub1"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="set flags according to A-imm8" , ccode={"loadimmedt","cmpf(cpu.a,cpu.t); lni;"} }, + { mnem="and imm8" , opcode=0x74, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="A&=imm8, set zero flag" , ccode={"loadimmedt","cpu.a&=cpu.t; setzf(cpu.a); lni;"} }, + { mnem="ior imm8" , opcode=0x75, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="A|=imm8, set zero flag" , ccode={"loadimmedt","cpu.a|=cpu.t; setzf(cpu.a); lni;"} }, + { mnem="xor imm8" , opcode=0x76, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpXor" ,"instrNext"}, desc="A^=imm8, set zero flag" , ccode={"loadimmedt","cpu.a^=cpu.t; setzf(cpu.a); lni;"} }, + { mnem="ann imm8" , opcode=0x77, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpAnn" ,"instrNext"}, desc="A&=~imm8, set zero flag" , ccode={"loadimmedt","cpu.a&=~cpu.t; setzf(cpu.a); lni;"} }, + { mnem="shl imm8" , opcode=0xD0, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpShl" ,"instrNext"}, desc="A<<=imm8, set zero flag" , ccode={"loadimmedt","cpu.a<<=cpu.t; setzf(cpu.a); lni;"} }, + { mnem="shr imm8" , opcode=0xD1, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpShr" ,"instrNext"}, desc="A>>=imm8, set zero flag" , ccode={"loadimmedt","cpu.a>>=cpu.t; setzf(cpu.a); lni;"} }, + { mnem="rol imm8" , opcode=0xD2, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpRol" ,"instrNext"}, desc="A<<<=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=rol(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, + { mnem="ror imm8" , opcode=0xD3, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpRor" ,"instrNext"}, desc="A>>>=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=ror(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, + { mnem="sra imm8" , opcode=0xD4, {"loadImmedT","instrSub1"}, {"aluA", "alurT","aluOpSra" ,"instrNext"}, desc="A>>a=imm8, set zero flag" , ccode={"loadimmedt","cpu.a=sra(cpu.a,cpu.t); setzf(cpu.a); lni;"} }, + { mnem="add *s+imm8" , opcode=0xAE, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAdd" ,"instrNext"}, desc="A+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u); lni;"} }, + { mnem="adb *s+imm8" , opcode=0x9B, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpAdd" ,"instrNext"}, desc="B+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.b,cpu.u); lni;"} }, + { mnem="adc *s+imm8" , opcode=0x9C, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpAdd" ,"instrNext"}, desc="C+=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.c,cpu.u); lni;"} }, + { mnem="sub *s+imm8" , opcode=0xAF, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSub" ,"instrNext"}, desc="A-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.a,cpu.u); lni;"} }, + { mnem="sbb *s+imm8" , opcode=0x9D, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluB", "alurT","aluOpSub" ,"instrNext"}, desc="B-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.b,cpu.u); lni;"} }, + { mnem="sbc *s+imm8" , opcode=0x9E, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluC", "alurT","aluOpSub" ,"instrNext"}, desc="C-=*(S+imm8), set flags" , ccode={"loadimmedt","loadstackrelu","subf(cpu.c,cpu.u); lni;"} }, + { mnem="acc *s+imm8" , opcode=0xB5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAddC","instrNext"}, desc="A+=*(S+imm8)+CF, set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,cpu.u+cpu.cf); lni;"} }, + { mnem="scc *s+imm8" , opcode=0xB7, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSubC","instrNext"}, desc="A-=*(S+imm8)+CF, set flags" , ccode={"loadimmedt","loadstackrelu","addf(cpu.a,-cpu.u+cpu.cf); lni;"} }, + { mnem="cmp *s+imm8" , opcode=0xB0, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"alulA","alurT","aluOpSub" ,"instrNext"}, desc="set flags according to A-*(S+imm8)", ccode={"loadimmedt","loadstackrelu","cmpf(cpu.a,cpu.u); lni;"} }, + { mnem="and *s+imm8" , opcode=0xB1, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnd" ,"instrNext"}, desc="A&=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a&=cpu.u; setzf(cpu.a); lni;"} }, + { mnem="ior *s+imm8" , opcode=0xB2, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpIor" ,"instrNext"}, desc="A|=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a|=cpu.u; setzf(cpu.a); lni;"} }, + { mnem="xor *s+imm8" , opcode=0xB3, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpXor" ,"instrNext"}, desc="A^=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a^=cpu.u; setzf(cpu.a); lni;"} }, + { mnem="ann *s+imm8" , opcode=0xB4, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpAnn" ,"instrNext"}, desc="A&=~*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a&=~cpu.u; setzf(cpu.a); lni;"} }, + { mnem="shl *s+imm8" , opcode=0xD5, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpShl" ,"instrNext"}, desc="A<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a<<=cpu.u; setzf(cpu.a); lni;"} }, + { mnem="shr *s+imm8" , opcode=0xD6, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpShr" ,"instrNext"}, desc="A<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a>>=cpu.u; setzf(cpu.a); lni;"} }, + { mnem="rol *s+imm8" , opcode=0xD7, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpRol" ,"instrNext"}, desc="A<<<=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=rol(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, + { mnem="ror *s+imm8" , opcode=0xD8, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpRor" ,"instrNext"}, desc="A>>>=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=ror(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, + { mnem="sra *s+imm8" , opcode=0xD9, {"loadImmedT","instrSub1"}, {"loadStackRelT","instrSub2"}, {"aluA", "alurT","aluOpSra" ,"instrNext"}, desc="A>>a=*(S+imm8), set zero flag" , ccode={"loadimmedt","loadstackrelu","cpu.a=sra(cpu.a,cpu.u); setzf(cpu.a); lni;"} }, + { mnem="add b" , opcode=0xA0, {"aluA", "alurB","aluOpAdd" ,"instrNext"}, desc="A+=B, set flags" , ccode={"addf(cpu.a,cpu.b); lni;"} }, + { mnem="adc b" , opcode=0x9F, {"aluC", "alurB","aluOpAdd" ,"instrNext"}, desc="C+=B, set flags" , ccode={"addf(cpu.c,cpu.b); lni;"} }, + { mnem="sub b" , opcode=0xA1, {"aluA", "alurB","aluOpSub" ,"instrNext"}, desc="A-=B, set flags" , ccode={"subf(cpu.a,cpu.b); lni;"} }, + { mnem="sbc b" , opcode=0xB6, {"aluC", "alurB","aluOpSub" ,"instrNext"}, desc="C-=B, set flags" , ccode={"subf(cpu.c,cpu.b); lni;"} }, + { mnem="acc b" , opcode=0xB8, {"aluA", "alurB","aluOpAddC","instrNext"}, desc="A+=B+CF, set flags" , ccode={"addf(cpu.a,cpu.b+cpu.cf); lni;"} }, + { mnem="scc b" , opcode=0xB9, {"aluA", "alurB","aluOpSubC","instrNext"}, desc="A-=B+CF, set flags" , ccode={"addf(cpu.a,-cpu.b+cpu.cf); lni;"} }, + { mnem="cmp b" , opcode=0xA2, {"alulA","alurB","aluOpSub" ,"instrNext"}, desc="set flags according to A-B" , ccode={"cmpf(cpu.a,cpu.b); lni;"} }, + { mnem="and b" , opcode=0xA3, {"aluA", "alurB","aluOpAnd" ,"instrNext"}, desc="A&=B, set zero flag" , ccode={"cpu.a&=cpu.b; setzf(cpu.a); lni;"} }, + { mnem="ior b" , opcode=0xA4, {"aluA", "alurB","aluOpIor" ,"instrNext"}, desc="A|=B, set zero flag" , ccode={"cpu.a|=cpu.b; setzf(cpu.a); lni;"} }, + { mnem="xor b" , opcode=0xA5, {"aluA", "alurB","aluOpXor" ,"instrNext"}, desc="A^=B, set zero flag" , ccode={"cpu.a^=cpu.b; setzf(cpu.a); lni;"} }, + { mnem="ann b" , opcode=0xA6, {"aluA", "alurB","aluOpAnn" ,"instrNext"}, desc="A&=~B, set zero flag" , ccode={"cpu.a&=~cpu.b; setzf(cpu.a); lni;"} }, + { mnem="shl b" , opcode=0xDA, {"aluA", "alurB","aluOpShl" ,"instrNext"}, desc="A<<=B, set zero flag" , ccode={"cpu.a<<=cpu.b; setzf(cpu.a); lni;"} }, + { mnem="shr b" , opcode=0xDB, {"aluA", "alurB","aluOpShr" ,"instrNext"}, desc="A>>=B, set zero flag" , ccode={"cpu.a>>=cpu.b; setzf(cpu.a); lni;"} }, + { mnem="rol b" , opcode=0xDC, {"aluA", "alurB","aluOpRol" ,"instrNext"}, desc="A<<<=B, set zero flag" , ccode={"cpu.a=rol(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, + { mnem="ror b" , opcode=0xDD, {"aluA", "alurB","aluOpRor" ,"instrNext"}, desc="A>>>=B, set zero flag" , ccode={"cpu.a=ror(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, + { mnem="sra b" , opcode=0xDE, {"aluA", "alurB","aluOpSra" ,"instrNext"}, desc="A>>a=B, set zero flag" , ccode={"cpu.a=sra(cpu.a,cpu.b); setzf(cpu.a); lni;"} }, + { mnem="add c" , opcode=0xA7, {"aluA", "alurC","aluOpAdd" ,"instrNext"}, desc="A+=C, set flags" , ccode={"addf(cpu.a,cpu.c); lni;"} }, + { mnem="adb c" , opcode=0xBD, {"aluB", "alurC","aluOpAdd" ,"instrNext"}, desc="B+=C, set flags" , ccode={"addf(cpu.b,cpu.c); lni;"} }, + { mnem="sub c" , opcode=0xA8, {"aluA", "alurC","aluOpSub" ,"instrNext"}, desc="A-=C, set flags" , ccode={"subf(cpu.a,cpu.c); lni;"} }, + { mnem="sbb c" , opcode=0xBC, {"aluB", "alurC","aluOpSub" ,"instrNext"}, desc="B-=C, set flags" , ccode={"subf(cpu.b,cpu.c); lni;"} }, + { mnem="acc c" , opcode=0xBA, {"aluA", "alurC","aluOpAddC","instrNext"}, desc="A+=C+CF, set flags" , ccode={"addf(cpu.a,cpu.c+cpu.cf); lni;"} }, + { mnem="scc c" , opcode=0xBB, {"aluA", "alurC","aluOpSubC","instrNext"}, desc="A-=C+CF, set flags" , ccode={"addf(cpu.a,-cpu.c+cpu.cf); lni;"} }, + { mnem="cmp c" , opcode=0xA9, {"alulA","alurC","aluOpSub" ,"instrNext"}, desc="set flags according to A-C" , ccode={"cmpf(cpu.a,cpu.c); lni;"} }, + { mnem="and c" , opcode=0xAA, {"aluA", "alurC","aluOpAnd" ,"instrNext"}, desc="A&=C, set zero flag" , ccode={"cpu.a&=cpu.c; setzf(cpu.a); lni;"} }, + { mnem="ior c" , opcode=0xAB, {"aluA", "alurC","aluOpIor" ,"instrNext"}, desc="A|=C, set zero flag" , ccode={"cpu.a|=cpu.c; setzf(cpu.a); lni;"} }, + { mnem="xor c" , opcode=0xAC, {"aluA", "alurC","aluOpXor" ,"instrNext"}, desc="A^=C, set zero flag" , ccode={"cpu.a^=cpu.c; setzf(cpu.a); lni;"} }, + { mnem="ann c" , opcode=0xAD, {"aluA", "alurC","aluOpAnn" ,"instrNext"}, desc="A&=~C, set zero flag" , ccode={"cpu.a&=~cpu.c; setzf(cpu.a); lni;"} }, + { mnem="shl c" , opcode=0xDF, {"aluA", "alurC","aluOpShl" ,"instrNext"}, desc="A<<=C, set zero flag" , ccode={"cpu.a<<=cpu.c; setzf(cpu.a); lni;"} }, + { mnem="shr c" , opcode=0x4D, {"aluA", "alurC","aluOpShr" ,"instrNext"}, desc="A>>=C, set zero flag" , ccode={"cpu.a>>=cpu.c; setzf(cpu.a); lni;"} }, + { mnem="rol c" , opcode=0x3E, {"aluA", "alurC","aluOpRol" ,"instrNext"}, desc="A<<<=C, set zero flag" , ccode={"cpu.a=rol(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, + { mnem="ror c" , opcode=0x3F, {"aluA", "alurC","aluOpRor" ,"instrNext"}, desc="A>>>=C, set zero flag" , ccode={"cpu.a=ror(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, + { mnem="sra c" , opcode=0x2F, {"aluA", "alurC","aluOpSra" ,"instrNext"}, desc="A>>a=C, set zero flag" , ccode={"cpu.a=sra(cpu.a,cpu.c); setzf(cpu.a); lni;"} }, + { mnem="adb a" , opcode=0xBE, {"aluB", "alurA","aluOpAdd" ,"instrNext"}, desc="B+=A, set flags" , ccode={"addf(cpu.b,cpu.a); lni;"} }, + { mnem="sbb a" , opcode=0xBF, {"aluB", "alurA","aluOpSub" ,"instrNext"}, desc="B-=A, set flags" , ccode={"subf(cpu.b,cpu.a); lni;"} }, + { mnem="adc a" , opcode=0x4E, {"aluC", "alurA","aluOpAdd" ,"instrNext"}, desc="C+=A, set flags" , ccode={"addf(cpu.c,cpu.a); lni;"} }, + { mnem="sbc a" , opcode=0x4F, {"aluC", "alurA","aluOpSub" ,"instrNext"}, desc="C-=A, set flags" , ccode={"subf(cpu.c,cpu.a); lni;"} }, - { category = "Jumps", catlet="J" }, - { mnem="jmp imm16" , opcode=0x60, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"jmpAbsUT" }, desc="I=imm16" , ccode={"loadimm161","loadimm162","jmpabsut"} }, - { mnem="jsr imm16" , opcode=0x63, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"jmpAbsUT","saveRetAddr"}, desc="I=imm16, Q=I", ccode={"loadimm161","loadimm162","jmpabsut saveretaddr"} }, - { mnem="jss imm16" , opcode=0xE2, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"pushRetAddr1","instrSub3"}, {"pushRetAddr2","instrSub4"}, {"jmpAbsUT"}, desc="I=imm16, *(S++++)=I-1", ccode={"loadimm161","loadimm162","pushretaddr1","pushretaddr2","jmpabsut"} }, - { mnem="jmp p" , opcode=0x64, {"jmpAbsP" }, desc="I=P" , ccode={"jmpabsp"} }, - { mnem="jmp q" , opcode=0x66, {"jmpAbsQ" }, desc="I=Q" , ccode={"jmpabsq"} }, - { mnem="jsr p" , opcode=0x65, {"jmpAbsP","saveRetAddr"}, desc="I=P, Q=I", ccode={"jmpabsp","saveretaddr"} }, - { mnem="jsr q" , opcode=0x67, {"jmpAbsQ","saveRetAddr"}, desc="I=Q, Q=I", ccode={"jmpabsq","saveretaddr"} }, - { mnem="jss p" , opcode=0xE4, {"pushRetAddr1","instrSub1"}, {"pushRetAddr2","instrSub2"}, {"jmpAbsP"}, desc="I=P, *(S++++)=I-1", ccode={"pushretaddr1","pushretaddr2","jmpabsp"} }, - { mnem="jss q" , opcode=0xE5, {"pushRetAddr1","instrSub1"}, {"pushRetAddr2","instrSub2"}, {"jmpAbsQ"}, desc="I=Q, *(S++++)=I-1", ccode={"pushretaddr1","pushretaddr2","jmpabsq"} }, - { mnem="rts" , opcode=0xE1, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"jmpAbsUT","adrInc"}, desc="I=*(----S)+1", ccode={"pop161","pop162","jmpabsutplus1"} }, - { mnem="jpr imm8" , opcode=0x31, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub1"}, {"jmpRelT"}, desc="I+=imm8", ccode={"loadimmedt","jmprelt"} }, - { mnem="jnz imm8" , opcode=0x30, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NZ" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Zero" , ccode={"loadimmedt","if( cpu.nz ) { jmprelt } else { lni }"} }, - { mnem="jpz imm8" , opcode=0x32, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0Z" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero" , ccode={"loadimmedt","if(!cpu.nz ) { jmprelt } else { lni }"} }, - { mnem="jlt imm8" , opcode=0x33, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" , ccode={"loadimmedt","if(!cpu.cf ) { jmprelt } else { lni }"} }, - { mnem="jge imm8" , opcode=0x34, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" , ccode={"loadimmedt","if( cpu.cf ) { jmprelt } else { lni }"} }, - { mnem="jgt imm8" , opcode=0x35, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero & Carry", ccode={"loadimmedt","if( cpu.nz && cpu.cf ) { jmprelt } else { lni }"} }, - { mnem="jle imm8" , opcode=0x36, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero | !Carry", ccode={"loadimmedt","if((!cpu.nz) || (!cpu.cf)) { jmprelt } else { lni }"} }, + { category = "Jumps" , catlet="J" }, + { mnem="jmp imm16" , opcode=0x60, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"jmpAbsUT" }, desc="I=imm16" , ccode={"loadimm161","loadimm162","jmpabsut"} }, + { mnem="jsr imm16" , opcode=0x63, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"jmpAbsUT","saveRetAddr"}, desc="I=imm16, Q=I", ccode={"loadimm161","loadimm162","jmpabsut saveretaddr"} }, + { mnem="jss imm16" , opcode=0xE2, jmp=true, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"pushRetAddr1","instrSub3"}, {"pushRetAddr2","instrSub4"}, {"jmpAbsUT"}, desc="I=imm16, *(S++++)=I-1", ccode={"loadimm161","loadimm162","pushretaddr1","pushretaddr2","jmpabsut"} }, + { mnem="jmp p" , opcode=0x64, {"jmpAbsP" }, desc="I=P" , ccode={"jmpabsp"} }, + { mnem="jmp q" , opcode=0x66, {"jmpAbsQ" }, desc="I=Q" , ccode={"jmpabsq"} }, + { mnem="jsr p" , opcode=0x65, {"jmpAbsP","saveRetAddr"}, desc="I=P, Q=I", ccode={"jmpabsp","saveretaddr"} }, + { mnem="jsr q" , opcode=0x67, {"jmpAbsQ","saveRetAddr"}, desc="I=Q, Q=I", ccode={"jmpabsq","saveretaddr"} }, + { mnem="jss p" , opcode=0xE4, {"pushRetAddr1","instrSub1"}, {"pushRetAddr2","instrSub2"}, {"jmpAbsP"}, desc="I=P, *(S++++)=I-1", ccode={"pushretaddr1","pushretaddr2","jmpabsp"} }, + { mnem="jss q" , opcode=0xE5, {"pushRetAddr1","instrSub1"}, {"pushRetAddr2","instrSub2"}, {"jmpAbsQ"}, desc="I=Q, *(S++++)=I-1", ccode={"pushretaddr1","pushretaddr2","jmpabsq"} }, + { mnem="rts" , opcode=0xE1, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"jmpAbsUT","adrInc"}, desc="I=*(----S)+1", ccode={"pop161","pop162","jmpabsutplus1"} }, + { mnem="jpr imm8" , opcode=0x31, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub1"}, {"jmpRelT"}, desc="I+=imm8", ccode={"loadimmedt","jmprelt"} }, + { mnem="jnz imm8" , opcode=0x30, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NZ" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Zero" , ccode={"loadimmedt","if( cpu.nz ) { jmprelt } else { lni }"} }, + { mnem="jpz imm8" , opcode=0x32, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0Z" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero" , ccode={"loadimmedt","if(!cpu.nz ) { jmprelt } else { lni }"} }, + { mnem="jlt imm8" , opcode=0x33, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" , ccode={"loadimmedt","if(!cpu.cf ) { jmprelt } else { lni }"} }, + { mnem="jge imm8" , opcode=0x34, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" , ccode={"loadimmedt","if( cpu.cf ) { jmprelt } else { lni }"} }, + { mnem="jgt imm8" , opcode=0x35, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero & Carry", ccode={"loadimmedt","if( cpu.nz && cpu.cf ) { jmprelt } else { lni }"} }, + { mnem="jle imm8" , opcode=0x36, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero | !Carry", ccode={"loadimmedt","if((!cpu.nz) || (!cpu.cf)) { jmprelt } else { lni }"} }, - { category = "Stack", catlet="S" }, - { mnem="psh a" , opcode=0x40, {"pushReg","alurA","instrSub1"}, {"instrNext"}, desc="*(S++)=A", ccode={"pushbyte(cpu.a);","lni;"} }, - { mnem="psh b" , opcode=0x44, {"pushReg","alurB","instrSub1"}, {"instrNext"}, desc="*(S++)=B", ccode={"pushbyte(cpu.b);","lni;"} }, - { mnem="psh c" , opcode=0x45, {"pushReg","alurC","instrSub1"}, {"instrNext"}, desc="*(S++)=C", ccode={"pushbyte(cpu.c);","lni;"} }, - { mnem="psh f" , opcode=0xE9, {"pushReg","alurF","instrSub1"}, {"instrNext"}, desc="*(S++)=F", ccode={"int f = cpu.nz | (cpu.cf<<1); pushbyte(f);","lni;"} }, - { mnem="psh p" , opcode=0x41, {"pushReg","alurPH","instrSub1"}, {"pushReg","alurPL","instrSub2"}, {"instrNext"}, desc="*(S++++)=P", ccode={"push161(cpu.p);","push162(cpu.p);","lni;"} }, - { mnem="psh q" , opcode=0x46, {"pushReg","alurQH","instrSub1"}, {"pushReg","alurQL","instrSub2"}, {"instrNext"}, desc="*(S++++)=Q", ccode={"push161(cpu.q);","push162(cpu.q);","lni;"} }, - { mnem="pop a" , opcode=0x42, {"popReg","memSaveA","instrSub1"}, {"instrNext"}, desc="A=*(--S)", ccode={"cpu.a=popbyte;","lni;"} }, - { mnem="pop b" , opcode=0x47, {"popReg","memSaveB","instrSub1"}, {"instrNext"}, desc="B=*(--S)", ccode={"cpu.b=popbyte;","lni;"} }, - { mnem="pop c" , opcode=0x48, {"popReg","memSaveC","instrSub1"}, {"instrNext"}, desc="C=*(--S)", ccode={"cpu.c=popbyte;","lni;"} }, - { mnem="pop f" , opcode=0xEA, {"popReg","memSaveF","instrSub1"}, {"instrNext"}, desc="F=*(--S)", ccode={"int f=popbyte; cpu.nz = f&1; cpu.cf = (f>>1)&1;","lni;"} }, - { mnem="pop p" , opcode=0x43, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*(----S)", ccode={"pop161","pop162","cpu.p=wordut; lni;"} }, - { mnem="pop q" , opcode=0x49, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*(----S)", ccode={"pop161","pop162","cpu.q=wordut; lni;"} }, - { mnem="psh imm8" , opcode=0x3B, {"loadImmedT","instrSub1"}, {"pushReg","alurT","instrSub2"}, {"instrNext"}, desc="*(S++)=imm8", ccode={"loadimmedt;","pushbyte(cpu.t);","lni;"} }, - { mnem="phw imm16" , opcode=0x3C, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"pushReg","alurU","instrSub3"}, {"pushReg","alurT","instrSub4"}, {"instrNext"}, desc="*(S++++)=imm16", ccode={"loadimm161","loadimm162","pushbyte(cpu.u);","pushbyte(cpu.t);","lni;"} }, -- 0x3D + { category = "Stack" , catlet="S" }, + { mnem="psh a" , opcode=0x40, {"pushReg","alurA","instrSub1"}, {"instrNext"}, desc="*(S++)=A", ccode={"pushbyte(cpu.a);","lni;"} }, + { mnem="psh b" , opcode=0x44, {"pushReg","alurB","instrSub1"}, {"instrNext"}, desc="*(S++)=B", ccode={"pushbyte(cpu.b);","lni;"} }, + { mnem="psh c" , opcode=0x45, {"pushReg","alurC","instrSub1"}, {"instrNext"}, desc="*(S++)=C", ccode={"pushbyte(cpu.c);","lni;"} }, + { mnem="psh f" , opcode=0xE9, {"pushReg","alurF","instrSub1"}, {"instrNext"}, desc="*(S++)=F", ccode={"int f = cpu.nz | (cpu.cf<<1); pushbyte(f);","lni;"} }, + { mnem="psh p" , opcode=0x41, {"pushReg","alurPH","instrSub1"}, {"pushReg","alurPL","instrSub2"}, {"instrNext"}, desc="*(S++++)=P", ccode={"push161(cpu.p);","push162(cpu.p);","lni;"} }, + { mnem="psh q" , opcode=0x46, {"pushReg","alurQH","instrSub1"}, {"pushReg","alurQL","instrSub2"}, {"instrNext"}, desc="*(S++++)=Q", ccode={"push161(cpu.q);","push162(cpu.q);","lni;"} }, + { mnem="pop a" , opcode=0x42, {"popReg","memSaveA","instrSub1"}, {"instrNext"}, desc="A=*(--S)", ccode={"cpu.a=popbyte;","lni;"} }, + { mnem="pop b" , opcode=0x47, {"popReg","memSaveB","instrSub1"}, {"instrNext"}, desc="B=*(--S)", ccode={"cpu.b=popbyte;","lni;"} }, + { mnem="pop c" , opcode=0x48, {"popReg","memSaveC","instrSub1"}, {"instrNext"}, desc="C=*(--S)", ccode={"cpu.c=popbyte;","lni;"} }, + { mnem="pop f" , opcode=0xEA, {"popReg","memSaveF","instrSub1"}, {"instrNext"}, desc="F=*(--S)", ccode={"int f=popbyte; cpu.nz = f&1; cpu.cf = (f>>1)&1;","lni;"} }, + { mnem="pop p" , opcode=0x43, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*(----S)", ccode={"pop161","pop162","cpu.p=wordut; lni;"} }, + { mnem="pop q" , opcode=0x49, {"pop161","instrSub1"}, {"pop162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*(----S)", ccode={"pop161","pop162","cpu.q=wordut; lni;"} }, + { mnem="psh imm8" , opcode=0x3B, {"loadImmedT","instrSub1"}, {"pushReg","alurT","instrSub2"}, {"instrNext"}, desc="*(S++)=imm8", ccode={"loadimmedt;","pushbyte(cpu.t);","lni;"} }, + { mnem="phw imm16" , opcode=0x3C, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"pushReg","alurU","instrSub3"}, {"pushReg","alurT","instrSub4"}, {"instrNext"}, desc="*(S++++)=imm16", ccode={"loadimm161","loadimm162","pushbyte(cpu.u);","pushbyte(cpu.t);","lni;"} }, -- 0x3D { category = "8-bit Load/Store", catlet="B" }, - { mnem="lda imm8" , opcode=0x20, {"loadImmed", "memSaveA","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=imm8, update zero flag", ccode={"cpu.a=loadimmed; setzf(cpu.a);","lni;"} }, - { mnem="ldb imm8" , opcode=0x26, {"loadImmed", "memSaveB","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=imm8, update zero flag", ccode={"cpu.b=loadimmed; setzf(cpu.b);","lni;"} }, - { mnem="ldc imm8" , opcode=0x27, {"loadImmed", "memSaveC","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=imm8, update zero flag", ccode={"cpu.c=loadimmed; setzf(cpu.c);","lni;"} }, - { mnem="lda *s+imm8", opcode=0x28, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveA","memSaveFlags","instrSub2"}, {"instrNext"}, desc="A=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.a=loadstackrel; setzf(cpu.a);","lni;"} }, - { mnem="ldb *s+imm8", opcode=0x29, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveB","memSaveFlags","instrSub2"}, {"instrNext"}, desc="B=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.b=loadstackrel; setzf(cpu.b);","lni;"} }, - { mnem="ldc *s+imm8", opcode=0x2A, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveC","memSaveFlags","instrSub2"}, {"instrNext"}, desc="C=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.c=loadstackrel; setzf(cpu.c);","lni;"} }, - { mnem="sta *s+imm8", opcode=0x96, {"loadImmedT","instrSub1"}, {"storeStackRel","alurA","instrSub2"}, {"instrNext"}, desc="*s+imm8=A", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, - { mnem="stb *s+imm8", opcode=0x97, {"loadImmedT","instrSub1"}, {"storeStackRel","alurB","instrSub2"}, {"instrNext"}, desc="*s+imm8=B", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, - { mnem="stc *s+imm8", opcode=0x98, {"loadImmedT","instrSub1"}, {"storeStackRel","alurC","instrSub2"}, {"instrNext"}, desc="*s+imm8=C", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, - { mnem="lda *imm16" , opcode=0x51, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","loadReg","memSaveA","memSaveFlags","instrSub3"}, {"instrNext"}, desc="A=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.a=loadut; setzf(cpu.a);","lni;"} }, - { mnem="ldb *imm16" , opcode=0x56, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","loadReg","memSaveB","memSaveFlags","instrSub3"}, {"instrNext"}, desc="B=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.b=loadut; setzf(cpu.b);","lni;"} }, - { mnem="ldc *imm16" , opcode=0x57, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","loadReg","memSaveC","memSaveFlags","instrSub3"}, {"instrNext"}, desc="C=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.c=loadut; setzf(cpu.c);","lni;"} }, - { mnem="sta *imm16" , opcode=0x50, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","storeReg","alurA","instrSub3"}, {"instrNext"}, desc="*imm16=A", ccode={"loadimm161","loadimm162","storeut(cpu.a);","lni;"} }, - { mnem="stb *imm16" , opcode=0x58, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","storeReg","alurB","instrSub3"}, {"instrNext"}, desc="*imm16=B", ccode={"loadimm161","loadimm162","storeut(cpu.b);","lni;"} }, - { mnem="stc *imm16" , opcode=0x59, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2",}, {"adrrUT","storeReg","alurC","instrSub3"}, {"instrNext"}, desc="*imm16=C", ccode={"loadimm161","loadimm162","storeut(cpu.c);","lni;"} }, - { mnem="sta *p" , opcode=0x52, {"adrlP","storeReg","alurA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P=A", ccode={"storep(cpu.a);","lni;"} }, - { mnem="stb *p" , opcode=0x5A, {"adrlP","storeReg","alurB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P=B", ccode={"storep(cpu.b);","lni;"} }, - { mnem="stc *p" , opcode=0x5B, {"adrlP","storeReg","alurC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P=C", ccode={"storep(cpu.c);","lni;"} }, - { mnem="sta *q" , opcode=0x54, {"adrlQ","storeReg","alurA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q=A", ccode={"storeq(cpu.a);","lni;"} }, - { mnem="stb *q" , opcode=0x5C, {"adrlQ","storeReg","alurB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q=B", ccode={"storeq(cpu.b);","lni;"} }, - { mnem="stc *q" , opcode=0x5D, {"adrlQ","storeReg","alurC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q=C", ccode={"storeq(cpu.c);","lni;"} }, - { mnem="lda *p" , opcode=0x53, {"adrlP","loadReg","memSaveA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*P, update zero flag", ccode={"cpu.a=loadp; setzf(cpu.a);","lni;"} }, - { mnem="ldb *p" , opcode=0x5E, {"adrlP","loadReg","memSaveB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*P, update zero flag", ccode={"cpu.b=loadp; setzf(cpu.b);","lni;"} }, - { mnem="ldc *p" , opcode=0x5F, {"adrlP","loadReg","memSaveC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*P, update zero flag", ccode={"cpu.c=loadp; setzf(cpu.c);","lni;"} }, - { mnem="lda *q" , opcode=0x55, {"adrlQ","loadReg","memSaveA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*Q, update zero flag", ccode={"cpu.a=loadq; setzf(cpu.a);","lni;"} }, - { mnem="ldb *q" , opcode=0x61, {"adrlQ","loadReg","memSaveB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*Q, update zero flag", ccode={"cpu.b=loadq; setzf(cpu.b);","lni;"} }, - { mnem="ldc *q" , opcode=0x62, {"adrlQ","loadReg","memSaveC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*Q, update zero flag", ccode={"cpu.c=loadq; setzf(cpu.c);","lni;"} }, - { mnem="sta *p++" , opcode=0xC0, {"adrlP","storeReg","alurA", "incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P++=A", ccode={"storepinc(cpu.a);","lni;"} }, - { mnem="stb *p++" , opcode=0xC1, {"adrlP","storeReg","alurB", "incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P++=B", ccode={"storepinc(cpu.b);","lni;"} }, - { mnem="stc *p++" , opcode=0xC2, {"adrlP","storeReg","alurC", "incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*P++=C", ccode={"storepinc(cpu.c);","lni;"} }, - { mnem="sta *q++" , opcode=0xC3, {"adrlQ","storeReg","alurA", "incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q++=A", ccode={"storeqinc(cpu.a);","lni;"} }, - { mnem="stb *q++" , opcode=0xC4, {"adrlQ","storeReg","alurB", "incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q++=B", ccode={"storeqinc(cpu.b);","lni;"} }, - { mnem="stc *q++" , opcode=0xC5, {"adrlQ","storeReg","alurC", "incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="*Q++=C", ccode={"storeqinc(cpu.c);","lni;"} }, - { mnem="lda *p++" , opcode=0xC6, {"adrlP","loadReg","memSaveA","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*P++, update zero flag", ccode={"cpu.a=loadpinc; setzf(cpu.a);","lni;"} }, - { mnem="ldb *p++" , opcode=0xC7, {"adrlP","loadReg","memSaveB","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*P++, update zero flag", ccode={"cpu.b=loadpinc; setzf(cpu.b);","lni;"} }, - { mnem="ldc *p++" , opcode=0xC8, {"adrlP","loadReg","memSaveC","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*P++, update zero flag", ccode={"cpu.c=loadpinc; setzf(cpu.c);","lni;"} }, - { mnem="lda *q++" , opcode=0xC9, {"adrlQ","loadReg","memSaveA","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*Q++, update zero flag", ccode={"cpu.a=loadqinc; setzf(cpu.a);","lni;"} }, - { mnem="ldb *q++" , opcode=0xCA, {"adrlQ","loadReg","memSaveB","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*Q++, update zero flag", ccode={"cpu.b=loadqinc; setzf(cpu.b);","lni;"} }, - { mnem="ldc *q++" , opcode=0xCB, {"adrlQ","loadReg","memSaveC","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*Q++, update zero flag", ccode={"cpu.c=loadqinc; setzf(cpu.c);","lni;"} }, + { mnem="lda imm8" , opcode=0x20, {"loadImmed", "memSaveA","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=imm8, update zero flag", ccode={"cpu.a=loadimmed; setzf(cpu.a);","lni;"} }, + { mnem="ldb imm8" , opcode=0x26, {"loadImmed", "memSaveB","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=imm8, update zero flag", ccode={"cpu.b=loadimmed; setzf(cpu.b);","lni;"} }, + { mnem="ldc imm8" , opcode=0x27, {"loadImmed", "memSaveC","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=imm8, update zero flag", ccode={"cpu.c=loadimmed; setzf(cpu.c);","lni;"} }, + { mnem="lda *s+imm8" , opcode=0x28, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveA","memSaveFlags","instrSub2"}, {"instrNext"}, desc="A=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.a=loadstackrel; setzf(cpu.a);","lni;"} }, + { mnem="ldb *s+imm8" , opcode=0x29, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveB","memSaveFlags","instrSub2"}, {"instrNext"}, desc="B=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.b=loadstackrel; setzf(cpu.b);","lni;"} }, + { mnem="ldc *s+imm8" , opcode=0x2A, {"loadImmedT","instrSub1"}, {"loadStackRel","memSaveC","memSaveFlags","instrSub2"}, {"instrNext"}, desc="C=*s+imm8, update zero flag", ccode={"loadimmedt;","cpu.c=loadstackrel; setzf(cpu.c);","lni;"} }, + { mnem="sta *s+imm8" , opcode=0x96, {"loadImmedT","instrSub1"}, {"storeStackRel","alurA","instrSub2"}, {"instrNext"}, desc="*s+imm8=A", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, + { mnem="stb *s+imm8" , opcode=0x97, {"loadImmedT","instrSub1"}, {"storeStackRel","alurB","instrSub2"}, {"instrNext"}, desc="*s+imm8=B", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, + { mnem="stc *s+imm8" , opcode=0x98, {"loadImmedT","instrSub1"}, {"storeStackRel","alurC","instrSub2"}, {"instrNext"}, desc="*s+imm8=C", ccode={"loadimmedt;","storestackrel(cpu.a);","lni;"} }, + { mnem="lda *imm16" , opcode=0x51, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "loadReg", "memSaveA","memSaveFlags","instrSub3"}, {"instrNext"}, desc="A=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.a=loadut; setzf(cpu.a);", "lni;"} }, + { mnem="ldb *imm16" , opcode=0x56, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "loadReg", "memSaveB","memSaveFlags","instrSub3"}, {"instrNext"}, desc="B=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.b=loadut; setzf(cpu.b);", "lni;"} }, + { mnem="ldc *imm16" , opcode=0x57, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "loadReg", "memSaveC","memSaveFlags","instrSub3"}, {"instrNext"}, desc="C=*imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.c=loadut; setzf(cpu.c);", "lni;"} }, + { mnem="sta *imm16" , opcode=0x50, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "storeReg","alurA", "instrSub3"}, {"instrNext"}, desc="*imm16=A", ccode={"loadimm161","loadimm162","storeut(cpu.a);", "lni;"} }, + { mnem="stb *imm16" , opcode=0x58, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "storeReg","alurB", "instrSub3"}, {"instrNext"}, desc="*imm16=B", ccode={"loadimm161","loadimm162","storeut(cpu.b);", "lni;"} }, + { mnem="stc *imm16" , opcode=0x59, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT", "storeReg","alurC", "instrSub3"}, {"instrNext"}, desc="*imm16=C", ccode={"loadimm161","loadimm162","storeut(cpu.c);", "lni;"} }, + { mnem="lda *p+imm16", opcode=0x01, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","loadReg", "memSaveA","memSaveFlags","instrSub3"}, {"instrNext"}, desc="A=*P+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.a=loadput; setzf(cpu.a);","lni;"} }, + { mnem="ldb *p+imm16", opcode=0xF7, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","loadReg", "memSaveB","memSaveFlags","instrSub3"}, {"instrNext"}, desc="B=*P+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.b=loadput; setzf(cpu.b);","lni;"} }, + { mnem="ldc *p+imm16", opcode=0xFE, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","loadReg", "memSaveC","memSaveFlags","instrSub3"}, {"instrNext"}, desc="C=*P+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.c=loadput; setzf(cpu.c);","lni;"} }, + { mnem="lda *q+imm16", opcode=0xEB, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","loadReg", "memSaveA","memSaveFlags","instrSub3"}, {"instrNext"}, desc="A=*Q+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.a=loadqut; setzf(cpu.a);","lni;"} }, + { mnem="ldb *q+imm16", opcode=0x08, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","loadReg", "memSaveB","memSaveFlags","instrSub3"}, {"instrNext"}, desc="B=*Q+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.b=loadqut; setzf(cpu.b);","lni;"} }, + { mnem="ldc *q+imm16", opcode=0x09, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","loadReg", "memSaveC","memSaveFlags","instrSub3"}, {"instrNext"}, desc="C=*Q+imm16, update zero flag", ccode={"loadimm161","loadimm162","cpu.c=loadqut; setzf(cpu.c);","lni;"} }, + { mnem="sta *p+imm16", opcode=0x0A, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","storeReg","alurA", "instrSub3"}, {"instrNext"}, desc="*P+imm16=A", ccode={"loadimm161","loadimm162","storeput(cpu.a);", "lni;"} }, + { mnem="stb *p+imm16", opcode=0x0B, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","storeReg","alurB", "instrSub3"}, {"instrNext"}, desc="*P+imm16=B", ccode={"loadimm161","loadimm162","storeput(cpu.b);", "lni;"} }, + { mnem="stc *p+imm16", opcode=0x0C, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlP","storeReg","alurC", "instrSub3"}, {"instrNext"}, desc="*P+imm16=C", ccode={"loadimm161","loadimm162","storeput(cpu.c);", "lni;"} }, + { mnem="sta *q+imm16", opcode=0x0D, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","storeReg","alurA", "instrSub3"}, {"instrNext"}, desc="*Q+imm16=A", ccode={"loadimm161","loadimm162","storequt(cpu.a);", "lni;"} }, + { mnem="stb *q+imm16", opcode=0x0E, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","storeReg","alurB", "instrSub3"}, {"instrNext"}, desc="*Q+imm16=B", ccode={"loadimm161","loadimm162","storequt(cpu.b);", "lni;"} }, + { mnem="stc *q+imm16", opcode=0x0F, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adrrUT","adrlQ","storeReg","alurC", "instrSub3"}, {"instrNext"}, desc="*Q+imm16=C", ccode={"loadimm161","loadimm162","storequt(cpu.c);", "lni;"} }, + { mnem="lda *p" , opcode=0x53, {"adrlP","loadReg", "memSaveA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*P, update zero flag", ccode={"cpu.a=loadp; setzf(cpu.a);","lni;"} }, + { mnem="ldb *p" , opcode=0x5E, {"adrlP","loadReg", "memSaveB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*P, update zero flag", ccode={"cpu.b=loadp; setzf(cpu.b);","lni;"} }, + { mnem="ldc *p" , opcode=0x5F, {"adrlP","loadReg", "memSaveC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*P, update zero flag", ccode={"cpu.c=loadp; setzf(cpu.c);","lni;"} }, + { mnem="lda *q" , opcode=0x55, {"adrlQ","loadReg", "memSaveA", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*Q, update zero flag", ccode={"cpu.a=loadq; setzf(cpu.a);","lni;"} }, + { mnem="ldb *q" , opcode=0x61, {"adrlQ","loadReg", "memSaveB", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*Q, update zero flag", ccode={"cpu.b=loadq; setzf(cpu.b);","lni;"} }, + { mnem="ldc *q" , opcode=0x62, {"adrlQ","loadReg", "memSaveC", "memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*Q, update zero flag", ccode={"cpu.c=loadq; setzf(cpu.c);","lni;"} }, + { mnem="sta *p" , opcode=0x52, {"adrlP","storeReg","alurA", "instrSub1"}, {"instrNext"}, desc="*P=A", ccode={"storep(cpu.a);","lni;"} }, + { mnem="stb *p" , opcode=0x5A, {"adrlP","storeReg","alurB", "instrSub1"}, {"instrNext"}, desc="*P=B", ccode={"storep(cpu.b);","lni;"} }, + { mnem="stc *p" , opcode=0x5B, {"adrlP","storeReg","alurC", "instrSub1"}, {"instrNext"}, desc="*P=C", ccode={"storep(cpu.c);","lni;"} }, + { mnem="sta *q" , opcode=0x54, {"adrlQ","storeReg","alurA", "instrSub1"}, {"instrNext"}, desc="*Q=A", ccode={"storeq(cpu.a);","lni;"} }, + { mnem="stb *q" , opcode=0x5C, {"adrlQ","storeReg","alurB", "instrSub1"}, {"instrNext"}, desc="*Q=B", ccode={"storeq(cpu.b);","lni;"} }, + { mnem="stc *q" , opcode=0x5D, {"adrlQ","storeReg","alurC", "instrSub1"}, {"instrNext"}, desc="*Q=C", ccode={"storeq(cpu.c);","lni;"} }, + { mnem="lda *p++" , opcode=0xC6, {"adrlP","loadReg", "memSaveA","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*P++, update zero flag", ccode={"cpu.a=loadpinc; setzf(cpu.a);","lni;"} }, + { mnem="ldb *p++" , opcode=0xC7, {"adrlP","loadReg", "memSaveB","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*P++, update zero flag", ccode={"cpu.b=loadpinc; setzf(cpu.b);","lni;"} }, + { mnem="ldc *p++" , opcode=0xC8, {"adrlP","loadReg", "memSaveC","incP","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*P++, update zero flag", ccode={"cpu.c=loadpinc; setzf(cpu.c);","lni;"} }, + { mnem="lda *q++" , opcode=0xC9, {"adrlQ","loadReg", "memSaveA","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="A=*Q++, update zero flag", ccode={"cpu.a=loadqinc; setzf(cpu.a);","lni;"} }, + { mnem="ldb *q++" , opcode=0xCA, {"adrlQ","loadReg", "memSaveB","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="B=*Q++, update zero flag", ccode={"cpu.b=loadqinc; setzf(cpu.b);","lni;"} }, + { mnem="ldc *q++" , opcode=0xCB, {"adrlQ","loadReg", "memSaveC","incQ","memSaveFlags","instrSub1"}, {"instrNext"}, desc="C=*Q++, update zero flag", ccode={"cpu.c=loadqinc; setzf(cpu.c);","lni;"} }, + { mnem="sta *p++" , opcode=0xC0, {"adrlP","storeReg","alurA", "incP", "instrSub1"}, {"instrNext"}, desc="*P++=A", ccode={"storepinc(cpu.a);","lni;"} }, + { mnem="stb *p++" , opcode=0xC1, {"adrlP","storeReg","alurB", "incP", "instrSub1"}, {"instrNext"}, desc="*P++=B", ccode={"storepinc(cpu.b);","lni;"} }, + { mnem="stc *p++" , opcode=0xC2, {"adrlP","storeReg","alurC", "incP", "instrSub1"}, {"instrNext"}, desc="*P++=C", ccode={"storepinc(cpu.c);","lni;"} }, + { mnem="sta *q++" , opcode=0xC3, {"adrlQ","storeReg","alurA", "incQ", "instrSub1"}, {"instrNext"}, desc="*Q++=A", ccode={"storeqinc(cpu.a);","lni;"} }, + { mnem="stb *q++" , opcode=0xC4, {"adrlQ","storeReg","alurB", "incQ", "instrSub1"}, {"instrNext"}, desc="*Q++=B", ccode={"storeqinc(cpu.b);","lni;"} }, + { mnem="stc *q++" , opcode=0xC5, {"adrlQ","storeReg","alurC", "incQ", "instrSub1"}, {"instrNext"}, desc="*Q++=C", ccode={"storeqinc(cpu.c);","lni;"} }, { category = "16-bit Load/Store", catlet="W" }, - { mnem="ldp imm16" , opcode=0x21, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; lni;"} }, - { mnem="ldq imm16" , opcode=0x23, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; lni;"} }, - { mnem="lds imm16" , opcode=0x25, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveS","instrNext"}, desc="S=imm16", ccode={"loadimm161","loadimm162","cpu.s=wordut; lni;"} }, - { mnem="ldv imm16" , opcode=0x22, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveV","instrNext"}, desc="V=imm16", ccode={"loadimm161","loadimm162","cpu.v=wordut; lni;"} }, - { mnem="ldp *s+imm8", opcode=0x7A, {"loadImmedT","instrSub1"}, {"loadStackRel161","instrSub2"}, {"loadStackRel162","instrSub3"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*S+imm8", ccode={"loadimmedt","loadstackrel161","loadstackrel162","cpu.p=wordut; lni;"} }, - { mnem="ldq *s+imm8", opcode=0x7B, {"loadImmedT","instrSub1"}, {"loadStackRel161","instrSub2"}, {"loadStackRel162","instrSub3"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*S+imm8", ccode={"loadimmedt","loadstackrel161","loadstackrel162","cpu.p=wordut; lni;"} }, - { mnem="stp *s+imm8", opcode=0x7E, {"loadImmedT","instrSub1"}, {"storeStackRel161","alurPH","instrSub2"}, {"storeStackRel162","alurPL","instrSub3"}, {"instrNext"}, desc="*S+imm8=P", ccode={"loadimmedt","storestackrel161(cpu.p);","storestackrel162(cpu.p);","lni;"} }, - { mnem="stq *s+imm8", opcode=0x7F, {"loadImmedT","instrSub1"}, {"storeStackRel161","alurQH","instrSub2"}, {"storeStackRel162","alurQL","instrSub3"}, {"instrNext"}, desc="*S+imm8=Q", ccode={"loadimmedt","storestackrel161(cpu.q);","storestackrel162(cpu.q);","lni;"} }, - { mnem="ldp *imm16" , opcode=0x68, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTU","adwIncUT","adwSaveP","instrSub3"}, {"adrlP","loadRegT","instrSub4"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; cpu.u=loadut;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, -- 0x69 - { mnem="ldq *imm16" , opcode=0x6A, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTU","adwIncUT","adwSaveQ","instrSub3"}, {"adrlQ","loadRegT","instrSub4"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; cpu.u=loadut;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, -- 0x6B - { mnem="stp *imm16" , opcode=0x6C, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUT","alurPH","instrSub3"}, {"storeUT","adrInc","alurPL","instrSub4"}, {"instrNext"}, desc="*imm16=P", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.p));","storeutp1(lobyte(cpu.p));","lni;"} }, -- 0x6D - { mnem="stq *imm16" , opcode=0x6E, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUT","alurQH","instrSub3"}, {"storeUT","adrInc","alurQL","instrSub4"}, {"instrNext"}, desc="*imm16=Q", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.q));","storeutp1(lobyte(cpu.q));","lni;"} }, -- 0x6F - { mnem="ldp *p" , opcode=0x92, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*P", ccode={"cpu.u=loadp;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, - { mnem="ldq *p" , opcode=0x93, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*P", ccode={"cpu.u=loadp;","cpu.t=loadpp1;","cpu.q=wordut; lni;"} }, - { mnem="ldp *q" , opcode=0x94, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*Q", ccode={"cpu.u=loadq;","cpu.t=loadqp1;","cpu.p=wordut; lni;"} }, - { mnem="ldq *q" , opcode=0x95, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*Q", ccode={"cpu.u=loadq;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, - { mnem="stp *q" , opcode=0x7C, {"adrlQ","store161","alurPH","instrSub1"}, {"adrlQ","store162","alurPL","instrSub2"}, {"instrNext"}, desc="*Q=P", ccode={"storeq(hibyte(cpu.p));","storeqp1(lobyte(cpu.p));","lni;"} }, - { mnem="stq *p" , opcode=0x7D, {"adrlP","store161","alurQH","instrSub1"}, {"adrlP","store162","alurQL","instrSub2"}, {"instrNext"}, desc="*P=Q", ccode={"storep(hibyte(cpu.q));","storepp1(lobyte(cpu.q));","lni;"} }, - { mnem="ldq *p++" , opcode=0xCC, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2","incP2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*P++++", ccode={"cpu.u=loadpinc;","cpu.t=loadpinc;","cpu.q=wordut; lni;"} }, - { mnem="ldp *q++" , opcode=0xCD, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2","incQ2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*Q++++", ccode={"cpu.u=loadqinc;","cpu.t=loadqinc;","cpu.p=wordut; lni;"} }, - { mnem="stp *q++" , opcode=0xCE, {"adrlQ","store161","alurPH","instrSub1"}, {"adrlQ","store162","alurPL","instrSub2","incQ2"}, {"instrNext"}, desc="*Q++++=P", ccode={"storeqinc(hibyte(cpu.p));","storeqinc(lobyte(cpu.p));","lni;"} }, - { mnem="stq *p++" , opcode=0xCF, {"adrlP","store161","alurQH","instrSub1"}, {"adrlP","store162","alurQL","instrSub2","incP2"}, {"instrNext"}, desc="*P++++=Q", ccode={"storepinc(hibyte(cpu.q));","storepinc(lobyte(cpu.q));","lni;"} }, + { mnem="ldp imm16" , opcode=0x21, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; lni;"} }, + { mnem="ldq imm16" , opcode=0x23, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; lni;"} }, + { mnem="lds imm16" , opcode=0x25, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveS","instrNext"}, desc="S=imm16", ccode={"loadimm161","loadimm162","cpu.s=wordut; lni;"} }, + { mnem="ldv imm16" , opcode=0x22, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"adwrUT","adwSaveV","instrNext"}, desc="V=imm16", ccode={"loadimm161","loadimm162","cpu.v=wordut; lni;"} }, + { mnem="ldp *s+imm8" , opcode=0x7A, {"loadImmedT","instrSub1"}, {"loadStackRel161","instrSub2"}, {"loadStackRel162","instrSub3"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*S+imm8", ccode={"loadimmedt","loadstackrel161","loadstackrel162","cpu.p=wordut; lni;"} }, + { mnem="ldq *s+imm8" , opcode=0x7B, {"loadImmedT","instrSub1"}, {"loadStackRel161","instrSub2"}, {"loadStackRel162","instrSub3"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*S+imm8", ccode={"loadimmedt","loadstackrel161","loadstackrel162","cpu.p=wordut; lni;"} }, + { mnem="stp *s+imm8" , opcode=0x7E, {"loadImmedT","instrSub1"}, {"storeStackRel161","alurPH","instrSub2"}, {"storeStackRel162","alurPL","instrSub3"}, {"instrNext"}, desc="*S+imm8=P", ccode={"loadimmedt","storestackrel161(cpu.p);","storestackrel162(cpu.p);","lni;"} }, + { mnem="stq *s+imm8" , opcode=0x7F, {"loadImmedT","instrSub1"}, {"storeStackRel161","alurQH","instrSub2"}, {"storeStackRel162","alurQL","instrSub3"}, {"instrNext"}, desc="*S+imm8=Q", ccode={"loadimmedt","storestackrel161(cpu.q);","storestackrel162(cpu.q);","lni;"} }, + { mnem="ldp *imm16" , opcode=0x68, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTU" ,"adwIncUT", "adwSaveP","instrSub3"}, {"adrlP","loadRegT", "instrSub4"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; cpu.u=loadut;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, -- 0x69 + { mnem="ldq *imm16" , opcode=0x6A, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTU" ,"adwIncUT", "adwSaveQ","instrSub3"}, {"adrlQ","loadRegT", "instrSub4"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; cpu.u=loadut;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, -- 0x6B + { mnem="stp *imm16" , opcode=0x6C, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUT" ,"alurPH", "instrSub3"}, {"storeUT","adrInc","alurPL", "instrSub4"}, { "instrNext"}, desc="*imm16=P", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.p));","storeutp1(lobyte(cpu.p));","lni;" } }, -- 0x6D + { mnem="stq *imm16" , opcode=0x6E, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUT" ,"alurQH", "instrSub3"}, {"storeUT","adrInc","alurQL", "instrSub4"}, { "instrNext"}, desc="*imm16=Q", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.q));","storeutp1(lobyte(cpu.q));","lni;" } }, -- 0x6F + { mnem="ldp *p+imm16", opcode=0xEC, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTUP","adwIncUTP","adwSaveP","instrSub3"}, {"adrlP","loadRegT", "instrSub4"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*P+imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; cpu.u=loadut;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, -- 0xED + { mnem="ldq *p+imm16", opcode=0xEE, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTUP","adwIncUTP","adwSaveQ","instrSub3"}, {"adrlQ","loadRegT", "instrSub4"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*P+imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; cpu.u=loadut;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, -- 0xEF + { mnem="ldp *q+imm16", opcode=0xF8, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTUQ","adwIncUTQ","adwSaveP","instrSub3"}, {"adrlP","loadRegT", "instrSub4"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*Q+imm16", ccode={"loadimm161","loadimm162","cpu.p=wordut; cpu.u=loadut;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, -- 0xF9 + { mnem="ldq *q+imm16", opcode=0xFA, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"loadUTUQ","adwIncUTQ","adwSaveQ","instrSub3"}, {"adrlQ","loadRegT", "instrSub4"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*Q+imm16", ccode={"loadimm161","loadimm162","cpu.q=wordut; cpu.u=loadut;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, -- 0xFB + { mnem="stq *p+imm16", opcode=0x06, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUTQ","alurQH", "instrSub3"}, {"storeUTQ","adrInc","alurQL","instrSub4"}, { "instrNext"}, desc="*P+imm16=Q", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.q));","storeutp1(lobyte(cpu.q));","lni;" } }, -- 0x07 + { mnem="stp *q+imm16", opcode=0xFC, {"loadImm161","instrSub1"}, {"loadImm162","instrSub2"}, {"storeUTP","alurPH", "instrSub3"}, {"storeUTP","adrInc","alurPL","instrSub4"}, { "instrNext"}, desc="*Q+imm16=P", ccode={"loadimm161","loadimm162","storeut(hibyte(cpu.p));","storeutp1(lobyte(cpu.p));","lni;" } }, -- 0xFD + { mnem="ldp *p" , opcode=0x92, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*P", ccode={"cpu.u=loadp;","cpu.t=loadpp1;","cpu.p=wordut; lni;"} }, + { mnem="ldq *p" , opcode=0x93, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*P", ccode={"cpu.u=loadp;","cpu.t=loadpp1;","cpu.q=wordut; lni;"} }, + { mnem="ldp *q" , opcode=0x94, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*Q", ccode={"cpu.u=loadq;","cpu.t=loadqp1;","cpu.p=wordut; lni;"} }, + { mnem="ldq *q" , opcode=0x95, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*Q", ccode={"cpu.u=loadq;","cpu.t=loadqp1;","cpu.q=wordut; lni;"} }, + { mnem="stp *q" , opcode=0x7C, {"adrlQ","store161","alurPH","instrSub1"}, {"adrlQ","store162","alurPL","instrSub2"}, {"instrNext"}, desc="*Q=P", ccode={"storeq(hibyte(cpu.p));","storeqp1(lobyte(cpu.p));","lni;"} }, + { mnem="stq *p" , opcode=0x7D, {"adrlP","store161","alurQH","instrSub1"}, {"adrlP","store162","alurQL","instrSub2"}, {"instrNext"}, desc="*P=Q", ccode={"storep(hibyte(cpu.q));","storepp1(lobyte(cpu.q));","lni;"} }, + { mnem="ldq *p++" , opcode=0xCC, {"adrlP","load161","instrSub1"}, {"adrlP","load162","instrSub2","incP2"}, {"adwrUT","adwSaveQ","instrNext"}, desc="Q=*P++++", ccode={"cpu.u=loadpinc;","cpu.t=loadpinc;","cpu.q=wordut; lni;"} }, + { mnem="ldp *q++" , opcode=0xCD, {"adrlQ","load161","instrSub1"}, {"adrlQ","load162","instrSub2","incQ2"}, {"adwrUT","adwSaveP","instrNext"}, desc="P=*Q++++", ccode={"cpu.u=loadqinc;","cpu.t=loadqinc;","cpu.p=wordut; lni;"} }, + { mnem="stp *q++" , opcode=0xCE, {"adrlQ","store161","alurPH","instrSub1"}, {"adrlQ","store162","alurPL","instrSub2","incQ2"}, {"instrNext"}, desc="*Q++++=P", ccode={"storeqinc(hibyte(cpu.p));","storeqinc(lobyte(cpu.p));","lni;"} }, + { mnem="stq *p++" , opcode=0xCF, {"adrlP","store161","alurQH","instrSub1"}, {"adrlP","store162","alurQL","instrSub2","incP2"}, {"instrNext"}, desc="*P++++=Q", ccode={"storepinc(hibyte(cpu.q));","storepinc(lobyte(cpu.q));","lni;"} }, - { category = "Moves", catlet="M" }, - { mnem="lda b" , opcode=0x80, {"alurB" ,"aluOpMov","aluSaveA","instrNext"}, desc="A=B", ccode={"cpu.a=cpu.b; lni;"} }, - { mnem="lda c" , opcode=0x81, {"alurC" ,"aluOpMov","aluSaveA","instrNext"}, desc="A=C", ccode={"cpu.a=cpu.c; lni;"} }, - { mnem="ldb a" , opcode=0x82, {"alurA" ,"aluOpMov","aluSaveB","instrNext"}, desc="B=A", ccode={"cpu.b=cpu.a; lni;"} }, - { mnem="ldb c" , opcode=0x83, {"alurC" ,"aluOpMov","aluSaveB","instrNext"}, desc="B=C", ccode={"cpu.b=cpu.c; lni;"} }, - { mnem="ldc a" , opcode=0x84, {"alurA" ,"aluOpMov","aluSaveC","instrNext"}, desc="C=A", ccode={"cpu.c=cpu.a; lni;"} }, - { mnem="ldc b" , opcode=0x85, {"alurB" ,"aluOpMov","aluSaveC","instrNext"}, desc="C=B", ccode={"cpu.c=cpu.b; lni;"} }, - { mnem="lda pl" , opcode=0x86, {"alurPL","aluOpMov","aluSaveA","instrNext"}, desc="A=P&FF", ccode={"cpu.a=lobyte(cpu.p); lni;"} }, - { mnem="lda ph" , opcode=0x87, {"alurPH","aluOpMov","aluSaveA","instrNext"}, desc="A=P>>8", ccode={"cpu.a=hibyte(cpu.p); lni;"} }, - { mnem="lda ql" , opcode=0x88, {"alurQL","aluOpMov","aluSaveA","instrNext"}, desc="A=Q&FF", ccode={"cpu.a=lobyte(cpu.q); lni;"} }, - { mnem="lda qh" , opcode=0x89, {"alurQH","aluOpMov","aluSaveA","instrNext"}, desc="A=Q>>8", ccode={"cpu.a=hibyte(cpu.q); lni;"} }, - { mnem="ldb pl" , opcode=0x37, {"alurPL","aluOpMov","aluSaveB","instrNext"}, desc="B=P&FF", ccode={"cpu.b=lobyte(cpu.p); lni;"} }, - { mnem="ldc ph" , opcode=0x38, {"alurPH","aluOpMov","aluSaveC","instrNext"}, desc="C=P>>8", ccode={"cpu.c=hibyte(cpu.p); lni;"} }, - { mnem="ldb ql" , opcode=0x39, {"alurQL","aluOpMov","aluSaveB","instrNext"}, desc="B=Q&FF", ccode={"cpu.b=lobyte(cpu.q); lni;"} }, - { mnem="ldc qh" , opcode=0x3A, {"alurQH","aluOpMov","aluSaveC","instrNext"}, desc="C=Q>>8", ccode={"cpu.c=hibyte(cpu.q); lni;"} }, - { mnem="ldp q" , opcode=0x8A, {"adwlQ" , "adwSaveP","instrNext"}, desc="P=Q", ccode={"cpu.p=cpu.q; lni;"} }, - { mnem="ldp s" , opcode=0x8B, {"adwlS" , "adwSaveP","instrNext"}, desc="P=S", ccode={"cpu.p=cpu.s; lni;"} }, - { mnem="ldp v" , opcode=0x8C, {"adwlV" , "adwSaveP","instrNext"}, desc="P=V", ccode={"cpu.p=cpu.v; lni;"} }, - { mnem="ldp i" , opcode=0x8D, {"adwlI" , "adwSaveP","instrNext"}, desc="P=I", ccode={"cpu.p=cpu.i; lni;"} }, - { mnem="ldp cb" , opcode=0x91, {"adwrCB", "adwSaveP","instrNext"}, desc="P=(C<<8)+B", ccode={"cpu.p=wordcb; lni;"} }, - { mnem="ldq cb" , opcode=0xE0, {"adwrCB", "adwSaveQ","instrNext"}, desc="Q=(C<<8)+B", ccode={"cpu.q=wordcb; lni;"} }, - { mnem="ldq p" , opcode=0x8E, {"adwlP" , "adwSaveQ","instrNext"}, desc="Q=P", ccode={"cpu.q=cpu.p; lni;"} }, - { mnem="lds p" , opcode=0x8F, {"adwlP" , "adwSaveS","instrNext"}, desc="S=P", ccode={"cpu.s=cpu.p; lni;"} }, - { mnem="ldv p" , opcode=0x90, {"adwlP" , "adwSaveV","instrNext"}, desc="V=P", ccode={"cpu.v=cpu.p; lni;"} }, + { category = "Moves" , catlet="M" }, + { mnem="lda b" , opcode=0x80, {"alurB" ,"aluOpMov","aluSaveA","instrNext"}, desc="A=B", ccode={"cpu.a=cpu.b; lni;"} }, + { mnem="lda c" , opcode=0x81, {"alurC" ,"aluOpMov","aluSaveA","instrNext"}, desc="A=C", ccode={"cpu.a=cpu.c; lni;"} }, + { mnem="ldb a" , opcode=0x82, {"alurA" ,"aluOpMov","aluSaveB","instrNext"}, desc="B=A", ccode={"cpu.b=cpu.a; lni;"} }, + { mnem="ldb c" , opcode=0x83, {"alurC" ,"aluOpMov","aluSaveB","instrNext"}, desc="B=C", ccode={"cpu.b=cpu.c; lni;"} }, + { mnem="ldc a" , opcode=0x84, {"alurA" ,"aluOpMov","aluSaveC","instrNext"}, desc="C=A", ccode={"cpu.c=cpu.a; lni;"} }, + { mnem="ldc b" , opcode=0x85, {"alurB" ,"aluOpMov","aluSaveC","instrNext"}, desc="C=B", ccode={"cpu.c=cpu.b; lni;"} }, + { mnem="lda pl" , opcode=0x86, {"alurPL","aluOpMov","aluSaveA","instrNext"}, desc="A=P&FF", ccode={"cpu.a=lobyte(cpu.p); lni;"} }, + { mnem="lda ph" , opcode=0x87, {"alurPH","aluOpMov","aluSaveA","instrNext"}, desc="A=P>>8", ccode={"cpu.a=hibyte(cpu.p); lni;"} }, + { mnem="lda ql" , opcode=0x88, {"alurQL","aluOpMov","aluSaveA","instrNext"}, desc="A=Q&FF", ccode={"cpu.a=lobyte(cpu.q); lni;"} }, + { mnem="lda qh" , opcode=0x89, {"alurQH","aluOpMov","aluSaveA","instrNext"}, desc="A=Q>>8", ccode={"cpu.a=hibyte(cpu.q); lni;"} }, + { mnem="ldb pl" , opcode=0x37, {"alurPL","aluOpMov","aluSaveB","instrNext"}, desc="B=P&FF", ccode={"cpu.b=lobyte(cpu.p); lni;"} }, + { mnem="ldc ph" , opcode=0x38, {"alurPH","aluOpMov","aluSaveC","instrNext"}, desc="C=P>>8", ccode={"cpu.c=hibyte(cpu.p); lni;"} }, + { mnem="ldb ql" , opcode=0x39, {"alurQL","aluOpMov","aluSaveB","instrNext"}, desc="B=Q&FF", ccode={"cpu.b=lobyte(cpu.q); lni;"} }, + { mnem="ldc qh" , opcode=0x3A, {"alurQH","aluOpMov","aluSaveC","instrNext"}, desc="C=Q>>8", ccode={"cpu.c=hibyte(cpu.q); lni;"} }, + { mnem="ldp q" , opcode=0x8A, {"adwlQ" , "adwSaveP","instrNext"}, desc="P=Q", ccode={"cpu.p=cpu.q; lni;"} }, + { mnem="ldp s" , opcode=0x8B, {"adwlS" , "adwSaveP","instrNext"}, desc="P=S", ccode={"cpu.p=cpu.s; lni;"} }, + { mnem="ldp v" , opcode=0x8C, {"adwlV" , "adwSaveP","instrNext"}, desc="P=V", ccode={"cpu.p=cpu.v; lni;"} }, + { mnem="ldp i" , opcode=0x8D, {"adwlI" , "adwSaveP","instrNext"}, desc="P=I", ccode={"cpu.p=cpu.i; lni;"} }, + { mnem="ldp cb" , opcode=0x91, {"adwrCB", "adwSaveP","instrNext"}, desc="P=(C<<8)+B", ccode={"cpu.p=wordcb; lni;"} }, + { mnem="ldq cb" , opcode=0xE0, {"adwrCB", "adwSaveQ","instrNext"}, desc="Q=(C<<8)+B", ccode={"cpu.q=wordcb; lni;"} }, + { mnem="ldq p" , opcode=0x8E, {"adwlP" , "adwSaveQ","instrNext"}, desc="Q=P", ccode={"cpu.q=cpu.p; lni;"} }, + { mnem="lds p" , opcode=0x8F, {"adwlP" , "adwSaveS","instrNext"}, desc="S=P", ccode={"cpu.s=cpu.p; lni;"} }, + { mnem="ldv p" , opcode=0x90, {"adwlP" , "adwSaveV","instrNext"}, desc="V=P", ccode={"cpu.v=cpu.p; lni;"} }, }, aliases = { - ["jpz imm8"] = {"jeq imm8"}, - ["jnz imm8"] = {"jne imm8"}, - ["jmp q" ] = {"ret" }, + ["jpz imm8" ] = {"jeq imm8"}, + ["jnz imm8" ] = {"jne imm8"}, + ["jmp q" ] = {"ret" }, }, }