Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Unified Diff: src/mips64/simulator-mips64.cc

Issue 426863006: MIPS64: Add support for architecture revision 6. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips64/simulator-mips64.cc
diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc
index 86e8b91464eacbd74a54294a7a14fee232673782..f4cad547bbd8ef23474a92508d2a6fa679564fc6 100644
--- a/src/mips64/simulator-mips64.cc
+++ b/src/mips64/simulator-mips64.cc
@@ -1955,9 +1955,6 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
switch (op) {
case COP1: // Coprocessor instructions.
switch (instr->RsFieldRaw()) {
- case BC1: // Handled in DecodeTypeImmed, should never come here.
- UNREACHABLE();
- break;
case CFC1:
// At the moment only FCSR is supported.
ASSERT(fs_reg == kFCSRRegister);
@@ -1976,8 +1973,6 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
case MTC1:
case DMTC1:
case MTHC1:
- // Do the store in the execution step.
- break;
case S:
case D:
case W:
@@ -1986,7 +1981,8 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
// Do everything in the execution step.
break;
default:
- UNIMPLEMENTED_MIPS();
+ // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here.
+ UNREACHABLE();
}
break;
case COP1X:
@@ -2071,13 +2067,23 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
case DSRAV:
*alu_out = rt >> rs;
break;
- case MFHI:
- *alu_out = get_register(HI);
+ case MFHI: // MFHI == CLZ on R6.
+ if (kArchVariant != kMips64r6) {
+ ASSERT(instr->SaValue() == 0);
+ *alu_out = get_register(HI);
+ } else {
+ // MIPS spec: If no bits were set in GPR rs, the result written to
+ // GPR rd is 32.
+ // GCC __builtin_clz: If input is 0, the result is undefined.
+ ASSERT(instr->SaValue() == 1);
+ *alu_out =
+ rs_u == 0 ? 32 : CompilerIntrinsics::CountLeadingZeros(rs_u);
+ }
break;
case MFLO:
*alu_out = get_register(LO);
break;
- case MULT:
+ case MULT: // MULT == D_MUL_MUH.
// TODO(plind) - Unify MULT/DMULT with single set of 64-bit HI/Lo
// regs.
// TODO(plind) - make the 32-bit MULT ops conform to spec regarding
@@ -2088,9 +2094,23 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
case MULTU:
*u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
break;
- case DMULT:
- *i128resultH = MultiplyHighSigned(rs, rt);
- *i128resultL = rs * rt;
+ case DMULT: // DMULT == D_MUL_MUH.
+ if (kArchVariant != kMips64r6) {
+ *i128resultH = MultiplyHighSigned(rs, rt);
+ *i128resultL = rs * rt;
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ *i128resultL = rs * rt;
+ break;
+ case MUH_OP:
+ *i128resultH = MultiplyHighSigned(rs, rt);
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case DMULTU:
UNIMPLEMENTED_MIPS();
@@ -2295,6 +2315,8 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
case COP1:
switch (instr->RsFieldRaw()) {
case BC1: // Branch on coprocessor condition.
+ case BC1EQZ:
+ case BC1NEZ:
UNREACHABLE();
break;
case CFC1:
@@ -2328,20 +2350,9 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
f = get_fpu_register_float(fs_reg);
set_fpu_register_double(fd_reg, static_cast<double>(f));
break;
- case CVT_W_S:
- case CVT_L_S:
- case TRUNC_W_S:
- case TRUNC_L_S:
- case ROUND_W_S:
- case ROUND_L_S:
- case FLOOR_W_S:
- case FLOOR_L_S:
- case CEIL_W_S:
- case CEIL_L_S:
- case CVT_PS_S:
- UNIMPLEMENTED_MIPS();
- break;
default:
+ // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S
+ // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented.
UNREACHABLE();
}
break;
@@ -2514,25 +2525,77 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
alu_out = get_fpu_register_signed_word(fs_reg);
set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
break;
- default:
+ default: // Mips64r6 CMP.S instructions unimplemented.
UNREACHABLE();
}
break;
case L:
+ fs = get_fpu_register_double(fs_reg);
+ ft = get_fpu_register_double(ft_reg);
switch (instr->FunctionFieldRaw()) {
- case CVT_D_L: // Mips32r2 instruction.
- i64 = get_fpu_register(fs_reg);
- set_fpu_register_double(fd_reg, static_cast<double>(i64));
- break;
+ case CVT_D_L: // Mips32r2 instruction.
+ i64 = get_fpu_register(fs_reg);
+ set_fpu_register_double(fd_reg, static_cast<double>(i64));
+ break;
case CVT_S_L:
UNIMPLEMENTED_MIPS();
break;
- default:
+ case CMP_AF: // Mips64r6 CMP.D instructions.
+ UNIMPLEMENTED_MIPS();
+ break;
+ case CMP_UN:
+ if (std::isnan(fs) || std::isnan(ft)) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_EQ:
+ if (fs == ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_UEQ:
+ if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_LT:
+ if (fs < ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_ULT:
+ if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_LE:
+ if (fs <= ft) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ case CMP_ULE:
+ if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) {
+ set_fpu_register(fd_reg, -1);
+ } else {
+ set_fpu_register(fd_reg, 0);
+ }
+ break;
+ default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED
UNREACHABLE();
}
break;
- case PS:
- break;
default:
UNREACHABLE();
}
@@ -2572,32 +2635,91 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
}
// Instructions using HI and LO registers.
case MULT:
- set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
- set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+ if (kArchVariant != kMips64r6) {
+ set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
+ set_register(HI, static_cast<int32_t>(i64hilo >> 32));
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ set_register(rd_reg,
+ static_cast<int32_t>(i64hilo & 0xffffffff));
+ break;
+ case MUH_OP:
+ set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case MULTU:
set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
set_register(HI, static_cast<int32_t>(u64hilo >> 32));
break;
- case DMULT:
- set_register(LO, static_cast<int64_t>(i128resultL));
- set_register(HI, static_cast<int64_t>(i128resultH));
+ case DMULT: // DMULT == D_MUL_MUH.
+ if (kArchVariant != kMips64r6) {
+ set_register(LO, static_cast<int64_t>(i128resultL));
+ set_register(HI, static_cast<int64_t>(i128resultH));
+ } else {
+ switch (instr->SaValue()) {
+ case MUL_OP:
+ set_register(rd_reg, static_cast<int64_t>(i128resultL));
+ break;
+ case MUH_OP:
+ set_register(rd_reg, static_cast<int64_t>(i128resultH));
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ }
break;
case DMULTU:
UNIMPLEMENTED_MIPS();
break;
+ case DSLL:
+ set_register(rd_reg, alu_out);
+ break;
case DIV:
case DDIV:
- // Divide by zero and overflow was not checked in the configuration
- // step - div and divu do not raise exceptions. On division by 0
- // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1),
- // return INT_MIN which is what the hardware does.
- if (rs == INT_MIN && rt == -1) {
- set_register(LO, INT_MIN);
- set_register(HI, 0);
- } else if (rt != 0) {
- set_register(LO, rs / rt);
- set_register(HI, rs % rt);
+ switch (kArchVariant) {
+ case kMips64r2:
+ // Divide by zero and overflow was not checked in the
+ // configuration step - div and divu do not raise exceptions. On
+ // division by 0 the result will be UNPREDICTABLE. On overflow
+ // (INT_MIN/-1), return INT_MIN which is what the hardware does.
+ if (rs == INT_MIN && rt == -1) {
+ set_register(LO, INT_MIN);
+ set_register(HI, 0);
+ } else if (rt != 0) {
+ set_register(LO, rs / rt);
+ set_register(HI, rs % rt);
+ }
+ break;
+ case kMips64r6:
+ switch (instr->SaValue()) {
+ case DIV_OP:
+ if (rs == INT_MIN && rt == -1) {
+ set_register(rd_reg, INT_MIN);
+ } else if (rt != 0) {
+ set_register(rd_reg, rs / rt);
+ }
+ break;
+ case MOD_OP:
+ if (rs == INT_MIN && rt == -1) {
+ set_register(rd_reg, 0);
+ } else if (rt != 0) {
+ set_register(rd_reg, rs % rt);
+ }
+ break;
+ default:
+ UNIMPLEMENTED_MIPS();
+ break;
+ }
+ break;
+ default:
+ break;
}
break;
case DIVU:
@@ -2696,6 +2818,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
int16_t imm16 = instr->Imm16Value();
int32_t ft_reg = instr->FtValue(); // Destination register.
+ int64_t ft = get_fpu_register(ft_reg);
// Zero extended immediate.
uint32_t oe_imm16 = 0xffff & imm16;
@@ -2742,6 +2865,26 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
next_pc = current_pc + kBranchReturnOffset;
}
break;
+ case BC1EQZ:
+ do_branch = (ft & 0x1) ? false : true;
+ execute_branch_delay_instruction = true;
+ // Set next_pc.
+ if (do_branch) {
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ } else {
+ next_pc = current_pc + kBranchReturnOffset;
+ }
+ break;
+ case BC1NEZ:
+ do_branch = (ft & 0x1) ? true : false;
+ execute_branch_delay_instruction = true;
+ // Set next_pc.
+ if (do_branch) {
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ } else {
+ next_pc = current_pc + kBranchReturnOffset;
+ }
+ break;
default:
UNREACHABLE();
}
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698