bdd8312d2b18c8b014f659874baa65718e15696a
[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, operand1, operand2;
208
209   operand1 = regs.A;
210   operand2 = OPERAND(code, prefix);
211   result = operand1 + operand2;
212   FLAG_NZ (result);
213   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
214   FLAG_ASSIGN (BIT_C, 0x100 & result);
215   FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result));
216   
217   regs.A = result & 0xff;
218   return(resGO);
219 }
220
221 int
222 cl_hc08::inst_adc(t_mem code, bool prefix)
223 {
224   int result, operand1, operand2;
225   int carryin = (regs.P & BIT_C)!=0;
226
227   operand1 = regs.A;
228   operand2 = OPERAND(code, prefix);
229   result = operand1 + operand2 + carryin;
230   FLAG_NZ (result);
231   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
232   FLAG_ASSIGN (BIT_C, 0x100 & result);
233   FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result));
234
235   regs.A = result & 0xff;
236   return(resGO);
237 }
238
239 int
240 cl_hc08::inst_sub(t_mem code, bool prefix)
241 {
242   int result, operand1, operand2;
243
244   operand1 = regs.A;
245   operand2 = OPERAND(code, prefix);
246   result = operand1 - operand2;
247   FLAG_NZ (result);
248   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
249   FLAG_ASSIGN (BIT_C, 0x100 & result);
250
251   regs.A = result & 0xff;
252   return(resGO);
253 }
254
255 int
256 cl_hc08::inst_sbc(t_mem code, bool prefix)
257 {
258   int result, operand1, operand2;
259   int carryin = (regs.P & BIT_C)!=0;
260
261   operand1 = regs.A;
262   operand2 = OPERAND(code, prefix);
263   result = operand1 - operand2 - carryin;
264   FLAG_NZ (result);
265   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
266   FLAG_ASSIGN (BIT_C, 0x100 & result);
267
268   regs.A = result & 0xff;
269   return(resGO);
270 }
271
272 int
273 cl_hc08::inst_cmp(t_mem code, bool prefix)
274 {
275   int result, operand1, operand2;
276
277   operand1 = regs.A;
278   operand2 = OPERAND(code, prefix);
279   result = operand1 - operand2;
280   FLAG_NZ (result);
281   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
282   FLAG_ASSIGN (BIT_C, 0x100 & result);
283
284   return(resGO);
285 }
286
287 int
288 cl_hc08::inst_cpx(t_mem code, bool prefix)
289 {
290   int result, operand1, operand2;
291
292   operand1 = regs.X;
293   operand2 = OPERAND(code, prefix);
294   result = operand1 - operand2;
295   FLAG_NZ (result);
296   FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1)));
297   FLAG_ASSIGN (BIT_C, 0x100 & result);
298
299   return(resGO);
300 }
301
302 int
303 cl_hc08::inst_jmp(t_mem code, bool prefix)
304 {
305   PC = fetchea(code, prefix);
306
307   return(resGO);
308 }
309
310 int
311 cl_hc08::inst_jsr(t_mem code, bool prefix)
312 {
313   int newPC = fetchea(code, prefix);
314   
315   push2(PC);
316   PC = newPC;
317
318   return(resGO);
319 }
320
321 int
322 cl_hc08::inst_bsr(t_mem code, bool prefix)
323 {
324   signed char ofs = fetch();
325   
326   push2(PC);
327   PC += ofs;
328
329   return(resGO);
330 }
331
332 int
333 cl_hc08::inst_ais(t_mem code, bool prefix)
334 {
335   regs.SP = regs.SP + (signed char)fetch();
336   return(resGO);
337 }
338
339 int
340 cl_hc08::inst_aix(t_mem code, bool prefix)
341 {
342   int hx = (regs.H << 8) | (regs.X);
343   hx += (signed char)fetch();
344   regs.H = (hx >> 8) & 0xff;
345   regs.X = hx & 0xff;
346   return(resGO);
347 }
348
349 int
350 cl_hc08::inst_and(t_mem code, bool prefix)
351 {
352   regs.A = regs.A & OPERAND(code, prefix);
353   FLAG_CLEAR(BIT_V);
354   FLAG_NZ(regs.A);
355   return(resGO);
356 }
357
358 int
359 cl_hc08::inst_bit(t_mem code, bool prefix)
360 {
361   uchar operand = regs.A & OPERAND(code, prefix);
362   FLAG_CLEAR(BIT_V);
363   FLAG_NZ(operand);
364   return(resGO);
365 }
366
367 int
368 cl_hc08::inst_ora(t_mem code, bool prefix)
369 {
370   regs.A = regs.A | OPERAND(code, prefix);
371   FLAG_CLEAR(BIT_V);
372   FLAG_NZ(regs.A);
373   return(resGO);
374 }
375
376 int
377 cl_hc08::inst_eor(t_mem code, bool prefix)
378 {
379   regs.A = regs.A ^ OPERAND(code, prefix);
380   FLAG_CLEAR(BIT_V);
381   FLAG_NZ(regs.A);
382   return(resGO);
383 }
384
385 int
386 cl_hc08::inst_asr(t_mem code, bool prefix)
387 {
388   int ea = 0xffff;
389   uchar operand;
390   
391   if ((code & 0xf0) == 0x40)
392     operand = regs.A;
393   else if ((code & 0xf0) == 0x50)
394     operand = regs.X;
395   else {
396     ea = fetchea(code,prefix);
397     operand = get1(ea);
398   }
399
400   FLAG_ASSIGN (BIT_C, operand & 1);
401   operand = (operand >> 1) | (operand & 0x80);
402   FLAG_NZ (operand);
403   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
404
405   if ((code & 0xf0) == 0x40)
406     regs.A = operand;
407   else if ((code & 0xf0) == 0x50)
408     regs.X = operand;
409   else {
410     store1(ea, operand);
411   }
412
413   return(resGO);
414 }
415
416
417 int
418 cl_hc08::inst_lsr(t_mem code, bool prefix)
419 {
420   int ea = 0xffff;
421   uchar operand;
422   
423   if ((code & 0xf0) == 0x40)
424     operand = regs.A;
425   else if ((code & 0xf0) == 0x50)
426     operand = regs.X;
427   else {
428     ea = fetchea(code,prefix);
429     operand = get1(ea);
430   }
431
432   FLAG_ASSIGN (BIT_C, operand & 1);
433   operand = (operand >> 1) & 0x7f;
434   FLAG_NZ (operand);
435   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
436
437   if ((code & 0xf0) == 0x40)
438     regs.A = operand;
439   else if ((code & 0xf0) == 0x50)
440     regs.X = operand;
441   else {
442     store1(ea, operand);
443   }
444   return(resGO);
445 }
446
447
448 int
449 cl_hc08::inst_lsl(t_mem code, bool prefix)
450 {
451   int ea = 0xffff;
452   uchar operand;
453   
454   if ((code & 0xf0) == 0x40)
455     operand = regs.A;
456   else if ((code & 0xf0) == 0x50)
457     operand = regs.X;
458   else {
459     ea = fetchea(code,prefix);
460     operand = get1(ea);
461   }
462
463   FLAG_ASSIGN (BIT_C, operand & 0x80);
464   operand = (operand << 1);
465   FLAG_NZ (operand);
466   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
467
468   if ((code & 0xf0) == 0x40)
469     regs.A = operand;
470   else if ((code & 0xf0) == 0x50)
471     regs.X = operand;
472   else {
473     store1(ea, operand);
474   }
475   return(resGO);
476 }
477
478
479 int
480 cl_hc08::inst_rol(t_mem code, bool prefix)
481 {
482   uchar c = (regs.P & BIT_C)!=0;
483   int ea = 0xffff;
484   uchar operand;
485   
486   if ((code & 0xf0) == 0x40)
487     operand = regs.A;
488   else if ((code & 0xf0) == 0x50)
489     operand = regs.X;
490   else {
491     ea = fetchea(code,prefix);
492     operand = get1(ea);
493   }
494
495   FLAG_ASSIGN (BIT_C, operand & 0x80);
496   operand = (operand << 1) | c;
497   FLAG_NZ (operand);
498   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
499
500   if ((code & 0xf0) == 0x40)
501     regs.A = operand;
502   else if ((code & 0xf0) == 0x50)
503     regs.X = operand;
504   else {
505     store1(ea, operand);
506   }
507   return(resGO);
508 }
509
510
511 int
512 cl_hc08::inst_ror(t_mem code, bool prefix)
513 {
514   uchar c = (regs.P & BIT_C)!=0;
515   int ea = 0xffff;
516   uchar operand;
517   
518   if ((code & 0xf0) == 0x40)
519     operand = regs.A;
520   else if ((code & 0xf0) == 0x50)
521     operand = regs.X;
522   else {
523     ea = fetchea(code,prefix);
524     operand = get1(ea);
525   }
526
527   FLAG_ASSIGN (BIT_C, operand & 1);
528   operand = (operand >> 1) | (c << 7);
529   FLAG_NZ (operand);
530   FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0));
531
532   if ((code & 0xf0) == 0x40)
533     regs.A = operand;
534   else if ((code & 0xf0) == 0x50)
535     regs.X = operand;
536   else {
537     store1(ea, operand);
538   }
539   return(resGO);
540 }
541
542
543 int
544 cl_hc08::inst_inc(t_mem code, bool prefix)
545 {
546   int ea = 0xffff;
547   uchar operand;
548   
549   if ((code & 0xf0) == 0x40)
550     operand = regs.A;
551   else if ((code & 0xf0) == 0x50)
552     operand = regs.X;
553   else {
554     ea = fetchea(code,prefix);
555     operand = get1(ea);
556   }
557
558   operand++;
559   FLAG_NZ (operand);
560   FLAG_ASSIGN (BIT_V, operand == 0x80);
561
562   if ((code & 0xf0) == 0x40)
563     regs.A = operand;
564   else if ((code & 0xf0) == 0x50)
565     regs.X = operand;
566   else {
567     store1(ea, operand);
568   }
569   return(resGO);
570 }
571
572
573 int
574 cl_hc08::inst_dec(t_mem code, bool prefix)
575 {
576   int ea = 0xffff;
577   uchar operand;
578   
579   if ((code & 0xf0) == 0x40)
580     operand = regs.A;
581   else if ((code & 0xf0) == 0x50)
582     operand = regs.X;
583   else {
584     ea = fetchea(code,prefix);
585     operand = get1(ea);
586   }
587
588   operand--;
589   FLAG_NZ (operand);
590   FLAG_ASSIGN (BIT_V, operand == 0x7f);
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 int
603 cl_hc08::inst_dbnz(t_mem code, bool prefix)
604 {
605   int ea = 0xffff;
606   uchar operand;
607   signed char ofs;
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 == 0x7f);
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
630   ofs = fetch();
631   if (operand)
632     PC += ofs;
633
634   return(resGO);
635 }
636
637
638 int
639 cl_hc08::inst_tst(t_mem code, bool prefix)
640 {
641   int ea = 0xffff;
642   uchar operand;
643   
644   if ((code & 0xf0) == 0x40)
645     operand = regs.A;
646   else if ((code & 0xf0) == 0x50)
647     operand = regs.X;
648   else {
649     ea = fetchea(code,prefix);
650     operand = get1(ea);
651   }
652
653   FLAG_NZ (operand);
654   FLAG_CLEAR (BIT_V);
655
656   return(resGO);
657 }
658
659
660 int
661 cl_hc08::inst_clr(t_mem code, bool prefix)
662 {
663   int ea = 0xffff;
664   uchar operand;
665   
666   operand = 0;
667   FLAG_CLEAR (BIT_V);
668   FLAG_CLEAR (BIT_N);
669   FLAG_SET (BIT_Z);
670
671   if ((code & 0xf0) == 0x40)
672     regs.A = operand;
673   else if ((code & 0xf0) == 0x50)
674     regs.X = operand;
675   else {
676     store1(ea, operand);
677   }
678   return(resGO);
679 }
680
681
682 int
683 cl_hc08::inst_clrh(t_mem code, bool prefix)
684 {
685   FLAG_CLEAR (BIT_V);
686   FLAG_CLEAR (BIT_N);
687   FLAG_SET (BIT_Z);
688   regs.H = 0;
689   return(resGO);
690 }
691
692
693 int
694 cl_hc08::inst_com(t_mem code, bool prefix)
695 {
696   int ea = 0xffff;
697   uchar operand;
698   
699   if ((code & 0xf0) == 0x40)
700     operand = regs.A;
701   else if ((code & 0xf0) == 0x50)
702     operand = regs.X;
703   else {
704     ea = fetchea(code,prefix);
705     operand = get1(ea);
706   }
707
708   operand = ~operand;
709   FLAG_SET (BIT_C);
710   FLAG_NZ (operand);
711   FLAG_CLEAR (BIT_V);
712
713   if ((code & 0xf0) == 0x40)
714     regs.A = operand;
715   else if ((code & 0xf0) == 0x50)
716     regs.X = operand;
717   else {
718     store1(ea, operand);
719   }
720   return(resGO);
721 }
722
723
724 int
725 cl_hc08::inst_neg(t_mem code, bool prefix)
726 {
727   int ea = 0xffff;
728   uchar operand;
729   
730   if ((code & 0xf0) == 0x40)
731     operand = regs.A;
732   else if ((code & 0xf0) == 0x50)
733     operand = regs.X;
734   else {
735     ea = fetchea(code,prefix);
736     operand = get1(ea);
737   }
738
739   FLAG_ASSIGN (BIT_V, operand==0x80);
740   FLAG_ASSIGN (BIT_C, operand!=0x00);
741   operand = -operand;
742   FLAG_NZ (operand);
743
744   if ((code & 0xf0) == 0x40)
745     regs.A = operand;
746   else if ((code & 0xf0) == 0x50)
747     regs.X = operand;
748   else {
749     store1(ea, operand);
750   }
751   return(resGO);
752 }
753
754
755
756 int
757 cl_hc08::inst_pushpull(t_mem code, bool prefix)
758 {
759   switch (code) {
760     case 0x86:
761       pop1(regs.A);
762       break;
763     case 0x87:
764       push1(regs.A);
765       break;
766     case 0x88:
767       pop1(regs.X);
768       break;
769     case 0x89:
770       push1(regs.X);
771       break;
772     case 0x8a:
773       pop1(regs.H);
774       break;
775     case 0x8b:
776       push1(regs.H);
777       break;
778     default:
779       return(resHALT);
780   }
781   return(resGO);
782 }
783
784
785
786
787 int
788 cl_hc08::inst_stop(t_mem code, bool prefix)
789 {
790   FLAG_CLEAR (BIT_I);
791   return(resGO);
792 }
793
794
795 int
796 cl_hc08::inst_wait(t_mem code, bool prefix)
797 {
798   FLAG_CLEAR (BIT_I);
799   return(resGO);
800 }
801
802
803 int
804 cl_hc08::inst_daa(t_mem code, bool prefix)
805 {
806   uchar lsn, msn;
807
808   lsn = regs.A & 0xf;
809   msn = (regs.A >> 4) & 0xf;
810   if (regs.P & BIT_H) {
811     lsn += 16;
812     msn = (msn-1) & 0xf;
813   }
814   if (regs.P & BIT_C)
815     msn += 16;
816
817   FLAG_CLEAR (BIT_C);
818   while (lsn>9) {
819     lsn -= 10;
820     msn++;
821   }
822   if (msn>9) {
823     msn = msn % 10;
824     FLAG_SET (BIT_C);
825   }
826
827   return(resGO);
828 }
829
830 int
831 cl_hc08::inst_mul(t_mem code, bool prefix)
832 {
833   int result = regs.A * regs.X;
834   regs.A = result & 0xff;
835   regs.X = (result >> 8) & 0xff;
836   FLAG_CLEAR (BIT_C);
837   FLAG_CLEAR (BIT_H);
838   return(resGO);
839 }
840
841 int
842 cl_hc08::inst_div(t_mem code, bool prefix)
843 {
844   unsigned int dividend = (regs.H << 8) | regs.A;
845   unsigned int quotient;
846
847   if (regs.X) {
848     quotient = dividend / (unsigned int)regs.X;
849     if (quotient<=0xff) {
850       regs.A = quotient;
851       regs.H = dividend % regs.X;
852       FLAG_CLEAR (BIT_C);
853       FLAG_ASSIGN (BIT_Z, quotient==0);
854     }
855     else
856       FLAG_SET (BIT_C);  // overflow
857   } else
858     FLAG_SET (BIT_C);    // division by zero
859
860   return(resGO);
861 }
862
863
864 int
865 cl_hc08::inst_condbranch(t_mem code, bool prefix)
866 {
867   bool taken;
868   signed char ofs;
869   
870   if ((code & 0xf0)==0x20) {
871     switch ((code>>1) & 7) {
872       case 0: // BRA
873         taken = 1;
874         break;
875       case 1: // BHI
876         taken = (regs.P & BIT_C) || !(regs.P & BIT_Z);
877         break;
878       case 2: // BCC
879         taken = !(regs.P & BIT_C);
880         break;
881       case 3: // BNE
882         taken = !(regs.P & BIT_Z);
883         break;
884       case 4: // BHCC
885         taken = !(regs.P & BIT_H);
886         break;
887       case 5: // BPL
888         taken = !(regs.P & BIT_N);
889         break;
890       case 6: // BMC
891         taken = !(regs.P & BIT_I);
892         break;
893       case 7: // BIL
894         taken = 0; // TODO: should read simulated IRQ# pin
895       default:
896         return(resHALT);
897     } 
898   }
899   else if ((code & 0xf0)==0x90) {
900     switch ((code>>1) & 7) {
901       case 0: // BGE
902         taken = !(((regs.P & BIT_N)!=0) ^ ((regs.P & BIT_V)!=0));
903         break;
904       case 1: // BLT
905         taken = (!(((regs.P & BIT_N)!=0) ^ ((regs.P & BIT_V)!=0)))
906                 || (regs.P & BIT_Z);
907         break;
908       default:
909         return(resHALT);
910     }
911   }
912   else
913     return(resHALT);
914   
915   if (code & 1)
916     taken = ! taken;
917   
918   ofs = fetch();
919   if (taken)
920     PC += ofs;
921
922   return(resGO);
923 }
924
925 int
926 cl_hc08::inst_bitsetclear(t_mem code, bool prefix)
927 {
928   uchar bit = (code >> 1) & 7;
929   int ea = fetchea(code, prefix);
930   uchar operand = get1(ea);
931
932   if (code & 1)
933     operand &= ~(1 << bit);
934   else
935     operand |= (1 << bit);
936   store1(ea, operand);
937   return(resGO);
938 }
939
940 int
941 cl_hc08::inst_bittestsetclear(t_mem code, bool prefix)
942 {
943   uchar bit = (code >> 1) & 7;
944   int ea = fetchea(code, prefix);
945   uchar operand = get1(ea);
946   signed char ofs;
947   bool taken;
948   
949   if (code & 1)
950     taken = operand & (1 << bit);
951   else
952     taken = !(operand & (1 << bit));
953
954   ofs = fetch();
955   if (taken)
956     PC += ofs;
957
958   FLAG_ASSIGN (BIT_C, operand & (1 << bit));
959   return(resGO);
960 }
961
962 int
963 cl_hc08::inst_cbeq(t_mem code, bool prefix)
964 {
965   int ea;
966   uchar operand1, operand2;
967   signed char ofs;
968     
969   if ((code & 0xf0) == 0x40) {
970     operand1 = regs.A;
971     operand2 = fetch();
972   }
973   else if ((code & 0xf0) == 0x50) {
974     operand1 = regs.X;
975     operand2 = fetch();
976   }
977   else {
978     ea = fetchea(code,prefix);
979     operand1 = get1(ea);
980     operand2 = regs.A;
981   }
982
983   ofs = fetch();
984   if (operand1==operand2)
985     PC += ofs;  
986
987   if (code==0x71)
988     incx();
989     
990   return(resGO);
991 }
992
993 int
994 cl_hc08::inst_rti(t_mem code, bool prefix)
995 {
996   pop1(regs.P);
997   regs.P |= 0x60;
998   pop1(regs.A);
999   pop1(regs.X);
1000   pop2(PC);
1001   
1002   return(resGO);
1003 }
1004
1005 int
1006 cl_hc08::inst_rts(t_mem code, bool prefix)
1007 {
1008   pop2(PC);
1009   
1010   return(resGO);
1011 }
1012
1013
1014 int
1015 cl_hc08::inst_mov(t_mem code, bool prefix)
1016 {
1017   int ea;
1018   uchar operand;
1019   bool aix;
1020   int hx = (regs.H << 8) | (regs.X);
1021   
1022   switch (code) {
1023     case 0x4e:  //mov opr8a,opr8a
1024       operand = get1(fetch());
1025       ea = fetch();
1026       aix = 0;
1027       break;
1028     case 0x5e:  //mov opr8a,x+
1029       operand = get1(fetch());
1030       ea = hx;
1031       aix = 1;
1032       break;
1033     case 0x6e:  //mov #opr8i,opr8a
1034       operand = fetch();
1035       ea = fetch();
1036       aix = 0;
1037       break;
1038     case 0x7e:  //mov x+,opr8a
1039       operand = get1(hx);
1040       ea = fetch();
1041       aix = 1;
1042       break;
1043     default:
1044       return(resHALT);
1045   }
1046   
1047   store1(ea, operand);
1048   if (aix)
1049     incx();
1050
1051   FLAG_NZ(operand);
1052   FLAG_CLEAR(BIT_V);
1053     
1054   return(resGO);
1055 }
1056
1057
1058 int
1059 cl_hc08::inst_sthx(t_mem code, bool prefix)
1060 {
1061   int ea = fetch1();
1062   
1063   store1(ea, regs.H);
1064   store1((ea+1) & 0xffff, regs.X);
1065
1066   FLAG_CLEAR(BIT_V);
1067   FLAG_ASSIGN(BIT_N, regs.H & 0x80);
1068   FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H);
1069   return(resGO);
1070 }
1071
1072 int
1073 cl_hc08::inst_ldhx(t_mem code, bool prefix)
1074 {
1075   int ea;
1076   
1077   if (code == 0x45) {
1078     regs.H = fetch();
1079     regs.X = fetch();
1080   }
1081   else if (code == 0x55) {
1082     ea = fetch();
1083     regs.H = get1(ea);
1084     regs.X = get1(ea+1);
1085   }
1086   else
1087     return(resHALT);
1088   
1089   FLAG_CLEAR(BIT_V);
1090   FLAG_ASSIGN(BIT_N, regs.H & 0x80);
1091   FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H);
1092   return(resGO);
1093 }
1094
1095
1096 int
1097 cl_hc08::inst_cphx(t_mem code, bool prefix)
1098 {
1099   int ea;
1100   int hx;
1101   int operand;
1102   int result;
1103   
1104   if (code == 0x65) {
1105     operand = fetch2();
1106   }
1107   else if (code == 0x75) {
1108     ea = fetch();
1109     operand = (get1(ea) << 8) | get1(ea+1);
1110   }
1111   else
1112     return(resHALT);
1113
1114   hx = (regs.H << 8) | regs.X;
1115   result = hx-operand;
1116
1117   FLAG_ASSIGN (BIT_V, 0x8000 & (hx ^ operand ^ result ^ (result>>1)));
1118   FLAG_ASSIGN (BIT_C, 0x10000 & result);
1119   FLAG_ASSIGN(BIT_N, result & 0x8000);
1120   FLAG_ASSIGN(BIT_Z, !(result & 0xffff));
1121                               
1122   return(resGO);
1123 }
1124
1125 int
1126 cl_hc08::inst_swi(t_mem code, bool prefix)
1127 {
1128   push2(PC);
1129   push1(regs.X);
1130   push1(regs.A);
1131   push1(regs.P);
1132   FLAG_CLEAR(BIT_I);
1133   
1134   PC = get2(0xfffc);
1135
1136   return(resGO);
1137 }
1138
1139
1140 /* End of hc08.src/inst.cc */