* support/regression/fwk/lib/testfwk.c: printn is recursive and thus needs
[fw/sdcc] / sim / ucsim / hc08.src / inst.cc
1 /*
2  * Simulator of microcontrollers (inst.cc)
3  *
4  * hc08 code base from Erik Petrich  epetrich@users.sourceforge.net
5  *
6  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
7  * 
8  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
9  *
10  */
11
12 /* This file is part of microcontroller simulator: ucsim.
13
14 UCSIM is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 UCSIM is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with UCSIM; see the file COPYING.  If not, write to the Free
26 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 02111-1307, USA. */
28 /*@1@*/
29
30 #include "ddconfig.h"
31 #include "stdio.h"
32 #include <stdlib.h>
33
34 // local
35 #include "hc08cl.h"
36 #include "regshc08.h"
37 #include "hc08mac.h"
38
39
40
41 void
42 cl_hc08::incx(void)
43 {
44   int hx = (regs.H << 8) | (regs.X);
45   hx++;
46   regs.H = (hx >> 8) & 0xff;
47   regs.X = hx & 0xff;
48 }
49
50 int
51 cl_hc08::fetchea(t_mem code, bool prefix)
52 {
53   switch ((code >> 4) & 0x0f) {
54     case 0x0: 
55     case 0x1:
56     case 0x3:
57     case 0xb:
58       return fetch(); // Direct
59     case 0x7:
60     case 0xf:
61       return (regs.H << 8) | regs.X;  // IX
62     case 0x6:
63     case 0xe:
64       if (!prefix)
65         return ((unsigned char)fetch())+((regs.H << 8) | regs.X); // IX1
66       else
67         return ((unsigned char)fetch())+regs.SP; // SP1
68     case 0xd:
69       if (!prefix)
70         return fetch2()+((regs.H << 8) | regs.X); // IX2
71       else
72         return fetch2()+regs.SP; // SP2
73     case 0xc:
74       return fetch2();
75     default:
76       return(resHALT);
77   }
78 }
79
80
81 int
82 cl_hc08::inst_nop(t_mem code, bool prefix)
83 {
84   return(resGO);
85 }
86
87
88 int
89 cl_hc08::inst_transfer(t_mem code, bool prefix)
90 {
91   int hx;
92   
93   switch (code) {
94     case 0x84: // TAP
95       regs.P = regs.A | 0x60;
96       break;
97     case 0x85: // TPA
98       regs.A = regs.P | 0x60;
99       break;
100     case 0x97: // TAX
101       regs.X = regs.A;
102       break;
103     case 0x9f: // TXA
104       regs.A = regs.X;
105       break;
106     case 0x94: // TXS
107       hx = (regs.H << 8) | regs.X;
108       regs.SP = (hx - 1) & 0xffff;
109       break;
110     case 0x95: // TSX
111       hx = regs.SP +1;
112       regs.H = (hx >> 8) & 0xff;
113       regs.X = hx & 0xff;
114       break;
115     default:
116       return(resHALT);
117   }
118   return(resGO);
119 }
120
121
122 int
123 cl_hc08::inst_setclearflags(t_mem code, bool prefix)
124 {
125   switch (code) {
126     case 0x98:
127       regs.P &= ~BIT_C;
128       break;
129     case 0x99:
130       regs.P |= BIT_C;
131       break;
132     case 0x9a:
133       regs.P &= ~BIT_I;
134       break;
135     case 0x9b:
136       regs.P |= BIT_I;
137       break;
138     default:
139       return(resHALT);
140   }
141   return(resGO);
142 }
143
144
145 int
146 cl_hc08::inst_rsp(t_mem code, bool prefix)
147 {
148   regs.SP = 0x00ff;
149   return(resGO);
150 }
151
152
153 int
154 cl_hc08::inst_nsa(t_mem code, bool prefix)
155 {
156   regs.A = ((regs.A & 0xf0)>>4) | ((regs.A & 0x0f)<<4);
157   return(resGO);
158 }
159
160
161
162 int
163 cl_hc08::inst_lda(t_mem code, bool prefix)
164 {
165   regs.A = OPERAND(code, prefix);
166   FLAG_CLEAR(BIT_V);
167   FLAG_NZ(regs.A);
168   return(resGO);
169 }
170
171 int
172 cl_hc08::inst_ldx(t_mem code, bool prefix)
173 {
174   regs.X = OPERAND(code, prefix);
175   FLAG_CLEAR(BIT_V);
176   FLAG_NZ(regs.X);
177   return(resGO);
178 }
179
180 int
181 cl_hc08::inst_sta(t_mem code, bool prefix)
182 {
183   int ea = fetchea(code, prefix);
184
185   //fprintf (stdout, "ea = 0x%04x\n", ea);
186     
187   FLAG_CLEAR(BIT_V);
188   FLAG_NZ(regs.A);
189   store1(ea, regs.A);
190   return(resGO);
191 }
192
193 int
194 cl_hc08::inst_stx(t_mem code, bool prefix)
195 {
196   int ea = fetchea(code, prefix);
197
198   FLAG_CLEAR(BIT_V);
199   FLAG_NZ(regs.X);
200   store1(ea, regs.X);
201   return(resGO);
202 }
203
204 int
205 cl_hc08::inst_add(t_mem code, bool prefix)
206 {
207   int result;
208   uchar operand;
209
210   operand = OPERAND(code, prefix);
211   result = (regs.A + operand) & 0xff;
212   FLAG_NZ (result);
213   FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & operand & ~result)
214                               | (~regs.A & ~operand & result)));
215   FLAG_ASSIGN (BIT_H, 0x08 & ((regs.A & operand)
216                               | (operand & ~result)
217                               | (~result & regs.A)));
218   FLAG_ASSIGN (BIT_C, 0x80 & ((regs.A & operand)
219                               | (operand & ~result)
220                               | (~result & regs.A)));
221
222 #if 0
223   fprintf (stdout, "add 0x%02x + 0x%02x      = 0x%02x ",regs.A, operand, result & 0xff);
224   fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ",
225         (regs.P & BIT_V)!=0,
226         (regs.P & BIT_H)!=0,
227         (regs.P & BIT_C)!=0,
228         (regs.P & BIT_N)!=0,
229         (regs.P & BIT_Z)!=0);
230 #endif
231   
232   regs.A = result;
233   return(resGO);
234 }
235
236 int
237 cl_hc08::inst_adc(t_mem code, bool prefix)
238 {
239   int result;
240   uchar operand;
241   int sresult;
242   uchar carryin = (regs.P & BIT_C)!=0;
243
244   operand = OPERAND(code, prefix);
245   result = regs.A + operand + carryin;
246   sresult = (signed char)regs.A + (signed char)operand + ((regs.P & BIT_C)!=0);
247   FLAG_NZ (result & 0xff);
248   FLAG_ASSIGN (BIT_V, (sresult<-128) || (sresult>127));
249   /* 0x80 & ((regs.A & operand & ~result)
250                               | (~regs.A & ~operand & result))); */
251   FLAG_ASSIGN (BIT_H, (result & 0xf) < (regs.A & 0xf));
252   /*                            0x10 & ((regs.A & operand)
253                               | (operand & ~result)
254                               | (~result & regs.A))); */
255   FLAG_ASSIGN (BIT_C, result & 0x100);
256   /*                            0x80 & ((regs.A & operand)
257                               | (operand & ~result)
258                               | (~result & regs.A))); */
259   
260 #if 0
261   fprintf (stdout, "adc 0x%02x + 0x%02x + %d = 0x%02x ",
262         regs.A, operand, carryin, result & 0xff);
263   fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ",
264         (regs.P & BIT_V)!=0,
265         (regs.P & BIT_H)!=0,
266         (regs.P & BIT_C)!=0,
267         (regs.P & BIT_N)!=0,
268         (regs.P & BIT_Z)!=0);
269 #endif
270   
271   regs.A = result & 0xff;
272   return(resGO);
273 }
274
275 int
276 cl_hc08::inst_sub(t_mem code, bool prefix)
277 {
278   int result;
279   uchar operand;
280
281   operand = OPERAND(code, prefix);
282   result = (regs.A - operand) & 0xff;
283   FLAG_NZ (result);
284   FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result)
285                               | (~regs.A & operand & result)));
286   FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand)
287                               | (operand & result)
288                               | (result & ~regs.A)));
289 #if 0  
290   fprintf (stdout, "sub 0x%02x - 0x%02x      = 0x%02x ",regs.A, operand, result & 0xff);
291   fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ",
292         (regs.P & BIT_V)!=0,
293         (regs.P & BIT_H)!=0,
294         (regs.P & BIT_C)!=0,
295         (regs.P & BIT_N)!=0,
296         (regs.P & BIT_Z)!=0);
297 #endif  
298   regs.A = result;
299   return(resGO);
300 }
301
302 int
303 cl_hc08::inst_sbc(t_mem code, bool prefix)
304 {
305   int result;
306   uchar operand;
307   uchar carryin = (regs.P & BIT_C)!=0;
308
309   operand = OPERAND(code, prefix);
310   result = (regs.A - operand - carryin) & 0xff;
311   FLAG_NZ (result);
312   FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result)
313                               | (~regs.A & operand & result)));
314   FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand)
315                               | (operand & result)
316                               | (result & ~regs.A)));
317 #if 0  
318   fprintf (stdout, "sbc 0x%02x - 0x%02x - %d = 0x%02x ",
319         regs.A, operand, carryin, result & 0xff);
320   fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ",
321         (regs.P & BIT_V)!=0,
322         (regs.P & BIT_H)!=0,
323         (regs.P & BIT_C)!=0,
324         (regs.P & BIT_N)!=0,
325         (regs.P & BIT_Z)!=0);
326 #endif  
327   regs.A = result;
328   return(resGO);
329 }
330
331 int
332 cl_hc08::inst_cmp(t_mem code, bool prefix)
333 {
334   int result;
335   uchar operand;
336
337   operand = OPERAND(code, prefix);
338   result = (regs.A - operand) & 0xff;
339   FLAG_NZ (result);
340   FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result)
341                               | (~regs.A & operand & result)));
342   FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand)
343                               | (operand & result)
344                               | (result & ~regs.A)));
345   return(resGO);
346 }
347
348 int
349 cl_hc08::inst_cpx(t_mem code, bool prefix)
350 {
351   int result;
352   uchar operand;
353
354   operand = OPERAND(code, prefix);
355   result = (regs.X - operand) & 0xff;
356   FLAG_NZ (result);
357   FLAG_ASSIGN (BIT_V, 0x80 & ((regs.X & ~operand & ~result)
358                               | (~regs.X & operand & result)));
359   FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.X & operand)
360                               | (operand & result)
361                               | (result & ~regs.X)));
362   return(resGO);
363 }
364
365 int
366 cl_hc08::inst_jmp(t_mem code, bool prefix)
367 {
368   PC = fetchea(code, prefix);
369
370   return(resGO);
371 }
372
373 int
374 cl_hc08::inst_jsr(t_mem code, bool prefix)
375 {
376   int newPC = fetchea(code, prefix);
377   
378   push2(PC);
379   PC = newPC;
380
381   return(resGO);
382 }
383
384 int
385 cl_hc08::inst_bsr(t_mem code, bool prefix)
386 {
387   signed char ofs = fetch();
388   
389   push2(PC);
390   PC += ofs;
391
392   return(resGO);
393 }
394
395 int
396 cl_hc08::inst_ais(t_mem code, bool prefix)
397 {
398   regs.SP = regs.SP + (signed char)fetch();
399   return(resGO);
400 }
401
402 int
403 cl_hc08::inst_aix(t_mem code, bool prefix)
404 {
405   regs.X = regs.X + (signed char)fetch();
406   return(resGO);
407 }
408
409 int
410 cl_hc08::inst_and(t_mem code, bool prefix)
411 {
412   regs.A = regs.A & OPERAND(code, prefix);
413   FLAG_CLEAR(BIT_V);
414   FLAG_NZ(regs.A);
415   return(resGO);
416 }
417
418 int
419 cl_hc08::inst_bit(t_mem code, bool prefix)
420 {
421   uchar operand = regs.A & OPERAND(code, prefix);
422   FLAG_CLEAR(BIT_V);
423   FLAG_NZ(operand);
424   return(resGO);
425 }
426
427 int
428 cl_hc08::inst_ora(t_mem code, bool prefix)
429 {
430   regs.A = regs.A | OPERAND(code, prefix);
431   FLAG_CLEAR(BIT_V);
432   FLAG_NZ(regs.A);
433   return(resGO);
434 }
435
436 int
437 cl_hc08::inst_eor(t_mem code, bool prefix)
438 {
439   regs.A = regs.A ^ OPERAND(code, prefix);
440   FLAG_CLEAR(BIT_V);
441   FLAG_NZ(regs.A);
442   return(resGO);
443 }
444
445 int
446 cl_hc08::inst_asr(t_mem code, bool prefix)
447 {
448   int ea = 0xffff;
449   uchar operand;
450   
451   if ((code & 0xf0) == 0x40)
452     operand = regs.A;
453   else if ((code & 0xf0) == 0x50)
454     operand = regs.X;
455   else {
456     ea = fetchea(code,prefix);
457     operand = get1(ea);
458   }
459
460   FLAG_ASSIGN (BIT_C, operand & 1);
461   operand = (operand >> 1) | (operand & 0x80);
462   FLAG_NZ (operand);
463   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
464
465   if ((code & 0xf0) == 0x40)
466     regs.A = operand;
467   else if ((code & 0xf0) == 0x50)
468     regs.X = operand;
469   else {
470     store1(ea, operand);
471   }
472
473   return(resGO);
474 }
475
476
477 int
478 cl_hc08::inst_lsr(t_mem code, bool prefix)
479 {
480   int ea = 0xffff;
481   uchar operand;
482   
483   if ((code & 0xf0) == 0x40)
484     operand = regs.A;
485   else if ((code & 0xf0) == 0x50)
486     operand = regs.X;
487   else {
488     ea = fetchea(code,prefix);
489     operand = get1(ea);
490   }
491
492   FLAG_ASSIGN (BIT_C, operand & 1);
493   operand = (operand >> 1) & 0x7f;
494   FLAG_NZ (operand);
495   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
496
497   if ((code & 0xf0) == 0x40)
498     regs.A = operand;
499   else if ((code & 0xf0) == 0x50)
500     regs.X = operand;
501   else {
502     store1(ea, operand);
503   }
504   return(resGO);
505 }
506
507
508 int
509 cl_hc08::inst_lsl(t_mem code, bool prefix)
510 {
511   int ea = 0xffff;
512   uchar operand;
513   
514   if ((code & 0xf0) == 0x40)
515     operand = regs.A;
516   else if ((code & 0xf0) == 0x50)
517     operand = regs.X;
518   else {
519     ea = fetchea(code,prefix);
520     operand = get1(ea);
521   }
522
523   FLAG_ASSIGN (BIT_C, operand & 0x80);
524   operand = (operand << 1);
525   FLAG_NZ (operand);
526   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
527
528   if ((code & 0xf0) == 0x40)
529     regs.A = operand;
530   else if ((code & 0xf0) == 0x50)
531     regs.X = operand;
532   else {
533     store1(ea, operand);
534   }
535   return(resGO);
536 }
537
538
539 int
540 cl_hc08::inst_rol(t_mem code, bool prefix)
541 {
542   uchar c = (regs.P & BIT_C)!=0;
543   int ea = 0xffff;
544   uchar operand;
545   
546   if ((code & 0xf0) == 0x40)
547     operand = regs.A;
548   else if ((code & 0xf0) == 0x50)
549     operand = regs.X;
550   else {
551     ea = fetchea(code,prefix);
552     operand = get1(ea);
553   }
554
555   FLAG_ASSIGN (BIT_C, operand & 0x80);
556   operand = (operand << 1) | c;
557   FLAG_NZ (operand);
558   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
559
560   if ((code & 0xf0) == 0x40)
561     regs.A = operand;
562   else if ((code & 0xf0) == 0x50)
563     regs.X = operand;
564   else {
565     store1(ea, operand);
566   }
567   return(resGO);
568 }
569
570
571 int
572 cl_hc08::inst_ror(t_mem code, bool prefix)
573 {
574   uchar c = (regs.P & BIT_C)!=0;
575   int ea = 0xffff;
576   uchar operand;
577   
578   if ((code & 0xf0) == 0x40)
579     operand = regs.A;
580   else if ((code & 0xf0) == 0x50)
581     operand = regs.X;
582   else {
583     ea = fetchea(code,prefix);
584     operand = get1(ea);
585   }
586
587   FLAG_ASSIGN (BIT_C, operand & 1);
588   operand = (operand >> 1) | (c << 7);
589   FLAG_NZ (operand);
590   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
591
592   if ((code & 0xf0) == 0x40)
593     regs.A = operand;
594   else if ((code & 0xf0) == 0x50)
595     regs.X = operand;
596   else {
597     store1(ea, operand);
598   }
599   return(resGO);
600 }
601
602
603 int
604 cl_hc08::inst_inc(t_mem code, bool prefix)
605 {
606   int ea = 0xffff;
607   uchar operand;
608   
609   if ((code & 0xf0) == 0x40)
610     operand = regs.A;
611   else if ((code & 0xf0) == 0x50)
612     operand = regs.X;
613   else {
614     ea = fetchea(code,prefix);
615     operand = get1(ea);
616   }
617
618   operand++;
619   FLAG_NZ (operand);
620   FLAG_ASSIGN (BIT_V, operand == 0x80);
621
622   if ((code & 0xf0) == 0x40)
623     regs.A = operand;
624   else if ((code & 0xf0) == 0x50)
625     regs.X = operand;
626   else {
627     store1(ea, operand);
628   }
629   return(resGO);
630 }
631
632
633 int
634 cl_hc08::inst_dec(t_mem code, bool prefix)
635 {
636   int ea = 0xffff;
637   uchar operand;
638   
639   if ((code & 0xf0) == 0x40)
640     operand = regs.A;
641   else if ((code & 0xf0) == 0x50)
642     operand = regs.X;
643   else {
644     ea = fetchea(code,prefix);
645     operand = get1(ea);
646   }
647
648   operand--;
649   FLAG_NZ (operand);
650   FLAG_ASSIGN (BIT_V, operand == 0x7f);
651
652   if ((code & 0xf0) == 0x40)
653     regs.A = operand;
654   else if ((code & 0xf0) == 0x50)
655     regs.X = operand;
656   else {
657     store1(ea, operand);
658   }
659   return(resGO);
660 }
661
662 int
663 cl_hc08::inst_dbnz(t_mem code, bool prefix)
664 {
665   int ea = 0xffff;
666   uchar operand;
667   signed char ofs;
668   
669   if ((code & 0xf0) == 0x40)
670     operand = regs.A;
671   else if ((code & 0xf0) == 0x50)
672     operand = regs.X;
673   else {
674     ea = fetchea(code,prefix);
675     operand = get1(ea);
676   }
677
678   operand--;
679   FLAG_NZ (operand);
680   FLAG_ASSIGN (BIT_V, operand == 0x7f);
681
682   if ((code & 0xf0) == 0x40)
683     regs.A = operand;
684   else if ((code & 0xf0) == 0x50)
685     regs.X = operand;
686   else {
687     store1(ea, operand);
688   }
689
690   ofs = fetch();
691   if (operand)
692     PC += ofs;
693
694   return(resGO);
695 }
696
697
698 int
699 cl_hc08::inst_tst(t_mem code, bool prefix)
700 {
701   int ea = 0xffff;
702   uchar operand;
703   
704   if ((code & 0xf0) == 0x40)
705     operand = regs.A;
706   else if ((code & 0xf0) == 0x50)
707     operand = regs.X;
708   else {
709     ea = fetchea(code,prefix);
710     operand = get1(ea);
711   }
712
713   FLAG_NZ (operand);
714   FLAG_CLEAR (BIT_V);
715
716   return(resGO);
717 }
718
719
720 int
721 cl_hc08::inst_clr(t_mem code, bool prefix)
722 {
723   int ea = 0xffff;
724   uchar operand;
725   
726   operand = 0;
727   FLAG_CLEAR (BIT_V);
728   FLAG_CLEAR (BIT_N);
729   FLAG_SET (BIT_Z);
730
731   if ((code & 0xf0) == 0x40)
732     regs.A = operand;
733   else if ((code & 0xf0) == 0x50)
734     regs.X = operand;
735   else {
736     store1(ea, operand);
737   }
738   return(resGO);
739 }
740
741
742 int
743 cl_hc08::inst_clrh(t_mem code, bool prefix)
744 {
745   FLAG_CLEAR (BIT_V);
746   FLAG_CLEAR (BIT_N);
747   FLAG_SET (BIT_Z);
748   regs.H = 0;
749   return(resGO);
750 }
751
752
753 int
754 cl_hc08::inst_com(t_mem code, bool prefix)
755 {
756   int ea = 0xffff;
757   uchar operand;
758   
759   if ((code & 0xf0) == 0x40)
760     operand = regs.A;
761   else if ((code & 0xf0) == 0x50)
762     operand = regs.X;
763   else {
764     ea = fetchea(code,prefix);
765     operand = get1(ea);
766   }
767
768   operand = ~operand;
769   FLAG_SET (BIT_C);
770   FLAG_NZ (operand);
771   FLAG_CLEAR (BIT_V);
772
773   if ((code & 0xf0) == 0x40)
774     regs.A = operand;
775   else if ((code & 0xf0) == 0x50)
776     regs.X = operand;
777   else {
778     store1(ea, operand);
779   }
780   return(resGO);
781 }
782
783
784 int
785 cl_hc08::inst_neg(t_mem code, bool prefix)
786 {
787   int ea = 0xffff;
788   uchar operand;
789   
790   if ((code & 0xf0) == 0x40)
791     operand = regs.A;
792   else if ((code & 0xf0) == 0x50)
793     operand = regs.X;
794   else {
795     ea = fetchea(code,prefix);
796     operand = get1(ea);
797   }
798
799   FLAG_ASSIGN (BIT_V, operand==0x80);
800   FLAG_ASSIGN (BIT_C, operand!=0x00);
801   operand = -operand;
802   FLAG_NZ (operand);
803
804   if ((code & 0xf0) == 0x40)
805     regs.A = operand;
806   else if ((code & 0xf0) == 0x50)
807     regs.X = operand;
808   else {
809     store1(ea, operand);
810   }
811   return(resGO);
812 }
813
814
815
816 int
817 cl_hc08::inst_pushpull(t_mem code, bool prefix)
818 {
819   switch (code) {
820     case 0x86:
821       pop1(regs.A);
822       break;
823     case 0x87:
824       push1(regs.A);
825       break;
826     case 0x88:
827       pop1(regs.X);
828       break;
829     case 0x89:
830       push1(regs.X);
831       break;
832     case 0x8a:
833       pop1(regs.H);
834       break;
835     case 0x8b:
836       push1(regs.H);
837       break;
838     default:
839       return(resHALT);
840   }
841   return(resGO);
842 }
843
844
845
846
847 int
848 cl_hc08::inst_stop(t_mem code, bool prefix)
849 {
850   FLAG_CLEAR (BIT_I);
851   return(resGO);
852 }
853
854
855 int
856 cl_hc08::inst_wait(t_mem code, bool prefix)
857 {
858   FLAG_CLEAR (BIT_I);
859   return(resGO);
860 }
861
862
863 int
864 cl_hc08::inst_daa(t_mem code, bool prefix)
865 {
866   uchar lsn, msn;
867
868   lsn = regs.A & 0xf;
869   msn = (regs.A >> 4) & 0xf;
870   if (regs.P & BIT_H) {
871     lsn += 16;
872     msn = (msn-1) & 0xf;
873   }
874   if (regs.P & BIT_C)
875     msn += 16;
876
877   FLAG_CLEAR (BIT_C);
878   while (lsn>9) {
879     lsn -= 10;
880     msn++;
881   }
882   if (msn>9) {
883     msn = msn % 10;
884     FLAG_SET (BIT_C);
885   }
886
887   return(resGO);
888 }
889
890 int
891 cl_hc08::inst_mul(t_mem code, bool prefix)
892 {
893   int result = regs.A * regs.X;
894   regs.A = result & 0xff;
895   regs.X = (result >> 8) & 0xff;
896   FLAG_CLEAR (BIT_C);
897   FLAG_CLEAR (BIT_H);
898   return(resGO);
899 }
900
901 int
902 cl_hc08::inst_div(t_mem code, bool prefix)
903 {
904   int dividend = (regs.H << 8) | regs.A;
905   int quotient;
906
907   if (regs.X) {
908     quotient = dividend / regs.X;
909     if (quotient<=0xff) {
910       regs.A = quotient;
911       regs.H = dividend % regs.X;
912       FLAG_CLEAR (BIT_C);
913       FLAG_ASSIGN (BIT_Z, quotient==0);
914     }
915     else
916       FLAG_SET (BIT_C);  // overflow
917   } else
918     FLAG_SET (BIT_C);    // division by zero
919
920   return(resGO);
921 }
922
923
924 int
925 cl_hc08::inst_condbranch(t_mem code, bool prefix)
926 {
927   bool taken;
928   signed char ofs;
929   
930   if ((code & 0xf0)==0x20) {
931     switch ((code>>1) & 7) {
932       case 0: // BRA
933         taken = 1;
934         break;
935       case 1: // BHI
936         taken = (regs.P & BIT_C) || !(regs.P & BIT_Z);
937         break;
938       case 2: // BCC
939         taken = !(regs.P & BIT_C);
940         break;
941       case 3: // BNE
942         taken = !(regs.P & BIT_Z);
943         break;
944       case 4: // BHCC
945         taken = !(regs.P & BIT_H);
946         break;
947       case 5: // BPL
948         taken = !(regs.P & BIT_N);
949         break;
950       case 6: // BMC
951         taken = !(regs.P & BIT_I);
952         break;
953       case 7: // BIL
954         taken = 0; // TODO: should read simulated IRQ# pin
955       default:
956         return(resHALT);
957     } 
958   }
959   else if ((code & 0xf0)==0x90) {
960     switch ((code>>1) & 7) {
961       case 0: // BGE
962         taken = !(((regs.P & BIT_N)!=0) ^ ((regs.P & BIT_V)!=0));
963         break;
964       case 1: // BLT
965         taken = (!(((regs.P & BIT_N)!=0) ^ ((regs.P & BIT_V)!=0)))
966                 || (regs.P & BIT_Z);
967         break;
968       default:
969         return(resHALT);
970     }
971   }
972   else
973     return(resHALT);
974   
975   if (code & 1)
976     taken = ! taken;
977   
978   ofs = fetch();
979   if (taken)
980     PC += ofs;
981
982   return(resGO);
983 }
984
985 int
986 cl_hc08::inst_bitsetclear(t_mem code, bool prefix)
987 {
988   uchar bit = (code >> 1) & 7;
989   int ea = fetchea(code, prefix);
990   uchar operand = get1(ea);
991
992   if (code & 1)
993     operand &= ~(1 << bit);
994   else
995     operand |= (1 << bit);
996   store1(ea, operand);
997   return(resGO);
998 }
999
1000 int
1001 cl_hc08::inst_bittestsetclear(t_mem code, bool prefix)
1002 {
1003   uchar bit = (code >> 1) & 7;
1004   int ea = fetchea(code, prefix);
1005   uchar operand = get1(ea);
1006   signed char ofs;
1007   bool taken;
1008   
1009   if (code & 1)
1010     taken = operand & (1 << bit);
1011   else
1012     taken = !(operand & (1 << bit));
1013
1014   ofs = fetch();
1015   if (taken)
1016     PC += ofs;
1017
1018   FLAG_ASSIGN (BIT_C, operand & (1 << bit));
1019   return(resGO);
1020 }
1021
1022 int
1023 cl_hc08::inst_cbeq(t_mem code, bool prefix)
1024 {
1025   int ea;
1026   uchar operand1, operand2;
1027   signed char ofs;
1028     
1029   if ((code & 0xf0) == 0x40) {
1030     operand1 = regs.A;
1031     operand2 = fetch();
1032   }
1033   else if ((code & 0xf0) == 0x50) {
1034     operand1 = regs.X;
1035     operand2 = fetch();
1036   }
1037   else {
1038     ea = fetchea(code,prefix);
1039     operand1 = get1(ea);
1040     operand2 = regs.A;
1041   }
1042
1043   ofs = fetch();
1044   if (operand1==operand2)
1045     PC += ofs;  
1046
1047   if (code==0x71)
1048     incx();
1049     
1050   return(resGO);
1051 }
1052
1053 int
1054 cl_hc08::inst_rti(t_mem code, bool prefix)
1055 {
1056   pop1(regs.P);
1057   regs.P |= 0x60;
1058   pop1(regs.A);
1059   pop1(regs.X);
1060   pop2(PC);
1061   
1062   return(resGO);
1063 }
1064
1065 int
1066 cl_hc08::inst_rts(t_mem code, bool prefix)
1067 {
1068   pop2(PC);
1069   
1070   return(resGO);
1071 }
1072
1073
1074 int
1075 cl_hc08::inst_mov(t_mem code, bool prefix)
1076 {
1077   int ea;
1078   uchar operand;
1079   bool aix;
1080   int hx = (regs.H << 8) | (regs.X);
1081   
1082   switch (code) {
1083     case 0x4e:  //mov opr8a,opr8a
1084       operand = get1(fetch());
1085       ea = fetch();
1086       aix = 0;
1087       break;
1088     case 0x5e:  //mov opr8a,x+
1089       operand = get1(fetch());
1090       ea = hx;
1091       aix = 1;
1092       break;
1093     case 0x6e:  //mov #opr8i,opr8a
1094       operand = fetch();
1095       ea = fetch();
1096       aix = 0;
1097       break;
1098     case 0x7e:  //mov x+,opr8a
1099       operand = get1(hx);
1100       ea = fetch();
1101       aix = 1;
1102       break;
1103     default:
1104       return(resHALT);
1105   }
1106   
1107   store1(ea, operand);
1108   if (aix)
1109     incx();
1110
1111   FLAG_NZ(operand);
1112   FLAG_CLEAR(BIT_V);
1113     
1114   return(resGO);
1115 }
1116
1117
1118 int
1119 cl_hc08::inst_sthx(t_mem code, bool prefix)
1120 {
1121   int ea = fetch1();
1122   
1123   store1(ea, regs.H);
1124   store1((ea+1) & 0xffff, regs.X);
1125
1126   FLAG_CLEAR(BIT_V);
1127   FLAG_ASSIGN(BIT_N, regs.X & 0x80);
1128   FLAG_ASSIGN(BIT_Z, !regs.X && !regs.A);
1129   return(resGO);
1130 }
1131
1132 int
1133 cl_hc08::inst_ldhx(t_mem code, bool prefix)
1134 {
1135   int ea;
1136   
1137   if (code == 0x45) {
1138     regs.H = fetch();
1139     regs.X = fetch();
1140   }
1141   else if (code == 0x55) {
1142     ea = fetch();
1143     regs.H = get1(ea);
1144     regs.X = get1(ea+1);
1145   }
1146   else
1147     return(resHALT);
1148   
1149   FLAG_CLEAR(BIT_V);
1150   FLAG_ASSIGN(BIT_N, regs.X & 0x80);
1151   FLAG_ASSIGN(BIT_Z, !regs.X && !regs.A);
1152   return(resGO);
1153 }
1154
1155
1156 int
1157 cl_hc08::inst_cphx(t_mem code, bool prefix)
1158 {
1159   int ea;
1160   int hx;
1161   int operand;
1162   int result;
1163   
1164   if (code == 0x65) {
1165     operand = fetch2();
1166   }
1167   else if (code == 0x75) {
1168     ea = fetch();
1169     operand = (get1(ea) << 8) | get1(ea+1);
1170   }
1171   else
1172     return(resHALT);
1173
1174   hx = (regs.H << 8) | regs.X;
1175
1176   result = (hx-operand) & 0xffff;
1177
1178   FLAG_ASSIGN (BIT_V, 0x8000 & ((hx & ~operand & ~result)
1179                               | (~hx & operand & result)));
1180   FLAG_ASSIGN (BIT_C, 0x8000 & ((~hx & operand)
1181                               | (operand & result)
1182                               | (result & ~hx)));
1183   FLAG_ASSIGN(BIT_N, result & 0x8000);
1184   FLAG_ASSIGN(BIT_Z, !result);
1185                               
1186   return(resGO);
1187 }
1188
1189 int
1190 cl_hc08::inst_swi(t_mem code, bool prefix)
1191 {
1192   push2(PC);
1193   push1(regs.X);
1194   push1(regs.A);
1195   push1(regs.P);
1196   FLAG_CLEAR(BIT_I);
1197   
1198   PC = get2(0xfffc);
1199
1200   return(resGO);
1201 }
1202
1203
1204 /* End of hc08.src/inst.cc */