1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-08 06:25:17 +00:00

Merge branch 'cc65:master' into struct-assignment-bug2566

This commit is contained in:
Sidney Cadot
2024-12-24 08:34:11 +01:00
committed by GitHub
3 changed files with 475 additions and 74 deletions

View File

@@ -8,6 +8,8 @@
.import _fgetc, popptr1, pushptr1, popax, pushax, return0, ___errno .import _fgetc, popptr1, pushptr1, popax, pushax, return0, ___errno
.importzp ptr1, ptr4 .importzp ptr1, ptr4
.feature string_escapes
.include "errno.inc" .include "errno.inc"
.include "stdio.inc" .include "stdio.inc"
.include "_file.inc" .include "_file.inc"
@@ -88,7 +90,22 @@ read_loop:
bne :+ bne :+
inc ptr4+1 inc ptr4+1
: cmp #$0A ; Stop at \n ; The next code line:
;
; .byte $c9, "\n"
;
; corresponds to a CMP #imm with the target-specific newline value as its operand.
; This works because (with the 'string_escapes' feature enabled), the "\n" string
; assembles to the target-specific value for the newline character.
;
; It would be better if we could just write:
;
; cmp #'\n'
;
; Unfortunately, ca65 doesn't currently handle escape characters in character
; constants. In the longer term, fixing that would be the preferred solution.
: .byte $c9, "\n" ; cmp #'\n'
beq done beq done
bne read_loop bne read_loop

View File

@@ -35,9 +35,8 @@
/*****************************************************************************/ /*****************************************************************************/
/* Known bugs and limitations of the 65C02 simulation: /* Known bugs and limitations of the 65C02 simulation:
* support currently only on the level of 65SC02: * the WAI ($CB) and STP ($DB) instructions are unsupported.
BBRx, BBSx, RMBx, SMBx, WAI, and STP are unsupported */
*/
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -623,14 +622,14 @@ static unsigned HaveIRQRequest;
/* 2 x Read-Modify-Write opcode helpers (illegal opcodes) */ /* 2 x Read-Modify-Write opcode helpers (illegal opcodes) */
/* Execution cycles for 2 x R-M-W opcodes */ /* Execution cycles for 2 x R-M-W opcodes */
#define RMW2_CY_ZP 5 #define RMW2_CY_ZP 5
#define RMW2_CY_ZPX 6 #define RMW2_CY_ZPX 6
#define RMW2_CY_ZPY 6 #define RMW2_CY_ZPY 6
#define RMW2_CY_ABS 6 #define RMW2_CY_ABS 6
#define RMW2_CY_ABSX 7 #define RMW2_CY_ABSX 7
#define RMW2_CY_ABSY 7 #define RMW2_CY_ABSY 7
#define RMW2_CY_ZPXIND 8 #define RMW2_CY_ZPXIND 8
#define RMW2_CY_ZPINDY 8 #define RMW2_CY_ZPINDY 8
/* zp / zp,x / zp,y / abs / abs,x / abs,y / (zp,x) / (zp),y */ /* zp / zp,x / zp,y / abs / abs,x / abs,y / (zp,x) / (zp),y */
#define ILLx2_OP(mode, op) \ #define ILLx2_OP(mode, op) \
@@ -664,15 +663,12 @@ static unsigned HaveIRQRequest;
/* ADC, binary mode (6502 and 65C02) */ /* ADC, binary mode (6502 and 65C02) */
/* TODO: once the Regs fields are properly sized, get rid of the
* "& 0xff" in the Regs.AC asignment.
*/
#define ADC_BINARY_MODE(v) \ #define ADC_BINARY_MODE(v) \
do { \ do { \
const uint8_t op = v; \ const uint8_t op = v; \
const uint8_t OldAC = Regs.AC; \ const uint8_t OldAC = Regs.AC; \
bool carry = GET_CF(); \ bool carry = GET_CF(); \
Regs.AC = (OldAC + op + carry) & 0xff; \ Regs.AC = (OldAC + op + carry); \
const bool NV = Regs.AC >= 0x80; \ const bool NV = Regs.AC >= 0x80; \
carry = OldAC + op + carry >= 0x100; \ carry = OldAC + op + carry >= 0x100; \
SET_SF(NV); \ SET_SF(NV); \
@@ -969,8 +965,14 @@ static unsigned HaveIRQRequest;
} while (0); } while (0);
/* ANE */ /* ANE */
/* An "unstable" illegal opcode that depends on a "constant" value that isn't
* really constant. It varies between machines, with temperature, and so on.
* Original sim65 behavior was to use the constant 0xEF here. To get behavior
* in line with the 65x02 testsuite, we now use the value 0xEE instead,
* which is also a reasonable choice that can be observed in practice.
*/
#define ANE(Val) \ #define ANE(Val) \
Val = (Regs.AC | 0xEF) & Regs.XR & Val; \ Val = (Regs.AC | 0xEE) & Regs.XR & Val; \
Regs.AC = Val; \ Regs.AC = Val; \
TEST_SF (Val); \ TEST_SF (Val); \
TEST_ZF (Val) TEST_ZF (Val)
@@ -1027,15 +1029,12 @@ static unsigned HaveIRQRequest;
TEST_ZF (Val) TEST_ZF (Val)
/* SBC, binary mode (6502 and 65C02) */ /* SBC, binary mode (6502 and 65C02) */
/* TODO: once the Regs fields are properly sized, get rid of the
* "& 0xff" in the Regs.AC asignment.
*/
#define SBC_BINARY_MODE(v) \ #define SBC_BINARY_MODE(v) \
do { \ do { \
const uint8_t op = v; \ const uint8_t op = v; \
const uint8_t OldAC = Regs.AC; \ const uint8_t OldAC = Regs.AC; \
const bool borrow = !GET_CF(); \ const bool borrow = !GET_CF(); \
Regs.AC = (OldAC - op - borrow) & 0xff; \ Regs.AC = (OldAC - op - borrow); \
const bool NV = Regs.AC >= 0x80; \ const bool NV = Regs.AC >= 0x80; \
SET_SF(NV); \ SET_SF(NV); \
SET_OF(((OldAC >= 0x80) ^ NV) & ((op < 0x80) ^ NV)); \ SET_OF(((OldAC >= 0x80) ^ NV) & ((op < 0x80) ^ NV)); \
@@ -1112,6 +1111,46 @@ static unsigned HaveIRQRequest;
/* Set/reset a specific bit in a zero-page byte. This macro
* macro is used to implement the 65C02 RMBx and SMBx instructions.
*/
#define ZP_BITOP(bitnr, bitval) \
do { \
uint8_t zp_address = MemReadByte (Regs.PC + 1); \
uint8_t zp_value = MemReadByte (zp_address); \
if (bitval) { \
zp_value |= (1 << bitnr); \
} else { \
zp_value &= ~(1 << bitnr); \
} \
MemWriteByte (zp_address, zp_value); \
Regs.PC += 2; \
Cycles = 5; \
} while (0)
/* Branch depending on the state of a specific bit of a zero page
* address. This macro is used to implement the 65C02 BBRx and
* BBSx instructions.
*/
#define ZP_BIT_BRANCH(bitnr, bitval) \
do { \
uint8_t zp_address = MemReadByte (Regs.PC + 1); \
uint8_t zp_value = MemReadByte (zp_address); \
int displacement = (int8_t)MemReadByte (Regs.PC + 2); \
if (((zp_value & (1 << bitnr)) != 0) == bitval) { \
Regs.PC += 3; \
uint8_t OldPCH = PCH; \
Regs.PC += displacement; \
Cycles = 6; \
if (PCH != OldPCH) { \
Cycles += 1; \
} \
} else { \
Regs.PC += 3; \
Cycles = 5; \
} \
} while (0)
/*****************************************************************************/ /*****************************************************************************/
/* Opcode handling functions */ /* Opcode handling functions */
/*****************************************************************************/ /*****************************************************************************/
@@ -1204,6 +1243,14 @@ static void OPC_6502_07 (void)
static void OPC_65C02_07 (void)
/* Opcode $07: RMB0 zp */
{
ZP_BITOP(0, 0);
}
static void OPC_6502_08 (void) static void OPC_6502_08 (void)
/* Opcode $08: PHP */ /* Opcode $08: PHP */
{ {
@@ -1283,6 +1330,14 @@ static void OPC_6502_0F (void)
static void OPC_65C02_0F (void)
/* Opcode $0F: BBR0 zp, rel */
{
ZP_BIT_BRANCH (0, 0);
}
static void OPC_6502_10 (void) static void OPC_6502_10 (void)
/* Opcode $10: BPL */ /* Opcode $10: BPL */
{ {
@@ -1362,6 +1417,14 @@ static void OPC_6502_17 (void)
static void OPC_65C02_17 (void)
/* Opcode $17: RMB1 zp */
{
ZP_BITOP(1, 0);
}
static void OPC_6502_18 (void) static void OPC_6502_18 (void)
/* Opcode $18: CLC */ /* Opcode $18: CLC */
{ {
@@ -1453,16 +1516,49 @@ static void OPC_6502_1F (void)
static void OPC_65C02_1F (void)
/* Opcode $1F: BBR1 zp, rel */
{
ZP_BIT_BRANCH (1, 0);
}
static void OPC_6502_20 (void) static void OPC_6502_20 (void)
/* Opcode $20: JSR */ /* Opcode $20: JSR */
{ {
unsigned Addr; /* The obvious way to implement JSR for the 6502 is to (a) read the target address,
* and then (b) push the return address minus one. Or do (b) first, then (a).
*
* However, there is a non-obvious case where this conflicts with the actual order
* of operations that the 6502 does, which is:
*
* (a) Load the LSB of the target address.
* (b) Push the MSB of the return address, minus one.
* (c) Push the LSB of the return address, minus one.
* (d) Load the MSB of the target address.
*
* This can make a difference in a pretty esoteric case, if the JSR target is located,
* wholly or in part, inside the stack page (!). This won't happen in normal code
* but it can happen in specifically constructed examples.
*
* To deal with this, we load the LSB and MSB of the target address separately,
* with the pushing of the return address sandwiched in between, to mimic
* the order of the bus operations on a real 6502.
*/
unsigned AddrLo, AddrHi;
Cycles = 6; Cycles = 6;
Addr = MemReadWord (Regs.PC+1); Regs.PC += 1;
Regs.PC += 2; AddrLo = MemReadByte(Regs.PC);
Regs.PC += 1;
PUSH (PCH); PUSH (PCH);
PUSH (PCL); PUSH (PCL);
Regs.PC = Addr; AddrHi = MemReadByte(Regs.PC);
Regs.PC = AddrLo + (AddrHi << 8);
ParaVirtHooks (&Regs); ParaVirtHooks (&Regs);
} }
@@ -1517,6 +1613,14 @@ static void OPC_6502_27 (void)
static void OPC_65C02_27 (void)
/* Opcode $27: RMB2 zp */
{
ZP_BITOP(2, 0);
}
static void OPC_6502_28 (void) static void OPC_6502_28 (void)
/* Opcode $28: PLP */ /* Opcode $28: PLP */
{ {
@@ -1580,6 +1684,14 @@ static void OPC_6502_2F (void)
static void OPC_65C02_2F (void)
/* Opcode $2F: BBR2 zp, rel */
{
ZP_BIT_BRANCH (2, 0);
}
static void OPC_6502_30 (void) static void OPC_6502_30 (void)
/* Opcode $30: BMI */ /* Opcode $30: BMI */
{ {
@@ -1644,6 +1756,14 @@ static void OPC_6502_37 (void)
static void OPC_65C02_37 (void)
/* Opcode $37: RMB3 zp */
{
ZP_BITOP(3, 0);
}
static void OPC_6502_38 (void) static void OPC_6502_38 (void)
/* Opcode $38: SEC */ /* Opcode $38: SEC */
{ {
@@ -1720,6 +1840,14 @@ static void OPC_6502_3F (void)
static void OPC_65C02_3F (void)
/* Opcode $3F: BBR3 zp, rel */
{
ZP_BIT_BRANCH (3, 0);
}
static void OPC_6502_40 (void) static void OPC_6502_40 (void)
/* Opcode $40: RTI */ /* Opcode $40: RTI */
{ {
@@ -1773,6 +1901,14 @@ static void OPC_6502_47 (void)
static void OPC_65C02_47 (void)
/* Opcode $47: RMB4 zp */
{
ZP_BITOP(4, 0);
}
static void OPC_6502_48 (void) static void OPC_6502_48 (void)
/* Opcode $48: PHA */ /* Opcode $48: PHA */
{ {
@@ -1844,6 +1980,14 @@ static void OPC_6502_4F (void)
static void OPC_65C02_4F (void)
/* Opcode $4F: BBR4 zp, rel */
{
ZP_BIT_BRANCH (4, 0);
}
static void OPC_6502_50 (void) static void OPC_6502_50 (void)
/* Opcode $50: BVC */ /* Opcode $50: BVC */
{ {
@@ -1900,6 +2044,14 @@ static void OPC_6502_57 (void)
static void OPC_65C02_57 (void)
/* Opcode $57: RMB5 zp */
{
ZP_BITOP(5, 0);
}
static void OPC_6502_58 (void) static void OPC_6502_58 (void)
/* Opcode $58: CLI */ /* Opcode $58: CLI */
{ {
@@ -1977,6 +2129,14 @@ static void OPC_6502_5F (void)
static void OPC_65C02_5F (void)
/* Opcode $5F: BBR5 zp, rel */
{
ZP_BIT_BRANCH (5, 0);
}
static void OPC_6502_60 (void) static void OPC_6502_60 (void)
/* Opcode $60: RTS */ /* Opcode $60: RTS */
{ {
@@ -2050,6 +2210,14 @@ static void OPC_6502_67 (void)
static void OPC_65C02_67 (void)
/* Opcode $67: RMB6 zp */
{
ZP_BITOP(6, 0);
}
static void OPC_6502_68 (void) static void OPC_6502_68 (void)
/* Opcode $68: PLA */ /* Opcode $68: PLA */
{ {
@@ -2163,6 +2331,14 @@ static void OPC_6502_6F (void)
static void OPC_65C02_6F (void)
/* Opcode $6F: BBR6 zp, rel */
{
ZP_BIT_BRANCH (6, 0);
}
static void OPC_6502_70 (void) static void OPC_6502_70 (void)
/* Opcode $70: BVS */ /* Opcode $70: BVS */
{ {
@@ -2241,6 +2417,14 @@ static void OPC_6502_77 (void)
static void OPC_65C02_77 (void)
/* Opcode $77: RMB7 zp */
{
ZP_BITOP(7, 0);
}
static void OPC_6502_78 (void) static void OPC_6502_78 (void)
/* Opcode $78: SEI */ /* Opcode $78: SEI */
{ {
@@ -2341,6 +2525,14 @@ static void OPC_6502_7F (void)
static void OPC_65C02_7F (void)
/* Opcode $7F: BBR7 zp, rel */
{
ZP_BIT_BRANCH (7, 0);
}
/* Aliases of opcode $80 */ /* Aliases of opcode $80 */
#define OPC_6502_82 OPC_6502_80 #define OPC_6502_82 OPC_6502_80
#define OPC_6502_C2 OPC_6502_80 #define OPC_6502_C2 OPC_6502_80
@@ -2411,6 +2603,14 @@ static void OPC_6502_87 (void)
static void OPC_65C02_87 (void)
/* Opcode $87: SMB0 zp */
{
ZP_BITOP(0, 1);
}
static void OPC_6502_88 (void) static void OPC_6502_88 (void)
/* Opcode $88: DEY */ /* Opcode $88: DEY */
{ {
@@ -2483,6 +2683,14 @@ static void OPC_6502_8F (void)
static void OPC_65C02_8F (void)
/* Opcode $8F: BBS0 zp, rel */
{
ZP_BIT_BRANCH (0, 1);
}
static void OPC_6502_90 (void) static void OPC_6502_90 (void)
/* Opcode $90: BCC */ /* Opcode $90: BCC */
{ {
@@ -2510,7 +2718,20 @@ static void OPC_65SC02_92 (void)
static void OPC_6502_93 (void) static void OPC_6502_93 (void)
/* Opcode $93: SHA (zp),y */ /* Opcode $93: SHA (zp),y */
{ {
STO_CB (ZPINDY, SHA); ++Regs.PC;
uint8_t zp_ptr_lo = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t zp_ptr_hi = zp_ptr_lo + 1;
uint8_t baselo = MemReadByte(zp_ptr_lo);
uint8_t basehi = MemReadByte(zp_ptr_hi);
uint8_t basehi_incremented = basehi + 1;
uint8_t write_value = Regs.AC & Regs.XR & basehi_incremented;
uint8_t write_address_lo = (baselo + Regs.YR);
bool pagecross = (baselo + Regs.YR) > 0xff;
uint8_t write_address_hi = pagecross ? write_value : basehi;
uint16_t write_address = write_address_lo + (write_address_hi << 8);
MemWriteByte(write_address, write_value);
Cycles=6;
} }
@@ -2547,6 +2768,14 @@ static void OPC_6502_97 (void)
static void OPC_65C02_97 (void)
/* Opcode $97: SMB1 zp */
{
ZP_BITOP(1, 1);
}
static void OPC_6502_98 (void) static void OPC_6502_98 (void)
/* Opcode $98: TYA */ /* Opcode $98: TYA */
{ {
@@ -2580,7 +2809,20 @@ static void OPC_6502_9A (void)
static void OPC_6502_9B (void) static void OPC_6502_9B (void)
/* Opcode $9B: TAS abs,y */ /* Opcode $9B: TAS abs,y */
{ {
STO_CB (ABSY, TAS); ++Regs.PC;
uint8_t baselo = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi_incremented = basehi + 1;
uint8_t write_value = Regs.AC & Regs.XR & basehi_incremented;
uint8_t write_address_lo = (baselo + Regs.YR);
bool pagecross = (baselo + Regs.YR) > 0xff;
uint8_t write_address_hi = pagecross ? write_value : basehi;
uint16_t write_address = write_address_lo + (write_address_hi << 8);
MemWriteByte(write_address, write_value);
Regs.SP = Regs.AC & Regs.XR;
Cycles=5;
} }
@@ -2588,7 +2830,19 @@ static void OPC_6502_9B (void)
static void OPC_6502_9C (void) static void OPC_6502_9C (void)
/* Opcode $9D: SHY abs,x */ /* Opcode $9D: SHY abs,x */
{ {
STO_OP (ABSX, Regs.YR & ((address >> 8) + 1)); ++Regs.PC;
uint8_t baselo = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi_incremented = basehi + 1;
uint8_t write_value = Regs.YR & basehi_incremented;
uint8_t write_address_lo = (baselo + Regs.XR);
bool pagecross = (baselo + Regs.XR) > 0xff;
uint8_t write_address_hi = pagecross ? write_value : basehi;
uint16_t write_address = write_address_lo + (write_address_hi << 8);
MemWriteByte(write_address, write_value);
Cycles=5;
} }
@@ -2612,15 +2866,19 @@ static void OPC_6502_9D (void)
static void OPC_6502_9E (void) static void OPC_6502_9E (void)
/* Opcode $9E: SHX abs,x */ /* Opcode $9E: SHX abs,x */
{ {
STO_OP (ABSY, Regs.XR & ((address >> 8) + 1)); ++Regs.PC;
} uint8_t baselo = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi = MemReadByte(Regs.PC);
++Regs.PC;
static void OPC_6502_9F (void) uint8_t basehi_incremented = basehi + 1;
/* Opcode $9F: SHA abs,y */ uint8_t write_value = Regs.XR & basehi_incremented;
{ uint8_t write_address_lo = (baselo + Regs.YR);
STO_CB (ABSY, SHA); bool pagecross = (baselo + Regs.YR) > 0xff;
uint8_t write_address_hi = pagecross ? write_value : basehi;
uint16_t write_address = write_address_lo + (write_address_hi << 8);
MemWriteByte(write_address, write_value);
Cycles=5;
} }
@@ -2633,6 +2891,34 @@ static void OPC_65SC02_9E (void)
static void OPC_6502_9F (void)
/* Opcode $9F: SHA abs,y */
{
++Regs.PC;
uint8_t baselo = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi = MemReadByte(Regs.PC);
++Regs.PC;
uint8_t basehi_incremented = basehi + 1;
uint8_t write_value = Regs.AC & Regs.XR & basehi_incremented;
uint8_t write_address_lo = (baselo + Regs.YR);
bool pagecross = (baselo + Regs.YR) > 0xff;
uint8_t write_address_hi = pagecross ? write_value : basehi;
uint16_t write_address = write_address_lo + (write_address_hi << 8);
MemWriteByte(write_address, write_value);
Cycles=5;
}
static void OPC_65C02_9F (void)
/* Opcode $9F: BBS1 zp, rel */
{
ZP_BIT_BRANCH (1, 1);
}
static void OPC_6502_A0 (void) static void OPC_6502_A0 (void)
/* Opcode $A0: LDY #imm */ /* Opcode $A0: LDY #imm */
{ {
@@ -2697,6 +2983,14 @@ static void OPC_6502_A7 (void)
static void OPC_65C02_A7 (void)
/* Opcode $A7: SMB2 zp */
{
ZP_BITOP(2, 1);
}
static void OPC_6502_A8 (void) static void OPC_6502_A8 (void)
/* Opcode $A8: TAY */ /* Opcode $A8: TAY */
{ {
@@ -2769,6 +3063,14 @@ static void OPC_6502_AF (void)
static void OPC_65C02_AF (void)
/* Opcode $AF: BBS2 zp, rel */
{
ZP_BIT_BRANCH (2, 1);
}
static void OPC_6502_B0 (void) static void OPC_6502_B0 (void)
/* Opcode $B0: BCS */ /* Opcode $B0: BCS */
{ {
@@ -2833,6 +3135,14 @@ static void OPC_6502_B7 (void)
static void OPC_65C02_B7 (void)
/* Opcode $B7: SMB3 zp */
{
ZP_BITOP(3, 1);
}
static void OPC_6502_B8 (void) static void OPC_6502_B8 (void)
/* Opcode $B8: CLV */ /* Opcode $B8: CLV */
{ {
@@ -2903,6 +3213,14 @@ static void OPC_6502_BF (void)
static void OPC_65C02_BF (void)
/* Opcode $BF: BBS3 zp, rel */
{
ZP_BIT_BRANCH (3, 1);
}
static void OPC_6502_C0 (void) static void OPC_6502_C0 (void)
/* Opcode $C0: CPY #imm */ /* Opcode $C0: CPY #imm */
{ {
@@ -2959,6 +3277,14 @@ static void OPC_6502_C7 (void)
static void OPC_65C02_C7 (void)
/* Opcode $C7: SMB4 zp */
{
ZP_BITOP(4, 1);
}
static void OPC_6502_C8 (void) static void OPC_6502_C8 (void)
/* Opcode $C8: INY */ /* Opcode $C8: INY */
{ {
@@ -3027,6 +3353,14 @@ static void OPC_6502_CF (void)
static void OPC_65C02_CF (void)
/* Opcode $CF: BBS4 zp, rel */
{
ZP_BIT_BRANCH (4, 1);
}
static void OPC_6502_D0 (void) static void OPC_6502_D0 (void)
/* Opcode $D0: BNE */ /* Opcode $D0: BNE */
{ {
@@ -3083,6 +3417,14 @@ static void OPC_6502_D7 (void)
static void OPC_65C02_D7 (void)
/* Opcode $D7: SMB5 zp */
{
ZP_BITOP(5, 1);
}
static void OPC_6502_D8 (void) static void OPC_6502_D8 (void)
/* Opcode $D8: CLD */ /* Opcode $D8: CLD */
{ {
@@ -3143,6 +3485,14 @@ static void OPC_6502_DF (void)
static void OPC_65C02_DF (void)
/* Opcode $DF: BBS5 zp, rel */
{
ZP_BIT_BRANCH (5, 1);
}
static void OPC_6502_E0 (void) static void OPC_6502_E0 (void)
/* Opcode $E0: CPX #imm */ /* Opcode $E0: CPX #imm */
{ {
@@ -3213,6 +3563,14 @@ static void OPC_6502_E7 (void)
static void OPC_65C02_E7 (void)
/* Opcode $E7: SMB6 zp */
{
ZP_BITOP(6, 1);
}
static void OPC_6502_E8 (void) static void OPC_6502_E8 (void)
/* Opcode $E8: INX */ /* Opcode $E8: INX */
{ {
@@ -3333,6 +3691,14 @@ static void OPC_6502_EF (void)
static void OPC_65C02_EF (void)
/* Opcode $EF: BBS6 zp, rel */
{
ZP_BIT_BRANCH (6, 1);
}
static void OPC_6502_F0 (void) static void OPC_6502_F0 (void)
/* Opcode $F0: BEQ */ /* Opcode $F0: BEQ */
{ {
@@ -3406,6 +3772,14 @@ static void OPC_6502_F7 (void)
static void OPC_65C02_F7 (void)
/* Opcode $F7: SMB7 zp */
{
ZP_BITOP(7, 1);
}
static void OPC_6502_F8 (void) static void OPC_6502_F8 (void)
/* Opcode $F8: SED */ /* Opcode $F8: SED */
{ {
@@ -3484,6 +3858,14 @@ static void OPC_6502_FF (void)
static void OPC_65C02_FF (void)
/* Opcode $FF: BBS7 zp, rel */
{
ZP_BIT_BRANCH (7, 1);
}
/*****************************************************************************/ /*****************************************************************************/
/* Opcode handler tables */ /* Opcode handler tables */
/*****************************************************************************/ /*****************************************************************************/
@@ -4023,7 +4405,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_04, OPC_65SC02_04,
OPC_6502_05, OPC_6502_05,
OPC_6502_06, OPC_6502_06,
OPC_Illegal, // $07: RMB0 currently unsupported OPC_65C02_07,
OPC_6502_08, OPC_6502_08,
OPC_6502_09, OPC_6502_09,
OPC_6502_0A, OPC_6502_0A,
@@ -4031,7 +4413,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_0C, OPC_65SC02_0C,
OPC_6502_0D, OPC_6502_0D,
OPC_6502_0E, OPC_6502_0E,
OPC_Illegal, // $0F: BBR0 currently unsupported OPC_65C02_0F,
OPC_6502_10, OPC_6502_10,
OPC_6502_11, OPC_6502_11,
OPC_65SC02_12, OPC_65SC02_12,
@@ -4039,7 +4421,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_14, OPC_65SC02_14,
OPC_6502_15, OPC_6502_15,
OPC_6502_16, OPC_6502_16,
OPC_Illegal, // $17: RMB1 currently unsupported OPC_65C02_17,
OPC_6502_18, OPC_6502_18,
OPC_6502_19, OPC_6502_19,
OPC_65SC02_1A, OPC_65SC02_1A,
@@ -4047,7 +4429,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_1C, OPC_65SC02_1C,
OPC_6502_1D, OPC_6502_1D,
OPC_65C02_1E, OPC_65C02_1E,
OPC_Illegal, // $1F: BBR1 currently unsupported OPC_65C02_1F,
OPC_6502_20, OPC_6502_20,
OPC_6502_21, OPC_6502_21,
OPC_65C02_NOP22, // $22 OPC_65C02_NOP22, // $22
@@ -4055,7 +4437,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_24, OPC_6502_24,
OPC_6502_25, OPC_6502_25,
OPC_6502_26, OPC_6502_26,
OPC_Illegal, // $27: RMB2 currently unsupported OPC_65C02_27,
OPC_6502_28, OPC_6502_28,
OPC_6502_29, OPC_6502_29,
OPC_6502_2A, OPC_6502_2A,
@@ -4063,7 +4445,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_2C, OPC_6502_2C,
OPC_6502_2D, OPC_6502_2D,
OPC_6502_2E, OPC_6502_2E,
OPC_Illegal, // $2F: BBR2 currently unsupported OPC_65C02_2F,
OPC_6502_30, OPC_6502_30,
OPC_6502_31, OPC_6502_31,
OPC_65SC02_32, OPC_65SC02_32,
@@ -4071,7 +4453,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_34, OPC_65SC02_34,
OPC_6502_35, OPC_6502_35,
OPC_6502_36, OPC_6502_36,
OPC_Illegal, // $37: RMB3 currently unsupported OPC_65C02_37,
OPC_6502_38, OPC_6502_38,
OPC_6502_39, OPC_6502_39,
OPC_65SC02_3A, OPC_65SC02_3A,
@@ -4079,7 +4461,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_3C, OPC_65SC02_3C,
OPC_6502_3D, OPC_6502_3D,
OPC_65C02_3E, OPC_65C02_3E,
OPC_Illegal, // $3F: BBR3 currently unsupported OPC_65C02_3F,
OPC_6502_40, OPC_6502_40,
OPC_6502_41, OPC_6502_41,
OPC_65C02_NOP22, // $42 OPC_65C02_NOP22, // $42
@@ -4087,7 +4469,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_44, // $44 OPC_6502_44, // $44
OPC_6502_45, OPC_6502_45,
OPC_6502_46, OPC_6502_46,
OPC_Illegal, // $47: RMB4 currently unsupported OPC_65C02_47,
OPC_6502_48, OPC_6502_48,
OPC_6502_49, OPC_6502_49,
OPC_6502_4A, OPC_6502_4A,
@@ -4095,7 +4477,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_4C, OPC_6502_4C,
OPC_6502_4D, OPC_6502_4D,
OPC_6502_4E, OPC_6502_4E,
OPC_Illegal, // $4F: BBR4 currently unsupported OPC_65C02_4F,
OPC_6502_50, OPC_6502_50,
OPC_6502_51, OPC_6502_51,
OPC_65SC02_52, OPC_65SC02_52,
@@ -4103,7 +4485,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_NOP24, // $54 OPC_65C02_NOP24, // $54
OPC_6502_55, OPC_6502_55,
OPC_6502_56, OPC_6502_56,
OPC_Illegal, // $57: RMB5 currently unsupported OPC_65C02_57,
OPC_6502_58, OPC_6502_58,
OPC_6502_59, OPC_6502_59,
OPC_65SC02_5A, OPC_65SC02_5A,
@@ -4111,7 +4493,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_5C, OPC_65C02_5C,
OPC_6502_5D, OPC_6502_5D,
OPC_65C02_5E, OPC_65C02_5E,
OPC_Illegal, // $5F: BBR5 currently unsupported OPC_65C02_5F,
OPC_6502_60, OPC_6502_60,
OPC_65C02_61, OPC_65C02_61,
OPC_65C02_NOP22, // $62 OPC_65C02_NOP22, // $62
@@ -4119,7 +4501,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_64, OPC_65SC02_64,
OPC_65C02_65, OPC_65C02_65,
OPC_6502_66, OPC_6502_66,
OPC_Illegal, // $67: RMB6 currently unsupported OPC_65C02_67,
OPC_6502_68, OPC_6502_68,
OPC_65C02_69, OPC_65C02_69,
OPC_6502_6A, OPC_6502_6A,
@@ -4127,7 +4509,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_6C, OPC_65C02_6C,
OPC_65C02_6D, OPC_65C02_6D,
OPC_6502_6E, OPC_6502_6E,
OPC_Illegal, // $6F: BBR6 currently unsupported OPC_65C02_6F,
OPC_6502_70, OPC_6502_70,
OPC_65C02_71, OPC_65C02_71,
OPC_65C02_72, OPC_65C02_72,
@@ -4135,7 +4517,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_74, OPC_65SC02_74,
OPC_65C02_75, OPC_65C02_75,
OPC_6502_76, OPC_6502_76,
OPC_Illegal, // $77: RMB7 currently unsupported OPC_65C02_77,
OPC_6502_78, OPC_6502_78,
OPC_65C02_79, OPC_65C02_79,
OPC_65SC02_7A, OPC_65SC02_7A,
@@ -4143,7 +4525,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_7C, OPC_65SC02_7C,
OPC_65C02_7D, OPC_65C02_7D,
OPC_65C02_7E, OPC_65C02_7E,
OPC_Illegal, // $7F: BBR7 currently unsupported OPC_65C02_7F,
OPC_65SC02_80, OPC_65SC02_80,
OPC_6502_81, OPC_6502_81,
OPC_65C02_NOP22, // $82 OPC_65C02_NOP22, // $82
@@ -4151,7 +4533,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_84, OPC_6502_84,
OPC_6502_85, OPC_6502_85,
OPC_6502_86, OPC_6502_86,
OPC_Illegal, // $87: SMB0 currently unsupported OPC_65C02_87,
OPC_6502_88, OPC_6502_88,
OPC_65SC02_89, OPC_65SC02_89,
OPC_6502_8A, OPC_6502_8A,
@@ -4159,7 +4541,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_8C, OPC_6502_8C,
OPC_6502_8D, OPC_6502_8D,
OPC_6502_8E, OPC_6502_8E,
OPC_Illegal, // $8F: BBS0 currently unsupported OPC_65C02_8F,
OPC_6502_90, OPC_6502_90,
OPC_6502_91, OPC_6502_91,
OPC_65SC02_92, OPC_65SC02_92,
@@ -4167,7 +4549,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_94, OPC_6502_94,
OPC_6502_95, OPC_6502_95,
OPC_6502_96, OPC_6502_96,
OPC_Illegal, // $97: SMB1 currently unsupported OPC_65C02_97,
OPC_6502_98, OPC_6502_98,
OPC_6502_99, OPC_6502_99,
OPC_6502_9A, OPC_6502_9A,
@@ -4175,7 +4557,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65SC02_9C, OPC_65SC02_9C,
OPC_6502_9D, OPC_6502_9D,
OPC_65SC02_9E, OPC_65SC02_9E,
OPC_Illegal, // $9F: BBS1 currently unsupported OPC_65C02_9F,
OPC_6502_A0, OPC_6502_A0,
OPC_6502_A1, OPC_6502_A1,
OPC_6502_A2, OPC_6502_A2,
@@ -4183,7 +4565,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_A4, OPC_6502_A4,
OPC_6502_A5, OPC_6502_A5,
OPC_6502_A6, OPC_6502_A6,
OPC_Illegal, // $A7: SMB2 currently unsupported OPC_65C02_A7,
OPC_6502_A8, OPC_6502_A8,
OPC_6502_A9, OPC_6502_A9,
OPC_6502_AA, OPC_6502_AA,
@@ -4191,7 +4573,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_AC, OPC_6502_AC,
OPC_6502_AD, OPC_6502_AD,
OPC_6502_AE, OPC_6502_AE,
OPC_Illegal, // $AF: BBS2 currently unsupported OPC_65C02_AF,
OPC_6502_B0, OPC_6502_B0,
OPC_6502_B1, OPC_6502_B1,
OPC_65SC02_B2, OPC_65SC02_B2,
@@ -4199,7 +4581,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_B4, OPC_6502_B4,
OPC_6502_B5, OPC_6502_B5,
OPC_6502_B6, OPC_6502_B6,
OPC_Illegal, // $B7: SMB3 currently unsupported OPC_65C02_B7,
OPC_6502_B8, OPC_6502_B8,
OPC_6502_B9, OPC_6502_B9,
OPC_6502_BA, OPC_6502_BA,
@@ -4207,7 +4589,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_BC, OPC_6502_BC,
OPC_6502_BD, OPC_6502_BD,
OPC_6502_BE, OPC_6502_BE,
OPC_Illegal, // $BF: BBS3 currently unsupported OPC_65C02_BF,
OPC_6502_C0, OPC_6502_C0,
OPC_6502_C1, OPC_6502_C1,
OPC_65C02_NOP22, // $C2 OPC_65C02_NOP22, // $C2
@@ -4215,7 +4597,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_C4, OPC_6502_C4,
OPC_6502_C5, OPC_6502_C5,
OPC_6502_C6, OPC_6502_C6,
OPC_Illegal, // $C7: SMB4 currently unsupported OPC_65C02_C7,
OPC_6502_C8, OPC_6502_C8,
OPC_6502_C9, OPC_6502_C9,
OPC_6502_CA, OPC_6502_CA,
@@ -4223,7 +4605,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_CC, OPC_6502_CC,
OPC_6502_CD, OPC_6502_CD,
OPC_6502_CE, OPC_6502_CE,
OPC_Illegal, // $CF: BBS4 currently unsupported OPC_65C02_CF,
OPC_6502_D0, OPC_6502_D0,
OPC_6502_D1, OPC_6502_D1,
OPC_65SC02_D2, OPC_65SC02_D2,
@@ -4231,7 +4613,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_NOP24, // $D4 OPC_65C02_NOP24, // $D4
OPC_6502_D5, OPC_6502_D5,
OPC_6502_D6, OPC_6502_D6,
OPC_Illegal, // $D7: SMB5 currently unsupported OPC_65C02_D7,
OPC_6502_D8, OPC_6502_D8,
OPC_6502_D9, OPC_6502_D9,
OPC_65SC02_DA, OPC_65SC02_DA,
@@ -4239,7 +4621,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_NOP34, // $DC OPC_65C02_NOP34, // $DC
OPC_6502_DD, OPC_6502_DD,
OPC_6502_DE, OPC_6502_DE,
OPC_Illegal, // $DF: BBS5 currently unsupported OPC_65C02_DF,
OPC_6502_E0, OPC_6502_E0,
OPC_65C02_E1, OPC_65C02_E1,
OPC_65C02_NOP22, // $E2 OPC_65C02_NOP22, // $E2
@@ -4247,7 +4629,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_E4, OPC_6502_E4,
OPC_65C02_E5, OPC_65C02_E5,
OPC_6502_E6, OPC_6502_E6,
OPC_Illegal, // $E7: SMB6 currently unsupported OPC_65C02_E7,
OPC_6502_E8, OPC_6502_E8,
OPC_65C02_E9, OPC_65C02_E9,
OPC_6502_EA, OPC_6502_EA,
@@ -4255,7 +4637,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_6502_EC, OPC_6502_EC,
OPC_65C02_ED, OPC_65C02_ED,
OPC_6502_EE, OPC_6502_EE,
OPC_Illegal, // $EF: BBS6 currently unsupported OPC_65C02_EF,
OPC_6502_F0, OPC_6502_F0,
OPC_65C02_F1, OPC_65C02_F1,
OPC_65C02_F2, OPC_65C02_F2,
@@ -4263,7 +4645,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_NOP24, // $F4 OPC_65C02_NOP24, // $F4
OPC_65C02_F5, OPC_65C02_F5,
OPC_6502_F6, OPC_6502_F6,
OPC_Illegal, // $F7: SMB7 currently unsupported OPC_65C02_F7,
OPC_6502_F8, OPC_6502_F8,
OPC_65C02_F9, OPC_65C02_F9,
OPC_65SC02_FA, OPC_65SC02_FA,
@@ -4271,7 +4653,7 @@ static const OPFunc OP65C02Table[256] = {
OPC_65C02_NOP34, // $FC OPC_65C02_NOP34, // $FC
OPC_65C02_FD, OPC_65C02_FD,
OPC_6502_FE, OPC_6502_FE,
OPC_Illegal, // $FF: BBS7 currently unsupported OPC_65C02_FF
}; };

View File

@@ -37,6 +37,8 @@
#define _6502_H #define _6502_H
#include <stdint.h>
/*****************************************************************************/ /*****************************************************************************/
/* Data */ /* Data */
@@ -57,12 +59,12 @@ extern CPUType CPU;
/* 6502 CPU registers */ /* 6502 CPU registers */
typedef struct CPURegs CPURegs; typedef struct CPURegs CPURegs;
struct CPURegs { struct CPURegs {
unsigned AC; /* Accumulator */ uint8_t AC; /* Accumulator */
unsigned XR; /* X register */ uint8_t XR; /* X register */
unsigned YR; /* Y register */ uint8_t YR; /* Y register */
unsigned SR; /* Status register */ uint8_t SR; /* Status register */
unsigned SP; /* Stackpointer */ uint8_t SP; /* Stackpointer */
unsigned PC; /* Program counter */ uint16_t PC; /* Program counter */
}; };
/* Current CPU registers */ /* Current CPU registers */