Skip to content

Commit

Permalink
Make Simulator use {djnz,ldir}_fast() only if interrupts are disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
skoolkid committed Mar 27, 2024
1 parent 8b1d881 commit e0fcdb9
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 17 deletions.
5 changes: 4 additions & 1 deletion skoolkit/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ def djnz(self, registers, memory):
registers[15] = R1[registers[15]] # R

def djnz_fast(self, registers, memory):
if memory[(registers[24] + 1) % 65536] == 0xFE:
if registers[26] == 0 and memory[(registers[24] + 1) % 65536] == 0xFE:
b = (registers[2] - 1) % 256
registers[2] = 0
r = registers[15]
Expand Down Expand Up @@ -737,6 +737,9 @@ def ldi(self, registers, memory, inc, repeat):
registers[15] = R2[registers[15]] # R

def ldir_fast(self, registers, memory, inc):
if registers[26]:
self.ldi(registers, memory, inc, 1)
return
de = registers[5] + 256 * registers[4]
bc = registers[3] + 256 * registers[2]
hl = registers[7] + 256 * registers[6]
Expand Down
2 changes: 1 addition & 1 deletion skoolkit/skoolmacro.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ def _read_sim_state(writer, execint, reg=None, clear=0):
if v >= 0:
registers[r] = v
state = {a: registers.pop(a) for a in ('iff', 'im', 'halted', 'tstates', 'fffd', 'ay')}
config = {'fast_djnz': execint < 1, 'fast_ldir': execint < 1}
config = {'fast_djnz': True, 'fast_ldir': True}
if len(writer.snapshot) == 0x20000:
config['frame_duration'] = FRAME_DURATIONS[1]
config['int_active'] = INT_ACTIVE[1]
Expand Down
2 changes: 1 addition & 1 deletion skoolkit/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def run(snafile, options, config):
registers[reg] = get_int_param(val, True)
except ValueError:
raise SkoolKitError("Cannot parse register value: {}".format(spec))
fast = options.verbose == 0 and not options.interrupts
fast = options.verbose == 0 and options.max_operations == 0 and options.max_tstates == 0
sim_config = {'fast_djnz': fast, 'fast_ldir': fast}
if snapshot:
border = snapshot.border
Expand Down
35 changes: 21 additions & 14 deletions tests/test_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1923,16 +1923,20 @@ def test_djnz_fast(self):
registers = simulator.registers
start = 35732

for offset, b_in, b_out, timing, r_out, end in (
(-2, 100, 0, 1295, 100, start + 2),
(-2, 1, 0, 8, 1, start + 2),
(-2, 0, 0, 3323, 0, start + 2),
(-3, 100, 99, 13, 1, start - 1),
(-3, 1, 0, 8, 1, start + 2),
(-3, 0, 255, 13, 1, start - 1),
for offset, iff, b_in, b_out, timing, r_out, end in (
(-2, 0, 100, 0, 1295, 100, start + 2),
(-2, 0, 1, 0, 8, 1, start + 2),
(-2, 0, 0, 0, 3323, 0, start + 2),
(-2, 1, 100, 99, 13, 1, start),
(-2, 1, 1, 0, 8, 1, start + 2),
(-2, 1, 0, 255, 13, 1, start),
(-3, 0, 100, 99, 13, 1, start - 1),
(-3, 0, 1, 0, 8, 1, start + 2),
(-3, 0, 0, 255, 13, 1, start - 1),
):
operation = f'DJNZ ${start + 2 + offset:04X}'
data = (16, offset & 0xFF)
registers[IFF] = iff
registers[B] = b_in
registers[R] = 0
reg_out = {B: b_out, R: r_out}
Expand Down Expand Up @@ -2261,14 +2265,17 @@ def test_ldir_fast(self):
start = 30000
at_hl = 250

for bc_in, bc_out, de_in, de_out, hl_in, hl_out, f_out, r_out, timing, end in (
# SZ5H3PNC
(52, 1, 29950, 30001, 40000, 40051, 0b00100100, 102, 1066, start), # 0xED overwritten
(51, 0, 29950, 30001, 40000, 40051, 0b00101000, 102, 1066, start + 2), # 0xED overwritten
(50, 0, 29950, 30000, 40000, 40050, 0b00101000, 100, 1045, start + 2),
( 1, 0, 29950, 29951, 40000, 40001, 0b00101000, 2, 16, start + 2),
( 0, 1, 30002, 30001, 30002, 30001, 0b00100100, 126, 1376230, start), # 0xED overwritten
for iff, bc_in, bc_out, de_in, de_out, hl_in, hl_out, f_out, r_out, timing, end in (
# SZ5H3PNC
(0, 52, 1, 29950, 30001, 40000, 40051, 0b00100100, 102, 1066, start), # 0xED overwritten
(0, 51, 0, 29950, 30001, 40000, 40051, 0b00101000, 102, 1066, start + 2), # 0xED overwritten
(0, 50, 0, 29950, 30000, 40000, 40050, 0b00101000, 100, 1045, start + 2),
(0, 1, 0, 29950, 29951, 40000, 40001, 0b00101000, 2, 16, start + 2),
(0, 0, 1, 30002, 30001, 30002, 30001, 0b00100100, 126, 1376230, start), # 0xED overwritten
(1, 50, 49, 50000, 50001, 40000, 40001, 0b00100100, 2, 21, start),
(1, 1, 0, 50000, 50001, 40000, 40001, 0b00101000, 2, 16, start + 2),
):
registers[IFF] = iff
registers[B] = bc_in // 256
registers[C] = bc_in % 256
registers[D] = de_in // 256
Expand Down
118 changes: 118 additions & 0 deletions tests/test_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,44 @@ def test_option_max_operations(self):
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_option_max_operations_disables_fast_djnz(self):
data = (
0xF3, # $8000 DI
0x06, 0x02, # $8001 LD B,2
0x10, 0xFE, # $8003 DJNZ $8002
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
Stopped at $8003: 3 operations
Wrote out.z80
"""
output, error = self.run_trace(f'-o {start} -m 3 {binfile} out.z80')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertLessEqual({'BC=256', 'R=3'}, set(s_reg))

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_option_max_operations_disables_fast_ldir(self):
data = (
0xF3, # $8000 DI
0x01, 0x02, 0x00, # $8001 LD BC,$0002
0x11, 0x01, 0xC0, # $8004 LD DE,$C001
0x21, 0x00, 0xC0, # $8007 LD HL,$C000
0xED, 0xB0, # $800A LDIR
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
Stopped at $800A: 5 operations
Wrote out.z80
"""
output, error = self.run_trace(f'-o {start} -m 5 {binfile} out.z80')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertLessEqual({'BC=1', 'DE=49154', 'HL=49153', 'R=6'}, set(s_reg))

def test_option_max_tstates(self):
data = [
0xAF, # XOR A
Expand All @@ -1195,6 +1233,44 @@ def test_option_max_tstates(self):
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_option_max_tstates_disables_fast_djnz(self):
data = (
0xF3, # $8000 DI ; [4]
0x06, 0x02, # $8001 LD B,2 ; [7]
0x10, 0xFE, # $8003 DJNZ $8002 ; [13/8]
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
Stopped at $8003: 24 T-states
Wrote out.z80
"""
output, error = self.run_trace(f'-o {start} -M 24 {binfile} out.z80')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertLessEqual({'BC=256', 'R=3'}, set(s_reg))

@patch.object(trace, 'write_snapshot', mock_write_snapshot)
def test_option_max_tstates_disables_fast_ldir(self):
data = (
0xF3, # $8000 DI ; [4]
0x01, 0x02, 0x00, # $8001 LD BC,$0002 ; [10]
0x11, 0x01, 0xC0, # $8004 LD DE,$C001 ; [10]
0x21, 0x00, 0xC0, # $8007 LD HL,$C000 ; [10]
0xED, 0xB0, # $800A LDIR ; [21/16]
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
Stopped at $800A: 55 T-states
Wrote out.z80
"""
output, error = self.run_trace(f'-o {start} -M 55 {binfile} out.z80')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())
self.assertLessEqual({'BC=1', 'DE=49154', 'HL=49153', 'R=6'}, set(s_reg))

def test_option_no_interrupts(self):
data = [
0x00, # $8000 NOP ; t=69886 (interrupt would normally follow)
Expand Down Expand Up @@ -1495,6 +1571,48 @@ def test_option_verbose(self):
"""
self.assertEqual(dedent(exp_output).strip(), output.rstrip())

def test_option_verbose_disables_fast_djnz(self):
data = (
0xF3, # $8000 DI
0x06, 0x02, # $8001 LD B,2
0x10, 0xFE, # $8003 DJNZ $8002
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
$8000 DI
$8001 LD B,$02
$8003 DJNZ $8003
$8003 DJNZ $8003
Stopped at $8005
"""
output, error = self.run_trace(f'-v -o {start} -S 0x8005 {binfile}')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())

def test_option_verbose_disables_fast_ldir(self):
data = (
0xF3, # $8000 DI
0x01, 0x02, 0x00, # $8001 LD BC,$0002
0x11, 0x01, 0xC0, # $8004 LD DE,$C001
0x21, 0x00, 0xC0, # $8007 LD HL,$C000
0xED, 0xB0, # $800A LDIR
)
binfile = self.write_bin_file(data, suffix='.bin')
start = 32768
exp_output = """
$8000 DI
$8001 LD BC,$0002
$8004 LD DE,$C001
$8007 LD HL,$C000
$800A LDIR
$800A LDIR
Stopped at $800C
"""
output, error = self.run_trace(f'-v -o {start} -S 0x800C {binfile}')
self.assertEqual(error, '')
self.assertEqual(dedent(exp_output).strip(), output.rstrip())

def test_option_vv(self):
data = [
0xAF, # XOR A
Expand Down

0 comments on commit e0fcdb9

Please sign in to comment.