[Scummvm-cvs-logs] SF.net SVN: scummvm:[51452] tools/branches/gsoc2010-decompiler/decompiler/ kyra/disassembler.cpp
pidgeot at users.sourceforge.net
pidgeot at users.sourceforge.net
Thu Jul 29 03:05:58 CEST 2010
Revision: 51452
http://scummvm.svn.sourceforge.net/scummvm/?rev=51452&view=rev
Author: pidgeot
Date: 2010-07-29 01:05:58 +0000 (Thu, 29 Jul 2010)
Log Message:
-----------
Preliminary KYRA disassembler
Still a few things to add, like function detection and calls, but this
can at least decode the individual instructions.
Modified Paths:
--------------
tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp
Modified: tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp
===================================================================
--- tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp 2010-07-29 01:05:11 UTC (rev 51451)
+++ tools/branches/gsoc2010-decompiler/decompiler/kyra/disassembler.cpp 2010-07-29 01:05:58 UTC (rev 51452)
@@ -29,7 +29,7 @@
_data = NULL;
}
-Kyra::Disassembler::Disassembler(Engine *engine) : _engine(engine) {
+Kyra::Disassembler::Disassembler(Engine *engine) : ::Disassembler(), _engine(engine) {
}
Kyra::Disassembler::~Disassembler() {
@@ -99,5 +99,126 @@
#undef posString
// Disassemble
- // TODO
+ uint16 numInsts = _dataChunk._size / 2;
+ for (uint16 i = 0; i < numInsts; ++i) {
+ uint16 address = i*2;
+ uint16 code = READ_BE_UINT16(&((uint16 *)_dataChunk._data)[i]);
+ int16 opcode = (code >> 8) & 0x1F;
+ int16 parameter;
+
+ if (code & 0x8000) {
+ opcode = 0;
+ parameter = code & 0x7FFF;
+ } else if (code & 0x4000) {
+ parameter = (int8)(code);
+ } else if (code & 0x2000) {
+ i++;
+ parameter = READ_BE_UINT16(&((uint16 *)_dataChunk._data)[i]);
+ } else {
+ parameter = 0;
+ }
+
+#define ADD_INST _insts.push_back(Instruction());
+#define LAST_INST (_insts[_insts.size()-1])
+#define OPCODE_MD(name, category, stackChange, codeGenData) \
+ ADD_INST; \
+ LAST_INST._opcode = opcode; \
+ LAST_INST._address = address; \
+ LAST_INST._stackChange = stackChange; \
+ LAST_INST._name = name; \
+ LAST_INST._type = category; \
+ LAST_INST._codeGenData = codeGenData; \
+ { \
+ Parameter p; \
+ p._type = kShort; \
+ p._value = parameter; \
+ LAST_INST._params.push_back(p);\
+ }
+#define OPCODE(name, category, stackChange) OPCODE_MD(name, category, stackChange, "");
+
+ // TOOD: Add metadata where applicable
+ switch(opcode) {
+ case 0:
+ OPCODE("jumpTo", kJump, 0);
+ break;
+ case 1:
+ OPCODE("setRetValue", kStore, 0);
+ break;
+ case 2:
+ if (parameter == 0) {
+ OPCODE("pushRet", kLoad, 1);
+ } else if (parameter == 1) {
+ OPCODE("pushPos", kSpecial, 2); // Sets up function call?
+ } else {
+ // Error: invalid parameter halts execution
+ }
+ break;
+ case 3:
+ case 4:
+ OPCODE("push", kLoad, 1);
+ break;
+ case 5:
+ OPCODE("pushVar", kLoad, 1);
+ break;
+ case 6:
+ OPCODE("pushBPNeg", kLoad, 1);
+ break;
+ case 7:
+ OPCODE("pushBPAdd", kLoad, 1);
+ break;
+ case 8:
+ if (parameter == 0) {
+ OPCODE("popRet", kStore, -1);
+ } else if (parameter == 1) {
+ OPCODE("popPos", kSpecial, -2); // Returns from function call?
+ } else {
+ // Error: invalid parameter halts execution
+ }
+ break;
+ case 9:
+ OPCODE("popVar", kStore, 1);
+ break;
+ case 10:
+ OPCODE("popBPNeg", kStore, 1);
+ break;
+ case 11:
+ OPCODE("popBPAdd", kStore, 1);
+ break;
+ case 12:
+ OPCODE("addSP", kStack, -parameter);
+ break;
+ case 13:
+ OPCODE("subSP", kStack, parameter);
+ break;
+ case 14:
+ OPCODE("execOpcode", kSpecial, 0); // TODO: Full details of opcode
+ break;
+ case 15:
+ OPCODE("ifNotJmp", kCondJump, -1);
+ break;
+ case 16:
+ if (parameter == 0) {
+ OPCODE_MD("boolCast", kUnaryOp, 0, "(bool)");
+ } else if (parameter == 1) {
+ OPCODE_MD("arithmeticNegate", kUnaryOp, 0, "-");
+ } else if (parameter == 2) {
+ OPCODE_MD("bitwiseNegate", kUnaryOp, 0, "~");
+ } else {
+ // Error: invalid parameter halts execution
+ }
+ break;
+ case 17:
+ OPCODE("eval", kBinaryOp, -1); // TODO: Full details of opcode
+ break;
+ case 18:
+ OPCODE("setRetAndJmp", kSpecial, -2); // Returns from function call?
+ break;
+ default:
+ throw UnknownOpcodeException(i*2, code);
+ }
+#undef OPCODE
+#undef OPCODE_MD
+#undef LAST_INST
+#undef ADD_INST
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list