unit test

This commit is contained in:
Irmen de Jong 2019-09-04 02:41:09 +02:00
parent 8d6542905d
commit bed0e33b4f
5 changed files with 319 additions and 21 deletions

View File

@ -15,10 +15,12 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="kotlinx-cli-jvm-0.1.0-dev-5" level="project" />
<orderEntry type="library" name="unittest-libs" level="project" />
</component>
</module>

View File

@ -65,8 +65,8 @@ private fun startSimulator(args: Array<String>) {
bus.reset()
ram.load("sim65/ram.bin", 0x8000)
ram.load("sim65/bcdtest.bin", 0x1000)
ram.load("sim65/test/testfiles/ram.bin", 0x8000)
ram.load("sim65/test/testfiles/bcdtest.bin", 0x1000)
//ram.dump(0x8000, 0x802f)
//cpu.disassemble(ram, 0x8000, 0x802f)

View File

@ -4,7 +4,7 @@ package sim65.components
class InstructionError(msg: String) : RuntimeException(msg)
interface ICpu {
fun disassemble(memory: Array<UByte>, baseAddress: Address, from: Address, to: Address)
fun disassemble(memory: Array<UByte>, baseAddress: Address, from: Address, to: Address): List<String>
fun disassemble(component: MemMappedComponent, from: Address, to: Address) =
disassemble(component.cloneMem(), component.startAddress, from, to)
@ -30,10 +30,13 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
const val RESET_vector = 0xfffc
const val IRQ_vector = 0xfffe
fun hexW(number: Address): String {
fun hexW(number: Address, allowSingleByte: Boolean = false): String {
val msb = number ushr 8
val lsb = number and 255
return hexB(msb) + hexB(lsb)
return if(msb==0 && allowSingleByte)
hexB(lsb)
else
hexB(msb) + hexB(lsb)
}
private const val hexdigits = "0123456789abcdef"
@ -130,38 +133,43 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
AddrMode.IzY to ::amIzy
)
override fun disassemble(memory: Array<UByte>, baseAddress: Address, from: Address, to: Address) {
override fun disassemble(memory: Array<UByte>, baseAddress: Address, from: Address, to: Address): List<String> {
var address = from - baseAddress
val spacing1 = " "
val spacing2 = " "
val spacing3 = " "
val result = mutableListOf<String>()
while (address <= (to - baseAddress)) {
val byte = memory[address]
print("\$${hexW(address)} ${hexB(byte)} ")
var line = "\$${hexW(address)} ${hexB(byte)} "
address++
val opcode = opcodes[byte.toInt()]
if (!opcode.official && !illegalInstrsAllowed) {
println("$spacing1 ???")
line += "$spacing1 ???"
} else {
when (opcode.mode) {
AddrMode.Imp, AddrMode.Acc -> {
println("$spacing1 ${opcode.mnemonic}")
AddrMode.Acc -> {
line += "$spacing1 ${opcode.mnemonic} a"
}
AddrMode.Imp -> {
line += "$spacing1 ${opcode.mnemonic}"
}
AddrMode.Imm -> {
val value = memory[address++]
println("${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}")
line += "${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}"
}
AddrMode.Zp -> {
val zpAddr = memory[address++]
println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}")
line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}"
}
AddrMode.ZpX -> {
val zpAddr = memory[address++]
println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x")
line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x"
}
AddrMode.ZpY -> {
val zpAddr = memory[address++]
println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y")
line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y"
}
AddrMode.Rel -> {
val rel = memory[address++]
@ -170,43 +178,46 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
address + rel
else
address - (256 - rel)
println("${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target)}")
line += "${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target, true)}"
}
AddrMode.Abs -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}")
line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}"
}
AddrMode.AbsX -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x")
line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x"
}
AddrMode.AbsY -> {
val lo = memory[address++]
val hi = memory[address++]
val absAddr = lo.toInt() or (hi.toInt() shl 8)
println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y")
line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y"
}
AddrMode.Ind -> {
val lo = memory[address++]
val hi = memory[address++]
val indirectAddr = lo.toInt() or (hi.toInt() shl 8)
println("${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})")
line += "${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})"
}
AddrMode.IzX -> {
val zpAddr = memory[address++]
println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)")
line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)"
}
AddrMode.IzY -> {
val zpAddr = memory[address++]
println("${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y")
line += "${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y"
}
}
}
result.add(line)
}
return result
}
override fun reset() {

View File

@ -0,0 +1,29 @@
import org.junit.jupiter.api.Test
import sim65.components.*
import java.io.File
import kotlin.test.*
class TestDisassembler {
@Test
fun testDisassembleAllOpcodes() {
val cpu = Cpu6502(true)
val memory = Ram(0, 0xffff)
memory.load("test/testfiles/disassem_instr_test.prg", 0x1000-2)
val result = cpu.disassemble(memory, 0x1000, 0x1221)
assertEquals(256, result.size)
assertEquals("\$1000 69 01 adc #\$01", result[0])
val reference = File("test/testfiles/disassem_ref_output.txt").readLines()
assertEquals(256, reference.size)
for(line in result.zip(reference)) {
if(line.first!=line.second) {
fail("disassembled instruction mismatch: '${line.first}', expected '${line.second}'")
}
}
}
}

View File

@ -0,0 +1,256 @@
$1000 69 01 adc #$01
$1002 65 02 adc $02
$1004 75 03 adc $03,x
$1006 6d 05 04 adc $0405
$1009 7d 07 06 adc $0607,x
$100c 79 09 08 adc $0809,y
$100f 61 0a adc ($0a,x)
$1011 71 0b adc ($0b),y
$1013 29 0c and #$0c
$1015 25 0d and $0d
$1017 35 0e and $0e,x
$1019 2d 10 0f and $0f10
$101c 3d 12 11 and $1112,x
$101f 39 14 13 and $1314,y
$1022 21 15 and ($15,x)
$1024 31 16 and ($16),y
$1026 0a asl a
$1027 06 17 asl $17
$1029 16 18 asl $18,x
$102b 0e 1a 19 asl $191a
$102e 1e 1c 1b asl $1b1c,x
$1031 90 1d bcc $1050
$1033 b0 1e bcs $1053
$1035 f0 1f beq $1056
$1037 24 20 bit $20
$1039 2c 22 21 bit $2122
$103c 30 23 bmi $1061
$103e d0 24 bne $1064
$1040 10 25 bpl $1067
$1042 00 brk
$1043 50 26 bvc $106b
$1045 70 27 bvs $106e
$1047 18 clc
$1048 d8 cld
$1049 58 cli
$104a b8 clv
$104b c9 28 cmp #$28
$104d c5 29 cmp $29
$104f d5 2a cmp $2a,x
$1051 cd 2c 2b cmp $2b2c
$1054 dd 2e 2d cmp $2d2e,x
$1057 d9 30 2f cmp $2f30,y
$105a c1 31 cmp ($31,x)
$105c d1 32 cmp ($32),y
$105e e0 33 cpx #$33
$1060 e4 34 cpx $34
$1062 ec 36 35 cpx $3536
$1065 c0 37 cpy #$37
$1067 c4 38 cpy $38
$1069 cc 3a 39 cpy $393a
$106c c6 3b dec $3b
$106e d6 3c dec $3c,x
$1070 ce 3e 3d dec $3d3e
$1073 de 40 3f dec $3f40,x
$1076 ca dex
$1077 88 dey
$1078 49 41 eor #$41
$107a 45 42 eor $42
$107c 55 43 eor $43,x
$107e 4d 45 44 eor $4445
$1081 5d 47 46 eor $4647,x
$1084 59 49 48 eor $4849,y
$1087 41 4a eor ($4a,x)
$1089 51 4b eor ($4b),y
$108b e6 4c inc $4c
$108d f6 4d inc $4d,x
$108f ee 4f 4e inc $4e4f
$1092 fe 51 50 inc $5051,x
$1095 e8 inx
$1096 c8 iny
$1097 4c 53 52 jmp $5253
$109a 6c 55 54 jmp ($5455)
$109d 20 57 56 jsr $5657
$10a0 a9 58 lda #$58
$10a2 a5 59 lda $59
$10a4 b5 5a lda $5a,x
$10a6 ad 5c 5b lda $5b5c
$10a9 bd 5e 5d lda $5d5e,x
$10ac b9 60 5f lda $5f60,y
$10af a1 61 lda ($61,x)
$10b1 b1 62 lda ($62),y
$10b3 a2 63 ldx #$63
$10b5 a6 64 ldx $64
$10b7 b6 65 ldx $65,y
$10b9 ae 67 66 ldx $6667
$10bc be 69 68 ldx $6869,y
$10bf a0 6a ldy #$6a
$10c1 a4 6b ldy $6b
$10c3 b4 6c ldy $6c,x
$10c5 ac 6e 6d ldy $6d6e
$10c8 bc 70 6f ldy $6f70,x
$10cb 4a lsr a
$10cc 46 71 lsr $71
$10ce 56 72 lsr $72,x
$10d0 4e 74 73 lsr $7374
$10d3 5e 76 75 lsr $7576,x
$10d6 ea nop
$10d7 09 77 ora #$77
$10d9 05 78 ora $78
$10db 15 79 ora $79,x
$10dd 0d 7b 7a ora $7a7b
$10e0 1d 7d 7c ora $7c7d,x
$10e3 19 7f 7e ora $7e7f,y
$10e6 01 80 ora ($80,x)
$10e8 11 81 ora ($81),y
$10ea 48 pha
$10eb 08 php
$10ec 68 pla
$10ed 28 plp
$10ee 2a rol a
$10ef 26 82 rol $82
$10f1 36 83 rol $83,x
$10f3 2e 85 84 rol $8485
$10f6 3e 87 86 rol $8687,x
$10f9 6a ror a
$10fa 66 88 ror $88
$10fc 76 89 ror $89,x
$10fe 6e 8b 8a ror $8a8b
$1101 7e 8d 8c ror $8c8d,x
$1104 40 rti
$1105 60 rts
$1106 e9 8e sbc #$8e
$1108 e5 8f sbc $8f
$110a f5 90 sbc $90,x
$110c ed 92 91 sbc $9192
$110f fd 94 93 sbc $9394,x
$1112 f9 96 95 sbc $9596,y
$1115 e1 97 sbc ($97,x)
$1117 f1 98 sbc ($98),y
$1119 38 sec
$111a f8 sed
$111b 78 sei
$111c 85 99 sta $99
$111e 95 9a sta $9a,x
$1120 8d 9c 9b sta $9b9c
$1123 9d 9e 9d sta $9d9e,x
$1126 99 a0 9f sta $9fa0,y
$1129 81 a1 sta ($a1,x)
$112b 91 a2 sta ($a2),y
$112d 86 a3 stx $a3
$112f 96 a4 stx $a4,y
$1131 8e a6 a5 stx $a5a6
$1134 84 a7 sty $a7
$1136 94 a8 sty $a8,x
$1138 8c aa a9 sty $a9aa
$113b aa tax
$113c a8 tay
$113d ba tsx
$113e 8a txa
$113f 9a txs
$1140 98 tya
$1141 02 ???
$1142 12 ???
$1143 22 ???
$1144 32 ???
$1145 42 ???
$1146 52 ???
$1147 62 ???
$1148 72 ???
$1149 92 ???
$114a b2 ???
$114b d2 ???
$114c f2 ???
$114d 7a nop
$114e 5a nop
$114f 1a nop
$1150 3a nop
$1151 da nop
$1152 fa nop
$1153 80 00 nop #$00
$1155 82 00 nop #$00
$1157 89 00 nop #$00
$1159 c2 00 nop #$00
$115b e2 00 nop #$00
$115d 04 00 nop $00
$115f 64 00 nop $00
$1161 44 00 nop $00
$1163 0c 00 00 nop $0000
$1166 14 00 nop $00,x
$1168 34 00 nop $00,x
$116a 54 00 nop $00,x
$116c 74 00 nop $00,x
$116e d4 00 nop $00,x
$1170 f4 00 nop $00,x
$1172 1c 00 00 nop $0000,x
$1175 3c 00 00 nop $0000,x
$1178 5c 00 00 nop $0000,x
$117b 7c 00 00 nop $0000,x
$117e dc 00 00 nop $0000,x
$1181 fc 00 00 nop $0000,x
$1184 ab 00 lax #$00
$1186 a7 00 lax $00
$1188 b7 00 lax $00,y
$118a af 00 00 lax $0000
$118d bf 00 00 lax $0000,y
$1190 a3 00 lax ($00,x)
$1192 b3 00 lax ($00),y
$1194 87 00 sax $00
$1196 97 00 sax $00,y
$1198 8f 00 00 sax $0000
$119b 83 00 sax ($00,x)
$119d eb 00 sbc #$00
$119f c7 00 dcp $00
$11a1 d7 00 dcp $00,x
$11a3 cf 00 00 dcp $0000
$11a6 df 00 00 dcp $0000,x
$11a9 db 00 00 dcp $0000,y
$11ac c3 00 dcp ($00,x)
$11ae d3 00 dcp ($00),y
$11b0 e7 00 isc $00
$11b2 f7 00 isc $00,x
$11b4 ef 00 00 isc $0000
$11b7 ff 00 00 isc $0000,x
$11ba fb 00 00 isc $0000,y
$11bd e3 00 isc ($00,x)
$11bf f3 00 isc ($00),y
$11c1 27 00 rla $00
$11c3 37 00 rla $00,x
$11c5 2f 00 00 rla $0000
$11c8 3f 00 00 rla $0000,x
$11cb 3b 00 00 rla $0000,y
$11ce 23 00 rla ($00,x)
$11d0 33 00 rla ($00),y
$11d2 67 00 rra $00
$11d4 77 00 rra $00,x
$11d6 6f 00 00 rra $0000
$11d9 7f 00 00 rra $0000,x
$11dc 7b 00 00 rra $0000,y
$11df 63 00 rra ($00,x)
$11e1 73 00 rra ($00),y
$11e3 07 00 slo $00
$11e5 17 00 slo $00,x
$11e7 0f 00 00 slo $0000
$11ea 1f 00 00 slo $0000,x
$11ed 1b 00 00 slo $0000,y
$11f0 03 00 slo ($00,x)
$11f2 13 00 slo ($00),y
$11f4 47 00 sre $00
$11f6 57 00 sre $00,x
$11f8 4f 00 00 sre $0000
$11fb 5f 00 00 sre $0000,x
$11fe 5b 00 00 sre $0000,y
$1201 43 00 sre ($00,x)
$1203 53 00 sre ($00),y
$1205 0b 00 anc #$00
$1207 2b 00 anc #$00
$1209 4b 00 alr #$00
$120b 6b 00 arr #$00
$120d 8b 00 xaa #$00
$120f 93 00 ahx ($00),y
$1211 9f 00 00 ahx $0000,y
$1214 9b 00 00 tas $0000,y
$1217 9e 00 00 shx $0000,y
$121a 9c 00 00 shy $0000,x
$121d bb 00 00 las $0000,y
$1220 cb 00 axs #$00