1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29#include "constants-mips.h"
30
31namespace assembler {
32namespace mips {
33
34namespace v8i = v8::internal;
35
36
37// -----------------------------------------------------------------------------
38// Registers
39
40
41// These register names are defined in a way to match the native disassembler
42// formatting. See for example the command "objdump -d <binary file>".
43const char* Registers::names_[kNumSimuRegisters] = {
44  "zero_reg",
45  "at",
46  "v0", "v1",
47  "a0", "a1", "a2", "a3",
48  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
49  "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
50  "t8", "t9",
51  "k0", "k1",
52  "gp",
53  "sp",
54  "fp",
55  "ra",
56  "LO", "HI",
57  "pc"
58};
59
60// List of alias names which can be used when referring to MIPS registers.
61const Registers::RegisterAlias Registers::aliases_[] = {
62  {0, "zero"},
63  {23, "cp"},
64  {30, "s8"},
65  {30, "s8_fp"},
66  {kInvalidRegister, NULL}
67};
68
69const char* Registers::Name(int reg) {
70  const char* result;
71  if ((0 <= reg) && (reg < kNumSimuRegisters)) {
72    result = names_[reg];
73  } else {
74    result = "noreg";
75  }
76  return result;
77}
78
79
80int Registers::Number(const char* name) {
81  // Look through the canonical names.
82  for (int i = 0; i < kNumSimuRegisters; i++) {
83    if (strcmp(names_[i], name) == 0) {
84      return i;
85    }
86  }
87
88  // Look through the alias names.
89  int i = 0;
90  while (aliases_[i].reg != kInvalidRegister) {
91    if (strcmp(aliases_[i].name, name) == 0) {
92      return aliases_[i].reg;
93    }
94    i++;
95  }
96
97  // No register with the reguested name found.
98  return kInvalidRegister;
99}
100
101
102const char* FPURegister::names_[kNumFPURegister] = {
103  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
104  "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
105  "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
106};
107
108// List of alias names which can be used when referring to MIPS registers.
109const FPURegister::RegisterAlias FPURegister::aliases_[] = {
110  {kInvalidRegister, NULL}
111};
112
113const char* FPURegister::Name(int creg) {
114  const char* result;
115  if ((0 <= creg) && (creg < kNumFPURegister)) {
116    result = names_[creg];
117  } else {
118    result = "nocreg";
119  }
120  return result;
121}
122
123
124int FPURegister::Number(const char* name) {
125  // Look through the canonical names.
126  for (int i = 0; i < kNumSimuRegisters; i++) {
127    if (strcmp(names_[i], name) == 0) {
128      return i;
129    }
130  }
131
132  // Look through the alias names.
133  int i = 0;
134  while (aliases_[i].creg != kInvalidRegister) {
135    if (strcmp(aliases_[i].name, name) == 0) {
136      return aliases_[i].creg;
137    }
138    i++;
139  }
140
141  // No Cregister with the reguested name found.
142  return kInvalidFPURegister;
143}
144
145
146// -----------------------------------------------------------------------------
147// Instruction
148
149bool Instruction::IsForbiddenInBranchDelay() {
150  int op = OpcodeFieldRaw();
151  switch (op) {
152    case J:
153    case JAL:
154    case BEQ:
155    case BNE:
156    case BLEZ:
157    case BGTZ:
158    case BEQL:
159    case BNEL:
160    case BLEZL:
161    case BGTZL:
162      return true;
163    case REGIMM:
164      switch (RtFieldRaw()) {
165        case BLTZ:
166        case BGEZ:
167        case BLTZAL:
168        case BGEZAL:
169          return true;
170        default:
171          return false;
172      };
173      break;
174    case SPECIAL:
175      switch (FunctionFieldRaw()) {
176        case JR:
177        case JALR:
178          return true;
179        default:
180          return false;
181      };
182      break;
183    default:
184      return false;
185  };
186}
187
188
189bool Instruction::IsLinkingInstruction() {
190  int op = OpcodeFieldRaw();
191  switch (op) {
192    case JAL:
193    case BGEZAL:
194    case BLTZAL:
195      return true;
196    case SPECIAL:
197      switch (FunctionFieldRaw()) {
198        case JALR:
199          return true;
200        default:
201          return false;
202      };
203    default:
204      return false;
205  };
206}
207
208
209bool Instruction::IsTrap() {
210  if (OpcodeFieldRaw() != SPECIAL) {
211    return false;
212  } else {
213    switch (FunctionFieldRaw()) {
214      case BREAK:
215      case TGE:
216      case TGEU:
217      case TLT:
218      case TLTU:
219      case TEQ:
220      case TNE:
221        return true;
222      default:
223        return false;
224    };
225  }
226}
227
228
229Instruction::Type Instruction::InstructionType() const {
230  switch (OpcodeFieldRaw()) {
231    case SPECIAL:
232      switch (FunctionFieldRaw()) {
233        case JR:
234        case JALR:
235        case BREAK:
236        case SLL:
237        case SRL:
238        case SRA:
239        case SLLV:
240        case SRLV:
241        case SRAV:
242        case MFHI:
243        case MFLO:
244        case MULT:
245        case MULTU:
246        case DIV:
247        case DIVU:
248        case ADD:
249        case ADDU:
250        case SUB:
251        case SUBU:
252        case AND:
253        case OR:
254        case XOR:
255        case NOR:
256        case SLT:
257        case SLTU:
258        case TGE:
259        case TGEU:
260        case TLT:
261        case TLTU:
262        case TEQ:
263        case TNE:
264          return kRegisterType;
265        default:
266          UNREACHABLE();
267      };
268      break;
269    case SPECIAL2:
270      switch (FunctionFieldRaw()) {
271        case MUL:
272          return kRegisterType;
273        default:
274          UNREACHABLE();
275      };
276      break;
277    case COP1:    // Coprocessor instructions
278      switch (FunctionFieldRaw()) {
279        case BC1:   // branch on coprocessor condition
280          return kImmediateType;
281        default:
282          return kRegisterType;
283      };
284      break;
285    // 16 bits Immediate type instructions. eg: addi dest, src, imm16
286    case REGIMM:
287    case BEQ:
288    case BNE:
289    case BLEZ:
290    case BGTZ:
291    case ADDI:
292    case ADDIU:
293    case SLTI:
294    case SLTIU:
295    case ANDI:
296    case ORI:
297    case XORI:
298    case LUI:
299    case BEQL:
300    case BNEL:
301    case BLEZL:
302    case BGTZL:
303    case LB:
304    case LW:
305    case LBU:
306    case SB:
307    case SW:
308    case LWC1:
309    case LDC1:
310    case SWC1:
311    case SDC1:
312      return kImmediateType;
313    // 26 bits immediate type instructions. eg: j imm26
314    case J:
315    case JAL:
316      return kJumpType;
317    default:
318      UNREACHABLE();
319  };
320  return kUnsupported;
321}
322
323} }   // namespace assembler::mips
324