/*
Copyright (C) 1998 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 gpasm; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include<stdio.h>
#include <iostream>
#include <iomanip>
#include <string>
#include "../config.h"
#include "pic-processor.h"
#include "14bit-registers.h"
//#include "symbol.h"
#include "pic-instructions.h"
#include "12bit-instructions.h"
#include "16bit-instructions.h"
#include "16bit-processors.h"
#include "16bit-registers.h"
//--------------------------------------------------
Branching::Branching(Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode,0),
destination_index(0),
absolute_destination_index(0)
{
}
void Branching::decode(Processor *new_cpu, unsigned int new_opcode)
{
opcode = new_opcode;
cpu = new_cpu;
switch(cpu16->isa()) {
case _P18Cxx2_:
case _P18C2x2_:
case _P18C242_:
case _P18C252_:
case _P18C442_:
case _P18C452_:
case _P18F242_:
case _P18F252_:
case _P18F442_:
case _P18F248_:
case _P18F452_:
case _P18F1220_:
case _P18F1320_:
destination_index = (new_opcode & 0xff)+1;
absolute_destination_index = (cpu16->getCurrentDisasmIndex() + destination_index) & 0xfffff;
if(new_opcode & 0x80)
{
absolute_destination_index -= 0x100;
destination_index = 0x100 - destination_index;
}
break;
case _P17C7xx_:
case _P17C75x_:
case _P17C756_:
case _P17C756A_:
case _P17C762_:
case _P17C766_:
cout << "Which instructions go here?\n";
break;
default:
cout << "ERROR: (Branching) the processor is not defined\n";
break;
}
}
char *Branching::name(char *return_str, int len)
{
snprintf(return_str, len,"%s\t$%c0x%x\t;(0x%x)",
gpsimValue::name().c_str(),
(opcode & 0x80) ? '-' : '+',
(destination_index & 0x7f)<<1,
absolute_destination_index<<1);
return(return_str);
}
//--------------------------------------------------
multi_word_instruction::multi_word_instruction(Processor *new_cpu,
unsigned int new_opcode)
: instruction(new_cpu, new_opcode,0),
word2_opcode(0),
PMaddress(0),
PMindex(0),
initialized(false)
{
}
multi_word_branch::multi_word_branch(Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode),
destination_index(0)
{
}
void multi_word_branch::runtime_initialize(void)
{
if(cpu16->program_memory[PMindex+1] != &bad_instruction)
{
word2_opcode = cpu16->program_memory[PMindex+1]->get_opcode();
if((word2_opcode & 0xf000) != 0xf000)
{
cout << "16bit-instructions.cc multiword instruction error\n";
return;
}
cpu16->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 & 0xfff)<<8) | (opcode & 0xff);
initialized = true;
}
}
char * multi_word_branch::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);
}
//---------------------------------------------------------
ADDULNK::ADDULNK(Processor *new_cpu, unsigned int new_opcode, const char *pName)
: instruction(new_cpu, new_opcode,0)
{
m_lit = opcode & 0x3f;
new_name(pName);
}
char *ADDULNK::name(char *return_str,int len)
{
snprintf(return_str,len,"%s\t0x%x",
gpsimValue::name().c_str(),
m_lit);
return(return_str);
}
void ADDULNK::execute(void)
{
if (opcode & 0x100)
cpu16->ind2.put_fsr(cpu16->ind2.get_fsr_value() - m_lit); // SUBULNK
else
cpu16->ind2.put_fsr(cpu16->ind2.get_fsr_value() + m_lit); // ADDULNK
cpu16->pc->new_address(cpu16->stack->pop());
}
//---------------------------------------------------------
ADDFSR::ADDFSR(Processor *new_cpu, unsigned int new_opcode, const char *pName)
: instruction(new_cpu, new_opcode,0)
{
m_fsr = (opcode>>6)&3;
m_lit = opcode & 0x3f;
switch(m_fsr) {
case 0:
ia = &cpu16->ind0;
break;
case 1:
ia = &cpu16->ind1;
break;
case 2:
ia = &cpu16->ind2;
break;
case 3:
ia = &cpu16->ind2;
}
new_name(pName);
}
char *ADDFSR::name(char *return_str,int len)
{
snprintf(return_str,len,"%s\t%d,0x%x",
gpsimValue::name().c_str(),
m_fsr,
m_lit);
return(return_str);
}
void ADDFSR::execute()
{
if (opcode & 0x100)
ia->put_fsr(ia->get_fsr_value() - m_lit); //SUBFSR
else
ia->put_fsr(ia->get_fsr_value() + m_lit); //ADDFSR
cpu16->pc->increment();
}
//--------------------------------------------------
CALLW::CALLW(Processor *new_cpu, unsigned int new_opcode)
:instruction (new_cpu, new_opcode, 0)
{
new_name("callw");
}
char *CALLW::name(char *return_str,int len)
{
snprintf(return_str,len,"%s",
gpsimValue::name().c_str());
return(return_str);
}
void CALLW::execute()
{
cpu16->stack->push(cpu16->pc->get_next());
cpu16->pcl->put(cpu16->W->get());
cpu16->pc->increment();
}
//--------------------------------------------------
PUSHL::PUSHL(Processor *new_cpu, unsigned int new_opcode)
:instruction (new_cpu, new_opcode, 0),
m_lit(new_opcode & 0xff)
{
new_name("pushl");
}
char *PUSHL::name(char *return_str,int len)
{
snprintf(return_str,len,"%s\t0x%x",
gpsimValue::name().c_str(),m_lit);
return(return_str);
}
void PUSHL::execute()
{
cpu16->ind2.put(m_lit);
cpu16->ind2.put_fsr(cpu16->ind2.get_fsr_value() -1);
cpu16->pc->increment();
}
//--------------------------------------------------
MOVSF::MOVSF (Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode)
{
opcode = new_opcode;
cpu = new_cpu;
PMaddress = cpu16->getCurrentDisasmAddress();
PMindex = cpu16->getCurrentDisasmIndex();
initialized = false;
destination = 0;
source = opcode & 0x7f;
if (opcode & 0x80)
new_name("movss");
else
new_name("movsf");
}
void MOVSF::runtime_initialize(void)
{
if(cpu_pic->program_memory[PMindex+1])
{
word2_opcode = cpu_pic->program_memory[PMindex+1]->get_opcode();
if((word2_opcode & 0xf000) != 0xf000)
{
cout << "16bit-instructions.cc MOVSF error\n";
return;
}
cpu_pic->program_memory[PMindex+1]->update_line_number( file_id, src_line, lst_line, 0, 0);
destination = word2_opcode & ((opcode & 0x80) ? 0x7f : 0xfff);
initialized = true;
}
}
char *MOVSF::name(char *return_str,int len)
{
if(!initialized)
runtime_initialize();
if (opcode & 0x80)
snprintf(return_str,len,"%s\t[0x%x],[0x%x]",
gpsimValue::name().c_str(),
source, destination);
else
snprintf(return_str,len,"%s\t[0x%x],%s",
gpsimValue::name().c_str(),
source,
cpu_pic->registers[destination]->name().c_str());
return(return_str);
}
void MOVSF::execute()
{
if(!initialized)
runtime_initialize();
unsigned int source_addr = (cpu16->ind2.get_fsr_value() + source)&0xfff;
unsigned int r = cpu_pic->registers[source_addr]->get();
cpu16->pc->skip();
unsigned int destination_addr =
(opcode & 0x80) ?
(cpu16->ind2.get_fsr_value() + destination)&0xfff
:
destination;
cpu_pic->registers[destination_addr]->put(r);
cpu16->pc->increment();
}
//--------------------------------------------------
void ADDLW16::execute(void)
{
unsigned int old_value,new_value;
new_value = (old_value = cpu16->W->value.get()) + L;
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N(new_value, old_value, L);
cpu16->pc->increment();
}
//--------------------------------------------------
void ADDWF16::execute(void)
{
unsigned int new_value,src_value,w_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (src_value = source->get()) + (w_value = cpu16->W->value.get());
// Store the result
if(destination)
{
source->put(new_value & 0xff); // Result goes to source
cpu16->status->put_Z_C_DC_OV_N(new_value, src_value, w_value);
}
else
{
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N(new_value, w_value, src_value);
}
cpu16->pc->increment();
}
//--------------------------------------------------
ADDWFC::ADDWFC (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("addwfc");
}
void ADDWFC::execute(void)
{
unsigned int new_value,src_value,w_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (src_value = source->get()) +
(w_value = cpu16->W->value.get()) +
((cpu16->status->value.get() & STATUS_C) ? 1 : 0);
// Store the result
if(destination)
source->put(new_value & 0xff); // Result goes to source
else
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N(new_value, src_value, w_value);
cpu16->pc->increment();
}
//--------------------------------------------------
void ANDLW16::execute(void)
{
unsigned int new_value;
new_value = cpu16->W->value.get() & L;
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
void ANDWF16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = source->get() & cpu16->W->value.get();
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
BC::BC (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bc");
}
void BC::execute(void)
{
if(cpu16->status->value.get() & STATUS_C)
cpu16->pc->jump(absolute_destination_index);
else
cpu16->pc->increment();
}
//--------------------------------------------------
BN::BN (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bn");
}
void BN::execute(void)
{
if(cpu16->status->value.get() & STATUS_N)
cpu16->pc->jump(absolute_destination_index);
else
cpu16->pc->increment();
}
//--------------------------------------------------
BNC::BNC (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bnc");
}
void BNC::execute(void)
{
if(cpu16->status->value.get() & STATUS_C)
cpu16->pc->increment();
else
cpu16->pc->jump(absolute_destination_index);
}
//--------------------------------------------------
BNN::BNN (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bnn");
}
void BNN::execute(void)
{
if(cpu16->status->value.get() & STATUS_N)
cpu16->pc->increment();
else
cpu16->pc->jump(absolute_destination_index);
}
//--------------------------------------------------
BNOV::BNOV (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bnov");
}
void BNOV::execute(void)
{
if(cpu16->status->value.get() & STATUS_OV)
cpu16->pc->increment();
else
cpu16->pc->jump(absolute_destination_index);
}
//--------------------------------------------------
BNZ::BNZ (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bnz");
}
void BNZ::execute(void)
{
if(cpu16->status->value.get() & STATUS_Z)
cpu16->pc->increment();
else
cpu16->pc->jump(absolute_destination_index);
}
//--------------------------------------------------
BOV::BOV (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bov");
}
void BOV::execute(void)
{
if(cpu16->status->value.get() & STATUS_OV)
cpu16->pc->jump(absolute_destination_index);
else
cpu16->pc->increment();
}
//--------------------------------------------------
BRA::BRA (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
destination_index = (new_opcode & 0x7ff)+1;
absolute_destination_index = (cpu16->getCurrentDisasmIndex() + destination_index) & 0xfffff;
if(new_opcode & 0x400)
{
absolute_destination_index -= 0x800;
destination_index = 0x800 - destination_index;
}
new_name("bra");
}
void BRA::execute(void)
{
cpu16->pc->jump(absolute_destination_index);
}
char * BRA::name(char *return_str,int len)
{
sprintf(return_str,"%s\t$%c0x%x\t;(0x%05x)",
gpsimValue::name().c_str(),
(opcode & 0x400) ? '-' : '+',
(destination_index & 0x7ff)<<1,
absolute_destination_index<<1);
return(return_str);
}
//--------------------------------------------------
BTG::BTG (Processor *new_cpu, unsigned int new_opcode)
: Bit_op(new_cpu, new_opcode,0)
{
decode(new_cpu, new_opcode);
new_name("btg");
}
void BTG::execute(void)
{
if(!access)
reg = cpu_pic->registers[register_address];
else
reg = cpu_pic->register_bank[register_address];
reg->put(reg->get() ^ mask);
cpu16->pc->increment();
}
//--------------------------------------------------
BZ::BZ (Processor *new_cpu, unsigned int new_opcode)
: Branching(new_cpu, new_opcode)
{
decode(new_cpu, new_opcode);
new_name("bz");
}
void BZ::execute(void)
{
if(cpu16->status->value.get() & STATUS_Z)
cpu16->pc->jump(absolute_destination_index);
else
cpu16->pc->increment();
}
//--------------------------------------------------
CALL16::CALL16 (Processor *new_cpu, unsigned int new_opcode)
: multi_word_branch(new_cpu, new_opcode)
{
fast = (new_opcode & 0x100) ? true : false;
cpu = new_cpu;
PMaddress = cpu16->getCurrentDisasmAddress();
PMindex = cpu16->getCurrentDisasmIndex();
initialized = false;
new_name("call");
}
void CALL16::execute(void)
{
if(!initialized)
runtime_initialize();
cpu16->stack->push(cpu16->pc->get_next());
if(fast)
cpu16->fast_stack.push();
cpu16->pc->jump(destination_index);
}
char *CALL16::name(char *return_str,int len)
{
if(!initialized)
runtime_initialize();
snprintf(return_str,len,"call\t0x%05x%s",
destination_index<<1,
((fast) ? ",f" : " "));
return(return_str);
}
//--------------------------------------------------
void COMF16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = source->get() ^ 0xff;
// Store the result
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
CPFSEQ::CPFSEQ (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("cpfseq");
}
void CPFSEQ::execute(void)
{
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
if(source->get() == cpu16->W->value.get())
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
CPFSGT::CPFSGT (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("cpfsgt");
}
void CPFSGT::execute(void)
{
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
if(source->get() > cpu16->W->value.get())
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
CPFSLT::CPFSLT (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("cpfslt");
}
void CPFSLT::execute(void)
{
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
if(source->get() < cpu16->W->value.get())
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
DAW::DAW (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("daw");
}
void DAW::execute(void)
{
unsigned int new_value;
new_value = cpu16->W->value.get();
if(((new_value & 0x0f) > 0x9) || (cpu16->status->value.get() & STATUS_DC))
new_value += 0x6;
if(((new_value & 0xf0) > 0x90) || (cpu16->status->value.get() & STATUS_C))
new_value += 0x60;
cpu16->W->put(new_value & 0xff);
cpu16->status->put_C(new_value>0xff);
cpu16->pc->increment();
}
//--------------------------------------------------
void DECF16::execute(void)
{
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
unsigned int src_value = source->get();
unsigned int new_value = src_value - 1;
if(destination)
source->put(new_value & 0xff); // Result goes to source
else
cpu16->W->put(new_value & 0xff);
// cpu16->status->put_N_Z(new_value);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value,src_value,1);
cpu16->pc->increment();
}
//--------------------------------------------------
void DECFSZ16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (source->get() - 1)&0xff;
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
if(0==new_value)
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
DCFSNZ::DCFSNZ (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("dcfsnz");
}
void DCFSNZ::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (source->get() - 1)&0xff;
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
if(0!=new_value)
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
GOTO16::GOTO16 (Processor *new_cpu, unsigned int new_opcode)
: multi_word_branch(new_cpu, new_opcode)
{
PMaddress = cpu16->getCurrentDisasmAddress();
PMindex = cpu16->getCurrentDisasmIndex();
initialized = false;
new_name("goto");
}
void GOTO16::execute(void)
{
if(!initialized)
runtime_initialize();
cpu16->pc->jump(destination_index);
}
//--------------------------------------------------
void INCF16::execute(void)
{
unsigned int new_value, src_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
src_value = source->get();
new_value = (src_value + 1);
if(destination)
{
source->put(new_value & 0xff); // Result goes to source
cpu16->status->put_Z_C_DC_OV_N(new_value, src_value, 1);
}
else
{
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N(new_value, 1, src_value);
}
cpu16->pc->increment();
}
//--------------------------------------------------
void INCFSZ16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (source->get() + 1)&0xff;
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
if(0==new_value)
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
INFSNZ::INFSNZ (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("infsnz");
}
void INFSNZ::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (source->get() + 1)&0xff;
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
if(0!=new_value)
cpu16->pc->skip(); // Skip next instruction
cpu16->pc->increment();
}
//--------------------------------------------------
void IORLW16::execute(void)
{
unsigned int new_value;
new_value = cpu16->W->value.get() | L;
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
void IORWF16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = source->get() | cpu16->W->value.get();
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
LCALL16::LCALL16 (Processor *new_cpu, unsigned int new_opcode)
: multi_word_branch(new_cpu, new_opcode)
{
// opcode = new_opcode;
// fast = new_opcode & 0x100;
// cpu = new_cpu;
// address = cpu16->current_disasm_address;
// initialized = 0;
new_name("lcall");
}
void LCALL16::execute(void)
{
// if(!initialized)
// runtime_initialize();
// cpu16->stack->push(cpu16->pc->get_next());
// if(fast)
// cpu16->fast_stack.push();
// cpu16->pc->jump(destination);
}
char *LCALL16::name(char *return_str,int len)
{
// if(!initialized)
// runtime_initialize();
snprintf(return_str,len,"lcall\t0x%05x%s",
destination_index<<1,
((fast) ? ",f" : " "));
return(return_str);
}
//--------------------------------------------------
LFSR::LFSR (Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode)
{
PMaddress = cpu16->getCurrentDisasmAddress();
PMindex = cpu16->getCurrentDisasmIndex();
initialized = false;
fsr = (opcode & 0x30)>>4;
switch(fsr)
{
case 0:
ia = &cpu16->ind0;
break;
case 1:
ia = &cpu16->ind1;
break;
case 2:
ia = &cpu16->ind2;
break;
case 3:
cout << "LFSR decode error, fsr is 3 and should only be 0,1, or 2\n";
ia = &cpu16->ind0;
}
new_name("lfsr");
}
void LFSR::runtime_initialize(void)
{
if(cpu_pic->program_memory[PMindex+1])
{
word2_opcode = cpu_pic->program_memory[PMindex+1]->get_opcode();
if((word2_opcode & 0xff00) != 0xf000)
{
cout << "16bit-instructions.cc LFSR error\n";
return;
}
cpu_pic->program_memory[PMindex+1]->update_line_number( file_id, src_line, lst_line, 0, 0);
k = ( (opcode & 0xf)<<8) | (word2_opcode & 0xff);
initialized = true;
}
}
char *LFSR::name(char *return_str,int len)
{
if(!initialized)
runtime_initialize();
snprintf(return_str,len,"%s\t%d,0x%x",
gpsimValue::name().c_str(),
fsr,
k);
return(return_str);
}
void LFSR::execute(void)
{
if(!initialized)
runtime_initialize();
ia->put_fsr(k);
cpu16->pc->skip();
cpu16->pc->increment();
}
//--------------------------------------------------
void MOVF16::execute(void)
{
unsigned int source_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
source_value = source->get();
// Store the result
if(destination)
source->put(source_value);
else
cpu16->W->put(source_value);
cpu16->status->put_N_Z(source_value);
cpu16->pc->increment();
}
//--------------------------------------------------
MOVFF::MOVFF (Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode)
{
PMaddress = cpu16->getCurrentDisasmAddress();
PMindex = cpu16->getCurrentDisasmIndex();
initialized = false;
destination = 0;
source = opcode & 0xfff;
new_name("movff");
}
void MOVFF::runtime_initialize(void)
{
if(cpu_pic->program_memory[PMindex+1])
{
word2_opcode = cpu_pic->program_memory[PMindex+1]->get_opcode();
if((word2_opcode & 0xf000) != 0xf000)
{
cout << "16bit-instructions.cc MOVFF error\n";
return;
}
cpu_pic->program_memory[PMindex+1]->update_line_number( file_id, src_line, lst_line, 0, 0);
destination = word2_opcode & 0xfff;
initialized = true;
}
}
char *MOVFF::name(char *return_str,int len)
{
if(!initialized)
runtime_initialize();
snprintf(return_str,len,"%s\t%s,%s",
gpsimValue::name().c_str(),
cpu_pic->registers[source]->name().c_str(),
cpu_pic->registers[destination]->name().c_str());
return(return_str);
}
void MOVFF::execute(void)
{
if(!initialized)
runtime_initialize();
unsigned int r = cpu_pic->registers[source]->get();
cpu16->pc->skip();
cpu_pic->registers[destination]->put(r);
cpu16->pc->increment();
}
//--------------------------------------------------
MOVFP::MOVFP (Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode)
{
// opcode = new_opcode;
// cpu = new_cpu;
// address = cpu16->current_disasm_address;
// initialized = 0;
// destination = 0;
// source = opcode & 0xfff;
new_name("movfp");
}
void MOVFP::runtime_initialize(void)
{
// if(cpu_pic->program_memory[address+1])
// {
// word2_opcode = cpu_pic->program_memory[address+1]->get_opcode();
// if((word2_opcode & 0xf000) != 0xf000)
// {
// cout << "16bit-instructions.cc MOVFP error\n";
// return;
// }
// cpu_pic->program_memory[address+1]->update_line_number( file_id, src_line, lst_line);
// destination = word2_opcode & 0xfff;
// initialized = 1;
// }
}
char *MOVFP::name(char *return_str, int len)
{
// if(!initialized)
// runtime_initialize();
snprintf(return_str,len,"%s\t%s,%s",
gpsimValue::name().c_str(),
cpu_pic->registers[source]->name().c_str(),
cpu_pic->registers[destination]->name().c_str());
return(return_str);
}
void MOVFP::execute(void)
{
// if(!initialized)
// runtime_initialize();
// unsigned int r = cpu_pic->registers[source]->get();
// cpu_pic->pc->skip();
// cpu_pic->registers[destination]->put(r);
// cpu_pic->pc->increment();
}
//--------------------------------------------------
MOVLB::MOVLB (Processor *new_cpu, unsigned int new_opcode)
: Literal_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("movlb");
}
void MOVLB::execute(void)
{
cpu16->bsr.put(L);
cpu16->pc->increment();
}
//--------------------------------------------------
MOVLR::MOVLR (Processor *new_cpu, unsigned int new_opcode)
: Literal_op(new_cpu, new_opcode, 0)
{
// decode(new_cpu, new_opcode);
new_name("movlr");
}
void MOVLR::execute(void)
{
// unsigned int source_value;
// cpu16->bsr.put(L);
// cpu_pic->pc->increment();
}
//--------------------------------------------------
MOVPF::MOVPF (Processor *new_cpu, unsigned int new_opcode)
: multi_word_instruction(new_cpu, new_opcode)
{
// opcode = new_opcode;
// cpu = new_cpu;
// address = cpu16->current_disasm_address;
// initialized = 0;
// destination = 0;
// source = opcode & 0xfff;
new_name("movpf");
}
void MOVPF::runtime_initialize(void)
{
// if(cpu_pic->program_memory[address+1])
// {
// word2_opcode = cpu_pic->program_memory[address+1]->get_opcode();
// if((word2_opcode & 0xf000) != 0xf000)
// {
// cout << "16bit-instructions.cc MOVFP error\n";
// return;
// }
// cpu_pic->program_memory[address+1]->update_line_number( file_id, src_line, lst_line);
// destination = word2_opcode & 0xfff;
// initialized = 1;
// }
}
char *MOVPF::name(char *return_str,int len)
{
// if(!initialized)
// runtime_initialize();
snprintf(return_str,len,"%s\t%s,%s",
gpsimValue::name().c_str(),
cpu_pic->registers[source]->name().c_str(),
cpu_pic->registers[destination]->name().c_str());
return(return_str);
}
void MOVPF::execute(void)
{
// if(!initialized)
// runtime_initialize();
// unsigned int r = cpu_pic->registers[source]->get();
// cpu_pic->pc->skip();
// cpu_pic->registers[destination]->put(r);
// cpu_pic->pc->increment();
}
//--------------------------------------------------
MOVWF16::MOVWF16(Processor *new_cpu, unsigned int new_opcode)
: MOVWF(new_cpu,new_opcode)
{
register_address = new_opcode & 0xff;
}
void MOVWF16::execute(void)
{
// source = ((!access) ?
// cpu_pic->registers[register_address]
// :
// cpu_pic->register_bank[register_address] );
source = cpu_pic->register_bank[register_address];
source->put(cpu16->W->get());
cpu16->pc->increment();
}
//--------------------------------------------------
MOVWF16a::MOVWF16a(Processor *new_cpu, unsigned int new_opcode) : MOVWF(new_cpu,new_opcode)
{
register_address = ((new_opcode & 0x80) ? 0xf80 : 0 ) | (new_opcode & 0x7f);
}
void MOVWF16a::execute(void)
{
source = cpu_pic->registers[register_address];
source->put(cpu16->W->get());
cpu16->pc->increment();
}
//--------------------------------------------------
MULLW::MULLW (Processor *new_cpu, unsigned int new_opcode)
: Literal_op(new_cpu, new_opcode,0)
{
decode(new_cpu, new_opcode);
new_name("mullw");
}
void MULLW::execute(void)
{
unsigned int value;
value = (0xff & cpu16->W->get()) * L;
cpu16->prodl.put(value &0xff);
cpu16->prodh.put((value>>8) &0xff);
cpu16->pc->increment();
}
//--------------------------------------------------
MULWF::MULWF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("mulwf");
}
void MULWF::execute(void)
{
unsigned int value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
//It's not necessary to '&' the get()'s with 0xff, but it doesn't
//hurt either.
value = (0xff & cpu16->W->get()) * (0xff & source->get());
cpu16->prodl.put(value &0xff);
cpu16->prodh.put((value>>8) &0xff);
cpu16->pc->increment();
}
//--------------------------------------------------
NEGF::NEGF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("negf");
}
void NEGF::execute(void)
{
unsigned int new_value,src_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
src_value = source->get();
new_value = 1 + ~src_value; // two's complement
source->put(new_value&0xff);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value,0,src_value);
cpu16->pc->increment();
}
//--------------------------------------------------
NEGW::NEGW (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode,0)
{
// decode(new_cpu, new_opcode);
new_name("negw");
}
void NEGW::execute(void)
{
cout << "negw is not implemented???";
}
//--------------------------------------------------
POP::POP (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("pop");
}
void POP::execute(void)
{
cpu16->stack->pop(); // discard TOS
cpu16->pc->increment();
}
//--------------------------------------------------
PUSH::PUSH (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("push");
}
void PUSH::execute(void)
{
cpu16->stack->push(cpu16->pc->get_next());
cpu16->pc->increment();
}
//--------------------------------------------------
RCALL::RCALL (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
destination_index = (new_opcode & 0x7ff)+1;
if(new_opcode & 0x400)
destination_index -= 0x800;
absolute_destination_index = (cpu16->getCurrentDisasmIndex() + destination_index) & 0xfffff;
new_name("rcall");
}
void RCALL::execute(void)
{
cpu16->stack->push(cpu16->pc->get_next());
cpu16->pc->jump(absolute_destination_index);
}
char * RCALL::name(char *return_str,int len)
{
snprintf(return_str,len,"%s\t$%c0x%x\t;(0x%05x)",
gpsimValue::name().c_str(),
(destination_index < 0) ? '-' : '+',
(destination_index & 0x7ff)<<1,
absolute_destination_index<<1);
return(return_str);
}
//--------------------------------------------------
RESET::RESET (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("reset");
}
void RESET::execute(void)
{
cpu16->reset(SOFT_RESET);
}
//--------------------------------------------------
void RETFIE16::execute(void)
{
cpu16->pc->new_address(cpu16->stack->pop());
if(fast)
cpu16->fast_stack.pop();
//cout << "retfie: need to enable interrupts\n";
cpu16->intcon.set_gies(); // re-enable the appropriate interrupt
}
char *RETFIE16::name(char *return_str,int len)
{
if(fast)
snprintf(return_str,len,"retfie\tfast");
else
snprintf(return_str,len,"retfie");
return(return_str);
}
//--------------------------------------------------
void RETURN16::execute(void)
{
cpu16->pc->new_address(cpu16->stack->pop());
if(fast)
cpu16->fast_stack.pop();
}
char *RETURN16::name(char *return_str,int len)
{
if(fast)
snprintf(return_str,len,"return\tfast");
else
snprintf(return_str,len,"return");
return(return_str);
}
//--------------------------------------------------
RLCF::RLCF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("rlcf");
}
void RLCF::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (source->get() << 1) | cpu16->status->get_C();
if(destination)
source->put(new_value&0xff); // Result goes to source
else
cpu16->W->put(new_value&0xff);
cpu16->status->put_Z_C_N(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
RLNCF::RLNCF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("rlncf");
}
void RLNCF::execute(void)
{
unsigned int new_value,src_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
src_value = source->get();
new_value = (src_value << 1) | ( (src_value & 0x80) ? 1 : 0);
if(destination)
source->put(new_value&0xff); // Result goes to source
else
cpu16->W->put(new_value&0xff);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
RRCF::RRCF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("rrcf");
}
void RRCF::execute(void)
{
unsigned int new_value,src_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
src_value = source->get() & 0xff;
new_value = (src_value >> 1) | (cpu16->status->get_C() ? 0x80 : 0);
if(destination)
source->put(new_value&0xff); // Result goes to source
else
cpu16->W->put(new_value&0xff);
cpu16->status->put_Z_C_N(new_value | ((src_value & 1) ? 0x100 : 0) );
cpu16->pc->increment();
}
//--------------------------------------------------
RRNCF::RRNCF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("rrncf");
}
void RRNCF::execute(void)
{
unsigned int new_value,src_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
src_value = source->get() & 0xff;
new_value = (src_value >> 1) | ( (src_value & 1) ? 0x80 : 0);
if(destination)
source->put(new_value&0xff); // Result goes to source
else
cpu16->W->put(new_value&0xff);
cpu16->status->put_N_Z(new_value | ((src_value & 1) ? 0x100 : 0) );
cpu16->pc->increment();
}
//--------------------------------------------------
SETF::SETF (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("setf");
}
void SETF::execute(void)
{
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
source->put(0xff);
cpu16->pc->increment();
}
//--------------------------------------------------
void SLEEP16::execute(void)
{
//cpu_pic->status->put_TO(1);
//cpu_pic->status->put_PD(0);
cout << "16BIT-SLEEP is not implemented\n";
// bp.set_sleep();
}
//--------------------------------------------------
void SUBLW16::execute(void)
{
unsigned int new_value,old_value;
new_value = L - (old_value = cpu16->W->value.get());
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value, L, old_value);
cpu16->pc->increment();
}
//--------------------------------------------------
SUBFWB::SUBFWB (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("subfwb");
}
void SUBFWB::execute(void)
{
unsigned int new_value,src_value,w_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (w_value = cpu16->W->value.get()) - (src_value = source->get()) -
(1 - cpu16->status->get_C());
if(destination)
source->put(new_value & 0xff);
else
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value, w_value, src_value);
cpu16->pc->increment();
}
//--------------------------------------------------
void SUBWF16::execute(void)
{
unsigned int new_value,src_value,w_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (src_value = source->get()) - (w_value = cpu16->W->value.get());
if(destination)
source->put(new_value & 0xff);
else
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value, src_value, w_value);
cpu16->pc->increment();
}
//--------------------------------------------------
SUBWFB::SUBWFB (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("subwfb");
}
void SUBWFB::execute(void)
{
unsigned int new_value,src_value,w_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = (src_value = source->get()) - (w_value = cpu16->W->value.get()) -
(1 - cpu16->status->get_C());
if(destination)
source->put(new_value & 0xff);
else
cpu16->W->put(new_value & 0xff);
cpu16->status->put_Z_C_DC_OV_N_for_sub(new_value, src_value, w_value);
cpu16->pc->increment();
}
//--------------------------------------------------
TBLRD::TBLRD (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("tblrd");
}
char *TBLRD::name(char *return_str,int len)
{
char *index_modes[4] = {"*","*+","*-","+*"};
snprintf(return_str,len,"%s\t%s",
gpsimValue::name().c_str(),
index_modes[opcode&0x3]);
return(return_str);
}
void TBLRD::execute(void)
{
if((opcode & 3)==3)
cpu16->tbl.increment();
cpu16->tbl.read();
if((opcode & 3)==1)
cpu16->tbl.increment();
else if((opcode & 3)==2)
cpu16->tbl.decrement();
cpu16->pc->increment();
}
//--------------------------------------------------
TBLWT::TBLWT (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("tblwt");
}
char *TBLWT::name(char *return_str,int len)
{
char *index_modes[4] = {"*","*+","*-","+*"};
snprintf(return_str,len,"%s\t%s",
gpsimValue::name().c_str(),
index_modes[opcode&0x3]);
return(return_str);
}
void TBLWT::execute(void)
{
if((opcode & 3)==3)
cpu16->tbl.increment();
cpu16->tbl.write();
if((opcode & 3)==1)
cpu16->tbl.increment();
else if((opcode & 3)==2)
cpu16->tbl.decrement();
cpu16->pc->increment();
}
//--------------------------------------------------
TLRD::TLRD (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
// decode(new_cpu, new_opcode);
new_name("tlrd");
}
char *TLRD::name(char *return_str,int len)
{
char *index_modes[4] = {"*","*+","*-","+*"};
snprintf(return_str,len,"%s\t%s",
gpsimValue::name().c_str(),
index_modes[opcode&0x3]);
return(return_str);
}
void TLRD::execute(void)
{
// unsigned int pm_opcode;
// if((opcode & 3)==3)
// cpu16->tbl.increment();
// cpu16->tbl.read();
// if((opcode & 3)==1)
// cpu16->tbl.increment();
// else if((opcode & 3)==2)
// cpu16->tbl.decrement();
// cpu_pic->pc->increment();
}
//--------------------------------------------------
TLWT::TLWT (Processor *new_cpu, unsigned int new_opcode)
: instruction(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("tlwt");
}
char *TLWT::name(char *return_str,int len)
{
char *index_modes[4] = {"*","*+","*-","+*"};
snprintf(return_str,len,"%s\t%s",
gpsimValue::name().c_str(),
index_modes[opcode&0x3]);
return(return_str);
}
void TLWT::execute(void)
{
// unsigned int pm_opcode;
// if((opcode & 3)==3)
// cpu16->tbl.increment();
// cpu16->tbl.write();
// if((opcode & 3)==1)
// cpu16->tbl.increment();
// else if((opcode & 3)==2)
// cpu16->tbl.decrement();
// cpu_pic->pc->increment();
}
//--------------------------------------------------
TSTFSZ::TSTFSZ (Processor *new_cpu, unsigned int new_opcode)
: Register_op(new_cpu, new_opcode, 0)
{
decode(new_cpu, new_opcode);
new_name("tstfsz");
}
void TSTFSZ::execute(void)
{
if(!access)
source = cpu_pic->registers[register_address];
else
source = cpu_pic->register_bank[register_address];
if( 0 == (source->get() & 0xff) )
{
cpu16->pc->skip(); // Skip next instruction
}
cpu16->pc->increment();
}
//--------------------------------------------------
void XORLW16::execute(void)
{
unsigned int new_value;
new_value = cpu16->W->value.get() ^ L;
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
//--------------------------------------------------
void XORWF16::execute(void)
{
unsigned int new_value;
source = ((!access) ?
cpu_pic->registers[register_address]
:
cpu_pic->register_bank[register_address] );
new_value = source->get() ^ cpu16->W->value.get();
if(destination)
source->put(new_value); // Result goes to source
else
cpu16->W->put(new_value);
cpu16->status->put_N_Z(new_value);
cpu16->pc->increment();
}
syntax highlighted by Code2HTML, v. 0.9.1