diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/xa.src/inst.cc | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sim/ucsim/xa.src/inst.cc')
| -rw-r--r-- | sim/ucsim/xa.src/inst.cc | 1191 |
1 files changed, 1191 insertions, 0 deletions
diff --git a/sim/ucsim/xa.src/inst.cc b/sim/ucsim/xa.src/inst.cc new file mode 100644 index 0000000..c9f7d08 --- /dev/null +++ b/sim/ucsim/xa.src/inst.cc @@ -0,0 +1,1191 @@ +/* + * Simulator of microcontrollers (inst.cc) + * + * Copyright (C) 1999,2002 Drotos Daniel, Talker Bt. + * + * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu + * Other contributors include: + * Karl Bongers karl@turbobit.com, + * Johan Knol johan.knol@iduna.nl + * + */ + +/* This file is part of microcontroller simulator: ucsim. + +UCSIM is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +UCSIM is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with UCSIM; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ +/*@1@*/ + +#include "ddconfig.h" + +#include <stdlib.h> + +// 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) +{ + 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) +{ + 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; + } + 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) { + set_byte_direct(offset + (bit/8), i | (1 << (bit%8)) ); + } else { + set_byte_direct(offset + (bit/8), i & ~(1 << (bit%8)) ); + } +} + +#define RI_F0 ((code >> 4) & 0xf) +#define RI_70 ((code >> 4) & 0x7) +#define RI_0F (code & 0xf) +#define RI_07 (code & 0x7) + +int cl_xa::inst_ADD(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 add1 +#undef FUNC2 +#define FUNC2 add2 +#include "inst_gen.cc" + + return(resGO); +} + +int cl_xa::inst_ADDC(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 addc1 +#undef FUNC2 +#define FUNC2 addc2 +#include "inst_gen.cc" + + return(resGO); +} + +int cl_xa::inst_ADDS(uint code, int operands) +{ + NOTDONE_ASSERT; + return(resGO); +} + +int cl_xa::inst_AND(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 and1 +#undef FUNC2 +#define FUNC2 and2 +#include "inst_gen.cc" + 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); +} + +int cl_xa::inst_BEQ(uint code, int operands) +{ + short jmpAddr = fetch1()*2; + if (get_psw() & BIT_Z) { + 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)&0xfffffe; + return(resGO); +} + +int cl_xa::inst_CALL(uint code, int operands) +{ + int jmpaddr; + unsigned int sp; + bool pageZero=get_scr()&1; + + switch(operands) { + case REL16: + { + jmpaddr = (signed short)fetch2(); + sp = get_sp() - (pageZero ? 2 : 4); + set_sp(sp); + store2(sp, PC&0xffff); + if (!pageZero) { + store2(sp+2, (PC>>16)&0xff); + } + jmpaddr *= 2; + PC = (PC + jmpaddr) & 0xfffffe; + } + break; + case IREG: + { + sp = get_sp() - (pageZero ? 2 : 4); + set_sp(sp); + store2(sp, PC&0xffff); + if (!pageZero) { + store2(sp+2, (PC>>16)&0xff); + } + jmpaddr = reg2(RI_07); + jmpaddr *= 2; + PC = (PC + jmpaddr) & 0xfffffe; + } + break; + } + return(resGO); +} + +int cl_xa::inst_CJNE(uint code, int operands) +{ + switch(operands) { + case REG_DIRECT_REL8: + { + // update C,N,Z + if (code & 0x800) { // word op + int result; + int src = get_word_direct( ((code & 0x7)<<4) | fetch1()); + int addr = (fetch1() * 2); + int dst = reg2(RI_F0); + unsigned char flags; + flags = get_psw(); + flags &= ~BIT_ALL; /* clear these bits */ + result = dst - src; + if (result == 0) flags |= BIT_Z; + if (result > 0xffff) flags |= BIT_C; + if (dst < src) flags |= BIT_N; + set_psw(flags); + if (flags & BIT_Z) + PC += addr; + } else { + int result; + int src = get_byte_direct( ((code & 0x7)<<4) | fetch1()); + int addr = (fetch1() * 2); + int dst = reg1(RI_F0); + unsigned char flags; + flags = get_psw(); + flags &= ~BIT_ALL; /* clear these bits */ + result = dst - src; + if (result == 0) flags |= BIT_Z; + if (result > 0xff) flags |= BIT_C; + if (dst < src) flags |= BIT_N; + set_psw(flags); + if (flags & BIT_Z) + PC += addr; + } + } + break; + + case DIRECT_REL8: + { + int daddr = ((code & 0x7) << 8) | fetch(); + int addr = fetch() * 2; + + if (code & 0x800) { // word op + unsigned short tmp = get_word_direct(daddr)-1; + set_word_direct(daddr, tmp); + if (tmp != 0) + PC += addr; + } else { + unsigned char tmp = get_word_direct(daddr)-1; + set_byte_direct(daddr, tmp); + if (tmp != 0) + PC += addr; + } + } + break; + } + return(resGO); +} + +int cl_xa::inst_CLR(uint code, int operands) +{ + unsigned short bitAddr = (code&0x03 << 8) + fetch(); + set_bit (bitAddr, 0); + return(resGO); +} + +int cl_xa::inst_CMP(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 cmp1 +#undef FUNC2 +#define FUNC2 cmp2 +#include "inst_gen.cc" + 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); +} + +int cl_xa::inst_DJNZ(uint code, int operands) +{ + // update N Z flags. + switch(operands) { + case REG_REL8: + { + int addr = ( ((char)fetch1()) * 2); + if (code & 0x800) { // word op + unsigned short tmp = mov2(0, reg2(RI_F0)-1); + set_reg2(RI_F0, tmp); + if (tmp != 0) + 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) & 0xfffffe; + } + } + break; + + case DIRECT_REL8: + { + int daddr = ((code & 0x7) << 8) | fetch(); + int addr = fetch() * 2; + + if (code & 0x800) { // word op + unsigned short tmp = get_word_direct(daddr)-1; + set_word_direct(daddr, tmp); + if (tmp != 0) + PC += addr; + } else { + unsigned char tmp = get_word_direct(daddr)-1; + set_byte_direct(daddr, tmp); + if (tmp != 0) + PC += addr; + } + } + break; + } + + return(resGO); +} + +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_JB(uint code, int operands) +{ + short bitAddr=((code&0x3)<<8) + fetch1(); + short jmpAddr = (fetch1() * 2); + if (get_bit(bitAddr)) { + PC = (PC+jmpAddr)&0xfffffe; + } + 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) +{ + short bitAddr=((code&0x3)<<8) + fetch1(); + short jmpAddr = (fetch1() * 2); + if (!get_bit(bitAddr)) { + PC = (PC+jmpAddr)&0xfffffe; + } + return(resGO); +} +int cl_xa::inst_JMP(uint code, int operands) +{ + int jmpAddr; + + switch(operands) { + case REL16: + { + jmpAddr = (signed short)fetch2()*2; + PC = (PC + jmpAddr) & 0xfffffe; + } + break; + case IREG: + PC &= 0xff0000; + PC |= (reg2(RI_07) & 0xfffe); /* word aligned */ + break; + /* fixme 2 more... */ + } + return(resGO); +} +int cl_xa::inst_JNZ(uint code, int operands) +{ + short saddr = (fetch1() * 2); + /* reg1(8) = R4L, is ACC for MCS51 compatiblility */ + if (reg1(8)!=0) { + PC = (PC + saddr) & 0xfffffe; + } + return(resGO); +} +int cl_xa::inst_JZ(uint code, int operands) +{ + /* reg1(8) = R4L, is ACC for MCS51 compatiblility */ + short saddr = (fetch1() * 2); + if (reg1(8)==0) { + PC += saddr; + } + return(resGO); +} +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) +{ +#undef FUNC1 +#define FUNC1 mov1 +#undef FUNC2 +#define FUNC2 mov2 +#include "inst_gen.cc" + return(resGO); +} +int cl_xa::inst_MOVC(uint code, int operands) +{ + switch (operands) { + case REG_IREGINC: + { + short srcreg = reg2(RI_07); + if (code & 0x0800) { /* word op */ + set_reg2( RI_F0, + mov2( reg2(RI_F0), + getcode2(srcreg) + ) + ); + } else { + set_reg1( RI_F0, + mov1( reg1(RI_F0), + getcode1(srcreg) + ) + ); + } + if (operands == REG_IREGINC) { + set_reg2(RI_07, srcreg+1); + } + } + break; + 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) +{ + return(resGO); +} +int cl_xa::inst_NORM(uint code, int operands) +{ + NOTDONE_ASSERT; + return(resGO); +} +int cl_xa::inst_OR(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 or1 +#undef FUNC2 +#define FUNC2 or2 +#include "inst_gen.cc" + return(resGO); +} + +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 direct_addr = ((operands & 0x7) << 8) | fetch(); + + if (code & 0x0800) { /* word op */ + set_word_direct(direct_addr, get2(sp) ); + } else { + set_byte_direct(direct_addr, get2(sp) & 0xff ); + } + set_sp(sp+2); + } + break; + + case RLIST: + { + unsigned char rlist = fetch(); + 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); +} + +int cl_xa::inst_PUSH(uint code, int operands) +{ + switch(operands) { + case DIRECT: + { + unsigned short sp; + unsigned short direct_addr = ((operands & 0x7) << 8) | fetch(); + + sp = get_sp()-2; + set_sp(sp); + if (code & 0x0800) { /* word op */ + store2( sp, get_word_direct(direct_addr)); + } else { + store2( sp, get_byte_direct(direct_addr)); + } + } + break; + + case RLIST: + { + unsigned short sp=get_sp(); + unsigned char rlist = fetch(); + 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) +{ + unsigned int retaddr; + unsigned short sp; + bool pageZero=get_scr()&1; + + sp = get_sp(); + retaddr = get2(sp); + if (!pageZero) { + retaddr |= get2(sp+2) << 16; + set_sp(sp+4); + } else { + set_sp(sp+2); + } + PC = retaddr; + return(resGO); +} +int cl_xa::inst_RETI(uint code, int operands) +{ + unsigned int retaddr; + unsigned short sp; + bool pageZero=get_scr()&1; + + sp = get_sp(); + set_psw(get2(sp)); + retaddr = get2(sp+2); + if (!pageZero) { + retaddr |= get2(sp+4) << 16; + set_sp(sp+6); + } else { + set_sp(sp+4); + } + PC = retaddr; + return(resGO); +} +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(); + 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); +} + +int cl_xa::inst_SUB(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 sub1 +#undef FUNC2 +#define FUNC2 sub2 +#include "inst_gen.cc" + return(resGO); +} + +int cl_xa::inst_SUBB(uint code, int operands) +{ +#undef FUNC1 +#define FUNC1 subb1 +#undef FUNC2 +#define FUNC2 subb2 +#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) +{ +#undef FUNC1 +#define FUNC1 xor1 +#undef FUNC2 +#define FUNC2 xor2 +#include "inst_gen.cc" + return(resGO); +} + +/* End of xa.src/inst.cc */ |
