/* 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 uint32 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; | |
} | |