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