File Coverage

blib/lib/CPU/Emulator/Z80.pm
Criterion Covered Total %
statement 698 707 98.7
branch 223 236 94.4
condition 79 87 90.8
subroutine 131 134 97.7
pod 12 12 100.0
total 1143 1176 97.1


line stmt bran cond sub pod time code
1             package CPU::Emulator::Z80;
2              
3 15     15   828607 use strict;
  15         160  
  15         403  
4 15     15   68 use warnings;
  15         167  
  15         490  
5              
6 15     15   77 use vars qw($VERSION %INSTR_LENGTHS %INSTR_DISPATCH);
  15         21  
  15         1664  
7              
8             $VERSION = '1.01';
9              
10             $SIG{__WARN__} = sub {
11             warn(__PACKAGE__.": $_[0]\n");
12             };
13              
14 15     15   91 use Carp;
  15         32  
  15         1059  
15 15     15   121 use Scalar::Util qw(blessed reftype);
  15         43  
  15         807  
16 15     15   5974 use Tie::Hash::Vivify;
  15         8004  
  15         414  
17 15     15   78 use Carp qw(confess);
  15         23  
  15         952  
18 15     15   7753 use Data::Dumper;
  15         89627  
  15         978  
19              
20 15     15   5728 use CPU::Emulator::Memory::Banked;
  15         35074  
  15         464  
21 15     15   5871 use CPU::Emulator::Z80::Register8;
  15         38  
  15         414  
22 15     15   5773 use CPU::Emulator::Z80::Register8F;
  15         32  
  15         378  
23 15     15   5241 use CPU::Emulator::Z80::Register8R;
  15         36  
  15         362  
24 15     15   5321 use CPU::Emulator::Z80::Register16;
  15         35  
  15         1624  
25 15     15   4912 use CPU::Emulator::Z80::Register16SP;
  15         34  
  15         346  
26 15     15   77 use CPU::Emulator::Z80::ALU; # import add/subtract methods
  15         28  
  15         230695  
27              
28             my @REGISTERS16 = qw(PC SP IX IY HL); # 16 bit registers
29             # NB W and Z aren't programmer-accesible, for internal use only!
30             my @REGISTERS8 = qw(A B C D E F R W Z I); # 8 bit registers
31             my @ALTREGISTERS = qw(A B C D E F HL); # those which have alt.s
32             my @REGISTERS = (@REGISTERS16, @REGISTERS8); # all registers
33              
34             =head1 NAME
35              
36             CPU::Emulator::Z80 - a Z80 emulator
37              
38             =head1 SYNOPSIS
39              
40             # create a CPU with 64K of zeroes in RAM
41             my $cpu = CPU::Emulator::Z80->new();
42              
43             # set a breakpoint
44             $cpu->memory()->poke16(0xF000, 0xDDDD); # STOP instruction
45             $cpu->memory()->poke(0xF002, 0x00);
46              
47             $cpu->memory()->poke(0, 0xC3); # JP 0xC000
48             $cpu->memory()->poke16(1, 0xC000);
49              
50             # run until we hit a breakpoint ie RST 1
51             eval { $cpu->run(); }
52             print $cpu->format_registers();
53              
54             =head1 DESCRIPTION
55              
56             This class provides a virtual Z80 micro-processor written in pure perl.
57             You can program it in Z80 machine code. Machine code is fast! This will
58             make your code faster!
59              
60             =head1 METHODS
61              
62             =head2 new
63              
64             The constructor returns an object representing a Z80 CPU. It takes
65             several optional parameters:
66              
67             =over
68              
69             =item memory
70              
71             can be either an object inheriting from CPU::Emulator::Memory, or a string
72             of data with which to initialise RAM. If a string is passed, then a
73             CPU::Emulator::Memory::Banked is created of the appropriate size. If not
74             specified at all, then a CPU::Emulator::Memory::Banked is created with
75             64K of zeroes.
76              
77             =item ports
78              
79             can be either 256 or 65536 (no other values are permitted) and defaults
80             to 65536. This is the number of I/O ports that can be addressed.
81             If set to 65536, the entire address bus is used to determine what
82             port I/O instructions tickle. If 256, then the most significant 8
83             bits are ignored.
84              
85             =item init_PC, init_A, init_B ...
86              
87             For each of A B C D E F R HL IX IY PC SP, an integer, the starting
88             value for that register, defaulting to 0.
89              
90             =item init_A_, init_B_, ...
91              
92             For each of A B C D E F HL, an integer for the starting value for that
93             register in the alternate set, defaulting to 0. Note that contrary to
94             normal Z80 custom these are named as X_ instead of X'. This is just for
95             quoting convenience.
96              
97             =back
98              
99             =cut
100              
101             sub new {
102 1314     1314 1 2427375 my($class, %args) = @_;
103 1314 100       5294 if(exists($args{memory})) {
104 1287 100       6106 if(blessed($args{memory})) {
    50          
105             die("memory must be a CPU::Emulator::Memory")
106 1285 50       6665 unless($args{memory}->isa('CPU::Emulator::Memory'));
107             } elsif(!ref($args{memory})) {
108             $args{memory} = CPU::Emulator::Memory::Banked->new(
109             bytes => $args{memory},
110             size => length($args{memory})
111 2         32 );
112             } else {
113 0         0 die("memory must be a string or an object\n");
114             }
115             } else {
116 27         199 $args{memory} = CPU::Emulator::Memory::Banked->new();
117             }
118              
119 1314 100       5917 if(exists($args{ports})) {
120             die("$args{ports} is a stupid number of ports\n")
121 3 100 66     39 unless($args{ports} == 256 || $args{ports} == 65536);
122             } else {
123 1311         2473 $args{ports} = 65536;
124             }
125              
126 1313         3991 foreach my $register (@REGISTERS, map { "${_}_" } @ALTREGISTERS) {
  9191         15962  
127             $args{"init_$register"} = 0
128 28886 100       61187 if(!exists($args{"init_$register"}));
129             }
130              
131             # bless early so we can close over it ...
132 1313         3277 my $self;
133             $self = bless {
134             iff1 => 0,
135             iff2 => 0,
136             ports => $args{ports},
137             inputs => {},
138             outputs => {},
139             memory => $args{memory},
140 0     0   0 registers => Tie::Hash::Vivify->new(sub { confess("No auto-vivifying registers!\n".Dumper(\@_)) }),
141 0     0   0 hw_registers => Tie::Hash::Vivify->new(sub { confess("No auto-vivifying hw_registers!\n".Dumper(\@_)) }),
142 1313     0   12678 derived_registers => Tie::Hash::Vivify->new(sub { confess("No auto-vivifying derived_registers!\n".Dumper(\@_)) }),
  0         0  
143             }, $class;
144              
145             $self->{hw_registers}->{$_} = CPU::Emulator::Z80::Register8->new(
146             cpu => $self, value => $args{"init_$_"}
147 1313         56289 ) foreach(@REGISTERS8);
148              
149             $self->{hw_registers}->{$_} = CPU::Emulator::Z80::Register16->new(
150             cpu => $self, value => $args{"init_$_"}
151 1313         15924 ) foreach(@REGISTERS16);
152              
153             $self->{hw_registers}->{$_.'_'} = blessed($self->{hw_registers}->{$_})->new(
154             cpu => $self, value => $args{"init_$_"}
155 1313         13032 ) foreach(@ALTREGISTERS);
156              
157             bless $self->{hw_registers}->{$_}, 'CPU::Emulator::Z80::Register8F'
158 1313         11660 foreach(qw(F F_));
159 1313         21074 bless $self->{hw_registers}->{R}, 'CPU::Emulator::Z80::Register8R';
160 1313         11290 bless $self->{hw_registers}->{SP}, 'CPU::Emulator::Z80::Register16SP';
161              
162              
163 1313         11903 $self->{derived_registers}->{AF} = $self->_derive_register16(qw(A F));
164 1313         10244 $self->{derived_registers}->{AF_} = $self->_derive_register16(qw(A_ F_));
165 1313         9961 $self->{derived_registers}->{BC} = $self->_derive_register16(qw(B C));
166 1313         9781 $self->{derived_registers}->{BC_} = $self->_derive_register16(qw(B_ C_));
167 1313         9628 $self->{derived_registers}->{DE} = $self->_derive_register16(qw(D E));
168 1313         9427 $self->{derived_registers}->{DE_} = $self->_derive_register16(qw(D_ E_));
169 1313         9787 $self->{derived_registers}->{WZ} = $self->_derive_register16(qw(W Z));
170 1313         10256 $self->{derived_registers}->{H} = $self->_derive_register8(qw(HL high));
171 1313         10443 $self->{derived_registers}->{H_} = $self->_derive_register8(qw(HL_ high));
172 1313         9538 $self->{derived_registers}->{L} = $self->_derive_register8(qw(HL low));
173 1313         9176 $self->{derived_registers}->{L_} = $self->_derive_register8(qw(HL_ low));
174 1313         9487 $self->{derived_registers}->{HIX} = $self->_derive_register8(qw(IX high));
175 1313         10155 $self->{derived_registers}->{LIX} = $self->_derive_register8(qw(IX low));
176 1313         9281 $self->{derived_registers}->{HIY} = $self->_derive_register8(qw(IY high));
177 1313         9408 $self->{derived_registers}->{LIY} = $self->_derive_register8(qw(IY low));
178              
179             $self->{registers}->{$_} = $self->{hw_registers}->{$_}
180 1313         9504 foreach(keys %{$self->{hw_registers}});
  1313         5376  
181             $self->{registers}->{$_} = $self->{derived_registers}->{$_}
182 1313         393505 foreach(keys %{$self->{derived_registers}});
  1313         4011  
183              
184 1313         270129 return $self;
185             }
186              
187             # create a 16-bit register-pair from two real 8-bit registers
188             sub _derive_register16 {
189 9191     9191   16387 my($self, $high, $low) = @_;
190             return CPU::Emulator::Z80::Register16->new(
191             get => sub {
192 7972     7972   11861 return 256 * $self->register($high)->get() +
193             $self->register($low)->get()
194             },
195             set => sub {
196 7838     7838   10828 my $value = shift;
197 7838         11432 $self->register($high)->set($value >>8);
198 7838         13226 $self->register($low)->set($value & 0xFF);
199             },
200 9191         51070 cpu => $self
201             );
202             }
203             # create an 8-bit pseudo-register from a 16-bit register
204             sub _derive_register8 {
205 10504     10504   18028 my($self, $pair, $half) = @_;
206             return CPU::Emulator::Z80::Register8->new(
207             get => sub {
208 653     653   1160 my $r = $self->register($pair)->get();
209 653 100       2940 return ($half eq 'high')
210             ? $r >> 8
211             : $r & 0xFF
212             },
213             set => sub {
214 505     505   681 my $value = shift;
215 505 100       921 $self->register($pair)->set(
216             ($half eq 'high')
217             ? ($self->register($pair)->get() & 0xFF) |
218             ($value << 8)
219             : ($self->register($pair)->get() & 0xFF00) | $value
220             );
221             },
222 10504         60354 cpu => $self
223             );
224             }
225              
226             =head2 add_input_device
227              
228             Takes two named parameters, 'address' and 'function', and creates an
229             input port at that address. Reading from the port will call the
230             function with no parameters,
231             returning whatever the function returns.
232              
233             In 256-port mode, the port is effectively replicated 256 times.
234              
235             =cut
236              
237             sub add_input_device {
238 27     27 1 308 my($self, %params) = @_;
239 27         81 my $address = $params{address} & ($self->{ports} - 1);
240             die(sprintf("Device already exists at %#06x", $address))
241 27 100       79 if(exists($self->{inputs}->{$address}));
242 26         75 $self->{inputs}->{$address} = $params{function};
243             }
244              
245             sub _get_from_input {
246 42     42   339 my($self, $addr) = @_;
247 42         90 $addr = $addr & ($self->{ports} - 1);
248 42 50       105 if(exists($self->{inputs}->{$addr})) {
249 42         109 return $self->{inputs}->{$addr}->();
250             } else {
251 0         0 die(sprintf("No such port %#06x", $addr));
252             }
253             }
254              
255             =head2 add_output_device
256              
257             Takes two named parameters, 'address' and 'function', and creates an
258             output port at that address. Writing to the port simply calls that
259             function with the byte to be written as its only parameter.
260              
261             In 256-port mode, the port is effectively replicated 256 times.
262              
263             =cut
264              
265             sub add_output_device {
266 10     10 1 67 my($self, %params) = @_;
267 10         21 my $address = $params{address} & ($self->{ports} - 1);
268             die(sprintf("Device already exists at %#06x", $address))
269 10 100       35 if(exists($self->{outputs}->{$address}));
270 9         25 $self->{outputs}->{$address} = $params{function};
271             }
272              
273             sub _put_to_output {
274 21     21   356 my($self, $addr, $byte) = @_;
275 21         31 $addr = $addr & ($self->{ports} - 1);
276 21 50       49 if(exists($self->{outputs}->{$addr})) {
277 21         47 $self->{outputs}->{$addr}->($byte);
278             } else {
279 0         0 carp(sprintf("No such port %#06x", $addr));
280             }
281             }
282              
283             =head2 memory
284              
285             Return a reference to the object that represent's the system's memory.
286              
287             =cut
288              
289             sub memory {
290 14971     14971 1 134400 my $self = shift;
291 14971         35691 return $self->{memory};
292             }
293              
294             =head2 register
295              
296             Return the object representing a specified register. This can be any
297             of the real registers (eg D or D_) or a derived register (eg DE or L).
298             For (HL) it returns the private internal DON'T TOUCH THIS 'W' register,
299             for evil twisty internals reasons.
300              
301             =cut
302              
303             sub register {
304 128904     128904 1 1834552 my($self, $r) = @_;
305 128904 100       317619 return $self->{registers}->{($r eq '(HL)') ? 'W' : $r};
306             }
307              
308             =head2 status
309              
310             Return a scalar representing the entire state of the CPU or, if passed
311             a scalar, attempt to initialise the CPU to the status it represents.
312              
313             =cut
314              
315             sub status {
316 3     3 1 755 my $self = shift;
317 3 100       13 if(@_) { $self->_status_load(@_); }
  1         4  
318             return
319             join('', map {
320 42         59 chr($self->register($_)->get())
321             } qw(A B C D E F A_ B_ C_ D_ E_ F_ R I))
322             .join('', map {
323 3         10 chr($self->register($_)->get() >> 8),
  18         38  
324             chr($self->register($_)->get() & 0xFF),
325             } qw(SP PC IX IY HL HL_));
326             }
327             sub _status_load {
328 1     1   3 my($self, $status) = @_;
329 1         10 my @regs = split(//, $status);
330             $self->register($_)->set(ord(shift(@regs)))
331 1         4 foreach(qw(A B C D E F A_ B_ C_ D_ E_ F_ R I));
332             $self->register($_)->set(256 * ord(shift(@regs)) + ord(shift(@regs)))
333 1         4 foreach(qw(SP PC IX IY HL HL_));
334             }
335              
336             =head2 registers
337              
338             Return a hashref of all the real registers and their values.
339              
340             =head2 format_registers
341              
342             A convenient method for getting all the registers in a nice
343             printable format. It mostly exists to help me with debuggering,
344             but if you promise to be good you can use it too. Just don't
345             rely on the format remaining unchanged.
346              
347             =cut
348              
349             sub registers {
350 2     2 1 15 my $self = shift;
351             return {
352             map {
353 40         55 $_ => $self->register($_)->get()
354 2         3 } grep { $_ !~ /^(W|Z)$/ } keys %{$self->{hw_registers}}
  44         195  
  2         8  
355             }
356             }
357              
358             sub format_registers {
359 1283     1283 1 4390 my $self = shift;
360             sprintf("#
361             # SZ5H3PNC SZ5H3PNC
362             # A: 0x%02X F: %08b HL: 0x%04X A_: 0x%02X F_: %08b HL_: 0x%04X
363             # B: 0x%02X C: 0x%02X B_: 0x%02X C_: 0x%02X
364             # D: 0x%02X E: 0x%02X D_: 0x%02X E_: 0x%02X
365             #
366             # IX: 0x%04X IY: 0x%04X SP: 0x%04X PC: 0x%04X
367             #
368             # R: 0x%02X I: 0x%02X
369             # W: 0x%02X Z: 0x%02X (internal use only)
370 1283         3113 ", map { $self->register($_)->get(); } qw(A F HL A_ F_ HL_ B C B_ C_ D E D_ E_ IX IY SP PC R I W Z));
  28226         42008  
371             }
372              
373             =head2 interrupt
374              
375             Attempt to raise an interrupt. Whether any attention is paid to it or not
376             depends on whether you've enabled interrupts or not in your Z80 code.
377             Because only IM 1 is implemented, this will generate a RST 0x38 if
378             interrupts are enabled. Note that interrupts are disabled at power-on.
379              
380             This returns true if the interrupt will be acted upon, false otherwise.
381             That is, it returns true if interrupts are enabled.
382              
383             =head2 nmi
384              
385             Raise a non-maskable interrupt. This generates a CALL 0x0066 as the
386             next instruction.a This also disables interrupts. Interrupts are
387             restored to their previous state by a RETN instruction.
388              
389             =head2 run
390              
391             Start the CPU running from whatever the Program Counter (PC) is set to.
392             This will by default run for ever. However, it takes an optional
393             parameter telling the CPU to run that number of instructions.
394              
395             This returns either when that many instructions have been executed, or
396             when a STOP instruction executed - see 'Extra Instructions' below.
397              
398             On return, the PC will point at the next instruction to execute so that
399             you can resume where you left off.
400              
401             =head2 stopped
402              
403             Returns true if the CPU has STOPped, false otherwise. You can use this
404             to easily determine why the run() method returned.
405              
406             =cut
407              
408             # SEE http://www.z80.info/decoding.htm
409             # http://www.z80.info/z80sflag.htm
410             # NB when decoding, x == first 2 bits, y == next 3, z == last 3
411             # p == first 2 bits of y, q == last bit of y
412             my @TABLE_R = (qw(B C D E H L (HL) A));
413             my @TABLE_RP = (qw(BC DE HL SP));
414             my @TABLE_RP2 = (qw(BC DE HL AF));
415             my @TABLE_CC = (qw(NZ Z NC C PO PE P M));
416             my @TABLE_ALU = (
417             \&_ADD_r8_r8, \&_ADC_r8_r8, \&_SUB_r8_r8, \&_SBC_r8_r8,
418             \&_AND_r8_r8, \&_XOR_r8_r8, \&_OR_r8_r8, \&_CP_r8_r8
419             );
420             my @TABLE_ROT = (
421             \&_RLC, \&_RRC, \&_RL, \&_RR, \&_SLA, \&_SRA, \&_SLL, \&_SRL
422             );
423             my @TABLE_BLI = (
424             [\&_LDI, \&_CPI, \&_INI, \&_OUTI],
425             [\&_LDD, \&_CPD, \&_IND, \&_OUTD],
426             [\&_LDIR, \&_CPIR, \&_INIR, \&_OTIR],
427             [\&_LDDR, \&_CPDR, \&_INDR, \&_OTDR],
428             );
429              
430             # NB order is important in these tables
431             %INSTR_LENGTHS = (
432             (map { $_ => 'UNDEFINED' } (0 .. 255)),
433             # un-prefixed instructions
434             # x=0, z=0
435             (map { ($_ << 3) => 1 } (0, 1)), # NOP; EX AF, AF'
436             (map { ($_ << 3) => 2 } (2 .. 7)), # DJNZ d; JR d; JR X, d
437             # x=0, z=1
438             (map { 0b00000001 | ($_ << 4 ) => 3 } (0 .. 3)), # LD rp[p], nn
439             (map { 0b00001001 | ($_ << 4 ) => 1 } (0 .. 3)), # ADD HL, rp[p]
440             # x=0, z=2
441             (map { 0b00000010 | ($_ << 3) => 1 } (0 .. 3)), # LD (BC/DE), A; LD A, (BC/DE)
442             (map { 0b00000010 | ($_ << 3) => 3 } (4 .. 7)), # LD (nn), HL/A, LD HL/A, (nn)
443             # x=0, z=3
444             (map { 0b00000011 | ($_ << 3) => 1 } (0 .. 7)), # INC/DEC rp
445             # x=0, z=4
446             (map { 0b00000100 | ($_ << 3) => 1 } (0 .. 7)), # INC r[y]
447             # x=0, z=5
448             (map { 0b00000101 | ($_ << 3) => 1 } (0 .. 7)), # DEC r[y]
449             # x=0, z=6
450             (map { 0b00000110 | ($_ << 3) => 2 } (0 .. 7)), # LD r[y], n
451             # x=0, z=7: RLCA, RRCA, RLA, RRA, DAA, CPL, SCF, CCF
452             (map { 0b00000111 | ($_ << 3) => 1 } (0 .. 7)),
453             # x=1
454             (map { 0b01000000 + $_ => 1 } (0 .. 63)), # LD r[y], r[z], HALT
455             # x=2
456             (map { 0b10000000 + $_ => 1 } (0 .. 63)), # alu[y] on A and r[z]
457             # x=3, z=0
458             (map { 0b11000000 | ($_ << 3) => 1 } (0 .. 7)), # RET cc[y]
459             (map { 0b11000001 | ($_ << 3) => 1 } (0 .. 7)), # POP rp2[p]/RET/EXX/JP HL/LD SP, HL
460             (map { 0b11000010 | ($_ << 3) => 3 } (0 .. 7)), # JP cc[y], nn
461             (map { 0b11000100 | ($_ << 3) => 3 } (0 .. 7)), # CALL cc[y], nn
462             (map { 0b11000101 | ($_ << 4) => 1 } (0 .. 3)), # PUSH rp2[p]
463             (map { 0b11000110 | ($_ << 3) => 2 } (0 .. 7)), # ALU[y] A, n
464             (map { 0b11000111 | ($_ << 3) => 1 } (0 .. 7)), # RST y*8
465             (map { 0b11000011 | ($_ << 3) => 1 } (4 .. 7)), # EX(SP), HL/EX DE, HL/DI/EI
466             0b11010011 => 2, # OUT (n), A
467             0b11011011 => 2, # IN A, (n)
468             0xC3 => 3, # JP nn
469             0xCD => 3, # CALL nn
470              
471             0xCB, { (map { $_ => 1 } (0 .. 255)) }, # roll/shift/bit/res/set
472             0xED, {
473             (map { 0b01000000 | ($_ << 3) => 1 } (0 .. 7)), # IN r[y],(C)
474             (map { 0b01000001 | ($_ << 3) => 1 } (0 .. 7)), # OUT (C),r[y]/OUT (C), 0
475             (map { 0b01000010 | ($_ << 3) => 1 } (0 .. 7)), # ADC/SBC HL, rp[p]
476             (map { 0b01000011 | ($_ << 3) => 3 } (0 .. 7)), # LD (nn), rp[p]/LD rp[p], (nn)
477             (map { 0b01000100 | ($_ << 3) => 1 } (0 .. 7)), # NEG
478             (map { 0b01000101 | ($_ << 3) => 1 } (0 .. 7)), # RETI/RETN
479             (map { 0b01000110 | ($_ << 3) => 1 } (0 .. 7)), # IM im[y]
480             (map { 0b01000111 | ($_ << 3) => 1 } (0 .. 7)), # LD I/R,A;LD A,I/R;RRD;RLD;NOP
481             (map { 0b10000000 | $_ => 1 } (0 .. 63)), # block instrs
482             # invalid instr, equiv to NOP
483             (map { $_ => 1 } ( 0b00000000 .. 0b00111111,
484             0b11000000 .. 0b11111111)),
485             },
486             );
487             $INSTR_LENGTHS{0xDD} = $INSTR_LENGTHS{0xFD} = {
488             # NB lengths in here do *not* include the prefix
489             (map { $_ => $INSTR_LENGTHS{$_} } (0 .. 255)),
490             0x34 => 2, # INC (IX + d)
491             0x35 => 2, # DEC (IX + d)
492             0x36 => 3, # LD (IX + d), n
493             0x46 => 2, # LD B, (IX + n)
494             0x4E => 2, # LD C, (IX + n)
495             0x56 => 2, # LD D, (IX + n)
496             0x5E => 2, # LD E, (IX + n)
497             0x66 => 2, # LD H, (IX + n)
498             0x6E => 2, # LD L, (IX + n)
499             0x7E => 2, # LD A, (IX + n)
500             0x70 => 2, # LD (IX + n), B
501             0x71 => 2, # LD (IX + n), C
502             0x72 => 2, # LD (IX + n), D
503             0x73 => 2, # LD (IX + n), E
504             0x74 => 2, # LD (IX + n), H
505             0x75 => 2, # LD (IX + n), L
506             0x77 => 2, # LD (IX + n), A
507             0x86 => 2, # ADD A, (IX + n)
508             0x8E => 2, # ADC A, (IX + n)
509             0x96 => 2, # SUB A, (IX + n)
510             0x9E => 2, # SBC A, (IX + n)
511             0xA6 => 2, # AND (IX + n)
512             0xAE => 2, # XOR (IX + n)
513             0xB6 => 2, # OR (IX + n)
514             0xBE => 2, # CP (IX + n)
515             0xED => 1, # NOP
516             0xCB => { map { $_ => 2 } (0 .. 255) },
517             0xDD => { map { $_ => 1 } (0 .. 255) }, # magic
518             0xFD => { map { $_ => 1 } (0 .. 255) }, # magic
519             };
520              
521             # these are all passed a list of parameter bytes
522             %INSTR_DISPATCH = (
523             # un-prefixed instructions
524             0 => \&_NOP,
525             0b00001000 => sub { _swap_regs(shift(), qw(AF AF_)); },
526             0b00010000 => \&_DJNZ,
527             0b00011000 => \&_JR_unconditional,
528             (map { my $y = $_; ($_ << 3) => sub {
529             _check_cond($_[0], $TABLE_CC[$y - 4]) &&
530             _JR_unconditional(@_);
531             } } (4 .. 7)),
532             (map { my $p = $_; 0b00000001 | ($p << 4 ) => sub {
533             _LD_r16_imm(shift(), $TABLE_RP[$p], @_) # LD rp[p], nn
534             } } (0 .. 3)),
535             (map { my $p = $_; 0b00001001 | ($_ << 4 ) => sub {
536             _ADD_r16_r16(shift(), 'HL', $TABLE_RP[$p]) # ADD HL, rp[p]
537             } } (0 .. 3)),
538             0b00000010 => sub { _LD_indr16_r8($_[0], 'BC', 'A'); }, # LD (BC), A
539             0b00001010 => sub { _LD_r8_indr16($_[0], 'A', 'BC'); }, # LD A, (BC)
540             0b00010010 => sub { _LD_indr16_r8($_[0], 'DE', 'A'); }, # LD (DE), A
541             0b00011010 => sub { _LD_r8_indr16($_[0], 'A', 'DE'); }, # LD A, (DE)
542             0b00100010 => sub { _LD_ind_r16(shift(), 'HL', @_); }, # LD (nn), HL
543             0b00101010 => sub { _LD_r16_ind(shift(), 'HL', @_); }, #LD HL, (nn)
544             0b00110010 => sub { _LD_ind_r8(shift(), 'A', @_); }, # LD (nn), A
545             0b00111010 => sub { _LD_r8_ind(shift(), 'A', @_); }, #LD A, (nn)
546             (map {
547             my($p, $q) = (($_ & 0b110) >> 1, $_ & 0b1);
548             0b00000011 | ($_ << 3) => sub {
549             $q ? _DEC($_[0], $TABLE_RP[$p]) # DEC rp[p]
550             : _INC($_[0], $TABLE_RP[$p]) # INC rp[p]
551             }
552             } (0 .. 7)),
553             (map { my $y = $_; 0b00000100 | ($_ << 3) => sub {
554             _INC($_[0], $TABLE_R[$y], $_[1]) # INC r[y] or INC(IX/Y + d)
555             } } (0 .. 7)),
556             (map { my $y = $_; 0b00000101 | ($_ << 3) => sub {
557             _DEC($_[0], $TABLE_R[$y], $_[1]) # DEC r[y] or DEC(IX/Y + d)
558             } } (0 .. 7)),
559             (map { my $y = $_; 0b00000110 | ($_ << 3) => sub {
560             _LD_r8_imm(shift(), $TABLE_R[$y], @_) # LD r[y], n
561             } } (0 .. 7)),
562             0b00000111 => \&_RLCA,
563             0b00001111 => \&_RRCA,
564             0b00010111 => \&_RLA,
565             0b00011111 => \&_RRA,
566             0b00100111 => \&_DAA,
567             0b00101111 => \&_CPL,
568             0b00110111 => \&_SCF,
569             0b00111111 => \&_CCF,
570             (map { my $y = $_ >> 3; my $z = $_ & 0b111; 0b01000000 + $_ => sub {
571             _LD_r8_r8(shift(), $TABLE_R[$y], $TABLE_R[$z], shift()); # LD r[y], r[z]
572             } } (0 .. 0b111111)),
573             0b01110110 => \&_HALT,
574             (map { my $y = $_ >> 3; my $z = $_ & 0b111; 0b10000000 + $_ => sub {
575             $TABLE_ALU[$y]->(shift(), 'A', $TABLE_R[$z], shift()); # alu[y] A, r[z]
576             } } (0 .. 0b111111)),
577             (map { my $y = $_; 0b11000110 | ($_ << 3) => sub {
578             _LD_r8_imm($_[0], 'W', $_[1]); # alu[y] A, n
579             $TABLE_ALU[$y]->(shift(), 'A', 'W', shift());
580             } } (0 .. 7)),
581             (map { my $y = $_; 0b11000000 | ($_ << 3) => sub {
582             _check_cond($_[0], $TABLE_CC[$y]) && # RET cc[y]
583             _POP(shift(), 'PC');
584             } } (0 .. 7)),
585             (map { my $p = $_; 0b11000001 | ($_ << 4) => sub {
586             _POP(shift(), $TABLE_RP2[$p]); # POP rp2[p]
587             } } (0 .. 3)),
588             (map { my $y = $_; 0b11000010 | ($_ << 3) => sub {
589             _check_cond($_[0], $TABLE_CC[$y]) && # JP cc[y], nn
590             _JP_unconditional(@_);
591             } } (0 .. 7)),
592             (map { my $y = $_; 0b11000100 | ($_ << 3) => sub {
593             _check_cond($_[0], $TABLE_CC[$y]) && # CALL cc[y], nn
594             _CALL_unconditional(@_);
595             } } (0 .. 7)),
596             (map { my $y = $_; 0b11000111 | ($_ << 3) => sub {
597             _CALL_unconditional(shift(), $y * 8, 0); # RST y*8
598             } } (0 .. 7)),
599             0xC3 => \&_JP_unconditional,
600             0b11010011 => \&_OUT_n_A, # OUT (n), A
601             0b11011011 => \&_IN_A_n, # IN A, (n)
602             0b11100011 => sub { # EX (SP), HL
603             my $self = shift;
604             _POP($self, 'WZ'); _PUSH($self, 'HL');
605             _LD_r16_r16($self, 'HL', 'WZ');
606             },
607             0b11101011 => sub { _swap_regs(shift(), qw(DE HL)); },
608             0b11110011 => \&_DI,
609             0b11111011 => \&_EI,
610             (map { my $p = $_; 0b11000101 | ($_ << 4) => sub {
611             _PUSH(shift(), $TABLE_RP2[$p]); # PUSH rp2[p]
612             } } (0 .. 3)),
613             0xCD => \&_CALL_unconditional,
614             0b11001001 => sub { _POP(shift(), 'PC'); }, # RET
615             0b11011001 => \&_EXX,
616             0b11101001 => sub { _LD_r16_r16($_[0], 'PC', 'HL'); }, # JP HL
617             0b11111001 => sub { _LD_r16_r16($_[0], 'SP', 'HL'); }, # LD SP, HL
618              
619             # and finally, prefixed instructions
620             0xED, {
621             (map { $_ => \&_NOP } ( 0b00000000 .. 0b00111111,
622             0b11000000 .. 0b11111111)),
623             (map { my $y = $_; 0b01000000 | ($_ << 3) => sub {
624             _IN_r_C(shift(), $TABLE_R[$y]); # IN r[y], (C)
625             } } (0 .. 7)),
626             (map { my $y = $_; 0b01000001 | ($_ << 3) => sub {
627             _OUT_C_r(shift(), $TABLE_R[$y]); # OUT (C), r[y]
628             } } (0 .. 5, 7)),
629             0b01110001 => \&_OUT_C_0, # OUT (C), 0
630             (map { my $p = $_; 0b01000010 | ($_ << 4) => sub {
631             _SBC_r16_r16(shift(), 'HL', $TABLE_RP[$p]); # SBC HL, rp[p]
632             } } (0 .. 3)),
633             (map { my $p = $_; 0b01001010 | ($_ << 4) => sub {
634             _ADC_r16_r16(shift(), 'HL', $TABLE_RP[$p]); # ADC HL, rp[p]
635             } } (0 .. 3)),
636             (map { my $p = $_; 0b01000011 | ($_ << 4) => sub {
637             _LD_ind_r16(shift(), $TABLE_RP[$p], @_); # LD (nn), rp[p]
638             } } (0 .. 3)),
639             (map { my $p = $_; 0b01001011 | ($_ << 4) => sub {
640             _LD_r16_ind(shift(), $TABLE_RP[$p], @_); # LD rp[p], (nn)
641             } } (0 .. 3)),
642             (map { 0b01000100 | ($_ << 3) => \&_NEG } (0 .. 7)), # NEG
643             (map { 0b01000101 | ($_ << 3) => ($_== 1 ? \&_RETI : \&_RETN) }
644             (0 .. 7)),
645             (map { my $y = $_; 0b01000110 | ($_ << 3) => sub {
646             _IM(shift(), $y); # IM im[y]
647             } } (0 .. 7)),
648             0b01000111 => sub { _LD_r8_r8(shift(), 'I', 'A'); }, # LD I, A
649             0b01001111 => sub { _LD_r8_r8(shift(), 'R', 'A'); }, # LD R, A
650             0b01010111 => \&_LD_A_I, # LD A, I
651             0b01011111 => \&_LD_A_R, # LD A, R
652             0b01100111 => \&_RRD,
653             0b01101111 => \&_RLD,
654             0b01110111 => \&_NOP,
655             0b01111111 => \&_NOP,
656             # x=1 is all invalid ...
657             (map { 0b10000000 | $_ => \&_NOP } (0 .. 63)),
658             # ... except for z = 0,1,2,3 and y = 4,5,6,7
659             (map {
660             my $y = $_; (map {
661             my $z = $_;
662             0b10000000 | ($y << 3) | $z => sub {
663             $TABLE_BLI[$y - 4]->[$z]->(@_)
664             }
665             } (0 .. 3))
666             } (4 .. 7)),
667              
668             },
669             0xCB, {
670             (map { my $y = $_ >> 3; my $z = $_ & 7; 0b00000000 | $_ => sub {
671             $TABLE_ROT[$y]->($_[0], $TABLE_R[$z], $_[1]);
672             } } (0 .. 63)),
673             (map { my $y = $_ >> 3; my $z = $_ & 7; 0b01000000 | $_ => sub {
674             _BIT($_[0], $y, $TABLE_R[$z], $_[1]);
675             } } (0 .. 63)),
676             (map { my $y = $_ >> 3; my $z = $_ & 7; 0b10000000 | $_ => sub {
677             _RES($_[0], $y, $TABLE_R[$z], $_[1]);
678             } } (0 .. 63)),
679             (map { my $y = $_ >> 3; my $z = $_ & 7; 0b11000000 | $_ => sub {
680             _SET($_[0], $y, $TABLE_R[$z], $_[1]);
681             } } (0 .. 63)),
682             },
683             0xDD, {
684             (map { my $i = $_; $_ => sub {
685             $INSTR_DISPATCH{$i}->(@_);
686             } } (0 .. 255)),
687             0xED => \&_NOP,
688             0xDD => {
689             0b00000000 => sub { $_[0]->{STOPREACHED} = 1 },
690             },
691             0xFD => {
692             map { my $i = $_; $_ => sub {
693             $INSTR_DISPATCH{0xDD}->{0xDD}->{$i}->(@_)
694             } } (0 .. 255)
695             },
696             0xCB => {
697             # these are all DD CB offset OPCODE. Yuck
698             # the dispatcher calls DD->CB->offset passing the opcode
699             # as a param. This fixes things.
700             map { my $d = $_; $_ => sub {
701             $INSTR_DISPATCH{0xCB}->{$_[1]}->($_[0], $d)
702             } } (0 .. 255)
703             },
704             },
705             0xFD, {
706             (map{my $i=$_; $_=>sub {$INSTR_DISPATCH{$i}->(@_)}} (0 .. 255)),
707             0xED => \&_NOP,
708             0xDD => {
709             map { my $i = $_; $_ => sub {
710             $INSTR_DISPATCH{0xDD}->{0xDD}->{$i}->(@_)
711             } } (0 .. 255)
712             },
713             0xFD => {
714             map { my $i = $_; $_ => sub {
715             $INSTR_DISPATCH{0xDD}->{0xDD}->{$i}->(@_)
716             } } (0 .. 255)
717             },
718             0xCB => {
719             map { my $i = $_; $_ => sub {
720             $INSTR_DISPATCH{0xDD}->{0xCB}->{$i}->(@_)
721             } } (0 .. 255)
722             }
723             },
724             );
725              
726             sub nmi {
727 2     2 1 329 my $self = shift;
728 2         4 $self->{iff2} = $self->{iff1};
729 2         2 $self->{iff1} = 0;
730 2         5 $self->{NMI} = 1;
731             }
732             sub interrupt {
733 3     3 1 7 my $self = shift;
734 3 100       7 if(_interrupts_enabled($self)) {
735 1         2 $self->{INTERRUPT} = 1;
736 1         3 _DI($self);
737 1         4 return 1;
738             }
739 2         6 return 0;
740             }
741             sub _interrupts_enabled {
742 11     11   30 my($self, $toggle) = @_;
743 11 100       178 return $self->{iff1} if(!defined($toggle));
744 8         24 $self->{iff1} = $self->{iff2} = $toggle;
745             }
746              
747             sub run {
748 1346     1346 1 11217 my $self = shift;
749 1346         1864 my $instrs_to_execute = -1;
750 1346 100       3483 $instrs_to_execute = shift() if(@_);
751              
752 1346         3072 RUNLOOP: while($instrs_to_execute) {
753 3393         4598 delete $self->{STOPREACHED};
754 3393         4077 $instrs_to_execute--;
755 3393         5657 $self->{instr_length_table} = \%INSTR_LENGTHS;
756 3393         5419 $self->{instr_dispatch_table} = \%INSTR_DISPATCH;
757 3393         5677 $self->{prefix_bytes} = [];
758 3393 100       7305 if($self->{NMI}) {
    100          
759 1         4 delete $self->{NMI};
760 1         4 _DI($self);
761 1         3 _CALL_unconditional($self, 0x66, 0x00);
762             } elsif($self->{INTERRUPT}) {
763 1         2 delete $self->{INTERRUPT};
764 1         3 _DI($self);
765 1         2 $self->_execute(0xFF);
766 3391         7071 } else { $self->_execute($self->_fetch()); }
767 3392         6204 delete $self->{instr_length_table};
768 3392         4459 delete $self->{instr_dispatch_table};
769 3392         4975 delete $self->{prefix_bytes};
770 3392 100       8821 if($self->{STOPREACHED}) {
771 6         19 last RUNLOOP;
772             }
773             }
774             }
775              
776             sub stopped {
777 2     2 1 245 my $self = shift;
778 2         8 return exists($self->{STOPREACHED});
779             }
780              
781             # fetch all the bytes for an instruction and return them
782             sub _fetch {
783 4997     4997   6097 my $self = shift;
784 4997         7752 my $pcREG = $self->register('PC');
785 4997         38069 my $pc = $pcREG->get();
786            
787 4997 100 100     8506 $self->register('R')->inc() # don't inc for DDCB and FDCB
      100        
788             unless(
789             $self->_got_prefix(0xCB) &&
790             ($self->_got_prefix(0xDD) || $self->_got_prefix(0xFD))
791             );
792 4997         9538 my $byte = $self->memory()->peek($pc);
793 4997         41253 my @bytes = ($byte);
794              
795             # prefix byte
796 4997 100       13708 if(ref($self->{instr_length_table}->{$byte})) {
797             # printf("Found prefix byte %#04x\n", $byte);
798 1606         3336 $self->{instr_dispatch_table} = $self->{instr_dispatch_table}->{$byte};
799 1606         2856 $self->{instr_length_table} = $self->{instr_length_table}->{$byte};
800 1606         1935 push @{$self->{prefix_bytes}}, $byte;
  1606         3491  
801 1606         4992 $pcREG->inc(); # set($pc + 1);
802 1606         3200 return $self->_fetch();
803             }
804              
805 3391         4887 my $bytes_to_fetch = $self->{instr_length_table}->{$byte};
806            
807             die(sprintf(
808             "_fetch: Unknown instruction 0x%02X at 0x%04X with prefix bytes ["
809 0         0 .join(' ', map { "0x%02X" } @{$self->{prefix_bytes}})
  0         0  
810 3391 50       6836 ."]\n", $byte, $pc, @{$self->{prefix_bytes}}
  0         0  
811             )) if($bytes_to_fetch eq 'UNDEFINED');
812              
813 3391         6433 push @bytes, map { $self->memory()->peek($pc + $_) } (1 .. $bytes_to_fetch - 1);
  1950         5533  
814 3391         18865 $pcREG->set($pc + $bytes_to_fetch);
815 3391         8977 return @bytes;
816             }
817              
818             # execute an instruction. NB, the PC already points at the next instr
819             sub _execute {
820 3392     3392   6079 my($self, $instr) = (shift(), shift());
821 3392 100 66     22390 if(
      66        
822             exists($self->{instr_dispatch_table}->{$instr}) &&
823             ref($self->{instr_dispatch_table}->{$instr}) &&
824             reftype($self->{instr_dispatch_table}->{$instr}) eq 'CODE'
825             ) {
826 3391 100       6372 _swap_regs($self, qw(HL IX)) if($self->_got_prefix(0xDD));
827 3391 100       6022 _swap_regs($self, qw(HL IY)) if($self->_got_prefix(0xFD));
828 3391         10484 $self->{instr_dispatch_table}->{$instr}->($self, @_);
829 3391 100       18167 _swap_regs($self, qw(HL IY)) if($self->_got_prefix(0xFD));
830 3391 100       5603 _swap_regs($self, qw(HL IX)) if($self->_got_prefix(0xDD));
831             } else {
832             die(sprintf(
833             "_execute: No entry in dispatch table for instr "
834 3         7 .join(' ', map { "0x%02x" } (@{$self->{prefix_bytes}}, $instr))
  1         2  
835             ." of known length, near addr 0x%04x\n",
836 1         3 @{$self->{prefix_bytes}}, $instr, $self->register('PC')->get()
  1         2  
837             ));
838             }
839             }
840              
841             sub _got_prefix {
842 19983     19983   26048 my($self, $prefix) = @_;
843 19983         21045 return grep { $_ == $prefix } @{$self->{prefix_bytes}}
  10839         30604  
  19983         40592  
844             }
845              
846             sub _check_cond {
847 312     312   523 my($self, $cond) = @_;
848 312         513 my $f = $self->register('F');
849             return
850 312 100       4107 $cond eq 'NC' ? !$f->getC() :
    100          
    100          
    100          
    100          
    100          
    100          
851             $cond eq 'C' ? $f->getC() :
852             $cond eq 'NZ' ? !$f->getZ() :
853             $cond eq 'Z' ? $f->getZ() :
854             $cond eq 'PO' ? !$f->getP() :
855             $cond eq 'PE' ? $f->getP() :
856             $cond eq 'P' ? !$f->getS() :
857             $f->getS()
858             }
859              
860             sub _ADD_r16_r16 {
861 20     20   67 my($self, $r1, $r2, $c) = @_;
862             # $c is defined if this is really SBC
863 20         48 my $adc = 0 + defined($c);
864 20   100     112 $c ||= 0;
865 20         45 $self->register($r1)->add($self->register($r2)->get() + $c, $adc);
866             }
867             sub _ADC_r16_r16 {
868             # ADC also frobs S, Z and P, unlike ADD. argh. the magic $c
869             # will communicate that
870 4     4   16 _ADD_r16_r16(@_, $_[0]->register('F')->getC());
871             }
872 15     15   67 sub _ADC_r8_r8 { _ADD_r8_r8(@_[0..3], $_[0]->register('F')->getC()); }
873             sub _ADD_r8_r8 {
874 30     30   98 my($self, $r1, $r2, $d, $c) = @_;
875             # $c is defined if this is really ADC
876 30   100     183 $c ||= 0;
877 30 100       115 _LD_r8_indHL($self, 'W', $d) if($r2 eq '(HL)');
878 30         85 $self->register($r1)->add($self->register($r2)->get() + $c);
879             }
880 192     192   766 sub _RES { _RES_SET($_[0], 0, @_[1 .. $#_]); }
881 193     193   832 sub _SET { _RES_SET($_[0], 1, @_[1 .. $#_]); }
882             sub _RES_SET {
883 385     385   1076 my($self, $value, $bit, $r, $d) = @_;
884              
885 385 100 100     1326 if(defined($d) && $r ne '(HL)') { # weirdo DDCB*
886 224         449 my $realr = $r;
887 224 100       1182 $realr .= $self->_got_prefix(0xDD) ? 'IX' : 'IY'
    100          
888             if($realr =~ /^[HL]$/);
889 224         433 $r = '(HL)';
890 224         648 _LD_r8_indHL($self, 'W', $d);
891 224         669 $self->register($r)->set( # RES by default
892             $self->register($r)->get() & (255 - 2**$bit)
893             );
894 224 100       670 $self->register($r)->set( # SET if asked to
895             $self->register($r)->get() | (2**$bit)
896             ) if($value);
897 224 50       967 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
898 224         15602 _LD_r8_r8($self, $realr, 'W');
899             } else {
900 161 100       633 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
901 161         390 $self->register($r)->set( # RES by default
902             $self->register($r)->get() & (255 - 2**$bit)
903             );
904 161 100       656 $self->register($r)->set( # SET if asked to
905             $self->register($r)->get() | (2**$bit)
906             ) if($value);
907 161 100       622 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
908             }
909              
910             }
911             sub _BIT {
912 200     200   625 my($self, $bit, $r, $d) = @_; # $d is for DDCB/FFCB - NYI
913            
914 200         428 my $realr = $r;
915 200 100       556 $r = '(HL)' if(defined($d));
916              
917 200 100       705 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
918              
919 200         537 my $f = $self->register('F');
920 200         1610 $f->setZ(!($self->register($r)->get() & 2**$bit));
921 200         1048 $f->setH();
922 200         820 $f->resetN();
923 200   100     1008 $f->setS($bit == 7 && $self->register($r)->get() & 0x80);
924 200         630 $f->setP($self->register('F')->getZ());
925 200         587 $f->set5($self->register($r)->get() & 0b100000);
926 200         497 $f->set3($self->register($r)->get() & 0b1000);
927 200 100       629 if(defined($d)) {
928 128         327 $f->set5(((ALU_getsigned($d, 8) + $self->register('HL')->get()) >> 8) & 0b100000);
929 128         379 $f->set3(((ALU_getsigned($d, 8) + $self->register('HL')->get()) >> 8) & 0b1000);
930             }
931             }
932              
933             sub _binop {
934 301     301   599 my($self, $r1, $r2, $d, $op) = @_;
935             # $r1 is always A, $r2 is A/B/C/D/EH/L/(HL)/W/Z
936 301 100       567 _LD_r8_indHL($self, 'W', $d) if($r2 eq '(HL)');
937             # if($r2 eq '(HL)') {
938             # my @addr = map { $self->register($_)->get()} qw(L H);
939             # _LD_r8_ind($self, 'W', @addr);
940             # $r2 = 'W';
941             # }
942              
943 301         598 my $aREG = $self->register($r1);
944 301         2230 my $fREG = $self->register('F');
945              
946 301 50       2540 $op eq '&' ? $aREG->set($aREG->get() & $self->register($r2)->get()) :
    100          
    100          
947             $op eq '|' ? $aREG->set($aREG->get() | $self->register($r2)->get()) :
948             $op eq '^' ? $aREG->set($aREG->get() ^ $self->register($r2)->get()) :
949             die("unknown binop: $op\n");
950              
951 301         714 $fREG->setS($aREG->get() & 0x80);
952 301         639 $fREG->setZ($aREG->get() == 0);
953 301         638 $fREG->set5($aREG->get() & 0b100000);
954 301         1250 $fREG->setH($op eq '&');
955 301         618 $fREG->set3($aREG->get() & 0b1000);
956 301         648 $fREG->setP(ALU_parity($aREG->get()));
957 301         1173 $fREG->resetN();
958 301         994 $fREG->resetC();
959             }
960 15     15   58 sub _AND_r8_r8 { _binop(@_, '&'); }
961 271     271   489 sub _OR_r8_r8 { _binop(@_, '|'); }
962 15     15   47 sub _XOR_r8_r8 { _binop(@_, '^'); }
963 15     15   78 sub _SBC_r8_r8 { _SUB_r8_r8(@_[0 .. 3], $_[0]->register('F')->getC()); }
964 4     4   16 sub _SBC_r16_r16 { _SUB_r16_r16(@_, $_[0]->register('F')->getC()); }
965             sub _SUB_r8_r8 {
966 67     67   232 my($self, $r1, $r2, $d, $c) = @_;
967             # $c is defined if this is really SBC
968 67   100     371 $c ||= 0;
969 67 50       166 die("Can't SUB with Z reg") if($r2 eq 'Z');
970 67 100       213 _LD_r8_indHL($self, 'W', $d) if($r2 eq '(HL)');
971 67         157 $self->register($r1)->sub($self->register($r2)->get() + $c);
972             }
973             sub _SUB_r16_r16 {
974 4     4   18 my($self, $r1, $r2, $c) = @_;
975             # $c is defined if this is really SBC
976 4   50     12 $c ||= 0;
977 4         11 $self->register($r1)->sub($self->register($r2)->get() + $c);
978             }
979             sub _CP_r8_r8 {
980             # $r1 is always A, $r2 is A/B/C/D/EH/L/(HL)/W
981 29     29   97 my($self, $r1, $r2, $d) = @_;
982              
983             # bleh, CP uses the *operand* to set flags 3 and 5, instead of
984             # the result, so wrap SUB and correct afterwards.
985             # this is why we can't SUB with the Z reg
986 29         110 _LD_r8_r8($self, 'Z', $r1); # preserve r1
987 29         141 _SUB_r8_r8($self, $r1, $r2, $d);
988             # put result into Z - this is used by CPI
989 29         118 _swap_regs($self, $r1, 'Z'); # restore r1, result into Z
990 29         86 $self->register('F')->set5($self->register($r2)->get() & 0b100000);
991 29         91 $self->register('F')->set3($self->register($r2)->get() & 0b1000);
992             }
993             sub _DEC {
994 276     276   691 my($self, $r, $d) = @_;
995 276 100       584 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
996 276         448 $self->register($r)->dec();
997 276 100       880 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
998             # my($self, $r) = @_;
999             # if($r eq '(HL)') {
1000             # my @addr = map { $self->register($_)->get()} qw(L H);
1001             # _LD_r8_ind($self, 'W', @addr);
1002             # $self->register('W')->dec();
1003             # _LD_ind_r8($self, 'W', @addr);
1004             # } else {
1005             # $self->register($r)->dec();
1006             # }
1007             }
1008             sub _EXX {
1009 1     1   3 my $self = shift;
1010 1         4 _swap_regs($self, qw(BC BC_));
1011 1         4 _swap_regs($self, qw(DE DE_));
1012 1         3 _swap_regs($self, qw(HL HL_));
1013              
1014             }
1015             sub _DJNZ {
1016 268     268   393 my($self, $offset) = @_;
1017              
1018 268         403 my $fREG = $self->register('F');
1019 268         2011 my $bREG = $self->register('B');
1020 268         1909 my $pcREG = $self->register('PC');
1021              
1022 268         1967 my $f = $fREG->get(); # preserve flags
1023              
1024 268         596 $bREG->dec(); # decrement B and ...
1025 268 100       515 if($bREG->get()) { # jump if not zero
1026 265         526 $pcREG->set(
1027             $pcREG->get() +
1028             ALU_getsigned($offset, 8)
1029             );
1030             }
1031 268         527 $fREG->set($f); # restore flags
1032             }
1033 1     1   6 sub _HALT { shift()->register('PC')->dec(); select(undef, undef, undef, 0.01) }
  1         10171  
1034             sub _INC {
1035 21     21   76 my($self, $r, $d) = @_;
1036 21 100       87 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1037 21         60 $self->register($r)->inc();
1038 21 100       101 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1039             }
1040             sub _LDI {
1041 26     26   38 my $self = shift;
1042 26         47 my $f = $self->register('F');
1043 26         204 _LD_r8_indr16($self, 'W', 'HL'); # get from (HL);
1044 26         73 _LD_indr16_r8($self, 'DE', 'W'); # put to (DE);
1045 26         496 $self->register('DE')->inc();
1046 26         59 $self->register('HL')->inc();
1047 26         45 $self->register('BC')->dec();
1048 26         57 $f->set5(($self->register('A')->get() + $self->register('W')->get()) & 2);
1049 26         56 $f->set3(($self->register('A')->get() + $self->register('W')->get()) & 8);
1050 26         61 $f->setP($self->register('BC')->get() != 0);
1051 26         92 $f->resetN();
1052 26         103 $f->resetH();
1053             }
1054             sub _LDIR {
1055 16     16   20 my $self = shift;
1056 16         33 _LDI($self);
1057 16 100       29 $self->register('PC')->set($self->register('PC')->get() - 2)
1058             if($self->register('BC')->get());
1059             }
1060             sub _LDD {
1061 9     9   14 my $self = shift;
1062 9         18 _LDI($self); # cheat, do an LDI then correct HL and DE
1063 9         23 _swap_regs($self, qw(W F));
1064 9         23 $self->register('DE')->sub(2);
1065 9         26 $self->register('HL')->sub(2);
1066 9         23 _swap_regs($self, qw(W F));
1067             }
1068             sub _LDDR {
1069 8     8   10 my $self = shift;
1070 8         18 _LDD($self);
1071 8 100       17 $self->register('PC')->set($self->register('PC')->get() - 2)
1072             if($self->register('BC')->get());
1073             }
1074             sub _CPI {
1075 14     14   31 my $self = shift;
1076 14         36 my $f = $self->register('F');
1077 14         169 my $c = $f->getC();
1078 14         54 _CP_r8_r8($self, 'A', '(HL)'); # Z = A - (HL), S/Z/H now set OK
1079 14         36 $self->register('HL')->inc();
1080 14         36 $self->register('BC')->dec();
1081 14         40 $f->setP($self->register('BC')->get() != 0);
1082 14         56 $f->setC($c);
1083 14         71 $f->setN();
1084 14         27 $f->set5(
1085             ($self->register('Z')->get() - $f->getH()) & 0b10
1086             );
1087 14         38 $f->set3(
1088             ($self->register('Z')->get() - $f->getH()) & 0b1000
1089             );
1090             }
1091             sub _CPIR {
1092 4     4   6 my $self = shift;
1093 4         11 _CPI($self);
1094 4 100 66     11 $self->register('PC')->set($self->register('PC')->get() - 2)
1095             if($self->register('BC')->get() && $self->register('Z')->get());
1096            
1097             }
1098             sub _CPD {
1099 9     9   14 my $self = shift;
1100 9         84 _CPI($self); # cheat, do a CPI then correct HL
1101 9         29 _swap_regs($self, qw(W F));
1102 9         21 $self->register('HL')->sub(2);
1103 9         28 _swap_regs($self, qw(W F));
1104             }
1105             sub _CPDR {
1106 8     8   17 my $self = shift;
1107 8         23 _CPD($self);
1108 8 100 66     22 $self->register('PC')->set($self->register('PC')->get() - 2)
1109             if($self->register('BC')->get() && $self->register('Z')->get());
1110             }
1111             sub _RLD {
1112 1     1   2 my $self = shift;
1113 1         3 my($a, $f, $w, $z) = map { $self->register($_) } (qw(A F W Z));
  4         23  
1114 1         11 _LD_r8_indHL($self, 'W'); # get (HL)
1115 1         6 $z->set($a->get() & 0x0F);
1116 1         3 $a->set(($a->get() & 0xF0) | ($w->get() & 0xF0) >> 4);# A now kosher
1117 1         3 $w->set(($w->get() << 4) | $z->get()); # W now correct
1118 1         3 _LD_indHL_r8($self, 'W'); # (HL) now correct
1119 1         83 $f->setS($a->get() & 0x80);
1120 1         6 $f->setZ($a->get() == 0);
1121 1         4 $f->set5($a->get() & 0b100000);
1122 1         2 $f->set3($a->get() & 0b1000);
1123 1         3 $f->setP(ALU_parity($a->get()));
1124 1         8 $f->resetH();
1125 1         5 $f->resetN();
1126             }
1127             sub _RRD {
1128 1     1   2 my $self = shift;
1129 1         3 my($a, $f, $w, $z) = map { $self->register($_) } (qw(A F W Z));
  4         22  
1130 1         10 _LD_r8_indHL($self, 'W'); # get (HL)
1131 1         3 $z->set($a->get() << 4);
1132 1         2 $a->set(($a->get() & 0xF0) | ($w->get() & 0x0F)); # A now correct
1133 1         2 $w->set(($w->get() >> 4) | $z->get()); # W now correct
1134 1         3 _LD_indHL_r8($self, 'W'); # (HL) now correct
1135 1         79 $f->setS($a->get() & 0x80);
1136 1         3 $f->setZ($a->get() == 0);
1137 1         2 $f->set5($a->get() & 0b100000);
1138 1         3 $f->set3($a->get() & 0b1000);
1139 1         4 $f->setP(ALU_parity($a->get()));
1140 1         4 $f->resetH();
1141 1         11 $f->resetN();
1142             }
1143             sub _JR_unconditional {
1144 134     134   207 my($self, $offset) = @_;
1145 134         220 $self->register('PC')->set(
1146             $self->register('PC')->get() +
1147             ALU_getsigned($offset, 8)
1148             );
1149             }
1150             sub _JP_unconditional {
1151 156     156   371 _LD_r16_imm(shift(), 'PC', @_);
1152             }
1153             sub _CALL_unconditional {
1154 19     19   100 _PUSH($_[0], 'PC');
1155 19         1440 _JP_unconditional(@_);
1156             }
1157             sub _LD_ind_r16 {
1158 8     8   33 my($self, $r16, @bytes) = @_;
1159 8         25 $self->memory()->poke16($bytes[0] + 256 * $bytes[1], $self->register($r16)->get())
1160             }
1161             sub _LD_ind_r8 {
1162 22     22   57 my($self, $r8, @bytes) = @_;
1163 22         51 $self->memory()->poke($bytes[0] + 256 * $bytes[1], $self->register($r8)->get())
1164             }
1165             sub _LD_indHL_r8 {
1166 681     681   1145 my($self, $r8, $d) = @_;
1167 681   100     2134 $d = ALU_getsigned($d || 0, 8);
1168 681         1295 $self->memory()->poke($d + $self->register('HL')->get(), $self->register($r8)->get())
1169             }
1170             sub _LD_indr16_r8 {
1171 28     28   51 my($self, $r16, $r8) = @_;
1172 28         44 $self->memory()->poke($self->register($r16)->get(), $self->register($r8)->get());
1173             }
1174             sub _LD_r16_imm {
1175             # self, register, lo, hi
1176 189     189   296 my $self = shift;
1177 189         372 $self->register(shift())->set(shift() + 256 * shift());
1178             }
1179             sub _LD_r8_imm {
1180             # self, register, data
1181 299     299   619 my($self, $r, $d, $byte) = @_;
1182             # yuck, (IX+d) puts d first
1183 299 100       700 ($d, $byte) = ($byte, $d) if(!defined($byte));
1184 299         556 $self->register($r)->set($byte);
1185 299 100       893 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1186             }
1187             sub _LD_r16_ind {
1188 8     8   33 my($self, $r16, @bytes) = @_;
1189 8         31 $self->register($r16)->set($self->memory()->peek16($bytes[0] + 256 * $bytes[1]));
1190             }
1191             sub _LD_r8_indr16 {
1192 28     28   56 my($self, $r8, $r16) = @_;
1193 28         48 $self->register($r8)->set($self->memory()->peek($self->register($r16)->get()));
1194             }
1195             sub _LD_r8_ind {
1196 22     22   54 my($self, $r8, @bytes) = @_;
1197 22         77 $self->register($r8)->set($self->memory()->peek($bytes[0] + 256 * $bytes[1]));
1198             }
1199             sub _LD_r8_indHL {
1200 590     590   1180 my($self, $r8, $d) = @_;
1201 590   100     2362 $d = ALU_getsigned($d || 0, 8);
1202 590         1798 $self->register($r8)->set($self->memory()->peek($d + $self->register('HL')->get()));
1203             }
1204             sub _LD_r16_r16 {
1205 9     9   27 my($self, $r1, $r2) = @_;
1206 9         24 $self->register($r1)->set($self->register($r2)->get());
1207             }
1208             sub _LD_r8_r8 {
1209 774     774   1872 my($self, $r1, $r2, $d) = @_;
1210             # print "_LD_r8_r8 $r1, $r2 $d\n" if($d);
1211 774 100 100     3593 if(defined($d) && $r2 eq '(HL)' && $r1 =~ /^[HL]$/) { # LD H/L, (IX/IY+d)
    100 100        
      100        
      100        
1212 4 100       18 $r1 .= $self->_got_prefix(0xDD) ? 'IX' : 'IY';
1213             } elsif(defined($d) && $r1 eq '(HL)' && $r2 =~ /^[HL]$/) { # LD (IX/IY+d), H/L
1214 4 100       12 $r2 .= $self->_got_prefix(0xDD) ? 'IX' : 'IY';
1215             }
1216              
1217 774         1102 my $addr; my @addr; # 'if' optimises away a bunch of ->register->get
1218 774 100 100     2711 if($r1 eq '(HL)' || $r2 eq '(HL)') {
1219 42         101 $addr = $self->register('HL')->get() + ALU_getsigned($d, 8);
1220 42         113 @addr = ($addr & 0xFF, $addr >> 8);
1221             }
1222 774 100       1462 if($r2 eq '(HL)') {
1223 21         87 _LD_r8_ind($self, 'W', @addr);
1224 21         51 $r2 = 'W';
1225             }
1226 774 100       1469 if($r1 eq '(HL)') {
1227 21         81 _LD_ind_r8($self, $r2, @addr);
1228             } else {
1229 753         1353 $self->register($r1)->set($self->register($r2)->get());
1230             }
1231             }
1232             # special casesof LD_r8_r8 which also frob some flags
1233 1     1   4 sub _LD_A_R { _LD_A_IR(shift(), 'R'); }
1234 1     1   5 sub _LD_A_I { _LD_A_IR(shift(), 'I'); }
1235             sub _LD_A_IR {
1236 2     2   7 my($self, $r2) = @_;
1237 2         4 my($a, $f) = map { $self->register($_) } qw(A F);
  4         20  
1238 2         22 _LD_r8_r8($self, 'A', $r2);
1239 2         23 $f->resetH();
1240 2         11 $f->resetN();
1241 2         6 $f->set5($a->get() & 0b100000);
1242 2         4 $f->set3($a->get() & 0b1000);
1243 2         6 $f->setS($a->get() & 0x80);
1244 2         6 $f->setZ($a->get() == 0);
1245 2         8 $f->setP($self->{iff2});
1246             }
1247             sub _NEG {
1248 8     8   19 my $self = shift();
1249 8         49 _LD_r8_imm($self, 'W', 0);
1250 8         37 _SUB_r8_r8($self, 'W', 'A');
1251 8         36 _LD_r8_r8($self, 'A', 'W');
1252             }
1253       282     sub _NOP { }
1254             sub _RLCA {
1255 25     25   48 my $self = shift;
1256 25         55 $self->register('A')->set(
1257             (($self->register('A')->get() & 0b01111111) << 1) |
1258             (($self->register('A')->get() & 0b10000000) >> 7)
1259             );
1260 25         76 $self->register('F')->resetH();
1261 25         92 $self->register('F')->resetN();
1262 25         92 $self->register('F')->set5($self->register('A')->get() & 0b100000);
1263 25         75 $self->register('F')->set3($self->register('A')->get() & 0b1000);
1264 25         65 $self->register('F')->setC($self->register('A')->get() & 1);
1265             }
1266             sub _RRCA {
1267 25     25   51 my $self = shift;
1268 25         70 $self->register('A')->set(
1269             (($self->register('A')->get() & 0b11111110) >> 1) |
1270             (($self->register('A')->get() & 1) << 7)
1271             );
1272 25         68 $self->register('F')->resetH();
1273 25         94 $self->register('F')->resetN();
1274 25         72 $self->register('F')->set5($self->register('A')->get() & 0b100000);
1275 25         111 $self->register('F')->set3($self->register('A')->get() & 0b1000);
1276 25         68 $self->register('F')->setC($self->register('A')->get() & 0x80);
1277             }
1278             sub _RLA {
1279 25     25   51 my $self = shift;
1280 25         56 my $msb = $self->register('A')->get() & 0b10000000;
1281 25         85 $self->register('A')->set(
1282             (($self->register('A')->get() & 0b01111111) << 1) |
1283             $self->register('F')->getC()
1284             );
1285 25         91 $self->register('F')->setC($msb);
1286 25         90 $self->register('F')->resetH();
1287 25         64 $self->register('F')->resetN();
1288             }
1289             sub _RRA {
1290 25     25   47 my $self = shift;
1291 25         58 my $lsb = $self->register('A')->get() & 1;
1292 25         108 my $c = $self->register('F')->getC();
1293 25         69 $self->register('A')->set(
1294             (($self->register('A')->get() & 0b11111110) >> 1) |
1295             ($c << 7)
1296             );
1297 25         66 $self->register('F')->setC($lsb);
1298 25         77 $self->register('F')->resetH();
1299 25         70 $self->register('F')->resetN();
1300             }
1301             # generic wrapper for CB prefixed ROTs - wrap around A-reg version
1302             # and also diddle P/S/Z flags
1303             sub _cb_rot {
1304 96     96   265 my($self, $fn, $r, $d) = @_;
1305              
1306 96 100 100     453 if(defined($d) && $r ne '(HL)') {
1307 56 100       303 $r .= $self->_got_prefix(0xDD) ? 'IX' : 'IY' if($r =~ /^[HL]$/);
    100          
1308 56         115 my $realr = $r;
1309 56         99 $r = '(HL)';
1310 56 50       223 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1311 56 50       270 _swap_regs($self, $r, 'A') if($r ne 'A'); # preserve A, mv r to A
1312 56         217 $fn->($self);
1313 56 50       309 _swap_regs($self, $r, 'A') if($r ne 'A'); # swap back again
1314 56 50       287 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1315 56         3401 _LD_r8_r8($self, $realr, 'W');
1316             } else {
1317 40 100       162 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1318 40 100       189 _swap_regs($self, $r, 'A') if($r ne 'A'); # preserve A, mv r to A
1319 40         163 $fn->($self);
1320 40 100       201 _swap_regs($self, $r, 'A') if($r ne 'A'); # swap back again
1321 40 100       161 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1322             }
1323              
1324             # now frob extra flags
1325 96         1201 $self->register('F')->setP(ALU_parity($self->register($r)->get()));
1326 96         346 $self->register('F')->setS($self->register($r)->get() & 0x80);
1327 96         304 $self->register('F')->setZ($self->register($r)->get() == 0);
1328             }
1329             sub _RLC {
1330 24     24   80 my($self, $r, $d) = @_;
1331 24         123 $self->_cb_rot(\&_RLCA, $r, $d);
1332             }
1333             sub _RRC {
1334 24     24   80 my($self, $r, $d) = @_;
1335 24         90 _cb_rot($self, \&_RRCA, $r, $d);
1336             }
1337             sub _RL {
1338 24     24   97 my($self, $r, $d) = @_;
1339 24         118 _cb_rot($self, \&_RLA, $r, $d);
1340              
1341             # extra flags not done by _cb_rot
1342 24 100       155 $r .= $self->_got_prefix(0xDD) ? 'IX' :
    100          
    100          
1343             $self->_got_prefix(0xFD) ? 'IY' : ''
1344             if($r =~ /^[HL]$/);
1345 24         68 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1346 24         80 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1347             }
1348             sub _RR {
1349 24     24   78 my($self, $r, $d) = @_;
1350 24         112 _cb_rot($self, \&_RRA, $r, $d);
1351 24 100       160 $r .= $self->_got_prefix(0xDD) ? 'IX' :
    100          
    100          
1352             $self->_got_prefix(0xFD) ? 'IY' : ''
1353             if($r =~ /^[HL]$/);
1354 24         62 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1355 24         67 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1356             }
1357             sub _SLA {
1358 24     24   86 my($self, $r, $d) = @_;
1359              
1360 24 100 100     145 if(defined($d) && $r ne '(HL)') { # weirdo DDCB*
1361 14         32 my $realr = $r;
1362 14 100       99 $realr .= $self->_got_prefix(0xDD) ? 'IX' : 'IY'
    100          
1363             if($realr =~ /^[HL]$/);
1364 14         29 $r = '(HL)';
1365 14         56 _LD_r8_indHL($self, 'W', $d);
1366 14         65 $self->register('F')->setC($self->register($r)->get() & 0x80);
1367 14         69 $self->register($r)->set($self->register($r)->get() << 1);
1368 14         69 _LD_indHL_r8($self, 'W', $d);
1369 14         822 _LD_r8_r8($self, $realr, 'W');
1370             } else {
1371 10 100       55 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1372 10         31 $self->register('F')->setC($self->register($r)->get() & 0x80);
1373 10         35 $self->register($r)->set($self->register($r)->get() << 1);
1374 10 100       44 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1375             }
1376              
1377 24         381 $self->register('F')->setZ($self->register($r)->get() == 0);
1378 24         86 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1379 24         102 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1380 24         113 $self->register('F')->setP(ALU_parity($self->register($r)->get()));
1381 24         113 $self->register('F')->setS($self->register($r)->get() & 0x80);
1382 24         111 $self->register('F')->resetH();
1383 24         80 $self->register('F')->resetN();
1384             }
1385             sub _SLL {
1386 24     24   96 my($self, $r, $d) = @_;
1387              
1388 24 100 100     129 if(defined($d) && $r ne '(HL)') { # weirdo DDCB*
1389 14         33 my $realr = $r;
1390 14 100       97 $realr .= $self->_got_prefix(0xDD) ? 'IX' : 'IY'
    100          
1391             if($realr =~ /^[HL]$/);
1392 14         28 $r = '(HL)';
1393 14         49 _LD_r8_indHL($self, 'W', $d);
1394 14         48 $self->register('F')->setC($self->register($r)->get() & 0x80);
1395 14         42 $self->register($r)->set($self->register($r)->get() << 1);
1396 14         52 $self->register($r)->set($self->register($r)->get() | 1);
1397 14         71 _LD_indHL_r8($self, 'W', $d);
1398 14         930 _LD_r8_r8($self, $realr, 'W');
1399             } else {
1400 10 100       42 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1401 10         42 $self->register('F')->setC($self->register($r)->get() & 0x80);
1402 10         55 $self->register($r)->set($self->register($r)->get() << 1);
1403 10         33 $self->register($r)->set($self->register($r)->get() | 1);
1404 10 100       41 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1405             }
1406              
1407 24         317 $self->register('F')->setZ($self->register($r)->get() == 0);
1408 24         86 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1409 24         77 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1410 24         78 $self->register('F')->setP(ALU_parity($self->register($r)->get()));
1411 24         103 $self->register('F')->setS($self->register($r)->get() & 0x80);
1412 24         88 $self->register('F')->resetH();
1413 24         78 $self->register('F')->resetN();
1414             }
1415             sub _SRA {
1416 24     24   77 my($self, $r, $d) = @_;
1417              
1418 24 100 100     106 if(defined($d) && $r ne '(HL)') { # weirdo DDCB*
1419 14         25 my $realr = $r;
1420 14 100       79 $realr .= $self->_got_prefix(0xDD) ? 'IX' : 'IY'
    100          
1421             if($realr =~ /^[HL]$/);
1422 14         37 $r = '(HL)';
1423 14         42 _LD_r8_indHL($self, 'W', $d);
1424 14         53 $self->register('F')->setC($self->register($r)->get() & 1);
1425 14         56 $self->register($r)->set(
1426             ($self->register($r)->get() & 0x80) |
1427             ($self->register($r)->get() >> 1)
1428             );
1429 14         57 _LD_indHL_r8($self, 'W', $d);
1430 14         1056 _LD_r8_r8($self, $realr, 'W');
1431             } else {
1432 10 100       66 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1433 10         30 $self->register('F')->setC($self->register($r)->get() & 1);
1434 10         40 $self->register($r)->set(
1435             ($self->register($r)->get() & 0x80) |
1436             ($self->register($r)->get() >> 1)
1437             );
1438 10 100       42 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1439             }
1440              
1441 24         252 $self->register('F')->setZ($self->register($r)->get() == 0);
1442 24         89 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1443 24         108 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1444 24         87 $self->register('F')->setP(ALU_parity($self->register($r)->get()));
1445 24         81 $self->register('F')->setS($self->register($r)->get() & 0x80);
1446 24         83 $self->register('F')->resetH();
1447 24         98 $self->register('F')->resetN();
1448             }
1449             sub _SRL {
1450 24     24   89 my($self, $r, $d) = @_;
1451              
1452 24 100 100     130 if(defined($d) && $r ne '(HL)') { # weirdo DDCB*
1453 14         27 my $realr = $r;
1454 14 100       93 $realr .= $self->_got_prefix(0xDD) ? 'IX' : 'IY'
    100          
1455             if($realr =~ /^[HL]$/);
1456 14         27 $r = '(HL)';
1457 14         47 _LD_r8_indHL($self, 'W', $d);
1458 14         57 $self->register('F')->setC($self->register($r)->get() & 1);
1459 14         39 $self->register($r)->set(
1460             ($self->register($r)->get() & 0x80) |
1461             ($self->register($r)->get() >> 1)
1462             );
1463 14         45 $self->register($r)->set($self->register($r)->get() & 0x7F);
1464 14         52 _LD_indHL_r8($self, 'W', $d);
1465 14         1034 _LD_r8_r8($self, $realr, 'W');
1466             } else {
1467 10 100       57 _LD_r8_indHL($self, 'W', $d) if($r eq '(HL)');
1468 10         32 $self->register('F')->setC($self->register($r)->get() & 1);
1469 10         44 $self->register($r)->set(
1470             ($self->register($r)->get() & 0x80) |
1471             ($self->register($r)->get() >> 1)
1472             );
1473 10         41 $self->register($r)->set($self->register($r)->get() & 0x7F);
1474 10 100       42 _LD_indHL_r8($self, 'W', $d) if($r eq '(HL)');
1475             }
1476              
1477 24         164 $self->register('F')->setZ($self->register($r)->get() == 0);
1478 24         75 $self->register('F')->set5($self->register($r)->get() & 0b100000);
1479 24         90 $self->register('F')->set3($self->register($r)->get() & 0b1000);
1480 24         81 $self->register('F')->setP(ALU_parity($self->register($r)->get()));
1481 24         89 $self->register('F')->setS($self->register($r)->get() & 0x80);
1482 24         90 $self->register('F')->resetH();
1483 24         80 $self->register('F')->resetN();
1484             }
1485             sub _DAA {
1486 2     2   5 my $self = shift;
1487 2         5 my $a = $self->register('A');
1488 2         17 my $f = $self->register('F');
1489 2         30 my($n, $h, $lo, $hi) =
1490             ($f->getN(), $f->getH(),
1491             $a->get() & 0x0F, ($a->get() >> 4) & 0x0F);
1492 2         38 my $table = [
1493             # NB this table comes from Sean Young's "The Undocumented
1494             # Z80 Documented". Zaks is wrong.
1495             # http://www.z80.info/zip/z80-documented.pdf
1496             # C high H low add Cafter
1497             [qw(0 0-9 0 0-9 0 0)],
1498             [qw(0 0-9 1 0-9 6 0)],
1499             [qw(0 0-8 . a-f 6 0)],
1500             [qw(0 a-f 0 0-9 60 1)],
1501             [qw(1 0-9a-f 0 0-9 60 1)],
1502             [qw(1 0-9a-f 1 0-9 66 1)],
1503             [qw(1 0-9a-f . a-f 66 1)],
1504             [qw(0 9a-f . a-f 66 1)],
1505             [qw(0 a-f 1 0-9 66 1)],
1506             ];
1507 2         5 foreach my $row (@{$table}) {
  2         5  
1508 11         15 my @row = @{$row};
  11         21  
1509 11 100 100     35 if(
      100        
      100        
      100        
1510             $f->getC() == $row[0] &&
1511             ($row[2] eq '.' || $f->getH() == $row[2]) &&
1512             sprintf('%x', ($a->get() >> 4) & 0x0F) =~ /^[$row[1]]$/ &&
1513             sprintf('%x', $a->get() & 0x0F) =~ /^[$row[3]]$/
1514             ) {
1515 2 100       16 $f->getN() ? $a->set(ALU_sub8($f, $a->get(), hex($row[4])))
1516             : $a->set(ALU_add8($f, $a->get(), hex($row[4])));
1517 2         9 $f->setC($row[5]);
1518 2         7 last;
1519             }
1520             }
1521 2 100       18 $f->setH($lo > 9) if(!$n);
1522 2 100 66     12 $f->resetH() if($n && !$h);
1523 2 50 66     7 $f->setH($lo < 6) if($n && $h);
1524 2         5 $f->set3($a->get() & 0b1000);
1525 2         7 $f->set5($a->get() & 0b100000);
1526 2         7 $f->setP(ALU_parity($a->get()));
1527             }
1528             sub _CPL {
1529 1     1   2 my $self = shift;
1530 1         3 $self->register('A')->set(~ $self->register('A')->get());
1531 1         3 $self->register('F')->setH();
1532 1         3 $self->register('F')->setN();
1533 1         3 $self->register('F')->set3($self->register('A')->get() & 0b1000);
1534 1         3 $self->register('F')->set5($self->register('A')->get() & 0b100000);
1535             }
1536             sub _SCF {
1537 4     4   7 my $self = shift();
1538 4         13 my $f = $self->register('F');
1539 4         34 my $a = $self->register('A');
1540 4         85 $f->setC();
1541 4         24 $f->resetH();
1542 4         19 $f->resetN();
1543 4         91 $f->set5($a->get() & 0b100000);
1544 4         11 $f->set3($a->get() & 0b1000);
1545             }
1546             sub _CCF {
1547 1     1   2 my $self = shift;
1548 1         4 my $f = $self->register('F');
1549 1         10 my $a = $self->register('A');
1550 1         18 $f->setH($f->getC());
1551 1         5 $f->setC(!$f->getC());
1552 1         6 $f->resetN();
1553 1         5 $f->set5($a->get() & 0b100000);
1554 1         5 $f->set3($a->get() & 0b1000);
1555             }
1556             sub _POP {
1557 30     30   89 my($self, $r) = @_;
1558 30         80 $self->register($r)->set(
1559             $self->memory()->peek16($self->register('SP')->get())
1560             );
1561 30         108 $self->register('SP')->add(2);
1562             }
1563             sub _PUSH {
1564 32     32   91 my($self, $r) = @_;
1565 32         80 $self->register('SP')->sub(2);
1566 32         95 $self->memory()->poke16(
1567             $self->register('SP')->get(),
1568             $self->register($r)->get()
1569             );
1570             }
1571             sub _IN_A_n {
1572 8     8   12 my($self, $lobyte) = @_;
1573 8         12 $self->register('A')->set(
1574             $self->_get_from_input(($self->register('A')->get() << 8) + $lobyte)
1575             );
1576             }
1577             sub _IN_r_C {
1578 30     30   59 my($self, $r) = @_;
1579 30         148 $r = $self->register($r); # for (HL) this is W and magically correct!
1580 30         251 $r->set($self->_get_from_input($self->register('BC')->get()));
1581            
1582 30         133 my $f = $self->register('F');
1583 30         237 $f->setS($r->get() & 0x80);
1584 30         74 $f->setZ($r->get() == 0);
1585 30         75 $f->set5($r->get() & 0b100000);
1586 30         146 $f->resetH();
1587 30         85 $f->set3($r->get() & 0b1000);
1588 30         72 $f->setP(ALU_parity($r->get()));
1589             }
1590              
1591             sub _OUT_n_A { # output A to B<<8 + n
1592 1     1   3 my($self, $n) = @_;
1593 1         3 $self->_put_to_output(
1594             ($self->register('B')->get() << 8) + $n,
1595             $self->register('A')->get()
1596             );
1597             }
1598             sub _OUT_C_r {
1599 8     8   14 my($self, $r) = @_;
1600 8         18 $self->_put_to_output(
1601             $self->register('BC')->get(),
1602             $self->register($r)->get()
1603             );
1604             }
1605             sub _OUT_C_0 {
1606 1     1   2 my $self = shift();
1607 1         2 $self->register('W')->set(0);
1608 1         3 _OUT_C_r($self, 'W');
1609             }
1610             sub _IND {
1611 3     3   5 my $self = shift;
1612 3         10 _IN_r_C($self, '(HL)');
1613 3         11 _LD_indHL_r8($self, 'W', 0);
1614 3         46 $self->register($_)->dec() foreach(qw(HL B));
1615             }
1616             sub _INI {
1617 3     3   6 my $self = shift;
1618 3         8 _IN_r_C($self, '(HL)');
1619 3         12 _LD_indHL_r8($self, 'W');
1620 3         45 $self->register('HL')->inc();
1621 3         6 $self->register('B')->dec();
1622             }
1623             sub _INDR {
1624 2     2   4 my $self = shift;
1625 2         6 _IND($self);
1626 2 100       5 $self->register('PC')->set($self->register('PC')->get() - 2)
1627             if($self->register('B')->get());
1628             }
1629             sub _INIR {
1630 2     2   5 my $self = shift;
1631 2         6 _INI($self);
1632 2 100       6 $self->register('PC')->set($self->register('PC')->get() - 2)
1633             if($self->register('B')->get());
1634             }
1635             sub _OUTD {
1636 4     4   5 my $self = shift;
1637 4         9 $self->register('B')->dec();
1638 4         10 $self->_put_to_output(
1639             $self->register('BC')->get(),
1640             $self->memory()->peek($self->register('HL')->get())
1641             );
1642 4         16 $self->register('HL')->dec();
1643             }
1644             sub _OUTI {
1645 4     4   6 my $self = shift;
1646 4         7 $self->register('B')->dec();
1647 4         12 $self->_put_to_output(
1648             $self->register('BC')->get(),
1649             $self->memory()->peek($self->register('HL')->get())
1650             );
1651 4         16 $self->register('HL')->inc();
1652             }
1653             sub _OTDR {
1654 3     3   4 my $self = shift;
1655 3         16 _OUTD($self);
1656 3 100       7 $self->register('PC')->set($self->register('PC')->get() - 2)
1657             if($self->register('B')->get());
1658             }
1659             sub _OTIR {
1660 3     3   4 my $self = shift;
1661 3         7 _OUTI($self);
1662 3 100       7 $self->register('PC')->set($self->register('PC')->get() - 2)
1663             if($self->register('B')->get());
1664             }
1665              
1666       8     sub _IM {} # everything is IM 1
1667              
1668             sub _RETI {
1669 1     1   6 _POP(shift(), 'PC');
1670             }
1671             sub _RETN {
1672 7     7   28 my $self = shift();
1673 7         20 $self->{iff1} = $self->{iff2};
1674 7         27 _POP($self, 'PC');
1675             }
1676             sub _DI {
1677 5     5   266 my $self = shift;
1678 5         14 _interrupts_enabled($self, 0);
1679             }
1680             sub _EI {
1681 3     3   356 my $self = shift;
1682 3         9 _interrupts_enabled($self, 1);
1683             }
1684             sub _swap_regs {
1685 1636     1636   2919 my($self, $r1, $r2) = @_;
1686 1636         2743 my $temp = $self->register($r1)->get();
1687 1636         3280 $self->register($r1)->set($self->register($r2)->get());
1688 1636         3608 $self->register($r2)->set($temp);
1689             }
1690              
1691             =head1 EXTRA INSTRUCTIONS
1692              
1693             Whenever any combination of two of the 0xDD and 0xFD prefixes are
1694             met, behaviour deviates from that of a normal Z80 and instead
1695             depends on the following byte:
1696              
1697             =head2 0x00 - STOP
1698              
1699             The run() method stops, even if the desired number of instructions
1700             has not yet been reached.
1701              
1702             =head2 anything else
1703              
1704             Fatal error.
1705              
1706             =head1 PROGRAMMING THE Z80
1707              
1708             I recommend "Programming the Z80" by Rodnay Zaks. This excellent
1709             book is unfortunately out of print, but may be available through
1710             abebooks.com
1711             L.
1712              
1713             =head1 BUGS/WARNINGS/LIMITATIONS
1714              
1715             Claims about making your code faster may not be true in all realities.
1716              
1717             I assume you're using a twos-complement machine. I *think* that
1718             that's true of anything perl runs on.
1719              
1720             Only interrupt mode 1 is implemented. All interrupts are serviced
1721             by a RST 0x38 instruction.
1722              
1723             The DDFD- and FDDD-prefixed instructions (the "use this index
1724             register - no, wait, I meant the other one" prefixes) and the DDDD-
1725             and FDFD-prefixed instructions (the "use this index register, no
1726             really, I mean it, pleeeeease" prefixes) are silly,
1727             and have been replaced - see "Extra Instructions" above.
1728              
1729             =head1 FEEDBACK
1730              
1731             I welcome feedback about my code, including constructive criticism
1732             and bug reports. The best bug reports include files that I can add
1733             to the test suite, which fail with the current code and will
1734             pass once I've fixed the bug.
1735              
1736             Feature requests are far more likely to get implemented if you submit
1737             a patch yourself.
1738              
1739             =head1 SEE ALSO
1740              
1741             L
1742              
1743             L
1744              
1745             The FUSE Free Unix Spectrum Emulator: L
1746              
1747             =head1 SOURCE CODE REPOSITORY
1748              
1749             L
1750              
1751             =head1 AUTHOR, COPYRIGHT and LICENCE
1752              
1753             Copyright 2008 David Cantrell EFE
1754              
1755             This software is free-as-in-speech software, and may be used,
1756             distributed, and modified under the terms of either the GNU
1757             General Public Licence version 2 or the Artistic Licence. It's
1758             up to you which one you use. The full text of the licences can
1759             be found in the files GPL2.txt and ARTISTIC.txt, respectively.
1760              
1761             =head1 CONSPIRACY
1762              
1763             This module is also free-as-in-mason software.
1764              
1765             =cut
1766              
1767             1;