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