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 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 // List of alias names which can be used when referring to MIPS registers. 62 const Registers::RegisterAlias Registers::aliases_[] = { 63 {0, "zero"}, 64 {23, "cp"}, 65 {30, "s8"}, 66 {30, "s8_fp"}, 67 {kInvalidRegister, NULL} 68 }; 69 70 const 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 81 int 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 103 const 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. 110 const FPURegisters::RegisterAlias FPURegisters::aliases_[] = { 111 {kInvalidRegister, NULL} 112 }; 113 114 const 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 125 int 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 150 bool 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 190 bool 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 216 bool 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 236 Instruction::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