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