/*
* Author: Pawel Jablonski
* E-mail: pj@xirx.net
* WWW: xirx.net
* GIT: git.xirx.net
*
* License: You can use this code however you like
* but leave information about the original author.
* Code is free for non-commercial and commercial use.
*/
#include "uromdata.h"
//! Default constructor for creating an empty uROM opcode table
URomData::URomData()
{
this->data[0].fill(0);
this->data[1].fill(0);
}
/**
* Add an instruction to the uROM opcode table
*
* @param instruction Instruction to add
*/
void URomData::addInstruction(const Instruction &instruction)
{
int opcodeWidth = 1;
// Calculate how many consecutive opcodes the instruction uses
opcodeWidth *= ((instruction.getArg0() == Instruction::Arg::AB) ? 2 : 1);
opcodeWidth *= ((instruction.getArg0() == Instruction::Arg::ABXY) ? 4 : 1);
opcodeWidth *= ((instruction.getArg1() == Instruction::Arg::AB) ? 2 : 1);
opcodeWidth *= ((instruction.getArg1() == Instruction::Arg::ABXY) ? 4 : 1);
// Calculate how many steps is used by the instruction
int stepQuantity = qMin(instruction.getStepList().size(), INSTRUCTION_CYCLE_QUANTITY);
// Add instruction entrys to the opcode table
for(int i = 0; i < opcodeWidth; i++)
{
for(int s = 0; s < stepQuantity; s++)
{
// Calculate the base offset of the entry
int offsetBase = ((static_cast<int>(s) * INSTRUCTION_QUANTITY) + static_cast<int>(instruction.getOpcode()) + i);
Step step = instruction.getStepList().at(s);
// Fill only entries where the carry and the zero flags fit to the selected by instruction
for(int c = 0; c < 2; c++)
{
for(int z = 0; z < 2; z++)
{
if(!((instruction.getC() == Instruction::Flag::Any) || (static_cast<int>(instruction.getC()) == c)))
{
continue;
}
if(!((instruction.getZ() == Instruction::Flag::Any) || (static_cast<int>(instruction.getZ()) == z)))
{
continue;
}
int offset = (offsetBase + (c << ADDRESS_FLAG_C_POSITION) + (z << ADDRESS_FLAG_Z_POSITION));
this->data[0][offset] = step.getUCode().getCode0();
this->data[1][offset] = step.getUCode().getCode1();
}
}
}
}
}
/**
* Save a binary microcode to files
*
* @param urom0Path Path to the first output file
* @param urom1Path Path to the second output file
*
* @return Status of the save operation
*/
bool URomData::saveFiles(const QString &urom0Path, const QString &urom1Path)
{
QFile urom0File(urom0Path);
// Try to save the first output file
if(urom0File.open(QIODevice::WriteOnly))
{
urom0File.write(reinterpret_cast<const char *>(this->data[0].constData()), UROM_SIZE);
urom0File.close();
}
else
{
return(false);
}
QFile urom1File(urom1Path);
// Try to save the second output file
if(urom1File.open(QIODevice::WriteOnly))
{
urom1File.write(reinterpret_cast<const char *>(this->data[1].constData()), UROM_SIZE);
urom1File.close();
}
else
{
return(false);
}
return(true);
}