View Single Post
Old 2nd September 2008, 17:48   #37  |  Link
Disabled
Registered User
 
Join Date: Aug 2004
Posts: 211
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

Last edited by Disabled; 2nd September 2008 at 22:44.
Disabled is offline   Reply With Quote