1// Copyright 2011 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
30#if defined(V8_TARGET_ARCH_MIPS)
31
32#include "constants-mips.h"
33
34namespace v8 {
35namespace internal {
36
37
38// -----------------------------------------------------------------------------
39// Registers.
40
41
42// These register names are defined in a way to match the native disassembler
43// formatting. See for example the command "objdump -d <binary file>".
44const char* Registers::names_[kNumSimuRegisters] = {
45  "zero_reg",
46  "at",
47  "v0", "v1",
48  "a0", "a1", "a2", "a3",
49  "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
50  "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
51  "t8", "t9",
52  "k0", "k1",
53  "gp",
54  "sp",
55  "fp",
56  "ra",
57  "LO", "HI",
58  "pc"
59};
60
61// List of alias names which can be used when referring to MIPS registers.
62const Registers::RegisterAlias Registers::aliases_[] = {
63  {0, "zero"},
64  {23, "cp"},
65  {30, "s8"},
66  {30, "s8_fp"},
67  {kInvalidRegister, NULL}
68};
69
70const char* Registers::Name(int reg) {
71  const char* result;
72  if ((0 <= reg) && (reg < kNumSimuRegisters)) {
73    result = names_[reg];
74  } else {
75    result = "noreg";
76  }
77  return result;
78}
79
80
81int Registers::Number(const char* name) {
82  // Look through the canonical names.
83  for (int i = 0; i < kNumSimuRegisters; i++) {
84    if (strcmp(names_[i], name) == 0) {
85      return i;
86    }
87  }
88
89  // Look through the alias names.
90  int i = 0;
91  while (aliases_[i].reg != kInvalidRegister) {
92    if (strcmp(aliases_[i].name, name) == 0) {
93      return aliases_[i].reg;
94    }
95    i++;
96  }
97
98  // No register with the reguested name found.
99  return kInvalidRegister;
100}
101
102
103const char* FPURegisters::names_[kNumFPURegisters] = {
104  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
105  "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
106  "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
107};
108
109// List of alias names which can be used when referring to MIPS registers.
110const FPURegisters::RegisterAlias FPURegisters::aliases_[] = {
111  {kInvalidRegister, NULL}
112};
113
114const char* FPURegisters::Name(int creg) {
115  const char* result;
116  if ((0 <= creg) && (creg < kNumFPURegisters)) {
117    result = names_[creg];
118  } else {
119    result = "nocreg";
120  }
121  return result;
122}
123
124
125int FPURegisters::Number(const char* name) {
126  // Look through the canonical names.
127  for (int i = 0; i < kNumFPURegisters; i++) {
128    if (strcmp(names_[i], name) == 0) {
129      return i;
130    }
131  }
132
133  // Look through the alias names.
134  int i = 0;
135  while (aliases_[i].creg != kInvalidRegister) {
136    if (strcmp(aliases_[i].name, name) == 0) {
137      return aliases_[i].creg;
138    }
139    i++;
140  }
141
142  // No Cregister with the reguested name found.
143  return kInvalidFPURegister;
144}
145
146
147// -----------------------------------------------------------------------------
148// Instructions.
149
150bool Instruction::IsForbiddenInBranchDelay() const {
151  const int op = OpcodeFieldRaw();
152  switch (op) {
153    case J:
154    case JAL:
155    case BEQ:
156    case BNE:
157    case BLEZ:
158    case BGTZ:
159    case BEQL:
160    case BNEL:
161    case BLEZL:
162    case BGTZL:
163      return true;
164    case REGIMM:
165      switch (RtFieldRaw()) {
166        case BLTZ:
167        case BGEZ:
168        case BLTZAL:
169        case BGEZAL:
170          return true;
171        default:
172          return false;
173      };
174      break;
175    case SPECIAL:
176      switch (FunctionFieldRaw()) {
177        case JR:
178        case JALR:
179          return true;
180        default:
181          return false;
182      };
183      break;
184    default:
185      return false;
186  };
187}
188
189
190bool Instruction::IsLinkingInstruction() const {
191  const int op = OpcodeFieldRaw();
192  switch (op) {
193    case JAL:
194      return true;
195    case REGIMM:
196      switch (RtFieldRaw()) {
197        case BGEZAL:
198        case BLTZAL:
199          return true;
200      default:
201        return false;
202      };
203    case SPECIAL:
204      switch (FunctionFieldRaw()) {
205        case JALR:
206          return true;
207        default:
208          return false;
209      };
210    default:
211      return false;
212  };
213}
214
215
216bool Instruction::IsTrap() const {
217  if (OpcodeFieldRaw() != SPECIAL) {
218    return false;
219  } else {
220    switch (FunctionFieldRaw()) {
221      case BREAK:
222      case TGE:
223      case TGEU:
224      case TLT:
225      case TLTU:
226      case TEQ:
227      case TNE:
228        return true;
229      default:
230        return false;
231    };
232  }
233}
234
235
236Instruction::Type Instruction::InstructionType() const {
237  switch (OpcodeFieldRaw()) {
238    case SPECIAL:
239      switch (FunctionFieldRaw()) {
240        case JR:
241        case JALR:
242        case BREAK:
243        case SLL:
244        case SRL:
245        case SRA:
246        case SLLV:
247        case SRLV:
248        case SRAV:
249        case MFHI:
250        case MFLO:
251        case MULT:
252        case MULTU:
253        case DIV:
254        case DIVU:
255        case ADD:
256        case ADDU:
257        case SUB:
258        case SUBU:
259        case AND:
260        case OR:
261        case XOR:
262        case NOR:
263        case SLT:
264        case SLTU:
265        case TGE:
266        case TGEU:
267        case TLT:
268        case TLTU:
269        case TEQ:
270        case TNE:
271        case MOVZ:
272        case MOVN:
273        case MOVCI:
274          return kRegisterType;
275        default:
276          return kUnsupported;
277      };
278      break;
279    case SPECIAL2:
280      switch (FunctionFieldRaw()) {
281        case MUL:
282        case CLZ:
283          return kRegisterType;
284        default:
285          return kUnsupported;
286      };
287      break;
288    case SPECIAL3:
289      switch (FunctionFieldRaw()) {
290        case INS:
291        case EXT:
292          return kRegisterType;
293        default:
294          return kUnsupported;
295      };
296      break;
297    case COP1:    // Coprocessor instructions.
298      switch (RsFieldRawNoAssert()) {
299        case BC1:   // Branch on coprocessor condition.
300          return kImmediateType;
301        default:
302          return kRegisterType;
303      };
304      break;
305    // 16 bits Immediate type instructions. e.g.: addi dest, src, imm16.
306    case REGIMM:
307    case BEQ:
308    case BNE:
309    case BLEZ:
310    case BGTZ:
311    case ADDI:
312    case ADDIU:
313    case SLTI:
314    case SLTIU:
315    case ANDI:
316    case ORI:
317    case XORI:
318    case LUI:
319    case BEQL:
320    case BNEL:
321    case BLEZL:
322    case BGTZL:
323    case LB:
324    case LH:
325    case LWL:
326    case LW:
327    case LBU:
328    case LHU:
329    case LWR:
330    case SB:
331    case SH:
332    case SWL:
333    case SW:
334    case SWR:
335    case LWC1:
336    case LDC1:
337    case SWC1:
338    case SDC1:
339      return kImmediateType;
340    // 26 bits immediate type instructions. e.g.: j imm26.
341    case J:
342    case JAL:
343      return kJumpType;
344    default:
345      return kUnsupported;
346  };
347  return kUnsupported;
348}
349
350
351} }   // namespace v8::internal
352
353#endif  // V8_TARGET_ARCH_MIPS
354