area51/Support/scriptvm/xsc_vm_disasm.cpp
Andrew Sampson 431f72b93a source
2021-08-27 19:22:41 -07:00

190 lines
11 KiB
C++

//==============================================================================
//
// xsc_vm_disasm.cpp
//
//==============================================================================
#include "xsc_vm_core.hpp"
#include "xsc_vm_module.hpp"
#include "xsc_vm_instructions.hpp"
//==============================================================================
// Defines
//==============================================================================
struct disasm_data
{
s32 Opcode;
const char* Instruction;
s32 Args;
};
enum disasm_args
{
DA_NULL,
DA_OFFSET,
DA_COUNT,
DA_METHODREF,
DA_CLASSREF,
DA_FIELDREF,
DA_CONST_INT,
DA_CONST_FLT,
};
disasm_data DisasmData[] =
{
{ vm_nop, "nop", 0 }, // no operation 1 byte
{ vm_assert, "assert", 0 }, // assert exception 1 byte
{ vm_break, "break", 0 }, // break exception 1 byte
{ vm_ba, "ba", DA_OFFSET }, // Branch Always 3 bytes (Relative offset)
{ vm_bf, "bf", DA_OFFSET }, // Branch False 3 bytes (Relative offset)
{ vm_bt, "bt", DA_OFFSET }, // Branch True 3 bytes (Relative offset)
{ vm_itof, "itof", 0 }, // cast int to float 1 byte
{ vm_ftoi, "ftoi", 0 }, // cast float to int 1 byte
{ vm_icmp_eq, "icmp_eq", 0 }, // compare equal int 1 byte
{ vm_icmp_ge, "icmp_ge", 0 }, // compare greater or equal int 1 byte
{ vm_icmp_gt, "icmp_gt", 0 }, // compare greater int 1 byte
{ vm_icmp_le, "icmp_le", 0 }, // compare less or equal int 1 byte
{ vm_icmp_lt, "icmp_lt", 0 }, // compare less than int 1 byte
{ vm_icmp_ne, "icmp_ne", 0 }, // compare not equal int 1 byte
{ vm_fcmp_eq, "fcmp_eq", 0 }, // compare equal float 1 byte
{ vm_fcmp_ge, "fcmp_ge", 0 }, // compare greater or equal float 1 byte
{ vm_fcmp_gt, "fcmp_gt", 0 }, // compare greater float 1 byte
{ vm_fcmp_le, "fcmp_le", 0 }, // compare less or equal float 1 byte
{ vm_fcmp_lt, "fcmp_lt", 0 }, // compare less than float 1 byte
{ vm_fcmp_ne, "fcmp_ne", 0 }, // compare not equal float 1 byte
{ vm_idup, "idup", 0 }, // Duplicate top stack item int 1 byte
{ vm_fdup, "fdup", 0 }, // Duplicate top stack item float 1 byte
{ vm_cdup, "cdup", DA_CLASSREF }, // Duplicate top stack item class 3 bytes (ClassRef index)
{ vm_invoke, "invoke", DA_METHODREF }, // Invoke instance method 3 bytes (MethodRef index)
{ vm_invokenative, "invokenative", DA_METHODREF }, // Invoke native method 3 bytes (MethodRef index)
{ vm_invokestatic, "invokestatic", DA_METHODREF }, // Invoke static method 3 bytes (MethodRef index)
{ vm_invokevirtual, "invokevirtual", DA_METHODREF }, // Invoke virtual method 3 bytes (MethodRef index)
{ vm_this, "this", 0 }, // Load this pointer 1 byte
{ vm_aaddr, "aaddr", DA_COUNT }, // Load argument address 3 bytes (Argument byte index)
{ vm_laddr, "laddr", DA_COUNT }, // Load local address 3 bytes (Local byte index)
{ vm_faddr, "faddr", DA_FIELDREF }, // Add field address to top of stack 3 bytes (FieldRef index)
{ vm_iconst, "iconst", DA_CONST_INT }, // Load Const Int 3 bytes (Const index)
{ vm_fconst, "fconst", DA_CONST_FLT }, // Load Const Float 3 bytes (Const index)
{ vm_iload, "iload", 0 }, // Load Int from address 1 byte
{ vm_fload, "fload", 0 }, // Load Flt from address 1 byte
{ vm_cload, "cload", DA_CLASSREF }, // Load Class from address 3 bytes (ClassRef index)
{ vm_istore, "istore", 0 }, // Store Int to address 1 byte
{ vm_fstore, "fstore", 0 }, // Store Flt to address 1 byte
{ vm_cstore, "cstore", DA_CLASSREF }, // Store Class to address 3 bytes (ClassRef index)
{ vm_iadd, "iadd", 0 }, // Add top 2 stack Int 1 byte
{ vm_idiv, "idiv", 0 }, // Div top 2 stack Int 1 byte
{ vm_imod, "imod", 0 }, // Mod top 2 stack Int 1 byte
{ vm_imul, "imul", 0 }, // Mul top 2 stack Int 1 byte
{ vm_ineg, "ineg", 0 }, // Neg top stack Int 1 byte
{ vm_isub, "isub", 0 }, // Sub top 2 stack Int 1 byte
{ vm_fadd, "fadd", 0 }, // Add top 2 stack Float 1 byte
{ vm_fdiv, "fdiv", 0 }, // Div top 2 stack Float 1 byte
{ vm_fmod, "fmod", 0 }, // Mod top 2 stack Float 1 byte
{ vm_fmul, "fmul", 0 }, // Mul top 2 stack Float 1 byte
{ vm_fneg, "fneg", 0 }, // Neg top stack Float 1 byte
{ vm_fsub, "fsub", 0 }, // Sub top 2 stack Float 1 byte
{ vm_bit_and, "bit_and", 0 }, // Bitwise And top 2 stack Int 1 byte
{ vm_bit_or, "bit_or", 0 }, // Bitwise Or top 2 stack Int 1 byte
{ vm_log_and, "log_and", 0 }, // Logical And top 2 stack Int 1 byte
{ vm_log_or, "log_or", 0 }, // Logical Or top 2 stack Int 1 byte
{ vm_not, "not", 0 }, // Not top stack Int 1 byte
{ vm_shl, "shl", 0 }, // Shift Left 1 byte
{ vm_shr, "shr", 0 }, // Shift Right 1 byte
{ vm_xor, "xor", 0 }, // Xor top 2 stack Int 1 byte
{ vm_pop, "pop", DA_COUNT }, // Pop n bytes from stack 3 bytes (Number of bytes)
{ vm_vret, "vret", 0 }, // Return Void 1 byte
{ vm_iret, "iret", 0 }, // Return Int 1 byte
{ vm_fret, "fret", 0 }, // Return Flt 1 byte
{ vm_cret, "cret", DA_CLASSREF }, // Return Class 3 bytes (ClassRef index)
{ vm_rret, "rret", 0 }, // Return Reference 1 byte
};
//==============================================================================
// ValidateDisasmTable
//==============================================================================
void xsc_vm_core::ValidateDisasmTable( void ) const
{
// Loop through table validating entries
for( s32 i=0 ; i<(s32)((sizeof(DisasmData)/sizeof(disasm_data))) ; i++ )
{
ASSERT( DisasmData[i].Opcode == i );
}
}
//==============================================================================
// Disasm
//==============================================================================
xstring xsc_vm_core::Disasm( const xsc_vm_module* pModule, s32& IP )
{
ASSERT( (IP >= 0) && (IP < pModule->m_pHeader->MethodsBytes) );
xstring s;
const u8* pMethod = pModule->m_pMethods;
s32 Opcode = (s32)pMethod[IP];
ASSERT( (Opcode >= vm_nop) && (Opcode < vm_last_opcode) );
s32 Operand;
disasm_data& dd = DisasmData[Opcode];
s.AddFormat( "%06d %-15s", IP, dd.Instruction );
IP++;
switch( dd.Args )
{
case DA_OFFSET:
Operand = (s16)(((s16)pMethod[IP+0])<<8) + (s16)(((s16)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%d)", Operand, IP+Operand );
break;
case DA_COUNT:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d", Operand );
break;
case DA_METHODREF:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%s.%s)", Operand, &pModule->m_pConstStr[pModule->m_pMethodRef[Operand].ClassNameOffset],
&pModule->m_pConstStr[pModule->m_pMethodRef[Operand].MethodNameOffset] );
break;
case DA_CLASSREF:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%s)", Operand, &pModule->m_pConstStr[pModule->m_pClassRef[Operand].ClassNameOffset] );
break;
case DA_FIELDREF:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%s)", Operand, &pModule->m_pConstStr[pModule->m_pFieldRef[Operand].FieldNameOffset] );
break;
case DA_CONST_INT:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%d)", Operand, pModule->m_pConstInt[Operand] );
break;
case DA_CONST_FLT:
Operand = (((s32)pMethod[IP+0])<<8) + (((s32)pMethod[IP+1]));
IP += 2;
s.AddFormat( "%d (%f)", Operand, pModule->m_pConstFlt[Operand] );
break;
}
// Return disassembled line
return s;
}
//==============================================================================