*** empty log message ***
[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 
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 int cl_xa::get_reg(int word_flag, unsigned int index)
39 {
40   int result;
41
42   if (word_flag) {
43     result = get_word_direct(index);
44   }
45   else {
46     result = get_byte_direct(index);
47   }
48   return result;
49 }
50
51 bool cl_xa::get_bit(int bit) {
52   short offset=0;
53   unsigned char result;
54
55   if (bit>=0x200) {
56     // in sfr space
57     bit-=0x200;
58     offset=0x400;
59   }
60   result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8));
61   return result;
62   //return mem_direct[offset + (bit/8)] & (1 << (bit%8));
63 }
64
65 void cl_xa::set_bit(int bit, int value) {
66   int i;
67   short offset=0;
68   if (bit>=0x200) {
69     // in sfr space
70     bit-=0x200;
71     offset=0x400;
72   }
73
74   i = get_byte_direct(offset + (bit/8));
75   if (value) {
76     set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) );
77     //mem_direct[offset + (bit/8)] |= (1 << (bit%8));
78   } else {
79     set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) );
80     //mem_direct[offset + (bit/8)] &= ~(1 << (bit%8));
81   }
82 }
83
84 #define RI_F0 ((code >> 4) & 0xf)
85 #define RI_70 ((code >> 4) & 0x7)
86 #define RI_0F (code & 0xf)
87 #define RI_07 (code & 0x7)
88
89 int cl_xa::inst_ADD(uint code, int operands)
90 {
91 #undef FUNC1
92 #define FUNC1 add1
93 #undef FUNC2
94 #define FUNC2 add2
95 #include "inst_gen.cc"
96
97   return(resGO);
98 }
99
100 int cl_xa::inst_ADDC(uint code, int operands)
101 {
102 #undef FUNC1
103 #define FUNC1 addc1
104 #undef FUNC2
105 #define FUNC2 addc2
106 #include "inst_gen.cc"
107
108   return(resGO);
109 }
110
111 int cl_xa::inst_ADDS(uint code, int operands)
112 {
113   return(resGO);
114 }
115
116 int cl_xa::inst_AND(uint code, int operands)
117 {
118 #undef FUNC1
119 #define FUNC1 and1
120 #undef FUNC2
121 #define FUNC2 and2
122 #include "inst_gen.cc"
123   return(resGO);
124 }
125
126 int cl_xa::inst_ANL(uint code, int operands)
127 {
128   return(resGO);
129 }
130
131 int cl_xa::inst_ASL(uint code, int operands)
132 {
133   return(resGO);
134 }
135
136 int cl_xa::inst_ASR(uint code, int operands)
137 {
138   return(resGO);
139 }
140
141 int cl_xa::inst_BCC(uint code, int operands)
142 {
143   return(resGO);
144 }
145
146 int cl_xa::inst_BCS(uint code, int operands)
147 {
148   return(resGO);
149 }
150
151 int cl_xa::inst_BEQ(uint code, int operands)
152 {
153   short jmpAddr = fetch1()*2;
154   if (get_psw() & BIT_Z) {
155     PC=(PC+jmpAddr)&0xfffffffe;
156   }
157   return(resGO);
158 }
159
160 int cl_xa::inst_BG(uint code, int operands)
161 {
162   return(resGO);
163 }
164 int cl_xa::inst_BGE(uint code, int operands)
165 {
166   return(resGO);
167 }
168 int cl_xa::inst_BGT(uint code, int operands)
169 {
170   return(resGO);
171 }
172 int cl_xa::inst_BKPT(uint code, int operands)
173 {
174   return(resGO);
175 }
176 int cl_xa::inst_BL(uint code, int operands)
177 {
178   return(resGO);
179 }
180 int cl_xa::inst_BLE(uint code, int operands)
181 {
182   return(resGO);
183 }
184 int cl_xa::inst_BLT(uint code, int operands)
185 {
186   return(resGO);
187 }
188 int cl_xa::inst_BMI(uint code, int operands)
189 {
190   return(resGO);
191 }
192 int cl_xa::inst_BNE(uint code, int operands)
193 {
194   return(resGO);
195 }
196 int cl_xa::inst_BNV(uint code, int operands)
197 {
198   return(resGO);
199 }
200 int cl_xa::inst_BOV(uint code, int operands)
201 {
202   return(resGO);
203 }
204 int cl_xa::inst_BPL(uint code, int operands)
205 {
206   return(resGO);
207 }
208
209 int cl_xa::inst_BR(uint code, int operands)
210 {
211   short jmpAddr = fetch1()*2;
212   PC=(PC+jmpAddr)&0xfffffe;
213   return(resGO);
214 }
215
216 int cl_xa::inst_CALL(uint code, int operands)
217 {
218   int jmpaddr;
219   unsigned int sp;
220   bool pageZero=get_scr()&1;
221
222   switch(operands) {
223     case REL16:
224     {
225       jmpaddr = (signed short)fetch2();
226       sp = get_sp() - (pageZero ? 2 : 4);
227       set_sp(sp);
228       store2(sp, PC&0xffff);
229       if (!pageZero) {
230         store2(sp+2, (PC>>16)&0xff);
231       }
232       jmpaddr *= 2;
233       PC = (PC + jmpaddr) & 0xfffffe;
234     }
235     break;
236     case IREG:
237     {
238       sp = get_sp() - (pageZero ? 2 : 4);
239       set_sp(sp);
240       store2(sp, PC&0xffff);
241       if (!pageZero) {
242         store2(sp+2, (PC>>16)&0xff);
243       }
244       jmpaddr = reg2(RI_07);
245       jmpaddr *= 2;
246       PC = (PC + jmpaddr) & 0xfffffe;
247     }
248     break;
249   }
250   return(resGO);
251 }
252
253 int cl_xa::inst_CJNE(uint code, int operands)
254 {
255   switch(operands) {
256     case REG_DIRECT_REL8:
257     {
258        // update C,N,Z
259        if (code & 0x800) {  // word op
260          int result;
261          int src = get_word_direct( ((code & 0x7)<<4) | fetch1());
262          int addr = (fetch1() * 2);
263          int dst = reg2(RI_F0);
264          unsigned char flags;
265          flags = get_psw();
266          flags &= ~BIT_ALL; /* clear these bits */
267          result = dst - src;
268          if (result == 0) flags |= BIT_Z;
269          if (result > 0xffff) flags |= BIT_C;
270          if (dst < src) flags |= BIT_N;
271          set_psw(flags);
272          if (flags & BIT_Z)
273            PC += addr;
274        } else {
275          int result;
276          int src = get_byte_direct( ((code & 0x7)<<4) | fetch1());
277          int addr = (fetch1() * 2);
278          int dst = reg1(RI_F0);
279          unsigned char flags;
280          flags = get_psw();
281          flags &= ~BIT_ALL; /* clear these bits */
282          result = dst - src;
283          if (result == 0) flags |= BIT_Z;
284          if (result > 0xff) flags |= BIT_C;
285          if (dst < src) flags |= BIT_N;
286          set_psw(flags);
287          if (flags & BIT_Z)
288            PC += addr;
289        }
290     }
291     break;
292
293     case DIRECT_REL8:
294     {
295        int daddr = ((code & 0x7) << 8) | fetch();
296        int addr = fetch() * 2;
297
298        if (code & 0x800) {  // word op
299          unsigned short tmp = get_word_direct(daddr)-1;
300          set_word_direct(daddr, tmp);
301          if (tmp != 0)
302            PC += addr;
303        } else {
304          unsigned char tmp = get_word_direct(daddr)-1;
305          set_byte_direct(daddr, tmp);
306          if (tmp != 0)
307            PC += addr;
308        }
309     }
310     break;
311   }
312   return(resGO);
313 }
314
315 int cl_xa::inst_CLR(uint code, int operands)
316 {
317   unsigned short bitAddr = (code&0x03 << 8) + fetch();
318   // fixme: implement
319   bitAddr=bitAddr;
320   return(resGO);
321 }
322
323 int cl_xa::inst_CMP(uint code, int operands)
324 {
325 #undef FUNC1
326 #define FUNC1 cmp1
327 #undef FUNC2
328 #define FUNC2 cmp2
329 #include "inst_gen.cc"
330   return(resGO);
331 }
332 int cl_xa::inst_CPL(uint code, int operands)
333 {
334   return(resGO);
335 }
336 int cl_xa::inst_DA(uint code, int operands)
337 {
338   return(resGO);
339 }
340 int cl_xa::inst_DIV(uint code, int operands)
341 {
342   return(resGO);
343 }
344
345 int cl_xa::inst_DJNZ(uint code, int operands)
346 {
347   // update N Z flags.
348   switch(operands) {
349     case REG_REL8:
350     {
351        int addr = ( ((char)fetch1()) * 2);
352        if (code & 0x800) {  // word op
353          unsigned short tmp = mov2(0, reg2(RI_F0)-1);
354          set_reg2(RI_F0, tmp);
355          if (tmp != 0)
356            PC = (PC + addr) & 0xfffffe;
357        } else {
358          unsigned char tmp = mov1(0, reg1(RI_F0)-1);
359          set_reg1(RI_F0, tmp);
360          if (tmp != 0)
361            PC = (PC + addr) & 0xfffffe;
362        }
363     }
364     break;
365
366     case DIRECT_REL8:
367     {
368        int daddr = ((code & 0x7) << 8) | fetch();
369        int addr = fetch() * 2;
370
371        if (code & 0x800) {  // word op
372          unsigned short tmp = get_word_direct(daddr)-1;
373          set_word_direct(daddr, tmp);
374          if (tmp != 0)
375            PC += addr;
376        } else {
377          unsigned char tmp = get_word_direct(daddr)-1;
378          set_byte_direct(daddr, tmp);
379          if (tmp != 0)
380            PC += addr;
381        }
382     }
383     break;
384   }
385
386   return(resGO);
387 }
388
389 int cl_xa::inst_FCALL(uint code, int operands)
390 {
391   return(resGO);
392 }
393
394 int cl_xa::inst_FJMP(uint code, int operands)
395 {
396   return(resGO);
397 }
398
399 int cl_xa::inst_JB(uint code, int operands)
400 {
401   short bitAddr=((code&0x3)<<8) + fetch1();
402   short jmpAddr = (fetch1() * 2);
403   if (get_bit(bitAddr)) {
404     PC = (PC+jmpAddr)&0xfffffe;
405   }
406   return(resGO);
407 }
408 int cl_xa::inst_JBC(uint code, int operands)
409 {
410   return(resGO);
411 }
412 int cl_xa::inst_JNB(uint code, int operands)
413 {
414   short bitAddr=((code&0x3)<<8) + fetch1();
415   short jmpAddr = (fetch1() * 2);
416   if (!get_bit(bitAddr)) {
417     PC = (PC+jmpAddr)&0xfffffe;
418   }
419   return(resGO);
420   return(resGO);
421 }
422 int cl_xa::inst_JMP(uint code, int operands)
423 {
424   int jmpAddr;
425
426   switch(operands) {
427     case REL16:
428     {
429       jmpAddr = (signed short)fetch2()*2;
430       PC = (PC + jmpAddr) & 0xfffffe;
431     }
432     break;
433     case IREG:
434       PC &= 0xff0000;
435       PC |= (reg2(RI_07) & 0xfffe);  /* word aligned */
436     break;
437     /* fixme 2 more... */
438   }
439   return(resGO);
440 }
441 int cl_xa::inst_JNZ(uint code, int operands)
442 {
443   short saddr = (fetch1() * 2);
444   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
445   if (reg1(8)!=0) {
446     PC = (PC + saddr) & 0xfffffe;
447   }
448   return(resGO);
449 }
450 int cl_xa::inst_JZ(uint code, int operands)
451 {
452   /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
453   short saddr = (fetch1() * 2);
454   if (reg1(8)==0) {
455       PC += saddr;
456   }
457   return(resGO);
458 }
459 int cl_xa::inst_LEA(uint code, int operands)
460 {
461   return(resGO);
462 }
463 int cl_xa::inst_LSR(uint code, int operands)
464 {
465   return(resGO);
466 }
467 int cl_xa::inst_MOV(uint code, int operands)
468 {
469 #undef FUNC1
470 #define FUNC1 mov1
471 #undef FUNC2
472 #define FUNC2 mov2
473 #include "inst_gen.cc"
474   return(resGO);
475 }
476 int cl_xa::inst_MOVC(uint code, int operands)
477 {
478   switch (operands) {
479     case REG_IREGINC:
480     {
481       short srcreg = reg2(RI_07);
482       if (code & 0x0800) {  /* word op */
483         set_reg2( RI_F0,
484                   mov2( reg2(RI_F0),
485                         getcode2(srcreg)
486                       )
487                 );
488       } else {
489         set_reg1( RI_F0,
490                   mov1( reg1(RI_F0),
491                         getcode1(srcreg)
492                       )
493                 );
494       }
495       if (operands == REG_IREGINC) {
496         set_reg2(RI_07,  srcreg+1);
497       }
498     }
499     break;
500     case A_APLUSDPTR:
501     {  /* R4l=ACC, R6=DPTR */
502       unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
503       unsigned short result;
504       unsigned char flags;
505       flags = get_psw();
506
507       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
508       result = getcode1(addr);
509       set_reg1( 4, result);
510       if (result == 0) flags |= BIT_Z;
511       if (result & 0x80) flags |= BIT_N;
512       set_psw(flags);
513     }
514     break;
515     case A_APLUSPC:
516     {  /* R4l=ACC, R6=DPTR */
517       unsigned int addr = (PC + reg1(4));
518       unsigned short result;
519       unsigned char flags;
520       flags = get_psw();
521
522       flags &= ~(BIT_Z | BIT_N); /* clear these bits */
523       result = getcode1(addr);
524       set_reg1( 4, result);
525       if (result == 0) flags |= BIT_Z;
526       if (result & 0x80) flags |= BIT_N;
527       set_psw(flags);
528     }
529     break;
530   }
531   return(resGO);
532 }
533 int cl_xa::inst_MOVS(uint code, int operands)
534 {
535   return(resGO);
536 }
537 int cl_xa::inst_MOVX(uint code, int operands)
538 {
539   return(resGO);
540 }
541 int cl_xa::inst_MUL(uint code, int operands)
542 {
543   return(resGO);
544 }
545 int cl_xa::inst_NEG(uint code, int operands)
546 {
547   return(resGO);
548 }
549 int cl_xa::inst_NOP(uint code, int operands)
550 {
551   return(resGO);
552 }
553 int cl_xa::inst_NORM(uint code, int operands)
554 {
555   return(resGO);
556 }
557 int cl_xa::inst_OR(uint code, int operands)
558 {
559 #undef FUNC1
560 #define FUNC1 or1
561 #undef FUNC2
562 #define FUNC2 or2
563 #include "inst_gen.cc"
564   return(resGO);
565 }
566
567 int cl_xa::inst_ORL(uint code, int operands)
568 {
569   return(resGO);
570 }
571
572 int cl_xa::inst_POP(uint code, int operands)
573 {
574   switch(operands) {
575     case DIRECT:
576     {
577       unsigned short sp;
578       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
579
580       sp = get_sp();
581       if (code & 0x0800) {  /* word op */
582         set_word_direct(direct_addr, get2(sp) );
583       } else {
584         set_byte_direct(direct_addr, get2(sp) & 0xff );
585       }
586       set_sp(sp+2);
587     }
588     break;
589
590     case RLIST:
591       // fixme: implement
592       unsigned char rlist = fetch();
593       rlist = rlist; //shutup compiler
594     break;
595   }
596   return(resGO);
597 }
598
599 int cl_xa::inst_PUSH(uint code, int operands)
600 {
601   switch(operands) {
602     case DIRECT:
603     {
604       unsigned short sp;
605       unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
606
607       sp = get_sp()-2;
608       set_sp(sp);
609       if (code & 0x0800) {  /* word op */
610         store2( sp, get_word_direct(direct_addr));
611       } else {
612         store2( sp, get_byte_direct(direct_addr));
613       }
614     }
615     break;
616
617     case RLIST:
618       // fixme: implement
619       unsigned char rlist = fetch();
620       rlist = rlist; //shutup compiler
621     break;
622   }
623   
624   return(resGO);
625 }
626 int cl_xa::inst_RESET(uint code, int operands)
627 {
628   return(resGO);
629 }
630 int cl_xa::inst_RET(uint code, int operands)
631 {
632   unsigned int retaddr;
633   unsigned short sp;
634   bool pageZero=get_scr()&1;
635
636   sp = get_sp();
637   retaddr = get2(sp);
638   if (!pageZero) {
639     retaddr |= get2(sp+2) << 16;
640     set_sp(sp+4);
641   } else {
642     set_sp(sp+2);
643   }
644   PC = retaddr;
645   return(resGO);
646 }
647 int cl_xa::inst_RETI(uint code, int operands)
648 {
649   unsigned int retaddr;
650   unsigned short sp;
651   bool pageZero=get_scr()&1;
652
653   sp = get_sp();
654   set_psw(get2(sp));
655   retaddr = get2(sp+2);
656   if (!pageZero) {
657     retaddr |= get2(sp+4) << 16;
658     set_sp(sp+6);
659   } else {
660     set_sp(sp+4);
661   }
662   PC = retaddr;
663   return(resGO);
664 }
665 int cl_xa::inst_RL(uint code, int operands)
666 {
667   return(resGO);
668 }
669 int cl_xa::inst_RLC(uint code, int operands)
670 {
671   return(resGO);
672 }
673 int cl_xa::inst_RR(uint code, int operands)
674 {
675   return(resGO);
676 }
677 int cl_xa::inst_RRC(uint code, int operands)
678 {
679   return(resGO);
680 }
681 int cl_xa::inst_SETB(uint code, int operands)
682 {
683   unsigned short bitAddr = (code&0x03 << 8) + fetch();
684   // fixme: implement
685   bitAddr=bitAddr;
686   return(resGO);
687 }
688
689 int cl_xa::inst_SEXT(uint code, int operands)
690 {
691   return(resGO);
692 }
693
694 int cl_xa::inst_SUB(uint code, int operands)
695 {
696 #undef FUNC1
697 #define FUNC1 sub1
698 #undef FUNC2
699 #define FUNC2 sub2
700 #include "inst_gen.cc"
701   return(resGO);
702 }
703
704 int cl_xa::inst_SUBB(uint code, int operands)
705 {
706 #undef FUNC1
707 #define FUNC1 subb1
708 #undef FUNC2
709 #define FUNC2 subb2
710 #include "inst_gen.cc"
711   return(resGO);
712 }
713 int cl_xa::inst_TRAP(uint code, int operands)
714 {
715   return(resGO);
716 }
717 int cl_xa::inst_XCH(uint code, int operands)
718 {
719   return(resGO);
720 }
721 int cl_xa::inst_XOR(uint code, int operands)
722 {
723 #undef FUNC1
724 #define FUNC1 xor1
725 #undef FUNC2
726 #define FUNC2 xor2
727 #include "inst_gen.cc"
728   return(resGO);
729 }
730
731 /* End of xa.src/inst.cc */