oscar64/oscar64/Assembler.cpp

372 lines
8.2 KiB
C++

#include "Assembler.h"
#include <assert.h>
#include <string.h>
AsmInsData DecInsData[256] = {
{ASMIT_BRK, ASMIM_IMPLIED},
{ASMIT_ORA, ASMIM_INDIRECT_X},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_ORA, ASMIM_ZERO_PAGE},
{ASMIT_ASL, ASMIM_ZERO_PAGE},
{ASMIT_INV},
{ASMIT_PHP, ASMIM_IMPLIED},
{ASMIT_ORA, ASMIM_IMMEDIATE},
{ASMIT_ASL, ASMIM_IMPLIED},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_ORA, ASMIM_ABSOLUTE},
{ASMIT_ASL, ASMIM_ABSOLUTE},
{ASMIT_INV},
{ASMIT_BPL, ASMIM_RELATIVE },
{ASMIT_ORA, ASMIM_INDIRECT_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_ORA, ASMIM_ZERO_PAGE_X},
{ASMIT_ASL, ASMIM_ZERO_PAGE_X},
{ASMIT_INV},
{ASMIT_CLC, ASMIM_IMPLIED},
{ASMIT_ORA, ASMIM_ABSOLUTE_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_ORA, ASMIM_ABSOLUTE_X},
{ASMIT_ASL, ASMIM_ABSOLUTE_X},
{ASMIT_INV},
{ASMIT_JSR, ASMIM_ABSOLUTE},
{ASMIT_AND, ASMIM_INDIRECT_X},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_BIT, ASMIM_ZERO_PAGE},
{ASMIT_AND, ASMIM_ZERO_PAGE},
{ASMIT_ROL, ASMIM_ZERO_PAGE},
{ASMIT_INV},
{ASMIT_PLP, ASMIM_IMPLIED},
{ASMIT_AND, ASMIM_IMMEDIATE},
{ASMIT_ROL, ASMIM_IMPLIED},
{ASMIT_INV},
{ASMIT_BIT, ASMIM_ABSOLUTE},
{ASMIT_AND, ASMIM_ABSOLUTE},
{ASMIT_ROL, ASMIM_ABSOLUTE},
{ASMIT_INV},
{ASMIT_BMI, ASMIM_RELATIVE },
{ASMIT_AND, ASMIM_INDIRECT_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_AND, ASMIM_ZERO_PAGE_X},
{ASMIT_ROL, ASMIM_ZERO_PAGE_X},
{ASMIT_INV},
{ASMIT_SEC, ASMIM_IMPLIED},
{ASMIT_AND, ASMIM_ABSOLUTE_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_AND, ASMIM_ABSOLUTE_X},
{ASMIT_ROL, ASMIM_ABSOLUTE_X},
{ASMIT_INV},
{ASMIT_RTI, ASMIM_IMPLIED},
{ASMIT_EOR, ASMIM_INDIRECT_X},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_EOR, ASMIM_ZERO_PAGE},
{ASMIT_LSR, ASMIM_ZERO_PAGE},
{ASMIT_INV},
{ASMIT_PHA, ASMIM_IMPLIED},
{ASMIT_EOR, ASMIM_IMMEDIATE},
{ASMIT_LSR, ASMIM_IMPLIED},
{ASMIT_INV},
{ASMIT_JMP, ASMIM_ABSOLUTE},
{ASMIT_EOR, ASMIM_ABSOLUTE},
{ASMIT_LSR, ASMIM_ABSOLUTE},
{ASMIT_INV},
{ASMIT_BVC, ASMIM_RELATIVE },
{ASMIT_EOR, ASMIM_INDIRECT_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_EOR, ASMIM_ZERO_PAGE_X},
{ASMIT_LSR, ASMIM_ZERO_PAGE_X},
{ASMIT_INV},
{ASMIT_CLI, ASMIM_IMPLIED},
{ASMIT_EOR, ASMIM_ABSOLUTE_Y},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_INV},
{ASMIT_EOR, ASMIM_ABSOLUTE_X},
{ASMIT_LSR, ASMIM_ABSOLUTE_X},
{ASMIT_INV},
{ ASMIT_RTS, ASMIM_IMPLIED },
{ ASMIT_ADC, ASMIM_INDIRECT_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_ADC, ASMIM_ZERO_PAGE },
{ ASMIT_ROR, ASMIM_ZERO_PAGE },
{ ASMIT_INV },
{ ASMIT_PLA, ASMIM_IMPLIED },
{ ASMIT_ADC, ASMIM_IMMEDIATE },
{ ASMIT_ROR, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_JMP, ASMIM_INDIRECT },
{ ASMIT_ADC, ASMIM_ABSOLUTE },
{ ASMIT_ROR, ASMIM_ABSOLUTE },
{ ASMIT_INV },
{ ASMIT_BVS, ASMIM_RELATIVE },
{ ASMIT_ADC, ASMIM_INDIRECT_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_ADC, ASMIM_ZERO_PAGE_X },
{ ASMIT_ROR, ASMIM_ZERO_PAGE_X },
{ ASMIT_INV },
{ ASMIT_SEI, ASMIM_IMPLIED },
{ ASMIT_ADC, ASMIM_ABSOLUTE_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_ADC, ASMIM_ABSOLUTE_X },
{ ASMIT_ROR, ASMIM_ABSOLUTE_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_STA, ASMIM_INDIRECT_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_STY, ASMIM_ZERO_PAGE },
{ ASMIT_STA, ASMIM_ZERO_PAGE },
{ ASMIT_STX, ASMIM_ZERO_PAGE },
{ ASMIT_INV },
{ ASMIT_DEY, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_TXA, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_STY, ASMIM_ABSOLUTE },
{ ASMIT_STA, ASMIM_ABSOLUTE },
{ ASMIT_STX, ASMIM_ABSOLUTE },
{ ASMIT_INV },
{ ASMIT_BCC, ASMIM_RELATIVE },
{ ASMIT_STA, ASMIM_INDIRECT_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_STY, ASMIM_ZERO_PAGE_X },
{ ASMIT_STA, ASMIM_ZERO_PAGE_X },
{ ASMIT_STX, ASMIM_ZERO_PAGE_Y },
{ ASMIT_INV },
{ ASMIT_TYA, ASMIM_IMPLIED },
{ ASMIT_STA, ASMIM_ABSOLUTE_Y },
{ ASMIT_TXS },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_STA, ASMIM_ABSOLUTE_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_LDY, ASMIM_IMMEDIATE },
{ ASMIT_LDA, ASMIM_INDIRECT_X },
{ ASMIT_LDX, ASMIM_IMMEDIATE },
{ ASMIT_INV },
{ ASMIT_LDY, ASMIM_ZERO_PAGE },
{ ASMIT_LDA, ASMIM_ZERO_PAGE },
{ ASMIT_LDX, ASMIM_ZERO_PAGE },
{ ASMIT_INV },
{ ASMIT_TAY, ASMIM_IMPLIED },
{ ASMIT_LDA, ASMIM_IMMEDIATE },
{ ASMIT_TAX, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_LDY, ASMIM_ABSOLUTE },
{ ASMIT_LDA, ASMIM_ABSOLUTE },
{ ASMIT_LDX, ASMIM_ABSOLUTE },
{ ASMIT_INV },
{ ASMIT_BCS, ASMIM_RELATIVE },
{ ASMIT_LDA, ASMIM_INDIRECT_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_LDY, ASMIM_ZERO_PAGE_X },
{ ASMIT_LDA, ASMIM_ZERO_PAGE_X },
{ ASMIT_LDX, ASMIM_ZERO_PAGE_Y },
{ ASMIT_INV },
{ ASMIT_CLV, ASMIM_IMPLIED },
{ ASMIT_LDA, ASMIM_ABSOLUTE_Y },
{ ASMIT_TSX, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_LDY, ASMIM_ABSOLUTE_X },
{ ASMIT_LDA, ASMIM_ABSOLUTE_X },
{ ASMIT_LDX, ASMIM_ABSOLUTE_Y },
{ ASMIT_INV },
{ ASMIT_CPY, ASMIM_IMMEDIATE },
{ ASMIT_CMP, ASMIM_INDIRECT_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_CPY, ASMIM_ZERO_PAGE },
{ ASMIT_CMP, ASMIM_ZERO_PAGE },
{ ASMIT_DEC, ASMIM_ZERO_PAGE },
{ ASMIT_INV },
{ ASMIT_INY, ASMIM_IMPLIED },
{ ASMIT_CMP, ASMIM_IMMEDIATE },
{ ASMIT_DEX, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_CPY, ASMIM_ABSOLUTE },
{ ASMIT_CMP, ASMIM_ABSOLUTE },
{ ASMIT_DEC, ASMIM_ABSOLUTE },
{ ASMIT_INV },
{ ASMIT_BNE, ASMIM_RELATIVE },
{ ASMIT_CMP, ASMIM_INDIRECT_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_CMP, ASMIM_ZERO_PAGE_X },
{ ASMIT_DEC, ASMIM_ZERO_PAGE_X },
{ ASMIT_INV },
{ ASMIT_CLD, ASMIM_IMPLIED },
{ ASMIT_CMP, ASMIM_ABSOLUTE_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_CMP, ASMIM_ABSOLUTE_X },
{ ASMIT_DEC, ASMIM_ABSOLUTE_X },
{ ASMIT_INV },
{ ASMIT_CPX, ASMIM_IMMEDIATE },
{ ASMIT_SBC, ASMIM_INDIRECT_X },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_CPX, ASMIM_ZERO_PAGE },
{ ASMIT_SBC, ASMIM_ZERO_PAGE },
{ ASMIT_INC, ASMIM_ZERO_PAGE },
{ ASMIT_INV },
{ ASMIT_INX, ASMIM_IMPLIED },
{ ASMIT_SBC, ASMIM_IMMEDIATE },
{ ASMIT_NOP, ASMIM_IMPLIED },
{ ASMIT_INV },
{ ASMIT_CPX, ASMIM_ABSOLUTE },
{ ASMIT_SBC, ASMIM_ABSOLUTE },
{ ASMIT_INC, ASMIM_ABSOLUTE },
{ ASMIT_INV },
{ ASMIT_BEQ, ASMIM_RELATIVE },
{ ASMIT_SBC, ASMIM_INDIRECT_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_SBC, ASMIM_ZERO_PAGE_X },
{ ASMIT_INC, ASMIM_ZERO_PAGE_X },
{ ASMIT_INV },
{ ASMIT_SED, ASMIM_IMPLIED },
{ ASMIT_SBC, ASMIM_ABSOLUTE_Y },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_INV },
{ ASMIT_SBC, ASMIM_ABSOLUTE_X },
{ ASMIT_INC, ASMIM_ABSOLUTE_X },
{ ASMIT_INV },
};
short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
"ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL", "BRK", "BVC", "BVS", "CLC",
"CLD", "CLI", "CLV", "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "EOR", "INC", "INX", "INY", "JMP",
"JSR", "LDA", "LDX", "LDY", "LSR", "NOP", "ORA", "PHA", "PHP", "PLA", "PLP", "ROL", "ROR", "RTI",
"RTS", "SBC", "SEC", "SED", "SEI", "STA", "STX", "STY", "TAX", "TAY", "TSX", "TXA", "TXS", "TYA",
"INV", "BYT"
};
int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
1,
2,
2,
2,
2,
3,
3,
3,
3,
2,
2,
2,
0,
2
};
void InitAssembler(void)
{
for (int i = 0; i < NUM_ASM_INS_TYPES; i++)
{
for (int j = 0; j < NUM_ASM_INS_MODES; j++)
{
AsmInsOpcodes[i][j] = -1;
}
}
for (int i = 0; i < 256; i++)
{
const AsmInsData& di(DecInsData[i]);
if (di.mType != ASMIT_INV)
{
assert(AsmInsOpcodes[di.mType][di.mMode] == -1);
AsmInsOpcodes[di.mType][di.mMode] = i;
}
}
AsmInsOpcodes[ASMIT_BYTE][ASMIM_ZERO_PAGE] = 0;
}
int AsmInsSize(AsmInsType type, AsmInsMode mode)
{
if (type < ASMIT_INV && mode >= ASMIM_IMPLIED && mode < NUM_ASM_INS_MODES)
return AsmInsModeSize[mode];
else
return 1;
}
static inline char toupper(char ch)
{
if (ch >= 'a' && ch <= 'z')
return ch - 'a' + 'A';
else
return ch;
}
AsmInsType FindAsmInstruction(const char* ins)
{
if (ins && strlen(ins) == 3)
{
for (int i = 0; i < NUM_ASM_INS_TYPES; i++)
{
if (AsmInstructionNames[i][0] == toupper(ins[0]) &&
AsmInstructionNames[i][1] == toupper(ins[1]) &&
AsmInstructionNames[i][2] == toupper(ins[2]))
return AsmInsType(i);
}
}
return ASMIT_INV;
}
bool HasAsmInstructionMode(AsmInsType type, AsmInsMode mode)
{
return AsmInsOpcodes[type][mode] != -1;
}