disassembler

This commit is contained in:
folkert van heusden 2022-03-16 12:06:01 +01:00
parent 7a77fefb24
commit 745657d76e
2 changed files with 360 additions and 4 deletions

363
cpu.cpp
View file

@ -6,8 +6,8 @@
#include <string.h> #include <string.h>
#include "cpu.h" #include "cpu.h"
#include "utils.h"
#include "gen.h" #include "gen.h"
#include "utils.h"
#ifndef _DEBUG #ifndef _DEBUG
std::string *src_gam_text = NULL, *dst_gam_text = NULL; std::string *src_gam_text = NULL, *dst_gam_text = NULL;
@ -1117,12 +1117,367 @@ void cpu::busError()
setPC(b -> readWord(4)); setPC(b -> readWord(4));
} }
std::string cpu::addressing_to_string(const uint8_t mode_register, const uint16_t pc)
{
assert(mode_register < 64);
uint16_t next_word = b->readWord((pc + 2) & 65535);
int reg = mode_register & 7;
std::string reg_name;
if (reg == 6)
reg_name = "SP";
else if (reg == 7)
reg_name = "PC";
else
reg_name = format("R%d", reg);
switch(mode_register >> 3) {
case 0:
return reg_name;
case 1:
return format("(%s)", reg_name.c_str());
case 2:
if (reg == 7)
return format("#%06o", next_word);
return format("(%s)+", reg_name.c_str());
case 3:
if (reg == 7)
return format("@#%06o", next_word);
return format("@(%s)+", reg_name.c_str());
case 4:
return format("-(%s)", reg_name.c_str());
case 5:
return format("@-(%s)", reg_name.c_str());
case 6:
if (reg == 7)
return format("%06o", (pc + next_word) & 65535);
return format("o%o(%s)", next_word, reg_name.c_str());
case 7:
if (reg == 7)
return format("@%06o", (pc + next_word) & 65535);
return format("@o%o(%s)", next_word, reg_name.c_str());
}
return "??";
}
void cpu::disassemble() void cpu::disassemble()
{ {
uint16_t pc = getPC(); uint16_t pc = getPC();
uint16_t instruction = b->readWord(pc); uint16_t instruction = b->readWord(pc);
fprintf(stderr, "PC: %05x, instruction: %04x\n", pc, instruction); bool word_mode = !!(instruction & 0x8000);
std::string word_mode_str = word_mode ? "B" : "";
uint8_t ado_opcode = (instruction >> 9) & 7; // additional double operand
uint8_t do_opcode = (instruction >> 12) & 7; // double operand
uint8_t so_opcode = (instruction >> 6) & 63; // single operand
std::string text;
std::string name;
uint8_t src_register = (instruction >> 6) & 63;
uint8_t dst_register = (instruction >> 0) & 63;
std::string src_text; // ASH, ASHC, MUL, DIV
std::string dst_text = addressing_to_string(dst_register, pc + 2); // for single as src can have an extra operand as well
// TODO: 100000011
if (do_opcode == 0b000) {
dst_text = addressing_to_string(dst_register, pc);
// single_operand_instructions
switch(so_opcode) {
case 0b00000011:
text = "SWAB " + dst_text;
break;
case 0b000101000:
name = "CLR";
break;
case 0b000101001:
name = "COM";
break;
case 0b000101010:
name = "INC";
break;
case 0b000101011:
name = "DEC";
break;
case 0b000101100:
name = "NEG";
break;
case 0b000101101:
name = "ADC";
break;
case 0b000101110:
name = "SBC";
break;
case 0b000101111:
name = "TST";
break;
case 0b000110000:
name = "ROR";
break;
case 0b000110001:
name = "ROL";
break;
case 0b000110010:
name = "ASR";
break;
case 0b00110011:
name = "ASL";
break;
case 0b00110101:
name = word_mode ? "MFPD" : "MFPI";
break;
case 0b00110110:
name = word_mode ? "MTPD" : "MTPI";
break;
case 0b000110100:
if (word_mode == false)
name = "MTPS";
break;
case 0b000110111:
if (word_mode == false)
name = "SXT";
else
name = "MFPS";
break;
}
if (text.empty() && name.empty() == false)
text = name + word_mode_str + " " + dst_text;
}
else if (do_opcode == 0b111) {
src_text = format("R%d", (instruction >> 6) & 7);
switch(ado_opcode) {
case 0:
name = "MUL";
break;
case 1:
name = "DIV";
break;
case 2:
name = "ASH";
break;
case 3:
name = "ASHC";
break;
case 4:
name = "XOR";
break;
case 7:
text = std::string("SOB") + dst_text;
break;
}
if (text.empty() && name.empty() == false)
text = name + " " + src_text + "," + dst_text;
}
else {
switch(do_opcode) {
case 0b001:
name = "MOV";
break;
case 0b010:
name = "CMP";
break;
case 0b011:
name = "BIT";
break;
case 0b100:
name = "BIC";
break;
case 0b101:
name = "BIS";
break;
case 0b110:
if (word_mode)
name = "SUB";
else
name = "ADD";
break;
}
text = name + word_mode_str + " " + addressing_to_string(src_register, pc) + "," + dst_text;
}
if (text.empty()) { // conditional branch instructions
uint8_t cb_opcode = (instruction >> 8) & 255;
int8_t offset = instruction & 255;
uint16_t new_pc = (pc + 2 + offset * 2) & 65535;
switch(cb_opcode) {
case 0b00000001:
name = "BR";
break;
case 0b00000010:
name = "BNE";
break;
case 0b00000011:
name = "BEQ";
break;
case 0b00000100:
name = "BGE";
break;
case 0b00000101:
name = "BLT";
break;
case 0b00000110:
name = "BGT";
break;
case 0b00000111:
name = "BLE";
break;
case 0b10000000:
name = "BPL";
break;
case 0b10000001:
name = "BMI";
break;
case 0b10000010:
name = "BHI";
break;
case 0b10000011:
name = "BLOS";
break;
case 0b10000100:
name = "BVC";
break;
case 0b10000101:
name = "BVS";
break;
case 0b10000110:
name = "BCC";
break;
case 0b10000111:
name = "BCS/BLO";
break;
}
if (text.empty() && name.empty() == false)
text = name + " $o" + format("%06o", new_pc);
}
if (text.empty()) {
if ((instruction & ~7) == 0000230)
text = format("SPL%d", instruction & 7);
if ((instruction & ~31) == 0b10100000) { // set condition bits
text = word_mode ? "S" : "C";
if (instruction & 0b1000)
text += "n";
if (instruction & 0b0100)
text += "z";
if (instruction & 0b0010)
text += "v";
if (instruction & 0b0001)
text += "c";
}
switch(instruction) {
case 0b0000000010100000:
case 0b0000000010110000:
text = "NOP";
break;
case 0b0000000000000000:
text = "HALT";
break;
case 0b0000000000000001:
text = "WAIT";
break;
case 0b0000000000000010:
text = "RTI";
break;
case 0b0000000000000110:
text = "RTT";
break;
case 0b0000000000000111:
text = "MFPT";
break;
case 0b0000000000000101:
text = "RESET";
break;
}
if ((instruction >> 8) == 0b10001000)
text = format("EMT %d", instruction & 255);
if ((instruction >> 8) == 0b10001001)
text = format("TRAP %d", instruction & 255);
if ((instruction & ~0b111111) == 0b0000000001000000)
text = std::string("JMP ") + dst_text;
if ((instruction & 0b1111111000000000) == 0b0000100000000000)
text = std::string("JSR ") + dst_text;
if ((instruction & 0b1111111111111000) == 0b0000000010000000)
text = "RTS";
}
fprintf(stderr, "PC: %06o, instruction: %06o: %s\n", pc, instruction, text.c_str());
} }
bool cpu::step() bool cpu::step()

1
cpu.h
View file

@ -39,6 +39,7 @@ private:
bool condition_code_operations(const uint16_t instr); bool condition_code_operations(const uint16_t instr);
bool misc_operations(const uint16_t instr); bool misc_operations(const uint16_t instr);
std::string addressing_to_string(const uint8_t mode_register, const uint16_t pc);
void disassemble(); void disassemble();
public: public: