* 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
*
*/
#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)
+{
+ if (addr < 0x2000) {
+ set_idata1(addr, val);
+ } else {
+ set_xdata1(addr, val);
+ }
+}
+
+void cl_xa::store2(t_addr addr, unsigned short val)
+{
+ if (addr < 0x2000) {
+ set_idata2(addr, val);
+ } else {
+ set_xdata2(addr, val);
+ }
+}
+
+unsigned char cl_xa::get1(t_addr addr)
+{
+ if (addr < 0x2000) {
+ return get_idata1(addr);
+ } else {
+ return get_xdata1(addr);
+ }
+}
+
+unsigned short cl_xa::get2(t_addr addr)
+{
+ if (addr < 0x2000) {
+ return get_idata2(addr);
+ } else {
+ return get_xdata2(addr);
+ }
+}
+
int cl_xa::get_reg(int word_flag, unsigned int index)
{
- //if (index < 3) { /* banked */
- // if (word_flag)
- // return get_word_direct(0x400+index);
- // else
- // return mem_direct[0x400+index];
- //} else { /* non-banked */
- if (word_flag)
- return get_word_direct(index);
- else
- return mem_direct[index];
- //}
+ int result;
+
+ if (word_flag) {
+ result = get_word_direct(index);
+ }
+ else {
+ result = get_byte_direct(index);
+ }
+ return result;
}
bool cl_xa::get_bit(int bit) {
short offset=0;
+ unsigned char result;
+
if (bit>=0x200) {
// in sfr space
bit-=0x200;
offset=0x400;
}
- return mem_direct[offset + (bit/8)] & (1 << (bit%8));
+ result = get_byte_direct(offset + (bit/8)) & (1 << (bit%8));
+ return result;
}
void cl_xa::set_bit(int bit, int value) {
+ int i;
short offset=0;
if (bit>=0x200) {
// in sfr space
bit-=0x200;
offset=0x400;
}
+
+ i = get_byte_direct(offset + (bit/8));
if (value) {
- mem_direct[offset + (bit/8)] |= (1 << (bit%8));
+ set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) );
} else {
- mem_direct[offset + (bit/8)] &= ~(1 << (bit%8));
+ set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) );
}
}
int cl_xa::inst_ADDS(uint code, int operands)
{
+ NOTDONE_ASSERT;
return(resGO);
}
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 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 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);
}
int cl_xa::inst_ASR(uint code, int operands)
{
+ NOTDONE_ASSERT;
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);
}
{
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);
}
int cl_xa::inst_BR(uint code, int operands)
{
short jmpAddr = fetch1()*2;
- PC=(PC+jmpAddr)&0xfffffffe;
+ PC=(PC+jmpAddr)&0xfffffe;
return(resGO);
}
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);
}
}
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);
}
unsigned short tmp = mov2(0, reg2(RI_F0)-1);
set_reg2(RI_F0, tmp);
if (tmp != 0)
- PC = (PC + addr) & 0xfffffffe;
+ PC = (PC + addr) & 0xfffffe;
} else {
unsigned char tmp = mov1(0, reg1(RI_F0)-1);
set_reg1(RI_F0, tmp);
if (tmp != 0)
- PC = (PC + addr) & 0xfffffffe;
+ PC = (PC + addr) & 0xfffffe;
}
}
break;
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);
}
}
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)
PC = (PC+jmpAddr)&0xfffffe;
}
return(resGO);
- return(resGO);
}
int cl_xa::inst_JMP(uint code, int operands)
{
case REL16:
{
jmpAddr = (signed short)fetch2()*2;
- PC = (PC + jmpAddr) & 0xfffffffe;
+ PC = (PC + jmpAddr) & 0xfffffe;
}
break;
case IREG:
}
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)
}
}
break;
- // fixme, 2 more
+ case A_APLUSDPTR:
+ { /* R4l=ACC, R6=DPTR */
+ unsigned int addr = (PC & 0xff0000) | (reg1(4) + reg2(6));
+ unsigned short result;
+ unsigned char flags;
+ flags = get_psw();
+
+ flags &= ~(BIT_Z | BIT_N); /* clear these bits */
+ result = getcode1(addr);
+ set_reg1( 4, result);
+ if (result == 0) flags |= BIT_Z;
+ if (result & 0x80) flags |= BIT_N;
+ set_psw(flags);
+ }
+ break;
+ case A_APLUSPC:
+ { /* R4l=ACC, R6=DPTR */
+ unsigned int addr = (PC + reg1(4));
+ unsigned short result;
+ unsigned char flags;
+ flags = get_psw();
+
+ flags &= ~(BIT_Z | BIT_N); /* clear these bits */
+ result = getcode1(addr);
+ set_reg1( 4, result);
+ if (result == 0) flags |= BIT_Z;
+ if (result & 0x80) flags |= BIT_N;
+ set_psw(flags);
+ }
+ break;
}
return(resGO);
}
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)
{
+ NOTDONE_ASSERT;
return(resGO);
}
int cl_xa::inst_NORM(uint code, int operands)
{
+ NOTDONE_ASSERT;
return(resGO);
}
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 {
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);
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)
}
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);
}
#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)