2 * Simulator of microcontrollers (inst.cc)
4 * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt.
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
13 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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
38 #define NOTDONE_ASSERT { printf("**********Instr not done at %d!\n", __LINE__); }
40 void cl_xa::store1(t_addr addr, unsigned char val)
43 set_idata1(addr, val);
45 set_xdata1(addr, val);
49 void cl_xa::store2(t_addr addr, unsigned short val)
52 set_idata2(addr, val);
54 set_xdata2(addr, val);
58 unsigned char cl_xa::get1(t_addr addr)
61 return get_idata1(addr);
63 return get_xdata1(addr);
67 unsigned short cl_xa::get2(t_addr addr)
70 return get_idata2(addr);
72 return get_xdata2(addr);
76 int cl_xa::get_reg(int word_flag, unsigned int index)
81 result = get_word_direct(index);
84 result = get_byte_direct(index);
89 bool cl_xa::get_bit(int bit) {
98 result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8));
102 void cl_xa::set_bit(int bit, int value) {
111 i = get_byte_direct(offset + (bit/8));
113 set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) );
115 set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) );
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)
124 int cl_xa::inst_ADD(uint code, int operands)
130 #include "inst_gen.cc"
135 int cl_xa::inst_ADDC(uint code, int operands)
141 #include "inst_gen.cc"
146 int cl_xa::inst_ADDS(uint code, int operands)
152 int cl_xa::inst_AND(uint code, int operands)
158 #include "inst_gen.cc"
162 /* logical AND bit with Carry flag */
163 int cl_xa::inst_ANL(uint code, int operands)
166 unsigned short bitAddr = (code&0x03 << 8) + fetch();
170 /* have work to do */
173 if (!get_bit(bitAddr)) {
174 set_psw(flags & ~BIT_C);
179 if (get_bit(bitAddr)) {
180 set_psw(flags & ~BIT_C);
189 /* arithmetic shift left */
190 int cl_xa::inst_ASL(uint code, int operands)
192 unsigned int dst, cnt;
197 C = dest.80H; dest <<= 1; if sign chg then set V=1
198 this is a confusing one...
202 flags &= ~BIT_ALL; /* clear these bits */
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
207 cnt = reg1(RI_0F) & 0x1f;
208 switch (code & 0xc00) {
215 if ((dst & 0xff) == 0)
224 if ((dst & 0xffff) == 0)
229 dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16);
230 if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
234 set_reg2(RI_F0,dst & 0xffff);
235 set_reg2(RI_F0+2, (dst>>16) & 0xffff);
244 switch (code & 0xc00) {
247 cnt = operands & 0x0f;
252 if ((dst & 0xff) == 0)
257 cnt = operands & 0x0f;
262 if ((dst & 0xffff) == 0)
266 dst = reg1(RI_F0 & 0xe);
267 cnt = operands & 0x1f;
268 if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) {
272 set_reg2(RI_F0,dst & 0xffff);
273 set_reg2(RI_F0+2, (dst>>16) & 0xffff);
285 int cl_xa::inst_ASR(uint code, int operands)
291 int cl_xa::inst_BCC(uint code, int operands)
293 short jmpAddr = fetch1()*2;
294 if (!(get_psw() & BIT_C)) {
295 PC=(PC+jmpAddr)&0xfffffe;
300 int cl_xa::inst_BCS(uint code, int operands)
302 short jmpAddr = fetch1()*2;
303 if (get_psw() & BIT_C) {
304 PC=(PC+jmpAddr)&0xfffffe;
309 int cl_xa::inst_BEQ(uint code, int operands)
311 short jmpAddr = fetch1()*2;
312 if (get_psw() & BIT_Z) {
313 PC=(PC+jmpAddr)&0xfffffe;
318 int cl_xa::inst_BG(uint code, int operands)
320 short jmpAddr = fetch1()*2;
321 short flags=get_psw();
322 bool Z=flags&BIT_Z, C=flags&BIT_C;
324 PC=(PC+jmpAddr)&0xfffffe;
328 int cl_xa::inst_BGE(uint code, int operands)
330 short jmpAddr = fetch1()*2;
331 short flags=get_psw();
332 bool N=flags&BIT_N, V=flags&BIT_V;
334 PC=(PC+jmpAddr)&0xfffffe;
338 int cl_xa::inst_BGT(uint code, int operands)
340 short jmpAddr = fetch1()*2;
341 short flags=get_psw();
342 bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
344 PC=(PC+jmpAddr)&0xfffffe;
348 int cl_xa::inst_BKPT(uint code, int operands)
353 int cl_xa::inst_BL(uint code, int operands)
355 short jmpAddr = fetch1()*2;
356 short flags=get_psw();
357 bool Z=flags&BIT_Z, C=flags&BIT_C;
359 PC=(PC+jmpAddr)&0xfffffe;
363 int cl_xa::inst_BLE(uint code, int operands)
365 short jmpAddr = fetch1()*2;
366 short flags=get_psw();
367 bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V;
369 PC=(PC+jmpAddr)&0xfffffe;
373 int cl_xa::inst_BLT(uint code, int operands)
375 short jmpAddr = fetch1()*2;
376 short flags=get_psw();
377 bool N=flags&BIT_N, V=flags&BIT_V;
379 PC=(PC+jmpAddr)&0xfffffe;
383 int cl_xa::inst_BMI(uint code, int operands)
385 short jmpAddr = fetch1()*2;
386 if (get_psw()&BIT_N) {
387 PC=(PC+jmpAddr)&0xfffffe;
391 int cl_xa::inst_BNE(uint code, int operands)
393 short jmpAddr = fetch1()*2;
394 if (!(get_psw()&BIT_Z)) {
395 PC=(PC+jmpAddr)&0xfffffe;
399 int cl_xa::inst_BNV(uint code, int operands)
401 short jmpAddr = fetch1()*2;
402 if (!(get_psw()&BIT_V)) {
403 PC=(PC+jmpAddr)&0xfffffe;
407 int cl_xa::inst_BOV(uint code, int operands)
409 short jmpAddr = fetch1()*2;
410 if (get_psw()&BIT_V) {
411 PC=(PC+jmpAddr)&0xfffffe;
415 int cl_xa::inst_BPL(uint code, int operands)
417 short jmpAddr = fetch1()*2;
418 if (!(get_psw()&BIT_N)) {
419 PC=(PC+jmpAddr)&0xfffffe;
424 int cl_xa::inst_BR(uint code, int operands)
426 short jmpAddr = fetch1()*2;
427 PC=(PC+jmpAddr)&0xfffffe;
431 int cl_xa::inst_CALL(uint code, int operands)
435 bool pageZero=get_scr()&1;
440 jmpaddr = (signed short)fetch2();
441 sp = get_sp() - (pageZero ? 2 : 4);
443 store2(sp, PC&0xffff);
445 store2(sp+2, (PC>>16)&0xff);
448 PC = (PC + jmpaddr) & 0xfffffe;
453 sp = get_sp() - (pageZero ? 2 : 4);
455 store2(sp, PC&0xffff);
457 store2(sp+2, (PC>>16)&0xff);
459 jmpaddr = reg2(RI_07);
461 PC = (PC + jmpaddr) & 0xfffffe;
468 int cl_xa::inst_CJNE(uint code, int operands)
471 case REG_DIRECT_REL8:
474 if (code & 0x800) { // word op
476 int src = get_word_direct( ((code & 0x7)<<4) | fetch1());
477 int addr = (fetch1() * 2);
478 int dst = reg2(RI_F0);
481 flags &= ~BIT_ALL; /* clear these bits */
483 if (result == 0) flags |= BIT_Z;
484 if (result > 0xffff) flags |= BIT_C;
485 if (dst < src) flags |= BIT_N;
491 int src = get_byte_direct( ((code & 0x7)<<4) | fetch1());
492 int addr = (fetch1() * 2);
493 int dst = reg1(RI_F0);
496 flags &= ~BIT_ALL; /* clear these bits */
498 if (result == 0) flags |= BIT_Z;
499 if (result > 0xff) flags |= BIT_C;
500 if (dst < src) flags |= BIT_N;
510 int daddr = ((code & 0x7) << 8) | fetch();
511 int addr = fetch() * 2;
513 if (code & 0x800) { // word op
514 unsigned short tmp = get_word_direct(daddr)-1;
515 set_word_direct(daddr, tmp);
519 unsigned char tmp = get_word_direct(daddr)-1;
520 set_byte_direct(daddr, tmp);
530 int cl_xa::inst_CLR(uint code, int operands)
532 unsigned short bitAddr = (code&0x03 << 8) + fetch();
533 set_bit (bitAddr, 0);
537 int cl_xa::inst_CMP(uint code, int operands)
543 #include "inst_gen.cc"
546 int cl_xa::inst_CPL(uint code, int operands)
551 int cl_xa::inst_DA(uint code, int operands)
556 int cl_xa::inst_DIV(uint code, int operands)
562 int cl_xa::inst_DJNZ(uint code, int operands)
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);
573 PC = (PC + addr) & 0xfffffe;
575 unsigned char tmp = mov1(0, reg1(RI_F0)-1);
576 set_reg1(RI_F0, tmp);
578 PC = (PC + addr) & 0xfffffe;
585 int daddr = ((code & 0x7) << 8) | fetch();
586 int addr = fetch() * 2;
588 if (code & 0x800) { // word op
589 unsigned short tmp = get_word_direct(daddr)-1;
590 set_word_direct(daddr, tmp);
594 unsigned char tmp = get_word_direct(daddr)-1;
595 set_byte_direct(daddr, tmp);
606 int cl_xa::inst_FCALL(uint code, int operands)
612 int cl_xa::inst_FJMP(uint code, int operands)
618 int cl_xa::inst_JB(uint code, int operands)
620 short bitAddr=((code&0x3)<<8) + fetch1();
621 short jmpAddr = (fetch1() * 2);
622 if (get_bit(bitAddr)) {
623 PC = (PC+jmpAddr)&0xfffffe;
627 int cl_xa::inst_JBC(uint code, int operands)
629 short bitAddr=((code&0x3)<<8) + fetch1();
630 short jmpAddr = (fetch1() * 2);
631 if (get_bit(bitAddr)) {
632 PC = (PC+jmpAddr)&0xfffffe;
637 int cl_xa::inst_JNB(uint code, int operands)
639 short bitAddr=((code&0x3)<<8) + fetch1();
640 short jmpAddr = (fetch1() * 2);
641 if (!get_bit(bitAddr)) {
642 PC = (PC+jmpAddr)&0xfffffe;
646 int cl_xa::inst_JMP(uint code, int operands)
653 jmpAddr = (signed short)fetch2()*2;
654 PC = (PC + jmpAddr) & 0xfffffe;
659 PC |= (reg2(RI_07) & 0xfffe); /* word aligned */
661 /* fixme 2 more... */
665 int cl_xa::inst_JNZ(uint code, int operands)
667 short saddr = (fetch1() * 2);
668 /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
670 PC = (PC + saddr) & 0xfffffe;
674 int cl_xa::inst_JZ(uint code, int operands)
676 /* reg1(8) = R4L, is ACC for MCS51 compatiblility */
677 short saddr = (fetch1() * 2);
683 int cl_xa::inst_LEA(uint code, int operands)
688 char offset=fetch1();
689 set_reg2(RI_70, reg2(RI_07)+offset);
694 short offset=fetch2();
695 set_reg2(RI_70, reg2(RI_07)+offset);
701 int cl_xa::inst_LSR(uint code, int operands)
706 int cl_xa::inst_MOV(uint code, int operands)
712 #include "inst_gen.cc"
715 int cl_xa::inst_MOVC(uint code, int operands)
720 short srcreg = reg2(RI_07);
721 if (code & 0x0800) { /* word op */
734 if (operands == REG_IREGINC) {
735 set_reg2(RI_07, srcreg+1);
740 { /* R4l=ACC, R6=DPTR */
741 unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
742 unsigned short result;
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;
755 { /* R4l=ACC, R6=DPTR */
756 unsigned int addr = (PC + reg1(4));
757 unsigned short result;
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;
772 int cl_xa::inst_MOVS(uint code, int operands)
777 int cl_xa::inst_MOVX(uint code, int operands)
782 int cl_xa::inst_MUL(uint code, int operands)
787 int cl_xa::inst_NEG(uint code, int operands)
792 int cl_xa::inst_NOP(uint code, int operands)
796 int cl_xa::inst_NORM(uint code, int operands)
801 int cl_xa::inst_OR(uint code, int operands)
807 #include "inst_gen.cc"
811 int cl_xa::inst_ORL(uint code, int operands)
817 int cl_xa::inst_POP(uint code, int operands)
819 unsigned short sp=get_sp();
823 unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
825 if (code & 0x0800) { /* word op */
826 set_word_direct(direct_addr, get2(sp) );
828 set_byte_direct(direct_addr, get2(sp) & 0xff );
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; }
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; }
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; }
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; }
884 int cl_xa::inst_PUSH(uint code, int operands)
890 unsigned short direct_addr = ((operands & 0x7) << 8) | fetch();
894 if (code & 0x0800) { /* word op */
895 store2( sp, get_word_direct(direct_addr));
897 store2( sp, get_byte_direct(direct_addr));
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)); }
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)); }
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)); }
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)); }
953 int cl_xa::inst_RESET(uint code, int operands)
958 int cl_xa::inst_RET(uint code, int operands)
960 unsigned int retaddr;
962 bool pageZero=get_scr()&1;
967 retaddr |= get2(sp+2) << 16;
975 int cl_xa::inst_RETI(uint code, int operands)
977 unsigned int retaddr;
979 bool pageZero=get_scr()&1;
983 retaddr = get2(sp+2);
985 retaddr |= get2(sp+4) << 16;
993 int cl_xa::inst_RL(uint code, int operands)
998 int cl_xa::inst_RLC(uint code, int operands)
1003 int cl_xa::inst_RR(uint code, int operands)
1008 int cl_xa::inst_RRC(uint code, int operands)
1013 int cl_xa::inst_SETB(uint code, int operands)
1015 unsigned short bitAddr = (code&0x03 << 8) + fetch();
1016 set_bit (bitAddr, 1);
1020 int cl_xa::inst_SEXT(uint code, int operands)
1022 bool neg=get_psw()&BIT_N;
1023 if (code & 0x0800) { // word op
1024 set_reg2(RI_F0, neg ? 0xffff : 0);
1026 set_reg1(RI_F0, neg ? 0xff : 0);
1031 int cl_xa::inst_SUB(uint code, int operands)
1037 #include "inst_gen.cc"
1041 int cl_xa::inst_SUBB(uint code, int operands)
1047 #include "inst_gen.cc"
1051 int cl_xa::inst_TRAP(uint code, int operands)
1053 // steal a few opcodes for simulator only putchar() and exit()
1054 // functions. Used in SDCC regression testing.
1055 switch (code & 0x0f) {
1057 // implement a simulator putchar() routine
1058 //printf("PUTCHAR-----> %xH\n", reg1(0));
1070 int cl_xa::inst_XCH(uint code, int operands)
1075 int cl_xa::inst_XOR(uint code, int operands)
1081 #include "inst_gen.cc"
1085 /* End of xa.src/inst.cc */