X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=sim%2Fucsim%2Fxa.src%2Finst.cc;h=c9f7d088558f0b2c9aa4c8555d20ea1ee8a31a84;hb=6947ba235772f04a3f916a611be619f428d2250b;hp=ec737aa83bd2d38e10cd059eed8574e881502c4f;hpb=7b0c1bf49c52185dcf0fc02421dda5a781ce9409;p=fw%2Fsdcc diff --git a/sim/ucsim/xa.src/inst.cc b/sim/ucsim/xa.src/inst.cc index ec737aa8..c9f7d088 100644 --- a/sim/ucsim/xa.src/inst.cc +++ b/sim/ucsim/xa.src/inst.cc @@ -6,7 +6,7 @@ * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * Other contributors include: * Karl Bongers karl@turbobit.com, - * Johan Knol + * Johan Knol johan.knol@iduna.nl * */ @@ -30,11 +30,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "ddconfig.h" +#include + // local #include "glob.h" #include "xacl.h" #include "regsxa.h" +#define NOTDONE_ASSERT { printf("**********Instr not done at %d!\n", __LINE__); } void cl_xa::store1(t_addr addr, unsigned char val) { @@ -45,7 +48,7 @@ void cl_xa::store1(t_addr addr, unsigned char val) } } -void cl_xa::store2(t_addr addr, unsigned char val) +void cl_xa::store2(t_addr addr, unsigned short val) { if (addr < 0x2000) { set_idata2(addr, val); @@ -96,7 +99,6 @@ bool cl_xa::get_bit(int bit) { } result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8)); return result; - //return mem_direct[offset + (bit/8)] & (1 << (bit%8)); } void cl_xa::set_bit(int bit, int value) { @@ -111,10 +113,8 @@ void cl_xa::set_bit(int bit, int value) { i = get_byte_direct(offset + (bit/8)); if (value) { set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) ); - //mem_direct[offset + (bit/8)] |= (1 << (bit%8)); } else { set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) ); - //mem_direct[offset + (bit/8)] &= ~(1 << (bit%8)); } } @@ -147,6 +147,7 @@ int cl_xa::inst_ADDC(uint code, int operands) int cl_xa::inst_ADDS(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } @@ -160,28 +161,254 @@ int cl_xa::inst_AND(uint code, int operands) return(resGO); } +/* logical AND bit with Carry flag */ int cl_xa::inst_ANL(uint code, int operands) { + unsigned char flags; + unsigned short bitAddr = (code&0x03 << 8) + fetch(); + flags = get_psw(); + + if (flags & BIT_C) { + /* have work to do */ + switch(operands) { + case CY_BIT : + if (!get_bit(bitAddr)) { + set_psw(flags & ~BIT_C); + } + break; + + case CY_NOTBIT : + if (get_bit(bitAddr)) { + set_psw(flags & ~BIT_C); + } + break; + } + } + return(resGO); } +/* arithmetic shift left */ int cl_xa::inst_ASL(uint code, int operands) { + unsigned int dst, cnt; + unsigned char flags; + + /* ASL, dest, count + while (count != 0) + C = dest.80H; dest <<= 1; if sign chg then set V=1 + this is a confusing one... + */ + + flags = get_psw(); + flags &= ~BIT_ALL; /* clear these bits */ + + switch(operands) { + //{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 + case REG_REG : + cnt = reg1(RI_0F) & 0x1f; + switch (code & 0xc00) { + case 0: // byte + dst = reg1(RI_F0); + dst <<= cnt; + set_reg1(RI_F0,dst); + if (dst & 0x100) + flags |= BIT_C; + if ((dst & 0xff) == 0) + flags |= BIT_Z; + break; + case 1: // word + dst = reg2(RI_F0); + dst <<= cnt; + set_reg2(RI_F0,dst); + if (dst & 0x10000) + flags |= BIT_C; + if ((dst & 0xffff) == 0) + flags |= BIT_Z; + break; + case 2: // ? + // not really sure about the encoding here.. + NOTDONE_ASSERT; + break; + case 3: // dword + //dst = reg4(RI_F0); + dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16); + if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) { + flags |= BIT_C; + } + dst <<= cnt; + set_reg2(RI_F0,dst & 0xffff); + set_reg2(RI_F0+2, (dst>>16) & 0xffff); + if (dst == 0) + flags |= BIT_Z; + break; + } + break; + + case REG_DATA4 : + case REG_DATA5 : + switch (code & 0xc00) { + case 0: // byte + dst = reg1(RI_F0); + cnt = operands & 0x0f; + dst <<= cnt; + set_reg1(RI_F0,dst); + if (dst & 0x100) + flags |= BIT_C; + if ((dst & 0xff) == 0) + flags |= BIT_Z; + break; + case 1: // word + dst = reg2(RI_F0); + cnt = operands & 0x0f; + dst <<= cnt; + set_reg2(RI_F0,dst); + if (dst & 0x10000) + flags |= BIT_C; + if ((dst & 0xffff) == 0) + flags |= BIT_Z; + break; + case 2: // ? + // not really sure about the encoding here.. + NOTDONE_ASSERT; + break; + case 3: // dword + dst = reg1(RI_F0 & 0xe); + cnt = operands & 0x1f; + if ((cnt != 0) && (dst & (0x80000000 >> (cnt-1)))) { + flags |= BIT_C; + } + dst <<= cnt; + set_reg2(RI_F0,dst & 0xffff); + set_reg2(RI_F0+2, (dst>>16) & 0xffff); + if (dst == 0) + flags |= BIT_Z; + break; + } + break; + } + set_psw(flags); + return(resGO); } +/* arithmetic shift right */ int cl_xa::inst_ASR(uint code, int operands) { + unsigned int dst, cnt; + unsigned char flags; + + /* ASR, dest, count + while (count != 0) + C = dest.0; dest >>= 1; + this is a confusing one... + */ + + flags = get_psw(); + flags &= ~BIT_ALL; /* clear these bits */ + + switch(operands) { + case REG_REG : + cnt = reg1(RI_0F) & 0x1f; + switch (code & 0xc00) { + case 0: // byte + dst = reg1(RI_F0); + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + if (dst & 0x01) + flags |= BIT_C; + dst >>= cnt; + set_reg1(RI_F0,dst); + if ((dst & 0xff) == 0) + flags |= BIT_Z; + break; + case 1: // word + dst = reg2(RI_F0); + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + dst >>= cnt; + set_reg2(RI_F0,dst); + if ((dst & 0xffff) == 0) + flags |= BIT_Z; + break; + case 2: // ? + // not really sure about the encoding here.. + NOTDONE_ASSERT; + break; + case 3: // dword + dst = reg2(RI_F0) | (reg2(RI_F0 + 2) << 16); + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + dst >>= cnt; + set_reg2(RI_F0,dst & 0xffff); + set_reg2(RI_F0+2, (dst>>16) & 0xffff); + if (dst == 0) + flags |= BIT_Z; + break; + } + break; + + case REG_DATA4 : + case REG_DATA5 : + switch (code & 0xc00) { + case 0: // byte + dst = reg1(RI_F0); + cnt = operands & 0x0f; + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + dst >>= cnt; + set_reg1(RI_F0,dst); + if ((dst & 0xff) == 0) + flags |= BIT_Z; + break; + case 1: // word + dst = reg2(RI_F0); + cnt = operands & 0x0f; + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + dst >>= cnt; + set_reg2(RI_F0,dst); + if ((dst & 0xffff) == 0) + flags |= BIT_Z; + break; + case 2: // ? + // not really sure about the encoding here.. + NOTDONE_ASSERT; + break; + case 3: // dword + dst = reg1(RI_F0 & 0xe); + cnt = operands & 0x1f; + if ((cnt != 0) && (dst & (0x00000001 << (cnt-1)))) + flags |= BIT_C; + dst >>= cnt; + set_reg2(RI_F0,dst & 0xffff); + set_reg2(RI_F0+2, (dst>>16) & 0xffff); + if (dst == 0) + flags |= BIT_Z; + break; + } + break; + } + set_psw(flags); + return(resGO); } int cl_xa::inst_BCC(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (!(get_psw() & BIT_C)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BCS(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (get_psw() & BIT_C) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } @@ -189,57 +416,114 @@ int cl_xa::inst_BEQ(uint code, int operands) { short jmpAddr = fetch1()*2; if (get_psw() & BIT_Z) { - PC=(PC+jmpAddr)&0xfffffffe; + PC=(PC+jmpAddr)&0xfffffe; } return(resGO); } int cl_xa::inst_BG(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool Z=flags&BIT_Z, C=flags&BIT_C; + if (!(Z|C)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BGE(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool N=flags&BIT_N, V=flags&BIT_V; + if (!(N^V)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BGT(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V; + if (!((Z|N)^V)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BKPT(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_BL(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool Z=flags&BIT_Z, C=flags&BIT_C; + if (Z|C) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BLE(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool Z=flags&BIT_Z, N=flags&BIT_N, V=flags&BIT_V; + if ((Z|N)^V) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BLT(uint code, int operands) { + short jmpAddr = fetch1()*2; + short flags=get_psw(); + bool N=flags&BIT_N, V=flags&BIT_V; + if (N^V) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BMI(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (get_psw()&BIT_N) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BNE(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (!(get_psw()&BIT_Z)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BNV(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (!(get_psw()&BIT_V)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BOV(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (get_psw()&BIT_V) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } int cl_xa::inst_BPL(uint code, int operands) { + short jmpAddr = fetch1()*2; + if (!(get_psw()&BIT_N)) { + PC=(PC+jmpAddr)&0xfffffe; + } return(resGO); } @@ -352,8 +636,7 @@ int cl_xa::inst_CJNE(uint code, int operands) int cl_xa::inst_CLR(uint code, int operands) { unsigned short bitAddr = (code&0x03 << 8) + fetch(); - // fixme: implement - bitAddr=bitAddr; + set_bit (bitAddr, 0); return(resGO); } @@ -368,14 +651,17 @@ int cl_xa::inst_CMP(uint code, int operands) } int cl_xa::inst_CPL(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_DA(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_DIV(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } @@ -425,11 +711,13 @@ int cl_xa::inst_DJNZ(uint code, int operands) int cl_xa::inst_FCALL(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_FJMP(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } @@ -444,6 +732,12 @@ int cl_xa::inst_JB(uint code, int operands) } int cl_xa::inst_JBC(uint code, int operands) { + short bitAddr=((code&0x3)<<8) + fetch1(); + short jmpAddr = (fetch1() * 2); + if (get_bit(bitAddr)) { + PC = (PC+jmpAddr)&0xfffffe; + } + set_bit(bitAddr,0); return(resGO); } int cl_xa::inst_JNB(uint code, int operands) @@ -454,7 +748,6 @@ int cl_xa::inst_JNB(uint code, int operands) PC = (PC+jmpAddr)&0xfffffe; } return(resGO); - return(resGO); } int cl_xa::inst_JMP(uint code, int operands) { @@ -495,10 +788,25 @@ int cl_xa::inst_JZ(uint code, int operands) } int cl_xa::inst_LEA(uint code, int operands) { + switch (operands) { + case REG_REGOFF8: + { + char offset=fetch1(); + set_reg2(RI_70, reg2(RI_07)+offset); + break; + } + case REG_REGOFF16: + { + short offset=fetch2(); + set_reg2(RI_70, reg2(RI_07)+offset); + break; + } + } return(resGO); } int cl_xa::inst_LSR(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_MOV(uint code, int operands) @@ -569,18 +877,22 @@ int cl_xa::inst_MOVC(uint code, int operands) } int cl_xa::inst_MOVS(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_MOVX(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_MUL(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_NEG(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_NOP(uint code, int operands) @@ -589,6 +901,7 @@ int cl_xa::inst_NOP(uint code, int operands) } int cl_xa::inst_NORM(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_OR(uint code, int operands) @@ -603,18 +916,18 @@ int cl_xa::inst_OR(uint code, int operands) int cl_xa::inst_ORL(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_POP(uint code, int operands) { + unsigned short sp=get_sp(); switch(operands) { case DIRECT: { - unsigned short sp; unsigned short direct_addr = ((operands & 0x7) << 8) | fetch(); - sp = get_sp(); if (code & 0x0800) { /* word op */ set_word_direct(direct_addr, get2(sp) ); } else { @@ -625,9 +938,50 @@ int cl_xa::inst_POP(uint code, int operands) break; case RLIST: - // fixme: implement + { unsigned char rlist = fetch(); - rlist = rlist; //shutup compiler + if (code & 0x0800) { // word op + if (code & 0x4000) { // R8-R15 + if (rlist&0x01) { set_reg2(8, get2(sp)); sp+=2; } + if (rlist&0x02) { set_reg2(9, get2(sp)); sp+=2; } + if (rlist&0x04) { set_reg2(10, get2(sp)); sp+=2; } + if (rlist&0x08) { set_reg2(11, get2(sp)); sp+=2; } + if (rlist&0x10) { set_reg2(12, get2(sp)); sp+=2; } + if (rlist&0x20) { set_reg2(13, get2(sp)); sp+=2; } + if (rlist&0x40) { set_reg2(14, get2(sp)); sp+=2; } + if (rlist&0x80) { set_reg2(15, get2(sp)); sp+=2; } + } else { // R0-R7 + if (rlist&0x01) { set_reg2(0, get2(sp)); sp+=2; } + if (rlist&0x02) { set_reg2(1, get2(sp)); sp+=2; } + if (rlist&0x04) { set_reg2(2, get2(sp)); sp+=2; } + if (rlist&0x08) { set_reg2(3, get2(sp)); sp+=2; } + if (rlist&0x10) { set_reg2(4, get2(sp)); sp+=2; } + if (rlist&0x20) { set_reg2(5, get2(sp)); sp+=2; } + if (rlist&0x40) { set_reg2(6, get2(sp)); sp+=2; } + if (rlist&0x80) { set_reg2(7, get2(sp)); sp+=2; } + } + } else { // byte op + if (code & 0x4000) { // R4l-R7h + if (rlist&0x01) { set_reg1(8, get1(sp)); sp+=2; } + if (rlist&0x02) { set_reg1(9, get1(sp)); sp+=2; } + if (rlist&0x04) { set_reg1(10, get1(sp)); sp+=2; } + if (rlist&0x08) { set_reg1(11, get1(sp)); sp+=2; } + if (rlist&0x10) { set_reg1(12, get1(sp)); sp+=2; } + if (rlist&0x20) { set_reg1(13, get1(sp)); sp+=2; } + if (rlist&0x40) { set_reg1(14, get1(sp)); sp+=2; } + if (rlist&0x80) { set_reg1(15, get1(sp)); sp+=2; } + } else { // R0l-R3h + if (rlist&0x01) { set_reg1(0, get1(sp)); sp+=2; } + if (rlist&0x02) { set_reg1(1, get1(sp)); sp+=2; } + if (rlist&0x04) { set_reg1(2, get1(sp)); sp+=2; } + if (rlist&0x08) { set_reg1(3, get1(sp)); sp+=2; } + if (rlist&0x10) { set_reg1(4, get1(sp)); sp+=2; } + if (rlist&0x20) { set_reg1(5, get1(sp)); sp+=2; } + if (rlist&0x40) { set_reg1(6, get1(sp)); sp+=2; } + if (rlist&0x80) { set_reg1(7, get1(sp)); sp+=2; } + } + } + } break; } return(resGO); @@ -652,16 +1006,59 @@ int cl_xa::inst_PUSH(uint code, int operands) break; case RLIST: - // fixme: implement + { + unsigned short sp=get_sp(); unsigned char rlist = fetch(); - rlist = rlist; //shutup compiler + if (code & 0x0800) { // word op + if (code & 0x4000) { // R15-R8 + if (rlist&0x80) { sp-=2; store2(sp, reg2(15)); } + if (rlist&0x40) { sp-=2; store2(sp, reg2(14)); } + if (rlist&0x20) { sp-=2; store2(sp, reg2(13)); } + if (rlist&0x10) { sp-=2; store2(sp, reg2(12)); } + if (rlist&0x08) { sp-=2; store2(sp, reg2(11)); } + if (rlist&0x04) { sp-=2; store2(sp, reg2(10)); } + if (rlist&0x02) { sp-=2; store2(sp, reg2(9)); } + if (rlist&0x01) { sp-=2; store2(sp, reg2(8)); } + } else { // R7-R0 + if (rlist&0x80) { sp-=2; store2(sp, reg2(7)); } + if (rlist&0x40) { sp-=2; store2(sp, reg2(6)); } + if (rlist&0x20) { sp-=2; store2(sp, reg2(5)); } + if (rlist&0x10) { sp-=2; store2(sp, reg2(4)); } + if (rlist&0x08) { sp-=2; store2(sp, reg2(3)); } + if (rlist&0x04) { sp-=2; store2(sp, reg2(2)); } + if (rlist&0x02) { sp-=2; store2(sp, reg2(1)); } + if (rlist&0x01) { sp-=2; store2(sp, reg2(0)); } + } + } else { // byte op + if (code & 0x4000) { // R7h-R4l + if (rlist&0x80) { sp-=2; store2(sp, reg1(15)); } + if (rlist&0x40) { sp-=2; store2(sp, reg1(14)); } + if (rlist&0x20) { sp-=2; store2(sp, reg1(13)); } + if (rlist&0x10) { sp-=2; store2(sp, reg1(12)); } + if (rlist&0x08) { sp-=2; store2(sp, reg1(11)); } + if (rlist&0x04) { sp-=2; store2(sp, reg1(10)); } + if (rlist&0x02) { sp-=2; store2(sp, reg1(9)); } + if (rlist&0x01) { sp-=2; store2(sp, reg1(8)); } + } else { // R3h-R0l + if (rlist&0x80) { sp-=2; store2(sp, reg1(7)); } + if (rlist&0x40) { sp-=2; store2(sp, reg1(6)); } + if (rlist&0x20) { sp-=2; store2(sp, reg1(5)); } + if (rlist&0x10) { sp-=2; store2(sp, reg1(4)); } + if (rlist&0x08) { sp-=2; store2(sp, reg1(3)); } + if (rlist&0x04) { sp-=2; store2(sp, reg1(2)); } + if (rlist&0x02) { sp-=2; store2(sp, reg1(1)); } + if (rlist&0x01) { sp-=2; store2(sp, reg1(0)); } + } + } + set_sp(sp); + } break; } - return(resGO); } int cl_xa::inst_RESET(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_RET(uint code, int operands) @@ -701,30 +1098,39 @@ int cl_xa::inst_RETI(uint code, int operands) } int cl_xa::inst_RL(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_RLC(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_RR(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_RRC(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_SETB(uint code, int operands) { unsigned short bitAddr = (code&0x03 << 8) + fetch(); - // fixme: implement - bitAddr=bitAddr; + set_bit (bitAddr, 1); return(resGO); } int cl_xa::inst_SEXT(uint code, int operands) { + bool neg=get_psw()&BIT_N; + if (code & 0x0800) { // word op + set_reg2(RI_F0, neg ? 0xffff : 0); + } else { + set_reg1(RI_F0, neg ? 0xff : 0); + } return(resGO); } @@ -747,12 +1153,29 @@ int cl_xa::inst_SUBB(uint code, int operands) #include "inst_gen.cc" return(resGO); } + int cl_xa::inst_TRAP(uint code, int operands) { + // steal a few opcodes for simulator only putchar() and exit() + // functions. Used in SDCC regression testing. + switch (code & 0x0f) { + case 0xe: + // implement a simulator putchar() routine + //printf("PUTCHAR-----> %xH\n", reg1(0)); + putchar(reg1(0)); + fflush(stdout); + break; + + case 0xf: + ::exit(0); + break; + } return(resGO); } + int cl_xa::inst_XCH(uint code, int operands) { + NOTDONE_ASSERT; return(resGO); } int cl_xa::inst_XOR(uint code, int operands)