jitcraft/Opcodes.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 27 02:28:39 2012 -0700 (2012-06-27)
changeset 5 9b63fb7cf5bf
parent 4 633176823669
child 6 172dd7799d0a
permissions -rw-r--r--
Always add a sign when spewing jump distances.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #include "Opcodes.h"
    19 #include "Utility.h"
    20 #include "Code.h"
    21 
    22 using namespace jc;
    23 
    24 OpInfo jc::OpcodeInfo[] =
    25 {
    26 #define OPDEF(name, number, text, length, uses, defs) \
    27     {text, length, uses, defs},
    28 #include "Opcodes.tbl"
    29 #undef OPDEF
    30 };
    31 
    32 // All jumps must be the same length.
    33 STATIC_ASSERT(OP_JL_LENGTH == OP_JUMP_LENGTH);
    34 STATIC_ASSERT(OP_JLE_LENGTH == OP_JUMP_LENGTH);
    35 STATIC_ASSERT(OP_JG_LENGTH == OP_JUMP_LENGTH);
    36 STATIC_ASSERT(OP_JGE_LENGTH == OP_JUMP_LENGTH);
    37 STATIC_ASSERT(OP_JEQ_LENGTH == OP_JUMP_LENGTH);
    38 STATIC_ASSERT(OP_JNE_LENGTH == OP_JUMP_LENGTH);
    39 STATIC_ASSERT(OP_JT_LENGTH == OP_JUMP_LENGTH);
    40 STATIC_ASSERT(OP_JF_LENGTH == OP_JUMP_LENGTH);
    41 
    42 void
    43 jc::Disassemble(Code *code, FILE *fp)
    44 {
    45     bytecode *pc = code->start();
    46     for (;;) {
    47         Opcode op = Opcode(*pc);
    48 
    49         fprintf(fp, "%-4d %s ", int(pc - code->start()), OpcodeInfo[op].name);
    50 
    51         switch (op) {
    52           case OP_NOP:
    53           case OP_RETURN:
    54           case OP_ADD:
    55           case OP_SUB:
    56           case OP_MUL:
    57           case OP_DIV:
    58           case OP_ADD_F:
    59           case OP_SUB_F:
    60           case OP_MUL_F:
    61           case OP_DIV_F:
    62           case OP_CVT_I2F:
    63           case OP_POP:
    64           case OP_LD_STA_I:
    65           case OP_LD_STA_P:
    66           case OP_ST_STA_I:
    67           case OP_BOUNDS_STA:
    68             break;
    69 
    70           case OP_STOP:
    71             fprintf(fp, "\n");
    72             return;
    73 
    74           case OP_INT:
    75             fprintf(fp, "%d", READ_INT32(pc));
    76             break;
    77 
    78           case OP_FLOAT:
    79             fprintf(fp, "%f", READ_FLOAT(pc));
    80             break;
    81 
    82           case OP_JL:
    83           case OP_JLE:
    84           case OP_JG:
    85           case OP_JGE:
    86           case OP_JEQ:
    87           case OP_JNE:
    88           case OP_JT:
    89           case OP_JF:
    90           case OP_JUMP:
    91             fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
    92             break;
    93 
    94           case OP_STACKARRAY:
    95           {
    96             unsigned width = pc[1];
    97             unsigned dims = pc[2];
    98 
    99             for (unsigned i = 0; i < dims; i++)
   100                 fprintf(fp, "[%u]", READ_UINT32(pc + 2 + (i * sizeof(unsigned))));
   101             fprintf(fp, " ; (width = %s)\n", (width == 1 ? "char" : "cell"));
   102             pc += 3 + dims * sizeof(unsigned);
   103             continue;
   104           }
   105 
   106           case OP_GETLOCAL:
   107           case OP_SETLOCAL:
   108           case OP_GETARG:
   109           case OP_SETARG:
   110           case OP_UNWIND:
   111             fprintf(fp, "%u", READ_UINT32(pc));
   112             break;
   113 
   114           case OP_CALLGLOBAL:
   115             fprintf(fp, "%u", READ_UINT32(pc));
   116             break;
   117 
   118           default:
   119             // Unknown opcode!
   120             assert(false);
   121             return;
   122         }
   123 
   124         fprintf(fp, "\n");
   125         pc += OpcodeInfo[op].length;
   126     }
   127 }