/*
Copyright (C) 2006 T. Scott Dattalo
This file is part of gpsim.
gpsim 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, or (at your option)
any later version.
gpsim 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 gpsim; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "../pic-instructions.h"
#include "dspic-processors.h"
#include "dspic-instructions.h"
using namespace dspic;
using namespace dspic_instructions;
namespace dspic {
extern Trace *gTrace; // Points to gpsim's global trace object.
extern Cycle_Counter *gCycles; // Points to gpsim's global cycle counter.
}
struct dsPicInstructionConstructor {
unsigned int inst_mask;
unsigned int opcode;
instruction * (*inst_constructor) (Processor *cpu, unsigned int inst,unsigned int addr);
};
struct dsPicInstructionConstructor op_dsPic[] = {
{ 0xff8000, 0xb00000, ADDR::construct }, // Lit
{ 0xf80000, 0x400000, ADDR::construct }, // Wb + Lit -> Wd
{ 0xff7fff, 0xcb0000, ADD::construct }, // add accumulators
{ 0xff8000, 0xb48000, ADDC::construct }, // f to W
{ 0xff8000, 0xb08000, ADDC::construct }, // Lit
{ 0xf80000, 0x480000, ADDC::construct }, // Wb + Lit -> Wd
{ 0xff8000, 0xb60000, AND::construct }, // f to W
{ 0xff8000, 0xb20000, AND::construct }, // Lit
{ 0xf80000, 0x600060, AND::construct }, // Wb + Lit -> Wd
{ 0xf80000, 0x600000, AND::construct },
{ 0xff8000, 0xd58000, ASR::construct }, // f to W
{ 0xff8000, 0xd18000, ASR::construct }, // Lit
{ 0xff8070, 0xde8000, ASR::construct }, // Wb + Lit -> Wd
{ 0xff0000, 0xa90000, BCLR::construct },
{ 0xff0b80, 0xa10000, BCLR::construct },
{ 0xf00000, 0x300000, BRA::construct }, // branch literal offset
{ 0xfffff0, 0x016000, BRA::construct }, // computed branch
{ 0xfc0000, 0x0c0000, BRA::construct }, // branch on accumulator state
{ 0xff0000, 0xa80000, BSET::construct },
{ 0xff0b80, 0xa00000, BSET::construct },
{ 0xff0780, 0xad0000, BSW::construct },
{ 0xff0000, 0xaa0000, BTG::construct },
{ 0xff0000, 0xaf0000, BTS::construct },
{ 0xff0000, 0xab0000, BTST::construct },
{ 0xff0780, 0xa30000, BTST::construct },
{ 0xff0780, 0xa50000, BTST::construct },
{ 0xff0000, 0xac0000, BTSTS::construct },
{ 0xff0780, 0xa40000, BTSTS::construct },
{ 0xff0001, 0x020000, CALL::construct },
{ 0xfffff0, 0x010000, CALL::construct },
{ 0xff8000, 0xef0000, CLR::construct },
{ 0xff807f, 0xeb0000, CLR::construct },
{ 0xff4000, 0xc30000, CLR::construct },
{ 0xffffff, 0xfe6000, CLRWDT::construct },
{ 0xff8000, 0xee8000, COM::construct },
{ 0xff8000, 0xea8000, COM::construct },
{ 0xffa000, 0xe30000, CP::construct },
{ 0xff83e0, 0xe10060, CP::construct },
{ 0xff8380, 0xe10000, CP::construct },
{ 0xffa000, 0xe20000, CP0::construct },
{ 0xfffb80, 0xe00000, CP0::construct },
{ 0xffa000, 0xe38000, CPB::construct },
{ 0xff83e0, 0xe18060, CPB::construct },
{ 0xff8380, 0xe18000, CPB::construct },
{ 0xfe03f0, 0xe60000, CPS::construct },
{ 0xfffff0, 0xfd4000, DAW::construct },
{ 0xff8000, 0xed0000, DEC::construct },
{ 0xff8000, 0xe90000, DEC::construct },
{ 0xff8000, 0xed8000, DEC::construct }, // DEC2
{ 0xff8000, 0xe98000, DEC::construct }, // DEC2
{ 0xffc000, 0xfc0000, DISI::construct },
{ 0xff8030, 0xd80000, DIV::construct },
{ 0xff8030, 0xd88000, DIV::construct },
{ 0xff87f0, 0xd90000, DIV::construct },
{ 0xffc000, 0x080000, DO::construct },
{ 0xfffff0, 0x088000, DO::construct },
{ 0xfc4c03, 0xf04003, ED::construct },
{ 0xfc4c03, 0xf04002, ED::construct },
{ 0xfff870, 0xfd0000, EXCH::construct },
{ 0xfff800, 0xdf0000, FB::construct }, // FBCL
{ 0xfff800, 0xcf8000, FB::construct }, // FF1L
{ 0xfff800, 0xcf0000, FB::construct }, // FF1R
{ 0xff0000, 0x040000, GOTO::construct },
{ 0xfffff0, 0x014000, GOTO::construct },
{ 0xff8000, 0xec0000, DEC::construct },
{ 0xff8000, 0xe80000, DEC::construct },
{ 0xff8000, 0xec8000, DEC::construct }, // INC2
{ 0xff8000, 0xe88000, DEC::construct }, // DEC2
{ 0xff8000, 0xb70000, IOR::construct }, // f to W
{ 0xff8000, 0xb30000, IOR::construct }, // Lit
{ 0xf80000, 0x700000, IOR::construct }, // Wb + Lit -> Wd
{ 0xff0000, 0xca0000, LAC::construct },
{ 0xffc001, 0xfa0000, LNK::construct },
{ 0xff8000, 0xd50000, LSR::construct }, // Note LSR is similar to ASR
{ 0xff8000, 0xd10000, LSR::construct }, // Lit
{ 0xff8070, 0xde0000, LSR::construct }, // Wb + Lit -> Wd
{ 0xf84000, 0xc00000, MAC::construct },
{ 0xfc4003, 0xf00000, MAC::construct },
{ 0xff8000, 0xbf8000, MOV::construct },
{ 0xffa000, 0xb7a000, MOV::construct },
{ 0xf80000, 0x800000, MOV::construct },
{ 0xf80000, 0x880000, MOV::construct },
{ 0xfff000, 0xb3c000, MOV::construct }, //MOV.B
{ 0xf00000, 0x200000, MOV::construct },
{ 0xf80000, 0x900000, MOV::construct },
{ 0xf80000, 0x980000, MOV::construct },
{ 0xf80000, 0x780000, MOV::construct },
{ 0xfff880, 0xbe0000, MOV::construct }, //MOV.D
{ 0xffc071, 0xbe8000, MOV::construct }, //MOV.D
{ 0xff4000, 0xc70000, MOVSAC::construct },
{ 0xf84003, 0xc00003, MPY::construct }, // degenerate to MAC
{ 0xf84003, 0xc04003, MPY::construct }, // MPY.N and MSC
{ 0xffa000, 0xbc0000, MUL::construct },
{ 0xff8000, 0xb98000, MUL::construct }, //MUL.SS
{ 0xff8060, 0xb90000, MUL::construct }, //MUL.SU
{ 0xff8000, 0xb88000, MUL::construct }, //MUL.US
{ 0xff8060, 0xb80000, MUL::construct }, //MUL.UU
{ 0xff8000, 0xee0000, NEG::construct },
{ 0xff8000, 0xea0000, NEG::construct },
{ 0xff7fff, 0xcb1000, NEG::construct },
{ 0xff0000, 0x000000, NOP::construct },
{ 0xff0000, 0xff0000, NOP::construct },
{ 0xff0001, 0xf90000, POP::construct },
{ 0xf8407f, 0x78004f, POP::construct },
{ 0xfff8ff, 0xbe004f, POP::construct },
{ 0xffffff, 0xfe8000, POP::construct }, // POP.S
{ 0xff0001, 0xf80000, PUSH::construct },
{ 0xf87f80, 0x781f80, PUSH::construct },
{ 0xfffff1, 0xbe9f80, PUSH::construct },
{ 0xffffff, 0xfea000, PUSH::construct }, // PUSH.S
{ 0xfffffe, 0xfe4000, PWRSAV::construct },
{ 0xff0000, 0x070000, RCALL::construct },
{ 0xfffff0, 0x012000, RCALL::construct },
{ 0xffc000, 0x090000, REPEAT::construct },
{ 0xfffff0, 0x098000, REPEAT::construct },
{ 0xffffff, 0xfe0000, RESET::construct },
{ 0xffffff, 0x064000, RET::construct }, // RETFIE
{ 0xff8000, 0x050000, RET::construct }, // RETLW
{ 0xffffff, 0x060000, RET::construct }, // RETURN
{ 0xff8000, 0xd68000, ROT::construct }, // RLC
{ 0xff8000, 0xd28000, ROT::construct }, // RLC
{ 0xff8000, 0xd60000, ROT::construct }, // RLNC
{ 0xff8000, 0xd20000, ROT::construct }, // RLNC
{ 0xff8000, 0xd78000, ROT::construct }, // RRC
{ 0xff8000, 0xd38000, ROT::construct }, // RRC
{ 0xff8000, 0xd70000, ROT::construct }, // RNC
{ 0xff8000, 0xd30000, ROT::construct }, // RNC
{ 0xff0000, 0xcc0000, SAC::construct },
{ 0xff0000, 0xcd0000, SAC::construct }, // SAC.R
{ 0xfff800, 0xfb0000, SE::construct },
{ 0xff8000, 0xef8000, SETM::construct },
{ 0xff807f, 0xeb8000, SETM::construct },
{ 0xff7fc0, 0xc80040, SFTAC::construct },
{ 0xff7ff0, 0xc80000, SFTAC::construct },
{ 0xff8000, 0xd40000, SL::construct },
{ 0xff8000, 0xd00000, SL::construct },
{ 0xff8070, 0xdd0040, SL::construct },
{ 0xff8070, 0xdd0000, SL::construct },
{ 0xff8000, 0xb50000, SUB::construct },
{ 0xff8000, 0xb10000, SUB::construct },
{ 0xf80000, 0x500000, SUB::construct },
{ 0xff7fff, 0xcb3000, SUB::construct },
{ 0xff8000, 0xb58000, SUB::construct }, //SUBB
{ 0xff8000, 0xb18000, SUB::construct },
{ 0xf80000, 0x580000, SUB::construct },
{ 0xff8000, 0xbd8000, SUB::construct }, //SUBBR
{ 0xf80000, 0x180000, SUB::construct },
{ 0xff8000, 0xbd0000, SUB::construct }, //SUBR
{ 0xf80000, 0x100000, SUB::construct },
{ 0xffbff0, 0xfd8000, SWAP::construct },
{ 0xff8000, 0xba8000, TBLRD::construct }, //TBLRDH
{ 0xff8000, 0xba0000, TBLRD::construct }, //TBLRDL
{ 0xff8000, 0xbb8000, TBLWT::construct }, //TBLWTH
{ 0xff8000, 0xbb0000, TBLWT::construct }, //TBLWTL
{ 0xffffff, 0xfa8000, ULNK::construct },
{ 0xff8000, 0xb68000, XOR::construct }, // f to W
{ 0xff8000, 0xb28000, XOR::construct }, // Lit
{ 0xf80000, 0x680000, XOR::construct }, // Wb + Lit -> Wd
{ 0xffc000, 0xfb8000, ZE::construct }
};
const int NUM_OP_DSPIC = sizeof(op_dsPic) / sizeof(op_dsPic[0]);
instruction * dsPicProcessor::disasm (unsigned int address, unsigned int inst)
{
//printf("dspic disasm addr 0x%x, opcode 0x%x\n",address,inst);
instruction *pi;
pi = 0;
for(int i =0; i<NUM_OP_DSPIC; i++)
if((op_dsPic[i].inst_mask & inst) == op_dsPic[i].opcode)
pi = op_dsPic[i].inst_constructor(this, inst,address);
if(pi == 0)
pi = invalid_instruction::construct(this, inst);
return (pi);
}
namespace dspic_instructions
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Addressing Modes
//
// The various addressing modes for the dspic instructions are
// first defined.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------------------------------------
const RegisterValue AddressingMode::m_unknown = RegisterValue(0,0xffff);
AddressingMode::AddressingMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: m_cpu(cpu), m_addr(addr)
{
}
AddressingMode * AddressingMode::construct(dspic::dsPicProcessor *new_cpu,
unsigned int new_mode,
unsigned int addr)
{
switch (new_mode&7) {
case eDirect:
return new RegDirectAddrMode(new_cpu, addr);
case eIndirect:
return new RegIndirectAddrMode(new_cpu, addr);
case eIndirectPostDec:
return new RegIndirectPostDecAddrMode(new_cpu, addr);
case eIndirectPostInc:
return new RegIndirectPostIncAddrMode(new_cpu, addr);
case eIndirectPreDec:
return new RegIndirectPreDecAddrMode(new_cpu, addr);
case eIndirectPreInc:
return new RegIndirectPreIncAddrMode(new_cpu, addr);
//case eIndirectRegOffset:
//case eIndirectRegOffset_:
break;
case eLiteral:
case eLiteral_:
return new LiteralAddressingMode(new_cpu, addr&0x1f);
}
return 0;
}
//--------------------------------------------------
LiteralAddressingMode::LiteralAddressingMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: AddressingMode(cpu, addr),
m_rv(addr,0)
{
}
char *LiteralAddressingMode::name(char *buff,int len)
{
if (buff)
snprintf(buff,len,"#0x%x",m_addr);
return buff;
}
//--------------------------------------------------
RegisterAddressingMode::RegisterAddressingMode(dspic::dsPicProcessor *cpu,
unsigned int addr,
const char *cPformat)
: AddressingMode(cpu, addr&0xf),
m_cPformat(cPformat)
{
}
char *RegisterAddressingMode::name(char *buff,int len)
{
if (buff)
snprintf(buff,len,m_cPformat,m_cpu->registers[m_addr]->name().c_str());
return buff;
}
//--------------------------------------------------
RegDirectAddrMode::RegDirectAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"%s")
{
}
RegisterValue RegDirectAddrMode::get()
{
return m_cpu->registers[m_addr]->getRV();
}
void RegDirectAddrMode::put(RegisterValue &n_rv)
{
m_cpu->registers[m_addr]->putRV(n_rv);
}
//--------------------------------------------------
RegIndirectAddrMode::RegIndirectAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"[%s]")
{
}
RegisterValue RegIndirectAddrMode::get()
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
return rv.init ? m_unknown : m_cpu->registers[rv.data]->getRV();
}
void RegIndirectAddrMode::put(RegisterValue &n_rv)
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
if (rv.init == 0)
m_cpu->registers[rv.data]->putRV(n_rv);
}
//--------------------------------------------------
RegIndirectPostDecAddrMode::RegIndirectPostDecAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"[%s--]")
{
}
RegisterValue RegIndirectPostDecAddrMode::get()
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
RegisterValue retRV = rv.init ? m_unknown : m_cpu->registers[rv.data]->getRV();
rv.data = (rv.data-2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
return retRV;
}
void RegIndirectPostDecAddrMode::put(RegisterValue &n_rv)
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
if (rv.init == 0)
m_cpu->registers[rv.data]->putRV(n_rv);
rv.data = (rv.data-2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
}
//--------------------------------------------------
RegIndirectPostIncAddrMode::RegIndirectPostIncAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"[%s++]")
{
}
RegisterValue RegIndirectPostIncAddrMode::get()
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
RegisterValue retRV = rv.init ? m_unknown : m_cpu->registers[rv.data]->getRV();
rv.data = (rv.data+2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
return retRV;
}
void RegIndirectPostIncAddrMode::put(RegisterValue &n_rv)
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
if (rv.init == 0)
m_cpu->registers[rv.data]->putRV(n_rv);
rv.data = (rv.data+2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
}
//--------------------------------------------------
RegIndirectPreDecAddrMode::RegIndirectPreDecAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"[--%s]")
{
}
RegisterValue RegIndirectPreDecAddrMode::get()
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
rv.data = (rv.data-2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
RegisterValue retRV = rv.init ? m_unknown : m_cpu->registers[rv.data]->getRV();
return retRV;
}
void RegIndirectPreDecAddrMode::put(RegisterValue &n_rv)
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
rv.data = (rv.data-2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
if (rv.init == 0)
m_cpu->registers[rv.data]->putRV(n_rv);
}
//--------------------------------------------------
RegIndirectPreIncAddrMode::RegIndirectPreIncAddrMode(dspic::dsPicProcessor *cpu,
unsigned int addr)
: RegisterAddressingMode(cpu, addr,"[++%s]")
{
}
RegisterValue RegIndirectPreIncAddrMode::get()
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
rv.data = (rv.data+2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
RegisterValue retRV = rv.init ? m_unknown : m_cpu->registers[rv.data]->getRV();
return retRV;
}
void RegIndirectPreIncAddrMode::put(RegisterValue &n_rv)
{
RegisterValue rv = m_cpu->registers[m_addr]->getRV();
rv.data = (rv.data+2) & 0xffff;
m_cpu->registers[m_addr]->putRV(rv);
if (rv.init == 0)
m_cpu->registers[rv.data]->putRV(n_rv);
}
//--------------------------------------------------
MultiWordInstruction::MultiWordInstruction(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr)
: instruction(new_cpu, new_opcode, addr),
word2_opcode(0), PMaddress(addr), PMindex(addr/2), initialized(false)
{
}
//--------------------------------------------------
MultiWordBranch::MultiWordBranch(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr)
: MultiWordInstruction(new_cpu, new_opcode, addr)
{
}
void MultiWordBranch::runtime_initialize()
{
if(cpu_dsPic->program_memory[PMindex+1] != &bad_instruction) {
word2_opcode = cpu_dsPic->program_memory[PMindex+1]->get_opcode();
cpu_dsPic->program_memory[PMindex+1]->
update_line_number(file_id,src_line, lst_line, 0, 0);
// extract the destination address from the two-word opcode
destination_index = ((word2_opcode & 0x7f)<<15) | ((opcode>>1) & 0x7fff);
initialized = true;
}
}
char * MultiWordBranch::name(char *return_str,int len)
{
if(!initialized)
runtime_initialize();
snprintf(return_str,len,"%s\t0x%05x",
gpsimValue::name().c_str(),
destination_index<<1);
return(return_str);
}
//--------------------------------------------------
LiteralBranch::LiteralBranch(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr,
const char *_name)
: instruction(new_cpu, new_opcode, addr), mcP_conditionName("")
{
new_name(_name);
unsigned int signExtendedOffset =
((new_opcode&0xffff)<<1) | ((new_opcode & (1<<15)) ? 0xfffe0000 : 0);
m_destination = (addr + 2 + signExtendedOffset) & 0xfffffe;
}
char *LiteralBranch::name(char *buff,int len)
{
if (buff) {
char sign = (opcode & (1<<15)) ? '-' : '+';
int offset= (((sign=='-') ?
((opcode^0xffff)+1) : opcode) << 1) & 0x1fffe;
snprintf(buff, len, "%s\t%s#0x%06x\t; $%c0x%x",
instruction::name().c_str(),
mcP_conditionName,
m_destination,
sign, offset);
}
return buff;
}
//--------------------------------------------------
ImmediateInstruction::ImmediateInstruction(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr)
: instruction(new_cpu, new_opcode, addr), m_L(new_opcode & 0xfffe)
{
}
char *ImmediateInstruction::name(char *buff,int len)
{
if (buff) {
snprintf(buff, len, "%s\t#0x%04x", instruction::name().c_str(),m_L);
}
return buff;
}
//--------------------------------------------------
RegisterInstruction::RegisterInstruction(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr,
const char *_name)
: instruction(new_cpu, new_opcode, addr),
m_bByteOperation((new_opcode & (1<<14)) != 0),
m_base(0), m_source(0), m_destination(0)
{
new_name(_name);
}
//--------------------------------------------------
//--------------------------------------------------
RegisterToRegisterInstruction::RegisterToRegisterInstruction
(Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr,
const char *_name,
eAddressingModes addrMode
)
: RegisterInstruction(new_cpu, new_opcode, addr, _name),
m_addrMode(addrMode)
{
switch(m_addrMode) {
case eRegisterDirect:
m_base = new RegDirectAddrMode(cpu_dsPic,opcode & 0xf);
m_destination = new RegDirectAddrMode(cpu_dsPic,opcode & 0xf);
m_source = new LiteralAddressingMode(cpu_dsPic,
(opcode>>4) & (opcode & (1<<14) ? 0xff: 0x3ff));
break;
case eRegisterIndirect:
m_base = new RegDirectAddrMode(cpu_dsPic, (opcode>>15) & 0xf);
m_source = AddressingMode::construct(cpu_dsPic,
(opcode >> 4) & 0x7,
opcode & 0x1f);
m_destination = AddressingMode::construct(cpu_dsPic,
(opcode >> 11) & 0x7,
(opcode >> 7) & 0xf);
break;
default:
assert(0);
}
}
char *RegisterToRegisterInstruction::name(char *buff,int len)
{
if (!buff)
return buff;
char cpBase[256];
char cpSource[256];
char cpDestination[256];
switch(m_addrMode) {
case eRegisterDirect:
snprintf(buff, len, "%s%s\t%s, %s",
instruction::name().c_str(),
(m_bByteOperation ? ".b" :""),
m_source->name(cpBase,sizeof(cpBase)),
m_destination->name(cpDestination,sizeof(cpDestination))
);
break;
case eRegisterIndirect:
snprintf(buff, len, "%s%s\t%s,%s,%s",
instruction::name().c_str(),
(m_bByteOperation ? ".b" :""),
m_base->name(cpBase,sizeof(cpBase)),
m_source->name(cpSource,sizeof(cpSource)),
m_destination->name(cpDestination,sizeof(cpDestination))
);
break;
default:
break;
}
return buff;
}
//--------------------------------------------------
ADDR::ADDR (Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr,
eAddressingModes addrMode)
: RegisterToRegisterInstruction(new_cpu, new_opcode, addr,"add",addrMode)
{
}
void ADDR::execute()
{
RegisterValue baseRV(m_base ? m_base->get() : m_destination->get());
RegisterValue srcRV (m_source->get());
RegisterValue resRV (srcRV);
resRV.data += baseRV.data;
resRV.init |= baseRV.init;
m_destination->put(resRV);
unsigned flags =
((resRV.data & 0xffff ) ? 0 : eZ) |
((resRV.data & 0x10000 ) ? eC : 0) |
(((resRV.data ^ baseRV.data ^ srcRV.data)&0x10) ? eDC : 0) |
(((resRV.data & ~baseRV.data & ~srcRV.data |
~resRV.data & baseRV.data & srcRV.data) & 0x8000) ? eOV : 0) |
((resRV.data & 0x8000 ) ? eN : 0);
cpu_dsPic->m_status.putFlags(flags, eC|eZ|eOV|eN|eDC, 0);
cpu_dsPic->pc->increment();
}
//--------------------------------------------------
/*
ADDL::ADDL (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: RegisterDirectLiteralInstruction(new_cpu, new_opcode, addr,"add")
{
}
void ADDL::execute()
{
cpu_dsPic->pc->increment();
}
*/
//--------------------------------------------------
ADD::ADD (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("add");
printf("constructing a ADD\n");
}
void ADD::execute()
{
cpu_dsPic->pc->increment();
}
//--------------------------------------------------
ADDC::ADDC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("addc");
printf("constructing a ADDC\n");
}
void ADDC::execute()
{
}
//--------------------------------------------------
AND::AND (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("and");
printf("constructing a AND\n");
}
void AND::execute()
{
}
//--------------------------------------------------
ASR::ASR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("asr");
printf("constructing a ASR\n");
}
void ASR::execute()
{
}
//--------------------------------------------------
BCLR::BCLR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("bclr");
printf("constructing a BCLR\n");
}
void BCLR::execute()
{
}
//--------------------------------------------------
BRA::BRA (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: LiteralBranch(new_cpu, new_opcode, addr, "bra")
{
new_name("bra");
switch ((opcode>>16) & 0x0f) {
case OV: // Overflow
mcP_conditionName = "OV,";
break;
case C: // Carry and GEU
mcP_conditionName = "C,";
break;
case Z: // Zero
mcP_conditionName = "Z,";
break;
case N: // Negative
mcP_conditionName = "N,";
break;
case LE: // Less than or equal to
mcP_conditionName = "LE,";
break;
case LT: // Less than
mcP_conditionName = "LT,";
break;
case LEU: // Less than or equal unsigned
mcP_conditionName = "LEU,";
break;
case UN: // Unconditionally
mcP_conditionName = "";
break;
case NOV: // No overflow
mcP_conditionName = "NOV,";
break;
case NC: // No Carry and LTU (less than unsigned)
mcP_conditionName = "NC,";
break;
case NZ: // Not zero
mcP_conditionName = "NZ,";
break;
case NN: // Not Negative
mcP_conditionName = "NN,";
break;
case GT: // Greater than
mcP_conditionName = "GT,";
break;
case GE: // Greater than or equal
mcP_conditionName = "GE,";
break;
case GTU: // Greater than unsigned
mcP_conditionName = "GTU,";
break;
case NU: // not used...
default:
break;
}
}
void BRA::execute()
{
if (m_condition)
cpu_dsPic->pc->jump(m_destination>>1);
else
cpu_dsPic->pc->increment();
}
//--------------------------------------------------
BSET::BSET (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("bset");
printf("constructing a BSET\n");
}
void BSET::execute()
{
}
//--------------------------------------------------
BSW::BSW (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("bsw ");
printf("constructing a BSW\n");
}
void BSW::execute()
{
}
//--------------------------------------------------
BTG::BTG (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("btg ");
printf("constructing a BTG\n");
}
void BTG::execute()
{
}
//--------------------------------------------------
BTS::BTS (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("bts");
printf("constructing a BTS\n");
}
void BTS::execute()
{
}
//--------------------------------------------------
BTST::BTST (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("btst");
printf("constructing a BTST\n");
}
void BTST::execute()
{
}
//--------------------------------------------------
BTSTS::BTSTS (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("btsts");
printf("constructing a BTSTS\n");
}
void BTSTS::execute()
{
}
//--------------------------------------------------
CALL::CALL (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("call");
printf("constructing a CALL\n");
}
void CALL::execute()
{
}
//--------------------------------------------------
CLR::CLR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("clr");
printf("constructing a CLR\n");
}
void CLR::execute()
{
}
//--------------------------------------------------
CLRWDT::CLRWDT (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("clrwdt");
printf("constructing a CLRWDT\n");
}
void CLRWDT::execute()
{
}
//--------------------------------------------------
COM::COM (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("com");
printf("constructing a COM\n");
}
void COM::execute()
{
}
//--------------------------------------------------
CP::CP (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("cp");
printf("constructing a CP\n");
}
void CP::execute()
{
}
//--------------------------------------------------
CP0::CP0 (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("cp0");
printf("constructing a CP0\n");
}
void CP0::execute()
{
}
//--------------------------------------------------
CPB::CPB (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("cpb");
printf("constructing a CPB\n");
}
void CPB::execute()
{
}
//--------------------------------------------------
CPS::CPS (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("cps");
printf("constructing a CPS\n");
}
void CPS::execute()
{
}
//--------------------------------------------------
DAW::DAW (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("daw");
printf("constructing a DAW\n");
}
void DAW::execute()
{
}
//--------------------------------------------------
DEC::DEC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("dec");
printf("constructing a DEC\n");
}
void DEC::execute()
{
}
//--------------------------------------------------
DISI::DISI (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("disi");
printf("constructing a DISI\n");
}
void DISI::execute()
{
}
//--------------------------------------------------
DIV::DIV (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("div");
printf("constructing a DIV\n");
}
void DIV::execute()
{
}
//--------------------------------------------------
DO::DO (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("do");
printf("constructing a DO\n");
}
void DO::execute()
{
}
//--------------------------------------------------
ED::ED (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("ed");
printf("constructing a ED\n");
}
void ED::execute()
{
}
//--------------------------------------------------
EXCH::EXCH (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("exch");
printf("constructing a EXCH\n");
}
void EXCH::execute()
{
}
//--------------------------------------------------
FB::FB (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("fb");
printf("constructing a FB\n");
}
void FB::execute()
{
}
//--------------------------------------------------
GOTO::GOTO (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: MultiWordBranch(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("goto");
printf("constructing a GOTO\n");
}
void GOTO::execute()
{
if(!initialized)
runtime_initialize();
cpu_dsPic->pc->jump(destination_index);
}
//--------------------------------------------------
INC::INC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("inc");
printf("constructing a INC\n");
}
void INC::execute()
{
}
//--------------------------------------------------
IOR::IOR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("ior");
printf("constructing a IOR\n");
}
void IOR::execute()
{
}
//--------------------------------------------------
LAC::LAC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("lac");
printf("constructing a LAC\n");
}
void LAC::execute()
{
}
//--------------------------------------------------
LNK::LNK (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: ImmediateInstruction(new_cpu, new_opcode, addr)
{
new_name("lnk");
}
void LNK::execute()
{
unsigned int tos = cpu_dsPic->W[15].get_value();
unsigned int tos_index = tos>>1;
cpu_dsPic->registers[tos_index]->put(cpu_dsPic->W[14].get());
cpu_dsPic->W[14].put(tos+2);
cpu_dsPic->W[15].put(tos+2+m_L);
cpu_dsPic->pc->increment();
}
//--------------------------------------------------
LSR::LSR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("lsr");
printf("constructing a LSR\n");
}
void LSR::execute()
{
}
//--------------------------------------------------
MAC::MAC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("mac");
printf("constructing a MAC\n");
}
void MAC::execute()
{
}
//--------------------------------------------------
MOV::MOV (Processor *new_cpu,
unsigned int new_opcode,
unsigned int addr,
eAddressingModes addrMode)
: RegisterToRegisterInstruction(new_cpu, new_opcode, addr,"mov",addrMode)
{
printf("MOV instruction opcode:0x%x mode=%d\n",opcode,m_addrMode);
}
void MOV::execute()
{
RegisterValue baseRV(m_base ? m_base->get() : m_destination->get());
RegisterValue srcRV (m_source->get());
RegisterValue resRV (srcRV);
resRV.data += baseRV.data;
resRV.init |= baseRV.init;
m_destination->put(resRV);
unsigned flags =
((resRV.data & 0xffff ) ? 0 : eZ) |
((resRV.data & 0x10000 ) ? eC : 0) |
(((resRV.data ^ baseRV.data ^ srcRV.data)&0x10) ? eDC : 0) |
(((resRV.data & ~baseRV.data & ~srcRV.data |
~resRV.data & baseRV.data & srcRV.data) & 0x8000) ? eOV : 0) |
((resRV.data & 0x8000 ) ? eN : 0);
cpu_dsPic->m_status.putFlags(flags, eC|eZ|eOV|eN|eDC, 0);
cpu_dsPic->pc->increment();
}
//--------------------------------------------------
MOVSAC::MOVSAC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("movsac");
printf("constructing a MOVSAC\n");
}
void MOVSAC::execute()
{
}
//--------------------------------------------------
MPY::MPY (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("mpy");
printf("constructing a MPY\n");
}
void MPY::execute()
{
}
//--------------------------------------------------
MUL::MUL (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("mul");
printf("constructing a MUL\n");
}
void MUL::execute()
{
}
//--------------------------------------------------
NEG::NEG (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("neg");
printf("constructing a NEG\n");
}
void NEG::execute()
{
}
//--------------------------------------------------
NOP::NOP (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("nop");
// For the 18cxxx family, this 'nop' may in fact be the
// 2nd word in a 2-word opcode. So just to be safe, let's
// initialize the cross references to the source file.
// (Subsequent initialization code will overwrite this,
// but there is a chance that this info will be accessed
// before that occurs).
//printf("constructing a NOP\n");
}
void NOP::execute()
{
//cpu_pic->pc->increment();
}
//--------------------------------------------------
POP::POP (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("pop");
printf("constructing a POP\n");
}
void POP::execute()
{
}
//--------------------------------------------------
PUSH::PUSH (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("push");
printf("constructing a PUSH\n");
}
void PUSH::execute()
{
}
//--------------------------------------------------
PWRSAV::PWRSAV (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("pwrsav");
printf("constructing a PWRSAV\n");
}
void PWRSAV::execute()
{
}
//--------------------------------------------------
RCALL::RCALL (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: LiteralBranch(new_cpu, new_opcode, addr,"rcall")
{
}
void RCALL::execute()
{
cpu_dsPic->m_stack.push();
cpu_dsPic->pc->jump(m_destination>>1);
}
//--------------------------------------------------
REPEAT::REPEAT (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("repeat");
printf("constructing a REPEAT\n");
}
void REPEAT::execute()
{
}
//--------------------------------------------------
RESET::RESET (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("reset");
printf("constructing a RESET\n");
}
void RESET::execute()
{
}
//--------------------------------------------------
RET::RET (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("ret");
printf("constructing a RET\n");
}
void RET::execute()
{
}
//--------------------------------------------------
ROT::ROT (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("rot");
printf("constructing a ROT\n");
}
void ROT::execute()
{
}
//--------------------------------------------------
SAC::SAC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("sac");
printf("constructing a SAC\n");
}
void SAC::execute()
{
}
//--------------------------------------------------
SE::SE (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("se");
printf("constructing a SE\n");
}
void SE::execute()
{
}
//--------------------------------------------------
SETM::SETM (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("setm");
printf("constructing a SETM\n");
}
void SETM::execute()
{
}
//--------------------------------------------------
SFTAC::SFTAC (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("sftac");
printf("constructing a SFTAC\n");
}
void SFTAC::execute()
{
}
//--------------------------------------------------
SL::SL (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("sl");
printf("constructing a SL\n");
}
void SL::execute()
{
}
//--------------------------------------------------
SUB::SUB (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("sub");
printf("constructing a SUB\n");
}
void SUB::execute()
{
}
//--------------------------------------------------
SWAP::SWAP (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("swap");
printf("constructing a SWAP\n");
}
void SWAP::execute()
{
}
//--------------------------------------------------
TBLRD::TBLRD (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("tblrd");
printf("constructing a TBLRD\n");
}
void TBLRD::execute()
{
}
//--------------------------------------------------
TBLWT::TBLWT (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("tblwt");
printf("constructing a TBLWT\n");
}
void TBLWT::execute()
{
}
//--------------------------------------------------
ULNK::ULNK (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("ulnk");
printf("constructing a ULNK\n");
}
void ULNK::execute()
{
}
//--------------------------------------------------
XOR::XOR (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("xor");
printf("constructing a XOR\n");
}
void XOR::execute()
{
}
//--------------------------------------------------
ZE::ZE (Processor *new_cpu, unsigned int new_opcode, unsigned int addr)
: instruction(new_cpu, new_opcode, addr)
{
decode(new_cpu,new_opcode);
new_name("ZE");
printf("constructing a ZE\n");
}
void ZE::execute()
{
}
};
syntax highlighted by Code2HTML, v. 0.9.1