/* m6800.c: SWTP 6800 CPU simulator

   Copyright (c) 2005-2012, William Beech

       Permission is hereby granted, free of charge, to any person obtaining a
       copy of this software and associated documentation files (the "Software"),
       to deal in the Software without restriction, including without limitation
       the rights to use, copy, modify, merge, publish, distribute, sublicense,
       and/or sell copies of the Software, and to permit persons to whom the
       Software is furnished to do so, subject to the following conditions:

       The above copyright notice and this permission notice shall be included in
       all copies or substantial portions of the Software.

       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       WILLIAM A. BEECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
       IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

       Except as contained in this notice, the name of William A. Beech shall not
       be used in advertising or otherwise to promote the sale, use or other dealings
       in this Software without prior written authorization from William A. Beech.

    MODIFICATIONS:

        21 Apr 20 -- Richard Brinegar numerous fixes for condition code errors
        28 May 22 -- Roberto Sancho Villa (RSV)some more fixes for condition code errors

    NOTES:
       cpu                  Motorola M6800 CPU

       The register state for the M6800 CPU is:

       A<0:7>               Accumulator A
       B<0:7>               Accumulator B
       IX<0:15>             Index Register
       CC<0:7>              Condition Code Register
           HF                   half-carry flag
           IF                   interrupt flag
           NF                   negative flag
           ZF                   zero flag
           VF                   overflow flag
           CF                   carry flag
       PC<0:15>             program counter
       SP<0:15>             Stack Pointer

       The M6800 is an 8-bit CPU, which uses 16-bit registers to address
       up to 64KB of memory.

       The 72 basic instructions come in 1, 2, and 3-byte flavors.

       This routine is the instruction decode routine for the M6800.
       It is called from the CPU board simulator to execute
       instructions in simulated memory, starting at the simulated PC.
       It runs until 'reason' is set non-zero.

       General notes:

       1. Reasons to stop.  The simulator can be stopped by:

            WAI instruction
            I/O error in I/O simulator
            Invalid OP code (if ITRAP is set on CPU)
            Invalid mamory address (if MTRAP is set on CPU)

       2. Interrupts.
          There are 4 types of interrupt, and in effect they do a
          hardware CALL instruction to one of 4 possible high memory addresses.

       3. Non-existent memory.
            On the SWTP 6800, reads to non-existent memory
            return 0FFH, and writes are ignored.
*/

#include <stdio.h>

#include "swtp_defs.h"

#define UNIT_V_OPSTOP   (UNIT_V_UF)     /* Stop on Invalid OP? */
#define UNIT_OPSTOP     (1 << UNIT_V_OPSTOP)
#define UNIT_V_MSTOP    (UNIT_V_UF+1)   /* Stop on Invalid memory? */
#define UNIT_MSTOP      (1 << UNIT_V_MSTOP)

/* Flag values to set proper positions in CC */
#define HF      0x20
#define IF      0x10
#define NF      0x08
#define ZF      0x04
#define VF      0x02
#define CF      0x01

/* Macros to handle the flags in the CC */
#define CC_ALWAYS_ON       (0xC0)        /* for 6800 */
#define CC_MSK (HF|IF|NF|ZF|VF|CF)
#define TOGGLE_FLAG(FLAG)   (CC ^= (FLAG))
#define SET_FLAG(FLAG)      (CC |= (FLAG))
#define CLR_FLAG(FLAG)      (CC &= ~(FLAG))
#define GET_FLAG(FLAG)      (CC & (FLAG))
#define COND_SET_FLAG(COND,FLAG) \
    if (COND) SET_FLAG(FLAG); else CLR_FLAG(FLAG)
#define COND_SET_FLAG_N(VAR) \
    if ((VAR) & 0x80) SET_FLAG(NF); else CLR_FLAG(NF)
#define COND_SET_FLAG_Z(VAR) \
    if ((VAR) == 0) SET_FLAG(ZF); else CLR_FLAG(ZF)
#define COND_SET_FLAG_H(VAR) \
    if ((VAR) & 0x10) SET_FLAG(HF); else CLR_FLAG(HF)
#define COND_SET_FLAG_C(VAR) \
    if ((VAR) & 0x100) SET_FLAG(CF); else CLR_FLAG(CF)
#define COND_SET_FLAG_V(COND) \
    if (COND) SET_FLAG(VF); else CLR_FLAG(VF)

#define m6800_NAME    "Motorola M6800 Processor Chip"

#define HIST_MIN        64
#define HIST_MAX        (1u << 18)
#define HIST_ILNT       3                               /* max inst length */

typedef struct {
    uint16              pc;
    uint16              sp;
    uint8               cc;
    uint8               a;
    uint8               b;
    uint16              ix;
    t_value             inst[HIST_ILNT];
    } InstHistory;

/* local global variables */
int32 A = 0;                            /* Accumulator A */
int32 B = 0;                            /* Accumulator B */
int32 IX = 0;                           /* Index register */
int32 SP = 0;                           /* Stack pointer */
int32 CC = CC_ALWAYS_ON | IF;           /* Condition Code Register */
int32 saved_PC = 0xffff;                /* Program counter */
int32 PC;                               /* global for the helper routines */
int32 NMI = 0, IRQ = 0;                 //interrupt flags
int32 hst_p = 0;                        /* history pointer */
int32 hst_lnt = 0;                      /* history length */
InstHistory *hst = NULL;                /* instruction history */
int32 reason;                           //reason for halting processor
static const char* m6800_desc(DEVICE *dptr) {
    return m6800_NAME;
}

/* function prototypes */

t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat m6800_reset (DEVICE *dptr);
t_stat m6800_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat m6800_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw);

void dump_regs(void);
int32 fetch_byte(void);
int32 fetch_word(void);
uint8 pop_byte(void);
uint16 pop_word(void);
void push_byte(uint8 val);
void push_word(uint16 val);
void go_rel(int32 cond);
int32 get_vec_val(int32 vec);
int32 get_imm_val(void);
int32 get_dir_val(void);
int32 get_indir_val(void);
int32 get_ext_val(void);
int32 get_flag(int32 flag);
void condevalVa(int32 op1, int32 op2);
void condevalVs(int32 op1, int32 op2);
void condevalHa(int32 op1, int32 op2);

/* external routines */

extern void CPU_BD_put_mbyte(int32 addr, int32 val);
extern void CPU_BD_put_mword(int32 addr, int32 val);
extern int32 CPU_BD_get_mbyte(int32 addr);
extern int32 CPU_BD_get_mword(int32 addr);

static const char *opcode[] = {
"???  ", "NOP  ", "???  ", "???  ",     //0x00
"???  ", "???  ", "TAP  ", "TPA  ",
"INX  ", "DEX  ", "CLV  ", "SEV  ",
"CLC  ", "SEC  ", "CLI  ", "SEI  ",
"SBA  ", "CBA  ", "???  ", "???  ",     //0x10
"???  ", "???  ", "TAB  ", "TBA  ",
"???  ", "DAA  ", "???  ", "ABA  ",
"???  ", "???  ", "???  ", "???  ",
"BRA  ", "???  ", "BHI  ", "BLS  ",     //0x20
"BCC  ", "BCS  ", "BNE  ", "BEQ  ",
"BVC  ", "BVS  ", "BPL  ", "BMI  ",
"BGE  ", "BLT  ", "BGT  ", "BLE  ",
"TSX  ", "INS  ", "PUL A", "PUL B",     //0x30
"DES  ", "TXS  ", "PSH A", "PSH B",
"???  ", "RTS  ", "???  ", "RTI  ",
"???  ", "???  ", "WAI  ", "SWI  ",
"NEG A", "???  ", "???  ", "COM A",     //0x40
"LSR A", "???  ", "ROR A", "ASR A",
"ASL A", "ROL A", "DEC A", "???  ",
"INC A", "TST A", "???  ", "CLR A",
"NEG B", "???  ", "???  ", "COM B",     //0x50
"LSR B", "???  ", "ROR B", "ASR B",
"ASL B", "ROL B", "DEC B", "???  ",
"INC B", "TST B", "???  ", "CLR B",
"NEG  ", "???  ", "???  ", "COM  ",     //0x60
"LSR  ", "???  ", "ROR  ", "ASR  ",
"ASL  ", "ROL  ", "DEC  ", "???  ",
"INC  ", "TST  ", "JMP  ", "CLR  ",
"NEG  ", "???  ", "???  ", "COM  ",     //0x70
"LSR  ", "???  ", "ROR  ", "ASR  ",
"ASL  ", "ROL  ", "DEC  ", "???  ",
"INC  ", "TST  ", "JMP  ", "CLR  ",
"SUB A", "CMP A", "SBC A", "???  ",     //0x80
"AND A", "BIT A", "LDA A", "???  ",
"EOR A", "ADC A", "ORA A", "ADD A",
"CPX  ", "BSR  ", "LDS  ", "???  ",
"SUB A", "CMP A", "SBC A", "???  ",     //0x90
"AND A", "BIT A", "LDA A", "STA A",
"EOR A", "ADC A", "ORA A", "ADD A",
"CPX  ", "???  ", "LDS  ", "STS  ",
"SUB A", "CMP A", "SBC A", "???  ",     //0xA0
"AND A", "BIT A", "LDA A", "STA A",
"EOR A", "ADC A", "ORA A", "ADD A",
"CPX X", "JSR X", "LDS X", "STS X",
"SUB A", "CMP A", "SBC A", "???  ",     //0xB0
"AND A", "BIT A", "LDA A", "STA A",
"EOR A", "ADC A", "ORA A", "ADD A",
"CPX  ", "JSR  ", "LDS  ", "STS  ",
"SUB B", "CMP B", "SBC B", "???  ",     //0xC0
"AND B", "BIT B", "LDA B", "???  ",
"EOR B", "ADC B", "ORA B", "ADD B",
"???  ", "???  ", "LDX  ", "???  ",
"SUB B", "CMP B", "SBC B", "???  ",     //0xD0
"AND B", "BIT B", "LDA B", "STA B",
"EOR B", "AD CB", "ORA B", "ADD B",
"???  ", "???  ", "LDX  ", "STX  ",
"SUB B", "CMP B", "SBC B", "???  ",     //0xE0
"AND B", "BIT B", "LDA B", "STA B",
"EOR B", "ADC B", "ORA B", "ADD B",
"???  ", "???  ", "LDX  ", "STX  ",
"SUB B", "CMP B", "SBC B", "???  ",     //0xF0
"AND B", "BIT B", "LDA B", "STA B",
"EOR B", "ADC B", "ORA B", "ADD B",
"???  ", "???  ", "LDX  ", "STX  ",
};

int32 oplen[256] = {
0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,        //0x00
1,1,0,0,0,0,1,1,0,1,0,1,0,0,0,0,
2,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
1,1,1,1,1,1,1,1,0,1,0,1,0,0,1,1,
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,        //0x40
1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,
2,0,0,2,2,0,2,2,2,2,2,0,2,2,2,2,
3,0,0,3,3,0,3,3,3,3,3,0,3,3,3,3,
2,2,2,0,2,2,2,0,2,2,2,2,3,2,3,0,        //0x80
2,2,2,0,2,2,2,2,2,2,2,2,2,0,2,2,
2,2,2,0,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,0,3,3,3,3,3,3,3,3,3,3,3,3,
2,2,2,0,2,2,2,0,2,2,2,2,0,0,3,0,        //0xC0
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
2,2,2,0,2,2,2,2,2,2,2,2,0,0,2,2,
3,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3
};

/* CPU data structures

   m6800_dev        CPU device descriptor
   m6800_unit       CPU unit descriptor
   m6800_reg        CPU register list
   m6800_mod        CPU modifiers list */

UNIT m6800_unit = { UDATA (NULL, 0, 0) };

REG m6800_reg[] = {
    { HRDATA (PC, saved_PC, 16) },
    { HRDATA (A, A, 8) },
    { HRDATA (B, B, 8) },
    { HRDATA (IX, IX, 16) },
    { HRDATA (SP, SP, 16) },
    { HRDATA (CC, CC, 8) },
    { ORDATA (WRU, sim_int_char, 8) },
    { NULL }  
};

MTAB m6800_mod[] = {
    { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL },
    { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL },
    { UNIT_MSTOP, UNIT_MSTOP, "MTRAP", "MTRAP", NULL },
    { UNIT_MSTOP, 0, "NOMTRAP", "NOMTRAP", NULL },
    { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP|MTAB_NC, 0, "HISTORY", "HISTORY=n",
      &cpu_set_hist, &cpu_show_hist, NULL, "Enable/Display instruction history" },
    { 0 }  
};

DEBTAB m6800_debug[] = {
    { "ALL", DEBUG_all, "All debug bits" },
    { "FLOW", DEBUG_flow, "Flow control" },
    { "READ", DEBUG_read, "Read Command" },
    { "WRITE", DEBUG_write, "Write Command"},
    { NULL }
};

DEVICE m6800_dev = {
    "CPU",                              //name
    &m6800_unit,                        //units
    m6800_reg,                          //registers
    m6800_mod,                          //modifiers
    1,                                  //numunits
    16,                                 //aradix
    16,                                 //awidth
    1,                                  //aincr
    16,                                 //dradix
    8,                                  //dwidth
    &m6800_ex,                          //examine
    &m6800_dep,                         //deposit
    &m6800_reset,                       //reset
    NULL,                               //boot
    NULL,                               //attach
    NULL,                               //detach
    NULL,                               //ctxt
    DEV_DEBUG,                          //flags
    0,                                  //dctrl
    m6800_debug,                        //debflags
    NULL,                               //msize
    NULL,                               //lname
    NULL,                               //help routine
    NULL,                               //attach help routine
    NULL,                               //help context
    &m6800_desc                         //device description
};

t_stat sim_instr (void)
{
    int32 IR, EA, hi, lo, op1, i, sw = 0;
    InstHistory *hst_ent = NULL;

    PC = saved_PC & ADDRMASK;           /* load local PC */
    reason = 0;

    /* Main instruction fetch/decode loop */

    while (reason == 0) {               /* loop until halted */
        if (sim_interval <= 0)          /* check clock queue */
            if ((reason = sim_process_event ()))
                break;
        if (NMI > 0) {                  //* NMI? */
            push_word(PC);
            push_word(IX);
            push_byte(A);
            push_byte(B);
            push_byte(CC);
            PC = get_vec_val(0xFFFC);
        }                               /* end NMI */
        if (IRQ > 0) {                  //* IRQ? */
            if (GET_FLAG(IF) == 0) {
                push_word(PC);
                push_word(IX);
                push_byte(A);
                push_byte(B);
                push_byte(CC);
                SET_FLAG(IF);           //rsv fix
                PC = get_vec_val(0xFFF8);
            }
        }                               /* end IRQ */
        if (sim_brk_summ &&
            sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
            reason = STOP_IBKPT;        /* stop simulation */
            break;
        }

        if (hst_lnt) {                  /* record history? */
            hst_ent = &hst[hst_p];
            hst_ent->pc = PC;
            hst_ent->sp = SP;
            hst_ent->cc = CC;
            hst_ent->a = A;
            hst_ent->b = B;
            hst_ent->ix = IX;
            for (i = 0; i < HIST_ILNT; i++)
                hst_ent->inst[i] = (t_value)CPU_BD_get_mbyte (PC + i);
            hst_p = (hst_p + 1);
            if (hst_p >= hst_lnt)
                hst_p = 0;
        }

        sim_interval--;
        IR = fetch_byte();              /* fetch instruction */

        /* The Big Instruction Decode Switch */

        switch (IR) {
            case 0x01:                  /* NOP */
                break;
            case 0x06:                  /* TAP */
                CC = A | CC_ALWAYS_ON;
                break;
            case 0x07:                  /* TPA */
                A = CC;
                break;
            case 0x08:                  /* INX */
                IX = (IX + 1) & ADDRMASK;
                COND_SET_FLAG_Z(IX);
                break;
            case 0x09:                  /* DEX */
                IX = (IX - 1) & ADDRMASK;
                COND_SET_FLAG_Z(IX);
                break;
            case 0x0A:                  /* CLV */
                CLR_FLAG(VF);
                break;
            case 0x0B:                  /* SEV */
                SET_FLAG(VF);
                break;
            case 0x0C:                  /* CLC */
                CLR_FLAG(CF);
                break;
            case 0x0D:                  /* SEC */
                SET_FLAG(CF);
                break;
            case 0x0E:                  /* CLI */
                CLR_FLAG(IF);
                break;
            case 0x0F:                  /* SEI */
                SET_FLAG(IF);
                break;
            case 0x10:                  /* SBA */
                op1 = A;
                A = A - B;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, B);
                break;
            case 0x11:                  /* CBA */
                lo = A - B;
                COND_SET_FLAG_C(lo);
                lo &= BYTEMASK;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                condevalVs(A, B);
                break;
            case 0x16:                  /* TAB */
                B = A;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                CLR_FLAG(VF);
                break;
            case 0x17:                  /* TBA */
                A = B;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                CLR_FLAG(VF);
                break;
            case 0x19:                  /* DAA */
                EA = A & 0x0F;
                if ((EA > 9) || get_flag(HF)) {
                    EA += 6 ;
                    A = (A & 0xF0) + EA;
                    COND_SET_FLAG(EA & 0x10, HF);
                }
                EA = (A >> 4) & 0x0F;
                if ((EA > 9) || get_flag(CF)) {
                    EA += 6;
                    A = (A & 0x0F) | (EA << 4) | 0x100;
                }
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x1B:                  /* ABA */
                op1 = A ;
                A += B;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, B);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, B);
                break;
            case 0x20:                  /* BRA rel */
                go_rel(1);
                break;
            case 0x22:                  /* BHI rel */
                go_rel(!(get_flag(CF) | get_flag(ZF)));
                break;
            case 0x23:                  /* BLS rel */
                go_rel(get_flag(CF) | get_flag(ZF));
                break;
            case 0x24:                  /* BCC rel */
                go_rel(!get_flag(CF));
                break;
            case 0x25:                  /* BCS rel */
                go_rel(get_flag(CF));
                break;
            case 0x26:                  /* BNE rel */
                go_rel(!get_flag(ZF));
                break;
            case 0x27:                  /* BEQ rel */
                go_rel(get_flag(ZF));
                break;
            case 0x28:                  /* BVC rel */
                go_rel(!get_flag(VF));
                break;
            case 0x29:                  /* BVS rel */
                go_rel(get_flag(VF));
                break;
            case 0x2A:                  /* BPL rel */
                go_rel(!get_flag(NF));
                break;
            case 0x2B:                  /* BMI rel */
                go_rel(get_flag(NF));
                break;
            case 0x2C:                  /* BGE rel */
                go_rel(!(get_flag(NF) ^ get_flag(VF)));
                break;
            case 0x2D:                  /* BLT rel */
                go_rel(get_flag(NF) ^ get_flag(VF));
                break;
            case 0x2E:                  /* BGT rel */
                go_rel(!(get_flag(ZF) | (get_flag(NF) ^ get_flag(VF))));
                break;
            case 0x2F:                  /* BLE rel */
                go_rel(get_flag(ZF) | (get_flag(NF) ^ get_flag(VF)));
                break;
            case 0x30:                  /* TSX */
                IX = (SP + 1) & ADDRMASK;
                break;
            case 0x31:                  /* INS */
                SP = (SP + 1) & ADDRMASK;
                break;
            case 0x32:                  /* PUL A */
                A = pop_byte();
                break;
            case 0x33:                  /* PUL B */
                B = pop_byte();
                break;
            case 0x34:                  /* DES */
                SP = (SP - 1) & ADDRMASK;
                break;
            case 0x35:                  /* TXS */
                SP = (IX - 1) & ADDRMASK;
                break;
            case 0x36:                  /* PSH A */
                push_byte(A);
                break;
            case 0x37:                  /* PSH B */
                push_byte(B);
                break;
            case 0x39:                  /* RTS */
                PC = pop_word();
                break;
            case 0x3B:                  /* RTI */
                CC = pop_byte();
                B = pop_byte();
                A = pop_byte();
                IX = pop_word();
                PC = pop_word();
                break;
            case 0x3E:                  /* WAI */
                push_word(PC);
                push_word(IX);
                push_byte(A);
                push_byte(B);
                push_byte(CC);
                if (get_flag(IF)) {
                    reason = STOP_HALT;
                    continue;
                } else {
                    SET_FLAG(IF);
                    PC = get_vec_val(0xFFFE);
                }
                break;
            case 0x3F:                  /* SWI */
                push_word(PC);
                push_word(IX);
                push_byte(A);
                push_byte(B);
                push_byte(CC);
                SET_FLAG(IF);
                PC = get_vec_val(0xFFFA);
                break;
            case 0x40:                  /* NEG A */
                op1 = A;
                A = (0 - A) & BYTEMASK;
                condevalVs(A, op1); //RSV - fixed boundry condition
                COND_SET_FLAG(A,CF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x43:                  /* COM A */
                A = ~A & BYTEMASK;
                CLR_FLAG(VF);
                SET_FLAG(CF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x44:                  /* LSR A */
                COND_SET_FLAG(A & 0x01,CF);
                A = (A >> 1) & BYTEMASK;
                CLR_FLAG(NF);
                COND_SET_FLAG_Z(A);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x46:                  /* ROR A */
                hi = get_flag(CF);
                COND_SET_FLAG(A & 0x01,CF);
                A = (A >> 1) & BYTEMASK;
                if (hi)
                    A |= 0x80;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x47:                  /* ASR A */
                COND_SET_FLAG(A & 0x01,CF);
                lo = A & 0x80;
                A = (A >> 1) & BYTEMASK;
                A |= lo;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x48:                  /* ASL A */
                COND_SET_FLAG(A & 0x80,CF);
                A = (A << 1) & BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x49:                  /* ROL A */
                hi = get_flag(CF);
                COND_SET_FLAG(A & 0x80,CF);
                A = (A << 1) & BYTEMASK;
                if (hi)
                    A |= 0x01;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x4A:                  /* DEC A */
                COND_SET_FLAG_V(A == 0x80);
                A = (A - 1) & BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x4C:                  /* INC A */
                COND_SET_FLAG_V(A == 0x7F);
                A = (A + 1) & BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x4D:                  /* TST A */
                lo = (A - 0) & BYTEMASK;
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x4F:                  /* CLR A */
                A = 0;
                CLR_FLAG(NF);
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                SET_FLAG(ZF);
                break;
            case 0x50:                  /* NEG B */
                op1 = B;
                B = (0 - B) & BYTEMASK;
                condevalVs(B, op1); //RSV - fixed boundry condition
                COND_SET_FLAG(B,CF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0x53:                  /* COM B */
                B = ~B;
                B &= BYTEMASK;
                CLR_FLAG(VF);
                SET_FLAG(CF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0x54:                  /* LSR B */
                COND_SET_FLAG(B & 0x01,CF);
                B = (B >> 1) & BYTEMASK;
                CLR_FLAG(NF);
                COND_SET_FLAG_Z(B);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x56:                  /* ROR B */
                hi = get_flag(CF);
                COND_SET_FLAG(B & 0x01,CF);
                B = (B >> 1) & BYTEMASK;
                if (hi)
                    B |= 0x80;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x57:                  /* ASR B */
                COND_SET_FLAG(B & 0x01,CF);
                lo = B & 0x80;
                B = (B >> 1) & BYTEMASK;
                B |= lo;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x58:                  /* ASL B */
                COND_SET_FLAG(B & 0x80,CF);
                B = (B << 1) & BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x59:                  /* ROL B */
                hi = get_flag(CF);
                COND_SET_FLAG(B & 0x80,CF);
                B = (B << 1) & BYTEMASK;
                if (hi)
                    B |= 0x01;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x5A:                  /* DEC B */
                COND_SET_FLAG_V(B == 0x80);
                B = (B - 1) & BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0x5C:                  /* INC B */
                COND_SET_FLAG_V(B == 0x7F);
                B = (B + 1) & BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0x5D:                  /* TST B */
                lo = (B - 0) & BYTEMASK;
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x5F:                  /* CLR B */
                B = 0;
                CLR_FLAG(NF);
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                SET_FLAG(ZF);
                break;
            case 0x60:                  /* NEG ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                op1 = CPU_BD_get_mbyte(EA);
                lo = (0 - op1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                condevalVs(lo, op1); //RSV - fixed boundry condition
                COND_SET_FLAG(lo,CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x63:                  /* COM ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = ~CPU_BD_get_mbyte(EA);
                lo &= BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                CLR_FLAG(VF);
                SET_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x64:                  /* LSR ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x01,CF);
                lo >>= 1;
                CPU_BD_put_mbyte(EA, lo);
                CLR_FLAG(NF);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x66:                  /* ROR ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                hi = get_flag(CF);
                COND_SET_FLAG(lo & 0x01,CF);
                lo >>= 1;
                if (hi)
                    lo |= 0x80;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x67:                  /* ASR ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x01,CF);
                lo = (lo & 0x80) | (lo >> 1);
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x68:                  /* ASL ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x80,CF);
                lo = (lo << 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x69:                  /* ROL ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                hi = get_flag(CF);
                COND_SET_FLAG(lo & 0x80,CF);
                lo = (lo << 1) &BYTEMASK;
                if (hi) lo |= 0x01;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x6A:                  /* DEC ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG_V(lo == 0x80);
                lo = (lo - 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x6C:                  /* INC ind */
                EA= (fetch_byte() + IX) & ADDRMASK;
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG_V(lo == 0x7F);
                lo = (lo + 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x6D:                  /* TST ind */
                lo = (get_indir_val() - 0) & BYTEMASK;
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x6E:                  /* JMP ind */
                PC = (fetch_byte() + IX) & ADDRMASK;
                break;
            case 0x6F:                  /* CLR ind */
                CPU_BD_put_mbyte((fetch_byte() + IX) & ADDRMASK, 0);
                CLR_FLAG(NF);
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                SET_FLAG(ZF);
                break;
            case 0x70:                  /* NEG ext */
                EA = fetch_word();
                op1 = CPU_BD_get_mbyte(EA);
                lo = (0 - op1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                condevalVs(lo, op1); //RSV - fixed boundry condition
                CLR_FLAG(CF);
                if (lo)
                    SET_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x73:                  /* COM ext */
                EA = fetch_word();
                lo = ~CPU_BD_get_mbyte(EA);
                lo &= BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                CLR_FLAG(VF);
                SET_FLAG(CF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x74:                  /* LSR ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x01,CF);
                lo >>= 1;
                CPU_BD_put_mbyte(EA, lo);
                CLR_FLAG(NF);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x76:                  /* ROR ext */
                EA = fetch_word();
                hi = get_flag(CF);
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x01,CF);
                lo >>= 1;
                if (hi)
                    lo |= 0x80;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x77:                  /* ASR ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x01,CF);
                hi = lo & 0x80;
                lo >>= 1;
                lo |= hi;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x78:                  /* ASL ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG(lo & 0x80,CF);
                lo = (lo << 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x79:                  /* ROL ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                hi = get_flag(CF);
                COND_SET_FLAG(lo & 0x80,CF);
                lo = (lo << 1) & BYTEMASK;
                if (hi) lo |= 0x01;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                COND_SET_FLAG_V(get_flag(NF) ^ get_flag(CF));
                break;
            case 0x7A:                  /* DEC ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG_V(lo == 0x80);
                lo = (lo - 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x7C:                  /* INC ext */
                EA = fetch_word();
                lo = CPU_BD_get_mbyte(EA);
                COND_SET_FLAG_V(lo == 0x7F);
                lo = (lo + 1) & BYTEMASK;
                CPU_BD_put_mbyte(EA, lo);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x7D:                  /* TST ext */
                lo = CPU_BD_get_mbyte(fetch_word()) - 0;
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                COND_SET_FLAG_N(lo);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0x7E:                  /* JMP ext */
                PC = fetch_word() & ADDRMASK;
                break;
            case 0x7F:                  /* CLR ext */
                CPU_BD_put_mbyte(fetch_word(), 0);
                CLR_FLAG(NF);
                CLR_FLAG(VF);
                CLR_FLAG(CF);
                SET_FLAG(ZF);
                break;
            case 0x80:                  /* SUB A imm */
                lo = fetch_byte();
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0x81:                  /* CMP A imm */
                op1 = fetch_byte();
                lo = A - op1;
                COND_SET_FLAG_C(lo);
                lo &= BYTEMASK;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                condevalVs(A, op1);
                break;
            case 0x82:                  /* SBC A imm */
                lo = (fetch_byte() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0x84:                  /* AND A imm */
                A = (A & fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x85:                  /* BIT A imm */
                lo = (A & fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x86:                  /* LDA A imm */
                A = fetch_byte();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x88:                  /* EOR A imm */
                A = (A ^ fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x89:                  /* ADC A imm */
                lo = (fetch_byte() + get_flag(CF)) & BYTEMASK;
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0x8A:                  /* ORA A imm */
                A = (A | fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x8B:                  /* ADD A imm */
                lo = fetch_byte();
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0x8C:                  /* CPX imm */
                op1 = IX - fetch_word();
                COND_SET_FLAG_Z(op1);
                COND_SET_FLAG_N(op1 >> 8);
                COND_SET_FLAG_V(op1 & 0x10000);
                break;
            case 0x8D:                  /* BSR rel */
                lo = fetch_byte();
                if (lo & 0x80)
                    lo |= 0xFF00;
                lo &= ADDRMASK;
                push_word(PC);
                PC = PC + lo;
                PC &= ADDRMASK;
                break;
            case 0x8E:                  /* LDS imm */
                SP = fetch_word();
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0x90:                  /* SUB A dir */
                lo = get_dir_val();
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0x91:                  /* CMP A dir */
                op1 = get_dir_val();
                lo = A - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(A, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0x92:                  /* SBC A dir */
                lo = (get_dir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0x94:                  /* AND A dir */
                A = (A & get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x95:                  /* BIT A dir */
                lo = (A & get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0x96:                  /* LDA A dir */
                A = get_dir_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x97:                  /* STA A dir */
                CPU_BD_put_mbyte(fetch_byte(), A);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x98:                  /* EOR A dir */
                A = (A ^ get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x99:                  /* ADC A dir */
                lo = (get_dir_val() + get_flag(CF)) & BYTEMASK;
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0x9A:                  /* ORA A dir */
                A = (A | get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0x9B:                  /* ADD A dir */
                lo = get_dir_val();
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0x9C:                  /* CPX dir */
                op1 = IX - CPU_BD_get_mword(fetch_byte());
                COND_SET_FLAG_Z(op1);
                COND_SET_FLAG_N(op1 >> 8);
                COND_SET_FLAG_V(op1 & 0x10000);
                break;
            case 0x9E:                  /* LDS dir */
                SP = CPU_BD_get_mword(fetch_byte());
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0x9F:                  /* STS dir */
                CPU_BD_put_mword(fetch_byte(), SP);
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0xA0:                  /* SUB A ind */
                lo = get_indir_val();
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0xA1:                  /* CMP A ind */
                op1 = get_indir_val();
                lo = A - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(A, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0xA2:                  /* SBC A ind */
                lo = (get_indir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0xA4:                  /* AND A ind */
                A = (A & get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xA5:                  /* BIT A ind */
                lo = (A & get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xA6:                  /* LDA A ind */
                A = get_indir_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xA7:                  /* STA A ind */
                CPU_BD_put_mbyte((fetch_byte() + IX) & ADDRMASK, A);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xA8:                  /* EOR A ind */
                A = (A ^ get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xA9:                  /* ADC A ind */
                lo = (get_indir_val() + get_flag(CF)) & BYTEMASK;
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0xAA:                  /* ORA A ind */
                A = (A | get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xAB:                  /* ADD A ind */
                lo = get_indir_val();
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0xAC:                  /* CPX ind */
                op1 = (IX - (fetch_byte() + IX) & ADDRMASK) & ADDRMASK;
                COND_SET_FLAG_Z(op1);
                COND_SET_FLAG_N(op1 >> 8);
                COND_SET_FLAG_V(op1 & 0x10000);
                break;
            case 0xAD:                  /* JSR ind */
                EA = (fetch_byte() + IX) & ADDRMASK;
                push_word(PC);
                PC = EA;
                break;
            case 0xAE:                  /* LDS ind */
                SP = CPU_BD_get_mword((fetch_byte() + IX) & ADDRMASK);
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0xAF:                  /* STS ind */
                CPU_BD_put_mword((fetch_byte() + IX) & ADDRMASK, SP);
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0xB0:                  /* SUB A ext */
                lo = get_ext_val();
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0xB1:                  /* CMP A ext */
                op1 = get_ext_val();
                lo = A - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(A, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0xB2:                  /* SBC A ext */
                lo = (get_ext_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = A;
                A = A - lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVs(op1, lo);
                break;
            case 0xB4:                  /* AND A ext */
                A = (A & get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xB5:                  /* BIT A ext */
                lo = (A & get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xB6:                  /* LDA A ext */
                A = get_ext_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xB7:                  /* STA A ext */
                CPU_BD_put_mbyte(fetch_word(), A);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xB8:                  /* EOR A ext */
                A = (A ^ get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xB9:                  /* ADC A ext */
                lo = (get_ext_val() + get_flag(CF)) & BYTEMASK;
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0xBA:                  /* ORA A ext */
                A = (A | get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                break;
            case 0xBB:                  /* ADD A ext */
                lo = get_ext_val();
                op1 = A;
                A = A + lo;
                COND_SET_FLAG_C(A);
                A &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(A);
                COND_SET_FLAG_Z(A);
                condevalVa(op1, lo);
                break;
            case 0xBC:                  /* CPX ext */
                op1 = (IX - CPU_BD_get_mword(fetch_word()));
                COND_SET_FLAG_Z(op1);
                COND_SET_FLAG_N(op1 >> 8);
                COND_SET_FLAG_V(op1 & 0x10000);
                break;
            case 0xBD:                  /* JSR ext */
                EA = fetch_word();
                push_word(PC);
                PC = EA;
                break;
            case 0xBE:                  /* LDS ext */
                SP = CPU_BD_get_mword(fetch_word());
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0xBF:                  /* STS ext */
                CPU_BD_put_mword(fetch_word(), SP);
                COND_SET_FLAG_N(SP >> 8);
                COND_SET_FLAG_Z(SP);
                CLR_FLAG(VF);
                break;
            case 0xC0:                  /* SUB B imm */
                lo = fetch_byte();
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xC1:                  /* CMP B imm */
                op1 = fetch_byte();
                lo = B - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(B, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0xC2:                  /* SBC B imm */
                lo = (fetch_byte() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xC4:                  /* AND B imm */
                B = (B & fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xC5:                  /* BIT B imm */
                lo = (B & fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xC6:                  /* LDA B imm */
                B = fetch_byte();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xC8:                  /* EOR B imm */
                B = (B ^ fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xC9:                  /* ADC B imm */
                lo = (fetch_byte() + get_flag(CF)) & BYTEMASK;
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xCA:                  /* ORA B imm */
                B = (B | fetch_byte()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xCB:                  /* ADD B imm */
                lo = fetch_byte();
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xCE:                  /* LDX imm */
                IX = fetch_word();
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xD0:                  /* SUB B dir */
                lo = get_dir_val();
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xD1:                  /* CMP B dir */
                lo = get_dir_val();
                op1 = B - lo;
                COND_SET_FLAG_C(op1);
                op1 &= BYTEMASK;
                COND_SET_FLAG_N(op1);
                COND_SET_FLAG_Z(op1);
                condevalVs(B, lo);
                break;
            case 0xD2:                  /* SBC B dir */
                lo = (get_dir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xD4:                  /* AND B dir */
                B = (B & get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xD5:                  /* BIT B dir */
                lo = (B & get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xD6:                  /* LDA B dir */
                B = get_dir_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xD7:                  /* STA B dir */
                CPU_BD_put_mbyte(fetch_byte(), B);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xD8:                  /* EOR B dir */
                B = (B ^ get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xD9:                  /* ADC B dir */
                lo = (get_dir_val() + get_flag(CF)) & BYTEMASK;
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xDA:                  /* ORA B dir */
                B = (B | get_dir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xDB:                  /* ADD B dir */
                lo = get_dir_val();
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xDE:                  /* LDX dir */
                IX = CPU_BD_get_mword(fetch_byte());
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xDF:                  /* STX dir */
                CPU_BD_put_mword(fetch_byte(), IX);
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xE0:                  /* SUB B ind */
                lo = get_indir_val();
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xE1:                  /* CMP B ind */
                op1 = get_indir_val();
                lo = B - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(B, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0xE2:                  /* SBC B ind */
                lo = (get_indir_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xE4:                  /* AND B ind */
                B = (B & get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xE5:                  /* BIT B ind */
                lo = (B & get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xE6:                  /* LDA B ind */
                B = get_indir_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xE7:                  /* STA B ind */
                CPU_BD_put_mbyte((fetch_byte() + IX) & ADDRMASK, B);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xE8:                  /* EOR B ind */
                B = (B ^ get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xE9:                  /* ADC B ind */
                lo = (get_indir_val() + get_flag(CF)) & BYTEMASK;
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xEA:                  /* ORA B ind */
                B = (B | get_indir_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xEB:                  /* ADD B ind */
                lo = get_indir_val();
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xEE:                  /* LDX ind */
                IX = CPU_BD_get_mword((fetch_byte() + IX) & ADDRMASK);
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xEF:                  /* STX ind */
                CPU_BD_put_mword((fetch_byte() + IX) & ADDRMASK, IX);
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xF0:                  /* SUB B ext */
                lo = get_ext_val();
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xF1:                  /* CMP B ext */
                op1 = get_ext_val();
                lo = B - op1;
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_C(lo);
                condevalVs(B, op1);
                lo &= BYTEMASK;
                COND_SET_FLAG_Z(lo);
                break;
            case 0xF2:                  /* SBC B ext */
                lo = (get_ext_val() + get_flag(CF)) & BYTEMASK; //RSV - fixed ordering problem
                op1 = B;
                B = B - lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVs(op1, lo);
                break;
            case 0xF4:                  /* AND B ext */
                B = (B & get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xF5:                  /* BIT B ext */
                lo = (B & get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(lo);
                COND_SET_FLAG_Z(lo);
                break;
            case 0xF6:                  /* LDA B ext */
                B = get_ext_val();
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xF7:                  /* STA B ext */
                CPU_BD_put_mbyte(fetch_word(), B);
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xF8:                  /* EOR B ext */
                B = (B ^ get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xF9:                  /* ADC B ext */
                lo = (get_ext_val() + get_flag(CF)) & BYTEMASK;
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xFA:                  /* ORA B ext */
                B = (B | get_ext_val()) & BYTEMASK;
                CLR_FLAG(VF);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                break;
            case 0xFB:                  /* ADD B ext */
                lo = get_ext_val();
                op1 = B;
                B = B + lo;
                COND_SET_FLAG_C(B);
                B &= BYTEMASK;
                condevalHa(op1, lo);
                COND_SET_FLAG_N(B);
                COND_SET_FLAG_Z(B);
                condevalVa(op1, lo);
                break;
            case 0xFE:                  /* LDX ext */
                IX = CPU_BD_get_mword(fetch_word());
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;
            case 0xFF:                  /* STX ext */
                CPU_BD_put_mword(fetch_word(), IX);
                COND_SET_FLAG_N(IX >> 8);
                COND_SET_FLAG_Z(IX);
                CLR_FLAG(VF);
                break;

            default: {                  /* Unassigned */
                if (m6800_unit.flags & UNIT_OPSTOP) {
                    reason = STOP_OPCODE;
                    PC--;
                }
                break;
            }
        }
    }
    /* Simulation halted - lets dump all the registers! */
    saved_PC = PC;
    return reason;
}

/* dump the working registers */

void dump_regs(void)
{
    printf("\r\nPC=%04X SP=%04X IX=%04X ", PC, SP, IX);
    printf("A=%02X B=%02X CC=%02X", A, B, CC);
}

/* fetch an instruction or byte */
int32 fetch_byte(void)
{
    uint8 val;

    val = CPU_BD_get_mbyte(PC) & BYTEMASK;   /* fetch byte */
    //rsv fix on opernd order but moved the "& BYTEMASK" here
    PC = (PC + 1) & ADDRMASK;           /* increment PC */
    return val;
}

/* fetch a word */
int32 fetch_word(void)
{
    uint16 val;

    val = CPU_BD_get_mbyte(PC) << 8;     /* fetch high byte */
    val |= CPU_BD_get_mbyte(PC + 1) & BYTEMASK; /* fetch low byte */
    PC = (PC + 2) & ADDRMASK;           /* increment PC */
    return val;
}

/* push a byte to the stack */
void push_byte(uint8 val)
{
    CPU_BD_put_mbyte(SP, val & BYTEMASK);
    //rsv fix on opernd order but moved the "& BYTEMASK" here
    SP = (SP - 1) & ADDRMASK;
}

/* push a word to the stack */
void push_word(uint16 val)
{
    push_byte(val & BYTEMASK);
    push_byte(val >> 8);
}

/* pop a byte from the stack */
uint8 pop_byte(void)
{
    register uint8 res;

    SP = (SP + 1) & ADDRMASK;
    res = CPU_BD_get_mbyte(SP);
    return res;
}

/* pop a word from the stack */
uint16 pop_word(void)
{
    register uint16 res;

    res = pop_byte() << 8;
    res |= pop_byte();
    return res;
}

/*      this routine does the jump to relative offset if the condition is
        met.  Otherwise, execution continues at the current PC. */

void go_rel(int32 cond)
{
    int32 temp;

    temp = fetch_byte();
    if (temp & 0x80)
        temp |= 0xFF00;
    temp &= ADDRMASK;
    if (cond)
        PC += temp;
    PC &= ADDRMASK;
}

/* get the word vector at vec */
int32 get_vec_val(int32 vec)
{
    return (CPU_BD_get_mword(vec) & ADDRMASK);
}

/* returns the value at the immediate address pointed to by PC */

int32 get_imm_val(void)
{
    return fetch_byte();
}

/* returns the value at the direct address pointed to by PC */

int32 get_dir_val(void)
{
    return CPU_BD_get_mbyte(fetch_byte());
}

/* returns the value at the indirect address pointed to by PC */

int32 get_indir_val(void)
{
    return CPU_BD_get_mbyte((fetch_byte() + IX) & ADDRMASK);
}

/* returns the value at the extended address pointed to by PC */

int32 get_ext_val(void)
{
    return CPU_BD_get_mbyte(fetch_word());
}

/* return 1 for flag set or 0 for flag clear */

int32 get_flag(int32 flg)
{
    if (CC & flg)
        return 1;
    else
        return 0;
}

/* test and set V for addition */

void condevalVa(int32 op1, int32 op2)
{
    if (((op1 & 0x80) == (op2 & 0x80)) &&
        (((op1 + op2) & 0x80) != (op1 & 0x80))) 
        SET_FLAG(VF);
    else 
        CLR_FLAG(VF);
}

/* test and set V for subtraction */

void condevalVs(int32 op1, int32 op2)
{
    if (((op1 & 0x80) != (op2 & 0x80)) &&
        (((op1 - op2) & 0x80) == (op2 & 0x80)))
        SET_FLAG(VF);
    else 
        CLR_FLAG(VF);

}

/* test and set H for addition */
void condevalHa(int32 op1, int32 op2)
{
    if (((op1 & 0x0f) + (op2 & 0x0f)) & 0x10) 
        SET_FLAG(HF);
    else 
        CLR_FLAG(HF);
}

/* calls from the simulator */

/* Reset routine */

t_stat m6800_reset(DEVICE *dptr)
{
    CC = CC_ALWAYS_ON | IF;
    NMI = 0, IRQ = 0;
    sim_brk_types = sim_brk_dflt = SWMASK ('E');
    saved_PC = CPU_BD_get_mword(0xFFFE);
    if ((saved_PC == 0xFFFF) && ((sim_switches & SWMASK ('P')) == 0)) {
        printf("No EPROM image found\n");
        reason = STOP_MEMORY;           /* stop simulation - no ROM*/
    }
    return SCPE_OK;
}

/* This is the dumper/loader. This command uses the -h to signify a
    hex dump/load vice a binary one.  If no address is given to load, it
    takes the address from the hex record or the current PC for binary.
*/

#define HLEN    16

int32 sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
{
    int32 i, addr = 0, addr0 = 0, cnt = 0, cnt0 = 0, start = 0x10000;
    int32 addr1 = 0, end = 0, byte, chk, rtype, flag0 = 1;
    char buf[128], data[128], *p;

    cnt = sscanf(cptr, " %04X %04X", &start, &end);
    addr=start;
    if (flag == 0) {                    //load
        if (sim_switches & SWMASK ('H')) { //hex
            if (cnt > 1)                //2 arguments - error
                return SCPE_ARG;
            cnt = 0;
            while (fgets(buf, sizeof(buf)-1, fileref)) {
                sscanf(buf, " S%1d%02x%04x%s", &rtype, &cnt0, &addr, data);
                if (flag0) {
                    addr1 = addr;
                    flag0 = 0;
                }
                if (rtype == 1) {
                    chk = 0;
                    chk += cnt0;
                    cnt0 -= 3;
                    chk += addr & BYTEMASK;
                    chk += addr >> 8;
                    p = (char *) data;
                    for (i=0; i<cnt0; i++) {
                        sscanf (p, "%2x", &byte);
                        p += 2;
                        CPU_BD_put_mbyte(addr + i, byte);
                        chk += byte; chk &= BYTEMASK;
                        cnt++;
                    }
                    sscanf (p, "%2x", &byte);
                    chk += byte; chk &= BYTEMASK;
                    if (chk == 0xff)
                        printf("+");
                    else
                        printf("-");
                } else if (rtype == 9) {
                    printf("\n");
                } else 
                    return SCPE_ARG;
            }
        } else {                        //binary
            if (cnt > 1)                //2 arguments - error
                return SCPE_ARG;
            cnt = 0;
            addr1 = addr;
            while ((i = getc (fileref)) != EOF) {
                CPU_BD_put_mbyte(addr, i);
                addr++; cnt++;
            }
        }
        printf ("%d Bytes loaded at %04X\n", cnt, addr1);
        return (SCPE_OK);
    } else {                            //dump
        if (cnt != 2)                   //must be 2 arguments
            return SCPE_ARG;
        cnt = 0;
        addr0 = addr;
        if (sim_switches & SWMASK ('H')) { //hex
            while((addr + HLEN) <= end) { //full records
                fprintf(fileref,"S1%02X%04X", HLEN + 3, addr);
                chk = 0;
                chk += HLEN + 3;
                chk += addr & BYTEMASK;
                chk += addr >> 8;
                for (i=0; i<HLEN; i++) {
                    byte = CPU_BD_get_mbyte(addr + i);
                    fprintf(fileref, "%02X", byte);
                    chk += byte; chk &= BYTEMASK;
                    cnt++;
                }
                chk = (~chk) & BYTEMASK; 
                fprintf(fileref,"%02X\n", chk);
                addr += HLEN;
            }
            if(addr < end) { //last record
                fprintf(fileref, "S1%02X%04X", end - addr + 3, addr);
                chk = 0;
                chk += end - addr;
                chk += addr & BYTEMASK;
                chk += addr >> 8;
                for (i=0; i<=(end - addr); i++) {
                    byte = CPU_BD_get_mbyte(addr + i);
                    fprintf(fileref, "%02X", byte);
                    chk += byte; chk &= BYTEMASK;
                    cnt++;
                }
                chk = (~chk) & BYTEMASK; 
                fprintf(fileref, "%02X\n", chk);
                addr = end;
            }
            fprintf(fileref,"S9\n"); //EOF record
        } else {                        //binary
            while (addr <= end) {
                i = CPU_BD_get_mbyte(addr);
                putc(i, fileref);
                addr++; cnt++;
            }
        }
        printf ("%d Bytes dumped from %04X\n", cnt, addr0);
    }
    return SCPE_OK;
}

/* Symbolic output

    Inputs:
        *of     =   output stream
        addr    =   current PC
        *val    =   pointer to values
        *uptr   =   pointer to unit
        sw      =   switches
    Outputs:
        status  =   error code
        for M6800
*/
t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
    int i, inst, inst1;

    if (sw & SWMASK ('D')) {            // dump memory
        for (i=0; i<16; i++)
            fprintf(of, "%02X ", val[i]);
        fprintf(of, "  ");
        for (i=0; i<16; i++)
            if (isprint(val[i]))
                fprintf(of, "%c", val[i]);
            else
                fprintf(of, ".");
        return -15;
    } else if (sw & SWMASK ('M')) {     // dump instruction mnemonic
        inst = val[0];
        if (!oplen[inst]) {             // invalid opcode
            fprintf(of, "%02X", inst);
            return 0;
        }
        inst1 = inst & 0xF0;
        fprintf (of, "%s", opcode[inst]); // mnemonic
        if (strlen(opcode[inst]) == 3)
            fprintf(of, " ");
        if (inst1 == 0x20 || inst == 0x8D) { // rel operand
            inst1 = val[1];
            if (val[1] & 0x80)
                inst1 |= 0xFF00;
            fprintf(of, " $%04X", (addr + inst1 + 2) & ADDRMASK);
        } else if (inst1 == 0x80 || inst1 == 0xC0) { // imm operand
            if ((inst & 0x0F) < 0x0C)
                fprintf(of, " #$%02X", val[1]);
            else
                fprintf(of, " #$%02X%02X", val[1], val[2]);
        } else if (inst1 == 0x60 || inst1 == 0xA0 || inst1 == 0xE0) // ind operand
            fprintf(of, " %d,X", val[1]);
        else if (inst1 == 0x70 || inst1 == 0xb0 || inst1 == 0xF0) // ext operand
            fprintf(of, " $%02X%02X", val[1], val[2]);
        return (-(oplen[inst] - 1));
    } else
        return SCPE_ARG;
}

/* Symbolic input

    Inputs:
        *cptr   =   pointer to input string
        addr    =   current PC
        *uptr   =   pointer to unit
        *val    =   pointer to output values
        sw      =   switches
    Outputs:
        status  =   error status
*/

t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
    return (1);
}

/* Set history */

t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
    int i, lnt;
    t_stat r;

    if (cptr == NULL) {
        for (i = 0; i < hst_lnt; i++)
            hst[i].pc = 0;
        hst_p = 0;
        return SCPE_OK;
        }
    lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
    if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
        return SCPE_ARG;
    hst_p = 0;
    if (hst_lnt) {
        free (hst);
        hst_lnt = 0;
        hst = NULL;
        }
    if (lnt) {
        hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
        if (hst == NULL)
            return SCPE_MEM;
        hst_lnt = lnt;
        }
    return SCPE_OK;
}

/* Show history */

t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
    int k, di, lnt, ir;
    const char *cptr = (const char *) desc;
    t_stat r;
    InstHistory *h;

    if (hst_lnt == 0)                       /* enabled? */
        return SCPE_NOFNC;
    if (cptr) {
        lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
        if ((r != SCPE_OK) || (lnt == 0))
            return SCPE_ARG;
        }
    else lnt = hst_lnt;
    di = hst_p - lnt;                       /* work forward */
    if (di < 0)
        di = di + hst_lnt;
    fprintf (st, "PC   SP   CC A  B  IX   Instruction\n\n");
    for (k = 0; k < lnt; k++) {             /* print specified */
        h = &hst[(di++) % hst_lnt];         /* entry pointer */
        ir = h->inst[0];
        fprintf (st, "%04X %04X %02X ", h->pc , h->sp, h->cc);
        fprintf (st, "%02X %02X %04X ", h->a, h->b, h->ix);
        if ((fprint_sym (st, h->pc, h->inst, &m6800_unit, SWMASK ('M'))) > 0)
            fprintf (st, "(undefined) %02X", h->inst[0]);
        fputc ('\n', st);                               /* end line */
        }
    return SCPE_OK;
}

/* Memory examine */

t_stat m6800_ex(t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
    if (addr >= MAXMEMSIZE) 
        return SCPE_NXM;
    if (vptr != NULL) 
        *vptr = CPU_BD_get_mbyte(addr);
    return SCPE_OK;
}

/* Memory deposit */

t_stat m6800_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
    if (addr >= MAXMEMSIZE) 
        return SCPE_NXM;
    CPU_BD_put_mbyte(addr, val);
    return SCPE_OK;
}

/* end of m6800.c */
