#!/usr/bin/env python
|
#!/usr/bin/env python3
|
#
|
#
|
# This script simulates 'sbc' calculation and generates values for selected numbers.
|
# This script simulates 'sbc' calculation and generates values for selected numbers.
|
# These can be compared with a real Z80 run values.
|
# These can be compared with a real Z80 run values.
|
#
|
#
|
import sys
|
import sys
|
|
|
def printFlags(f):
|
def printFlags(f):
|
s = ''
|
s = ''
|
if f & (1 << 7):
|
if f & (1 << 7):
|
s += 'S'
|
s += 'S'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 6):
|
if f & (1 << 6):
|
s += 'Z'
|
s += 'Z'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 5):
|
if f & (1 << 5):
|
s += 'Y'
|
s += 'Y'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 4):
|
if f & (1 << 4):
|
s += 'H'
|
s += 'H'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 3):
|
if f & (1 << 3):
|
s += 'X'
|
s += 'X'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 2):
|
if f & (1 << 2):
|
s += 'P'
|
s += 'P'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 1):
|
if f & (1 << 1):
|
s += 'V'
|
s += 'V'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
if f & (1 << 0):
|
if f & (1 << 0):
|
s += 'C'
|
s += 'C'
|
else:
|
else:
|
s += ' '
|
s += ' '
|
print 'Flags = %s' % s
|
print ('Flags = %s' % s)
|
|
|
def sbc(inA, op2, CYin):
|
def sbc(inA, op2, CYin):
|
print '------------------------------------------'
|
print ('------------------------------------------')
|
print 'Input: %0.2X SBC %0.2X CY = %0.2X' % ( inA, op2, CYin)
|
print ('Input: %0.2X SBC %0.2X CY = %0.2X' % ( inA, op2, CYin))
|
|
|
double_cpl = 0 # Flag that we did a double 1's complement
|
double_cpl = 0 # Flag that we did a double 1's complement
|
cplOp2 = op2 ^ 0xFF # Bit-wise complement of OP2
|
cplOp2 = op2 ^ 0xFF # Bit-wise complement of OP2
|
|
|
if CYin: # If CF was set, we'll also use complemented ACCT
|
if CYin: # If CF was set, we'll also use complemented ACCT
|
double_cpl = 1
|
double_cpl = 1
|
cplA = inA ^ 0xFF
|
cplA = inA ^ 0xFF
|
finalA = cplA + cplOp2 + CYin
|
finalA = cplA + cplOp2 + CYin
|
carry_ins = finalA ^ cplA ^ cplOp2 # Bitfield of all internal carry-ins
|
carry_ins = finalA ^ cplA ^ cplOp2 # Bitfield of all internal carry-ins
|
else: # Otherwise, set CF to act as '+1' in NEG
|
else: # Otherwise, set CF to act as '+1' in NEG
|
CYin = 1
|
CYin = 1
|
finalA = inA + cplOp2 + CYin
|
finalA = inA + cplOp2 + CYin
|
carry_ins = finalA ^ inA ^ cplOp2 # Bitfield of all internal carry-ins
|
carry_ins = finalA ^ inA ^ cplOp2 # Bitfield of all internal carry-ins
|
carry_ins ^= 0xFF
|
carry_ins ^= 0xFF
|
|
|
# Calculate CF while we have bit [9] available
|
# Calculate CF while we have bit [9] available
|
cf = 0
|
cf = 0
|
if finalA > 255 or finalA < 0:
|
if finalA > 255 or finalA < 0:
|
cf = 1
|
cf = 1
|
|
|
cf ^= 1 # Complement CY since we used cpl(A) and not A
|
cf ^= 1 # Complement CY since we used cpl(A) and not A
|
if double_cpl:
|
if double_cpl:
|
cf ^= 1
|
cf ^= 1
|
|
|
nf = 1 # 1 for SUB operation
|
nf = 1 # 1 for SUB operation
|
|
|
finalA = finalA & 0xFF # Clamp final value to 8 bits
|
finalA = finalA & 0xFF # Clamp final value to 8 bits
|
|
|
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
# Flag calculation: SF, ZF, YF, HF, XF, VF/PF, NF, CF
|
# Flag calculation: SF, ZF, YF, HF, XF, VF/PF, NF, CF
|
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
# Carry and Overflow calculation on Z80 require us to use internal carry-ins
|
# Carry and Overflow calculation on Z80 require us to use internal carry-ins
|
# http://stackoverflow.com/questions/8034566/overflow-and-carry-flags-on-z80
|
# http://stackoverflow.com/questions/8034566/overflow-and-carry-flags-on-z80
|
#carry_ins = finalA ^ inA ^ op2 # Bitfield of all internal carry-ins
|
#carry_ins = finalA ^ inA ^ op2 # Bitfield of all internal carry-ins
|
|
|
sf = (finalA>>7) & 1 # SF = Copy of [7]
|
sf = (finalA>>7) & 1 # SF = Copy of [7]
|
zf = finalA==0 # ZF = Set if all result bits are zero
|
zf = finalA==0 # ZF = Set if all result bits are zero
|
yf = (finalA>>5) & 1 # YF = Copy of [5]
|
yf = (finalA>>5) & 1 # YF = Copy of [5]
|
hf = (carry_ins>>4)&1 # HF = Internal carry from bit [3] to [4]
|
hf = (carry_ins>>4)&1 # HF = Internal carry from bit [3] to [4]
|
xf = (finalA>>3) & 1 # XF = Copy of [3]
|
xf = (finalA>>3) & 1 # XF = Copy of [3]
|
# # PF = XOR all final bits to get odd parity value
|
# # PF = XOR all final bits to get odd parity value
|
pf = (((finalA>>7)^(finalA>>6)^(finalA>>5)^(finalA>>4)^(finalA>>3)^(finalA>>2)^(finalA>>1)^(finalA>>0))&1)^1
|
pf = (((finalA>>7)^(finalA>>6)^(finalA>>5)^(finalA>>4)^(finalA>>3)^(finalA>>2)^(finalA>>1)^(finalA>>0))&1)^1
|
vf = (carry_ins>>7)&1 # VF = Internal carry from bit [6] to [7]
|
vf = (carry_ins>>7)&1 # VF = Internal carry from bit [6] to [7]
|
vf ^= cf # XOR'ed with the final carry out
|
vf ^= cf # XOR'ed with the final carry out
|
|
|
flags = (sf<<7) | (zf<<6) | (yf<<5) | (hf<<4) | (xf<<3) | (vf<<2) | (nf<<1) | (cf<<0)
|
flags = (sf<<7) | (zf<<6) | (yf<<5) | (hf<<4) | (xf<<3) | (vf<<2) | (nf<<1) | (cf<<0)
|
|
|
print 'Out: A -> %0.2X Flags = %0.2X' % ( finalA, flags)
|
print ('Out: A -> %0.2X Flags = %0.2X' % ( finalA, flags))
|
printFlags(flags)
|
printFlags(flags)
|
|
|
sbc(0, 0, 0)
|
sbc(0, 0, 0)
|
print 'Should be A -> 00 Flags = 42'
|
print ('Should be A -> 00 Flags = 42')
|
printFlags(0x42)
|
printFlags(0x42)
|
sbc(0, 1, 0)
|
sbc(0, 1, 0)
|
print 'Should be A -> FF Flags = BB'
|
print ('Should be A -> FF Flags = BB')
|
printFlags(0xBB)
|
printFlags(0xBB)
|
|
|
sbc(0, 0, 1)
|
sbc(0, 0, 1)
|
print 'Should be A -> FF Flags = BB'
|
print ('Should be A -> FF Flags = BB')
|
printFlags(0xBB)
|
printFlags(0xBB)
|
sbc(0, 1, 1)
|
sbc(0, 1, 1)
|
print 'Should be A -> FE Flags = BB'
|
print ('Should be A -> FE Flags = BB')
|
printFlags(0xBB)
|
printFlags(0xBB)
|
|
|
sbc(0xAA, 0x55, 0)
|
sbc(0xAA, 0x55, 0)
|
print 'Should be A -> 55 Flags = 06'
|
print ('Should be A -> 55 Flags = 06')
|
printFlags(0x06)
|
printFlags(0x06)
|
sbc(0x55, 0xAA, 0)
|
sbc(0x55, 0xAA, 0)
|
print 'Should be A -> AB Flags = BF'
|
print ('Should be A -> AB Flags = BF')
|
printFlags(0xBF)
|
printFlags(0xBF)
|
|
|
sbc(0xAA, 0x55, 1)
|
sbc(0xAA, 0x55, 1)
|
print 'Should be A -> 54 Flags = 06'
|
print ('Should be A -> 54 Flags = 06')
|
printFlags(0x06)
|
printFlags(0x06)
|
sbc(0x55, 0xAA, 1)
|
sbc(0x55, 0xAA, 1)
|
print 'Should be A -> AA Flags = BF'
|
print ('Should be A -> AA Flags = BF')
|
printFlags(0xBF)
|
printFlags(0xBF)
|
|
|
sbc(0x0F, 0x03, 1)
|
sbc(0x0F, 0x03, 1)
|
print 'Should be A -> 0B Flags = 0A'
|
print ('Should be A -> 0B Flags = 0A')
|
printFlags(0x0A)
|
printFlags(0x0A)
|
|
|