Imported Upstream version 2.9.0
[debian/cc1111] / sim / ucsim / z80.src / inst_xd.cc
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
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     return(resGO);
48     case 0x26: // LD HX,nn
49       regs_iX_h = fetch1();
50     return(resGO);
51     case 0x2A: // LD IX,(nnnn)
52       tw = fetch2();
53       regs_IX_OR_IY = get2(tw);
54     return(resGO);
55     case 0x2E: // LD LX,nn
56       regs_iX_l = fetch1();
57     return(resGO);
58     case 0x36: // LD (IX+dd),nn
59       tw = add_u16_disp(regs_IX_OR_IY, fetch());
60       store1(tw, fetch());
61     return(resGO);
62     case 0x44: // LD B,HX
63       regs.bc.h = regs_iX_h;
64     return(resGO);
65     case 0x45: // LD B,LX
66       regs.bc.h = regs_iX_l;
67     return(resGO);
68     case 0x46: // LD B,(IX+dd)
69       regs.bc.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
70     return(resGO);
71     case 0x4C: // LD C,HX
72       regs.bc.l = regs_iX_h;
73     return(resGO);
74     case 0x4D: // LD C,LX
75       regs.bc.l = regs_iX_l;
76     return(resGO);
77     case 0x4E: // LD C,(IX+dd)
78       regs.bc.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
79     return(resGO);
80     case 0x54: // LD D,HX
81       regs.de.h = regs_iX_h;
82     return(resGO);
83     case 0x55: // LD D,LX
84       regs.de.h = regs_iX_l;
85     return(resGO);
86     case 0x56: // LD D,(IX+dd)
87       regs.de.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
88     return(resGO);
89     case 0x5C: // LD E,H
90       regs.de.l = regs.hl.h;
91     return(resGO);
92     case 0x5D: // LD E,L
93       regs.de.l = regs.hl.l;
94     return(resGO);
95     case 0x5E: // LD E,(IX+dd)
96       regs.de.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
97     return(resGO);
98     case 0x60: // LD HX,B
99       regs_iX_h = regs.bc.h;
100     return(resGO);
101     case 0x61: // LD HX,C
102       regs_iX_h = regs.bc.l;
103     return(resGO);
104     case 0x62: // LD HX,D
105       regs_iX_h = regs.de.h;
106     return(resGO);
107     case 0x63: // LD HX,E
108       regs_iX_h = regs.de.l;
109     return(resGO);
110     case 0x64: // LD HX,HX
111     return(resGO);
112     case 0x65: // LD HX,LX
113       regs_iX_h = regs_iX_l;
114     return(resGO);
115     case 0x66: // LD H,(IX+dd)
116       regs.hl.h = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
117     return(resGO);
118     case 0x67: // LD HX,A
119       regs_iX_h = regs.A;
120     return(resGO);
121     case 0x68: // LD LX,B
122       regs_iX_l = regs.bc.h;
123     return(resGO);
124     case 0x69: // LD LX,C
125       regs_iX_l = regs.bc.l;
126     return(resGO);
127     case 0x6A: // LD LX,D
128       regs_iX_l = regs.de.h;
129     return(resGO);
130     case 0x6B: // LD LX,E
131       regs_iX_l = regs.de.l;
132     return(resGO);
133     case 0x6C: // LD LX,HX
134       regs_iX_l = regs.hl.h;
135     return(resGO);
136     case 0x6D: // LD LX,LX
137     return(resGO);
138     case 0x6E: // LD L,(IX+dd)
139       regs.hl.l = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
140     return(resGO);
141     case 0x6F: // LD LX,A
142       regs_iX_l = regs.A;
143     return(resGO);
144     case 0x70: // LD (IX+dd),B
145       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.bc.h);
146     return(resGO);
147     case 0x71: // LD (IX+dd),C
148       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.bc.l);
149     return(resGO);
150     case 0x72: // LD (IX+dd),D
151       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.de.h);
152     return(resGO);
153     case 0x73: // LD (IX+dd),E
154       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.de.l);
155     return(resGO);
156     case 0x74: // LD (IX+dd),H
157       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.hl.h);
158     return(resGO);
159     case 0x75: // LD (IX+dd),L
160       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.hl.l);
161     return(resGO);
162     case 0x77: // LD (IX+dd),A
163       store1(add_u16_disp(regs_IX_OR_IY,fetch()), regs.A);
164     return(resGO);
165     case 0x7C: // LD A,HX
166       regs.A = regs_iX_h;
167     return(resGO);
168     case 0x7D: // LD A,LX
169       regs.A = regs_iX_l;
170     return(resGO);
171     case 0x7E: // LD A,(IX+dd)
172       regs.A = get1(add_u16_disp(regs_IX_OR_IY,fetch()));
173     return(resGO);
174     case 0xF9: // LD SP,IX
175       regs.SP = regs_IX_OR_IY;
176     return(resGO);
177   }
178   return(resINV_INST);
179 }
180
181 int
182 cl_z80::inst_Xd_add(t_mem code)
183 {
184 #define add_IX_Word(wr) { \
185       unsigned int tmp; \
186       regs.F &= ~(BIT_A | BIT_N | BIT_C);  /* clear these */ \
187       tmp = (unsigned int)regs_IX_OR_IY + (unsigned int)(wr); \
188       if (tmp > 0xffff) regs.F |= BIT_C; \
189       regs_IX_OR_IY = (unsigned short) tmp; }
190
191   switch (code) {
192     case 0x09: // ADD IX,BC
193       add_IX_Word(regs.BC);
194       return(resGO);
195     case 0x19: // ADD IX,DE
196       add_IX_Word(regs.DE);
197       return(resGO);
198     case 0x29: // ADD IX,IX
199       add_IX_Word(regs_IX_OR_IY);
200       return(resGO);
201     case 0x39: // ADD IX,SP
202       add_IX_Word(regs.SP);
203     return(resGO);
204     case 0x84: // ADD A,HX
205       add_A_bytereg(regs_iX_h);
206       return(resGO);
207     case 0x85: // ADD A,LX
208       add_A_bytereg(regs_iX_l);
209       return(resGO);
210     case 0x86: // ADD A,(IX+dd)
211       { unsigned char ourtmp;
212         t_addr addr;
213         addr = add_u16_disp(regs_IX_OR_IY, fetch());
214         ourtmp = get1(addr);
215         add_A_bytereg(ourtmp);
216       }
217       return(resGO);
218   }
219   return(resINV_INST);
220 }
221
222 int
223 cl_z80::inst_Xd_push(t_mem code)
224 {
225   switch (code) {
226     case 0xe5: // PUSH IX
227       push2(regs_IX_OR_IY);
228     return(resGO);
229   }
230   return(resINV_INST);
231 }
232
233 int
234 cl_z80::inst_Xd_inc(t_mem code)
235 {
236   switch(code) {
237     case 0x23: // INC IX
238       ++regs_IX_OR_IY;
239     break;
240     case 0x24: // INC HX
241       inc(regs_iX_h);
242     break;
243     case 0x2C: // INC LX
244       inc(regs_iX_l);
245     break;
246     case 0x34: // INC (IX+dd)
247       {
248         t_addr addr;
249         unsigned char tmp;
250         addr = add_u16_disp(regs_IX_OR_IY,fetch());
251         tmp = get1(addr);
252         inc(tmp);
253         store1(addr, tmp);
254       }
255     break;
256     default:
257       return(resINV_INST);
258     break;
259   }
260   return(resGO);
261 }
262
263 int
264 cl_z80::inst_Xd_dec(t_mem code)
265 {
266   switch(code) {
267     case 0x25: // DEC HX
268       dec(regs_iX_h);
269     break;
270     case 0x2B: // DEC IX
271       --regs.IX;
272     break;
273     case 0x2D: // DEC LX
274       dec(regs_iX_l);
275     break;
276     case 0x35: // DEC (IX+dd)
277       {
278         t_addr addr;
279         unsigned char tmp;
280         addr = add_u16_disp(regs_IX_OR_IY,fetch());
281         tmp = get1(addr);
282         dec(tmp);
283         store1(addr, tmp);
284       }
285     break;
286     default:
287       return(resINV_INST);
288     break;
289   }
290   return(resGO);
291 }
292
293
294 /* need ADC, SUB, SBC, AND, XOR, OR, CP */
295 int
296 cl_z80::inst_Xd_misc(t_mem code)
297 {
298   switch(code) {
299     case 0x8C: // ADC A,HX
300       adc_A_bytereg(regs_iX_h);
301     return(resGO);
302     case 0x8D: // ADC A,LX
303       adc_A_bytereg(regs_iX_l);
304     return(resGO);
305     case 0x8E: // ADC A,(IX+dd)
306       { unsigned char utmp;
307         t_addr addr;
308         addr = add_u16_disp(regs_IX_OR_IY, fetch());
309         utmp = get1(addr);
310         adc_A_bytereg(utmp);
311       }
312     return(resGO);
313
314     case 0x94: // SUB HX
315       sub_A_bytereg(regs_iX_h);
316     return(resGO);
317     case 0x95: // SUB LX
318       sub_A_bytereg(regs_iX_l);
319     return(resGO);
320     case 0x96: // SUB (IX+dd)
321       { unsigned char tmp1;
322         tmp1 = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
323         sub_A_bytereg(tmp1);
324       }
325     return(resGO);
326
327     case 0x9C: // SBC A,HX
328       sbc_A_bytereg(regs_iX_h);
329     return(resGO);
330     case 0x9D: // SBC A,LX
331       sbc_A_bytereg(regs_iX_l);
332     return(resGO);
333     case 0x9E: // SBC A,(IX+dd)
334       { unsigned char utmp;
335         utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
336         sbc_A_bytereg(utmp);
337       }
338     return(resGO);
339
340     case 0xA4: // AND HX
341       and_A_bytereg(regs_iX_h);
342     return(resGO);
343     case 0xA5: // AND LX
344       and_A_bytereg(regs_iX_l);
345     return(resGO);
346     case 0xA6: // AND (IX+dd)
347       { unsigned char utmp;
348         utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
349         and_A_bytereg(utmp);
350       }
351     return(resGO);
352
353     case 0xAC: // XOR HX
354       xor_A_bytereg(regs_iX_h);
355     return(resGO);
356     case 0xAD: // XOR LX
357       xor_A_bytereg(regs_iX_l);
358     return(resGO);
359     case 0xAE: // XOR (IX+dd)
360       { unsigned char utmp;
361         utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
362         xor_A_bytereg(utmp);
363       }
364     return(resGO);
365
366     case 0xB4: // OR HX
367       or_A_bytereg(regs_iX_h);
368     return(resGO);
369     case 0xB5: // OR LX
370       or_A_bytereg(regs_iX_l);
371     return(resGO);
372     case 0xB6: // OR (IX+dd)
373       { unsigned char utmp;
374         utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
375         or_A_bytereg(utmp);
376       }
377     return(resGO);
378
379     case 0xBC: // CP HX
380       cp_bytereg(regs_iX_h);
381     return(resGO);
382     case 0xBD: // CP LX
383       cp_bytereg(regs_iX_l);
384     return(resGO);
385     case 0xBE: // CP (IX+dd)
386       { unsigned char utmp;
387         utmp = get1(add_u16_disp(regs_IX_OR_IY, fetch()));
388         cp_bytereg(utmp);
389       }
390     return(resGO);
391   }
392   return(resINV_INST);
393 }
394
395 int
396 cl_z80::inst_Xd(void)
397 {
398   t_mem code;
399
400   if (fetch(&code))
401     return(resBREAKPOINT);
402
403   switch (code)
404     {
405       case 0x21: // LD IX,nnnn
406       case 0x22: // LD (nnnn),IX
407       case 0x26: // LD HX,nn
408       case 0x2A: // LD IX,(nnnn)
409       case 0x2E: // LD LX,nn
410       case 0x36: // LD (IX+dd),nn
411       case 0x44: // LD B,HX
412       case 0x45: // LD B,LX
413       case 0x46: // LD B,(IX+dd)
414       case 0x4C: // LD C,HX
415       case 0x4D: // LD C,LX
416       case 0x4E: // LD C,(IX+dd)
417       case 0x54: // LD D,HX
418       case 0x55: // LD D,LX
419       case 0x56: // LD D,(IX+dd)
420       case 0x5C: // LD E,H
421       case 0x5D: // LD E,L
422       case 0x5E: // LD E,(IX+dd)
423       case 0x60: // LD HX,B
424       case 0x61: // LD HX,C
425       case 0x62: // LD HX,D
426       case 0x63: // LD HX,E
427       case 0x64: // LD HX,HX
428       case 0x66: // LD H,(IX+dd)
429       case 0x67: // LD HX,A
430       case 0x68: // LD LX,B
431       case 0x69: // LD LX,C
432       case 0x6A: // LD LX,D
433       case 0x6B: // LD LX,E
434       case 0x6C: // LD LX,HX
435       case 0x6D: // LD LX,LX
436       case 0x6E: // LD L,(IX+dd)
437       case 0x6F: // LD LX,A
438       case 0x70: // LD (IX+dd),B
439       case 0x71: // LD (IX+dd),C
440       case 0x72: // LD (IX+dd),D
441       case 0x73: // LD (IX+dd),E
442       case 0x74: // LD (IX+dd),H
443       case 0x75: // LD (IX+dd),L
444       case 0x77: // LD (IX+dd),A
445       case 0x7C: // LD A,HX
446       case 0x7D: // LD A,LX
447       case 0x7E: // LD A,(IX+dd)
448       case 0xF9: // LD SP,IX
449         return(inst_Xd_ld(code));
450
451       case 0x23: // INC IX
452       case 0x24: // INC HX
453       case 0x2C: // INC LX
454       case 0x34: // INC (IX+dd)
455         return(inst_Xd_inc(code));
456       {
457         t_addr addr;
458         addr = add_u16_disp(regs_IX_OR_IY,fetch());
459         store1(addr, get1(addr)+1);
460       }
461
462       case 0x09: // ADD IX,BC
463       case 0x19: // ADD IX,DE
464       case 0x29: // ADD IX,IX
465       case 0x39: // ADD IX,SP
466       case 0x84: // ADD A,HX
467       case 0x85: // ADD A,LX
468       case 0x86: // ADD A,(IX)
469         return(inst_Xd_add(code));
470
471       case 0x25: // DEC HX
472       case 0x2B: // DEC IX
473       case 0x2D: // DEC LX
474       case 0x35: // DEC (IX+dd)
475       return(inst_Xd_dec(code));
476
477       case 0x8C: // ADC A,HX
478       case 0x8D: // ADC A,LX
479       case 0x8E: // ADC A,(IX)
480       case 0x94: // SUB HX
481       case 0x95: // SUB LX
482       case 0x96: // SUB (IX+dd)
483       case 0x9C: // SBC A,HX
484       case 0x9D: // SBC A,LX
485       case 0x9E: // SBC A,(IX+dd)
486       case 0xA4: // AND HX
487       case 0xA5: // AND LX
488       case 0xA6: // AND (IX+dd)
489       case 0xAC: // XOR HX
490       case 0xAD: // XOR LX
491       case 0xAE: // XOR (IX+dd)
492       case 0xB4: // OR HX
493       case 0xB5: // OR LX
494       case 0xB6: // OR (IX+dd)
495       case 0xBC: // CP HX
496       case 0xBD: // CP LX
497       case 0xBE: // CP (IX+dd)
498         return(inst_Xd_misc(code));
499       break;
500
501       case 0xCB: // escape, IX prefix to CB commands
502         return(inst_Xdcb()); /* see inst_ddcb.cc */
503       break;
504
505       case 0xE1: // POP IX
506         regs_IX_OR_IY = get2(regs.SP);
507         regs.SP+=2;
508       return(resGO);
509
510       case 0xE3: // EX (SP),IX
511         {
512           TYPE_UWORD tempw;
513
514           tempw = regs_IX_OR_IY;
515           regs_IX_OR_IY = get2(regs.SP);
516           store2(regs.SP, tempw);
517         }
518       return(resGO);
519
520       case 0xE5: // PUSH IX
521         push2(regs_IX_OR_IY);
522       return(resGO);
523
524       case 0xE9: // JP (IX)
525         PC = regs_IX_OR_IY;
526       return(resGO);
527
528       default:
529       return(resINV_INST);
530     }
531   return(resINV_INST);
532 }
533
534 /* End of z80.src/inst_xd.cc */