| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_ASSEMBLER_MIPS_H_ | 5 #ifndef VM_ASSEMBLER_MIPS_H_ |
| 6 #define VM_ASSEMBLER_MIPS_H_ | 6 #define VM_ASSEMBLER_MIPS_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_mips.h directly; use assembler.h instead. | 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 ASSERT(EvenFPURegister(ft)); | 236 ASSERT(EvenFPURegister(ft)); |
| 237 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD); | 237 EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD); |
| 238 } | 238 } |
| 239 | 239 |
| 240 void addiu(Register rt, Register rs, const Immediate& imm) { | 240 void addiu(Register rt, Register rs, const Immediate& imm) { |
| 241 ASSERT(Utils::IsInt(kImmBits, imm.value())); | 241 ASSERT(Utils::IsInt(kImmBits, imm.value())); |
| 242 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 242 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| 243 EmitIType(ADDIU, rs, rt, imm_value); | 243 EmitIType(ADDIU, rs, rt, imm_value); |
| 244 } | 244 } |
| 245 | 245 |
| 246 void adds(FRegister fd, FRegister fs, FRegister ft) { | |
| 247 EmitFpuRType(COP1, FMT_S, ft, fs, fd, COP1_ADD); | |
| 248 } | |
| 249 | |
| 250 void addu(Register rd, Register rs, Register rt) { | 246 void addu(Register rd, Register rs, Register rt) { |
| 251 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); | 247 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); |
| 252 } | 248 } |
| 253 | 249 |
| 254 void and_(Register rd, Register rs, Register rt) { | 250 void and_(Register rd, Register rs, Register rt) { |
| 255 EmitRType(SPECIAL, rs, rt, rd, 0, AND); | 251 EmitRType(SPECIAL, rs, rt, rd, 0, AND); |
| 256 } | 252 } |
| 257 | 253 |
| 258 void andi(Register rt, Register rs, const Immediate& imm) { | 254 void andi(Register rt, Register rs, const Immediate& imm) { |
| 259 ASSERT(Utils::IsUint(kImmBits, imm.value())); | 255 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
| 260 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 256 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| 261 EmitIType(ANDI, rs, rt, imm_value); | 257 EmitIType(ANDI, rs, rt, imm_value); |
| 262 } | 258 } |
| 263 | 259 |
| 264 // Unconditional branch. | 260 // Unconditional branch. |
| 265 void b(Label* l) { | 261 void b(Label* l) { |
| 266 beq(R0, R0, l); | 262 beq(R0, R0, l); |
| 267 } | 263 } |
| 268 | 264 |
| 269 void bal(Label *l) { | 265 void bal(Label *l) { |
| 270 ASSERT(!in_delay_slot_); | 266 ASSERT(!in_delay_slot_); |
| 271 EmitRegImmBranch(BGEZAL, R0, l); | 267 EmitRegImmBranch(BGEZAL, R0, l); |
| 272 EmitBranchDelayNop(); | 268 EmitBranchDelayNop(); |
| 273 } | 269 } |
| 274 | 270 |
| 271 // Branch on floating point false. |
| 272 void bc1f(Label* l) { |
| 273 EmitFpuBranch(false, l); |
| 274 EmitBranchDelayNop(); |
| 275 } |
| 276 |
| 277 // Branch on floating point true. |
| 278 void bc1t(Label* l) { |
| 279 EmitFpuBranch(true, l); |
| 280 EmitBranchDelayNop(); |
| 281 } |
| 282 |
| 275 // Branch if equal. | 283 // Branch if equal. |
| 276 void beq(Register rs, Register rt, Label* l) { | 284 void beq(Register rs, Register rt, Label* l) { |
| 277 ASSERT(!in_delay_slot_); | 285 ASSERT(!in_delay_slot_); |
| 278 EmitBranch(BEQ, rs, rt, l); | 286 EmitBranch(BEQ, rs, rt, l); |
| 279 EmitBranchDelayNop(); | 287 EmitBranchDelayNop(); |
| 280 } | 288 } |
| 281 | 289 |
| 282 // Branch if equal, likely taken. | 290 // Branch if equal, likely taken. |
| 283 // Delay slot executed only when branch taken. | 291 // Delay slot executed only when branch taken. |
| 284 void beql(Register rs, Register rt, Label* l) { | 292 void beql(Register rs, Register rt, Label* l) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 EmitBranchDelayNop(); | 370 EmitBranchDelayNop(); |
| 363 } | 371 } |
| 364 | 372 |
| 365 void break_(int32_t code) { | 373 void break_(int32_t code) { |
| 366 ASSERT(Utils::IsUint(20, code)); | 374 ASSERT(Utils::IsUint(20, code)); |
| 367 Emit(SPECIAL << kOpcodeShift | | 375 Emit(SPECIAL << kOpcodeShift | |
| 368 code << kBreakCodeShift | | 376 code << kBreakCodeShift | |
| 369 BREAK << kFunctionShift); | 377 BREAK << kFunctionShift); |
| 370 } | 378 } |
| 371 | 379 |
| 380 // FPU compare, always false. |
| 381 void cfd(FRegister fs, FRegister ft) { |
| 382 ASSERT(EvenFPURegister(fs)); |
| 383 ASSERT(EvenFPURegister(ft)); |
| 384 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_F); |
| 385 } |
| 386 |
| 387 // FPU compare, true if unordered, i.e. one is NaN. |
| 388 void cund(FRegister fs, FRegister ft) { |
| 389 ASSERT(EvenFPURegister(fs)); |
| 390 ASSERT(EvenFPURegister(ft)); |
| 391 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UN); |
| 392 } |
| 393 |
| 394 // FPU compare, true if equal. |
| 395 void ceqd(FRegister fs, FRegister ft) { |
| 396 ASSERT(EvenFPURegister(fs)); |
| 397 ASSERT(EvenFPURegister(ft)); |
| 398 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_EQ); |
| 399 } |
| 400 |
| 401 // FPU compare, true if unordered or equal. |
| 402 void cueqd(FRegister fs, FRegister ft) { |
| 403 ASSERT(EvenFPURegister(fs)); |
| 404 ASSERT(EvenFPURegister(ft)); |
| 405 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_UEQ); |
| 406 } |
| 407 |
| 408 // FPU compare, true if less than. |
| 409 void coltd(FRegister fs, FRegister ft) { |
| 410 ASSERT(EvenFPURegister(fs)); |
| 411 ASSERT(EvenFPURegister(ft)); |
| 412 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLT); |
| 413 } |
| 414 |
| 415 // FPU compare, true if unordered or less than. |
| 416 void cultd(FRegister fs, FRegister ft) { |
| 417 ASSERT(EvenFPURegister(fs)); |
| 418 ASSERT(EvenFPURegister(ft)); |
| 419 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULT); |
| 420 } |
| 421 |
| 422 // FPU compare, true if less or equal. |
| 423 void coled(FRegister fs, FRegister ft) { |
| 424 ASSERT(EvenFPURegister(fs)); |
| 425 ASSERT(EvenFPURegister(ft)); |
| 426 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_OLE); |
| 427 } |
| 428 |
| 429 // FPU compare, true if unordered or less or equal. |
| 430 void culed(FRegister fs, FRegister ft) { |
| 431 ASSERT(EvenFPURegister(fs)); |
| 432 ASSERT(EvenFPURegister(ft)); |
| 433 EmitFpuRType(COP1, FMT_D, ft, fs, F0, COP1_C_ULE); |
| 434 } |
| 435 |
| 372 void clo(Register rd, Register rs) { | 436 void clo(Register rd, Register rs) { |
| 373 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); | 437 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); |
| 374 } | 438 } |
| 375 | 439 |
| 376 void clz(Register rd, Register rs) { | 440 void clz(Register rd, Register rs) { |
| 377 EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ); | 441 EmitRType(SPECIAL2, rs, rd, rd, 0, CLZ); |
| 378 } | 442 } |
| 379 | 443 |
| 380 void div(Register rs, Register rt) { | 444 void div(Register rs, Register rt) { |
| 381 EmitRType(SPECIAL, rs, rt, R0, 0, DIV); | 445 EmitRType(SPECIAL, rs, rt, R0, 0, DIV); |
| (...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 1051 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 988 EmitRegImmType(REGIMM, rs, b, dest_off); | 1052 EmitRegImmType(REGIMM, rs, b, dest_off); |
| 989 } else { | 1053 } else { |
| 990 const int position = buffer_.Size(); | 1054 const int position = buffer_.Size(); |
| 991 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); | 1055 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
| 992 EmitRegImmType(REGIMM, rs, b, dest_off); | 1056 EmitRegImmType(REGIMM, rs, b, dest_off); |
| 993 label->LinkTo(position); | 1057 label->LinkTo(position); |
| 994 } | 1058 } |
| 995 } | 1059 } |
| 996 | 1060 |
| 1061 void EmitFpuBranch(bool kind, Label *label) { |
| 1062 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. |
| 1063 if (label->IsBound()) { |
| 1064 // Relative destination from an instruction after the branch. |
| 1065 const int32_t dest = |
| 1066 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
| 1067 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 1068 Emit(COP1 << kOpcodeShift | |
| 1069 COP1_BC << kCop1SubShift | |
| 1070 b16 | |
| 1071 dest_off); |
| 1072 } else { |
| 1073 const int position = buffer_.Size(); |
| 1074 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
| 1075 Emit(COP1 << kOpcodeShift | |
| 1076 COP1_BC << kCop1SubShift | |
| 1077 b16 | |
| 1078 dest_off); |
| 1079 label->LinkTo(position); |
| 1080 } |
| 1081 } |
| 1082 |
| 997 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); | 1083 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); |
| 998 static int DecodeBranchOffset(int32_t instr); | 1084 static int DecodeBranchOffset(int32_t instr); |
| 999 | 1085 |
| 1000 void EmitBranchDelayNop() { | 1086 void EmitBranchDelayNop() { |
| 1001 Emit(Instr::kNopInstruction); // Branch delay NOP. | 1087 Emit(Instr::kNopInstruction); // Branch delay NOP. |
| 1002 delay_slot_available_ = true; | 1088 delay_slot_available_ = true; |
| 1003 } | 1089 } |
| 1004 | 1090 |
| 1005 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); | 1091 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); |
| 1006 | 1092 |
| 1007 // Shorter filtering sequence that assumes that value is not a smi. | 1093 // Shorter filtering sequence that assumes that value is not a smi. |
| 1008 void StoreIntoObjectFilterNoSmi(Register object, | 1094 void StoreIntoObjectFilterNoSmi(Register object, |
| 1009 Register value, | 1095 Register value, |
| 1010 Label* no_update); | 1096 Label* no_update); |
| 1011 | 1097 |
| 1012 DISALLOW_ALLOCATION(); | 1098 DISALLOW_ALLOCATION(); |
| 1013 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1099 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1014 }; | 1100 }; |
| 1015 | 1101 |
| 1016 } // namespace dart | 1102 } // namespace dart |
| 1017 | 1103 |
| 1018 #endif // VM_ASSEMBLER_MIPS_H_ | 1104 #endif // VM_ASSEMBLER_MIPS_H_ |
| OLD | NEW |