//
// TOS caching values
//
const TOS_DIRTY   = 1
const TOS_CLEAN   = 2
//
// Y unknown value
//
const UNKNOWN     = -1
//
// Resolve virtual X with real X
//
def resolveX(codeptr, VX)#2
    while VX > 0
        ^codeptr = $E8; codeptr++ // INX
        VX--
    loop
    while VX < 0
        ^codeptr = $CA; codeptr++ // DEX
        VX++
    loop
    return codeptr, 0
end
//
// JIT compiler entry
//
def compiler(defptr)#0
    word codeptr, isdata[], addrxlate, bytecode, i, case, dest, VX, VY
    byte opcode, j, A_IS_TOSL

    defptr=>interpaddr = indirectentry // assume compile will fail
    addrxlate = heapmark // heapalloc(512 + defptr->bytecodesize)
    if isult(heapavail, 512 + defptr->bytecodesize) // 256 * sizeof(word) address xlate
        //
        // Not enough heap available
        //
        //puts("Not enough free heap\n")
        return
    fin
    //
    // Copy bytecode def from AUX to heap for compiling
    //
    bytecode = addrxlate + 512 // def bytecode
    defcpy(bytecode, defptr)
    //puts("JITC:$"); puth(defptr=>bytecodeaddr); puts("=>$"); puth(bytecode)
    //puts(",$"); puth(defptr->bytecodesize); 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_TOSL = FALSE
    VY        = UNKNOWN // Virtual Y register
    VX        = 0       // Virtual X register
    i         = 0
    if ^bytecode == $58
        //putc('$'); puth(codeptr);//puts(":[0] ENTER "); puti(^(bytecode+1)); putc(',');puti(^(bytecode+2)); putln
        //
        // Call into VM
        //
        codeptr->0 = $20           // JSR INTERP
        codeptr=>1 = directentry
        codeptr->3 = $58           // ENTER CODE
        codeptr=>4 = *(bytecode+1) // ENTER FRAME SIZE & ARG COUNT
        codeptr->6 = $C0           // NATV CODE
        codeptr    = codeptr + 7
        i          = 3
    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
            //
            codeptr, VX = resolveX(codeptr, VX)
            if A_IS_TOSL & TOS_DIRTY
                *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                codeptr  = codeptr + 2
            fin
            VY        = UNKNOWN
            A_IS_TOSL = 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_TOSL & TOS_DIRTY
                *codeptr = estkl8+$95+(VX<<8)       // STA ESTKL,X
                codeptr  = codeptr + 2
            fin
            VX--                                    // DEX
            if VY <> 0
                *codeptr = $00A0                    // LDY #$00
                codeptr  = codeptr + 2
                VY       = 0
            fin
            *codeptr  = estkh8+$94+(VX<<8)          // STY ESTKH,X
            codeptr   = codeptr + 2
            if opcode == 0
                ^codeptr = $98; codeptr++           // TYA -> LDA #$00
            else
                *codeptr = $A9+(opcode/2<<8)        // LDA #(CN/2)
                codeptr  = codeptr + 2
            fin
            A_IS_TOSL = TOS_DIRTY                   // STA ESTKL,X
        else
            when opcode
                is $20 // MINUS ONE
                    //puts("MINUS_ONE")
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                              // DEX
                    codeptr=>0 = $FFA9                // LDA #$FF
                    codeptr=>2 = estkh8+$95+(VX<<8)   // STA ESTKH,X
                    codeptr    = codeptr + 4
                    A_IS_TOSL  = TOS_DIRTY            // STA ESTKL,X
                    break
                is $22 // BREQ
                is $24 // BRNE
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    codeptr, VX = resolveX(codeptr, VX + 2)   // INX; INX
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5-$0200//+(VX<<8) // LDA ESTKL-2,X
                        codeptr  = codeptr + 2
                    fin
                    if opcode == $22
                        //puts("BREQ "); puti(dest)
                        codeptr=>2  = $09D0                   // BNE +9
                        codeptr=>8  = $03D0                   // BNE +3
                    else
                        //puts("BRNE "); puti(dest)
                        codeptr=>2  = $06D0                   // BNE +6
                        codeptr=>8  = $03F0                   // BEQ +3
                    fin
                    codeptr=>0  = estkl8+$D5-$0100//+(VX<<8)  // CMP ESTKL-1,X
                    codeptr=>4  = estkh8+$B5-$0200//+(VX<<8)  // LDA ESTKH-2,X
                    codeptr=>6  = estkh8+$D5-$0100//+(VX<<8)  // CMP ESTKH-1,X
                    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_TOSL = FALSE
                    break
                is $26 // LA
                is $2C // CW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    //puts("LA/CW $"); puth(dest)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)  // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                               // DEX
                    codeptr=>0 = $A9+(dest&$FF00)      // LDA #<VAL
                    codeptr=>2 = estkh8+$95+(VX<<8)    // STA ESTKH,X
                    codeptr=>4 = $A9+(dest<<8)         // LDA #>VAL
                    codeptr    = codeptr + 6
                    A_IS_TOSL = TOS_DIRTY              // STA ESTKL,X
                    break
                is $28 // LLA
                    i++
                    j = ^(bytecode+i)
                    //puts("LLA "); puti(^(bytecode+i))
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)  // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                               // DEX
                    if VY == j
                        ^codeptr = $98; codeptr++      // TYA -> LDA #imm
                    else
                        *codeptr = $A9+(j<<8)          // LDA #imm
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $18                   // CLC
                    codeptr=>1 = ifpl8+$65             // ADC IFPL
                    codeptr=>3 = estkl8+$95+(VX<<8)    // STA ESTKL,X
                    if VY == 0
                        codeptr->5 = $98               // TYA -> LDA #00
                        codeptr    = codeptr + 6
                    else
                        codeptr=>5 = $00A9             // LDA #$00
                        codeptr    = codeptr + 7
                    fin
                    codeptr=>0 = ifph8+$65             // ADC IFPH
                    codeptr=>2 = estkh8+$95+(VX<<8)    // STA ESTKH,X
                    codeptr    = codeptr + 4
                    A_IS_TOSL  = FALSE
                    break
                is $2A // CB
                is $5E // CFFB
                    i++
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)        // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                                     // DEX
                    if opcode == $2A
                        //puts("CB $"); putb(^(bytecode+i))
                        if VY <> 0
                            *codeptr = $00A0                 // LDY #$00
                            codeptr  = codeptr + 2
                            VY       = 0
                        fin
                        codeptr=>0 = estkh8+$94+(VX<<8)      // STY ESTKH,X
                        codeptr    = codeptr + 2
                    else
                        //puts("CFFB $FF"); putb(^(bytecode+i))
                        codeptr=>0 = $FFA9                   // LDA #$FF
                        codeptr=>2 = estkh8+$95+(VX<<8)      // STA ESTKH,X
                        codeptr    = codeptr + 4
                    fin
                    *codeptr  = $A9+(^(bytecode+i)<<8)       // LDA #imm
                    codeptr   = codeptr + 2
                    A_IS_TOSL = TOS_DIRTY                    // STA ESTKL,X
                    break
                is $2E // CS
                    i++
                    j    = ^(bytecode+i)
                    dest = codeptr + 10 + j
                    //puts("CS "); //puts(bytecode+i); //puts("-->"); puti(dest)
                    if isule(dest, codemax)
                        if A_IS_TOSL & TOS_DIRTY
                            *codeptr = estkl8+$95+(VX<<8)         // STA ESTKL,X
                            codeptr  = codeptr + 2
                        fin
                        VX--                                      // DEX
                        codeptr=>0 = $A9+((codeptr+9)&$FF00)      // LDA #>STRING
                        codeptr=>2 = estkh8+$95+(VX<<8)           // STA ESTKH,X
                        codeptr=>4 = $A9+((codeptr+9)<<8)         // LDA #<STRING
                        codeptr->6 = $4C                          // JMP abs
                        dest       = codeptr + 10 + j
                        codeptr=>7 = dest
                        strcpy(codeptr + 9, bytecode + i)
                        i = i + j
                    fin
                    codeptr   = dest
                    A_IS_TOSL = TOS_DIRTY                         // STA ESTKL,X
                    break
                is $32 // DROP2
                    //puts("DROP2")
                    VX++              // INX
                is $30 // DROP
                    //puts("DROP")
                    VX++              // INX
                    A_IS_TOSL = FALSE
                    break
                is $34 // DUP
                    //puts("DUP")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    elsif A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$B4+(VX<<8)   // LDY ESTKH,X
                    VX--                              // DEX
                    codeptr=>2 = estkh8+$94+(VX<<8)   // STY ESTKH,X
                    codeptr    = codeptr + 4
                    VY         = UNKNOWN
                    A_IS_TOSL  = TOS_DIRTY            // STA ESTKL,X
                    break
                //is $36
                    //puts("DIVMOD")
                    //
                    // Should never happen
                    //
                    //break
                is $38 // ADDI
                    i++
                    j = ^(bytecode+i)
                    //puts("ADDI $"); putb(^(bytecode+i))
                is $8C // INCR
                    if opcode == $8C
                        //puts("INCR")
                        j = 1
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $18                  // CLC
                    codeptr=>1 = $69+(j<<8)           // ADC #imm
                    codeptr=>3 = $0290                // BCC +2
                    codeptr=>5 = estkh8+$F6+(VX<<8)   // INC ESTKH,X
                    codeptr    = codeptr + 7
                    A_IS_TOSL  = TOS_DIRTY            // STA ESTKL,X
                    break
                is $3A // SUBI
                    i++
                    j = ^(bytecode+i)
                    //puts("SUBI $"); putb(^(bytecode+i))
                is $8E // DECR
                    if opcode == $8E
                        //puts("DECR")
                        j = 1
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $38                  // SEC
                    codeptr=>1 = $E9+(j<<8)           // SBC #imm
                    codeptr=>3 = $02B0                // BCS +2
                    codeptr=>5 = estkh8+$D6+(VX<<8)   // DEC ESTKH,X
                    codeptr    = codeptr + 7
                    A_IS_TOSL  = TOS_DIRTY            // STA ESTKL,X
                    break
                is $3C // ANDI
                    i++
                    //puts("ANDI $"); putb(^(bytecode+i))
                    if VY <> 0
                        *codeptr = $00A0                     // LDY #$00
                        codeptr  = codeptr + 2
                        VY       = 0
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)        // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = $29+(^(bytecode+i)<<8)      // AND #imm
                    codeptr=>2 = estkh8+$94+(VX<<8)          // STY ESTKH,X
                    codeptr    = codeptr + 4
                    A_IS_TOSL  = TOS_DIRTY                   // STA ESTKL,X
                    break
                is $3E // ORI
                    i++
                    //puts("ORI $"); putb(^(bytecode+i))
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)       // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    *codeptr  = $09+(^(bytecode+i)<<8)      // ORA #imm
                    codeptr   = codeptr + 2
                    A_IS_TOSL = TOS_DIRTY                   // STA ESTKL,X
                    break
                is $40 // ISEQ
                is $42 // ISNE
                    if VY <> 0
                        *codeptr = $00A0                   // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if opcode == $40
                        //puts("ISEQ")
                        codeptr=>2  = $07D0                // BNE +7
                        codeptr=>8  = $01D0                // BNE +1
                    else
                        //puts("ISNE")
                        codeptr=>2  = $06D0                // BNE +6
                        codeptr=>8  = $01F0                // BEQ +1
                    fin
                    codeptr=>0  = estkl8+$D5+$0100+(VX<<8) // CMP ESTKL+1,X
                    codeptr=>4  = estkh8+$B5+(VX<<8)       // LDA ESTKH,X
                    codeptr=>6  = estkh8+$D5+$0100+(VX<<8) // CMP ESTKH+1
                    codeptr=>10 = $9888                    // DEY; TYA
                    codeptr=>12 = estkh8+$94+$0100+(VX<<8) // STY ESTKH+1,X
                    codeptr     = codeptr + 14
                    VX++                                   // INX
                    VY          = UNKNOWN
                    A_IS_TOSL   = TOS_DIRTY                // STA ESTKL,X
                    break
                is $44 // ISGT
                is $4A // ISLE
                    if VY <> 0
                        *codeptr = $00A0                   // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkl8+$D5+$0100+(VX<<8) // CMP ESTKL+1,X
                    codeptr=>2  = estkh8+$B5+(VX<<8)       // LDA ESTKH,X
                    codeptr=>4  = estkh8+$F5+$0100+(VX<<8) // SBC ESTKH+1
                    codeptr=>6  = $0250                    // BVC +2
                    codeptr=>8  = $8049                    // EOR #$80
                    if opcode == $44
                        //puts("ISGT")
                        codeptr=>10 = $0110                // BPL +1
                    else
                        //puts("ISLE")
                        codeptr=>10 = $0130                // BMI +1
                    fin
                    codeptr=>12 = $9888                    // DEY TYA
                    codeptr=>14 = estkh8+$94+$0100+(VX<<8) // STY ESTKH+1,X
                    codeptr     = codeptr + 16
                    VX++                                   // INX
                    VY          = UNKNOWN
                    A_IS_TOSL   = TOS_DIRTY                // STA ESTKL,X
                    break
                is $46 // ISLT
                is $48 // ISGE
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)      // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> 0
                        *codeptr = $00A0                   // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkl8+$B5+$0100+(VX<<8) // LDA ESTKL+1,X
                    codeptr=>2  = estkl8+$D5+(VX<<8)       // CMP ESTKL,X
                    codeptr=>4  = estkh8+$B5+$0100+(VX<<8) // LDA ESTKH+1,X
                    codeptr=>6  = estkh8+$F5+(VX<<8)       // SBC ESTKH
                    codeptr=>8  = $0250                    // BVC +2
                    codeptr=>10 = $8049                    // EOR #$80
                    if opcode == $46
                        //puts("ISLT")
                        codeptr=>12 = $0110                // BPL +1
                    else
                        //puts("ISGE")
                        codeptr=>12 = $0130                // BMI +1
                    fin
                    codeptr=>14 = $9888                    // DEY; TYA
                    codeptr=>16 = estkh8+$94+$0100+(VX<<8) // STY ESTKH+1,X
                    codeptr     = codeptr + 18
                    VX++                                   // INX
                    VY          = UNKNOWN
                    A_IS_TOSL   = TOS_DIRTY                // STA ESTKL,X
                    break
                is $4C // BRFLS
                is $4E // BRTRU
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    codeptr, VX = resolveX(codeptr, VX + 1)      // INX
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5-$0100//+(VX<<8)    // LDA ESTKL-1,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$15-$0100//+(VX<<8)      // ORA ESTKH-1,X
                    if opcode == $4C
                        //puts("BRFLS "); puti(dest)
                        codeptr=>2 = $03D0                       // BNE +3
                    else
                        //puts("BRTRU "); puti(dest)
                        codeptr=>2 = $03F0                       // BEQ +3
                    fin
                    codeptr->4 = $4C                             // 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_TOSL = FALSE
                    break
                is $50 // BRNCH
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    //puts("BRNCH "); puti(dest)
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    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_TOSL = 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_TOSL
                            *codeptr = estkl8+$B5+(VX<<8)                // LDA ESTKL,X
                            codeptr  = codeptr + 2
                        fin
                        codeptr=>0 = estkh8+$B4+(VX<<8)                  // LDY ESTKH,X
                        codeptr, VX = resolveX(codeptr + 2, VX + 1)      // INX
                        repeat
                            dest = *(bytecode+case)
                            //puts("    $"); puth(dest)
                            codeptr=>0 = $C9+(dest<<8)                   // CMP #imm
                            codeptr=>2 = $07D0                           // BNE +7
                            codeptr=>4 = $C0+(dest&$FF00)                // CPY #imm
                            codeptr=>6 = $03D0                           // BNE +3
                            *(bytecode+case) = $FEFE
                            case = case + 2
                            dest = case + *(bytecode+case)
                            //puts("-->"); puti(dest); putln
                            codeptr->8 = $4C                             // JMP abs
                            codeptr=>9 = addrxlate=>[dest]
                            if not (codeptr->10 & $80) // Unresolved address list
                                addrxlate=>[dest] = codeptr + 9 - *jitcodeptr
                            fin
                            codeptr          = codeptr + 11
                            *(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
                    VY        = UNKNOWN
                    A_IS_TOSL = FALSE
                    break
                is $54 // CALL
                    //puts("CALL $"); puth(*(bytecode+i))
                    //
                    // Call address
                    //
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $20                    // JSR abs
                    codeptr=>1 = *(bytecode+i+1)
                    codeptr    = codeptr + 3
                    VY         = UNKNOWN
                    A_IS_TOSL  = FALSE
                    i          = i + 2
                    break
                is $56 // ICAL
                    //puts("ICAL")
                    //
                    // Pull address off stack
                    //
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)                // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = tmpl8+$85                           // STA $E7:TMPL
                    codeptr=>2 = estkh8+$B5+(VX<<8)                  // LDA ESTKH,X
                    codeptr=>4 = tmph8+$85                           // STA $E8:TMPH
                    codeptr, VX = resolveX(codeptr + 6, VX + 1)      // INX
                    //
                    // Call through TMP
                    //
                    codeptr->0 = $20                             // JSR abs
                    codeptr=>1 = jmptmp                          // $E6:JMPTMP
                    codeptr    = codeptr + 3
                    VY         = UNKNOWN
                    A_IS_TOSL  = FALSE
                   break
                is $5A // LEAVE
                    i++
                    //puts("LEAVE "); puti(^(bytecode+i))
                    //
                    // Call into VM
                    //
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8)        // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $20                           // JSR abs
                    codeptr=>1 = directentry                   // INTERP
                    codeptr=>3 = $5A + (^(bytecode+i)<<8)      // LEAVE CODE AND OPERAND
                    codeptr    = codeptr + 5
                    A_IS_TOSL  = FALSE
                    break
                is $5C // RET
                    //puts("RET")
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    ^codeptr  = $60; codeptr++          // RTS
                    A_IS_TOSL = FALSE
                   break
                is $60 // LB
                    //puts("LB")
                    if VY <> 0
                        *codeptr = $00A0                  // LDY #$00
                        codeptr  = codeptr + 2
                        VY       = 0
                    fin
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)     // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$95-$0100+(VX<<8) // STA ESTKH-1,X
                    codeptr=>2 = estkh8+$A1-$0100+(VX<<8) // LDA (ESTKH-1,X)
                    codeptr=>4 = estkh8+$94+(VX<<8)       // STY ESTKH,X
                    codeptr    = codeptr + 6
                    A_IS_TOSL  = TOS_DIRTY                // STA ESTKL,X
                    break
                is $62 // LW
                    //puts("LW")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkh8+$95-$0100+(VX<<8) // STA ESTKH-1,X
                    codeptr=>2  = estkh8+$A1-$0100+(VX<<8) // LDA (ESTKH-1,X)
                    codeptr=>4  = estkl8+$95+(VX<<8)       // STA ESTKL,X
                    codeptr=>6  = estkh8+$F6-$0100+(VX<<8) // INC ESTKH-1,X
                    codeptr=>8  = $02D0                    // BNE +2
                    codeptr=>10 = estkh8+$F6+(VX<<8)       // INC ESTKH,X
                    codeptr=>12 = estkh8+$A1-$0100+(VX<<8) // LDA (ESTKH-1,X)
                    codeptr=>14 = estkh8+$95+(VX<<8)       // STA ESTKH,X
                    codeptr     = codeptr + 16
                    A_IS_TOSL   = FALSE
                    break
                is $64 // LLB
                    i++
                    j = ^(bytecode+i)
                    //puts("LLB "); puti(j)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)  // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                               // DEX
                    if VY <> j
                        *codeptr = $A0+(j<<8)          // LDY #imm
                        codeptr  = codeptr + 2
                    fin
                    *codeptr = ifpl8+$B1               // LDA (IFP),Y
                    codeptr  = codeptr + 2
                    if j <> 0
                        *codeptr = $00A0               // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    *codeptr  = estkh8+$94+(VX<<8)     // STY ESTKH,X
                    codeptr   = codeptr + 2
                    VY        = 0
                    A_IS_TOSL = TOS_DIRTY              // STA ESTKL,X
                    break
                is $66 // LLW
                    i++
                    j = ^(bytecode+i)
                    //puts("LLW "); puti(j)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)  // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                               // DEX
                    if VY <> j
                        *codeptr = $A0+((j+1)<<8)      // LDY #imm
                        codeptr  = codeptr + 2
                        VY       = j
                    else
                        ^codeptr = $C8; codeptr++      // INY
                    fin
                    codeptr=>0 = ifpl8+$B1             // LDA (IFP),Y
                    codeptr=>2 = estkh8+$95+(VX<<8)    // STA ESTKH,X
                    codeptr->4 = $88                   // DEY
                    codeptr=>5 = ifpl8+$B1             // LDA (IFP),Y
                    codeptr    = codeptr + 7
                    A_IS_TOSL  = TOS_DIRTY             // STA ESTKL,X
                    break
                is $68 // LAB
                is $6A // LAW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)   // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    VX--                                // DEX
                    if opcode == $68
                        //puts("LAB $"); puth(dest)
                        if VY <> 0
                            *codeptr = $00A0            // LDY #$00
                            codeptr  = codeptr + 2
                            VY       = 0
                        fin
                        *codeptr = estkh8+$94+(VX<<8)   // STY ESTKH,X
                        codeptr  = codeptr + 2
                    else
                        //puts("LAW $"); puth(dest)
                        codeptr->0 = $AD                // LDA abs+1
                        codeptr=>1 = dest+1
                        codeptr=>3 = estkh8+$95+(VX<<8) // STA ESTKH,X
                        codeptr    = codeptr + 5
                    fin
                    codeptr->0 = $AD                    // LDA abs
                    codeptr=>1 = dest
                    codeptr    = codeptr + 3
                    A_IS_TOSL  = TOS_DIRTY              // STA ESTKL,X
                    break
                is $6C // DLB
                    i++
                    j = ^(bytecode+i)
                    //puts("DLB "); puti(j)
                   if not A_IS_TOSL
                        *codeptr  = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr   = codeptr + 2
                        A_IS_TOSL = TOS_CLEAN
                    fin
                    if VY <> j
                        *codeptr = $A0+(j<<8)          // LDY #imm
                        codeptr  = codeptr + 2
                        VY       = j
                    fin
                    *codeptr = ifpl8+$91               // STA (IFP),Y
                    codeptr  = codeptr + 2
                    if VY <> 0
                        *codeptr = $00A0               // LDY #$00
                        codeptr  = codeptr + 2
                        VY       = 0
                    fin
                    *codeptr = estkh8+$94+(VX<<8)      // STY ESTKH,X
                    codeptr  = codeptr + 2
                 break
                is $6E // DLW
                    i++
                    j = ^(bytecode+i)
                    //puts("DLW "); puti(j)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)  // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> j
                        *codeptr = $A0+((j+1)<<8)      // LDY #imm
                        codeptr  = codeptr + 2
                        VY       = j
                    else
                        ^codeptr = $C8; codeptr++      // INY
                    fin
                    codeptr=>0 = estkh8+$B5+(VX<<8)    // LDA ESTKH,X
                    codeptr=>2 = ifpl8+$91             // STA (IFP),Y
                    codeptr->4 = $88                   // DEY
                    codeptr=>5 = estkl8+$B5+(VX<<8)    // LDA ESTKL,X
                    codeptr=>7 = ifpl8+$91             // STA (IFP),Y
                    codeptr    = codeptr + 9
                    A_IS_TOSL  = TOS_CLEAN
                    break
                is $70 // SB
                is $72 // SW
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)          // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$95-$0100+(VX<<8)      // STA ESTKH-1,X
                    codeptr=>2 = estkl8+$B5+$0100+(VX<<8)      // LDA ESTKL+1,X
                    codeptr=>4 = estkh8+$81-$0100+(VX<<8)      // STA (ESTKH-1,X)
                    if opcode == $70
                        //puts("SB")
                        codeptr     = codeptr + 6
                    else
                        //puts("SW")
                        codeptr=>6  = estkh8+$B5+$0100+(VX<<8) // LDA ESTKH+1,X
                        codeptr=>8  = estkh8+$F6-$0100+(VX<<8) // INC ESTKH-1,X
                        codeptr=>10 = $02D0                    // BNE +2
                        codeptr=>12 = estkh8+$F6+(VX<<8)       // INC ESTKH,X
                        codeptr=>14 = estkh8+$81-$0100+(VX<<8) // STA (ESTKH-1,X)
                        codeptr     = codeptr + 16
                    fin
                    VX        = VX + 2                         // INX; INX
                    A_IS_TOSL = FALSE
                    break
                is $74 // SLB
                is $76 // SLW
                    i++
                    j = ^(bytecode+i)
                    if not A_IS_TOSL
                        *codeptr  = estkl8+$B5+(VX<<8)  // LDA ESTKL,X
                        codeptr   = codeptr + 2
                    fin
                    if VY <> j
                        *codeptr = $A0+(j<<8)           // LDY #imm
                        codeptr  = codeptr + 2
                        VY       = j
                    fin
                    codeptr=>0 = ifpl8+$91              // STA (IFP),Y
                    if opcode == $74
                        //puts("SLB "); puti(j)
                        codeptr    = codeptr + 2
                    else
                        //puts("SLW "); puti(j)
                        codeptr->2 = $C8                // INY
                        codeptr=>3 = estkh8+$B5+(VX<<8) // LDA ESTKH,X
                        codeptr=>5 = ifpl8+$91          // STA (IFP),Y
                        codeptr    = codeptr + 7
                        VY++
                    fin
                    VX++                                // INX
                    A_IS_TOSL  = FALSE
                    break
                is $78 // SAB
                is $7A // SAW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)   // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $8D                    // STA abs
                    codeptr=>1 = dest
                    if opcode ==  $78
                        //puts("SAB $"); puth(dest)
                        codeptr    = codeptr + 3
                    else
                        //puts("SAW $"); puth(dest)
                        codeptr=>3 = estkh8+$B5+(VX<<8) // LDA ESTKH,X
                        codeptr->5 = $8D                // STA abs+1
                        codeptr=>6 = dest+1
                        codeptr    = codeptr + 8
                    fin
                    VX++                                // INX
                    A_IS_TOSL = FALSE
                    break
                is $7C // DAB
                is $7E // DAW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    if not A_IS_TOSL
                        *codeptr  = estkl8+$B5+(VX<<8)  // LDA ESTKL,X
                        codeptr   = codeptr + 2
                        A_IS_TOSL = TOS_CLEAN
                    fin
                    codeptr->0 = $8D                    // STA abs
                    codeptr=>1 = dest
                    if opcode == $7C
                        //puts("DAB $"); puth(dest)
                        codeptr    = codeptr + 3
                        if VY <> 0
                            *codeptr = $00A0            // LDY #$00
                            codeptr  = codeptr + 2
                            VY       = 0
                        fin
                        *codeptr = estkh8+$94+(VX<<8)   // STY ESTKH,X
                        codeptr  = codeptr + 2
                    else
                        //puts("DAW $"); puth(dest)
                        codeptr=>3 = estkh8+$B4+(VX<<8) // LDY ESTKH,X
                        codeptr->5 = $8C                // STY abs+1
                        codeptr=>6 = dest+1
                        codeptr    = codeptr + 8
                        VY         = UNKNOWN
                    fin
                    break
                is $80 // NOT
                    //puts("NOT")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$15+(VX<<8)   // ORA ESTKH,X
                    codeptr=>2 = $02F0                // BEQ +2
                    codeptr=>4 = $FFA9                // LDA #$FF
                    codeptr=>6 = $FF49                // EOR #$FF
                    codeptr=>8 = estkh8+$95+(VX<<8)   // STA ESTKH,X
                    codeptr    = codeptr + 10
                    A_IS_TOSL  = TOS_DIRTY            // STA ESTKL,X
                    break
                is $82 // ADD
                    //puts("ADD")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)     // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $18                      // CLC
                    codeptr=>1 = estkl8+$75+$0100+(VX<<8) // ADC ESTKL+1,X
                    codeptr=>3 = estkl8+$95+$0100+(VX<<8) // STA ESTKL+1,X
                    codeptr=>5 = estkh8+$B5+(VX<<8)       // LDA ESTKH,X
                    codeptr=>7 = estkh8+$75+$0100+(VX<<8) // ADC ESTKH+1,X
                    codeptr=>9 = estkh8+$95+$0100+(VX<<8) // STA ESTKH+1,X
                    codeptr    = codeptr + 11
                    VX++                                  // INX
                    A_IS_TOSL  = FALSE
                    break
                is $84 // SUB
                    //puts("SUB")
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)      // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkl8+$B5+$0100+(VX<<8) // LDA ESTKL+1,X
                    codeptr->2  = $38                      // SEC
                    codeptr=>3  = estkl8+$F5+(VX<<8)       // SBC ESTKL,X
                    codeptr=>5  = estkl8+$95+$0100+(VX<<8) // STA ESTKL+1,X
                    codeptr=>7  = estkh8+$B5+$0100+(VX<<8) // LDA ESTKH+1,X
                    codeptr=>9  = estkh8+$F5+(VX<<8)       // SBC ESTKH,X
                    codeptr=>11 = estkh8+$95+$0100+(VX<<8) // STA ESTKH+1,X
                    codeptr     = codeptr + 13
                    VX++                                   // INX
                    A_IS_TOSL   = FALSE
                    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
                    //
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0 = $20               // JSR INTERP
                    codeptr=>1 = directentry       // INTERP
                    codeptr=>3 = $C000+opcode      // OPCODE; NATV CODE
                    codeptr    = codeptr + 5
                    VY         = UNKNOWN
                    A_IS_TOSL  = FALSE
                    break
                is $90 // NEG
                    //puts("NEG")
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> 0
                        *codeptr = $00A0              // LDY #$00
                        codeptr  = codeptr + 2
                        VY       = 0
                    fin
                    codeptr=>0 = $3898                // TYA -> LDA #$00; SEC
                    codeptr=>2 = estkl8+$F5+(VX<<8)   // SBC ESTKL,X
                    codeptr=>4 = estkl8+$95+(VX<<8)   // STA ESTKL,X
                    codeptr->6 = $98                  // TYA -> LDA #00
                    codeptr=>7 = estkh8+$F5+(VX<<8)   // SBC ESTKH,X
                    codeptr=>9 = estkh8+$95+(VX<<8)   // STA ESTKH,X
                    codeptr    = codeptr + 11
                    A_IS_TOSL  = FALSE
                    break
                is $92 // COMP
                    //puts("COMP")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = $FF49                // EOR #$FF
                    codeptr=>2 = estkl8+$95+(VX<<8)   // STA ESTKL,X
                    codeptr=>4 = estkh8+$B5+(VX<<8)   // LDA ESTKH,X
                    codeptr=>6 = $FF49                // EOR #$FF
                    codeptr=>8 = estkh8+$95+(VX<<8)   // STA ESTKH,X
                    codeptr    = codeptr + 10
                    A_IS_TOSL  = FALSE
                    break
                is $94 // AND
                is $96 // OR
                is $98 // XOR
                    when opcode
                        is $94
                            //puts("AND")
                            j = $35
                            break
                        is $96
                            //puts("OR")
                            j = $15
                            break
                        is $98
                            //puts("XOR")
                            j = $55
                    wend
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0  = j                        // OP
                    codeptr->1  = estkl+$01+VX             //     ESTKL+1,X
                    codeptr=>2  = estkl8+$95+$0100+(VX<<8) // STA ESTKL+1,X
                    codeptr=>4  = estkh8+$B5+(VX<<8)       // LDA ESTKH,X
                    codeptr->6  = j                        // OP
                    codeptr->7  = estkh+$01+VX             //     ESTKH+1,X
                    codeptr=>8  = estkh8+$95+$0100+(VX<<8) // STA ESTKH+1,X
                    codeptr     = codeptr + 10
                    VX++                                   // INX
                    A_IS_TOSL   = FALSE
                    break
                is $9E // IDXW
                    //puts("IDXW")
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0  = $0A                      // ASL
                    codeptr=>1  = estkh8+$36+(VX<<8)       // ROL ESTKH,X
                    codeptr->3  = $18                      // CLC
                    codeptr=>4  = estkl8+$75+$0100+(VX<<8) // ADC ESTKL+1,X
                    codeptr=>6  = estkl8+$95+$0100+(VX<<8) // STA ESTKL+1,X
                    codeptr=>8  = estkh8+$B5+(VX<<8)       // LDA ESTKH,X
                    codeptr=>10 = estkh8+$75+$0100+(VX<<8) // ADC ESTKH+1,X
                    codeptr=>12 = estkh8+$95+$0100+(VX<<8) // STA ESTKH+1,X
                    codeptr     = codeptr + 14
                    VX++                                   // INX
                    A_IS_TOSL   = FALSE
                    break
                is $A0 // BRGT - FOR/NEXT SPECIFIC TEST & BRANCH
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    //puts("BRGT "); puti(dest)
                    codeptr, VX = resolveX(codeptr, VX)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8)      // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkl8+$B5+$0100//+(VX<<8) // LDA ESTKL+1,X
                    codeptr=>2  = estkl8+$D5//+(VX<<8)       // CMP ESTKL,X
                    codeptr=>4  = estkh8+$B5+$0100//+(VX<<8) // LDA ESTKH+1,X
                    codeptr=>6  = estkh8+$F5//+(VX<<8)       // SBC ESTKH
                    codeptr=>8  = $0250                      // BVC +2
                    codeptr=>10 = $8049                      // EOR #$80
                    codeptr=>12 = $0310                      // BPL +3
                    codeptr->14 = $4C                        // JMP abs
                    codeptr=>15 = addrxlate=>[dest]
                    if not (codeptr->16 & $80) // Unresolved address list
                        addrxlate=>[dest] = codeptr + 15 - *jitcodeptr
                    fin
                    codeptr   = codeptr + 17
                    A_IS_TOSL = FALSE
                    break
                is $A2 // BRLT - FOR/NEXT SPECIFIC TEST & BRANCH
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    //puts("BRLT "); puti(dest)
                    codeptr, VX = resolveX(codeptr, VX)
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5//+(VX<<8)      // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    elsif A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8)      // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = estkl8+$D5+$0100//+(VX<<8) // CMP ESTKL+1,X
                    codeptr=>2  = estkh8+$B5//+(VX<<8)       // LDA ESTKH,X
                    codeptr=>4  = estkh8+$F5+$0100//+(VX<<8) // SBC ESTKH+1
                    codeptr=>6  = $0250                      // BVC +2
                    codeptr=>8  = $8049                      // EOR #$80
                    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_TOSL = 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_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)                     // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if opcode == $A4
                        //
                        // INCR
                        //
                        //puts("INCBRLE "); puti(dest)
                        codeptr->0 = $18                                  // CLC
                        codeptr=>1 = $0169                                // ADC #$01
                        codeptr=>3 = estkl8+$95+(VX<<8)                   // STA ESTKL,X
                        codeptr=>5 = $0290                                // BCC +2
                        codeptr=>7 = estkh8+$F6+(VX<<8)                   // INC ESTKH,X
                        codeptr, VX = resolveX(codeptr + 9, VX)
                    else
                        //
                        // ADD
                        //
                        //puts("ADDBRLE "); puti(dest)
                        codeptr->0 = $18                                  // CLC
                        codeptr=>1 = estkl8+$75+$0100+(VX<<8)             // ADC ESTKL+1,X
                        codeptr=>3 = estkl8+$95+$0100+(VX<<8)             // STA ESTKL+1,X
                        codeptr=>5 = estkh8+$B5+(VX<<8)                   // LDA ESTKH,X
                        codeptr=>7 = estkh8+$75+$0100+(VX<<8)             // ADC ESTKH+1,X
                        codeptr=>9 = estkh8+$95+$0100+(VX<<8)             // STA ESTKH+1,X
                        codeptr, VX = resolveX(codeptr + 11, VX + 1)      // INX
                    fin
                    //
                    // BRLE
                    //
                    codeptr=>0  = estkl8+$B5+$0100//+(VX<<8) // LDA ESTKL+1,X
                    codeptr=>2  = estkl8+$D5//+(VX<<8)       // CMP ESTKL,X
                    codeptr=>4  = estkh8+$B5+$0100//+(VX<<8) // LDA ESTKH+1,X
                    codeptr=>6  = estkh8+$F5//+(VX<<8)       // SBC ESTKH
                    codeptr=>8  = $0250                      // BVC +2
                    codeptr=>10 = $8049                      // EOR #$80
                    codeptr=>12 = $0330                      // BMI +3
                    codeptr->14 = $4C                        // JMP abs
                    codeptr=>15 = addrxlate=>[dest]
                    if not (codeptr->16 & $80) // Unresolved address list
                        addrxlate=>[dest] = codeptr + 15 - *jitcodeptr
                    fin
                    codeptr     = codeptr + 17
                    A_IS_TOSL   = 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 A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8)                     // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if opcode == $A8
                        //
                        // DECR
                        //
                        //puts("DECBRGE "); puti(dest)
                        if not A_IS_TOSL
                            *codeptr = estkl8+$B5+(VX<<8)                 // LDA ESTKL,X
                            codeptr  = codeptr + 2
                        fin
                        codeptr->0 = $38                                  // SEC
                        codeptr=>1 = $01E9                                // SBC #$01
                        codeptr=>3 = estkl8+$95+(VX<<8)                   // STA ESTKL,X
                        codeptr=>5 = $02B0                                // BCS +2
                        codeptr=>7 = estkh8+$D6+(VX<<8)                   // DEC ESTKH,X
                        codeptr, VX = resolveX(codeptr + 9, VX)
                    else
                        //
                        // SUB
                        //
                        //puts("SUBBRGE "); puti(dest)
                        if A_IS_TOSL & TOS_DIRTY
                            *codeptr = estkl8+$95+(VX<<8)                 // STA ESTKL,X
                            codeptr  = codeptr + 2
                        fin
                        codeptr=>0  = estkl8+$B5+$0100+(VX<<8)            // LDA ESTKL+1,X
                        codeptr->2  = $38                                 // SEC
                        codeptr=>3  = estkl8+$F5+(VX<<8)                  // SBC ESTKL,X
                        codeptr=>5  = estkl8+$95+$0100+(VX<<8)            // STA ESTKL+1,X
                        codeptr=>7  = estkh8+$B5+$0100+(VX<<8)            // LDA ESTKH+1,X
                        codeptr=>9  = estkh8+$F5+(VX<<8)                  // SBC ESTKH,X
                        codeptr=>11 = estkh8+$95+$0100+(VX<<8)            // STA ESTKH+1,X
                        codeptr, VX = resolveX(codeptr + 13, VX + 1)      // INX
                        *codeptr    = estkl8+$B5//+(VX<<8)                // LDA ESTKL,X
                        codeptr     = codeptr + 2
                    fin
                    //
                    // BRGE
                    //
                    codeptr=>0  = estkl8+$D5+$0100//+(VX<<8) // CMP ESTKL+1,X
                    codeptr=>2  = estkh8+$B5//+(VX<<8)       // LDA ESTKH,X
                    codeptr=>4  = estkh8+$F5+$0100//+(VX<<8) // SBC ESTKH+1,X
                    codeptr=>6  = $0250                      // BVC +2
                    codeptr=>8  = $8049                      // EOR #$80
                    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_TOSL   = FALSE
                    break
                is $AC // BRAND - LOGICAL AND SPECIFIC BRANCH
                is $AE // BROR - LOGICAL OR SPECIFIC BRANCH
                    i++
                    dest = i + *(bytecode+i)
                    i++
                    codeptr, VX = resolveX(codeptr, VX)
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5//+(VX<<8) // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    elsif A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95//+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = estkh8+$15//+(VX<<8)   // ORA ESTKH,X
                    if opcode == $AC
                        //puts("BRAND "); puti(dest)
                        codeptr=>2 = $03D0              // BNE +3
                    else
                        //puts("BROR "); puti(dest)
                        codeptr=>2 = $03F0              // BEQ +3
                    fin
                    codeptr->4 = $4C                    // JMP abs
                    codeptr=>5 = addrxlate=>[dest]
                    if not (codeptr->6 & $80) // Unresolved address list
                        addrxlate=>[dest] = codeptr + 5 - *jitcodeptr
                    fin
                    codeptr   = codeptr + 7
                    VX++                                // INX
                    A_IS_TOSL = FALSE
                    break
                is $B0 // ADDLB
                is $B2 // ADDLW
                    i++
                    j = ^(bytecode+i)
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)    // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> j
                        *codeptr = $A0+(j<<8)            // LDY #imm
                        codeptr  = codeptr + 2
                        VY       = j
                    fin
                    codeptr->0 = $18                     // CLC
                    codeptr=>1 = ifpl8+$71               // ADC (IFP),Y
                    if opcode == $B0
                        //puts("ADDLB "); puti(j)
                        codeptr=>3  = $0290              // BCC +2
                        codeptr=>5  = estkh8+$F6+(VX<<8) // INC ESTKH,X
                        codeptr     = codeptr + 7
                        A_IS_TOSL   = TOS_DIRTY          // STA ESTKL,X
                    else
                        //puts("ADDLW "); puti(j)
                        codeptr=>3  = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr=>5  = estkh8+$B5+(VX<<8) // LDA ESTKH,X
                        codeptr->7  = $C8                // INY
                        codeptr=>8  = ifpl8+$71          // ADC (IFP),Y
                        codeptr=>10 = estkh8+$95+(VX<<8) // STA ESTKH,X
                        codeptr     = codeptr + 12
                        VY++
                        A_IS_TOSL   = FALSE
                    fin
                    break
                is $B4 // ADDAB
                is $B6 // ADDAW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    if not A_IS_TOSL
                        *codeptr = estkl8+$B5+(VX<<8)    // LDA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0 = $6D18                   // CLC; ADC abs
                    codeptr=>2 = dest
                    if opcode == $B4
                        //puts("ADDAB $"); puth(dest)
                        codeptr=>4  = $0290              // BCC +2
                        codeptr=>6  = estkh8+$F6+(VX<<8) // INC ESTKH,X
                        codeptr     = codeptr + 8
                        A_IS_TOSL   = TOS_DIRTY          // STA ESTKL,X
                    else
                        //puts("ADDAW $"); puth(dest)
                        codeptr=>4  = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr=>6  = estkh8+$B5+(VX<<8) // LDA ESTKH,X
                        codeptr->8  = $6D                // ADC abs
                        codeptr=>9  = dest+1
                        codeptr=>11 = estkh8+$95+(VX<<8) // STA ESTKH,X
                        codeptr     = codeptr + 13
                        A_IS_TOSL   = FALSE
                    fin
                    break
                is $B8 // IDXLB
                    i++
                    j = ^(bytecode+i)
                    //puts("IDXLB "); puti(j)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> j
                        *codeptr = $A0+(j<<8)         // LDY #imm
                        codeptr  = codeptr + 2
                    fin
                    *codeptr = ifpl8+$B1              // LDA (IFP),Y
                    codeptr  = codeptr + 2
                    if j <> 0
                        *codeptr = $00A0              // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0  = $0A                 // ASL
                    codeptr=>1  = $0290               // BCC +2
                    codeptr=>3  = $18C8               // INY; CLC
                    codeptr=>5  = estkl8+$75+(VX<<8)  // ADC ESTKL,X
                    codeptr=>7  = estkl8+$95+(VX<<8)  // STA ESTKL,X
                    codeptr->9  = $98                 // TYA
                    codeptr=>10 = estkh8+$75+(VX<<8)  // ADC ESTKH,X
                    codeptr=>12 = estkh8+$95+(VX<<8)  // STA ESTKH,X
                    codeptr     = codeptr + 14
                    VY          = UNKNOWN
                    A_IS_TOSL   = FALSE
                    break
                is $BA // IDXLW
                    i++
                    j = ^(bytecode+i)
                    //puts("IDXLW "); puti(j)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> j
                        *codeptr = $A0+(j<<8)         // LDY #imm
                        codeptr  = codeptr + 2
                    fin
                    codeptr=>0  = ifpl8+$B1           // LDA (IFP),Y
                    codeptr->2  = $0A                 // ASL
                    codeptr=>3  = tmpl8+$85           // STA $E7:TMPL
                    codeptr->5  = $C8                 // INY
                    codeptr=>6  = ifpl8+$B1           // LDA (IFP),Y
                    codeptr=>8  = $A82A               // ROL; TAY
                    codeptr=>10 = tmpl8+$A5           // LDA $E7:TMPL
                    codeptr->12 = $18                 // CLC
                    codeptr=>13 = estkl8+$75+(VX<<8)  // ADC ESTKL,X
                    codeptr=>15 = estkl8+$95+(VX<<8)  // STA ESTKL,X
                    codeptr->17 = $98                 // TYA
                    codeptr=>18 = estkh8+$75+(VX<<8)  // ADC ESTKH,X
                    codeptr=>20 = estkh8+$95+(VX<<8)  // STA ESTKH,X
                    codeptr     = codeptr + 22
                    VY          = UNKNOWN
                    A_IS_TOSL   = FALSE
                    break
                is $BC // IDXAB
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    //puts("IDXAB $"); puth(*(bytecode+i))
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    if VY <> 0
                        *codeptr = $00A0              // LDY #$00
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0  = $AD                 // LDA abs
                    codeptr=>1  = dest
                    codeptr->3  = $0A                 // ASL
                    codeptr=>4  = $0290               // BCC +2
                    codeptr=>6  = $18C8               // INY; CLC
                    codeptr=>8  = estkl8+$75+(VX<<8)  // ADC ESTKL,X
                    codeptr=>10 = estkl8+$95+(VX<<8)  // STA ESTKL,X
                    codeptr->12 = $98                 // TYA
                    codeptr=>13 = estkh8+$75+(VX<<8)  // ADC ESTKH,X
                    codeptr=>15 = estkh8+$95+(VX<<8)  // STA ESTKH,X
                    codeptr     = codeptr + 17
                    VY          = UNKNOWN
                    A_IS_TOSL   = FALSE
                    break
                is $BE // IDXAW
                    dest = *(bytecode+i+1)
                    i    = i + 2
                    //puts("IDXAW $"); puth(dest)
                    if A_IS_TOSL & TOS_DIRTY
                        *codeptr = estkl8+$95+(VX<<8) // STA ESTKL,X
                        codeptr  = codeptr + 2
                    fin
                    codeptr->0  = $AD                 // LDA abs
                    codeptr=>1  = dest
                    codeptr->3  = $0A                 // ASL
                    codeptr=>4  = tmpl8+$85           // STA $E7:TMPL
                    codeptr->6  = $AD                 // LDA abs+1
                    codeptr=>7  = dest+1
                    codeptr=>9  = $A82A               // ROL; TAY
                    codeptr=>11 = tmpl8+$A5           // LDA $E7:TMPL
                    codeptr->13 = $18                 // CLC
                    codeptr=>14 = estkl8+$75+(VX<<8)  // ADC ESTKL,X
                    codeptr=>16 = estkl8+$95+(VX<<8)  // STA ESTKL,X
                    codeptr->18 = $98                 // TYA
                    codeptr=>19 = estkh8+$75+(VX<<8)  // ADC ESTKH,X
                    codeptr=>21 = estkh8+$95+(VX<<8)  // STA ESTKH,X
                    codeptr     = codeptr + 23
                    VY          = UNKNOWN
                    A_IS_TOSL   = FALSE
                    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
            //puts("Done compiling: $"); puth(defptr=>interpaddr)
            //puts("->$"); puth(*jitcodeptr); putln
            //getc
            return
        fin
    loop
    //
    // If we got here we ran out of code buffer space.
    //
    //puts("Ran out of code buffer\n")
    //getc
end
