aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2024-02-25 20:08:32 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2024-02-25 20:08:32 +0200
commit5776a07e6a3def343996c5ec83cd69242f7ea23a (patch)
treedfe91cff071a60be9fd9fc674625b8b462e06f27
parent3ac72608e8fc708277137fde62193c8763268ff5 (diff)
Add tests, fix bugs
-rw-r--r--atk16_asm/asm_ops.py8
-rw-r--r--atk16_emu/emu.py52
-rw-r--r--atk16_emu/test/test_alu.py344
-rw-r--r--atk16_emu/test/test_load.py32
-rw-r--r--atk16_emu/test/test_opcode_alr.py154
-rw-r--r--atk16_emu/test/test_store.py18
-rw-r--r--test/e2e/fibo/bootstrap.atk162
-rw-r--r--test/e2e/fibo/test_fibo.py2
-rw-r--r--test/e2e/just_hlt/test_just_hlt.py2
-rw-r--r--test/e2e/sum/test_sum.py2
10 files changed, 447 insertions, 169 deletions
diff --git a/atk16_asm/asm_ops.py b/atk16_asm/asm_ops.py
index 293b1cc..6a08495 100644
--- a/atk16_asm/asm_ops.py
+++ b/atk16_asm/asm_ops.py
@@ -54,11 +54,11 @@ def make_ldr(meta: Meta, symbols: Symbols, addr_reg: str, to_reg: str) -> int:
def make_str(meta: Meta, symbols: Symbols, from_reg: str, addr_reg: str) -> int:
"""STR 0011 XXXL LLRR RXXX"""
- from_reg_e = eval_expr(symbols, from_reg, bits=3)
- addr_reg_e = eval_expr(symbols, addr_reg, bits=3)
+ addr_reg_e = eval_expr(symbols, from_reg, bits=3)
+ from_reg_e = eval_expr(symbols, addr_reg, bits=3)
word = (0b0011 << 12) + \
- (addr_reg_e << 6) + \
- (from_reg_e << 3)
+ (from_reg_e << 6) + \
+ (addr_reg_e << 3)
return word
def make_ldi(meta: Meta, symbols: Symbols, imm: str, to_reg: str) -> int:
diff --git a/atk16_emu/emu.py b/atk16_emu/emu.py
index c87fff6..1d8fd1e 100644
--- a/atk16_emu/emu.py
+++ b/atk16_emu/emu.py
@@ -103,17 +103,54 @@ class ALU:
sign = (result & 0x8000) != 0
))
case 2: # L and R
- raise NotImplementedError()
+ result = L & R
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
case 3: # L or R
- raise NotImplementedError()
+ result = L | R
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
case 4: # L xor R
- raise NotImplementedError()
+ result = L ^ R
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
case 5: # L >> R logical
- raise NotImplementedError()
+ result = L >> R
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
case 6: # L >>> R arithmetic
- raise NotImplementedError()
+ # shift right but keep the sign bit (16-bit)
+ result = (L >> R) | (L & 0x8000)
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
case 7: # L << R
- raise NotImplementedError()
+ result = (L << R) & 0xFFFF
+ return ALUResult(result, ALUFlags(
+ carry = False,
+ overflow = False,
+ zero = result == 0,
+ sign = (result & 0x8000) != 0
+ ))
raise ValueError(f"Invalid ALU S: {S}")
@@ -200,7 +237,7 @@ class Machine:
def mem_write(self, addr: int, value: int):
if addr < 2 ** 15:
- raise ValueError(f"Cannot write to ROM, addr: {addr:>04x}")
+ raise ValueError(f"Cannot write to ROM, addr: 0x{addr:>04x}")
else:
# TODO: Implement memory-mapped I/O
self.ram.write(addr & 0x7FFF, value)
@@ -295,6 +332,7 @@ class Machine:
addr = self.get_nth_register(addr_reg).value
value = self.get_nth_register(from_reg).value
+ print(f"==== addr: 0x{addr:>04x}, value: 0x{value:>04x}")
self.mem_write(addr, value)
case LDI(to_reg, imm):
diff --git a/atk16_emu/test/test_alu.py b/atk16_emu/test/test_alu.py
new file mode 100644
index 0000000..dfae609
--- /dev/null
+++ b/atk16_emu/test/test_alu.py
@@ -0,0 +1,344 @@
+from atk16_emu import Machine
+from test.utils import make_rom
+
+def test_alr_add_small_unsigned():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 10
+ machine.rb.value = 20
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 30
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_add_large_unsigned():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF
+ machine.rb.value = 20
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 19
+ assert machine.fr.carry == True
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_add_small_signed():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF # -1
+ machine.rb.value = 0x0001 # 1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0
+ assert machine.fr.carry == True
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == True
+ assert machine.fr.sign == False
+
+def test_alr_add_large_signed():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0x7FFF # 32767
+ machine.rb.value = 0x0001 # 1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x8000 # -32768
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == True
+ assert machine.fr.zero == False
+ assert machine.fr.sign == True
+
+def test_alr_sub_small_unsigned():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 10
+ machine.rb.value = 20
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0xFFF6 # -10
+ assert machine.fr.carry == True
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == True
+
+def test_alr_sub_large_unsigned():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF
+ machine.rb.value = 0xFFFF
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x0000
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == True
+ assert machine.fr.sign == False
+
+def test_alr_sub_small_signed():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0x0001 # 1
+ machine.rb.value = 0xFFFF # -1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x0002
+ assert machine.fr.carry == True
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_sub_large_signed():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0x7FFF # 32767
+ machine.rb.value = 0xFFFF # -1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x8000 # -32768
+ assert machine.fr.carry == True
+ assert machine.fr.overflow == True
+ assert machine.fr.zero == False
+ assert machine.fr.sign == True
+
+def test_alr_and():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_010]) # ALR target=RC left=RA right=RB alu_code=2
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b1100
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b1000
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_or():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_011]) # ALR target=RC left=RA right=RB alu_code=3
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b1100
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b1110
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_xor():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_100]) # ALR target=RC left=RA right=RB alu_code=4
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b1100
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b0110
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_slr_small():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_101]) # ALR target=RC left=RA right=RB alu_code=5
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b0001
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b0101
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_slr_large():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_101]) # ALR target=RC left=RA right=RB alu_code=5
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF
+ machine.rb.value = 0x1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x7FFF
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_sar_small():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_110]) # ALR target=RC left=RA right=RB alu_code=6
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b0001
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b0101
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_sar_large():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_110]) # ALR target=RC left=RA right=RB alu_code=6
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF
+ machine.rb.value = 0x1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0xFFFF
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == True
+
+
+def test_alr_sll_small():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_111]) # ALR target=RC left=RA right=RB alu_code=7
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0b1010
+ machine.rb.value = 0b0001
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0b10100
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
+
+def test_alr_sll_large():
+ machine = Machine()
+
+ rom_image = make_rom([0b0000_010_000_001_111]) # ALR target=RC left=RA right=RB alu_code=7
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 0xFFFF
+ machine.rb.value = 0x1
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0xFFFE
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == True
+
+def test_ali_add_small_unsigned():
+ machine = Machine()
+
+ rom_image = make_rom([0b0001_010_000_001_000]) # ALI target=RC left=RA imm=0x000A alu_code=0
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.ra.value = 10
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 11
+ assert machine.fr.carry == False
+ assert machine.fr.overflow == False
+ assert machine.fr.zero == False
+ assert machine.fr.sign == False
diff --git a/atk16_emu/test/test_load.py b/atk16_emu/test/test_load.py
new file mode 100644
index 0000000..c03fb8d
--- /dev/null
+++ b/atk16_emu/test/test_load.py
@@ -0,0 +1,32 @@
+from atk16_emu import Machine
+from test.utils import make_rom
+
+def test_ldr():
+ machine = Machine()
+
+ rom_image = make_rom([0b0010_010_000_000_000]) # ALR target=RC reg=RA
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.mem_write(0x8000, 0x1234)
+ machine.ra.value = 0x8000 # mem address
+ machine.rc.value = 0x2345
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 0x1234
+
+def test_ldi():
+ machine = Machine()
+
+ rom_image = make_rom([0b0100_010_111111111]) # LDI target=RC imm=511
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.rc.value = 0x123
+
+ machine.run()
+ machine.step()
+
+ assert machine.rc.value == 511
diff --git a/atk16_emu/test/test_opcode_alr.py b/atk16_emu/test/test_opcode_alr.py
deleted file mode 100644
index 9a34845..0000000
--- a/atk16_emu/test/test_opcode_alr.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from atk16_emu import Machine
-from test.utils import make_rom
-
-def test_alr_add_small_unsigned():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 10
- machine.rb.value = 20
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 30
- assert machine.fr.carry == 0
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 0
- assert machine.fr.sign == 0
-
-def test_alr_add_large_unsigned():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0xFFFF
- machine.rb.value = 20
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 19
- assert machine.fr.carry == 1
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 0
- assert machine.fr.sign == 0
-
-def test_alr_add_small_signed():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0xFFFF # -1
- machine.rb.value = 0x0001 # 1
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0
- assert machine.fr.carry == 1
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 1
- assert machine.fr.sign == 0
-
-def test_alr_add_large_signed():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_000]) # ALR target=RC left=RA right=RB alu_code=0
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0x7FFF # 32767
- machine.rb.value = 0x0001 # 1
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0x8000 # -32768
- assert machine.fr.carry == 0
- assert machine.fr.overflow == 1
- assert machine.fr.zero == 0
- assert machine.fr.sign == 1
-
-def test_alr_sub_small_unsigned():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 10
- machine.rb.value = 20
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0xFFF6 # -10
- assert machine.fr.carry == 1
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 0
- assert machine.fr.sign == 1
-
-def test_alr_sub_large_unsigned():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0xFFFF
- machine.rb.value = 0xFFFF
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0x0000
- assert machine.fr.carry == 0
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 1
- assert machine.fr.sign == 0
-
-def test_alr_sub_small_signed():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0x0001 # 1
- machine.rb.value = 0xFFFF # -1
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0x0002
- assert machine.fr.carry == 1
- assert machine.fr.overflow == 0
- assert machine.fr.zero == 0
- assert machine.fr.sign == 0
-
-def test_alr_sub_large_signed():
- machine = Machine()
-
- rom_image = make_rom([0b0000_010_000_001_001]) # ALR target=RC left=RA right=RB alu_code=1
- machine.load_rom_image(rom_image)
- machine.reset()
-
- machine.ra.value = 0x7FFF # 32767
- machine.rb.value = 0xFFFF # -1
-
- machine.run()
- machine.step()
-
- assert machine.rc.value == 0x8000 # -32768
- assert machine.fr.carry == 1
- assert machine.fr.overflow == 1
- assert machine.fr.zero == 0
- assert machine.fr.sign == 1
diff --git a/atk16_emu/test/test_store.py b/atk16_emu/test/test_store.py
new file mode 100644
index 0000000..4b1b3df
--- /dev/null
+++ b/atk16_emu/test/test_store.py
@@ -0,0 +1,18 @@
+from atk16_emu import Machine
+from test.utils import make_rom
+
+def test_str():
+ machine = Machine()
+
+ rom_image = make_rom([0b0011_000_000_001_000]) # STR addr=RA data=RB
+ machine.load_rom_image(rom_image)
+ machine.reset()
+
+ machine.mem_write(0x8000, 0x1234)
+ machine.ra.value = 0x8000 # mem address
+ machine.rb.value = 0x2345
+
+ machine.run()
+ machine.step()
+
+ assert machine.mem_read(0x8000) == 0x2345
diff --git a/test/e2e/fibo/bootstrap.atk16 b/test/e2e/fibo/bootstrap.atk16
index 0fe2a9d..9b024e6 100644
--- a/test/e2e/fibo/bootstrap.atk16
+++ b/test/e2e/fibo/bootstrap.atk16
@@ -1,4 +1,4 @@
-@let sp RH
+@let SP RH
; vector table fields
@let vector_table 0x10
diff --git a/test/e2e/fibo/test_fibo.py b/test/e2e/fibo/test_fibo.py
index 6dae09b..a7146fc 100644
--- a/test/e2e/fibo/test_fibo.py
+++ b/test/e2e/fibo/test_fibo.py
@@ -8,7 +8,7 @@ def test_fibo():
source = f.read()
obj = assemble(source, filename)
- rom_image = pad_bytearray(obj)
+ rom_image = pad_bytearray(obj.program)
machine = Machine()
machine.load_rom_image(rom_image)
diff --git a/test/e2e/just_hlt/test_just_hlt.py b/test/e2e/just_hlt/test_just_hlt.py
index 60c59b0..c037615 100644
--- a/test/e2e/just_hlt/test_just_hlt.py
+++ b/test/e2e/just_hlt/test_just_hlt.py
@@ -8,7 +8,7 @@ def test_just_hlt():
source = f.read()
obj = assemble(source, filename)
- rom_image = pad_bytearray(obj)
+ rom_image = pad_bytearray(obj.program)
machine = Machine()
machine.load_rom_image(rom_image)
diff --git a/test/e2e/sum/test_sum.py b/test/e2e/sum/test_sum.py
index 3484af5..3edc1aa 100644
--- a/test/e2e/sum/test_sum.py
+++ b/test/e2e/sum/test_sum.py
@@ -8,7 +8,7 @@ def test_sum():
source = f.read()
obj = assemble(source, filename)
- rom_image = pad_bytearray(obj)
+ rom_image = pad_bytearray(obj.program)
machine = Machine()
machine.load_rom_image(rom_image)