1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-03-12 16:42:08 +00:00
Files
PLASMA/src/libsrc/jit16core.pla
2018-04-21 16:35:31 -07:00

1333 lines
54 KiB
Plaintext

//
// TOS and NOS stack offsets
//
const TOS = $01 // TOS
const NOS = $03 // TOS-1
//
// JIT compiler entry
//
def compiler(defptr)#0
word codeptr, isdata[], addrxlate, bytecode, i, case, dest
byte opcode, j, A_IS_TOS, X_IS_IFP
//puts("JIT compiler invoked for :$"); puth(defptr=>bytecodeaddr); putln
addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize)
//if not addrxlate
if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate
//
// Not enough heap available
//
//puts("Not enough free heap\n")
defptr=>interpaddr = indirectentry
return
fin
//
// Copy bytecode def from AUX to heap for compiling
//
bytecode = addrxlate + 512 // def bytecode
defcpy(bytecode, defptr)
//puts("Addr Xlate: $"); puth(addrxlate); putln
//
// Find all branch targets and optimization fences. Tag the opcode with the LSB set
//
// All PLASMA ops are even (LSB clear), so this will flag when to fence optimizations
// During compiling.
//
//isdata = addrxlate // Use this buffer
memset(isdata, 0, 256) // Clear isdata buffer
i = 0
while i < defptr->bytecodesize
if not ^(isdata+i)
//puth(bytecode+i); putc(':'); putb(^(bytecode+i) & $FE); putln; getc
when ^(bytecode+i) & $FE
//
// Double byte operands
//
is $26 // LA
is $2C // CW
is $54 // CALL
is $58 // ENTER
is $68 // LAB
is $6A // LAW
is $78 // SAB
is $7A // SAW
is $7C // DAB
is $7E // DAW
is $B4 // ADDAB
is $B6 // ADDAW
is $BC // IDXAB
is $BE // IDXAW
i = i + 2
break
//
// Multi-byte operands
//
is $2E // CS
i = i + ^(bytecode+i+1)
//
// Single byte operands
//
is $2A // CB
is $28 // LLA
is $38 // ADDI
is $3A // SUBI
is $3C // ANDI
is $3E // ORI
is $5A // LEAVE
is $5E // CFFB
is $64 // LLB
is $66 // LLW
is $6C // DLB
is $6E // DLW
is $74 // SLB
is $76 // SLW
is $B0 // ADDLB
is $B2 // ADDLW
is $B8 // IDXLB
is $BA // IDXLW
i++
break
//
// Branches
//
is $50 // BRNCH
is $22 // BREQ
is $24 // BRNE
is $4C // BRFLS
is $4E // BRTRU
is $A0 // BRGT
is $A2 // BRLT
is $A4 // INCBRLE
is $A6 // ADDBRLE
is $A8 // DECBRGE
is $AA // SUBBRGE
is $AC // BRAND
is $AE // BROR
i++
dest = i + *(bytecode+i)
i++
^(bytecode+dest) = ^(bytecode+dest) | 1 // Flag as branch dest
break
//
// SELect/caseblock
//
is $52 // SEL
i++
case = i + *(bytecode+i)
i++
^(isdata+case) = TRUE // Flag as data
j = ^(bytecode+case)
case++
repeat
*(isdata+case) = TRUE // Flag as data
case = case + 2
dest = case + *(bytecode+case)
^(bytecode+dest) = ^(bytecode+dest) | 1 // Flag as branch dest
*(isdata+case) = TRUE // Flag as data
case = case + 2
j--
until not j
break
wend
fin
i++
loop
//
// Compile the bytecodes
//
memset(addrxlate, 0, 512) // Clear xlate buffer
//puts("Bytecode: $"); puth(bytecode); putln; getc
codeptr = *jitcodeptr
A_IS_TOS = FALSE
X_IS_IFP = FALSE
codeptr->0 = $20 // JSR INTERP
codeptr=>1 = directentry
if ^bytecode == $58
//putc('$'); puth(codeptr);//puts(":[0] ENTER "); puti(^(bytecode+1)); putc(',');puti(^(bytecode+2)); putln
//
// Call into VM
//
codeptr->3 = $58 // ENTER CODE
codeptr=>4 = *(bytecode+1) // ENTER FRAME SIZE & ARG COUNT
codeptr->6 = $C0 // NATV CODE
codeptr = codeptr + 7
i = 3
else
//
// Call into VM
//
codeptr->3 = $C0 // NATV CODE
codeptr = codeptr + 4
i = 0
fin
while isule(codeptr, codemax)
//putc('$'); puth(codeptr); putc(':')
//putc('['); puti(i); //puts("] ")
opcode = ^(bytecode+i)
if opcode & 1
//
// Optimization fence. Sync A and X registers
//
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
A_IS_TOS = FALSE
X_IS_IFP = FALSE
opcode = opcode & $FE
fin
//
// Update bytecode->native code address translation.
//
// Here's how it works:
//
// The code buffer is above address $8000 so MSBit set.
// When we compile a bytecode, update the destination address in
// the address xlate buffer with actual address (MSBit set). But, if a branch
// opcode jumps to a bytecode address that hasn't been compiled yet, add the
// address offset in the code buffer to the list of addresses needing resolution.
// The offset will be less than $8000, so MSBit clear. This is how we know if
// an address has been resolved or is a list of addresses needing resolution.
// Before updating the address xlate buffer with the known address as we
// compile, look for existing resolution list and traverse it if there.
//
if addrxlate=>[i]
//
// Address list awaiting resolution
//
dest = addrxlate=>[i] + *jitcodeptr
repeat
case = *dest
*dest = codeptr
dest = case + *jitcodeptr
until not case
fin
//
// Update address translate buffer with bytecode->native address
//
addrxlate=>[i] = codeptr
//
// Compile this bad boy...
//
if opcode < $20 // CONSTANT NYBBLE
//puts("CN $"); putb(opcode/2)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $A9 // LDA #(CN/2)
codeptr=>1 = opcode/2
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
else
when opcode
is $20 // MINUS ONE
//puts("MINUS_ONE")
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $A9 // LDA #$FFFF
codeptr=>1 = $FFFF
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $22 // BREQ
is $24 // BRNE
i++
dest = i + *(bytecode+i)
i++
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $C3+(TOS<<8) // CMP TOS,S
if opcode == $22
//puts("BREQ "); puti(dest)
codeptr=>2 = $04D0 // BNE +4
else
//puts("BRNE "); puti(dest)
codeptr=>2 = $04F0 // BEQ +4
fin
codeptr=>4 = $4C68 // PLA; JMP abs
codeptr=>6 = addrxlate=>[dest]
if not (codeptr->7 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 6 - *jitcodeptr
fin
codeptr->8 = $68 // PLA
codeptr = codeptr + 9
A_IS_TOS = FALSE
break
is $26 // LA
is $2C // CW
dest = *(bytecode+i+1)
i = i + 2
//puts("LA/CW $"); puth(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $A9 // LDA #imm
codeptr=>1 = dest
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $28 // LLA
i++
j = ^(bytecode+i)
//puts("LLA "); puti(^(bytecode+i))
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
^codeptr = $8A; codeptr++ // TXA
if j <> 0
codeptr=>0 = $6918 // CLC; ADC #imm
codeptr=>2 = j
codeptr = codeptr + 4
fin
A_IS_TOS = TRUE
break
is $2A // CB
is $5E // CFFB
i++
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $A9
if opcode == $2A // LDA #imm
dest = ^(bytecode+i)
//puts("CB $"); putb(dest)
else
dest = ^(bytecode+i) | $FF00
//puts("CFFB $FF"); puth(dest)
fin
codeptr=>1 = dest
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $2E // CS
i++
j = ^(bytecode+i)
dest = codeptr + 7 + j
//puts("CS "); //puts(bytecode+i); //puts("-->"); puti(dest)
if isule(dest, codemax)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
dest = codeptr + 7 + j
codeptr->0 = $A9 // LDA #STRING
codeptr=>1 = codeptr + 6
codeptr->3 = $4C // JMP abs
codeptr=>4 = dest
strcpy(codeptr + 6, bytecode + i)
i = i + j
fin
codeptr = dest
A_IS_TOS = TRUE // PHA
break
is $32 // DROP2
//puts("DROP2")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
A_IS_TOS = FALSE
is $30 // DROP
//puts("DROP")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
A_IS_TOS = FALSE
break
is $34 // DUP
//puts("DUP")
if not A_IS_TOS
*codeptr = $A3+(TOS<<8) // LDA S, TOS
codeptr = codeptr + 2
else
^codeptr = $48; codeptr++ // PHA
fin
A_IS_TOS = TRUE // PHA
break
//is $36
//puts("DIVMOD")
//
// Should never happen
//
//break
is $38 // ADDI
i++
//puts("ADDI $"); putb(^(bytecode+i))
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $6918 // CLC; ADC #imm
codeptr=>2 = ^(bytecode+i)
codeptr = codeptr + 4
A_IS_TOS = TRUE // PHA
break
is $3A // SUBI
i++
//puts("SUBI $"); putb(^(bytecode+i))
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E938 // SEC; SBC #imm
codeptr=>2 = ^(bytecode+i)
codeptr = codeptr + 4
A_IS_TOS = TRUE // PHA
break
is $3C // ANDI
i++
//puts("ANDI $"); putb(^(bytecode+i))
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $29 // AND #imm
codeptr=>1 = ^(bytecode+i)
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $3E // ORI
i++
//puts("ORI $"); putb(^(bytecode+i))
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $09 // ORA #imm
codeptr=>1 = ^(bytecode+i)
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $40 // ISEQ
is $42 // ISNE
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $A0 // LDY #$0000
codeptr=>1 = $0000
codeptr=>3 = $C3+(TOS<<8) // CMP TOS,S
if opcode == $40
//puts("ISEQ")
codeptr=>5 = $01D0 // BNE +1
else
//puts("ISNE")
codeptr=>5 = $01F0 // BEQ +1
fin
codeptr=>7 = $9888 // DEY; TYA
codeptr->9 = $7A // PLY
codeptr = codeptr + 10
A_IS_TOS = TRUE // PHA
break
is $44 // ISGT
is $4A // ISLE
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $A0 // LDY #$0000
codeptr=>1 = $0000
codeptr->3 = $38 // SEC
codeptr=>4 = $E3+(TOS<<8) // SBC TOS,S
codeptr=>6 = $0350 // BVC +3
codeptr->8 = $49 // EOR #$8000
codeptr=>9 = $8000
if opcode == $44
//puts("ISGT")
codeptr=>11 = $0110 // BPL +1
else
//puts("ISLE")
codeptr=>11 = $0130 // BMI +1
fin
codeptr=>13 = $9888 // DEY; TYA
codeptr->15 = $7A // PLY
codeptr = codeptr + 16
A_IS_TOS = TRUE // PHA
break
is $46 // ISLT
is $48 // ISGE
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $A0 // LDY #$0000
codeptr=>1 = $0000
codeptr=>3 = $E785 // STA TMP
codeptr=>5 = $3868 // PLA; SEC
codeptr=>7 = $E7E5 // SBC TMP
codeptr=>9 = $0350 // BVC +3
codeptr->11 = $49 // EOR #$8000
codeptr=>12 = $8000
if opcode == $46
//puts("ISLT")
codeptr=>14 = $0110 // BPL +1
else
//puts("ISGE")
codeptr=>14 = $0130 // BMI +1
fin
codeptr=>16 = $9888 // DEY; TYA
codeptr = codeptr + 18
A_IS_TOS = TRUE // PHA
break
is $4C // BRFLS
is $4E // BRTRU
i++
dest = i + *(bytecode+i)
i++
if not A_IS_TOS
codeptr->0 = $68 // PLA
else
codeptr->0 = $A8 // TAY
fin
if opcode == $4C
//puts("BRFLS "); puti(dest)
codeptr=>1 = $03D0 // BNE +3
else
//puts("BRTRU "); puti(dest)
codeptr=>1 = $03F0 // BEQ +3
fin
codeptr->3 = $4C // JMP abs
codeptr=>4 = addrxlate=>[dest]
if not (codeptr->5 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 4 - *jitcodeptr
fin
codeptr = codeptr + 6
A_IS_TOS = FALSE
break
is $50 // BRNCH
i++
dest = i + *(bytecode+i)
i++
//puts("BRNCH "); puti(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $4C // JMP abs
codeptr=>1 = addrxlate=>[dest]
if not (codeptr->2 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 1 - *jitcodeptr
fin
codeptr = codeptr + 3
A_IS_TOS = FALSE
break
is $52 // SEL
i++
case = i + *(bytecode+i)
i++
//puts("SEL "); puti(case); putln
j = ^(bytecode+case)
dest = codeptr + 9 + case * 11)
if isule(dest, codemax)
^(bytecode+case) = $FE // Flag as NOP
case++
if not A_IS_TOS
codeptr->0 = $68; codeptr++ // PLA
fin
repeat
dest = *(bytecode+case)
//puts(" $"); puth(dest)
codeptr->0 = $C9 // CMP #imm
codeptr=>1 = dest
codeptr=>3 = $03D0 // BNE +3
*(bytecode+case) = $FEFE
case = case + 2
dest = case + *(bytecode+case)
//puts("-->"); puti(dest); putln
codeptr->5 = $4C // JMP abs
codeptr=>6 = addrxlate=>[dest]
if not (codeptr->7 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 6 - *jitcodeptr
fin
codeptr = codeptr + 8
*(bytecode+case) = $FEFE
case = case + 2
j--
until not j
codeptr->0 = $4C // JMP abs
codeptr=>1 = addrxlate=>[case]
if not (codeptr->2 & $80) // Unresolved address list
addrxlate=>[case] = codeptr + 1 - *jitcodeptr
fin
codeptr = codeptr + 3
else
codeptr = dest
fin
A_IS_TOS = FALSE
break
is $54 // CALL
is $56 // ICAL
is $5A // LEAVE
is $5C // RET
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr=>0 = $10E2 // SEP #$10 -> 8 BIT X/Y
codeptr->2 = $A9 // LDA #imm
codeptr=>3 = codeptr + 12
codeptr=>5 = $F285 // STA IP
codeptr=>7 = $00A0 // LDY #$00
codeptr->9 = $4C // JMP FETCHOP
codeptr=>10 = $00F1 // FETCHOP
codeptr->12 = opcode // OP
when opcode
is $54 // CALL
//
// Call address
//
//puts("CALL $"); puth(*(bytecode+i))
codeptr=>13 = *(bytecode+i+1) // CALL ADDR
codeptr->15 = $C0 // NATV
codeptr = codeptr + 16
i = i + 2
break
is $56 // ICAL
//
// Call address off stack
//
//puts("ICAL")
codeptr->13 = $C0 // NATV
codeptr = codeptr + 14
break
is $5A // LEAVE
//
// Leave routine
//
i++
//puts("LEAVE "); puti(^(bytecode+i))
codeptr->13 = ^(bytecode+i) // LEAVE CODE OPERAND
codeptr = codeptr + 14
break
is $5C // RET
//
// Quick return from routine
//
//puts("RET")
codeptr = codeptr + 13
break
wend
X_IS_IFP = FALSE
A_IS_TOS = FALSE
break
is $60 // LB
//puts("LB")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr=>4 = $E7B2 // LDA (TMP)
codeptr=>6 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
codeptr->8 = $29 // AND #$00FF
codeptr=>9 = $00FF
codeptr = codeptr + 11
A_IS_TOS = TRUE // PHA
break
is $62 // LW
//puts("LW")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $E7B2 // LDA (TMP)
codeptr = codeptr + 4
A_IS_TOS = TRUE // PHA
break
is $64 // LLB
i++
j = ^(bytecode+i)
//puts("LLB "); puti(j)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $B5+(j<<8) // LDA dp,X
codeptr->2 = $29 // AND #$00FF
codeptr=>3 = $00FF
codeptr = codeptr + 5
A_IS_TOS = TRUE // PHA
break
is $66 // LLW
i++
j = ^(bytecode+i)
//puts("LLW "); puti(j)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $B5+(j<<8) // LDA dp,X
codeptr = codeptr + 2
A_IS_TOS = TRUE // PHA
break
is $68 // LAB
dest = *(bytecode+i+1)
i = i + 2
//puts("LAB $"); puth(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
if is_hwaddr(dest)
//
// Ensure we only do byte sized accesses to H/W
//
codeptr=>0 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr->2 = $AD // LDA abs
codeptr=>3 = dest
codeptr=>5 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
codeptr->7 = $29 // AND #$00FF
codeptr=>8 = $00FF
codeptr = codeptr + 10
else
codeptr->0 = $AD // LDA abs
codeptr=>1 = dest
codeptr->3 = $29 // AND #$00FF
codeptr=>4 = $00FF
codeptr = codeptr + 6
fin
A_IS_TOS = TRUE // PHA
break
is $6A // LAW
dest = *(bytecode+i+1)
i = i + 2
//puts("LAW $"); puth(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $AD // LDA abs
codeptr=>1 = dest
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $6C // DLB
is $74 // SLB
i++
j = ^(bytecode+i)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr=>2 = $95+(j<<8) // STA dp,X
codeptr=>4 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
if opcode == $6C
//puts("DLB "); puti(j)
codeptr->6 = $29 // AND #$00FF
codeptr=>7 = $00FF
codeptr = codeptr + 9
A_IS_TOS = TRUE // PHA
else
//puts("SLB "); puti(j)
codeptr = codeptr + 6
A_IS_TOS = FALSE
fin
break
is $6E // DLW
is $76 // SLW
i++
j = ^(bytecode+i)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $95+(j<<8) // STA dp,X
codeptr = codeptr + 2
if opcode == $6E
//puts("DLW "); puti(j)
A_IS_TOS = TRUE // PHA
else
//puts("SLW "); puti(j)
A_IS_TOS = FALSE
fin
break
is $70 // SB
//puts("SB")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E785 // STA TMP
codeptr->2 = $68 // PLA
codeptr=>3 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr=>5 = $E792 // STA (TMP)
codeptr=>7 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
codeptr = codeptr + 9
A_IS_TOS = FALSE
break
is $72 // SW
//puts("SW")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E785 // STA TMP
codeptr->2 = $68 // PLA
codeptr=>3 = $E792 // STA (TMP)
codeptr = codeptr + 5
A_IS_TOS = FALSE
break
is $78 // SAB
is $7C // DAB
dest = *(bytecode+i+1)
i = i + 2
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr->2 = $8D // STA abs
codeptr=>3 = dest
codeptr=>5 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
if opcode == $78
//puts("SAB $"); puth(*(bytecode+i))
codeptr = codeptr + 7
A_IS_TOS = FALSE
else
//puts("DAB $"); puth(*(bytecode+i))
codeptr->7 = $29 // AND #$00FF
codeptr=>8 = $00FF
codeptr = codeptr + 10
A_IS_TOS = TRUE
fin
break
is $7A // SAW
is $7E // DAW
dest = *(bytecode+i+1)
i = i + 2
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $8D // STA abs
codeptr=>1 = dest
codeptr = codeptr + 3
if opcode == $7A
//puts("SAW $"); puth(dest)
A_IS_TOS = FALSE
else
//puts("DAW $"); puth(*(bytecode+i))
A_IS_TOS = TRUE
fin
break
is $80 // NOT
//puts("NOT")
if not A_IS_TOS
codeptr->0 = $68 // PLA
else
codeptr->0 = $A8 // TAY
fin
codeptr=>1 = $03F0 // BEQ +3
codeptr->3 = $A9 // LDA #$FFFF
codeptr=>4 = $FFFF
codeptr->6 = $49 // EOR #$FFFF
codeptr=>7 = $FFFF
codeptr = codeptr + 9
A_IS_TOS = TRUE
break
is $82 // ADD
//puts("ADD")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $18 // CLC
codeptr=>1 = $63+(TOS<<8) // ADC S,TOS
codeptr->3 = $7A // PLY
codeptr = codeptr + 4
A_IS_TOS = TRUE
break
is $84 // SUB
//puts("SUB")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $3868 // PLA; SEC
codeptr=>4 = $E7E5 // SBC TMP
codeptr = codeptr + 6
A_IS_TOS = TRUE
break
is $86 // MUL
is $88 // DIV
is $8A // MOD
is $9A // SHL
is $9C // SHR
//puts("MUL,DIV,MOD,SHL,SHR")
// when opcode
// is $86
// //puts("MUL")
// is $88
// //puts("DIV")
// is $8A
// //puts("MOD")
// is $9A
// //puts("SHL")
// is $9C
// //puts("SHR")
// wend
//
// Call into VM
//
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr=>0 = $10E2 // SEP #$10 -> 8 BIT X/Y
codeptr->2 = $A9 // LDA #imm
codeptr=>3 = codeptr + 12
codeptr=>5 = $F285 // STA IP
codeptr=>7 = $00A0 // LDY #$00
codeptr->9 = $4C // JMP FETCHOP
codeptr=>10 = $00F1 // FETCHOP
codeptr=>12 = $C000+opcode // OPCODE; NATV CODE
codeptr = codeptr + 14
X_IS_IFP = FALSE
A_IS_TOS = FALSE
break
is $8C // INCR
//puts("INCR")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
^codeptr = $1A; codeptr++ // INC A
A_IS_TOS = TRUE // PHA
break
is $8E // DECR
//puts("DECR")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
^codeptr = $3A; codeptr++ // DEC A
A_IS_TOS = TRUE // PHA
break
is $90 // NEG
//puts("NEG")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $49 // EOR #$FFFF
codeptr=>1 = $FFFF
codeptr->3 = $1A // INC A
codeptr = codeptr + 4
A_IS_TOS = TRUE
break
is $92 // COMP
//puts("COMP")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr->0 = $49 // EOR #$FFFF
codeptr=>1 = $FFFF
codeptr = codeptr + 3
A_IS_TOS = TRUE
break
is $94 // AND
//puts("AND")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $23+(TOS<<8) // AND S,TOS
codeptr->2 = $7A // PLY
codeptr = codeptr + 3
A_IS_TOS = TRUE
break
is $96 // OR
//puts("OR")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $03+(TOS<<8) // OR S,TOS
codeptr->2 = $7A // PLY
codeptr = codeptr + 3
A_IS_TOS = TRUE
break
is $98 // XOR
//puts("XOR")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $43+(TOS<<8) // EOR S,TOS
codeptr->2 = $7A // PLY
codeptr = codeptr + 3
A_IS_TOS = TRUE
break
is $9E // IDXW
//puts("IDXW")
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $180A // ASL; CLC
codeptr=>2 = $63+(TOS<<8) // ADC S,TOS
codeptr->4 = $7A // PLY
codeptr = codeptr + 5
A_IS_TOS = TRUE
break
is $A0 // BRGT - FOR/NEXT SPECIFIC TEST & BRANCH
i++
dest = i + *(bytecode+i)
i++
//puts("BRGT "); puti(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr=>0 = $A3+(NOS<<8) // LDA S,NOS
codeptr->2 = $38 // SEC
codeptr=>3 = $E3+(TOS<<8) // SBC S,TOS
codeptr=>5 = $0350 // BVC +3
codeptr->7 = $49 // EOR #$8000
codeptr=>8 = $8000
codeptr=>10 = $0310 // BPL +3
codeptr->12 = $4C // JMP abs
codeptr=>13 = addrxlate=>[dest]
if not (codeptr->14 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 13 - *jitcodeptr
fin
codeptr = codeptr + 15
A_IS_TOS = FALSE
break
is $A2 // BRLT - FOR/NEXT SPECIFIC TEST & BRANCH
i++
dest = i + *(bytecode+i)
i++
//puts("BRLT "); puti(dest)
if A_IS_TOS
^codeptr = $48; codeptr++ // PHA
fin
codeptr->0 = $38 // SEC
codeptr=>1 = $E3+(NOS<<8) // SBC S,NOS
codeptr=>3 = $0350 // BVC +3
codeptr->5 = $49 // EOR #$8000
codeptr=>6 = $8000
codeptr=>8 = $0310 // BPL +3
codeptr->10 = $4C // JMP abs
codeptr=>11 = addrxlate=>[dest]
if not (codeptr->12 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 11 - *jitcodeptr
fin
codeptr = codeptr + 13
A_IS_TOS = FALSE
break
is $A4 // INCBRLE - FOR/NEXT SPECIFIC INC & TEST & BRANCH
is $A6 // ADDBRLE - FOR/NEXT SPECIFIC ADD & TEST & BRANCH
i++
dest = i + *(bytecode+i)
i++
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if opcode == $A4
//
// INCR
//
//puts("INCBRLE "); puti(dest)
codeptr=>0 = $481A // INC A; PHA
codeptr = codeptr + 2
else
//
// ADD
//
//puts("ADDBRLE "); puti(dest)
codeptr->0 = $18 // CLC
codeptr=>1 = $63+(TOS<<8) // ADC S,TOS
codeptr=>3 = $83+(TOS<<8) // STA S,TOS
codeptr = codeptr + 5
fin
//
// BRLE
//
codeptr=>0 = $A3+(NOS<<8) // LDA S,NOS
codeptr->2 = $38 // SEC
codeptr=>3 = $E3+(TOS<<8) // SBC S,TOS
codeptr=>5 = $0350 // BVC +3
codeptr->7 = $49 // EOR #$8000
codeptr=>8 = $8000
codeptr=>10 = $0330 // BMI +3
codeptr->12 = $4C // JMP abs
codeptr=>13 = addrxlate=>[dest]
if not (codeptr->14 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 13 - *jitcodeptr
fin
codeptr = codeptr + 15
A_IS_TOS = FALSE
break
is $A8 // DECBRGR - FOR/NEXT SPECIFIC DEC & TEST & BRANCH
is $AA // SUBBRGE - FOR/NEXT SPECIFIC SUB & TEST & BRANCH
i++
dest = i + *(bytecode+i)
i++
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if opcode == $A8
//
// DECR
//
//puts("DECBRGE "); puti(dest)
codeptr=>0 = $483A // DEC A; PHA
codeptr = codeptr + 2
else
//
// SUB
//
//puts("SUBBRGE "); puti(dest)
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $A3+(TOS<<8) // LDA S,TOS
codeptr->4 = $68 // SEC
codeptr=>5 = $E7E5 // SBC TMP
codeptr=>7 = $83+(TOS<<8) // STA S,TOS
codeptr = codeptr + 9
fin
//
// BRGE
//
codeptr->0 = $38 // SEC
codeptr=>1 = $E3+(NOS<<8) // SBC S,NOS
codeptr=>3 = $0350 // BVC +3
codeptr->5 = $49 // EOR #$8000
codeptr=>6 = $8000
codeptr=>8 = $0330 // BMI +3
codeptr->10 = $4C // JMP abs
codeptr=>11 = addrxlate=>[dest]
if not (codeptr->12 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 11 - *jitcodeptr
fin
codeptr = codeptr + 13
A_IS_TOS = FALSE
break
is $AC // BRAND - LOGICAL AND SPECIFIC BRANCH
is $AE // BROR - LOGICAL OR SPECIFIC BRANCH
i++
dest = i + *(bytecode+i)
i++
if not A_IS_TOS
codeptr->0 = $68 // PLA
else
codeptr->0 = $A8 // TAY
fin
if opcode == $AC
//puts("BRAND "); puti(dest)
codeptr=>1 = $04D0 // BNE +4
else
//puts("BROR "); puti(dest)
codeptr=>1 = $04F0 // BEQ +4
fin
codeptr=>3 = $4C48 // PHA; JMP abs
codeptr=>5 = addrxlate=>[dest]
if not (codeptr->6 & $80) // Unresolved address list
addrxlate=>[dest] = codeptr + 5 - *jitcodeptr
fin
codeptr = codeptr + 7
A_IS_TOS = FALSE
break
is $B0 // ADDLB
//puts("ADDLB "); puti(j)
i++
j = ^(bytecode+i)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $B5+(j<<8) // LDA dp,X
codeptr->4 = $29 // AND #$00FF
codeptr=>5 = $00FF
codeptr->7 = $18 // CLC
codeptr=>8 = $E765 // ADC TMP
codeptr = codeptr + 10
A_IS_TOS = TRUE // PHA
break
is $B2 // ADDLW
i++
j = ^(bytecode+i)
//puts("ADDLW "); puti(j)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr->0 = $18 // CLC
codeptr=>1 = $75+(j<<8) // ADC dp,X
codeptr = codeptr + 3
A_IS_TOS = TRUE // PHA
break
is $B4 // ADDAB
dest = *(bytecode+i+1)
i = i + 2
//puts("ADDAB $"); puth(dest)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if is_hwaddr(dest)
//
// Ensure only byte sized accesses to H/W addresses
//
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr->4 = $AD // LDA abs
codeptr=>5 = dest
codeptr=>7 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
codeptr->9 = $29 // AND #$00FF
codeptr=>10 = $00FF
codeptr->12 = $18 // CLC
codeptr=>13 = $E765 // ADC TMP
codeptr = codeptr + 15
else
codeptr=>0 = $E785 // STA TMP
codeptr->2 = $AD // LDA abs
codeptr=>3 = dest
codeptr->5 = $29 // AND #$00FF
codeptr=>6 = $00FF
codeptr->8 = $18 // CLC
codeptr=>9 = $E765 // ADC TMP
codeptr = codeptr + 11
fin
A_IS_TOS = TRUE // PHA
break
is $B6 // ADDAW
dest = *(bytecode+i+1)
i = i + 2
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $6D18 // CLC; ADC abs
codeptr=>2 = dest
codeptr = codeptr + 4
A_IS_TOS = TRUE // PHA
break
is $B8 // IDXLB
i++
j = ^(bytecode+i)
//puts("IDXLB "); puti(j)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $B5+(j<<8) // LDA dp,X
codeptr->4 = $29 // AND #$00FF
codeptr=>5 = $00FF
codeptr->7 = $0A // ASL
codeptr=>8 = $E765 // ADC TMP
codeptr = codeptr + 10
A_IS_TOS = TRUE // PHA
break
is $BA // IDXLW
i++
j = ^(bytecode+i)
//puts("IDXLW "); puti(j)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if not X_IS_IFP
*codeptr = $E0A6 // LDX IFP
codeptr = codeptr + 2
X_IS_IFP = TRUE
fin
codeptr->0 = $18 // CLC
codeptr=>1 = $75+(j<<8) // ADC dp,X
codeptr->3 = $18 // CLC
codeptr=>4 = $75+(j<<8) // ADC dp,X
codeptr = codeptr + 6
A_IS_TOS = TRUE // PHA
break
is $BC // IDXAB
dest = *(bytecode+i+1)
i = i + 2
//puts("IDXAB $"); puth(*(bytecode+i))
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
if is_hwaddr(dest)
//
// Ensure only byte sized accesses to H/W addresses
//
codeptr=>0 = $E785 // STA TMP
codeptr=>2 = $20E2 // SEP #$20 -> 8 BIT ACCUM/MEM
codeptr->4 = $AD // LDA abs
codeptr=>5 = dest
codeptr=>7 = $20C2 // REP #$20 -> 16 BIT ACCUM/MEM
codeptr->9 = $29 // AND #$00FF
codeptr=>10 = $00FF
codeptr->12 = $0A // ASL
codeptr=>13 = $E765 // ADC TMP
codeptr = codeptr + 15
else
codeptr=>0 = $E785 // STA TMP
codeptr->2 = $AD // LDA abs
codeptr=>3 = dest
codeptr->5 = $29 // AND #$00FF
codeptr=>6 = $00FF
codeptr->8 = $0A // ASL
codeptr=>9 = $E765 // ADC TMP
codeptr = codeptr + 11
fin
A_IS_TOS = TRUE // PHA
break
is $BE // IDXAW
dest = *(bytecode+i+1)
i = i + 2
//puts("IDXAW $"); puth(dest)
if not A_IS_TOS
^codeptr = $68; codeptr++ // PLA
fin
codeptr=>0 = $6D18 // CLC; ADC abs
codeptr=>2 = dest
codeptr=>4 = $6D18 // CLC; ADC abs
codeptr=>6 = dest
codeptr = codeptr + 8
A_IS_TOS = TRUE // PHA
break
is $FE // NOPed out earlier by SELect
break
otherwise
//puts("???: $"); puth(^(bytecode+i)); putln
wend
fin
//putln
i++
if i >= defptr->bytecodesize
//
// Done compiling. Update DEF entry with JMP to compiled code
//
defptr->interpjsr = $4C // JMP
defptr=>interpaddr = *jitcodeptr
*jitcodeptr = codeptr
//
// Free working bufffers
//
//heaprelease(addrxlate)
//puts("Done compiling: $"); puth(defptr=>interpaddr); putln
//getc
return
fin
loop
//
// If we got here. we ran out of code buffer space. Overwrite interpreter
// entrypoint with standard bytecode interpreter
//
defptr=>interpaddr = indirectentry
//
// Free working bufffers
//
//heaprelease(addrxlate)
//puts("Ran out of code buffer\n")
//getc
end