work in progress
[fw/sdcc] / sim / ucsim / xa.src / inst.cc
1 /*
2  * Simulator of microcontrollers (inst.cc)
3  *
4  * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt.
5  *
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  * Other contributors include:
8  *   Karl Bongers karl@turbobit.com,
9  *   Johan Knol johan.knol@iduna.nl
10  *
11  */
12
13 /* This file is part of microcontroller simulator: ucsim.
14
15 UCSIM is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 UCSIM is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with UCSIM; see the file COPYING.  If not, write to the Free
27 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 02111-1307, USA. */
29 /*@1@*/
30
31 #include "ddconfig.h"
32
33 // local
34 #include "glob.h"
35 #include "xacl.h"
36 #include "regsxa.h"
37
38
39 void cl_xa::store1(t_addr addr, unsigned char val)
40 {
41   if (addr < 0x2000) {
42     set_idata1(addr, val);
43   } else {
44     set_xdata1(addr, val);
45   }
46 }
47
48 void cl_xa::store2(t_addr addr, unsigned short val)
49 {
50   if (addr < 0x2000) {
51     set_idata2(addr, val);
52   } else {
53     set_xdata2(addr, val);
54   }
55 }
56
57 unsigned char cl_xa::get1(t_addr addr)
58 {
59   if (addr < 0x2000) {
60     return get_idata1(addr);
61   } else {
62     return get_xdata1(addr);
63   }
64 }
65
66 unsigned short cl_xa::get2(t_addr addr)
67 {
68   if (addr < 0x2000) {
69     return get_idata2(addr);
70   } else {
71     return get_xdata2(addr);
72   }
73 }
74
75 int cl_xa::get_reg(int word_flag, unsigned int index)
76 {
77   int result;
78
79   if (word_flag) {
80     result = get_word_direct(index);
81   }
82   else {
83     result = get_byte_direct(index);
84   }
85   return result;
86 }
87
88 bool cl_xa::get_bit(int bit) {
89   short offset=0;
90   unsigned char result;
91
92   if (bit>=0x200) {
93     // in sfr space
94     bit-=0x200;
95     offset=0x400;
96   }
97   result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8));
98   return result;
99 }
100
101 void cl_xa::set_bit(int bit, int value) {
102   int i;
103   short offset=0;
104   if (bit>=0x200) {
105     // in sfr space
106     bit-=0x200;
107     offset=0x400;
108   }
109
110   i = get_byte_direct(offset + (bit/8));
111   if (value) {
112     set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) );
113   } else {
114     set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) );
115   }
116 }
117
118 #define RI_F0 ((code >> 4) & 0xf)
119 #define RI_70 ((code >> 4) & 0x7)
120 #define RI_0F (code & 0xf)
121 #define RI_07 (code & 0x7)
122
123 int cl_xa::inst_ADD(uint code, int operands)
124 {
125 #undef FUNC1
126 #define FUNC1 add1
127 #undef FUNC2
128 #define FUNC2 add2
129 #include "inst_gen.cc"
130
131   return(resGO);
132 }
133
134 int cl_xa::inst_ADDC(uint code, int operands)
135 {
136 #undef FUNC1
137 #define FUNC1 addc1
138 #undef FUNC2
139 #define FUNC2 addc2
140 #include "inst_gen.cc"
141
142   return(resGO);
143 }
144
145 int cl_xa::inst_ADDS(uint code, int operands)
146 {
147   return(resGO);
148 }
149
150 int cl_xa::inst_AND(uint code, int operands)
151 {
152 #undef FUNC1
153 #define FUNC1 and1
154 #undef FUNC2
155 #define FUNC2 and2
156 #include "inst_gen.cc"
157   return(resGO);
158 }
159
160 int cl_xa::inst_ANL(uint code, int operands)
161 {
162   return(resGO);
163 }
164
165 int cl_xa::inst_ASL(uint code, int operands)
166 {
167   return(resGO);
168 }
169
170 int cl_xa::inst_ASR(uint code, int operands)
171 {
172   return(resGO);
173 }
174
175 int cl_xa::inst_BCC(uint code, int operands)
176 {
177   short jmpAddr = fetch1()*2;
178   if (!(get_psw() & BIT_C)) {
179     PC=(PC+jmpAddr)&0xfffffe;
180   }
181   return(resGO);
182 }
183
184 int cl_xa::inst_BCS(uint code, int operands)
185 {
186   short jmpAddr = fetch1()*2;
187   if (get_psw() & BIT_C) {
188     PC=(PC+jmpAddr)&0xfffffe;
189   }
190   return(resGO);
191 }
192
193 int cl_xa::inst_BEQ(uint code, int operands)
194 {
195   short jmpAddr = fetch1()*2;
196   if (get_psw() & BIT_Z) {
197     PC=(PC+jmpAddr)&0xfffffe;
198   }
199   return(resGO);
200 }
201
202 int cl_xa::inst_BG(uint code, int operands)
203 {
204   short jmpAddr = fetch1()*2;
205   short flags=get_psw();
206   bool Z=flags&BIT_Z, C=flags&BIT_C;
207   if (!(Z|C)) {
208     PC=(PC+jmpAddr)&0xfffffe;
209   }
210   return(resGO);
211 }
212 int cl_xa::inst_BGE(uint code, int operands)
213 {
214   short jmpAddr = fetch1()*2;
215   short flags=get_psw();
216   bool N=flags&BIT_N, V=flags&BIT_V;
217   if (!(N^V)) {
218     PC=(PC+jmpAddr)&0xfffffe;
219   }
220   return(resGO);
221 }
222 int cl_xa::inst_BGT(uint code, int operands)
223 {
224   short jmpAddr = fetch1()*2;
225   short flags=get_psw();
226   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
227   if (!((Z|N)^V)) {
228     PC=(PC+jmpAddr)&0xfffffe;
229   }
230   return(resGO);
231 }
232 int cl_xa::inst_BKPT(uint code, int operands)
233 {
234   return(resGO);
235 }
236 int cl_xa::inst_BL(uint code, int operands)
237 {
238   short jmpAddr = fetch1()*2;
239   short flags=get_psw();
240   bool Z=flags&BIT_Z, C=flags&BIT_C;
241   if (Z|C) {
242     PC=(PC+jmpAddr)&0xfffffe;
243   }
244   return(resGO);
245 }
246 int cl_xa::inst_BLE(uint code, int operands)
247 {
248   short jmpAddr = fetch1()*2;
249   short flags=get_psw();
250   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
251   if ((Z|N)^V) {
252     PC=(PC+jmpAddr)&0xfffffe;
253   }
254   return(resGO);
255 }
256 int cl_xa::inst_BLT(uint code, int operands)
257 {
258   short jmpAddr = fetch1()*2;
259   short flags=get_psw();
260   bool N=flags&BIT_N, V=flags&BIT_V;
261   if (N^V) {
262     PC=(PC+jmpAddr)&0xfffffe;
263   }
264   return(resGO);
265 }
266 int cl_xa::inst_BMI(uint code, int operands)
267 {
268   short jmpAddr = fetch1()*2;
269   if (get_psw()&BIT_N) {
270     PC=(PC+jmpAddr)&0xfffffe;
271   }
272   return(resGO);
273 }
274 int cl_xa::inst_BNE(uint code, int operands)
275 {
276   short jmpAddr = fetch1()*2;
277   if (!(get_psw()&BIT_Z)) {
278     PC=(PC+jmpAddr)&0xfffffe;
279   }
280   return(resGO);
281 }
282 int cl_xa::inst_BNV(uint code, int operands)
283 {
284   short jmpAddr = fetch1()*2;
285   if (!(get_psw()&BIT_V)) {
286     PC=(PC+jmpAddr)&0xfffffe;
287   }
288   return(resGO);
289 }
290 int cl_xa::inst_BOV(uint code, int operands)
291 {
292   short jmpAddr = fetch1()*2;
293   if (get_psw()&BIT_V) {
294     PC=(PC+jmpAddr)&0xfffffe;
295   }
296   return(resGO);
297 }
298 int cl_xa::inst_BPL(uint code, int operands)
299 {
300   short jmpAddr = fetch1()*2;
301   if (!(get_psw()&BIT_N)) {
302     PC=(PC+jmpAddr)&0xfffffe;
303   }
304   return(resGO);
305 }
306
307 int cl_xa::inst_BR(uint code, int operands)
308 {
309   short jmpAddr = fetch1()*2;
310   PC=(PC+jmpAddr)&0xfffffe;
311   return(resGO);
312 }
313
314 int cl_xa::inst_CALL(uint code, int operands)
315 {
316   int jmpaddr;
317   unsigned int sp;
318   bool pageZero=get_scr()&1;
319
320   switch(operands) {
321     case REL16:
322     {
323       jmpaddr = (signed short)fetch2();
324       sp = get_sp() - (pageZero ? 2 : 4);
325       set_sp(sp);
326       store2(sp, PC&0xffff);
327       if (!pageZero) {
328         store2(sp+2, (PC>>16)&0xff);
329       }
330       jmpaddr *= 2;
331       PC = (PC + jmpaddr) & 0xfffffe;
332     }
333     break;
334     case IREG:
335     {
336       sp = get_sp() - (pageZero ? 2 : 4);
337       set_sp(sp);
338       store2(sp, PC&0xffff);
339       if (!pageZero) {
340         store2(sp+2, (PC>>16)&0xff);
341       }
342       jmpaddr = reg2(RI_07);
343       jmpaddr *= 2;
344       PC = (PC + jmpaddr) & 0xfffffe;
345     }
346     break;
347   }
348   return(resGO);
349 }
350
351 int cl_xa::inst_CJNE(uint code, int operands)
352 {
353   switch(operands) {
354     case REG_DIRECT_REL8:
355     {
356        // update C,N,Z
357        if (code & 0x800) {  // word op
358          int result;
359          int src = get_word_direct( ((code & 0x7)<<4) | fetch1());
360          int addr = (fetch1() * 2);
361          int dst = reg2(RI_F0);
362          unsigned char flags;
363          flags = get_psw();
364          flags &= ~BIT_ALL; /* clear these bits */
365          result = dst - src;
366          if (result == 0) flags |= BIT_Z;
367          if (result > 0xffff) flags |= BIT_C;
368          if (dst < src) flags |= BIT_N;
369          set_psw(flags);
370          if (flags & BIT_Z)
371            PC += addr;
372        } else {
373          int result;
374          int src = get_byte_direct( ((code & 0x7)<<4) | fetch1());
375          int addr = (fetch1() * 2);
376          int dst = reg1(RI_F0);
377          unsigned char flags;
378          flags = get_psw();
379          flags &= ~BIT_ALL; /* clear these bits */
380          result = dst - src;
381          if (result == 0) flags |= BIT_Z;
382          if (result > 0xff) flags |= BIT_C;
383          if (dst < src) flags |= BIT_N;
384          set_psw(flags);
385          if (flags & BIT_Z)
386            PC += addr;
387        }
388     }
389     break;
390
391     case DIRECT_REL8:
392     {
393        int daddr = ((code & 0x7) << 8) | fetch();
394        int addr = fetch() * 2;
395
396        if (code & 0x800) {  // word op
397          unsigned short tmp = get_word_direct(daddr)-1;
398          set_word_direct(daddr, tmp);
399          if (tmp != 0)
400            PC += addr;
401        } else {
402          unsigned char tmp = get_word_direct(daddr)-1;
403          set_byte_direct(daddr, tmp);
404          if (tmp != 0)
405            PC += addr;
406        }
407     }
408     break;
409   }
410   return(resGO);
411 }
412
413 int cl_xa::inst_CLR(uint code, int operands)
414 {
415   unsigned short bitAddr = (code&0x03 << 8) + fetch();
416   set_bit (bitAddr, 0);
417   return(resGO);
418 }
419
420 int cl_xa::inst_CMP(uint code, int operands)
421 {
422 #undef FUNC1
423 #define FUNC1 cmp1
424 #undef FUNC2
425 #define FUNC2 cmp2
426 #include "inst_gen.cc"
427   return(resGO);
428 }
429 int cl_xa::inst_CPL(uint code, int operands)
430 {
431   return(resGO);
432 }
433 int cl_xa::inst_DA(uint code, int operands)
434 {
435   return(resGO);
436 }
437 int cl_xa::inst_DIV(uint code, int operands)
438 {
439   return(resGO);
440 }
441
442 int cl_xa::inst_DJNZ(uint code, int operands)
443 {
444   // update N Z flags.
445   switch(operands) {
446     case REG_REL8:
447     {
448        int addr = ( ((char)fetch1()) * 2);
449        if (code & 0x800) {  // word op
450          unsigned short tmp = mov2(0, reg2(RI_F0)-1);
451          set_reg2(RI_F0, tmp);
452          if (tmp != 0)
453            PC = (PC + addr) & 0xfffffe;
454        } else {
455          unsigned char tmp = mov1(0, reg1(RI_F0)-1);
456          set_reg1(RI_F0, tmp);
457          if (tmp != 0)
458            PC = (PC + addr) & 0xfffffe;
459        }
460     }
461     break;
462
463     case DIRECT_REL8:
464     {
465        int daddr = ((code & 0x7) << 8) | fetch();
466        int addr = fetch() * 2;
467
468        if (code & 0x800) {  // word op
469          unsigned short tmp = get_word_direct(daddr)-1;
470          set_word_direct(daddr, tmp);
471          if (tmp != 0)
472            PC += addr;
473        } else {
474          unsigned char tmp = get_word_direct(daddr)-1;
475          set_byte_direct(daddr, tmp);
476          if (tmp != 0)
477            PC += addr;
478        }
479     }
480     break;
481   }
482
483   return(resGO);
484 }
485
486 int cl_xa::inst_FCALL(uint code, int operands)
487 {
488   return(resGO);
489 }
490
491 int cl_xa::inst_FJMP(uint code, int operands)
492 {
493   return(resGO);
494 }
495
496 int cl_xa::inst_JB(uint code, int operands)
497 {
498   short bitAddr=((code&0x3)<<8) + fetch1();
499   short jmpAddr = (fetch1() * 2);
500   if (get_bit(bitAddr)) {
501     PC = (PC+jmpAddr)&0xfffffe;
502   }
503   return(resGO);
504 }
505 int cl_xa::inst_JBC(uint code, int operands)
506 {
507   short bitAddr=((code&0x3)<<8) + fetch1();
508   short jmpAddr = (fetch1() * 2);
509   if (get_bit(bitAddr)) {
510     PC = (PC+jmpAddr)&0xfffffe;
511   }
512   set_bit(bitAddr);
513   return(resGO);
514 }
515 int cl_xa::inst_JNB(uint code, int operands)
516 {
517   short bitAddr=((code&0x3)<<8) + fetch1();
518   short jmpAddr = (fetch1() * 2);
519   if (!get_bit(bitAddr)) {
520     PC = (PC+jmpAddr)&0xfffffe;
521   }
522   return(resGO);
523 }
524 int cl_xa::inst_JMP(uint code, int operands)
525 {
526   int jmpAddr;
527
528   switch(operands) {
529     case REL16:
530     {
531       jmpAddr = (signed short)fetch2()*2;
532       PC = (PC + jmpAddr) & 0xfffffe;
533     }
534     break;
535     case IREG:
536       PC &= 0xff0000;
537       PC |= (reg2(RI_07) & 0xfffe);  /* word aligned */
538     break;
539     /* fixme 2 more... */
540   }
541   return(resGO);
542 }
543 int cl_xa::inst_JNZ(uint code, int operands)
544 {
545   short saddr = (fetch1() * 2);
546   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
547   if (reg1(8)!=0) {
548     PC = (PC + saddr) & 0xfffffe;
549   }
550   return(resGO);
551 }
552 int cl_xa::inst_JZ(uint code, int operands)
553 {
554   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
555   short saddr = (fetch1() * 2);
556   if (reg1(8)==0) {
557       PC += saddr;
558   }
559   return(resGO);
560 }
561 int cl_xa::inst_LEA(uint code, int operands)
562 {
563   switch (operands) {
564     case REG_REGOFF8:
565       {
566         char offset=fetch1();
567         set_reg2(RI_70, reg2(RI_07)+offset);
568         break;
569       }
570     case REG_REGOFF16:
571       {
572         short offset=fetch2();
573         set_reg2(RI_70, reg2(RI_07)+offset);
574         break;
575       }
576   }
577   return(resGO);
578 }
579 int cl_xa::inst_LSR(uint code, int operands)
580 {
581   return(resGO);
582 }
583 int cl_xa::inst_MOV(uint code, int operands)
584 {
585 #undef FUNC1
586 #define FUNC1 mov1
587 #undef FUNC2
588 #define FUNC2 mov2
589 #include "inst_gen.cc"
590   return(resGO);
591 }
592 int cl_xa::inst_MOVC(uint code, int operands)
593 {
594   switch (operands) {
595     case REG_IREGINC:
596     {
597       short srcreg = reg2(RI_07);
598       if (code & 0x0800) {  /* word op */
599         set_reg2( RI_F0,
600                   mov2( reg2(RI_F0),
601                         getcode2(srcreg)
602                       )
603                 );
604       } else {
605         set_reg1( RI_F0,
606                   mov1( reg1(RI_F0),
607                         getcode1(srcreg)
608                       )
609                 );
610       }
611       if (operands == REG_IREGINC) {
612         set_reg2(RI_07,  srcreg+1);
613       }
614     }
615     break;
616     case A_APLUSDPTR:
617     {  /* R4l=ACC, R6=DPTR */
618       unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
619       unsigned short result;
620       unsigned char flags;
621       flags = get_psw();
622
623       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
624       result = getcode1(addr);
625       set_reg1( 4, result);
626       if (result == 0) flags |= BIT_Z;
627       if (result & 0x80) flags |= BIT_N;
628       set_psw(flags);
629     }
630     break;
631     case A_APLUSPC:
632     {  /* R4l=ACC, R6=DPTR */
633       unsigned int addr = (PC + reg1(4));
634       unsigned short result;
635       unsigned char flags;
636       flags = get_psw();
637
638       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
639       result = getcode1(addr);
640       set_reg1( 4, result);
641       if (result == 0) flags |= BIT_Z;
642       if (result & 0x80) flags |= BIT_N;
643       set_psw(flags);
644     }
645     break;
646   }
647   return(resGO);
648 }
649 int cl_xa::inst_MOVS(uint code, int operands)
650 {
651   return(resGO);
652 }
653 int cl_xa::inst_MOVX(uint code, int operands)
654 {
655   return(resGO);
656 }
657 int cl_xa::inst_MUL(uint code, int operands)
658 {
659   return(resGO);
660 }
661 int cl_xa::inst_NEG(uint code, int operands)
662 {
663   return(resGO);
664 }
665 int cl_xa::inst_NOP(uint code, int operands)
666 {
667   return(resGO);
668 }
669 int cl_xa::inst_NORM(uint code, int operands)
670 {
671   return(resGO);
672 }
673 int cl_xa::inst_OR(uint code, int operands)
674 {
675 #undef FUNC1
676 #define FUNC1 or1
677 #undef FUNC2
678 #define FUNC2 or2
679 #include "inst_gen.cc"
680   return(resGO);
681 }
682
683 int cl_xa::inst_ORL(uint code, int operands)
684 {
685   return(resGO);
686 }
687
688 int cl_xa::inst_POP(uint code, int operands)
689 {
690   unsigned short sp=get_sp();
691   switch(operands) {
692     case DIRECT:
693     {
694       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
695
696       if (code & 0x0800) {  /* word op */
697         set_word_direct(direct_addr, get2(sp) );
698       } else {
699         set_byte_direct(direct_addr, get2(sp) & 0xff );
700       }
701       set_sp(sp+2);
702     }
703     break;
704
705     case RLIST:
706     {
707       unsigned char rlist = fetch();
708       if (code & 0x0800) { // word op
709         if (code & 0x4000) { // R8-R15
710           if (rlist&0x01) { set_reg2(8, get2(sp)); sp+=2; }
711           if (rlist&0x02) { set_reg2(9, get2(sp)); sp+=2; }
712           if (rlist&0x04) { set_reg2(10, get2(sp)); sp+=2; }
713           if (rlist&0x08) { set_reg2(11, get2(sp)); sp+=2; }
714           if (rlist&0x10) { set_reg2(12, get2(sp)); sp+=2; }
715           if (rlist&0x20) { set_reg2(13, get2(sp)); sp+=2; }
716           if (rlist&0x40) { set_reg2(14, get2(sp)); sp+=2; }
717           if (rlist&0x80) { set_reg2(15, get2(sp)); sp+=2; }
718         } else { // R0-R7
719           if (rlist&0x01) { set_reg2(0, get2(sp)); sp+=2; }
720           if (rlist&0x02) { set_reg2(1, get2(sp)); sp+=2; }
721           if (rlist&0x04) { set_reg2(2, get2(sp)); sp+=2; }
722           if (rlist&0x08) { set_reg2(3, get2(sp)); sp+=2; }
723           if (rlist&0x10) { set_reg2(4, get2(sp)); sp+=2; }
724           if (rlist&0x20) { set_reg2(5, get2(sp)); sp+=2; }
725           if (rlist&0x40) { set_reg2(6, get2(sp)); sp+=2; }
726           if (rlist&0x80) { set_reg2(7, get2(sp)); sp+=2; }
727         }
728       } else { // byte op
729         if (code & 0x4000) { // R4l-R7h
730           if (rlist&0x01) { set_reg1(8, get1(sp)); sp+=2; }
731           if (rlist&0x02) { set_reg1(9, get1(sp)); sp+=2; }
732           if (rlist&0x04) { set_reg1(10, get1(sp)); sp+=2; }
733           if (rlist&0x08) { set_reg1(11, get1(sp)); sp+=2; }
734           if (rlist&0x10) { set_reg1(12, get1(sp)); sp+=2; }
735           if (rlist&0x20) { set_reg1(13, get1(sp)); sp+=2; }
736           if (rlist&0x40) { set_reg1(14, get1(sp)); sp+=2; }
737           if (rlist&0x80) { set_reg1(15, get1(sp)); sp+=2; }
738         } else { // R0l-R3h
739           if (rlist&0x01) { set_reg1(0, get1(sp)); sp+=2; }
740           if (rlist&0x02) { set_reg1(1, get1(sp)); sp+=2; }
741           if (rlist&0x04) { set_reg1(2, get1(sp)); sp+=2; }
742           if (rlist&0x08) { set_reg1(3, get1(sp)); sp+=2; }
743           if (rlist&0x10) { set_reg1(4, get1(sp)); sp+=2; }
744           if (rlist&0x20) { set_reg1(5, get1(sp)); sp+=2; }
745           if (rlist&0x40) { set_reg1(6, get1(sp)); sp+=2; }
746           if (rlist&0x80) { set_reg1(7, get1(sp)); sp+=2; }
747         }
748       }
749     }
750     break;
751   }
752   return(resGO);
753 }
754
755 int cl_xa::inst_PUSH(uint code, int operands)
756 {
757   switch(operands) {
758     case DIRECT:
759     {
760       unsigned short sp;
761       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
762
763       sp = get_sp()-2;
764       set_sp(sp);
765       if (code & 0x0800) {  /* word op */
766         store2( sp, get_word_direct(direct_addr));
767       } else {
768         store2( sp, get_byte_direct(direct_addr));
769       }
770     }
771     break;
772
773     case RLIST:
774     {
775       unsigned short sp=get_sp();
776       unsigned char rlist = fetch();
777       if (code & 0x0800) { // word op
778         if (code & 0x4000) { // R15-R8
779           if (rlist&0x80) { sp-=2; store2(sp, reg2(15)); }
780           if (rlist&0x40) { sp-=2; store2(sp, reg2(14)); }
781           if (rlist&0x20) { sp-=2; store2(sp, reg2(13)); }
782           if (rlist&0x10) { sp-=2; store2(sp, reg2(12)); }
783           if (rlist&0x08) { sp-=2; store2(sp, reg2(11)); }
784           if (rlist&0x04) { sp-=2; store2(sp, reg2(10)); }
785           if (rlist&0x02) { sp-=2; store2(sp, reg2(9)); }
786           if (rlist&0x01) { sp-=2; store2(sp, reg2(8)); }
787         } else { // R7-R0
788           if (rlist&0x80) { sp-=2; store2(sp, reg2(7)); }
789           if (rlist&0x40) { sp-=2; store2(sp, reg2(6)); }
790           if (rlist&0x20) { sp-=2; store2(sp, reg2(5)); }
791           if (rlist&0x10) { sp-=2; store2(sp, reg2(4)); }
792           if (rlist&0x08) { sp-=2; store2(sp, reg2(3)); }
793           if (rlist&0x04) { sp-=2; store2(sp, reg2(2)); }
794           if (rlist&0x02) { sp-=2; store2(sp, reg2(1)); }
795           if (rlist&0x01) { sp-=2; store2(sp, reg2(0)); }
796         }
797       } else { // byte op
798         if (code & 0x4000) { // R7h-R4l
799           if (rlist&0x80) { sp-=2; store2(sp, reg1(15)); }
800           if (rlist&0x40) { sp-=2; store2(sp, reg1(14)); }
801           if (rlist&0x20) { sp-=2; store2(sp, reg1(13)); }
802           if (rlist&0x10) { sp-=2; store2(sp, reg1(12)); }
803           if (rlist&0x08) { sp-=2; store2(sp, reg1(11)); }
804           if (rlist&0x04) { sp-=2; store2(sp, reg1(10)); }
805           if (rlist&0x02) { sp-=2; store2(sp, reg1(9)); }
806           if (rlist&0x01) { sp-=2; store2(sp, reg1(8)); }
807         } else { // R3h-R0l
808           if (rlist&0x80) { sp-=2; store2(sp, reg1(7)); }
809           if (rlist&0x40) { sp-=2; store2(sp, reg1(6)); }
810           if (rlist&0x20) { sp-=2; store2(sp, reg1(5)); }
811           if (rlist&0x10) { sp-=2; store2(sp, reg1(4)); }
812           if (rlist&0x08) { sp-=2; store2(sp, reg1(3)); }
813           if (rlist&0x04) { sp-=2; store2(sp, reg1(2)); }
814           if (rlist&0x02) { sp-=2; store2(sp, reg1(1)); }
815           if (rlist&0x01) { sp-=2; store2(sp, reg1(0)); }
816         }
817       }
818       set_sp(sp);
819     }
820     break;
821   }
822   return(resGO);
823 }
824 int cl_xa::inst_RESET(uint code, int operands)
825 {
826   return(resGO);
827 }
828 int cl_xa::inst_RET(uint code, int operands)
829 {
830   unsigned int retaddr;
831   unsigned short sp;
832   bool pageZero=get_scr()&1;
833
834   sp = get_sp();
835   retaddr = get2(sp);
836   if (!pageZero) {
837     retaddr |= get2(sp+2) << 16;
838     set_sp(sp+4);
839   } else {
840     set_sp(sp+2);
841   }
842   PC = retaddr;
843   return(resGO);
844 }
845 int cl_xa::inst_RETI(uint code, int operands)
846 {
847   unsigned int retaddr;
848   unsigned short sp;
849   bool pageZero=get_scr()&1;
850
851   sp = get_sp();
852   set_psw(get2(sp));
853   retaddr = get2(sp+2);
854   if (!pageZero) {
855     retaddr |= get2(sp+4) << 16;
856     set_sp(sp+6);
857   } else {
858     set_sp(sp+4);
859   }
860   PC = retaddr;
861   return(resGO);
862 }
863 int cl_xa::inst_RL(uint code, int operands)
864 {
865   return(resGO);
866 }
867 int cl_xa::inst_RLC(uint code, int operands)
868 {
869   return(resGO);
870 }
871 int cl_xa::inst_RR(uint code, int operands)
872 {
873   return(resGO);
874 }
875 int cl_xa::inst_RRC(uint code, int operands)
876 {
877   return(resGO);
878 }
879 int cl_xa::inst_SETB(uint code, int operands)
880 {
881   unsigned short bitAddr = (code&0x03 << 8) + fetch();
882   set_bit (bitAddr, 1);
883   return(resGO);
884 }
885
886 int cl_xa::inst_SEXT(uint code, int operands)
887 {
888   bool neg=get_psw()&BIT_N;
889   if (code & 0x0800) { // word op
890     set_reg2(RI_F0, neg ? 0xffff : 0);
891   } else {
892     set_reg1(RI_F0, neg ? 0xff : 0);
893   }
894   return(resGO);
895 }
896
897 int cl_xa::inst_SUB(uint code, int operands)
898 {
899 #undef FUNC1
900 #define FUNC1 sub1
901 #undef FUNC2
902 #define FUNC2 sub2
903 #include "inst_gen.cc"
904   return(resGO);
905 }
906
907 int cl_xa::inst_SUBB(uint code, int operands)
908 {
909 #undef FUNC1
910 #define FUNC1 subb1
911 #undef FUNC2
912 #define FUNC2 subb2
913 #include "inst_gen.cc"
914   return(resGO);
915 }
916
917 int cl_xa::inst_TRAP(uint code, int operands)
918 {
919   // steal a few opcodes for simulator only putchar() and exit()
920   // functions.  Used in SDCC regression testing.
921   switch (code & 0x0f) {
922     case 0xe:
923       // implement a simulator putchar() routine
924       //printf("PUTCHAR-----> %xH\n", reg1(0));
925       putchar(reg1(0));
926       fflush(stdout);
927     break;
928
929     case 0xf:
930       ::exit(0);
931     break;
932   }
933   return(resGO);
934 }
935
936 int cl_xa::inst_XCH(uint code, int operands)
937 {
938   return(resGO);
939 }
940 int cl_xa::inst_XOR(uint code, int operands)
941 {
942 #undef FUNC1
943 #define FUNC1 xor1
944 #undef FUNC2
945 #define FUNC2 xor2
946 #include "inst_gen.cc"
947   return(resGO);
948 }
949
950 /* End of xa.src/inst.cc */