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