dvander@0: /* dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #include "Opcodes.h" dvander@0: #include "Utility.h" dvander@0: #include "Code.h" dvander@0: dvander@0: using namespace jc; dvander@0: dvander@0: OpInfo jc::OpcodeInfo[] = dvander@0: { dvander@0: #define OPDEF(name, number, text, length, uses, defs) \ dvander@0: {text, length, uses, defs}, dvander@0: #include "Opcodes.tbl" dvander@0: #undef OPDEF dvander@0: }; dvander@0: dvander@0: // All jumps must be the same length. dvander@0: STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH); dvander@0: STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH); dvander@0: dvander@0: void dvander@0: jc::Disassemble(Code *code, FILE *fp) dvander@0: { dvander@0: bytecode *pc = code->start(); dvander@0: for (;;) { dvander@0: Opcode op = Opcode(*pc); dvander@0: dvander@0: fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name); dvander@0: dvander@0: switch (op) { dvander@0: case OP_NOP: dvander@0: case OP_RETURN: dvander@0: case OP_ADD: dvander@0: case OP_SUB: dvander@0: case OP_MUL: dvander@0: case OP_DIV: dvander@4: case OP_ADD_F: dvander@4: case OP_SUB_F: dvander@4: case OP_MUL_F: dvander@4: case OP_DIV_F: dvander@4: case OP_CVT_I2F: dvander@0: case OP_POP: dvander@0: case OP_LD_STA_I: dvander@0: case OP_LD_STA_P: dvander@0: case OP_ST_STA_I: dvander@0: case OP_BOUNDS_STA: dvander@0: break; dvander@0: dvander@0: case OP_STOP: dvander@0: fprintf(fp, "\n"); dvander@0: return; dvander@0: dvander@0: case OP_INT: dvander@0: fprintf(fp, "%d", READ_INT32(pc)); dvander@0: break; dvander@0: dvander@4: case OP_FLOAT: dvander@4: fprintf(fp, "%f", READ_FLOAT(pc)); dvander@4: break; dvander@4: dvander@0: case OP_JL: dvander@0: case OP_JLE: dvander@0: case OP_JG: dvander@0: case OP_JGE: dvander@0: case OP_JEQ: dvander@0: case OP_JNE: dvander@0: case OP_JT: dvander@0: case OP_JF: dvander@0: case OP_JUMP: dvander@1: fprintf(fp, "%u (%d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc)); dvander@0: break; dvander@0: dvander@0: case OP_STACKARRAY: dvander@0: { dvander@0: unsigned width = pc[1]; dvander@0: unsigned dims = pc[2]; dvander@0: dvander@0: for (unsigned i = 0; i < dims; i++) dvander@0: fprintf(fp, "[%u]", READ_UINT32(pc + 2 + (i * sizeof(unsigned)))); dvander@0: fprintf(fp, " ; (width = %s)\n", (width == 1 ? "char" : "cell")); dvander@0: pc += 3 + dims * sizeof(unsigned); dvander@0: continue; dvander@0: } dvander@0: dvander@0: case OP_GETLOCAL: dvander@0: case OP_SETLOCAL: dvander@0: case OP_GETARG: dvander@0: case OP_SETARG: dvander@1: case OP_UNWIND: dvander@0: fprintf(fp, "%u", READ_UINT32(pc)); dvander@0: break; dvander@0: dvander@0: case OP_CALLGLOBAL: dvander@0: fprintf(fp, "%u", READ_UINT32(pc)); dvander@0: break; dvander@0: dvander@0: default: dvander@0: // Unknown opcode! dvander@0: assert(false); dvander@0: return; dvander@0: } dvander@0: dvander@0: fprintf(fp, "\n"); dvander@0: pc += OpcodeInfo[op].length; dvander@0: } dvander@0: }