Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #ifndef V8_MIPS_CONSTANTS_H_ | |
| 2 #define V8_MIPS_CONSTANTS_H_ | |
| 3 | |
| 4 // UNIMPLEMENTED_ macro for MIPS. | |
| 5 #define UNIMPLEMENTED_() \ | |
| 6 printf("%s, \tline %d: \tfunction %s not implemented. \n",__FILE__, __LINE__, __func__); | |
| 7 | |
| 8 // Defines constants and accessor classes to assemble, disassemble and | |
| 9 // simulate MIPS32 instructions. | |
| 10 // | |
| 11 // See MIPS32® Architecture For Programmers | |
| 12 // Volume II: The MIPS32® Instruction Set | |
| 13 // ( http://web.asic.sdesigns.com/tools/libs/mips/doc/74K/doc/MIPS32-ISA.pdf ) | |
|
Søren Thygesen Gjesse
2010/01/19 22:59:12
This link seems not to work. How about using a www
Alexandre
2010/01/22 23:08:42
Added a functional link and a comment. I doubt it
| |
| 14 | |
| 15 namespace assembler { | |
| 16 namespace mips { | |
| 17 | |
| 18 // ----------------------------------------------------------------------------- | |
| 19 // Registers and CRegisters | |
| 20 | |
| 21 // Number of general purpose registers | |
| 22 static const int kNumRegisters = 32; | |
| 23 static const int kInvalidRegister = -1; | |
| 24 | |
| 25 // In the simulator, the PC register is simulated as the 34th register | |
| 26 static const int kPCRegister = 34; | |
| 27 | |
| 28 // Number coprocessor registers | |
| 29 static const int kNumCRegisters = 32; | |
| 30 static const int kInvalidCRegister = -1; | |
| 31 | |
| 32 // Helper functions for converting between register numbers and names. | |
| 33 class Registers { | |
| 34 public: | |
| 35 // Return the name of the register. | |
| 36 static const char* Name(int reg); | |
| 37 | |
| 38 // Lookup the register number for the name provided. | |
| 39 static int Number(const char* name); | |
| 40 | |
| 41 struct RegisterAlias { | |
| 42 int reg; | |
| 43 const char *name; | |
| 44 }; | |
| 45 | |
| 46 static int32_t max_val() { return max_val_; } | |
| 47 static int32_t min_val() { return min_val_; } | |
| 48 | |
| 49 private: | |
| 50 static const int32_t max_val_ = 0x7fffffff; | |
| 51 static const int32_t min_val_ = 0x80000000; | |
| 52 | |
| 53 static const char* names_[kNumRegisters]; | |
| 54 static const RegisterAlias aliases_[]; | |
| 55 }; | |
| 56 | |
| 57 // Helper functions for converting between register numbers and names. | |
| 58 class CRegisters { | |
| 59 public: | |
| 60 // Return the name of the register. | |
| 61 static const char* Name(int reg); | |
| 62 | |
| 63 // Lookup the register number for the name provided. | |
| 64 static int Number(const char* name); | |
| 65 | |
| 66 struct RegisterAlias { | |
| 67 int creg; | |
| 68 const char *name; | |
| 69 }; | |
| 70 | |
| 71 private: | |
| 72 | |
| 73 static const char* names_[kNumCRegisters]; | |
| 74 static const RegisterAlias aliases_[]; | |
| 75 }; | |
| 76 | |
| 77 | |
| 78 // ----------------------------------------------------------------------------- | |
| 79 // Instructions encoding constants. | |
| 80 | |
| 81 // On MIPS all instructions are 32 bits. | |
| 82 typedef int32_t Instr; | |
| 83 | |
| 84 typedef unsigned char byte; | |
| 85 | |
| 86 // ----- Fields offset (_o) and length (_l) | |
| 87 static const int opcode_o = 26; | |
| 88 static const int opcode_l = 6; | |
| 89 static const int rs_o = 21; | |
| 90 static const int rs_l = 5; | |
| 91 static const int rt_o = 16; | |
| 92 static const int rt_l = 5; | |
| 93 static const int rd_o = 11; | |
| 94 static const int rd_l = 5; | |
| 95 static const int sa_o = 6; | |
| 96 static const int sa_l = 5; | |
| 97 static const int function_o = 0; | |
| 98 static const int function_l = 6; | |
| 99 | |
| 100 static const int imm16_o = 0; | |
| 101 static const int imm16_l = 16; | |
| 102 static const int imm26_o = 0; | |
| 103 static const int imm26_l = 26; | |
| 104 | |
| 105 // ----- MIPS Opcodes and Function Fields | |
| 106 // We use this presentation to stay close to the table representation in | |
| 107 // MIPS32® Architecture For Programmers, Volume II: The MIPS32® Instruction Set | |
| 108 enum Opcode { | |
| 109 SPECIAL = 0 << opcode_o, | |
| 110 REGIMM = 1 << opcode_o, | |
| 111 | |
| 112 J = ( (0<<3) + 2 ) << opcode_o, | |
|
Søren Thygesen Gjesse
2010/01/19 22:59:12
Formatting like ((0 << 3) + 2) << opcode_o matches
Alexandre
2010/01/22 23:08:42
Style issue fixed.
On 2010/01/19 22:59:12, Søren G
| |
| 113 JAL = ( (0<<3) + 3 ) << opcode_o, | |
| 114 BEQ = ( (0<<3) + 4 ) << opcode_o, | |
| 115 BNE = ( (0<<3) + 5 ) << opcode_o, | |
| 116 BLEZ = ( (0<<3) + 6 ) << opcode_o, | |
| 117 BGTZ = ( (0<<3) + 7 ) << opcode_o, | |
| 118 | |
| 119 ADDI = ( (1<<3) + 0 ) << opcode_o, | |
| 120 ADDIU = ( (1<<3) + 1 ) << opcode_o, | |
| 121 SLTI = ( (1<<3) + 2 ) << opcode_o, | |
| 122 SLTIU = ( (1<<3) + 3 ) << opcode_o, | |
| 123 ANDI = ( (1<<3) + 4 ) << opcode_o, | |
| 124 ORI = ( (1<<3) + 5 ) << opcode_o, | |
| 125 XORI = ( (1<<3) + 6 ) << opcode_o, | |
| 126 LUI = ( (1<<3) + 7 ) << opcode_o, | |
| 127 | |
| 128 COP1 = ( (2<<3) + 1 ) << opcode_o, // Coprocessor 1 class (floating p oint) | |
|
Søren Thygesen Gjesse
2010/01/19 22:59:12
Long line.
Alexandre
2010/01/22 23:08:42
Style issue fixed.
On 2010/01/19 22:59:12, Søren G
| |
| 129 BEQL = ( (2<<3) + 4 ) << opcode_o, | |
| 130 BNEL = ( (2<<3) + 5 ) << opcode_o, | |
| 131 BLEZL = ( (2<<3) + 6 ) << opcode_o, | |
| 132 BGTZL = ( (2<<3) + 7 ) << opcode_o, | |
| 133 | |
| 134 SPECIAL2 = ( (3<<3) + 4 ) << opcode_o, | |
| 135 | |
| 136 LB = ( (4<<3) + 0 ) << opcode_o, | |
| 137 LW = ( (4<<3) + 3 ) << opcode_o, | |
| 138 LBU = ( (4<<3) + 4 ) << opcode_o, | |
| 139 SB = ( (5<<3) + 0 ) << opcode_o, | |
| 140 SW = ( (5<<3) + 3 ) << opcode_o, | |
| 141 | |
| 142 LWC1 = ( (6<<3) + 1 ) << opcode_o, | |
| 143 LDC1 = ( (6<<3) + 5 ) << opcode_o, | |
| 144 | |
| 145 SWC1 = ( (7<<3) + 1 ) << opcode_o, | |
| 146 SDC1 = ( (7<<3) + 5 ) << opcode_o | |
| 147 }; | |
| 148 | |
| 149 enum SecondaryField { | |
| 150 // SPECIAL Encoding of Function Field | |
| 151 SLL = ( (0<<3) + 0 ), | |
| 152 SRL = ( (0<<3) + 2 ), | |
| 153 SRA = ( (0<<3) + 3 ), | |
| 154 SLLV = ( (0<<3) + 4 ), | |
| 155 SRLV = ( (0<<3) + 6 ), | |
| 156 SRAV = ( (0<<3) + 7 ), | |
| 157 | |
| 158 JR = ( (1<<3) + 0 ), | |
| 159 JALR = ( (1<<3) + 1 ), | |
| 160 BREAK = ( (1<<3) + 5 ), | |
| 161 | |
| 162 MFHI = ( (2<<3) + 0 ), | |
| 163 MFLO = ( (2<<3) + 2 ), | |
| 164 | |
| 165 MULT = ( (3<<3) + 0 ), | |
| 166 MULTU = ( (3<<3) + 1 ), | |
| 167 DIV = ( (3<<3) + 2 ), | |
| 168 DIVU = ( (3<<3) + 3 ), | |
| 169 | |
| 170 ADD = ( (4<<3) + 0 ), | |
| 171 ADDU = ( (4<<3) + 1 ), | |
| 172 SUB = ( (4<<3) + 2 ), | |
| 173 SUBU = ( (4<<3) + 3 ), | |
| 174 AND = ( (4<<3) + 4 ), | |
| 175 OR = ( (4<<3) + 5 ), | |
| 176 XOR = ( (4<<3) + 6 ), | |
| 177 NOR = ( (4<<3) + 7 ), | |
| 178 | |
| 179 SLT = ( (5<<3) + 2 ), | |
| 180 SLTU = ( (5<<3) + 3 ), | |
| 181 | |
| 182 TGE = ( (6<<3) + 0 ), | |
| 183 TGEU = ( (6<<3) + 1 ), | |
| 184 TLT = ( (6<<3) + 2 ), | |
| 185 TLTU = ( (6<<3) + 3 ), | |
| 186 TEQ = ( (6<<3) + 4 ), | |
| 187 TNE = ( (6<<3) + 6 ), | |
| 188 | |
| 189 // SPECIAL2 Encoding of Function Field | |
| 190 MUL = ( (0<<3) + 2 ), | |
| 191 | |
| 192 // REGIMM encoding of rt Field | |
| 193 BLTZ = ( (0<<3) + 0 ) << 16, | |
| 194 BGEZ = ( (0<<3) + 1 ) << 16, | |
| 195 BLTZAL = ( (2<<3) + 0 ) << 16, | |
| 196 BGEZAL = ( (2<<3) + 1 ) << 16, | |
| 197 | |
| 198 // COP1 Encoding of rs Field | |
| 199 MFC1 = ( (0<<3) + 0 ) << 21, | |
| 200 MFHC1 = ( (0<<3) + 3 ) << 21, | |
| 201 MTC1 = ( (0<<3) + 4 ) << 21, | |
| 202 MTHC1 = ( (0<<3) + 7 ) << 21, | |
| 203 BC1 = ( (1<<3) + 0 ) << 21, | |
| 204 S = ( (2<<3) + 0 ) << 21, | |
| 205 D = ( (2<<3) + 1 ) << 21, | |
| 206 W = ( (2<<3) + 4 ) << 21, | |
| 207 L = ( (2<<3) + 5 ) << 21, | |
| 208 PS = ( (2<<3) + 6 ) << 21, | |
| 209 // COP1 Encoding of Function Field When rs=S | |
| 210 CVT_D_S = ( (4<<3) + 1 ), | |
| 211 CVT_W_S = ( (4<<3) + 4 ), | |
| 212 CVT_L_S = ( (4<<3) + 5 ), | |
| 213 CVT_PS_S = ( (4<<3) + 6 ), | |
| 214 // COP1 Encoding of Function Field When rs=D | |
| 215 CVT_S_D = ( (4<<3) + 0 ), | |
| 216 CVT_W_D = ( (4<<3) + 4 ), | |
| 217 CVT_L_D = ( (4<<3) + 5 ), | |
| 218 // COP1 Encoding of Function Field When rs=W or L | |
| 219 CVT_S_W = ( (4<<3) + 0 ), | |
| 220 CVT_D_W = ( (4<<3) + 1 ), | |
| 221 CVT_S_L = ( (4<<3) + 0 ), | |
| 222 CVT_D_L = ( (4<<3) + 1 ), | |
| 223 // COP1 Encoding of Function Field When rs=PS | |
| 224 | |
| 225 NULLSF = 0 | |
| 226 }; | |
| 227 | |
| 228 // ----- Miscellianous useful masks. | |
| 229 enum { | |
| 230 // Instruction bit masks | |
| 231 OpcodeMask = 0x3f << opcode_o, | |
| 232 Imm16Mask = 0xffff, | |
| 233 Imm26Mask = 0x3fffffff, | |
| 234 rsFieldMask = 0x1f << rs_o, | |
| 235 rtFieldMask = 0x1f << rt_o, | |
| 236 rdFieldMask = 0x1f << rd_o, | |
| 237 saFieldMask = 0x1f << sa_o, | |
| 238 functionFieldMask = 0x3f << function_o, | |
| 239 // Misc masks | |
| 240 HIMask = 0xffff << 16, | |
| 241 LOMask = 0xffff, | |
| 242 signMask = 0x80000000 | |
| 243 }; | |
| 244 | |
| 245 | |
| 246 // ----- Emulated conditions | |
| 247 // On MIPS we use this enum to abstract from conditionnal branch instructions. | |
| 248 // the 'U' prefix is used to specify unsigned comparisons. | |
| 249 enum Condition { | |
| 250 // any value < 0 is considered no_condition | |
| 251 no_condition = -1, | |
| 252 | |
| 253 overflow = 0, | |
| 254 no_overflow = 1, | |
| 255 Uless = 2, | |
| 256 Ugreater_equal= 3, | |
| 257 equal = 4, | |
| 258 not_equal = 5, | |
| 259 Uless_equal = 6, | |
| 260 Ugreater = 7, | |
| 261 negative = 8, | |
| 262 positive = 9, | |
| 263 parity_even = 10, | |
| 264 parity_odd = 11, | |
| 265 less = 12, | |
| 266 greater_equal = 13, | |
| 267 less_equal = 14, | |
| 268 greater = 15, | |
| 269 | |
| 270 cc_always = 16, | |
| 271 | |
| 272 // aliases | |
| 273 carry = Uless, | |
| 274 not_carry = Ugreater_equal, | |
| 275 zero = equal, | |
| 276 eq = equal, | |
| 277 not_zero = not_equal, | |
| 278 ne = not_equal, | |
| 279 sign = negative, | |
| 280 not_sign = positive, | |
| 281 | |
| 282 cc_default = no_condition | |
| 283 }; | |
| 284 | |
| 285 // ----- Coprocessor conditions | |
| 286 enum C_Condition { | |
| 287 F, // False | |
| 288 UN, // Unordered | |
| 289 EQ, // Equal | |
| 290 UEQ, // Unordered or Equal | |
| 291 OLT, // Ordered or Less Than | |
| 292 ULT, // Unordered or Less Than | |
| 293 OLE, // Ordered or Less Than or Equal | |
| 294 ULE // Unordered or Less Than or Equal | |
| 295 }; | |
| 296 | |
| 297 | |
| 298 // The class Instruction enables access to individual fields defined in the ARM | |
| 299 // architecture instruction set encoding as described in figure A3-1. | |
| 300 // | |
| 301 // Example: Test whether the instruction at ptr does set the condition code | |
| 302 // bits. | |
| 303 // | |
| 304 // bool InstructionSetsConditionCodes(byte* ptr) { | |
| 305 // Instruction* instr = Instruction::At(ptr); | |
| 306 // int type = instr->TypeField(); | |
| 307 // return ((type == 0) || (type == 1)) && instr->HasS(); | |
| 308 // } | |
| 309 // | |
| 310 class Instruction { | |
| 311 public: | |
| 312 enum { | |
| 313 kInstructionSize = 4, | |
| 314 kInstructionSizeLog2 = 2, | |
| 315 // On MIPS PC cannot actually be directly accessed. We behave as if PC was | |
| 316 // always the value of the current instruction being exectued. | |
| 317 kPCReadOffset = 0 | |
| 318 }; | |
| 319 | |
| 320 // Get the raw instruction bits. | |
| 321 inline Instr InstructionBits() const { | |
| 322 return *reinterpret_cast<const Instr*>(this); | |
| 323 } | |
| 324 | |
| 325 // Set the raw instruction bits to value. | |
| 326 inline void SetInstructionBits(Instr value) { | |
| 327 *reinterpret_cast<Instr*>(this) = value; | |
| 328 } | |
| 329 | |
| 330 // Read one particular bit out of the instruction bits. | |
| 331 inline int Bit(int nr) const { | |
| 332 return (InstructionBits() >> nr) & 1; | |
| 333 } | |
| 334 | |
| 335 // Read a bit field out of the instruction bits. | |
| 336 inline int Bits(int hi, int lo) const { | |
| 337 return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1); | |
| 338 } | |
| 339 | |
| 340 | |
| 341 // Accessors for the different named fields used in the MIPS encoding. | |
| 342 // Generally applicable fields | |
| 343 | |
| 344 // Fields used in Data processing instructions | |
| 345 inline Opcode OpcodeField() const { | |
| 346 return static_cast<Opcode>(Bits(opcode_o+opcode_l-1, opcode_o)); | |
| 347 } | |
| 348 | |
| 349 inline int rsField() const { | |
| 350 return Bits(rs_o+rs_l-1, rs_o); | |
|
Søren Thygesen Gjesse
2010/01/19 22:59:12
Format expression with spaces rs_o + rs_l - 1.
Alexandre
2010/01/22 23:08:42
Style issue fixed.
On 2010/01/19 22:59:12, Søren G
| |
| 351 } | |
| 352 | |
| 353 inline int rtField() const { | |
| 354 return Bits(rt_o+rt_l-1, rt_o); | |
| 355 } | |
| 356 | |
| 357 inline int rdField() const { | |
| 358 return Bits(rd_o+rd_l-1, rd_o); | |
| 359 } | |
| 360 | |
| 361 inline int saField() const { | |
| 362 return Bits(sa_o+sa_l-1, sa_o); | |
| 363 } | |
| 364 | |
| 365 inline int functionField() const { | |
| 366 return Bits(function_o+function_l-1, function_o); | |
| 367 } | |
| 368 | |
| 369 // Return the fields at their original place in the instruction encoding. | |
| 370 inline Opcode OpcodeFieldRaw() const { | |
| 371 return static_cast<Opcode>(InstructionBits() & OpcodeMask); | |
| 372 } | |
| 373 | |
| 374 inline int rsFieldRaw() const { | |
| 375 return InstructionBits() & rsFieldMask; | |
| 376 } | |
| 377 | |
| 378 inline int rtFieldRaw() const { | |
| 379 return InstructionBits() & rtFieldMask; | |
| 380 } | |
| 381 | |
| 382 inline int rdFieldRaw() const { | |
| 383 return InstructionBits() & rdFieldMask; | |
| 384 } | |
| 385 | |
| 386 inline int saFieldRaw() const { | |
| 387 return InstructionBits() & saFieldMask; | |
| 388 } | |
| 389 | |
| 390 inline int functionFieldRaw() const { | |
| 391 return InstructionBits() & functionFieldMask; | |
| 392 } | |
| 393 | |
| 394 // Get the secondary field according to the opcode. | |
| 395 inline int secondaryField() const { | |
| 396 Opcode op = OpcodeFieldRaw(); | |
| 397 switch (op) { | |
| 398 case SPECIAL: | |
| 399 case SPECIAL2: | |
| 400 return functionField(); | |
| 401 break; | |
|
antonm
2010/01/21 13:10:45
why break after return?
Alexandre
2010/01/22 23:08:42
Fixed.
On 2010/01/21 13:10:45, antonm wrote:
| |
| 402 case COP1: | |
| 403 return rsField(); | |
| 404 break; | |
| 405 case REGIMM: | |
| 406 return rtField(); | |
| 407 break; | |
| 408 default: | |
| 409 return NULLSF; | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 inline int32_t Imm16Field() const { | |
| 414 return Bits(imm16_o+imm16_l-1, imm16_o); | |
| 415 } | |
| 416 | |
| 417 inline int32_t Imm26Field() const { | |
| 418 return Bits(imm16_o+imm26_l-1, imm26_o); | |
| 419 } | |
| 420 | |
| 421 // Say if the instruction should not be used in a branch delay slot. | |
| 422 bool isForbiddenInBranchDelay(); | |
| 423 // Say if the instruction 'links'. eg: jal, bal | |
| 424 bool isLinkingInstruction(); | |
| 425 | |
| 426 // Get the encoding type of the instruction. | |
| 427 // type 1 is imm16 type | |
| 428 // type 2 is register type | |
| 429 // type 3 is imm26 type | |
| 430 int instrType(); | |
| 431 | |
| 432 // Instructions are read of out a code stream. The only way to get a | |
| 433 // reference to an instruction is to convert a pointer. There is no way | |
| 434 // to allocate or create instances of class Instruction. | |
| 435 // Use the At(pc) function to create references to Instruction. | |
| 436 static Instruction* At(byte* pc) { return reinterpret_cast<Instruction*>(pc); } | |
| 437 | |
| 438 private: | |
| 439 // We need to prevent the creation of instances of class Instruction. | |
| 440 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); | |
| 441 }; | |
| 442 | |
| 443 | |
| 444 // ----------------------------------------------------------------------------- | |
| 445 // MIPS assembly various constants | |
| 446 | |
| 447 static const int argsSlotsSize = 4*Instruction::kInstructionSize; | |
| 448 static const int argsSlotsNum = 4; | |
| 449 | |
| 450 | |
| 451 } } // namespace assembler::mips | |
| 452 | |
| 453 #endif // #ifndef V8_MIPS_CONSTANTS_H_ | |
| OLD | NEW |