1ed332e1db8ee7d5a9446482e4042975ee7cac7b
[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 2: // ?
228           // not really sure about the encoding here..
229           NOTDONE_ASSERT;
230         break;
231         case 3:  // dword
232           //dst = reg4(RI_F0);
233           dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16);
234           if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
235             flags |= BIT_C;
236           }
237           dst <<= cnt;
238           set_reg2(RI_F0,dst & 0xffff);
239           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
240           if (dst == 0)
241             flags |= BIT_Z;
242         break;
243       }
244     break;
245
246     case REG_DATA4 :
247     case REG_DATA5 :
248       switch (code & 0xc00) {
249         case 0: // byte
250           dst = reg1(RI_F0);
251           cnt = operands & 0x0f;
252           dst <<= cnt;
253           set_reg1(RI_F0,dst);
254           if (dst & 0x100)
255             flags |= BIT_C;
256           if ((dst & 0xff) == 0)
257             flags |= BIT_Z;
258         break;
259         case 1: // word
260           dst = reg2(RI_F0);
261           cnt = operands & 0x0f;
262           dst <<= cnt;
263           set_reg2(RI_F0,dst);
264           if (dst & 0x10000)
265             flags |= BIT_C;
266           if ((dst & 0xffff) == 0)
267             flags |= BIT_Z;
268         break;
269         case 2: // ?
270           // not really sure about the encoding here..
271           NOTDONE_ASSERT;
272         break;
273         case 3:  // dword
274           dst = reg1(RI_F0 & 0xe);
275           cnt = operands & 0x1f;
276           if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
277             flags |= BIT_C;
278           }
279           dst <<= cnt;
280           set_reg2(RI_F0,dst & 0xffff);
281           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
282           if (dst == 0)
283             flags |= BIT_Z;
284         break;
285       }
286     break;
287   }
288   set_psw(flags);
289
290   return(resGO);
291 }
292
293 /* arithmetic shift right */
294 int cl_xa::inst_ASR(uint code, int operands)
295 {
296   unsigned int dst, cnt;
297   unsigned char flags;
298
299   /* ASR, dest, count
300     while (count != 0)
301       C = dest.0; dest >>= 1;
302       this is a confusing one...
303   */
304
305   flags = get_psw();
306   flags &= ~BIT_ALL; /* clear these bits */
307
308   switch(operands) {
309     case REG_REG :
310       cnt = reg1(RI_0F) & 0x1f;
311       switch (code & 0xc00) {
312         case 0: // byte
313           dst = reg1(RI_F0);
314           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
315             flags |= BIT_C;
316           if (dst & 0x01)
317             flags |= BIT_C;
318           dst >>= cnt;
319           set_reg1(RI_F0,dst);
320           if ((dst & 0xff) == 0)
321             flags |= BIT_Z;
322         break;
323         case 1: // word
324           dst = reg2(RI_F0);
325           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
326             flags |= BIT_C;
327           dst >>= cnt;
328           set_reg2(RI_F0,dst);
329           if ((dst & 0xffff) == 0)
330             flags |= BIT_Z;
331         break;
332         case 2: // ?
333           // not really sure about the encoding here..
334           NOTDONE_ASSERT;
335         break;
336         case 3:  // dword
337           dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16);
338           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
339             flags |= BIT_C;
340           dst >>= cnt;
341           set_reg2(RI_F0,dst & 0xffff);
342           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
343           if (dst == 0)
344             flags |= BIT_Z;
345         break;
346       }
347     break;
348
349     case REG_DATA4 :
350     case REG_DATA5 :
351       switch (code & 0xc00) {
352         case 0: // byte
353           dst = reg1(RI_F0);
354           cnt = operands & 0x0f;
355           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
356             flags |= BIT_C;
357           dst >>= cnt;
358           set_reg1(RI_F0,dst);
359           if ((dst & 0xff) == 0)
360             flags |= BIT_Z;
361         break;
362         case 1: // word
363           dst = reg2(RI_F0);
364           cnt = operands & 0x0f;
365           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
366             flags |= BIT_C;
367           dst >>= cnt;
368           set_reg2(RI_F0,dst);
369           if ((dst & 0xffff) == 0)
370             flags |= BIT_Z;
371         break;
372         case 2: // ?
373           // not really sure about the encoding here..
374           NOTDONE_ASSERT;
375         break;
376         case 3:  // dword
377           dst = reg1(RI_F0 & 0xe);
378           cnt = operands & 0x1f;
379           if ((cnt != 0) && (dst & (0x00000001 << (cnt-1))))
380             flags |= BIT_C;
381           dst >>= cnt;
382           set_reg2(RI_F0,dst & 0xffff);
383           set_reg2(RI_F0+2, (dst>>16) & 0xffff);
384           if (dst == 0)
385             flags |= BIT_Z;
386         break;
387       }
388     break;
389   }
390   set_psw(flags);
391
392   return(resGO);
393 }
394
395 int cl_xa::inst_BCC(uint code, int operands)
396 {
397   short jmpAddr = fetch1()*2;
398   if (!(get_psw() & BIT_C)) {
399     PC=(PC+jmpAddr)&0xfffffe;
400   }
401   return(resGO);
402 }
403
404 int cl_xa::inst_BCS(uint code, int operands)
405 {
406   short jmpAddr = fetch1()*2;
407   if (get_psw() & BIT_C) {
408     PC=(PC+jmpAddr)&0xfffffe;
409   }
410   return(resGO);
411 }
412
413 int cl_xa::inst_BEQ(uint code, int operands)
414 {
415   short jmpAddr = fetch1()*2;
416   if (get_psw() & BIT_Z) {
417     PC=(PC+jmpAddr)&0xfffffe;
418   }
419   return(resGO);
420 }
421
422 int cl_xa::inst_BG(uint code, int operands)
423 {
424   short jmpAddr = fetch1()*2;
425   short flags=get_psw();
426   bool Z=flags&BIT_Z, C=flags&BIT_C;
427   if (!(Z|C)) {
428     PC=(PC+jmpAddr)&0xfffffe;
429   }
430   return(resGO);
431 }
432 int cl_xa::inst_BGE(uint code, int operands)
433 {
434   short jmpAddr = fetch1()*2;
435   short flags=get_psw();
436   bool N=flags&BIT_N, V=flags&BIT_V;
437   if (!(N^V)) {
438     PC=(PC+jmpAddr)&0xfffffe;
439   }
440   return(resGO);
441 }
442 int cl_xa::inst_BGT(uint code, int operands)
443 {
444   short jmpAddr = fetch1()*2;
445   short flags=get_psw();
446   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
447   if (!((Z|N)^V)) {
448     PC=(PC+jmpAddr)&0xfffffe;
449   }
450   return(resGO);
451 }
452 int cl_xa::inst_BKPT(uint code, int operands)
453 {
454   NOTDONE_ASSERT;
455   return(resGO);
456 }
457 int cl_xa::inst_BL(uint code, int operands)
458 {
459   short jmpAddr = fetch1()*2;
460   short flags=get_psw();
461   bool Z=flags&BIT_Z, C=flags&BIT_C;
462   if (Z|C) {
463     PC=(PC+jmpAddr)&0xfffffe;
464   }
465   return(resGO);
466 }
467 int cl_xa::inst_BLE(uint code, int operands)
468 {
469   short jmpAddr = fetch1()*2;
470   short flags=get_psw();
471   bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
472   if ((Z|N)^V) {
473     PC=(PC+jmpAddr)&0xfffffe;
474   }
475   return(resGO);
476 }
477 int cl_xa::inst_BLT(uint code, int operands)
478 {
479   short jmpAddr = fetch1()*2;
480   short flags=get_psw();
481   bool N=flags&BIT_N, V=flags&BIT_V;
482   if (N^V) {
483     PC=(PC+jmpAddr)&0xfffffe;
484   }
485   return(resGO);
486 }
487 int cl_xa::inst_BMI(uint code, int operands)
488 {
489   short jmpAddr = fetch1()*2;
490   if (get_psw()&BIT_N) {
491     PC=(PC+jmpAddr)&0xfffffe;
492   }
493   return(resGO);
494 }
495 int cl_xa::inst_BNE(uint code, int operands)
496 {
497   short jmpAddr = fetch1()*2;
498   if (!(get_psw()&BIT_Z)) {
499     PC=(PC+jmpAddr)&0xfffffe;
500   }
501   return(resGO);
502 }
503 int cl_xa::inst_BNV(uint code, int operands)
504 {
505   short jmpAddr = fetch1()*2;
506   if (!(get_psw()&BIT_V)) {
507     PC=(PC+jmpAddr)&0xfffffe;
508   }
509   return(resGO);
510 }
511 int cl_xa::inst_BOV(uint code, int operands)
512 {
513   short jmpAddr = fetch1()*2;
514   if (get_psw()&BIT_V) {
515     PC=(PC+jmpAddr)&0xfffffe;
516   }
517   return(resGO);
518 }
519 int cl_xa::inst_BPL(uint code, int operands)
520 {
521   short jmpAddr = fetch1()*2;
522   if (!(get_psw()&BIT_N)) {
523     PC=(PC+jmpAddr)&0xfffffe;
524   }
525   return(resGO);
526 }
527
528 int cl_xa::inst_BR(uint code, int operands)
529 {
530   short jmpAddr = fetch1()*2;
531   PC=(PC+jmpAddr)&0xfffffe;
532   return(resGO);
533 }
534
535 int cl_xa::inst_CALL(uint code, int operands)
536 {
537   int jmpaddr;
538   unsigned int sp;
539   bool pageZero=get_scr()&1;
540
541   switch(operands) {
542     case REL16:
543     {
544       jmpaddr = (signed short)fetch2();
545       sp = get_sp() - (pageZero ? 2 : 4);
546       set_sp(sp);
547       store2(sp, PC&0xffff);
548       if (!pageZero) {
549         store2(sp+2, (PC>>16)&0xff);
550       }
551       jmpaddr *= 2;
552       PC = (PC + jmpaddr) & 0xfffffe;
553     }
554     break;
555     case IREG:
556     {
557       sp = get_sp() - (pageZero ? 2 : 4);
558       set_sp(sp);
559       store2(sp, PC&0xffff);
560       if (!pageZero) {
561         store2(sp+2, (PC>>16)&0xff);
562       }
563       jmpaddr = reg2(RI_07);
564       jmpaddr *= 2;
565       PC = (PC + jmpaddr) & 0xfffffe;
566     }
567     break;
568   }
569   return(resGO);
570 }
571
572 int cl_xa::inst_CJNE(uint code, int operands)
573 {
574   switch(operands) {
575     case REG_DIRECT_REL8:
576     {
577        // update C,N,Z
578        if (code & 0x800) {  // word op
579          int result;
580          int src = get_word_direct( ((code & 0x7)<<4) | fetch1());
581          int addr = (fetch1() * 2);
582          int dst = reg2(RI_F0);
583          unsigned char flags;
584          flags = get_psw();
585          flags &= ~BIT_ALL; /* clear these bits */
586          result = dst - src;
587          if (result == 0) flags |= BIT_Z;
588          if (result > 0xffff) flags |= BIT_C;
589          if (dst < src) flags |= BIT_N;
590          set_psw(flags);
591          if (flags & BIT_Z)
592            PC += addr;
593        } else {
594          int result;
595          int src = get_byte_direct( ((code & 0x7)<<4) | fetch1());
596          int addr = (fetch1() * 2);
597          int dst = reg1(RI_F0);
598          unsigned char flags;
599          flags = get_psw();
600          flags &= ~BIT_ALL; /* clear these bits */
601          result = dst - src;
602          if (result == 0) flags |= BIT_Z;
603          if (result > 0xff) flags |= BIT_C;
604          if (dst < src) flags |= BIT_N;
605          set_psw(flags);
606          if (flags & BIT_Z)
607            PC += addr;
608        }
609     }
610     break;
611
612     case DIRECT_REL8:
613     {
614        int daddr = ((code & 0x7) << 8) | fetch();
615        int addr = fetch() * 2;
616
617        if (code & 0x800) {  // word op
618          unsigned short tmp = get_word_direct(daddr)-1;
619          set_word_direct(daddr, tmp);
620          if (tmp != 0)
621            PC += addr;
622        } else {
623          unsigned char tmp = get_word_direct(daddr)-1;
624          set_byte_direct(daddr, tmp);
625          if (tmp != 0)
626            PC += addr;
627        }
628     }
629     break;
630   }
631   return(resGO);
632 }
633
634 int cl_xa::inst_CLR(uint code, int operands)
635 {
636   unsigned short bitAddr = (code&0x03 << 8) + fetch();
637   set_bit (bitAddr, 0);
638   return(resGO);
639 }
640
641 int cl_xa::inst_CMP(uint code, int operands)
642 {
643 #undef FUNC1
644 #define FUNC1 cmp1
645 #undef FUNC2
646 #define FUNC2 cmp2
647 #include "inst_gen.cc"
648   return(resGO);
649 }
650 int cl_xa::inst_CPL(uint code, int operands)
651 {
652   NOTDONE_ASSERT;
653   return(resGO);
654 }
655 int cl_xa::inst_DA(uint code, int operands)
656 {
657   NOTDONE_ASSERT;
658   return(resGO);
659 }
660 int cl_xa::inst_DIV(uint code, int operands)
661 {
662   NOTDONE_ASSERT;
663   return(resGO);
664 }
665
666 int cl_xa::inst_DJNZ(uint code, int operands)
667 {
668   // update N Z flags.
669   switch(operands) {
670     case REG_REL8:
671     {
672        int addr = ( ((char)fetch1()) * 2);
673        if (code & 0x800) {  // word op
674          unsigned short tmp = mov2(0, reg2(RI_F0)-1);
675          set_reg2(RI_F0, tmp);
676          if (tmp != 0)
677            PC = (PC + addr) & 0xfffffe;
678        } else {
679          unsigned char tmp = mov1(0, reg1(RI_F0)-1);
680          set_reg1(RI_F0, tmp);
681          if (tmp != 0)
682            PC = (PC + addr) & 0xfffffe;
683        }
684     }
685     break;
686
687     case DIRECT_REL8:
688     {
689        int daddr = ((code & 0x7) << 8) | fetch();
690        int addr = fetch() * 2;
691
692        if (code & 0x800) {  // word op
693          unsigned short tmp = get_word_direct(daddr)-1;
694          set_word_direct(daddr, tmp);
695          if (tmp != 0)
696            PC += addr;
697        } else {
698          unsigned char tmp = get_word_direct(daddr)-1;
699          set_byte_direct(daddr, tmp);
700          if (tmp != 0)
701            PC += addr;
702        }
703     }
704     break;
705   }
706
707   return(resGO);
708 }
709
710 int cl_xa::inst_FCALL(uint code, int operands)
711 {
712   NOTDONE_ASSERT;
713   return(resGO);
714 }
715
716 int cl_xa::inst_FJMP(uint code, int operands)
717 {
718   NOTDONE_ASSERT;
719   return(resGO);
720 }
721
722 int cl_xa::inst_JB(uint code, int operands)
723 {
724   short bitAddr=((code&0x3)<<8) + fetch1();
725   short jmpAddr = (fetch1() * 2);
726   if (get_bit(bitAddr)) {
727     PC = (PC+jmpAddr)&0xfffffe;
728   }
729   return(resGO);
730 }
731 int cl_xa::inst_JBC(uint code, int operands)
732 {
733   short bitAddr=((code&0x3)<<8) + fetch1();
734   short jmpAddr = (fetch1() * 2);
735   if (get_bit(bitAddr)) {
736     PC = (PC+jmpAddr)&0xfffffe;
737   }
738   set_bit(bitAddr,0);
739   return(resGO);
740 }
741 int cl_xa::inst_JNB(uint code, int operands)
742 {
743   short bitAddr=((code&0x3)<<8) + fetch1();
744   short jmpAddr = (fetch1() * 2);
745   if (!get_bit(bitAddr)) {
746     PC = (PC+jmpAddr)&0xfffffe;
747   }
748   return(resGO);
749 }
750 int cl_xa::inst_JMP(uint code, int operands)
751 {
752   int jmpAddr;
753
754   switch(operands) {
755     case REL16:
756     {
757       jmpAddr = (signed short)fetch2()*2;
758       PC = (PC + jmpAddr) & 0xfffffe;
759     }
760     break;
761     case IREG:
762       PC &= 0xff0000;
763       PC |= (reg2(RI_07) & 0xfffe);  /* word aligned */
764     break;
765     /* fixme 2 more... */
766   }
767   return(resGO);
768 }
769 int cl_xa::inst_JNZ(uint code, int operands)
770 {
771   short saddr = (fetch1() * 2);
772   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
773   if (reg1(8)!=0) {
774     PC = (PC + saddr) & 0xfffffe;
775   }
776   return(resGO);
777 }
778 int cl_xa::inst_JZ(uint code, int operands)
779 {
780   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
781   short saddr = (fetch1() * 2);
782   if (reg1(8)==0) {
783       PC += saddr;
784   }
785   return(resGO);
786 }
787 int cl_xa::inst_LEA(uint code, int operands)
788 {
789   switch (operands) {
790     case REG_REGOFF8:
791       {
792         char offset=fetch1();
793         set_reg2(RI_70, reg2(RI_07)+offset);
794         break;
795       }
796     case REG_REGOFF16:
797       {
798         short offset=fetch2();
799         set_reg2(RI_70, reg2(RI_07)+offset);
800         break;
801       }
802   }
803   return(resGO);
804 }
805 int cl_xa::inst_LSR(uint code, int operands)
806 {
807   NOTDONE_ASSERT;
808   return(resGO);
809 }
810 int cl_xa::inst_MOV(uint code, int operands)
811 {
812 #undef FUNC1
813 #define FUNC1 mov1
814 #undef FUNC2
815 #define FUNC2 mov2
816 #include "inst_gen.cc"
817   return(resGO);
818 }
819 int cl_xa::inst_MOVC(uint code, int operands)
820 {
821   switch (operands) {
822     case REG_IREGINC:
823     {
824       short srcreg = reg2(RI_07);
825       if (code & 0x0800) {  /* word op */
826         set_reg2( RI_F0,
827                   mov2( reg2(RI_F0),
828                         getcode2(srcreg)
829                       )
830                 );
831       } else {
832         set_reg1( RI_F0,
833                   mov1( reg1(RI_F0),
834                         getcode1(srcreg)
835                       )
836                 );
837       }
838       if (operands == REG_IREGINC) {
839         set_reg2(RI_07,  srcreg+1);
840       }
841     }
842     break;
843     case A_APLUSDPTR:
844     {  /* R4l=ACC, R6=DPTR */
845       unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
846       unsigned short result;
847       unsigned char flags;
848       flags = get_psw();
849
850       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
851       result = getcode1(addr);
852       set_reg1( 4, result);
853       if (result == 0) flags |= BIT_Z;
854       if (result & 0x80) flags |= BIT_N;
855       set_psw(flags);
856     }
857     break;
858     case A_APLUSPC:
859     {  /* R4l=ACC, R6=DPTR */
860       unsigned int addr = (PC + reg1(4));
861       unsigned short result;
862       unsigned char flags;
863       flags = get_psw();
864
865       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
866       result = getcode1(addr);
867       set_reg1( 4, result);
868       if (result == 0) flags |= BIT_Z;
869       if (result & 0x80) flags |= BIT_N;
870       set_psw(flags);
871     }
872     break;
873   }
874   return(resGO);
875 }
876 int cl_xa::inst_MOVS(uint code, int operands)
877 {
878   NOTDONE_ASSERT;
879   return(resGO);
880 }
881 int cl_xa::inst_MOVX(uint code, int operands)
882 {
883   NOTDONE_ASSERT;
884   return(resGO);
885 }
886 int cl_xa::inst_MUL(uint code, int operands)
887 {
888   NOTDONE_ASSERT;
889   return(resGO);
890 }
891 int cl_xa::inst_NEG(uint code, int operands)
892 {
893   NOTDONE_ASSERT;
894   return(resGO);
895 }
896 int cl_xa::inst_NOP(uint code, int operands)
897 {
898   return(resGO);
899 }
900 int cl_xa::inst_NORM(uint code, int operands)
901 {
902   NOTDONE_ASSERT;
903   return(resGO);
904 }
905 int cl_xa::inst_OR(uint code, int operands)
906 {
907 #undef FUNC1
908 #define FUNC1 or1
909 #undef FUNC2
910 #define FUNC2 or2
911 #include "inst_gen.cc"
912   return(resGO);
913 }
914
915 int cl_xa::inst_ORL(uint code, int operands)
916 {
917   NOTDONE_ASSERT;
918   return(resGO);
919 }
920
921 int cl_xa::inst_POP(uint code, int operands)
922 {
923   unsigned short sp=get_sp();
924   switch(operands) {
925     case DIRECT:
926     {
927       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
928
929       if (code & 0x0800) {  /* word op */
930         set_word_direct(direct_addr, get2(sp) );
931       } else {
932         set_byte_direct(direct_addr, get2(sp) & 0xff );
933       }
934       set_sp(sp+2);
935     }
936     break;
937
938     case RLIST:
939     {
940       unsigned char rlist = fetch();
941       if (code & 0x0800) { // word op
942         if (code & 0x4000) { // R8-R15
943           if (rlist&0x01) { set_reg2(8, get2(sp)); sp+=2; }
944           if (rlist&0x02) { set_reg2(9, get2(sp)); sp+=2; }
945           if (rlist&0x04) { set_reg2(10, get2(sp)); sp+=2; }
946           if (rlist&0x08) { set_reg2(11, get2(sp)); sp+=2; }
947           if (rlist&0x10) { set_reg2(12, get2(sp)); sp+=2; }
948           if (rlist&0x20) { set_reg2(13, get2(sp)); sp+=2; }
949           if (rlist&0x40) { set_reg2(14, get2(sp)); sp+=2; }
950           if (rlist&0x80) { set_reg2(15, get2(sp)); sp+=2; }
951         } else { // R0-R7
952           if (rlist&0x01) { set_reg2(0, get2(sp)); sp+=2; }
953           if (rlist&0x02) { set_reg2(1, get2(sp)); sp+=2; }
954           if (rlist&0x04) { set_reg2(2, get2(sp)); sp+=2; }
955           if (rlist&0x08) { set_reg2(3, get2(sp)); sp+=2; }
956           if (rlist&0x10) { set_reg2(4, get2(sp)); sp+=2; }
957           if (rlist&0x20) { set_reg2(5, get2(sp)); sp+=2; }
958           if (rlist&0x40) { set_reg2(6, get2(sp)); sp+=2; }
959           if (rlist&0x80) { set_reg2(7, get2(sp)); sp+=2; }
960         }
961       } else { // byte op
962         if (code & 0x4000) { // R4l-R7h
963           if (rlist&0x01) { set_reg1(8, get1(sp)); sp+=2; }
964           if (rlist&0x02) { set_reg1(9, get1(sp)); sp+=2; }
965           if (rlist&0x04) { set_reg1(10, get1(sp)); sp+=2; }
966           if (rlist&0x08) { set_reg1(11, get1(sp)); sp+=2; }
967           if (rlist&0x10) { set_reg1(12, get1(sp)); sp+=2; }
968           if (rlist&0x20) { set_reg1(13, get1(sp)); sp+=2; }
969           if (rlist&0x40) { set_reg1(14, get1(sp)); sp+=2; }
970           if (rlist&0x80) { set_reg1(15, get1(sp)); sp+=2; }
971         } else { // R0l-R3h
972           if (rlist&0x01) { set_reg1(0, get1(sp)); sp+=2; }
973           if (rlist&0x02) { set_reg1(1, get1(sp)); sp+=2; }
974           if (rlist&0x04) { set_reg1(2, get1(sp)); sp+=2; }
975           if (rlist&0x08) { set_reg1(3, get1(sp)); sp+=2; }
976           if (rlist&0x10) { set_reg1(4, get1(sp)); sp+=2; }
977           if (rlist&0x20) { set_reg1(5, get1(sp)); sp+=2; }
978           if (rlist&0x40) { set_reg1(6, get1(sp)); sp+=2; }
979           if (rlist&0x80) { set_reg1(7, get1(sp)); sp+=2; }
980         }
981       }
982     }
983     break;
984   }
985   return(resGO);
986 }
987
988 int cl_xa::inst_PUSH(uint code, int operands)
989 {
990   switch(operands) {
991     case DIRECT:
992     {
993       unsigned short sp;
994       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
995
996       sp = get_sp()-2;
997       set_sp(sp);
998       if (code & 0x0800) {  /* word op */
999         store2( sp, get_word_direct(direct_addr));
1000       } else {
1001         store2( sp, get_byte_direct(direct_addr));
1002       }
1003     }
1004     break;
1005
1006     case RLIST:
1007     {
1008       unsigned short sp=get_sp();
1009       unsigned char rlist = fetch();
1010       if (code & 0x0800) { // word op
1011         if (code & 0x4000) { // R15-R8
1012           if (rlist&0x80) { sp-=2; store2(sp, reg2(15)); }
1013           if (rlist&0x40) { sp-=2; store2(sp, reg2(14)); }
1014           if (rlist&0x20) { sp-=2; store2(sp, reg2(13)); }
1015           if (rlist&0x10) { sp-=2; store2(sp, reg2(12)); }
1016           if (rlist&0x08) { sp-=2; store2(sp, reg2(11)); }
1017           if (rlist&0x04) { sp-=2; store2(sp, reg2(10)); }
1018           if (rlist&0x02) { sp-=2; store2(sp, reg2(9)); }
1019           if (rlist&0x01) { sp-=2; store2(sp, reg2(8)); }
1020         } else { // R7-R0
1021           if (rlist&0x80) { sp-=2; store2(sp, reg2(7)); }
1022           if (rlist&0x40) { sp-=2; store2(sp, reg2(6)); }
1023           if (rlist&0x20) { sp-=2; store2(sp, reg2(5)); }
1024           if (rlist&0x10) { sp-=2; store2(sp, reg2(4)); }
1025           if (rlist&0x08) { sp-=2; store2(sp, reg2(3)); }
1026           if (rlist&0x04) { sp-=2; store2(sp, reg2(2)); }
1027           if (rlist&0x02) { sp-=2; store2(sp, reg2(1)); }
1028           if (rlist&0x01) { sp-=2; store2(sp, reg2(0)); }
1029         }
1030       } else { // byte op
1031         if (code & 0x4000) { // R7h-R4l
1032           if (rlist&0x80) { sp-=2; store2(sp, reg1(15)); }
1033           if (rlist&0x40) { sp-=2; store2(sp, reg1(14)); }
1034           if (rlist&0x20) { sp-=2; store2(sp, reg1(13)); }
1035           if (rlist&0x10) { sp-=2; store2(sp, reg1(12)); }
1036           if (rlist&0x08) { sp-=2; store2(sp, reg1(11)); }
1037           if (rlist&0x04) { sp-=2; store2(sp, reg1(10)); }
1038           if (rlist&0x02) { sp-=2; store2(sp, reg1(9)); }
1039           if (rlist&0x01) { sp-=2; store2(sp, reg1(8)); }
1040         } else { // R3h-R0l
1041           if (rlist&0x80) { sp-=2; store2(sp, reg1(7)); }
1042           if (rlist&0x40) { sp-=2; store2(sp, reg1(6)); }
1043           if (rlist&0x20) { sp-=2; store2(sp, reg1(5)); }
1044           if (rlist&0x10) { sp-=2; store2(sp, reg1(4)); }
1045           if (rlist&0x08) { sp-=2; store2(sp, reg1(3)); }
1046           if (rlist&0x04) { sp-=2; store2(sp, reg1(2)); }
1047           if (rlist&0x02) { sp-=2; store2(sp, reg1(1)); }
1048           if (rlist&0x01) { sp-=2; store2(sp, reg1(0)); }
1049         }
1050       }
1051       set_sp(sp);
1052     }
1053     break;
1054   }
1055   return(resGO);
1056 }
1057 int cl_xa::inst_RESET(uint code, int operands)
1058 {
1059   NOTDONE_ASSERT;
1060   return(resGO);
1061 }
1062 int cl_xa::inst_RET(uint code, int operands)
1063 {
1064   unsigned int retaddr;
1065   unsigned short sp;
1066   bool pageZero=get_scr()&1;
1067
1068   sp = get_sp();
1069   retaddr = get2(sp);
1070   if (!pageZero) {
1071     retaddr |= get2(sp+2) << 16;
1072     set_sp(sp+4);
1073   } else {
1074     set_sp(sp+2);
1075   }
1076   PC = retaddr;
1077   return(resGO);
1078 }
1079 int cl_xa::inst_RETI(uint code, int operands)
1080 {
1081   unsigned int retaddr;
1082   unsigned short sp;
1083   bool pageZero=get_scr()&1;
1084
1085   sp = get_sp();
1086   set_psw(get2(sp));
1087   retaddr = get2(sp+2);
1088   if (!pageZero) {
1089     retaddr |= get2(sp+4) << 16;
1090     set_sp(sp+6);
1091   } else {
1092     set_sp(sp+4);
1093   }
1094   PC = retaddr;
1095   return(resGO);
1096 }
1097 int cl_xa::inst_RL(uint code, int operands)
1098 {
1099   NOTDONE_ASSERT;
1100   return(resGO);
1101 }
1102 int cl_xa::inst_RLC(uint code, int operands)
1103 {
1104   NOTDONE_ASSERT;
1105   return(resGO);
1106 }
1107 int cl_xa::inst_RR(uint code, int operands)
1108 {
1109   NOTDONE_ASSERT;
1110   return(resGO);
1111 }
1112 int cl_xa::inst_RRC(uint code, int operands)
1113 {
1114   NOTDONE_ASSERT;
1115   return(resGO);
1116 }
1117 int cl_xa::inst_SETB(uint code, int operands)
1118 {
1119   unsigned short bitAddr = (code&0x03 << 8) + fetch();
1120   set_bit (bitAddr, 1);
1121   return(resGO);
1122 }
1123
1124 int cl_xa::inst_SEXT(uint code, int operands)
1125 {
1126   bool neg=get_psw()&BIT_N;
1127   if (code & 0x0800) { // word op
1128     set_reg2(RI_F0, neg ? 0xffff : 0);
1129   } else {
1130     set_reg1(RI_F0, neg ? 0xff : 0);
1131   }
1132   return(resGO);
1133 }
1134
1135 int cl_xa::inst_SUB(uint code, int operands)
1136 {
1137 #undef FUNC1
1138 #define FUNC1 sub1
1139 #undef FUNC2
1140 #define FUNC2 sub2
1141 #include "inst_gen.cc"
1142   return(resGO);
1143 }
1144
1145 int cl_xa::inst_SUBB(uint code, int operands)
1146 {
1147 #undef FUNC1
1148 #define FUNC1 subb1
1149 #undef FUNC2
1150 #define FUNC2 subb2
1151 #include "inst_gen.cc"
1152   return(resGO);
1153 }
1154
1155 int cl_xa::inst_TRAP(uint code, int operands)
1156 {
1157   // steal a few opcodes for simulator only putchar() and exit()
1158   // functions.  Used in SDCC regression testing.
1159   switch (code & 0x0f) {
1160     case 0xe:
1161       // implement a simulator putchar() routine
1162       //printf("PUTCHAR-----> %xH\n", reg1(0));
1163       putchar(reg1(0));
1164       fflush(stdout);
1165     break;
1166
1167     case 0xf:
1168       ::exit(0);
1169     break;
1170   }
1171   return(resGO);
1172 }
1173
1174 int cl_xa::inst_XCH(uint code, int operands)
1175 {
1176   NOTDONE_ASSERT;
1177   return(resGO);
1178 }
1179 int cl_xa::inst_XOR(uint code, int operands)
1180 {
1181 #undef FUNC1
1182 #define FUNC1 xor1
1183 #undef FUNC2
1184 #define FUNC2 xor2
1185 #include "inst_gen.cc"
1186   return(resGO);
1187 }
1188
1189 /* End of xa.src/inst.cc */