Very nice work, especially to Oopho2ei!
Till the 12th post in this thread I never thought this would become anything at all. (And I still don't know how much is done after the bdvm is implemented.)
First I thought about trying to continue the bdvm, but then my little C knowledge kept me from continuing. (And I never was sure if anyone else is working on it.)
So I took an easier task and tried to start with the disassembler.
I started with the source from the bdvm but now very few is left. Here it goes:
Code:
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
using namespace std;
typedef unsigned char byte; // for less typing
typedef unsigned int uint; // dito
class BDDasm {
public:
BDDasm();
string dasmCmd(uint);
void dasmFile(string, uint, uint);
uint makeint(byte, byte, byte, byte);
private:
uint pc;
};
// end header
int _signed(uint x) { return (int)x; }
int _signed(int x) { return x; }
int _unsigned(uint x) { return x; }
int _unsigned(int x) { return (uint)x; }
BDDasm::BDDasm(){
pc = 0;
}
uint BDDasm::makeint(byte b3, byte b2, byte b1, byte b0) {
return ((int)b0) << 24 | ((int)b1) << 16 | ((int)b2) << 8 | ((int)b3);
}
void BDDasm::dasmFile(string fname, uint pep, uint len){
ifstream file;
file.open(fname.c_str());
file.seekg(pep);
pc = pep-6*4;
uint I; //Instruction
while(pc <= pep+len){
pc +=4;
I = makeint((byte)file.get(),(byte)file.get(),(byte)file.get(),(byte)file.get());
cout << dasmCmd(I);
}
file.close();
}
string BDDasm::dasmCmd(uint I) {
std::ostringstream out;
char buffer [100];
// instruction fetch
uint C = I >> 0x1A; // command
uint Rd = ((I >> 0x13) & 0x7C) >> 2; // operand X
uint Rs1 = ((I >> 0x0E) & 0x7C) >> 2; // operand Y
uint Rs2 = ((I >> 0x09) & 0x7C) >> 2; // operand Z
uint C16 = I & 0xFFFF; // 16 bit constant
int C16S = _signed(_unsigned(I) << 16) >> 16; // same signed
uint C5 = I & 0x1F; // 5 bit constant
uint C26 = I & 0x3FFFFFF; // 26 bit constant
int C26S = _signed(_unsigned(I) << 6) >> 6; // same signed
sprintf (buffer, "%6X ", pc-4);
out << buffer;
sprintf (buffer, "%8X ", I);
out << buffer;
// instructions
string ops[0x3C] = {"NOP", "ADD", "SUB", "MUL", "IDIV", "DIVU",
"SLL", "SRL", "SRA", "AND", "OR", "XOR", "SEQ", "SNE", "SLT",
"SBT", "SGT", "SAT", "SLE", "SBE", "SGE", "SAE", "JR", "JALR",
"ADDIE", "ADDI", "SUBIE", "SUBI", "SLLI", "SRLI", "SRAI",
"ANDI", "ORI", "XORI", "SEQI", "SNEI", "SLI", "SBI", "SGI",
"SAI", "SLEI", "SBEI", "SGEI", "SAEI", "J", "JAL", "BEQZ",
"BNEZ", "LHI", "LBE", "LB", "LWE", "LW", "LDW", "SB", "SW",
"SDW", "TRAP", "SWDR", "unknown"};
if(C>=0x00 && C<=0x3A){
out << ops[C];
}
else {
out << ops[0x3b];
}
if(C>=0x01 && C<=0x15){
out << " R" << Rd << ", R" << Rs1 << ", R" << Rs2;
}
else if(C==0x16||C==0x17){
out << " R" << Rs1;
}
else if(C>=0x18 && C<=0x3A && C!=0x2c && C!=0x2d && C!=0x39 && C!=0x2e && C!=0x2f){
sprintf(buffer, ", #%Xh", C16);
out << " R" << Rd << ", R" << Rs1 << buffer;
}
else if(C==0x2c || C==0x2d){
sprintf(buffer, " #%Xh", (pc+(C16S& 0x3FFFFC))& 0x3FFFFC);
out << buffer;
}
else if(C==0x2e || C==0x2f){
sprintf(buffer, ", #%Xh", (pc+(C16S& 0x3FFFFC))& 0x3FFFFC);
out << " R" << Rs1 << buffer;
}
else if(C==0x39){
sprintf(buffer, " #%Xh", C26);
out << buffer;
}
out << endl;
return out.str();
}
int main() {
BDDasm a;
a.dasmFile("00000.svm",0x1000,0xF000);
}
Now you can laugh at my coding style. Whats left to be done is some improvements to the dasm and of course a file reader and much more.
For a start, here is the output of the hardcoded commands:
Code:
1000 E4000110 TRAP #110h
1004 42445356 SGT R18, R4, R10
1008 581F0000 JR R31
100C 4800800 ADD R4, R0, R1
1010 63BD0014 ADDIE R29, R29, #14h
1014 BC010038 BNEZ R0, R1, #38h
1018 63BDFFF4 ADDIE R29, R29, #FFF4h
101C E15D0000 SDW R10, R29, #0h
1020 E17D0004 SDW R11, R29, #4h
1024 74270002 SRLI R1, R7, #2h
1028 E03D0008 SDW R1, R29, #8h
102C B7FFF8EC JAL, #918h
1030 E4000230 TRAP #230h
Looks quite familliar to what Oopho decoded, except for the JR and some constants.
*edit* Fixed JR handling...
*edit2* Added trivial stream handling... and watch out if someone ever tries to use the experimental BDVM, b2 is used twice in the makeint function...
*edit3* Added Offset to adress display and executed pc+r1 for jumps
*edit4* Final update with file reader and correct jumps (I hope). There is an offset for the pc of 6dwords to align with the trace in post #35, I guess thats some kind of header or something... I will post the dasm of the first 0xF000 bytes in post #40