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
31 namespace assembler {
32 namespace mips {
33
34 namespace 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>".
43 const 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.
61 const Registers::RegisterAlias Registers::aliases_[] = {
62 {0, "zero"},
63 {23, "cp"},
64 {30, "s8"},
65 {30, "s8_fp"},
66 {kInvalidRegister, NULL}
67 };
68
Name(int reg)69 const 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
Number(const char * name)80 int 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
102 const 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.
109 const FPURegister::RegisterAlias FPURegister::aliases_[] = {
110 {kInvalidRegister, NULL}
111 };
112
Name(int creg)113 const 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
Number(const char * name)124 int 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
IsForbiddenInBranchDelay()149 bool 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
IsLinkingInstruction()189 bool 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
IsTrap()209 bool 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
InstructionType() const229 Instruction::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