1 /*
2 * Simulator of microcontrollers (inst_xd.cc)
3 * dd or fd escaped multi-byte opcodes.
4 *
5 * This module gets pulled in and pre-processed to create
6 * two modules. DD prefixed opcodes reference
7 * IX register, while FD prefixes reference IY register.
8 * See inst_ddcb.cc and inst_fdcb.cc
9 *
10 * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt.
11 * some z80 coding from Karl Bongers karl@turbobit.com
12 *
13 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
14 *
15 */
16
17 /* This file is part of microcontroller simulator: ucsim.
18
19 UCSIM is free software; you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation; either version 2 of the License, or
22 (at your option) any later version.
23
24 UCSIM is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28
29 You should have received a copy of the GNU General Public License
30 along with UCSIM; see the file COPYING. If not, write to the Free
31 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
32 02111-1307, USA. */
33 /*@1@*/
34
35 int
inst_Xd_ld(t_mem code)36 cl_z80::inst_Xd_ld(t_mem code)
37 {
38 unsigned short tw;
39
40 switch (code) {
41 case 0x21: // LD IX,nnnn
42 regs_IX_OR_IY = fetch2();
43 return(resGO);
44 case 0x22: // LD (nnnn),IX
45 tw = fetch2();
46 store2(tw, regs_IX_OR_IY);
47 vc.wr+= 2;
48 return(resGO);
49 case 0x26: // LD HX,nn
50 regs_iX_h = fetch1();
51 return(resGO);
52 case 0x2A: // LD IX,(nnnn)
53 tw = fetch2();
54 regs_IX_OR_IY = get2(tw);
55 vc.rd+= 2;
56 return(resGO);
57 case 0x2E: // LD LX,nn
58 regs_iX_l = fetch1();
59 return(resGO);
60 case 0x36: // LD (IX+dd),nn
61 tw = add_u16_disp(regs_IX_OR_IY, fetch());
62 store1(tw, fetch());
63 vc.wr++;
64 return(resGO);
65 case 0x44: // LD B,HX
66 regs.bc.h = regs_iX_h;
67 return(resGO);
68 case 0x45: // LD B,LX
69 regs.bc.h = regs_iX_l;
70 return(resGO);
71 case 0x46: // LD B,(IX+dd)
72 regs.bc.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
73 vc.rd++;
74 return(resGO);
75 case 0x4C: // LD C,HX
76 regs.bc.l = regs_iX_h;
77 return(resGO);
78 case 0x4D: // LD C,LX
79 regs.bc.l = regs_iX_l;
80 return(resGO);
81 case 0x4E: // LD C,(IX+dd)
82 regs.bc.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
83 vc.rd++;
84 return(resGO);
85 case 0x54: // LD D,HX
86 regs.de.h = regs_iX_h;
87 return(resGO);
88 case 0x55: // LD D,LX
89 regs.de.h = regs_iX_l;
90 return(resGO);
91 case 0x56: // LD D,(IX+dd)
92 regs.de.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
93 vc.rd++;
94 return(resGO);
95 case 0x5C: // LD E,H
96 regs.de.l = regs.hl.h;
97 return(resGO);
98 case 0x5D: // LD E,L
99 regs.de.l = regs.hl.l;
100 return(resGO);
101 case 0x5E: // LD E,(IX+dd)
102 regs.de.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
103 vc.rd++;
104 return(resGO);
105 case 0x60: // LD HX,B
106 regs_iX_h = regs.bc.h;
107 return(resGO);
108 case 0x61: // LD HX,C
109 regs_iX_h = regs.bc.l;
110 return(resGO);
111 case 0x62: // LD HX,D
112 regs_iX_h = regs.de.h;
113 return(resGO);
114 case 0x63: // LD HX,E
115 regs_iX_h = regs.de.l;
116 return(resGO);
117 case 0x64: // LD HX,HX
118 return(resGO);
119 case 0x65: // LD HX,LX
120 regs_iX_h = regs_iX_l;
121 return(resGO);
122 case 0x66: // LD H,(IX+dd)
123 regs.hl.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
124 vc.rd++;
125 return(resGO);
126 case 0x67: // LD HX,A
127 regs_iX_h = regs.raf.A;
128 return(resGO);
129 case 0x68: // LD LX,B
130 regs_iX_l = regs.bc.h;
131 return(resGO);
132 case 0x69: // LD LX,C
133 regs_iX_l = regs.bc.l;
134 return(resGO);
135 case 0x6A: // LD LX,D
136 regs_iX_l = regs.de.h;
137 return(resGO);
138 case 0x6B: // LD LX,E
139 regs_iX_l = regs.de.l;
140 return(resGO);
141 case 0x6C: // LD LX,HX
142 regs_iX_l = regs.hl.h;
143 return(resGO);
144 case 0x6D: // LD LX,LX
145 return(resGO);
146 case 0x6E: // LD L,(IX+dd)
147 regs.hl.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
148 vc.rd++;
149 return(resGO);
150 case 0x6F: // LD LX,A
151 regs_iX_l = regs.raf.A;
152 return(resGO);
153 case 0x70: // LD (IX+dd),B
154 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.bc.h);
155 vc.wr++;
156 return(resGO);
157 case 0x71: // LD (IX+dd),C
158 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.bc.l);
159 vc.wr++;
160 return(resGO);
161 case 0x72: // LD (IX+dd),D
162 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.de.h);
163 vc.wr++;
164 return(resGO);
165 case 0x73: // LD (IX+dd),E
166 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.de.l);
167 vc.wr++;
168 return(resGO);
169 case 0x74: // LD (IX+dd),H
170 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.hl.h);
171 vc.wr++;
172 return(resGO);
173 case 0x75: // LD (IX+dd),L
174 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.hl.l);
175 vc.wr++;
176 return(resGO);
177 case 0x77: // LD (IX+dd),A
178 store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.raf.A);
179 vc.wr++;
180 return(resGO);
181 case 0x7C: // LD A,HX
182 regs.raf.A = regs_iX_h;
183 return(resGO);
184 case 0x7D: // LD A,LX
185 regs.raf.A = regs_iX_l;
186 return(resGO);
187 case 0x7E: // LD A,(IX+dd)
188 regs.raf.A = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
189 vc.rd++;
190 return(resGO);
191 case 0xF9: // LD SP,IX
192 regs.SP = regs_IX_OR_IY;
193 return(resGO);
194 }
195 return(resINV_INST);
196 }
197
198 int
inst_Xd_add(t_mem code)199 cl_z80::inst_Xd_add(t_mem code)
200 {
201 switch (code) {
202 case 0x09: // ADD IX,BC
203 add_IX_Word(regs.BC);
204 return(resGO);
205 case 0x19: // ADD IX,DE
206 add_IX_Word(regs.DE);
207 return(resGO);
208 case 0x29: // ADD IX,IX
209 add_IX_Word(regs_IX_OR_IY);
210 return(resGO);
211 case 0x39: // ADD IX,SP
212 add_IX_Word(regs.SP);
213 return(resGO);
214 case 0x84: // ADD A,HX
215 add_A_bytereg(regs_iX_h);
216 return(resGO);
217 case 0x85: // ADD A,LX
218 add_A_bytereg(regs_iX_l);
219 return(resGO);
220 case 0x86: // ADD A,(IX+dd)
221 { unsigned char ourtmp;
222 t_addr addr;
223 addr = add_u16_disp(regs_IX_OR_IY, fetch());
224 ourtmp = get1(addr);
225 add_A_bytereg(ourtmp);
226 vc.rd++;
227 }
228 return(resGO);
229 }
230 return(resINV_INST);
231 }
232
233 int
inst_Xd_push(t_mem code)234 cl_z80::inst_Xd_push(t_mem code)
235 {
236 switch (code) {
237 case 0xe5: // PUSH IX
238 push2(regs_IX_OR_IY);
239 vc.wr+= 2;
240 return(resGO);
241 }
242 return(resINV_INST);
243 }
244
245 int
inst_Xd_inc(t_mem code)246 cl_z80::inst_Xd_inc(t_mem code)
247 {
248 switch(code) {
249 case 0x23: // INC IX
250 ++regs_IX_OR_IY;
251 break;
252 case 0x24: // INC HX
253 inc(regs_iX_h);
254 break;
255 case 0x2C: // INC LX
256 inc(regs_iX_l);
257 break;
258 case 0x34: // INC (IX+dd)
259 {
260 t_addr addr;
261 unsigned char tmp;
262 addr = add_u16_disp(regs_IX_OR_IY,fetch());
263 tmp = get1(addr);
264 inc(tmp);
265 store1(addr, tmp);
266 vc.rd++;
267 vc.wr++;
268 }
269 break;
270 default:
271 return(resINV_INST);
272 break;
273 }
274 return(resGO);
275 }
276
277 int
inst_Xd_dec(t_mem code)278 cl_z80::inst_Xd_dec(t_mem code)
279 {
280 switch(code) {
281 case 0x25: // DEC HX
282 dec(regs_iX_h);
283 break;
284 case 0x2B: // DEC IX
285 --regs_IX_OR_IY;
286 break;
287 case 0x2D: // DEC LX
288 dec(regs_iX_l);
289 break;
290 case 0x35: // DEC (IX+dd)
291 {
292 t_addr addr;
293 unsigned char tmp;
294 addr = add_u16_disp(regs_IX_OR_IY,fetch());
295 tmp = get1(addr);
296 dec(tmp);
297 store1(addr, tmp);
298 vc.rd++;
299 vc.wr++;
300 }
301 break;
302 default:
303 return(resINV_INST);
304 break;
305 }
306 return(resGO);
307 }
308
309
310 /* need ADC, SUB, SBC, AND, XOR, OR, CP */
311 int
inst_Xd_misc(t_mem code)312 cl_z80::inst_Xd_misc(t_mem code)
313 {
314 switch(code) {
315 case 0x8C: // ADC A,HX
316 adc_A_bytereg(regs_iX_h);
317 return(resGO);
318 case 0x8D: // ADC A,LX
319 adc_A_bytereg(regs_iX_l);
320 return(resGO);
321 case 0x8E: // ADC A,(IX+dd)
322 { unsigned char utmp;
323 t_addr addr;
324 addr = add_u16_disp(regs_IX_OR_IY, fetch());
325 utmp = get1(addr);
326 adc_A_bytereg(utmp);
327 vc.rd++;
328 }
329 return(resGO);
330
331 case 0x94: // SUB HX
332 sub_A_bytereg(regs_iX_h);
333 return(resGO);
334 case 0x95: // SUB LX
335 sub_A_bytereg(regs_iX_l);
336 return(resGO);
337 case 0x96: // SUB (IX+dd)
338 { unsigned char tmp1;
339 tmp1 = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
340 sub_A_bytereg(tmp1);
341 vc.rd++;
342 }
343 return(resGO);
344
345 case 0x9C: // SBC A,HX
346 sbc_A_bytereg(regs_iX_h);
347 return(resGO);
348 case 0x9D: // SBC A,LX
349 sbc_A_bytereg(regs_iX_l);
350 return(resGO);
351 case 0x9E: // SBC A,(IX+dd)
352 { unsigned char utmp;
353 utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
354 sbc_A_bytereg(utmp);
355 vc.rd++;
356 }
357 return(resGO);
358
359 case 0xA4: // AND HX
360 and_A_bytereg(regs_iX_h);
361 return(resGO);
362 case 0xA5: // AND LX
363 and_A_bytereg(regs_iX_l);
364 return(resGO);
365 case 0xA6: // AND (IX+dd)
366 { unsigned char utmp;
367 utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
368 and_A_bytereg(utmp);
369 vc.rd++;
370 }
371 return(resGO);
372
373 case 0xAC: // XOR HX
374 xor_A_bytereg(regs_iX_h);
375 return(resGO);
376 case 0xAD: // XOR LX
377 xor_A_bytereg(regs_iX_l);
378 return(resGO);
379 case 0xAE: // XOR (IX+dd)
380 { unsigned char utmp;
381 utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
382 xor_A_bytereg(utmp);
383 vc.rd++;
384 }
385 return(resGO);
386
387 case 0xB4: // OR HX
388 or_A_bytereg(regs_iX_h);
389 return(resGO);
390 case 0xB5: // OR LX
391 or_A_bytereg(regs_iX_l);
392 return(resGO);
393 case 0xB6: // OR (IX+dd)
394 { unsigned char utmp;
395 utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
396 or_A_bytereg(utmp);
397 vc.rd++;
398 }
399 return(resGO);
400
401 case 0xBC: // CP HX
402 cp_bytereg(regs_iX_h);
403 return(resGO);
404 case 0xBD: // CP LX
405 cp_bytereg(regs_iX_l);
406 return(resGO);
407 case 0xBE: // CP (IX+dd)
408 { unsigned char utmp;
409 utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
410 cp_bytereg(utmp);
411 vc.rd++;
412 }
413 return(resGO);
414 }
415 return(resINV_INST);
416 }
417
418 int
inst_Xd(t_mem prefix)419 cl_z80::inst_Xd(t_mem prefix)
420 {
421 t_mem code;
422 int i;
423
424 if (fetch(&code))
425 return(resBREAKPOINT);
426
427 switch (prefix)
428 {
429 case 0xdd:
430 if ((i= inst_dd_spec(code)) >= 0)
431 return i;
432 case 0xfd:
433 if ((i= inst_fd_spec(code)) >= 0)
434 return i;
435 }
436
437 switch (code)
438 {
439 case 0x21: // LD IX,nnnn
440 case 0x22: // LD (nnnn),IX
441 case 0x26: // LD HX,nn
442 case 0x2A: // LD IX,(nnnn)
443 case 0x2E: // LD LX,nn
444 case 0x36: // LD (IX+dd),nn
445 case 0x44: // LD B,HX
446 case 0x45: // LD B,LX
447 case 0x46: // LD B,(IX+dd)
448 case 0x4C: // LD C,HX
449 case 0x4D: // LD C,LX
450 case 0x4E: // LD C,(IX+dd)
451 case 0x54: // LD D,HX
452 case 0x55: // LD D,LX
453 case 0x56: // LD D,(IX+dd)
454 case 0x5C: // LD E,H
455 case 0x5D: // LD E,L
456 case 0x5E: // LD E,(IX+dd)
457 case 0x60: // LD HX,B
458 case 0x61: // LD HX,C
459 case 0x62: // LD HX,D
460 case 0x63: // LD HX,E
461 case 0x64: // LD HX,HX
462 case 0x66: // LD H,(IX+dd)
463 case 0x67: // LD HX,A
464 case 0x68: // LD LX,B
465 case 0x69: // LD LX,C
466 case 0x6A: // LD LX,D
467 case 0x6B: // LD LX,E
468 case 0x6C: // LD LX,HX
469 case 0x6D: // LD LX,LX
470 case 0x6E: // LD L,(IX+dd)
471 case 0x6F: // LD LX,A
472 case 0x70: // LD (IX+dd),B
473 case 0x71: // LD (IX+dd),C
474 case 0x72: // LD (IX+dd),D
475 case 0x73: // LD (IX+dd),E
476 case 0x74: // LD (IX+dd),H
477 case 0x75: // LD (IX+dd),L
478 case 0x77: // LD (IX+dd),A
479 case 0x7C: // LD A,HX
480 case 0x7D: // LD A,LX
481 case 0x7E: // LD A,(IX+dd)
482 case 0xF9: // LD SP,IX
483 return(inst_Xd_ld(code));
484
485 case 0x23: // INC IX
486 case 0x24: // INC HX
487 case 0x2C: // INC LX
488 case 0x34: // INC (IX+dd)
489 return(inst_Xd_inc(code));
490
491 case 0x09: // ADD IX,BC
492 case 0x19: // ADD IX,DE
493 case 0x29: // ADD IX,IX
494 case 0x39: // ADD IX,SP
495 case 0x84: // ADD A,HX
496 case 0x85: // ADD A,LX
497 case 0x86: // ADD A,(IX)
498 return(inst_Xd_add(code));
499
500 case 0x25: // DEC HX
501 case 0x2B: // DEC IX
502 case 0x2D: // DEC LX
503 case 0x35: // DEC (IX+dd)
504 return(inst_Xd_dec(code));
505
506 case 0x8C: // ADC A,HX
507 case 0x8D: // ADC A,LX
508 case 0x8E: // ADC A,(IX)
509 case 0x94: // SUB HX
510 case 0x95: // SUB LX
511 case 0x96: // SUB (IX+dd)
512 case 0x9C: // SBC A,HX
513 case 0x9D: // SBC A,LX
514 case 0x9E: // SBC A,(IX+dd)
515 case 0xA4: // AND HX
516 case 0xA5: // AND LX
517 case 0xA6: // AND (IX+dd)
518 case 0xAC: // XOR HX
519 case 0xAD: // XOR LX
520 case 0xAE: // XOR (IX+dd)
521 case 0xB4: // OR HX
522 case 0xB5: // OR LX
523 case 0xB6: // OR (IX+dd)
524 case 0xBC: // CP HX
525 case 0xBD: // CP LX
526 case 0xBE: // CP (IX+dd)
527 return(inst_Xd_misc(code));
528 break;
529
530 case 0xCB: // escape, IX prefix to CB commands
531 return(inst_Xdcb()); /* see inst_ddcb.cc */
532 break;
533
534 case 0xE1: // POP IX
535 regs_IX_OR_IY = get2(regs.SP);
536 regs.SP+=2;
537 vc.rd+= 2;
538 return(resGO);
539
540 case 0xE3: // EX (SP),IX
541 {
542 u16_t tempw;
543
544 tempw = regs_IX_OR_IY;
545 regs_IX_OR_IY = get2(regs.SP);
546 store2(regs.SP, tempw);
547 vc.rd+= 2;
548 vc.wr+= 2;
549 }
550 return(resGO);
551
552 case 0xE5: // PUSH IX
553 push2(regs_IX_OR_IY);
554 vc.wr+= 2;
555 return(resGO);
556
557 case 0xE9: // JP (IX)
558 PC = regs_IX_OR_IY;
559 return(resGO);
560
561 default:
562 return(resINV_INST);
563 }
564 return(resINV_INST);
565 }
566
567 /* End of z80.src/inst_xd.cc */
568