mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-21 18:29:45 +00:00
Fixed ADC and SBC in decimal mode. All tests pass.
This commit is contained in:
parent
f43150c93c
commit
8bd489522f
63
execute.go
63
execute.go
@ -221,43 +221,58 @@ func buildOpLogic(operation func(uint8, uint8) uint8) opFunc {
|
||||
|
||||
func opADC(s *state, line []uint8, opcode opcode) {
|
||||
value, _, _ := resolve(s, line, opcode)
|
||||
if s.registers.getFlag(flagD) {
|
||||
// TODO BCD. See http://www.6502.org/tutorials/decimal_mode.html
|
||||
panic("BCD not supported")
|
||||
} else {
|
||||
total := uint16(s.registers.getA()) +
|
||||
uint16(value) +
|
||||
uint16(s.registers.getFlagBit(flagC))
|
||||
signedTotal := int16(int8(s.registers.getA())) +
|
||||
int16(int8(value)) +
|
||||
int16(s.registers.getFlagBit(flagC))
|
||||
truncated := uint8(total)
|
||||
aValue := s.registers.getA()
|
||||
carry := s.registers.getFlagBit(flagC)
|
||||
|
||||
total := uint16(aValue) + uint16(value) + uint16(carry)
|
||||
signedTotal := int16(int8(aValue)) + int16(int8(value)) + int16(carry)
|
||||
truncated := uint8(total)
|
||||
|
||||
if s.registers.getFlag(flagD) {
|
||||
totalBcdLo := int(aValue&0x0f) + int(value&0x0f) + int(carry)
|
||||
totalBcdHi := int(aValue>>4) + int(value>>4)
|
||||
if totalBcdLo >= 10 {
|
||||
totalBcdHi++
|
||||
}
|
||||
totalBcd := (totalBcdHi%10)<<4 + (totalBcdLo % 10)
|
||||
s.registers.setA(uint8(totalBcd))
|
||||
s.registers.updateFlag(flagC, totalBcdHi > 9)
|
||||
} else {
|
||||
s.registers.setA(truncated)
|
||||
s.registers.updateFlagZN(truncated)
|
||||
s.registers.updateFlag(flagC, total > 0xFF)
|
||||
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
|
||||
}
|
||||
|
||||
// ZNV flags behave for BCD as if the operation was binary?
|
||||
s.registers.updateFlagZN(truncated)
|
||||
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
|
||||
}
|
||||
|
||||
func opSBC(s *state, line []uint8, opcode opcode) {
|
||||
value, _, _ := resolve(s, line, opcode)
|
||||
aValue := s.registers.getA()
|
||||
carry := s.registers.getFlagBit(flagC)
|
||||
|
||||
total := 0x100 + uint16(aValue) - uint16(value) + uint16(carry) - 1
|
||||
signedTotal := int16(int8(aValue)) - int16(int8(value)) + int16(carry) - 1
|
||||
truncated := uint8(total)
|
||||
|
||||
if s.registers.getFlag(flagD) {
|
||||
// TODO BCD
|
||||
panic("BCD not supported")
|
||||
totalBcdLo := 10 + int(aValue&0x0f) - int(value&0x0f) + int(carry) - 1
|
||||
totalBcdHi := 10 + int(aValue>>4) - int(value>>4)
|
||||
if totalBcdLo < 10 {
|
||||
totalBcdHi--
|
||||
}
|
||||
totalBcd := (totalBcdHi%10)<<4 + (totalBcdLo % 10)
|
||||
s.registers.setA(uint8(totalBcd))
|
||||
s.registers.updateFlag(flagC, totalBcdHi >= 10)
|
||||
} else {
|
||||
total := 0x100 + uint16(s.registers.getA()) -
|
||||
uint16(value) +
|
||||
uint16(s.registers.getFlagBit(flagC)) - 1
|
||||
signedTotal := int16(int8(s.registers.getA())) -
|
||||
int16(int8(value)) +
|
||||
int16(s.registers.getFlagBit(flagC)) - 1
|
||||
truncated := uint8(total)
|
||||
s.registers.setA(truncated)
|
||||
s.registers.updateFlagZN(truncated)
|
||||
s.registers.updateFlag(flagC, total > 0xFF)
|
||||
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
|
||||
}
|
||||
|
||||
// ZNV flags behave for SBC as if the operation was binary
|
||||
s.registers.updateFlagZN(truncated)
|
||||
s.registers.updateFlag(flagV, signedTotal < -128 || signedTotal > 127)
|
||||
}
|
||||
|
||||
const stackAddress uint16 = 0x0100
|
||||
|
@ -268,30 +268,65 @@ func TestAdd(t *testing.T) {
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x0B})
|
||||
if s.registers.getA() != 0xAB {
|
||||
t.Errorf("Error in ADC A0 + 0B. %v", s.registers)
|
||||
t.Errorf("Error in ADC. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry ADC A0 + 0B. %v", s.registers)
|
||||
t.Errorf("Error in carry ADC. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0xFF)
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x02})
|
||||
if s.registers.getA() != 0x01 {
|
||||
t.Errorf("Error in ADC A0 + 0B with carry. %v", s.registers)
|
||||
t.Errorf("Error in ADC with carry. %v", s.registers)
|
||||
}
|
||||
if !s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry ADC A0 + 0B with carry. %v", s.registers)
|
||||
t.Errorf("Error in carry ADC with carry. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0xA0)
|
||||
s.registers.setFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x01})
|
||||
if s.registers.getA() != 0xA2 {
|
||||
t.Errorf("Error in ADC C + A0 + 0B with carry. %v", s.registers)
|
||||
t.Errorf("Error in carried ADC with carry. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry ADC C + A0 + 0B with carry. %v", s.registers)
|
||||
t.Errorf("Error in carry in carried ADC with carry. %v", s.registers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddDecimal(t *testing.T) {
|
||||
var s state
|
||||
s.registers.setFlag(flagD)
|
||||
|
||||
s.registers.setA(0x12)
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x013})
|
||||
if s.registers.getA() != 0x25 {
|
||||
t.Errorf("Error in ADC decimal. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry ADC. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0x44)
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x68})
|
||||
if s.registers.getA() != 0x12 {
|
||||
t.Errorf("Error in ADC decimal with carry. %v", s.registers)
|
||||
}
|
||||
if !s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry ADC decimal with carry. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0x44)
|
||||
s.registers.setFlag(flagC)
|
||||
executeLine(&s, []uint8{0x69, 0x23})
|
||||
if s.registers.getA() != 0x68 {
|
||||
t.Errorf("Error in carried ADC decimal with carry. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry in carried ADC decimal with carry. %v", s.registers)
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,31 +336,31 @@ func TestSub(t *testing.T) {
|
||||
s.registers.setA(0x09)
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0xE9, 0x05})
|
||||
if s.registers.getA() != 0x04 {
|
||||
t.Errorf("Error in SBC A0 + 0B. %v", s.registers)
|
||||
if s.registers.getA() != 0x03 {
|
||||
t.Errorf("Error in SBC. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry SBC A0 + 0B. %v", s.registers)
|
||||
if !s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry SBC. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0x01)
|
||||
s.registers.clearFlag(flagC)
|
||||
executeLine(&s, []uint8{0xE9, 0x02})
|
||||
if s.registers.getA() != 0xFF {
|
||||
t.Errorf("Error in SBC A0 + 0B with carry. %v", s.registers)
|
||||
if s.registers.getA() != 0xFE {
|
||||
t.Errorf("Error in SBC with carry. %v", s.registers)
|
||||
}
|
||||
if !s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry SBC A0 + 0B with carry. %v", s.registers)
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry SBC with carry. %v", s.registers)
|
||||
}
|
||||
|
||||
s.registers.setA(0x08)
|
||||
s.registers.setFlag(flagC)
|
||||
executeLine(&s, []uint8{0xE9, 0x02})
|
||||
if s.registers.getA() != 0x05 {
|
||||
t.Errorf("Error in SBC C + A0 + 0B with carry. %v", s.registers)
|
||||
if s.registers.getA() != 0x06 {
|
||||
t.Errorf("Error in carried SBC with carry. %v", s.registers)
|
||||
}
|
||||
if s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry SBC C + A0 + 0B with carry. %v", s.registers)
|
||||
if !s.registers.getFlag(flagC) {
|
||||
t.Errorf("Error in carry in carried SBC with carry. %v", s.registers)
|
||||
}
|
||||
|
||||
}
|
||||
|
29
main.go
29
main.go
@ -8,19 +8,22 @@ func main() {
|
||||
|
||||
s.registers.setPC(0x0400)
|
||||
for true {
|
||||
for i := 0; i < 20; i++ {
|
||||
testCase := s.memory[0x0200]
|
||||
log := testCase > 41
|
||||
if log {
|
||||
fmt.Printf("[ %d ] ", testCase)
|
||||
}
|
||||
pc := s.registers.getPC()
|
||||
executeInstruction(&s, log)
|
||||
if pc == s.registers.getPC() {
|
||||
s.memory.printPage(0x00)
|
||||
//s.memory.printPage(0x01)
|
||||
panic("No change in PC")
|
||||
}
|
||||
testCase := s.memory[0x0200]
|
||||
if testCase >= 240 {
|
||||
break
|
||||
}
|
||||
log := testCase > 43
|
||||
if log {
|
||||
fmt.Printf("[ %d ] ", testCase)
|
||||
}
|
||||
pc := s.registers.getPC()
|
||||
executeInstruction(&s, log)
|
||||
if pc == s.registers.getPC() {
|
||||
//s.memory.printPage(0x00)
|
||||
//s.memory.printPage(0x01)
|
||||
panic("No change in PC")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Test completed\n")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user