Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions src/cpu/65816-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ void i_adc(CPU_t *cpu, memory_t *mem, uint8_t size, uint8_t cycles, CPU_Addr_Mod
else // Binary mode
{
al = (cpu->C & 0xff) + val + cpu->P.C;
cpu->P.V = ((int16_t)al < -128 || (int16_t)al > 127) ? 1 : 0;
// V flag: check if signed result overflows 8-bit signed range
// Must sign-extend operands before computing to get correct signed result
int16_t signed_al = (int8_t)(cpu->C & 0xff) + (int8_t)val + cpu->P.C;
cpu->P.V = (signed_al < -128 || signed_al > 127) ? 1 : 0;
}

// 1f
Expand Down Expand Up @@ -93,7 +96,10 @@ void i_adc(CPU_t *cpu, memory_t *mem, uint8_t size, uint8_t cycles, CPU_Addr_Mod
else
{
al = cpu->C + val + cpu->P.C;
cpu->P.V = ((int32_t)al < -32768 || (int32_t)al > 32767) ? 1 : 0;
// V flag: check if signed result overflows 16-bit signed range
// Must sign-extend operands before computing to get correct signed result
int32_t signed_al = (int16_t)cpu->C + (int16_t)val + cpu->P.C;
cpu->P.V = (signed_al < -32768 || signed_al > 32767) ? 1 : 0;
}
// 1f
cpu->C = al & 0xffff;
Expand Down Expand Up @@ -2266,6 +2272,8 @@ void i_sbc(CPU_t *cpu, memory_t *mem, uint8_t size, uint8_t cycles, CPU_Addr_Mod
{
uint8_t val = _get_mem_byte(mem, addr, cpu->setacc);
uint16_t al, alb;
uint8_t original_a = cpu->C & 0xff; // Save original A for carry calculation
uint8_t original_c = cpu->P.C; // Save original carry for carry calculation

// Binary mode calculation
alb = (cpu->C & 0xff) - val + cpu->P.C - 1;
Expand Down Expand Up @@ -2299,15 +2307,24 @@ void i_sbc(CPU_t *cpu, memory_t *mem, uint8_t size, uint8_t cycles, CPU_Addr_Mod
cpu->P.Z = ((al & 0xff) == 0) ? 1 : 0;

// C and V are based on the binary result
cpu->P.V = ((int16_t)alb < -128 || (int16_t)alb > 127) ? 1 : 0;
cpu->P.C = (alb >= 0x100) ? 1 : 0;
// V flag: check if signed result overflows 8-bit signed range
// Must sign-extend operands before computing to get correct signed result
{
int16_t signed_alb = (int8_t)original_a - (int8_t)val + original_c - 1;
cpu->P.V = (signed_alb < -128 || signed_alb > 127) ? 1 : 0;
}
// For SBC, carry is set if no borrow occurred: A >= M + (1 - C_in)
// Using original values saved at start of function
cpu->P.C = ((uint16_t)original_a + original_c > val) ? 1 : 0;

}
else // 16-bit
{
uint16_t val;
uint32_t al, alb;

uint16_t original_a = cpu->C; // Save original A for carry calculation
uint8_t original_c = cpu->P.C; // Save original carry for carry calculation

if (mode == CPU_ADDR_DP || mode == CPU_ADDR_DPX ||
mode == CPU_ADDR_IMMD || mode == CPU_ADDR_SR)
{
Expand Down Expand Up @@ -2364,8 +2381,15 @@ void i_sbc(CPU_t *cpu, memory_t *mem, uint8_t size, uint8_t cycles, CPU_Addr_Mod
cpu->P.Z = ((al & 0xffff) == 0) ? 1 : 0;

// C and V are based on the binary result
cpu->P.V = ((int32_t)alb < -32768 || (int32_t)alb > 32767) ? 1 : 0;
cpu->P.C = (alb >= 0x10000) ? 1 : 0;
// V flag: check if signed result overflows 16-bit signed range
// Must sign-extend operands before computing to get correct signed result
{
int32_t signed_alb = (int16_t)original_a - (int16_t)val + original_c - 1;
cpu->P.V = (signed_alb < -32768 || signed_alb > 32767) ? 1 : 0;
}
// For SBC, carry is set if no borrow occurred: A >= M + (1 - C_in)
// Using original values saved at start of function
cpu->P.C = ((uint32_t)original_a + original_c > val) ? 1 : 0;

cpu->cycles += 1;
if (mode == CPU_ADDR_IMMD)
Expand Down