strik wrote:
@drogon, are you aware that your union and its usage assumes a little endian machine on which this code is running?
The rest is left as an exercise to the user.
-Gordon
Code: Select all
// Macro to handle the Z and N Flags
#define SETNZ(val) writeflag(CPU, N_FL, (val) & 128U); writeflag(CPU, Z_FL, !(val))
uint16_t tmp16; // Temporary Result
uint8_t tmpin; // Input value (from Memory)
tmp16 = (uint16_t)A + tmpin + (readflag(CPU, C_FL) ? 1 : 0); // Add A, the input value, and the carry together
writeflag(CPU, C_FL, tmp16 >> 8); // Set the carry if the upper byte of tmp16 is not 0
writeflag(CPU, V_FL, ((~(A ^ tmpin)) & (A ^ tmp16)) & 0x80); // Set the V Flag (no idea what this does but it works, so thanks drogon!)
A = (uint8_t)tmp16; // put the low byte of tmp16 into A
SETNZ(A); // And set the Z and N Flags accordinglyCode: Select all
def isneg(b, signbit=7):
sign = b & (1 << signbit)
return 0 != sign
def iszero(b):
return b == 0
def incbyte(byte, addend):
''' Return 8-bit `byte` incremented by `addend` (which may be negative).
This returns an 8-bit unsigned result, wrapping at $FF/$00.
'''
return (byte + addend) & 0xFF
def add(m, augend, addend, carry=0):
''' Return the modular 8-bit sum of adding `addend` (the operand) and
`carry` to `augend` (the contents of the register). Set H, N, Z, V
and C flags based on the result, per pages A-4 (ADC) and A-5 (ADD)
in the PRG.
'''
sum = incbyte(augend, addend)
sum = incbyte(sum, carry)
m.N = isneg(sum)
m.Z = iszero(sum)
bit7 = 0b10000000; bit3 = 0b1000
x7 = bool(augend & bit7); x3 = bool(augend & bit3)
m7 = bool(addend & bit7); m3 = bool(addend & bit3)
r7 = bool(sum & bit7); r3 = bool(sum & bit3)
# The following is copied directly from PRG pages A-4 and A-5.
m.C = x7 and m7 or m7 and not r7 or not r7 and x7
m.H = x3 and m3 or m3 and not r3 or not r3 and x3
m.V = x7 and m7 and not r7 or not x7 and not m7 and r7
return sum
Code: Select all
def adda(m): m.a = add(m, m.a, readbyte(m))
def addaz(m): m.a = add(m, m.a, m.mem[readbyte(m)])
def addam(m): m.a = add(m, m.a, m.mem[readword(m)])
def addax(m): m.a = add(m, m.a, m.mem[readindex(m)])
def addb(m): m.b = add(m, m.b, readbyte(m))
def addbz(m): m.b = add(m, m.b, m.mem[readbyte(m)])
def addbm(m): m.b = add(m, m.b, m.mem[readword(m)])
def addbx(m): m.b = add(m, m.b, m.mem[readindex(m)])
def adca(m): m.a = add(m, m.a, readbyte(m), m.C)
...
Code: Select all
ADDtests = (
'arg0, arg1, res, H, N, Z, V, C',
(0x00, 0x00, 0x00, 0, 0, 1, 0, 0),
(0x00, 0xFF, 0xFF, 0, 1, 0, 0, 0),
# H: half carry determined by bits 3
(0x0E, 0x01, 0x0F, 0, 0, 0, 0, 0),
(0x0F, 0x01, 0x10, 1, 0, 0, 0, 0),
(0x10, 0x01, 0x11, 0, 0, 0, 0, 0),
# V: overflow determined by bits 6
(0x7E, 0x01, 0x7F, 0, 0, 0, 0, 0),
(0x7F, 0x01, 0x80, 1, 1, 0, 1, 0),
(0x80, 0x01, 0x81, 0, 1, 0, 0, 0),
# C: carry determined by bits 7
(0xFE, 0x01, 0xFF, 0, 1, 0, 0, 0),
(0xFF, 0x01, 0x00, 1, 0, 1, 0, 1),
(0xF0, 0x20, 0x10, 0, 0, 0, 0, 1), # no half carry
# C and V
(0x40, 0xF0, 0x30, 0, 0, 0, 0, 1), # 2's comp: subtract from positive
(0xF0, 0xF0, 0xE0, 0, 1, 0, 0, 1), # 2's comp: subtract from negative
(0x80, 0x80, 0x00, 0, 0, 1, 1, 1),
)
@tc(*ADDtests)
def test_ADD_C0(arg0, arg1, res, H, N, Z, V, C):
runbinary('ADD', arg0, arg1, res, N, Z, V, C, H=H, inflags=R(C=0))
@tc(*ADDtests)
def test_ADD_C1(arg0, arg1, res, H, N, Z, V, C):
runbinary('ADD', arg0, arg1, res, N, Z, V, C, H=H, inflags=R(C=1))
@tc(*ADDtests)
def test_ADC_C0(arg0, arg1, res, H, N, Z, V, C):
runbinary('ADC', arg0, arg1, res, N, Z, V, C, H=H, inflags=R(C=0))