324 lines
7.4 KiB
C++
324 lines
7.4 KiB
C++
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions are
|
||
|
// met:
|
||
|
//
|
||
|
// * Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
// * Redistributions in binary form must reproduce the above
|
||
|
// copyright notice, this list of conditions and the following
|
||
|
// disclaimer in the documentation and/or other materials provided
|
||
|
// with the distribution.
|
||
|
// * Neither the name of Google Inc. nor the names of its
|
||
|
// contributors may be used to endorse or promote products derived
|
||
|
// from this software without specific prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
#include "v8.h"
|
||
|
#include "constants-mips.h"
|
||
|
|
||
|
namespace assembler {
|
||
|
namespace mips {
|
||
|
|
||
|
namespace v8i = v8::internal;
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Registers
|
||
|
|
||
|
|
||
|
// These register names are defined in a way to match the native disassembler
|
||
|
// formatting. See for example the command "objdump -d <binary file>".
|
||
|
const char* Registers::names_[kNumSimuRegisters] = {
|
||
|
"zero_reg",
|
||
|
"at",
|
||
|
"v0", "v1",
|
||
|
"a0", "a1", "a2", "a3",
|
||
|
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||
|
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||
|
"t8", "t9",
|
||
|
"k0", "k1",
|
||
|
"gp",
|
||
|
"sp",
|
||
|
"fp",
|
||
|
"ra",
|
||
|
"LO", "HI",
|
||
|
"pc"
|
||
|
};
|
||
|
|
||
|
// List of alias names which can be used when referring to MIPS registers.
|
||
|
const Registers::RegisterAlias Registers::aliases_[] = {
|
||
|
{0, "zero"},
|
||
|
{23, "cp"},
|
||
|
{30, "s8"},
|
||
|
{30, "s8_fp"},
|
||
|
{kInvalidRegister, NULL}
|
||
|
};
|
||
|
|
||
|
const char* Registers::Name(int reg) {
|
||
|
const char* result;
|
||
|
if ((0 <= reg) && (reg < kNumSimuRegisters)) {
|
||
|
result = names_[reg];
|
||
|
} else {
|
||
|
result = "noreg";
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int Registers::Number(const char* name) {
|
||
|
// Look through the canonical names.
|
||
|
for (int i = 0; i < kNumSimuRegisters; i++) {
|
||
|
if (strcmp(names_[i], name) == 0) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Look through the alias names.
|
||
|
int i = 0;
|
||
|
while (aliases_[i].reg != kInvalidRegister) {
|
||
|
if (strcmp(aliases_[i].name, name) == 0) {
|
||
|
return aliases_[i].reg;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// No register with the reguested name found.
|
||
|
return kInvalidRegister;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* FPURegister::names_[kNumFPURegister] = {
|
||
|
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
|
||
|
"f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
|
||
|
"f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
|
||
|
};
|
||
|
|
||
|
// List of alias names which can be used when referring to MIPS registers.
|
||
|
const FPURegister::RegisterAlias FPURegister::aliases_[] = {
|
||
|
{kInvalidRegister, NULL}
|
||
|
};
|
||
|
|
||
|
const char* FPURegister::Name(int creg) {
|
||
|
const char* result;
|
||
|
if ((0 <= creg) && (creg < kNumFPURegister)) {
|
||
|
result = names_[creg];
|
||
|
} else {
|
||
|
result = "nocreg";
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int FPURegister::Number(const char* name) {
|
||
|
// Look through the canonical names.
|
||
|
for (int i = 0; i < kNumSimuRegisters; i++) {
|
||
|
if (strcmp(names_[i], name) == 0) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Look through the alias names.
|
||
|
int i = 0;
|
||
|
while (aliases_[i].creg != kInvalidRegister) {
|
||
|
if (strcmp(aliases_[i].name, name) == 0) {
|
||
|
return aliases_[i].creg;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// No Cregister with the reguested name found.
|
||
|
return kInvalidFPURegister;
|
||
|
}
|
||
|
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Instruction
|
||
|
|
||
|
bool Instruction::IsForbiddenInBranchDelay() {
|
||
|
int op = OpcodeFieldRaw();
|
||
|
switch (op) {
|
||
|
case J:
|
||
|
case JAL:
|
||
|
case BEQ:
|
||
|
case BNE:
|
||
|
case BLEZ:
|
||
|
case BGTZ:
|
||
|
case BEQL:
|
||
|
case BNEL:
|
||
|
case BLEZL:
|
||
|
case BGTZL:
|
||
|
return true;
|
||
|
case REGIMM:
|
||
|
switch (RtFieldRaw()) {
|
||
|
case BLTZ:
|
||
|
case BGEZ:
|
||
|
case BLTZAL:
|
||
|
case BGEZAL:
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
break;
|
||
|
case SPECIAL:
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case JR:
|
||
|
case JALR:
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
break;
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Instruction::IsLinkingInstruction() {
|
||
|
int op = OpcodeFieldRaw();
|
||
|
switch (op) {
|
||
|
case JAL:
|
||
|
case BGEZAL:
|
||
|
case BLTZAL:
|
||
|
return true;
|
||
|
case SPECIAL:
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case JALR:
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Instruction::IsTrap() {
|
||
|
if (OpcodeFieldRaw() != SPECIAL) {
|
||
|
return false;
|
||
|
} else {
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case BREAK:
|
||
|
case TGE:
|
||
|
case TGEU:
|
||
|
case TLT:
|
||
|
case TLTU:
|
||
|
case TEQ:
|
||
|
case TNE:
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Instruction::Type Instruction::InstructionType() const {
|
||
|
switch (OpcodeFieldRaw()) {
|
||
|
case SPECIAL:
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case JR:
|
||
|
case JALR:
|
||
|
case BREAK:
|
||
|
case SLL:
|
||
|
case SRL:
|
||
|
case SRA:
|
||
|
case SLLV:
|
||
|
case SRLV:
|
||
|
case SRAV:
|
||
|
case MFHI:
|
||
|
case MFLO:
|
||
|
case MULT:
|
||
|
case MULTU:
|
||
|
case DIV:
|
||
|
case DIVU:
|
||
|
case ADD:
|
||
|
case ADDU:
|
||
|
case SUB:
|
||
|
case SUBU:
|
||
|
case AND:
|
||
|
case OR:
|
||
|
case XOR:
|
||
|
case NOR:
|
||
|
case SLT:
|
||
|
case SLTU:
|
||
|
case TGE:
|
||
|
case TGEU:
|
||
|
case TLT:
|
||
|
case TLTU:
|
||
|
case TEQ:
|
||
|
case TNE:
|
||
|
return kRegisterType;
|
||
|
default:
|
||
|
UNREACHABLE();
|
||
|
};
|
||
|
break;
|
||
|
case SPECIAL2:
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case MUL:
|
||
|
return kRegisterType;
|
||
|
default:
|
||
|
UNREACHABLE();
|
||
|
};
|
||
|
break;
|
||
|
case COP1: // Coprocessor instructions
|
||
|
switch (FunctionFieldRaw()) {
|
||
|
case BC1: // branch on coprocessor condition
|
||
|
return kImmediateType;
|
||
|
default:
|
||
|
return kRegisterType;
|
||
|
};
|
||
|
break;
|
||
|
// 16 bits Immediate type instructions. eg: addi dest, src, imm16
|
||
|
case REGIMM:
|
||
|
case BEQ:
|
||
|
case BNE:
|
||
|
case BLEZ:
|
||
|
case BGTZ:
|
||
|
case ADDI:
|
||
|
case ADDIU:
|
||
|
case SLTI:
|
||
|
case SLTIU:
|
||
|
case ANDI:
|
||
|
case ORI:
|
||
|
case XORI:
|
||
|
case LUI:
|
||
|
case BEQL:
|
||
|
case BNEL:
|
||
|
case BLEZL:
|
||
|
case BGTZL:
|
||
|
case LB:
|
||
|
case LW:
|
||
|
case LBU:
|
||
|
case SB:
|
||
|
case SW:
|
||
|
case LWC1:
|
||
|
case LDC1:
|
||
|
case SWC1:
|
||
|
case SDC1:
|
||
|
return kImmediateType;
|
||
|
// 26 bits immediate type instructions. eg: j imm26
|
||
|
case J:
|
||
|
case JAL:
|
||
|
return kJumpType;
|
||
|
default:
|
||
|
UNREACHABLE();
|
||
|
};
|
||
|
return kUnsupported;
|
||
|
}
|
||
|
|
||
|
} } // namespace assembler::mips
|