f96a90022c09c75acb9a310924e36cbc1b20eb4c
[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 #define NOTDONE_ASSERT { printf("**********Instr not done at %d!\n", __LINE__); }
39
40 void cl_xa::store1(t_addr addr, unsigned char val)
41 {
42   if (addr < 0x2000) {
43     set_idata1(addr, val);
44   } else {
45     set_xdata1(addr, val);
46   }
47 }
48
49 void cl_xa::store2(t_addr addr, unsigned short val)
50 {
51   if (addr < 0x2000) {
52     set_idata2(addr, val);
53   } else {
54     set_xdata2(addr, val);
55   }
56 }
57
58 unsigned char cl_xa::get1(t_addr addr)
59 {
60   if (addr < 0x2000) {
61     return get_idata1(addr);
62   } else {
63     return get_xdata1(addr);
64   }
65 }
66
67 unsigned short cl_xa::get2(t_addr addr)
68 {
69   if (addr < 0x2000) {
70     return get_idata2(addr);
71   } else {
72     return get_xdata2(addr);
73   }
74 }
75
76 int cl_xa::get_reg(int word_flag, unsigned int index)
77 {
78   int result;
79
80   if (word_flag) {
81     result = get_word_direct(index);
82   }
83   else {
84     result = get_byte_direct(index);
85   }
86   return result;
87 }
88
89 bool cl_xa::get_bit(int bit) {
90   short offset=0;
91   unsigned char result;
92
93   if (bit>=0x200) {
94     // in sfr space
95     bit-=0x200;
96     offset=0x400;
97   }
98   result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8));
99   return result;
100 }
101
102 void cl_xa::set_bit(int bit, int value) {
103   int i;
104   short offset=0;
105   if (bit>=0x200) {
106     // in sfr space
107     bit-=0x200;
108     offset=0x400;
109   }
110
111   i = get_byte_direct(offset + (bit/8));
112   if (value) {
113     set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) );
114   } else {
115     set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) );
116   }
117 }
118
119 #define RI_F0 ((code >> 4) & 0xf)
120 #define RI_70 ((code >> 4) & 0x7)
121 #define RI_0F (code & 0xf)
122 #define RI_07 (code & 0x7)
123
124 int cl_xa::inst_ADD(uint code, int operands)
125 {
126 #undef FUNC1
127 #define FUNC1 add1
128 #undef FUNC2
129 #define FUNC2 add2
130 #include "inst_gen.cc"
131
132   return(resGO);
133 }
134
135 int cl_xa::inst_ADDC(uint code, int operands)
136 {
137 #undef FUNC1
138 #define FUNC1 addc1
139 #undef FUNC2
140 #define FUNC2 addc2
141 #include "inst_gen.cc"
142
143   return(resGO);
144 }
145
146 int cl_xa::inst_ADDS(uint code, int operands)
147 {
148   NOTDONE_ASSERT;
149   return(resGO);
150 }
151
152 int cl_xa::inst_AND(uint code, int operands)
153 {
154 #undef FUNC1
155 #define FUNC1 and1
156 #undef FUNC2
157 #define FUNC2 and2
158 #include "inst_gen.cc"
159   return(resGO);
160 }
161
162 /* logical AND bit with Carry flag */
163 int cl_xa::inst_ANL(uint code, int operands)
164 {
165  unsigned char flags;
166  unsigned short bitAddr = (code&0x03 << 8) + fetch();
167  flags = get_psw();
168
169   if (flags & BIT_C) {
170     /* have work to do */
171     switch(operands) {
172       case CY_BIT :
173         if (!get_bit(bitAddr)) {
174           set_psw(flags & ~BIT_C);
175         }
176       break;
177
178       case CY_NOTBIT :
179         if (get_bit(bitAddr)) {
180           set_psw(flags & ~BIT_C);
181         }
182       break;
183     }
184   }
185
186   return(resGO);
187 }
188
189 /* arithmetic shift left */
190 int cl_xa::inst_ASL(uint code, int operands)
191 {
192   unsigned int dst, cnt;
193   unsigned char flags;
194
195   /* ASL, dest, count
196     while (count != 0)
197       C = dest.80H; dest <<= 1; if sign chg then set V=1
198       this is a confusing one...
199   */
200
201   flags = get_psw();
202   flags &= ~BIT_ALL; /* clear these bits */
203
204   switch(operands) {
205     //{0,0xc150,0xf300,' ',2,ASL, REG_REG         }, //  ASL Rd, Rs                 1 1 0 0 S S 0 1  d d d d s s s s
206     case REG_REG :
207       cnt = reg1(RI_0F) & 0x1f;
208       switch (code & 0xc00) {
209         case 0: // byte
210           dst = reg1(RI_F0);
211           dst <<= cnt;
212           set_reg1(RI_F0,dst);
213           if (dst & 0x100)
214             flags |= BIT_C;
215           if ((dst & 0xff) == 0)
216             flags |= BIT_Z;
217         break;
218         case 1: // word
219           dst = reg2(RI_F0);
220           dst <<= cnt;
221           set_reg2(RI_F0,dst);
222           if (dst & 0x10000)
223             flags |= BIT_C;
224           if ((dst & 0xffff) == 0)
225             flags |= BIT_Z;
226         break;
227         case 3:  // dword
228           //dst = reg4(RI_F0);
229           dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16);
230           if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
231             flags |= BIT_C;
232           }
233           dst <<= cnt;
234           set_reg2(RI_F0,dst & 0xffff);
235           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
236           if (dst == 0)
237             flags |= BIT_Z;
238         break;
239       }
240     break;
241
242     case REG_DATA4 :
243     case REG_DATA5 :
244       switch (code & 0xc00) {
245         case 0: // byte
246           dst = reg1(RI_F0);
247           cnt = operands & 0x0f;
248           dst <<= cnt;
249           set_reg1(RI_F0,dst);
250           if (dst & 0x100)
251             flags |= BIT_C;
252           if ((dst & 0xff) == 0)
253             flags |= BIT_Z;
254         break;
255         case 1: // word
256           dst = reg2(RI_F0);
257           cnt = operands & 0x0f;
258           dst <<= cnt;
259           set_reg2(RI_F0,dst);
260           if (dst & 0x10000)
261             flags |= BIT_C;
262           if ((dst & 0xffff) == 0)
263             flags |= BIT_Z;
264         break;
265         case 3:  // dword
266           dst = reg1(RI_F0 & 0xe);
267           cnt = operands & 0x1f;
268           if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
269             flags |= BIT_C;
270           }
271           dst <<= cnt;
272           set_reg2(RI_F0,dst & 0xffff);
273           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
274           if (dst == 0)
275             flags |= BIT_Z;
276         break;
277       }
278     break;
279   }
280   set_psw(flags);
281
282   return(resGO);
283 }
284
285 int cl_xa::inst_ASR(uint code, int operands)
286 {
287   NOTDONE_ASSERT;
288   return(resGO);
289 }
290
291 int cl_xa::inst_BCC(uint code, int operands)
292 {
293   short jmpAddr = fetch1()*2;
294   if (!(get_psw() & BIT_C)) {
295     PC=(PC+jmpAddr)&0xfffffe;
296   }
297   return(resGO);
298 }
299
300 int cl_xa::inst_BCS(uint code, int operands)
301 {
302   short jmpAddr = fetch1()*2;
303   if (get_psw() & BIT_C) {
304     PC=(PC+jmpAddr)&0xfffffe;
305   }
306   return(resGO);
307 }
308
309 int cl_xa::inst_BEQ(uint code, int operands)
310 {
311   short jmpAddr = fetch1()*2;
312   if (get_psw() & BIT_Z) {
313     PC=(PC+jmpAddr)&0xfffffe;
314   }
315   return(resGO);
316 }
317
318 int cl_xa::inst_BG(uint code, int operands)
319 {
320   short jmpAddr = fetch1()*2;
321   short flags=get_psw();
322   bool Z=flags&BIT_Z, C=flags&BIT_C;
323   if (!(Z|C)) {
324     PC=(PC+jmpAddr)&0xfffffe;
325   }
326   return(resGO);
327 }
328 int cl_xa::inst_BGE(uint code, int operands)
329 {
330   short jmpAddr = fetch1()*2;
331   short flags=get_psw();
332   bool N=flags&BIT_N, V=flags&BIT_V;
333   if (!(N^V)) {
334     PC=(PC+jmpAddr)&0xfffffe;
335   }
336   return(resGO);
337 }
338 int cl_xa::inst_BGT(uint code, int operands)
339 {
340   short jmpAddr = fetch1()*2;
341   short flags=get_psw();
342   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
343   if (!((Z|N)^V)) {
344     PC=(PC+jmpAddr)&0xfffffe;
345   }
346   return(resGO);
347 }
348 int cl_xa::inst_BKPT(uint code, int operands)
349 {
350   NOTDONE_ASSERT;
351   return(resGO);
352 }
353 int cl_xa::inst_BL(uint code, int operands)
354 {
355   short jmpAddr = fetch1()*2;
356   short flags=get_psw();
357   bool Z=flags&BIT_Z, C=flags&BIT_C;
358   if (Z|C) {
359     PC=(PC+jmpAddr)&0xfffffe;
360   }
361   return(resGO);
362 }
363 int cl_xa::inst_BLE(uint code, int operands)
364 {
365   short jmpAddr = fetch1()*2;
366   short flags=get_psw();
367   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
368   if ((Z|N)^V) {
369     PC=(PC+jmpAddr)&0xfffffe;
370   }
371   return(resGO);
372 }
373 int cl_xa::inst_BLT(uint code, int operands)
374 {
375   short jmpAddr = fetch1()*2;
376   short flags=get_psw();
377   bool N=flags&BIT_N, V=flags&BIT_V;
378   if (N^V) {
379     PC=(PC+jmpAddr)&0xfffffe;
380   }
381   return(resGO);
382 }
383 int cl_xa::inst_BMI(uint code, int operands)
384 {
385   short jmpAddr = fetch1()*2;
386   if (get_psw()&BIT_N) {
387     PC=(PC+jmpAddr)&0xfffffe;
388   }
389   return(resGO);
390 }
391 int cl_xa::inst_BNE(uint code, int operands)
392 {
393   short jmpAddr = fetch1()*2;
394   if (!(get_psw()&BIT_Z)) {
395     PC=(PC+jmpAddr)&0xfffffe;
396   }
397   return(resGO);
398 }
399 int cl_xa::inst_BNV(uint code, int operands)
400 {
401   short jmpAddr = fetch1()*2;
402   if (!(get_psw()&BIT_V)) {
403     PC=(PC+jmpAddr)&0xfffffe;
404   }
405   return(resGO);
406 }
407 int cl_xa::inst_BOV(uint code, int operands)
408 {
409   short jmpAddr = fetch1()*2;
410   if (get_psw()&BIT_V) {
411     PC=(PC+jmpAddr)&0xfffffe;
412   }
413   return(resGO);
414 }
415 int cl_xa::inst_BPL(uint code, int operands)
416 {
417   short jmpAddr = fetch1()*2;
418   if (!(get_psw()&BIT_N)) {
419     PC=(PC+jmpAddr)&0xfffffe;
420   }
421   return(resGO);
422 }
423
424 int cl_xa::inst_BR(uint code, int operands)
425 {
426   short jmpAddr = fetch1()*2;
427   PC=(PC+jmpAddr)&0xfffffe;
428   return(resGO);
429 }
430
431 int cl_xa::inst_CALL(uint code, int operands)
432 {
433   int jmpaddr;
434   unsigned int sp;
435   bool pageZero=get_scr()&1;
436
437   switch(operands) {
438     case REL16:
439     {
440       jmpaddr = (signed short)fetch2();
441       sp = get_sp() - (pageZero ? 2 : 4);
442       set_sp(sp);
443       store2(sp, PC&0xffff);
444       if (!pageZero) {
445         store2(sp+2, (PC>>16)&0xff);
446       }
447       jmpaddr *= 2;
448       PC = (PC + jmpaddr) & 0xfffffe;
449     }
450     break;
451     case IREG:
452     {
453       sp = get_sp() - (pageZero ? 2 : 4);
454       set_sp(sp);
455       store2(sp, PC&0xffff);
456       if (!pageZero) {
457         store2(sp+2, (PC>>16)&0xff);
458       }
459       jmpaddr = reg2(RI_07);
460       jmpaddr *= 2;
461       PC = (PC + jmpaddr) & 0xfffffe;
462     }
463     break;
464   }
465   return(resGO);
466 }
467
468 int cl_xa::inst_CJNE(uint code, int operands)
469 {
470   switch(operands) {
471     case REG_DIRECT_REL8:
472     {
473        // update C,N,Z
474        if (code & 0x800) {  // word op
475          int result;
476          int src = get_word_direct( ((code & 0x7)<<4) | fetch1());
477          int addr = (fetch1() * 2);
478          int dst = reg2(RI_F0);
479          unsigned char flags;
480          flags = get_psw();
481          flags &= ~BIT_ALL; /* clear these bits */
482          result = dst - src;
483          if (result == 0) flags |= BIT_Z;
484          if (result > 0xffff) flags |= BIT_C;
485          if (dst < src) flags |= BIT_N;
486          set_psw(flags);
487          if (flags & BIT_Z)
488            PC += addr;
489        } else {
490          int result;
491          int src = get_byte_direct( ((code & 0x7)<<4) | fetch1());
492          int addr = (fetch1() * 2);
493          int dst = reg1(RI_F0);
494          unsigned char flags;
495          flags = get_psw();
496          flags &= ~BIT_ALL; /* clear these bits */
497          result = dst - src;
498          if (result == 0) flags |= BIT_Z;
499          if (result > 0xff) flags |= BIT_C;
500          if (dst < src) flags |= BIT_N;
501          set_psw(flags);
502          if (flags & BIT_Z)
503            PC += addr;
504        }
505     }
506     break;
507
508     case DIRECT_REL8:
509     {
510        int daddr = ((code & 0x7) << 8) | fetch();
511        int addr = fetch() * 2;
512
513        if (code & 0x800) {  // word op
514          unsigned short tmp = get_word_direct(daddr)-1;
515          set_word_direct(daddr, tmp);
516          if (tmp != 0)
517            PC += addr;
518        } else {
519          unsigned char tmp = get_word_direct(daddr)-1;
520          set_byte_direct(daddr, tmp);
521          if (tmp != 0)
522            PC += addr;
523        }
524     }
525     break;
526   }
527   return(resGO);
528 }
529
530 int cl_xa::inst_CLR(uint code, int operands)
531 {
532   unsigned short bitAddr = (code&0x03 << 8) + fetch();
533   set_bit (bitAddr, 0);
534   return(resGO);
535 }
536
537 int cl_xa::inst_CMP(uint code, int operands)
538 {
539 #undef FUNC1
540 #define FUNC1 cmp1
541 #undef FUNC2
542 #define FUNC2 cmp2
543 #include "inst_gen.cc"
544   return(resGO);
545 }
546 int cl_xa::inst_CPL(uint code, int operands)
547 {
548   NOTDONE_ASSERT;
549   return(resGO);
550 }
551 int cl_xa::inst_DA(uint code, int operands)
552 {
553   NOTDONE_ASSERT;
554   return(resGO);
555 }
556 int cl_xa::inst_DIV(uint code, int operands)
557 {
558   NOTDONE_ASSERT;
559   return(resGO);
560 }
561
562 int cl_xa::inst_DJNZ(uint code, int operands)
563 {
564   // update N Z flags.
565   switch(operands) {
566     case REG_REL8:
567     {
568        int addr = ( ((char)fetch1()) * 2);
569        if (code & 0x800) {  // word op
570          unsigned short tmp = mov2(0, reg2(RI_F0)-1);
571          set_reg2(RI_F0, tmp);
572          if (tmp != 0)
573            PC = (PC + addr) & 0xfffffe;
574        } else {
575          unsigned char tmp = mov1(0, reg1(RI_F0)-1);
576          set_reg1(RI_F0, tmp);
577          if (tmp != 0)
578            PC = (PC + addr) & 0xfffffe;
579        }
580     }
581     break;
582
583     case DIRECT_REL8:
584     {
585        int daddr = ((code & 0x7) << 8) | fetch();
586        int addr = fetch() * 2;
587
588        if (code & 0x800) {  // word op
589          unsigned short tmp = get_word_direct(daddr)-1;
590          set_word_direct(daddr, tmp);
591          if (tmp != 0)
592            PC += addr;
593        } else {
594          unsigned char tmp = get_word_direct(daddr)-1;
595          set_byte_direct(daddr, tmp);
596          if (tmp != 0)
597            PC += addr;
598        }
599     }
600     break;
601   }
602
603   return(resGO);
604 }
605
606 int cl_xa::inst_FCALL(uint code, int operands)
607 {
608   NOTDONE_ASSERT;
609   return(resGO);
610 }
611
612 int cl_xa::inst_FJMP(uint code, int operands)
613 {
614   NOTDONE_ASSERT;
615   return(resGO);
616 }
617
618 int cl_xa::inst_JB(uint code, int operands)
619 {
620   short bitAddr=((code&0x3)<<8) + fetch1();
621   short jmpAddr = (fetch1() * 2);
622   if (get_bit(bitAddr)) {
623     PC = (PC+jmpAddr)&0xfffffe;
624   }
625   return(resGO);
626 }
627 int cl_xa::inst_JBC(uint code, int operands)
628 {
629   short bitAddr=((code&0x3)<<8) + fetch1();
630   short jmpAddr = (fetch1() * 2);
631   if (get_bit(bitAddr)) {
632     PC = (PC+jmpAddr)&0xfffffe;
633   }
634   set_bit(bitAddr,0);
635   return(resGO);
636 }
637 int cl_xa::inst_JNB(uint code, int operands)
638 {
639   short bitAddr=((code&0x3)<<8) + fetch1();
640   short jmpAddr = (fetch1() * 2);
641   if (!get_bit(bitAddr)) {
642     PC = (PC+jmpAddr)&0xfffffe;
643   }
644   return(resGO);
645 }
646 int cl_xa::inst_JMP(uint code, int operands)
647 {
648   int jmpAddr;
649
650   switch(operands) {
651     case REL16:
652     {
653       jmpAddr = (signed short)fetch2()*2;
654       PC = (PC + jmpAddr) & 0xfffffe;
655     }
656     break;
657     case IREG:
658       PC &= 0xff0000;
659       PC |= (reg2(RI_07) & 0xfffe);  /* word aligned */
660     break;
661     /* fixme 2 more... */
662   }
663   return(resGO);
664 }
665 int cl_xa::inst_JNZ(uint code, int operands)
666 {
667   short saddr = (fetch1() * 2);
668   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
669   if (reg1(8)!=0) {
670     PC = (PC + saddr) & 0xfffffe;
671   }
672   return(resGO);
673 }
674 int cl_xa::inst_JZ(uint code, int operands)
675 {
676   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
677   short saddr = (fetch1() * 2);
678   if (reg1(8)==0) {
679       PC += saddr;
680   }
681   return(resGO);
682 }
683 int cl_xa::inst_LEA(uint code, int operands)
684 {
685   switch (operands) {
686     case REG_REGOFF8:
687       {
688         char offset=fetch1();
689         set_reg2(RI_70, reg2(RI_07)+offset);
690         break;
691       }
692     case REG_REGOFF16:
693       {
694         short offset=fetch2();
695         set_reg2(RI_70, reg2(RI_07)+offset);
696         break;
697       }
698   }
699   return(resGO);
700 }
701 int cl_xa::inst_LSR(uint code, int operands)
702 {
703   NOTDONE_ASSERT;
704   return(resGO);
705 }
706 int cl_xa::inst_MOV(uint code, int operands)
707 {
708 #undef FUNC1
709 #define FUNC1 mov1
710 #undef FUNC2
711 #define FUNC2 mov2
712 #include "inst_gen.cc"
713   return(resGO);
714 }
715 int cl_xa::inst_MOVC(uint code, int operands)
716 {
717   switch (operands) {
718     case REG_IREGINC:
719     {
720       short srcreg = reg2(RI_07);
721       if (code & 0x0800) {  /* word op */
722         set_reg2( RI_F0,
723                   mov2( reg2(RI_F0),
724                         getcode2(srcreg)
725                       )
726                 );
727       } else {
728         set_reg1( RI_F0,
729                   mov1( reg1(RI_F0),
730                         getcode1(srcreg)
731                       )
732                 );
733       }
734       if (operands == REG_IREGINC) {
735         set_reg2(RI_07,  srcreg+1);
736       }
737     }
738     break;
739     case A_APLUSDPTR:
740     {  /* R4l=ACC, R6=DPTR */
741       unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
742       unsigned short result;
743       unsigned char flags;
744       flags = get_psw();
745
746       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
747       result = getcode1(addr);
748       set_reg1( 4, result);
749       if (result == 0) flags |= BIT_Z;
750       if (result & 0x80) flags |= BIT_N;
751       set_psw(flags);
752     }
753     break;
754     case A_APLUSPC:
755     {  /* R4l=ACC, R6=DPTR */
756       unsigned int addr = (PC + reg1(4));
757       unsigned short result;
758       unsigned char flags;
759       flags = get_psw();
760
761       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
762       result = getcode1(addr);
763       set_reg1( 4, result);
764       if (result == 0) flags |= BIT_Z;
765       if (result & 0x80) flags |= BIT_N;
766       set_psw(flags);
767     }
768     break;
769   }
770   return(resGO);
771 }
772 int cl_xa::inst_MOVS(uint code, int operands)
773 {
774   NOTDONE_ASSERT;
775   return(resGO);
776 }
777 int cl_xa::inst_MOVX(uint code, int operands)
778 {
779   NOTDONE_ASSERT;
780   return(resGO);
781 }
782 int cl_xa::inst_MUL(uint code, int operands)
783 {
784   NOTDONE_ASSERT;
785   return(resGO);
786 }
787 int cl_xa::inst_NEG(uint code, int operands)
788 {
789   NOTDONE_ASSERT;
790   return(resGO);
791 }
792 int cl_xa::inst_NOP(uint code, int operands)
793 {
794   return(resGO);
795 }
796 int cl_xa::inst_NORM(uint code, int operands)
797 {
798   NOTDONE_ASSERT;
799   return(resGO);
800 }
801 int cl_xa::inst_OR(uint code, int operands)
802 {
803 #undef FUNC1
804 #define FUNC1 or1
805 #undef FUNC2
806 #define FUNC2 or2
807 #include "inst_gen.cc"
808   return(resGO);
809 }
810
811 int cl_xa::inst_ORL(uint code, int operands)
812 {
813   NOTDONE_ASSERT;
814   return(resGO);
815 }
816
817 int cl_xa::inst_POP(uint code, int operands)
818 {
819   unsigned short sp=get_sp();
820   switch(operands) {
821     case DIRECT:
822     {
823       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
824
825       if (code & 0x0800) {  /* word op */
826         set_word_direct(direct_addr, get2(sp) );
827       } else {
828         set_byte_direct(direct_addr, get2(sp) & 0xff );
829       }
830       set_sp(sp+2);
831     }
832     break;
833
834     case RLIST:
835     {
836       unsigned char rlist = fetch();
837       if (code & 0x0800) { // word op
838         if (code & 0x4000) { // R8-R15
839           if (rlist&0x01) { set_reg2(8, get2(sp)); sp+=2; }
840           if (rlist&0x02) { set_reg2(9, get2(sp)); sp+=2; }
841           if (rlist&0x04) { set_reg2(10, get2(sp)); sp+=2; }
842           if (rlist&0x08) { set_reg2(11, get2(sp)); sp+=2; }
843           if (rlist&0x10) { set_reg2(12, get2(sp)); sp+=2; }
844           if (rlist&0x20) { set_reg2(13, get2(sp)); sp+=2; }
845           if (rlist&0x40) { set_reg2(14, get2(sp)); sp+=2; }
846           if (rlist&0x80) { set_reg2(15, get2(sp)); sp+=2; }
847         } else { // R0-R7
848           if (rlist&0x01) { set_reg2(0, get2(sp)); sp+=2; }
849           if (rlist&0x02) { set_reg2(1, get2(sp)); sp+=2; }
850           if (rlist&0x04) { set_reg2(2, get2(sp)); sp+=2; }
851           if (rlist&0x08) { set_reg2(3, get2(sp)); sp+=2; }
852           if (rlist&0x10) { set_reg2(4, get2(sp)); sp+=2; }
853           if (rlist&0x20) { set_reg2(5, get2(sp)); sp+=2; }
854           if (rlist&0x40) { set_reg2(6, get2(sp)); sp+=2; }
855           if (rlist&0x80) { set_reg2(7, get2(sp)); sp+=2; }
856         }
857       } else { // byte op
858         if (code & 0x4000) { // R4l-R7h
859           if (rlist&0x01) { set_reg1(8, get1(sp)); sp+=2; }
860           if (rlist&0x02) { set_reg1(9, get1(sp)); sp+=2; }
861           if (rlist&0x04) { set_reg1(10, get1(sp)); sp+=2; }
862           if (rlist&0x08) { set_reg1(11, get1(sp)); sp+=2; }
863           if (rlist&0x10) { set_reg1(12, get1(sp)); sp+=2; }
864           if (rlist&0x20) { set_reg1(13, get1(sp)); sp+=2; }
865           if (rlist&0x40) { set_reg1(14, get1(sp)); sp+=2; }
866           if (rlist&0x80) { set_reg1(15, get1(sp)); sp+=2; }
867         } else { // R0l-R3h
868           if (rlist&0x01) { set_reg1(0, get1(sp)); sp+=2; }
869           if (rlist&0x02) { set_reg1(1, get1(sp)); sp+=2; }
870           if (rlist&0x04) { set_reg1(2, get1(sp)); sp+=2; }
871           if (rlist&0x08) { set_reg1(3, get1(sp)); sp+=2; }
872           if (rlist&0x10) { set_reg1(4, get1(sp)); sp+=2; }
873           if (rlist&0x20) { set_reg1(5, get1(sp)); sp+=2; }
874           if (rlist&0x40) { set_reg1(6, get1(sp)); sp+=2; }
875           if (rlist&0x80) { set_reg1(7, get1(sp)); sp+=2; }
876         }
877       }
878     }
879     break;
880   }
881   return(resGO);
882 }
883
884 int cl_xa::inst_PUSH(uint code, int operands)
885 {
886   switch(operands) {
887     case DIRECT:
888     {
889       unsigned short sp;
890       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
891
892       sp = get_sp()-2;
893       set_sp(sp);
894       if (code & 0x0800) {  /* word op */
895         store2( sp, get_word_direct(direct_addr));
896       } else {
897         store2( sp, get_byte_direct(direct_addr));
898       }
899     }
900     break;
901
902     case RLIST:
903     {
904       unsigned short sp=get_sp();
905       unsigned char rlist = fetch();
906       if (code & 0x0800) { // word op
907         if (code & 0x4000) { // R15-R8
908           if (rlist&0x80) { sp-=2; store2(sp, reg2(15)); }
909           if (rlist&0x40) { sp-=2; store2(sp, reg2(14)); }
910           if (rlist&0x20) { sp-=2; store2(sp, reg2(13)); }
911           if (rlist&0x10) { sp-=2; store2(sp, reg2(12)); }
912           if (rlist&0x08) { sp-=2; store2(sp, reg2(11)); }
913           if (rlist&0x04) { sp-=2; store2(sp, reg2(10)); }
914           if (rlist&0x02) { sp-=2; store2(sp, reg2(9)); }
915           if (rlist&0x01) { sp-=2; store2(sp, reg2(8)); }
916         } else { // R7-R0
917           if (rlist&0x80) { sp-=2; store2(sp, reg2(7)); }
918           if (rlist&0x40) { sp-=2; store2(sp, reg2(6)); }
919           if (rlist&0x20) { sp-=2; store2(sp, reg2(5)); }
920           if (rlist&0x10) { sp-=2; store2(sp, reg2(4)); }
921           if (rlist&0x08) { sp-=2; store2(sp, reg2(3)); }
922           if (rlist&0x04) { sp-=2; store2(sp, reg2(2)); }
923           if (rlist&0x02) { sp-=2; store2(sp, reg2(1)); }
924           if (rlist&0x01) { sp-=2; store2(sp, reg2(0)); }
925         }
926       } else { // byte op
927         if (code & 0x4000) { // R7h-R4l
928           if (rlist&0x80) { sp-=2; store2(sp, reg1(15)); }
929           if (rlist&0x40) { sp-=2; store2(sp, reg1(14)); }
930           if (rlist&0x20) { sp-=2; store2(sp, reg1(13)); }
931           if (rlist&0x10) { sp-=2; store2(sp, reg1(12)); }
932           if (rlist&0x08) { sp-=2; store2(sp, reg1(11)); }
933           if (rlist&0x04) { sp-=2; store2(sp, reg1(10)); }
934           if (rlist&0x02) { sp-=2; store2(sp, reg1(9)); }
935           if (rlist&0x01) { sp-=2; store2(sp, reg1(8)); }
936         } else { // R3h-R0l
937           if (rlist&0x80) { sp-=2; store2(sp, reg1(7)); }
938           if (rlist&0x40) { sp-=2; store2(sp, reg1(6)); }
939           if (rlist&0x20) { sp-=2; store2(sp, reg1(5)); }
940           if (rlist&0x10) { sp-=2; store2(sp, reg1(4)); }
941           if (rlist&0x08) { sp-=2; store2(sp, reg1(3)); }
942           if (rlist&0x04) { sp-=2; store2(sp, reg1(2)); }
943           if (rlist&0x02) { sp-=2; store2(sp, reg1(1)); }
944           if (rlist&0x01) { sp-=2; store2(sp, reg1(0)); }
945         }
946       }
947       set_sp(sp);
948     }
949     break;
950   }
951   return(resGO);
952 }
953 int cl_xa::inst_RESET(uint code, int operands)
954 {
955   NOTDONE_ASSERT;
956   return(resGO);
957 }
958 int cl_xa::inst_RET(uint code, int operands)
959 {
960   unsigned int retaddr;
961   unsigned short sp;
962   bool pageZero=get_scr()&1;
963
964   sp = get_sp();
965   retaddr = get2(sp);
966   if (!pageZero) {
967     retaddr |= get2(sp+2) << 16;
968     set_sp(sp+4);
969   } else {
970     set_sp(sp+2);
971   }
972   PC = retaddr;
973   return(resGO);
974 }
975 int cl_xa::inst_RETI(uint code, int operands)
976 {
977   unsigned int retaddr;
978   unsigned short sp;
979   bool pageZero=get_scr()&1;
980
981   sp = get_sp();
982   set_psw(get2(sp));
983   retaddr = get2(sp+2);
984   if (!pageZero) {
985     retaddr |= get2(sp+4) << 16;
986     set_sp(sp+6);
987   } else {
988     set_sp(sp+4);
989   }
990   PC = retaddr;
991   return(resGO);
992 }
993 int cl_xa::inst_RL(uint code, int operands)
994 {
995   NOTDONE_ASSERT;
996   return(resGO);
997 }
998 int cl_xa::inst_RLC(uint code, int operands)
999 {
1000   NOTDONE_ASSERT;
1001   return(resGO);
1002 }
1003 int cl_xa::inst_RR(uint code, int operands)
1004 {
1005   NOTDONE_ASSERT;
1006   return(resGO);
1007 }
1008 int cl_xa::inst_RRC(uint code, int operands)
1009 {
1010   NOTDONE_ASSERT;
1011   return(resGO);
1012 }
1013 int cl_xa::inst_SETB(uint code, int operands)
1014 {
1015   unsigned short bitAddr = (code&0x03 << 8) + fetch();
1016   set_bit (bitAddr, 1);
1017   return(resGO);
1018 }
1019
1020 int cl_xa::inst_SEXT(uint code, int operands)
1021 {
1022   bool neg=get_psw()&BIT_N;
1023   if (code & 0x0800) { // word op
1024     set_reg2(RI_F0, neg ? 0xffff : 0);
1025   } else {
1026     set_reg1(RI_F0, neg ? 0xff : 0);
1027   }
1028   return(resGO);
1029 }
1030
1031 int cl_xa::inst_SUB(uint code, int operands)
1032 {
1033 #undef FUNC1
1034 #define FUNC1 sub1
1035 #undef FUNC2
1036 #define FUNC2 sub2
1037 #include "inst_gen.cc"
1038   return(resGO);
1039 }
1040
1041 int cl_xa::inst_SUBB(uint code, int operands)
1042 {
1043 #undef FUNC1
1044 #define FUNC1 subb1
1045 #undef FUNC2
1046 #define FUNC2 subb2
1047 #include "inst_gen.cc"
1048   return(resGO);
1049 }
1050
1051 int cl_xa::inst_TRAP(uint code, int operands)
1052 {
1053   // steal a few opcodes for simulator only putchar() and exit()
1054   // functions.  Used in SDCC regression testing.
1055   switch (code & 0x0f) {
1056     case 0xe:
1057       // implement a simulator putchar() routine
1058       //printf("PUTCHAR-----> %xH\n", reg1(0));
1059       putchar(reg1(0));
1060       fflush(stdout);
1061     break;
1062
1063     case 0xf:
1064       ::exit(0);
1065     break;
1066   }
1067   return(resGO);
1068 }
1069
1070 int cl_xa::inst_XCH(uint code, int operands)
1071 {
1072   NOTDONE_ASSERT;
1073   return(resGO);
1074 }
1075 int cl_xa::inst_XOR(uint code, int operands)
1076 {
1077 #undef FUNC1
1078 #define FUNC1 xor1
1079 #undef FUNC2
1080 #define FUNC2 xor2
1081 #include "inst_gen.cc"
1082   return(resGO);
1083 }
1084
1085 /* End of xa.src/inst.cc */