Chromium Code Reviews| Index: runtime/vm/assembler_mips.h |
| =================================================================== |
| --- runtime/vm/assembler_mips.h (revision 21293) |
| +++ runtime/vm/assembler_mips.h (working copy) |
| @@ -223,12 +223,23 @@ |
| } |
| // CPU instructions in alphabetical order. |
| + void addd(FRegister fd, FRegister fs, FRegister ft) { |
| + ASSERT(EvenFPURegister(fd)); |
| + ASSERT(EvenFPURegister(fs)); |
| + ASSERT(EvenFPURegister(ft)); |
| + EmitFpuRType(COP1, FMT_D, ft, fs, fd, COP1_ADD); |
| + } |
| + |
| void addiu(Register rt, Register rs, const Immediate& imm) { |
| ASSERT(Utils::IsInt(kImmBits, imm.value())); |
| const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
| EmitIType(ADDIU, rs, rt, imm_value); |
| } |
| + void adds(FRegister fd, FRegister fs, FRegister ft) { |
| + EmitFpuRType(COP1, FMT_S, ft, fs, fd, COP1_ADD); |
| + } |
| + |
| void addu(Register rd, Register rs, Register rt) { |
| EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); |
| } |
| @@ -388,6 +399,11 @@ |
| EmitLoadStore(LBU, rt, addr); |
| } |
| + void ldc1(FRegister ft, const Address& addr) { |
| + ASSERT(EvenFPURegister(ft)); |
| + EmitFpuLoadStore(LDC1, ft, addr); |
| + } |
| + |
| void lh(Register rt, const Address& addr) { |
| EmitLoadStore(LH, rt, addr); |
| } |
| @@ -406,6 +422,17 @@ |
| EmitLoadStore(LW, rt, addr); |
| } |
| + void lwc1(FRegister ft, const Address& addr) { |
| + EmitFpuLoadStore(LWC1, ft, addr); |
| + } |
| + |
| + void mfc1(Register rt, FRegister fs) { |
| + Emit(COP1 << kOpcodeShift | |
| + COP1_MF << kCop1SubShift | |
| + rt << kRtShift | |
| + fs << kFsShift); |
| + } |
| + |
| void mfhi(Register rd) { |
| EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); |
| } |
| @@ -418,6 +445,12 @@ |
| or_(rd, rs, ZR); |
| } |
| + void movd(FRegister fd, FRegister fs) { |
| + ASSERT(EvenFPURegister(fd)); |
| + ASSERT(EvenFPURegister(fs)); |
| + EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_MOV); |
| + } |
| + |
| void movn(Register rd, Register rs, Register rt) { |
| EmitRType(SPECIAL, rs, rt, rd, 0, MOVN); |
| } |
| @@ -426,6 +459,17 @@ |
| EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); |
| } |
| + void movs(FRegister fd, FRegister fs) { |
| + EmitFpuRType(COP1, FMT_S, F0, fs, fd, COP1_MOV); |
| + } |
| + |
| + void mtc1(Register rt, FRegister fs) { |
| + Emit(COP1 << kOpcodeShift | |
| + COP1_MT << kCop1SubShift | |
| + rt << kRtShift | |
| + fs << kFsShift); |
| + } |
| + |
| void mult(Register rs, Register rt) { |
| EmitRType(SPECIAL, rs, rt, R0, 0, MULT); |
| } |
| @@ -456,6 +500,11 @@ |
| EmitLoadStore(SB, rt, addr); |
| } |
| + void sdc1(FRegister ft, const Address& addr) { |
| + ASSERT(EvenFPURegister(ft)); |
| + EmitFpuLoadStore(SDC1, ft, addr); |
| + } |
| + |
| void sh(Register rt, const Address& addr) { |
| EmitLoadStore(SH, rt, addr); |
| } |
| @@ -500,6 +549,10 @@ |
| EmitLoadStore(SW, rt, addr); |
| } |
| + void swc1(FRegister ft, const Address& addr) { |
| + EmitFpuLoadStore(SWC1, ft, addr); |
| + } |
| + |
| void xor_(Register rd, Register rs, Register rt) { |
| EmitRType(SPECIAL, rs, rt, rd, 0, XOR); |
| } |
| @@ -565,6 +618,36 @@ |
| } |
| } |
| + void LoadImmediate(FRegister rd, double value) { |
| + ASSERT(EvenFPURegister(rd)); |
| + const int64_t ival = bit_cast<uint64_t, double>(value); |
| + const int32_t low = Utils::Low32Bits(ival); |
| + const int32_t high = Utils::High32Bits(ival); |
| + if (low != 0) { |
| + LoadImmediate(TMP1, low); |
| + mtc1(TMP1, rd); |
| + } else { |
| + mtc1(ZR, rd); |
| + } |
| + |
| + if (high != 0) { |
| + LoadImmediate(TMP1, high); |
| + mtc1(TMP1, static_cast<FRegister>(rd + 1)); |
| + } else { |
| + mtc1(ZR, static_cast<FRegister>(rd + 1)); |
| + } |
| + } |
| + |
| + void LoadImmediate(FRegister rd, float value) { |
|
regis
2013/04/12 17:08:56
I am not sure we will need this one, since there i
zra
2013/04/12 17:19:26
I'll keep it for now since I use it in some tests,
|
| + const int32_t ival = bit_cast<int32_t, float>(value); |
| + if (ival == 0) { |
| + mtc1(ZR, rd); |
| + } else { |
| + LoadImmediate(TMP1, ival); |
| + mtc1(TMP1, rd); |
| + } |
| + } |
| + |
| void AddImmediate(Register rd, Register rs, int32_t value) { |
| if (Utils::IsInt(kImmBits, value)) { |
| addiu(rd, rs, Immediate(value)); |
| @@ -734,6 +817,10 @@ |
| GrowableArray<CodeComment*> comments_; |
| + bool EvenFPURegister(FRegister reg) { |
| + return (static_cast<int>(reg) & 1) == 0; |
| + } |
| + |
| void Emit(int32_t value) { |
| // Emitting an instruction clears the delay slot state. |
| in_delay_slot_ = false; |
| @@ -761,6 +848,13 @@ |
| addr.encoding()); |
| } |
| + void EmitFpuLoadStore(Opcode opcode, FRegister ft, |
| + const Address &addr) { |
| + Emit(opcode << kOpcodeShift | |
| + ft << kFtShift | |
| + addr.encoding()); |
| + } |
| + |
| void EmitRegImmType(Opcode opcode, |
| Register rs, |
| RtRegImm code, |
| @@ -790,6 +884,20 @@ |
| func << kFunctionShift); |
| } |
| + void EmitFpuRType(Opcode opcode, |
| + Format fmt, |
| + FRegister ft, |
| + FRegister fs, |
| + FRegister fd, |
| + Cop1Function func) { |
| + Emit(opcode << kOpcodeShift | |
| + fmt << kFmtShift | |
| + ft << kFtShift | |
| + fs << kFsShift | |
| + fd << kFdShift | |
| + func << kCop1FnShift); |
| + } |
| + |
| void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { |
| if (label->IsBound()) { |
| // Relative destination from an instruction after the branch. |