| /* swtp_6800_cpu.c: SWTP 6800 Motorola 6800 CPU simulator | |
| Copyright (c) 2005, 2007, 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. | |
| Based on work by Charles E Owen (c) 1997 and Peter Schorn (c) 2002-2005 | |
| cpu 6800 CPU | |
| The register state for the 6800 CPU is: | |
| A<0:7> Accumulator A | |
| B<0:7> Accumulator B | |
| IX<0:15> Index Register | |
| H half-carry flag | |
| I interrupt flag | |
| N negative flag | |
| Z zero flag | |
| V overflow flag | |
| C carry flag | |
| PC<0:15> program counter | |
| SP<0:15> Stack Pointer | |
| The 6800 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 6800. | |
| It is called from the simulator control program 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. In the simulator, the | |
| largest possible memory is instantiated and initialized to zero. | |
| Thus, only writes need be checked against actual memory size. | |
| 4. Adding I/O devices. These modules must be modified: | |
| swtp_6800_cpu.c add I/O service routines to dev_table | |
| swtp_sys.c add pointer to data structures in sim_devices | |
| */ | |
| #include <stdio.h> | |
| #include "swtp_defs.h" | |
| //#include <windows.h> | |
| //#include <mmsystem.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) | |
| #define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */ | |
| #define UNIT_MSIZE (1 << UNIT_V_MSIZE) | |
| #define UNIT_V_MA000 (UNIT_V_UF+2) /* 128B or 8kB at 0xA000 */ | |
| #define UNIT_MA000 (1 << UNIT_V_MA000) | |
| uint8 M[MAXMEMSIZE]; /* Memory */ | |
| int32 A = 0; /* Accumulator A */ | |
| int32 B = 0; /* Accumulator B */ | |
| int32 IX = 0; /* Index register */ | |
| int32 SP = 0; /* Stack pointer */ | |
| int32 H = 0; /* Half-carry flag */ | |
| int32 I = 1; /* Interrupt flag */ | |
| int32 N = 0; /* Negative flag */ | |
| int32 Z = 0; /* Zero flag */ | |
| int32 V = 0; /* Overflow flag */ | |
| int32 C = 0; /* Carry flag */ | |
| int32 saved_PC = 0; /* Program counter */ | |
| int32 INTE = 0; /* Interrupt Enable */ | |
| int32 int_req = 0; /* Interrupt request */ | |
| int32 mem_fault = 0; /* memory fault flag */ | |
| extern int32 sim_int_char; | |
| extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ | |
| /* function prototypes */ | |
| t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); | |
| t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); | |
| t_stat cpu_reset (DEVICE *dptr); | |
| t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); | |
| void dump_regs(); | |
| void go_rel(int32 cond); | |
| int32 get_rel_addr(); | |
| int32 get_dir_val(); | |
| int32 get_dir_addr(); | |
| int32 get_indir_val(); | |
| int32 get_indir_addr(); | |
| int32 get_ext_val(); | |
| int32 get_ext_addr(); | |
| int32 get_psw(); | |
| void set_psw(int32 psw); | |
| void condevalH(int32 res); | |
| void condevalN(int32 res); | |
| void condevalZ(int32 res); | |
| void condevalC(int32 res); | |
| void condevalVa(int32 op1, int32 op2); | |
| void condevalVs(int32 op1, int32 op2); | |
| void mem_put_byte(int32 addr, int32 val); | |
| void mem_put_word(int32 addr, int32 val); | |
| int32 mem_get_byte(int32 addr); | |
| int32 mem_get_word(int32 addr); | |
| int32 nulldev(int32 io, int32 data); | |
| /* external routines */ | |
| extern int32 sio0s(int32 io, int32 data); | |
| extern int32 sio0d(int32 io, int32 data); | |
| extern int32 sio1s(int32 io, int32 data); | |
| extern int32 sio1d(int32 io, int32 data); | |
| extern int32 fdcdrv(int32 io, int32 data); | |
| extern int32 fdccmd(int32 io, int32 data); | |
| extern int32 fdctrk(int32 io, int32 data); | |
| extern int32 fdcsec(int32 io, int32 data); | |
| extern int32 fdcdata(int32 io, int32 data); | |
| extern int32 fprint_sym (FILE *of, int32 addr, uint32 *val, | |
| UNIT *uptr, int32 sw); | |
| /* This is the I/O configuration table. There are 32 possible | |
| device addresses, if a device is plugged into a port it's routine | |
| address is here, 'nulldev' means no device is available | |
| */ | |
| struct idev { | |
| int32 (*routine)(int32, int32); | |
| }; | |
| struct idev dev_table[32] = { | |
| {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 0 8000-8003*/ | |
| {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /*Port 1 8004-8007*/ | |
| /* sio1x routines just return the last value read on the matching | |
| sio0x routine. SWTBUG tests for the MP-C with most port reads! */ | |
| {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 2 8008-800B*/ | |
| {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 3 800C-800F*/ | |
| {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 4 8010-8013*/ | |
| {&fdcdrv}, {&nulldev}, {&nulldev}, {&nulldev}, /*Port 5 8014-8017*/ | |
| {&fdccmd}, {&fdctrk}, {&fdcsec}, {&fdcdata}, /*Port 6 8018-801B*/ | |
| {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} /*Port 7 801C-801F*/ | |
| }; | |
| /* SWTP 6800 SWTBUG BOOT EPROM, fits at 0E000-0E3FFH and replicated | |
| at 0FC000-0FFFF for the interrupt vectors */ | |
| #define BOOTLEN 1024 | |
| int32 bootrom[BOOTLEN] = { | |
| 0xFE,0xA0,0x00,0x6E,0x00,0x8D,0x40,0x6E, | |
| 0x00,0x10,0x16,0x04,0xBD,0xE3,0x34,0x8D, | |
| 0x67,0x81,0x53,0x26,0xFA,0x8D,0x61,0x81, | |
| 0x39,0x27,0x29,0x81,0x31,0x26,0xF0,0x7F, | |
| 0xA0,0x0F,0x8D,0x31,0x80,0x02,0xB7,0xA0, | |
| 0x47,0x8D,0x1C,0x8D,0x28,0x7A,0xA0,0x47, | |
| 0x27,0x09,0xA7,0x00,0xA1,0x00,0x26,0x08, | |
| 0x08,0x20,0xF0,0x7C,0xA0,0x0F,0x27,0xCF, | |
| 0x86,0x3F,0x8D,0x31,0x7E,0xE2,0xD4,0x8D, | |
| 0x0C,0xB7,0xA0,0x0D,0x8D,0x07,0xB7,0xA0, | |
| 0x0E,0xFE,0xA0,0x0D,0x39,0x8D,0x53,0x48, | |
| 0x48,0x48,0x48,0x16,0x8D,0x4C,0x1B,0x16, | |
| 0xFB,0xA0,0x0F,0xF7,0xA0,0x0F,0x39,0x44, | |
| 0x44,0x44,0x44,0x84,0x0F,0x8B,0x30,0x81, | |
| 0x39,0x23,0x02,0x8B,0x07,0x7E,0xE1,0xD1, | |
| 0x7E,0xE1,0xAC,0x8D,0xF8,0x08,0xA6,0x00, | |
| 0x81,0x04,0x26,0xF7,0x39,0x7E,0xE1,0x4A, | |
| 0x8D,0xBD,0xCE,0xE1,0x9D,0x8D,0xEF,0xCE, | |
| 0xA0,0x0D,0x8D,0x34,0xFE,0xA0,0x0D,0x8D, | |
| 0x31,0x8D,0x31,0x8D,0xDB,0x81,0x20,0x27, | |
| 0xFA,0x81,0x0D,0x27,0xE0,0x81,0x5E,0x20, | |
| 0x2C,0x01,0x8D,0xCC,0x80,0x30,0x2B,0x4C, | |
| 0x81,0x09,0x2F,0x0A,0x81,0x11,0x2B,0x44, | |
| 0x81,0x16,0x2E,0x40,0x80,0x07,0x39,0xA6, | |
| 0x00,0x8D,0xA4,0xA6,0x00,0x08,0x20,0xA3, | |
| 0x8D,0xF5,0x8D,0xF3,0x86,0x20,0x20,0xA5, | |
| 0x8E,0xA0,0x42,0x20,0x2C,0x26,0x07,0x09, | |
| 0x09,0xFF,0xA0,0x0D,0x20,0xAC,0xFF,0xA0, | |
| 0x0D,0x20,0x02,0x20,0x6D,0x81,0x30,0x25, | |
| 0xA1,0x81,0x46,0x22,0x9D,0x8D,0xBD,0xBD, | |
| 0xE0,0x57,0x09,0xA7,0x00,0xA1,0x00,0x27, | |
| 0x91,0x7E,0xE0,0x40,0xBE,0xA0,0x08,0x20, | |
| 0x49,0xBF,0xA0,0x08,0x86,0xFF,0xBD,0xE3, | |
| 0x08,0xCE,0x80,0x04,0xBD,0xE2,0x84,0xA6, | |
| 0x00,0xA1,0x02,0x20,0x02,0x20,0x19,0x26, | |
| 0x39,0x86,0x03,0xA7,0x00,0x86,0x11,0xA7, | |
| 0x00,0x20,0x2F,0x01,0xBF,0xA0,0x08,0x30, | |
| 0x6D,0x06,0x26,0x02,0x6A,0x05,0x6A,0x06, | |
| 0xCE,0xE1,0x9D,0xBD,0xE0,0x7E,0xFE,0xA0, | |
| 0x08,0x08,0x8D,0x8E,0x8D,0x8C,0x8D,0x8A, | |
| 0x8D,0x86,0x8D,0x84,0xCE,0xA0,0x08,0xBD, | |
| 0xE0,0xC8,0xFE,0xA0,0x12,0x8C,0xE1,0x23, | |
| 0x27,0x19,0x8E,0xA0,0x42,0xCE,0x80,0x04, | |
| 0xFF,0xA0,0x0A,0x7F,0xA0,0x0C,0x8D,0x73, | |
| 0x27,0x03,0xBD,0xE2,0x7D,0xBD,0xE3,0x53, | |
| 0xBD,0xE3,0x47,0xCE,0xE1,0x9C,0xBD,0xE0, | |
| 0x7E,0x8D,0x39,0xCE,0xE3,0xD1,0xA1,0x00, | |
| 0x26,0x07,0xBD,0xE0,0xCC,0xEE,0x01,0x6E, | |
| 0x00,0x08,0x08,0x08,0x8C,0xE3,0xF8,0x26, | |
| 0xED,0x20,0xBF,0xFE,0xA0,0x12,0x6E,0x00, | |
| 0x53,0x39,0x04,0x0D,0x0A,0x15,0x00,0x00, | |
| 0x00,0x53,0x31,0x04,0x13,0x0D,0x0A,0x15, | |
| 0x00,0x00,0x00,0x24,0x04,0x20,0x4C,0xFE, | |
| 0xA0,0x06,0x6E,0x00,0x20,0x40,0xBD,0xE0, | |
| 0x47,0xFF,0xA0,0x04,0xBD,0xE0,0x47,0xBD, | |
| 0xE0,0x55,0x16,0xA6,0x00,0xFF,0xA0,0x0D, | |
| 0x11,0x27,0x02,0x20,0x21,0xCE,0xE1,0x9D, | |
| 0xBD,0xE0,0x7E,0xCE,0xA0,0x0D,0x20,0x10, | |
| 0x3B,0x20,0x3A,0xFF,0xA0,0x10,0xFE,0xA0, | |
| 0x0A,0x37,0xE6,0x01,0xE1,0x03,0x33,0x39, | |
| 0xBD,0xE0,0xC8,0xFE,0xA0,0x0D,0xBC,0xA0, | |
| 0x04,0x27,0x9E,0x08,0x20,0xCD,0x8D,0x06, | |
| 0x84,0x7F,0x39,0x31,0x31,0x31,0x37,0x8D, | |
| 0xDA,0x26,0x28,0x86,0x15,0xA7,0x00,0xA6, | |
| 0x00,0x47,0x24,0xFB,0xA6,0x01,0xF6,0xA0, | |
| 0x0C,0x27,0x07,0x20,0x11,0x37,0x8D,0xC3, | |
| 0x26,0x2E,0xC6,0x11,0xE7,0x00,0xE6,0x00, | |
| 0x57,0x57,0x24,0xFA,0xA7,0x01,0x33,0xFE, | |
| 0xA0,0x10,0x39,0xA6,0x00,0x2B,0xFC,0x8D, | |
| 0x3A,0xC6,0x04,0xE7,0x02,0x58,0x8D,0x2A, | |
| 0x0D,0x69,0x00,0x46,0x5A,0x26,0xF7,0x8D, | |
| 0x21,0xF6,0xA0,0x0C,0x27,0x13,0x20,0xDE, | |
| 0x8D,0x23,0xC6,0x0A,0x6A,0x00,0x8D,0x16, | |
| 0x8D,0x10,0xA7,0x00,0x0D,0x46,0x5A,0x26, | |
| 0xF7,0xE6,0x02,0x58,0x2A,0xC8,0x8D,0x02, | |
| 0x20,0xC4,0x6D,0x02,0x2A,0xFC,0x6C,0x02, | |
| 0x6A,0x02,0x39,0x6F,0x02,0x8D,0xF7,0x20, | |
| 0xF1,0x8D,0x83,0x16,0x7F,0xA0,0x0B,0xFE, | |
| 0xA0,0x0A,0x8D,0x10,0x8D,0x07,0xCE,0xE3, | |
| 0xEF,0x17,0x7E,0xE1,0x76,0x86,0x34,0xA7, | |
| 0x03,0xA7,0x02,0x39,0x6C,0x00,0x86,0x07, | |
| 0xA7,0x01,0x6C,0x00,0xA7,0x02,0x39,0x7F, | |
| 0x80,0x14,0x8D,0x2E,0xC6,0x0B,0x8D,0x25, | |
| 0xE6,0x04,0xC5,0x01,0x26,0xFA,0x6F,0x06, | |
| 0x8D,0x1D,0xC6,0x9C,0x8D,0x17,0xCE,0x24, | |
| 0x00,0xC5,0x02,0x27,0x06,0xB6,0x80,0x1B, | |
| 0xA7,0x00,0x08,0xF6,0x80,0x18,0xC5,0x01, | |
| 0x26,0xEF,0x7E,0x24,0x00,0xE7,0x04,0x8D, | |
| 0x00,0x39,0xCE,0xFF,0xFF,0x09,0x8C,0x80, | |
| 0x14,0x26,0xFA,0x39,0xCE,0xE0,0x09,0xBD, | |
| 0xE0,0x7E,0x8D,0xF1,0xBD,0xE3,0x47,0x20, | |
| 0x58,0xCE,0xE1,0x23,0xBC,0xA0,0x12,0x27, | |
| 0x1A,0x08,0x8D,0x32,0xBD,0xE0,0x47,0xFF, | |
| 0xA0,0x14,0xA6,0x00,0xB7,0xA0,0x16,0x86, | |
| 0x3F,0xA7,0x00,0xCE,0xE1,0x23,0x8D,0x1E, | |
| 0x7E,0xE1,0x6B,0xFE,0xA0,0x14,0xB6,0xA0, | |
| 0x16,0xA7,0x00,0xCE,0xE1,0x24,0x20,0xDA, | |
| 0xB7,0xA0,0x43,0xFE,0xA0,0x12,0x8C,0xE1, | |
| 0x23,0x27,0x06,0xCE,0xE1,0x24,0xFF,0xA0, | |
| 0x12,0x39,0x8D,0x5A,0x20,0x0F,0xCE,0xA0, | |
| 0x49,0xFF,0xA0,0x04,0x09,0x8D,0x52,0xCE, | |
| 0xE1,0x90,0xBD,0xE0,0x7E,0x8D,0x24,0x8D, | |
| 0x91,0x7E,0xE1,0x52,0x73,0xA0,0x0C,0x86, | |
| 0x11,0xC6,0x20,0x8D,0x1A,0xBD,0xE1,0xD9, | |
| 0x27,0x04,0x86,0x3C,0xA7,0x03,0x39,0x86, | |
| 0x13,0xC6,0x10,0x20,0x0A,0x86,0x12,0xC6, | |
| 0x04,0x20,0x04,0x86,0x14,0xC6,0x08,0xBD, | |
| 0xE0,0x75,0xBD,0xE1,0xD6,0x27,0x16,0x86, | |
| 0x02,0xCA,0x01,0x8D,0x0C,0x8D,0x08,0x86, | |
| 0x02,0xC6,0x01,0xE7,0x00,0x8D,0x02,0x86, | |
| 0x06,0xA7,0x01,0xE7,0x00,0x39,0xFE,0xA0, | |
| 0x02,0xFF,0xA0,0x44,0x8D,0xCF,0xB6,0xA0, | |
| 0x05,0xB0,0xA0,0x45,0xF6,0xA0,0x04,0xF2, | |
| 0xA0,0x44,0x26,0x04,0x81,0x10,0x25,0x02, | |
| 0x86,0x0F,0x8B,0x04,0xB7,0xA0,0x47,0x80, | |
| 0x03,0xB7,0xA0,0x46,0xCE,0xE1,0x93,0xBD, | |
| 0xE0,0x7E,0x5F,0xCE,0xA0,0x47,0x8D,0x24, | |
| 0xCE,0xA0,0x44,0x8D,0x1F,0x8D,0x1D,0xFE, | |
| 0xA0,0x44,0x8D,0x18,0x7A,0xA0,0x46,0x26, | |
| 0xF9,0xFF,0xA0,0x44,0x53,0x37,0x30,0x8D, | |
| 0x0B,0x33,0xFE,0xA0,0x44,0x09,0xBC,0xA0, | |
| 0x04,0x26,0xB3,0x39,0xEB,0x00,0x7E,0xE0, | |
| 0xBF,0x47,0xE1,0xD0,0x5A,0xC0,0x00,0x4D, | |
| 0xE0,0x88,0x46,0xE1,0xAE,0x52,0xE1,0x30, | |
| 0x4A,0xE0,0x05,0x43,0xE2,0xCC,0x44,0xE2, | |
| 0x8F,0x42,0xE2,0xD9,0x4F,0xE2,0x69,0x50, | |
| 0xE3,0x1A,0x4C,0xE0,0x0C,0x45,0xE3,0x1E, | |
| 0xE0,0x00,0xE1,0x8B,0xE1,0xA7,0xE0,0xD0 | |
| }; | |
| /* CPU data structures | |
| cpu_dev CPU device descriptor | |
| cpu_unit CPU unit descriptor | |
| cpu_reg CPU register list | |
| cpu_mod CPU modifiers list */ | |
| UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, | |
| 32768) }; | |
| REG cpu_reg[] = { | |
| { HRDATA (PC, saved_PC, 16) }, | |
| { HRDATA (A, A, 8) }, | |
| { HRDATA (B, B, 8) }, | |
| { HRDATA (IX, IX, 16) }, | |
| { HRDATA (SP, SP, 16) }, | |
| { FLDATA (H, H, 16) }, | |
| { FLDATA (I, I, 16) }, | |
| { FLDATA (N, N, 16) }, | |
| { FLDATA (Z, Z, 16) }, | |
| { FLDATA (V, V, 16) }, | |
| { FLDATA (C, C, 16) }, | |
| { FLDATA (INTE, INTE, 16) }, | |
| { ORDATA (WRU, sim_int_char, 8) }, | |
| { NULL } }; | |
| MTAB cpu_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 }, | |
| { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, | |
| { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, | |
| { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, | |
| { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, | |
| { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size }, | |
| { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, | |
| { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, | |
| { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, | |
| { UNIT_MA000, UNIT_MA000, "MA000", "MA000", NULL }, | |
| { UNIT_MA000, 0, "NOMA000", "NOMA000", NULL }, | |
| { 0 } }; | |
| DEVICE cpu_dev = { | |
| "CPU", &cpu_unit, cpu_reg, cpu_mod, | |
| 1, 16, 16, 1, 16, 8, | |
| &cpu_ex, &cpu_dep, &cpu_reset, | |
| NULL, NULL, NULL }; | |
| int32 PC; /* global for the helper routines */ | |
| int32 sim_instr (void) | |
| { | |
| extern int32 sim_interval; | |
| int32 IR, OP, DAR, reason, hi, lo, op1; | |
| // uint32 val1[3]; | |
| 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 (mem_fault) { /* memory fault? */ | |
| mem_fault = 0; /* reset fault flag */ | |
| reason = STOP_MEMORY; | |
| break; | |
| } | |
| if (int_req > 0) { /* interrupt? */ | |
| /* 6800 interrupts not implemented yet. None were used, | |
| on a standard SWTP 6800. All I/O is programmed. */ | |
| } /* end interrupt */ | |
| if (sim_brk_summ && | |
| sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ | |
| reason = STOP_IBKPT; /* stop simulation */ | |
| break; | |
| } | |
| /* transient routine area - trace */ | |
| /* | |
| if (PC >= 0xa100 && PC < 0xa400) { | |
| dump_regs(); | |
| printf("\n\r%04X: ", PC); | |
| val1[0] = M[PC]; | |
| val1[1] = M[PC+1]; | |
| val1[2] = M[PC+2]; | |
| fprint_sym(stdout, PC, val1, NULL, SWMASK ('M')); | |
| } | |
| */ | |
| IR = OP = mem_get_byte(PC); /* fetch instruction */ | |
| PC = (PC + 1) & ADDRMASK; /* increment PC */ | |
| sim_interval--; | |
| /* The Big Instruction Decode Switch */ | |
| switch (IR) { | |
| case 0x01: /* NOP */ | |
| break; | |
| case 0x06: /* TAP */ | |
| set_psw(A); | |
| break; | |
| case 0x07: /* TPA */ | |
| A = get_psw(); | |
| break; | |
| case 0x08: /* INX */ | |
| IX = (IX + 1) & ADDRMASK; | |
| condevalZ(IX); | |
| break; | |
| case 0x09: /* DEX */ | |
| IX = (IX + 1) & ADDRMASK; | |
| condevalZ(IX); | |
| break; | |
| case 0x0A: /* CLV */ | |
| V = 0; | |
| break; | |
| case 0x0B: /* SEV */ | |
| V = 0x10000; | |
| break; | |
| case 0x0C: /* CLC */ | |
| C = 0; | |
| break; | |
| case 0x0D: /* SEC */ | |
| C = 0x10000; | |
| break; | |
| case 0x0E: /* CLI */ | |
| I = 0; | |
| break; | |
| case 0x0F: /* SEI */ | |
| I = 0x10000; | |
| break; | |
| case 0x10: /* SBA */ | |
| op1 = A; | |
| A = A - B; | |
| condevalN(A); | |
| condevalZ(A); | |
| condevalC(A); | |
| condevalVs(B, op1); | |
| A &= 0xFF; | |
| break; | |
| case 0x11: /* CBA */ | |
| lo = A - B; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| condevalC(lo); | |
| condevalVs(B, A); | |
| break; | |
| case 0x16: /* TAB */ | |
| B = A; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| break; | |
| case 0x17: /* TBA */ | |
| A = B; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| break; | |
| case 0x19: /* DAA */ | |
| DAR = A & 0x0F; | |
| op1 = C; | |
| if (DAR > 9 || C) { | |
| DAR += 6; | |
| A &= 0xF0; | |
| A |= DAR & 0x0F; | |
| C = 0; | |
| if (DAR & 0x10) | |
| C = 0x10000; | |
| } | |
| DAR = (A >> 4) & 0x0F; | |
| if (DAR > 9 || C) { | |
| DAR += 6; | |
| if (C) | |
| DAR++; | |
| A &= 0x0F; | |
| A |= (DAR << 4); | |
| } | |
| C = op1; | |
| if ((DAR << 4) & 0x100) | |
| C = 0x10000; | |
| condevalN(A); | |
| condevalZ(A); | |
| A &= 0xFF; | |
| break; | |
| case 0x1B: /* ABA */ | |
| A += B; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalZ(A); | |
| condevalC(A); | |
| condevalVa(A, B); | |
| A &= 0xFF; | |
| break; | |
| case 0x20: /* BRA rel */ | |
| go_rel(1); | |
| break; | |
| case 0x22: /* BHI rel */ | |
| go_rel(!(C | Z)); | |
| break; | |
| case 0x23: /* BLS rel */ | |
| go_rel(C | Z); | |
| break; | |
| case 0x24: /* BCC rel */ | |
| go_rel(!C); | |
| break; | |
| case 0x25: /* BCS rel */ | |
| go_rel(C); | |
| break; | |
| case 0x26: /* BNE rel */ | |
| go_rel(!Z); | |
| break; | |
| case 0x27: /* BEQ rel */ | |
| go_rel(Z); | |
| break; | |
| case 0x28: /* BVC rel */ | |
| go_rel(!V); | |
| break; | |
| case 0x29: /* BVS rel */ | |
| go_rel(V); | |
| break; | |
| case 0x2A: /* BPL rel */ | |
| go_rel(!N); | |
| break; | |
| case 0x2B: /* BMI rel */ | |
| go_rel(N); | |
| break; | |
| case 0x2C: /* BGE rel */ | |
| go_rel(!(N ^ V)); | |
| break; | |
| case 0x2D: /* BLT rel */ | |
| go_rel(N ^ V); | |
| break; | |
| case 0x2E: /* BGT rel */ | |
| go_rel(!(Z | (N ^ V))); | |
| break; | |
| case 0x2F: /* BLE rel */ | |
| go_rel(Z | (N ^ V)); | |
| break; | |
| case 0x30: /* TSX */ | |
| IX = (SP + 1) & ADDRMASK; | |
| break; | |
| case 0x31: /* INS */ | |
| SP = (SP + 1) & ADDRMASK; | |
| break; | |
| case 0x32: /* PUL A */ | |
| SP = (SP + 1) & ADDRMASK; | |
| A = mem_get_byte(SP); | |
| break; | |
| case 0x33: /* PUL B */ | |
| SP = (SP + 1) & ADDRMASK; | |
| B = mem_get_byte(SP); | |
| break; | |
| case 0x34: /* DES */ | |
| SP = (SP - 1) & ADDRMASK; | |
| break; | |
| case 0x35: /* TXS */ | |
| SP = (IX - 1) & ADDRMASK; | |
| break; | |
| case 0x36: /* PSH A */ | |
| mem_put_byte(SP, A); | |
| SP = (SP - 1) & ADDRMASK; | |
| break; | |
| case 0x37: /* PSH B */ | |
| mem_put_byte(SP, B); | |
| SP = (SP - 1) & ADDRMASK; | |
| break; | |
| case 0x39: /* RTS */ | |
| SP = (SP + 1) & ADDRMASK; | |
| PC = mem_get_word(SP) & ADDRMASK; | |
| SP = (SP + 1) & ADDRMASK; | |
| break; | |
| case 0x3B: /* RTI */ | |
| SP = (SP + 1) & ADDRMASK; | |
| set_psw(mem_get_byte(SP)); | |
| SP = (SP + 1) & ADDRMASK; | |
| B = mem_get_byte(SP); | |
| SP = (SP + 1) & ADDRMASK; | |
| A = mem_get_byte(SP); | |
| SP = (SP + 1) & ADDRMASK; | |
| IX = mem_get_word(SP); | |
| SP = (SP + 2) & ADDRMASK; | |
| PC = mem_get_word(SP) & ADDRMASK; | |
| SP = (SP + 1) & ADDRMASK; | |
| break; | |
| case 0x3E: /* WAI */ | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_word(SP, PC); | |
| SP = (SP - 2) & ADDRMASK; | |
| mem_put_word(SP, IX); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, A); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, B); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, get_psw()); | |
| SP = (SP - 1) & ADDRMASK; | |
| if (I) { | |
| reason = STOP_HALT; | |
| continue; | |
| } else { | |
| I = 0x10000; | |
| PC = mem_get_word(0xFFFE) & ADDRMASK; | |
| } | |
| break; | |
| case 0x3F: /* SWI */ | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_word(SP, PC); | |
| SP = (SP - 2) & ADDRMASK; | |
| mem_put_word(SP, IX); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, A); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, B); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_byte(SP, get_psw()); | |
| SP = (SP - 1) & ADDRMASK; | |
| I = 0x10000; | |
| PC = mem_get_word(0xFFFB) & ADDRMASK; | |
| break; | |
| case 0x40: /* NEG A */ | |
| A = (0 - A) & 0xFF; | |
| V = 0; | |
| if (A & 0x80) | |
| V = 0x10000; | |
| C = 0; | |
| if (A) | |
| C = 0x10000; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x43: /* COM A */ | |
| A = ~A & 0xFF; | |
| V = 0; | |
| C = 0x10000; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x44: /* LSR A */ | |
| C = 0; | |
| if (A & 0x01) | |
| C = 0x10000; | |
| A = (A >> 1) & 0xFF; | |
| N = 0; | |
| condevalZ(A); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x46: /* ROR A */ | |
| hi = C; | |
| C = 0; | |
| if (A & 0x01) | |
| C = 0x10000; | |
| A = (A >> 1) & 0xFF; | |
| if (hi) | |
| A |= 0x80; | |
| condevalN(A); | |
| condevalZ(A); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x47: /* ASR A */ | |
| C = 0; | |
| if (A & 0x01) | |
| C = 0x10000; | |
| lo = A & 0x8000; | |
| A = (A >> 1) & 0xFF; | |
| A |= lo; | |
| condevalN(A); | |
| condevalZ(A); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x48: /* ASL A */ | |
| C = 0; | |
| if (A & 0x80) | |
| C = 0x10000; | |
| A = (A << 1) & 0xFF; | |
| condevalN(A); | |
| condevalZ(A); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x49: /* ROL A */ | |
| hi = C; | |
| C = 0; | |
| if (A & 0x80) | |
| C = 0x10000; | |
| A = (A << 1) & 0xFF; | |
| if (hi) | |
| A |= 0x01; | |
| condevalN(A); | |
| condevalZ(A); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x4A: /* DEC A */ | |
| V = 0; | |
| if (A == 0x80) | |
| V = 0x10000; | |
| A = (A - 1) & 0xFF; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x4C: /* INC A */ | |
| V = 0; | |
| if (A == 0x7F) | |
| V = 0x10000; | |
| A = (A + 1) & 0xFF; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x4D: /* TST A */ | |
| lo = (A - 0) & 0xFF; | |
| V = 0; | |
| C = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x4F: /* CLR A */ | |
| A = 0; | |
| N = V = C = 0; | |
| Z = 0x10000; | |
| break; | |
| case 0x50: /* NEG B */ | |
| B = (0 - V) & 0xFF; | |
| V = 0; | |
| if (B & 0x8000) | |
| V = 0x10000; | |
| C = 0; | |
| if (B) | |
| C = 0x10000; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0x53: /* COM B */ | |
| B = ~B & 0xFF; | |
| V = 0; | |
| C = 0x10000; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0x54: /* LSR B */ | |
| C = 0; | |
| if (B & 0x01) | |
| C = 0x10000; | |
| B = (B >> 1) & 0xFF; | |
| N = 0; | |
| condevalZ(B); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x56: /* ROR B */ | |
| hi = C; | |
| C = 0; | |
| if (B & 0x01) | |
| C = 0x10000; | |
| B = (B >> 1) & 0xFF; | |
| if (hi) | |
| B |= 0x80; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x57: /* ASR B */ | |
| C = 0; | |
| if (B & 0x01) | |
| C = 0x10000; | |
| lo = B & 0x8000; | |
| B = (B >> 1) & 0xFF; | |
| B |= lo; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x58: /* ASL B */ | |
| C = 0; | |
| if (B & 0x80) | |
| C = 0x10000; | |
| B = (B << 1) & 0xFF; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x59: /* ROL B */ | |
| hi = C; | |
| C = 0; | |
| if (B & 0x80) | |
| C = 0x10000; | |
| B = (B << 1) & 0xFF; | |
| if (hi) | |
| B |= 0x01; | |
| condevalN(B); | |
| condevalZ(B); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x5A: /* DEC B */ | |
| V = 0; | |
| if (B == 0x80) | |
| V = 0x10000; | |
| B = (B - 1) & 0xFF; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0x5C: /* INC B */ | |
| V = 0; | |
| if (B == 0x7F) | |
| V = 0x10000; | |
| B = (B + 1) & 0xFF; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0x5D: /* TST B */ | |
| lo = (B - 0) & 0xFF; | |
| V = 0; | |
| C = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x5F: /* CLR B */ | |
| B = 0; | |
| N = V = C = 0; | |
| Z = 0x10000; | |
| break; | |
| case 0x60: /* NEG ind */ | |
| DAR = get_indir_addr(); | |
| lo = (0 - mem_get_byte(DAR)) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| V = 0; | |
| if (lo & 0x80) | |
| V = 0x10000; | |
| C = 0; | |
| if (lo) | |
| C = 0x10000; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x63: /* COM ind */ | |
| DAR = get_indir_addr(); | |
| lo = ~mem_get_byte(DAR) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| V = 0; | |
| C = 0x10000; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x64: /* LSR ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| lo >>= 1; | |
| mem_put_byte(DAR, lo); | |
| N = 0; | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x66: /* ROR ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| hi = C; | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| lo >>= 1; | |
| if (hi) | |
| lo |= 0x80; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x67: /* ASR ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| lo = (lo & 0x80) | (lo >> 1); | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x68: /* ASL ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x80) | |
| C = 0x10000; | |
| lo <<= 1; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x69: /* ROL ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| hi = C; | |
| C = 0; | |
| if (lo & 0x80) | |
| C = 0x10000; | |
| lo <<= 1; | |
| if (hi) | |
| lo |= 0x01; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x6A: /* DEC ind */ | |
| DAR = get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| V = 0; | |
| if (lo == 0x80) | |
| V = 0x10000; | |
| lo = (lo - 1) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x6C: /* INC ind */ | |
| DAR= get_indir_addr(); | |
| lo = mem_get_byte(DAR); | |
| V = 0; | |
| if (lo == 0x7F) | |
| V = 0x10000; | |
| lo = (lo + 1) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x6D: /* TST ind */ | |
| lo = (get_indir_val() - 0) & 0xFF; | |
| V = 0; | |
| C = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x6E: /* JMP ind */ | |
| PC = get_indir_addr(); | |
| break; | |
| case 0x6F: /* CLR ind */ | |
| mem_put_byte(get_indir_addr(), 0); | |
| N = V = C = 0; | |
| Z = 0x10000; | |
| break; | |
| case 0x70: /* NEG ext */ | |
| DAR = get_ext_addr(PC); | |
| lo = (0 - mem_get_byte(DAR)) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| V = 0; | |
| if (lo & 0x80) | |
| V = 0x10000; | |
| C = 0; | |
| if (lo) | |
| C = 0x10000; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x73: /* COM ext */ | |
| DAR = get_ext_addr(); | |
| lo = ~mem_get_byte(DAR) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| V = 0; | |
| C = 0x10000; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x74: /* LSR ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| lo >>= 1; | |
| mem_put_byte(DAR, lo); | |
| N = 0; | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x76: /* ROR ext */ | |
| DAR = get_ext_addr(); | |
| hi = C; | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| lo >>= 1; | |
| if (hi) | |
| lo |= 0x80; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x77: /* ASR ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x01) | |
| C = 0x10000; | |
| hi = lo & 0x80; | |
| lo >>= 1; | |
| lo |= hi; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x78: /* ASL ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| C = 0; | |
| if (lo & 0x80) | |
| C = 0x10000; | |
| lo <<= 1; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x79: /* ROL ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| hi = C; | |
| C = 0; | |
| if (lo & 0x80) | |
| C = 0x10000; | |
| lo <<= 1; | |
| if (hi) | |
| lo |= 0x01; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| V = 0; | |
| if (N ^ C) | |
| V = 0x10000; | |
| break; | |
| case 0x7A: /* DEC ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| V = 0; | |
| if (lo == 0x80) | |
| V = 0x10000; | |
| lo = (lo - 1) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x7C: /* INC ext */ | |
| DAR = get_ext_addr(); | |
| lo = mem_get_byte(DAR); | |
| V = 0; | |
| if (lo == 0x7F) | |
| V = 0x10000; | |
| lo = (lo + 1) & 0xFF; | |
| mem_put_byte(DAR, lo); | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x7D: /* TST ext */ | |
| lo = mem_get_byte(get_ext_addr()) - 0; | |
| V = 0; | |
| C = 0; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| break; | |
| case 0x7E: /* JMP ext */ | |
| PC = get_ext_addr() & ADDRMASK; | |
| break; | |
| case 0x7F: /* CLR ext */ | |
| mem_put_byte(get_ext_addr(), 0); | |
| N = V = C = 0; | |
| Z = 0x10000; | |
| break; | |
| case 0x80: /* SUB A imm */ | |
| op1 = get_dir_addr(); | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x81: /* CMP A imm */ | |
| op1 = get_dir_addr(); | |
| lo = A - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(lo, op1); | |
| break; | |
| case 0x82: /* SBC A imm */ | |
| op1 = get_dir_addr(); | |
| if (C) | |
| A = A - op1 - 1; | |
| else | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x84: /* AND A imm */ | |
| A = (A & get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x85: /* BIT A imm */ | |
| lo = (A & get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x86: /* LDA A imm */ | |
| A = get_dir_addr(); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x88: /* EOR A imm */ | |
| A = (A ^ get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x89: /* ADC A imm */ | |
| op1 = get_dir_addr(); | |
| if (C) | |
| A = A + op1 + 1; | |
| else | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x8A: /* ORA A imm */ | |
| A = (A | get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x8B: /* ADD A imm */ | |
| op1 = get_dir_addr(); | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x8C: /* CPX imm */ | |
| op1 = IX - get_ext_addr(); | |
| condevalZ(op1); | |
| condevalN(op1 >> 8); | |
| V = op1 & 0x10000; | |
| break; | |
| case 0x8D: /* BSR rel */ | |
| lo = get_rel_addr(); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_word(SP, PC); | |
| SP = (SP - 1) & ADDRMASK; | |
| PC = PC + lo; | |
| PC &= ADDRMASK; | |
| break; | |
| case 0x8E: /* LDS imm */ | |
| SP = get_ext_addr(); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0x90: /* SUB A dir */ | |
| op1 = get_dir_val(); | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x91: /* CMP A dir */ | |
| op1 = get_dir_val(); | |
| lo = A - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xff); | |
| condevalC(lo); | |
| condevalVs(A, op1); | |
| break; | |
| case 0x92: /* SBC A dir */ | |
| op1 = get_dir_val(); | |
| if (C) | |
| A = A - op1 - 1; | |
| else | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x94: /* AND A dir */ | |
| A = (A & get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x95: /* BIT A dir */ | |
| lo = (A & get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0x96: /* LDA A dir */ | |
| A = get_dir_val(); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x97: /* STA A dir */ | |
| mem_put_byte(get_dir_addr(), A); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x98: /* EOR A dir */ | |
| A = (A ^ get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x99: /* ADC A dir */ | |
| op1 = get_dir_val(); | |
| if (C) | |
| A = A + op1 + 1; | |
| else | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x9A: /* ORA A dir */ | |
| A = (A | get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0x9B: /* ADD A dir */ | |
| op1 = get_dir_val(); | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0x9C: /* CPX dir */ | |
| op1 = IX - mem_get_word(get_dir_addr()); | |
| condevalZ(op1); | |
| condevalN(op1 >> 8); | |
| V = op1 & 0x10000; | |
| break; | |
| case 0x9E: /* LDS dir */ | |
| SP = mem_get_word(get_dir_addr()); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0x9F: /* STS dir */ | |
| mem_put_word(get_dir_addr(), SP); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0xA0: /* SUB A ind */ | |
| op1 = get_indir_val(); | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xA1: /* CMP A ind */ | |
| op1 = get_indir_val(); | |
| lo = A - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(A, op1); | |
| break; | |
| case 0xA2: /* SBC A ind */ | |
| op1 = get_indir_val(); | |
| if (C) | |
| A = A - op1 - 1; | |
| else | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xA4: /* AND A ind */ | |
| A = (A & get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xA5: /* BIT A ind */ | |
| lo = (A & get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xA6: /* LDA A ind */ | |
| A = get_indir_val(); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xA7: /* STA A ind */ | |
| mem_put_byte(get_indir_addr(), A); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xA8: /* EOR A ind */ | |
| A = (A ^ get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xA9: /* ADC A ind */ | |
| op1 = get_indir_val(); | |
| if (C) | |
| A = A + op1 + 1; | |
| else | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xAA: /* ORA A ind */ | |
| A = (A | get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xAB: /* ADD A ind */ | |
| op1 = get_indir_val(); | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xAC: /* CPX ind */ | |
| op1 = (IX - get_indir_addr()) & ADDRMASK; | |
| condevalZ(op1); | |
| condevalN(op1 >> 8); | |
| V = op1 & 0x10000; | |
| break; | |
| case 0xAD: /* JSR ind */ | |
| DAR = get_indir_addr(); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_word(SP, PC); | |
| SP = (SP - 1) & ADDRMASK; | |
| PC = DAR; | |
| break; | |
| case 0xAE: /* LDS ind */ | |
| SP = mem_get_word(get_indir_addr()); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0xAF: /* STS ind */ | |
| mem_put_word(get_indir_addr(), SP); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0xB0: /* SUB A ext */ | |
| op1 = get_ext_val(); | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xB1: /* CMP A ext */ | |
| op1 = get_ext_val(); | |
| lo = A - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(A, op1); | |
| break; | |
| case 0xB2: /* SBC A ext */ | |
| op1 = get_ext_val(); | |
| if (C) | |
| A = A - op1 - 1; | |
| else | |
| A = A - op1; | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVs(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xB4: /* AND A ext */ | |
| A = (A & get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xB5: /* BIT A ext */ | |
| lo = (A & get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xB6: /* LDA A ext */ | |
| A = get_ext_val(); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xB7: /* STA A ext */ | |
| mem_put_byte(get_ext_addr(), A); | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xB8: /* EOR A ext */ | |
| A = (A ^ get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xB9: /* ADC A ext */ | |
| op1 = get_ext_val(); | |
| if (C) | |
| A = A + op1 + 1; | |
| else | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xBA: /* ORA A ext */ | |
| A = (A | get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(A); | |
| condevalZ(A); | |
| break; | |
| case 0xBB: /* ADD A ext */ | |
| op1 = get_ext_val(); | |
| A = A + op1; | |
| condevalH(A); | |
| condevalN(A); | |
| condevalC(A); | |
| condevalVa(A, op1); | |
| A &= 0xFF; | |
| condevalZ(A); | |
| break; | |
| case 0xBC: /* CPX ext */ | |
| op1 = (IX - mem_get_word(get_ext_addr())) & ADDRMASK; | |
| condevalZ(op1); | |
| condevalN(op1 >> 8); | |
| V = op1 & 0x10000; | |
| break; | |
| case 0xBD: /* JSR ext */ | |
| DAR = get_ext_addr(); | |
| SP = (SP - 1) & ADDRMASK; | |
| mem_put_word(SP, PC); | |
| SP = (SP - 1) & ADDRMASK; | |
| PC = DAR; | |
| break; | |
| case 0xBE: /* LDS ext */ | |
| SP = mem_get_word(get_ext_addr()); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0xBF: /* STS ext */ | |
| mem_put_word(get_ext_addr(), SP); | |
| condevalN(SP >> 8); | |
| condevalZ(SP); | |
| V = 0; | |
| break; | |
| case 0xC0: /* SUB B imm */ | |
| op1 = get_dir_addr(); | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xC1: /* CMP B imm */ | |
| op1 = get_dir_addr(); | |
| lo = B - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(B, op1); | |
| break; | |
| case 0xC2: /* SBC B imm */ | |
| op1 = get_dir_addr(); | |
| if (C) | |
| B = B - op1 - 1; | |
| else | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xC4: /* AND B imm */ | |
| B = (B & get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xC5: /* BIT B imm */ | |
| lo = (B & get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xC6: /* LDA B imm */ | |
| B = get_dir_addr(); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xC8: /* EOR B imm */ | |
| B = (B ^ get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xC9: /* ADC B imm */ | |
| op1 = get_dir_addr(); | |
| if (C) | |
| B = B + op1 + 1; | |
| else | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xCA: /* ORA B imm */ | |
| B = (B | get_dir_addr()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xCB: /* ADD B imm */ | |
| op1 = get_dir_addr(); | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xCE: /* LDX imm */ | |
| IX = get_ext_addr(); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xD0: /* SUB B dir */ | |
| op1 = get_dir_val(); | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xD1: /* CMP B dir */ | |
| op1 = get_dir_val(); | |
| lo = B - op1; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| condevalC(lo); | |
| condevalVs(B, op1); | |
| break; | |
| case 0xD2: /* SBC B dir */ | |
| op1 = get_dir_val(); | |
| if (C) | |
| B = B - op1 - 1; | |
| else | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xD4: /* AND B dir */ | |
| B = (B & get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xD5: /* BIT B dir */ | |
| lo = (B & get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xD6: /* LDA B dir */ | |
| B = get_dir_val(); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xD7: /* STA B dir */ | |
| mem_put_byte(get_dir_addr(), B); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xD8: /* EOR B dir */ | |
| B = (B ^ get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xD9: /* ADC B dir */ | |
| op1 = get_dir_val(); | |
| if (C) | |
| B = B + op1 + 1; | |
| else | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xDA: /* ORA B dir */ | |
| B = (B | get_dir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xDB: /* ADD B dir */ | |
| op1 = get_dir_val(); | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xDE: /* LDX dir */ | |
| IX = mem_get_word(get_dir_addr()); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xDF: /* STX dir */ | |
| mem_put_word(get_dir_addr(), IX); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xE0: /* SUB B ind */ | |
| op1 = get_indir_val(); | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xE1: /* CMP B ind */ | |
| op1 = get_indir_val(); | |
| lo = B - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(B, op1); | |
| break; | |
| case 0xE2: /* SBC B ind */ | |
| op1 = get_indir_val(); | |
| if (C) | |
| B = B - op1 - 1; | |
| else | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xE4: /* AND B ind */ | |
| B = (B & get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xE5: /* BIT B ind */ | |
| lo = (B & get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xE6: /* LDA B ind */ | |
| B = get_indir_val(); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xE7: /* STA B ind */ | |
| mem_put_byte(get_indir_addr(), B); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xE8: /* EOR B ind */ | |
| B = (B ^ get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xE9: /* ADC B ind */ | |
| op1 = get_indir_val(); | |
| if (C) | |
| B = B + op1 + 1; | |
| else | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xEA: /* ORA B ind */ | |
| B = (B | get_indir_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xEB: /* ADD B ind */ | |
| op1 = get_indir_val(); | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xEE: /* LDX ind */ | |
| IX = mem_get_word(get_indir_addr()); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xEF: /* STX ind */ | |
| mem_put_word(get_indir_addr(), IX); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xF0: /* SUB B ext */ | |
| op1 = get_ext_val(); | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xF1: /* CMP B ext */ | |
| op1 = get_ext_val(); | |
| lo = B - op1; | |
| condevalN(lo); | |
| condevalZ(lo & 0xFF); | |
| condevalC(lo); | |
| condevalVs(B, op1); | |
| break; | |
| case 0xF2: /* SBC B ext */ | |
| op1 = get_ext_val(); | |
| if (C) | |
| B = B - op1 - 1; | |
| else | |
| B = B - op1; | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVs(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xF4: /* AND B ext */ | |
| B = (B & get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xF5: /* BIT B ext */ | |
| lo = (B & get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(lo); | |
| condevalZ(lo); | |
| break; | |
| case 0xF6: /* LDA B ext */ | |
| B = get_ext_val(); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xF7: /* STA B ext */ | |
| mem_put_byte(get_ext_addr(), B); | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xF8: /* EOR B ext */ | |
| B = (B ^ get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xF9: /* ADC B ext */ | |
| op1 = get_ext_val(); | |
| if (C) | |
| B = B + op1 + 1; | |
| else | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xFA: /* ORA B ext */ | |
| B = (B | get_ext_val()) & 0xFF; | |
| V = 0; | |
| condevalN(B); | |
| condevalZ(B); | |
| break; | |
| case 0xFB: /* ADD B ext */ | |
| op1 = get_ext_val(); | |
| B = B + op1; | |
| condevalH(B); | |
| condevalN(B); | |
| condevalC(B); | |
| condevalVa(B, op1); | |
| B &= 0xFF; | |
| condevalZ(B); | |
| break; | |
| case 0xFE: /* LDX ext */ | |
| IX = mem_get_word(get_ext_addr()); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| case 0xFF: /* STX ext */ | |
| mem_put_word(get_ext_addr(), IX); | |
| condevalN(IX >> 8); | |
| condevalZ(IX); | |
| V = 0; | |
| break; | |
| default: { /* Unassigned */ | |
| if (cpu_unit.flags & UNIT_OPSTOP) { | |
| reason = STOP_OPCODE; | |
| PC--; | |
| } | |
| break; | |
| } | |
| } | |
| } | |
| /* Simulation halted - lets dump all the registers! */ | |
| dump_regs(); | |
| saved_PC = PC; | |
| return reason; | |
| } | |
| /* dump the working registers */ | |
| void dump_regs() | |
| { | |
| printf("\r\nPC=%04X SP=%04X IX=%04X ", PC, SP, IX); | |
| printf("A=%02X B=%02X PSW=%02X", A, B, get_psw()); | |
| } | |
| /* 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 = get_rel_addr(); | |
| if (cond) | |
| PC += temp; | |
| PC &= ADDRMASK; | |
| } | |
| /* returns the relative offset sign-extended */ | |
| int32 get_rel_addr() | |
| { | |
| int32 temp; | |
| temp = mem_get_byte(PC++); | |
| if (temp & 0x80) | |
| temp |= 0xFF00; | |
| return temp & ADDRMASK; | |
| } | |
| /* returns the value at the direct address pointed to by PC */ | |
| int32 get_dir_val() | |
| { | |
| return mem_get_byte(get_dir_addr()); | |
| } | |
| /* returns the direct address pointed to by PC */ | |
| int32 get_dir_addr() | |
| { | |
| int32 temp; | |
| temp = mem_get_byte(PC); | |
| PC = (PC + 1) & ADDRMASK; | |
| return temp & 0xFF; | |
| } | |
| /* returns the value at the indirect address pointed to by PC */ | |
| int32 get_indir_val() | |
| { | |
| return mem_get_byte(get_indir_addr()); | |
| } | |
| /* returns the indirect address pointed to by PC or immediate byte */ | |
| int32 get_indir_addr() | |
| { | |
| int32 temp; | |
| temp = (mem_get_byte(PC++) + IX) & ADDRMASK; | |
| PC &= ADDRMASK; | |
| return temp; | |
| } | |
| /* returns the value at the extended address pointed to by PC */ | |
| int32 get_ext_val() | |
| { | |
| return mem_get_byte(get_ext_addr()); | |
| } | |
| /* returns the extended address pointed to by PC or immediate word */ | |
| int32 get_ext_addr() | |
| { | |
| int32 temp; | |
| temp = (mem_get_byte(PC) << 8) | mem_get_byte(PC+1); | |
| PC = (PC +2) & ADDRMASK; | |
| return temp; | |
| } | |
| /* return a PSW from the current flags */ | |
| int32 get_psw() | |
| { | |
| int32 psw; | |
| psw = 0xC0; | |
| if (H) | |
| psw |= 0x20; | |
| if (I) | |
| psw |= 0x10; | |
| if (N) | |
| psw |= 0x08; | |
| if (Z) | |
| psw |= 0x04; | |
| if (V) | |
| psw |= 0x02; | |
| if (C) | |
| psw |= 0x01; | |
| return psw; | |
| } | |
| /* set the current flags from a PSW */ | |
| void set_psw(int32 psw) | |
| { | |
| H = 0; | |
| if (psw & 0x20) | |
| H = 0x10000; | |
| I = 0; | |
| if (psw & 0x10) | |
| I = 0x10000; | |
| N = 0; | |
| if (psw & 0x08) | |
| N = 0x10000; | |
| Z = 0; | |
| if (psw & 0x04) | |
| Z = 0x10000; | |
| V = 0; | |
| if (psw & 0x02) | |
| V = 0x10000; | |
| C = 0; | |
| if (psw & 0x01) | |
| C = 0x10000; | |
| } | |
| /* test and set H */ | |
| void condevalH(int32 res) | |
| { | |
| H = (res & 0x10) << 12; | |
| } | |
| /* test and set N */ | |
| void condevalN(int32 res) | |
| { | |
| N = 0; | |
| if (res & 0x80) | |
| N = 0x10000; | |
| } | |
| /* test and set Z */ | |
| void condevalZ(int32 res) | |
| { | |
| Z = 0; | |
| if (res == 0) | |
| Z = 0x10000; | |
| } | |
| /* test and set V for addition */ | |
| void condevalVa(int32 op1, int32 op2) | |
| { | |
| if (C) { | |
| V = 0; | |
| if (((op1 & 0x80) && (op2 & 0x80)) || | |
| (((op1 & 0x80) == 0) && ((op2 & 0x80) == 0))) | |
| V = 0x10000; | |
| } | |
| } | |
| /* test and set V for subtraction */ | |
| void condevalVs(int32 op1, int32 op2) | |
| { | |
| if (C) { | |
| V = 0; | |
| if (((op1 & 0x80) && ((op2 & 0x80) == 0)) || | |
| (((op1 & 0x80) == 0) && (op2 & 0x80))) | |
| V = 0x10000; | |
| } | |
| } | |
| /* test and set C */ | |
| void condevalC(int32 res) | |
| { | |
| C = (res & 0x100) << 8; | |
| } | |
| /* memory write operations */ | |
| /* put word */ | |
| void mem_put_word(int32 addr, int32 val) | |
| { | |
| mem_put_byte(addr,val >> 8); | |
| mem_put_byte(addr + 1, val); | |
| } | |
| /* put byte */ | |
| void mem_put_byte(int32 addr, int32 val) | |
| { | |
| if (addr >= 0x0000 && addr < (int32) MEMSIZE) /* memory cards */ | |
| M[addr] = val & 0xFF; | |
| else if (addr >= 0x8000 && addr < 0x8020) /* memory mapped I/O */ | |
| dev_table[addr - 0x8000].routine(1, val); | |
| else if (addr >= 0xA000 && addr < 0xA080) /* CPU memory */ | |
| M[addr] = val & 0xFF; | |
| else if ((addr >= 0xA080 && addr < 0xC000) && /* extended CPU memory */ | |
| cpu_unit.flags & UNIT_MA000) | |
| M[addr] = val & 0xFF; | |
| else { | |
| if (cpu_unit.flags & UNIT_MSTOP) | |
| mem_fault = 1; | |
| printf("Invalid write to %04X\n\r", addr); | |
| } | |
| } | |
| /* memory read operations */ | |
| /* get word */ | |
| int32 mem_get_word(int32 addr) | |
| { | |
| int32 temp; | |
| temp = (mem_get_byte(addr) << 8) | mem_get_byte(addr+1); | |
| return temp; | |
| } | |
| /* get byte */ | |
| int32 mem_get_byte(int32 addr) | |
| { | |
| int32 val; | |
| if (addr >= 0x0000 && addr < (int32) MEMSIZE) /* memory cards */ | |
| val = M[addr]; | |
| else if (addr >= 0x8000 && addr < 0x8020) /* memory mapped I/O */ | |
| val = dev_table[addr - 0x8000].routine(0, 0); | |
| else if (addr >= 0xA000 && addr < 0xA080) /* CPU memory */ | |
| val = M[addr]; | |
| else if ((addr >= 0xA080 && addr < 0xC000) && /* extended CPU memory */ | |
| cpu_unit.flags & UNIT_MA000) | |
| val = M[addr]; | |
| else if (addr >= 0xE000 && addr < 0x10000) /* ROM memory */ | |
| val = M[addr]; | |
| else { | |
| if (cpu_unit.flags & UNIT_MSTOP) | |
| mem_fault = 1; | |
| val = 0xFF; /* default for no memory at address */ | |
| printf("Invalid read of %04X\n\r", addr); | |
| } | |
| return val & 0xFF; | |
| } | |
| /* calls from the simulator */ | |
| /* Reset routine */ | |
| t_stat cpu_reset (DEVICE *dptr) | |
| { | |
| int i; | |
| I = 0x10000; | |
| saved_PC = (M[0xFFFE] << 8) | M[0xFFFF]; | |
| int_req = 0; | |
| sim_brk_types = sim_brk_dflt = SWMASK ('E'); | |
| /* copy in rom image at E000 */ | |
| for (i = 0; i < BOOTLEN; i++) { | |
| M[i + 0xE000] = bootrom[i] & 0xFF; | |
| } | |
| /* copy in rom image at FC00 for vectors! */ | |
| for (i = 0; i < BOOTLEN; i++) { | |
| M[i + 0xFC00] = bootrom[i] & 0xFF; | |
| } | |
| return SCPE_OK; | |
| } | |
| /* Memory examine */ | |
| t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) | |
| { | |
| if (addr >= MAXMEMSIZE) | |
| return SCPE_NXM; | |
| if (vptr != NULL) | |
| *vptr = mem_get_byte(addr); | |
| return SCPE_OK; | |
| } | |
| /* Memory deposit */ | |
| t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) | |
| { | |
| if (addr >= MAXMEMSIZE) | |
| return SCPE_NXM; | |
| mem_put_byte(addr, val); | |
| // printf("Deposit to %04X of %02X\n\r", addr, val); | |
| return SCPE_OK; | |
| } | |
| /* adjust the memory size for the emulator 4k to 32k in 4k steps */ | |
| t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) | |
| { | |
| int32 mc = 0; | |
| uint32 i; | |
| if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 0x0FFF) != 0)) | |
| return SCPE_ARG; | |
| for (i = val; i < MEMSIZE; i++) | |
| mc = mc | M[i]; | |
| if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) | |
| return SCPE_OK; | |
| MEMSIZE = val; | |
| return SCPE_OK; | |
| } | |
| /* dummy i/o device */ | |
| int32 nulldev(int32 io, int32 data) | |
| { | |
| if (io == 0) | |
| return (0xFF); | |
| return 0; | |
| } | |