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

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

Issue 2760983003: PPC: Clean up simulator code by introducing a OpcodeBase function (Closed)
Patch Set: Add missing cases in simulator Created 3 years, 9 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/ppc/constants-ppc.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ppc/simulator-ppc.cc
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc
index 058632847dca58362291dade0e37c174d276f153..c82f9464eea9333ec3e7acc8b3428df29d403404 100644
--- a/src/ppc/simulator-ppc.cc
+++ b/src/ppc/simulator-ppc.cc
@@ -1620,11 +1620,154 @@ void Simulator::ExecuteBranchConditional(Instruction* instr, BCType type) {
}
}
-
-// Handle execution based on instruction types.
-void Simulator::ExecuteExt1(Instruction* instr) {
- uint32_t opcode = EXT1 | instr->BitField(10, 1);
+void Simulator::ExecuteGeneric(Instruction* instr) {
+ uint32_t opcode = instr->OpcodeBase();
switch (opcode) {
+ case SUBFIC: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ intptr_t ra_val = get_register(ra);
+ int32_t im_val = instr->Bits(15, 0);
+ im_val = SIGN_EXT_IMM16(im_val);
+ intptr_t alu_out = im_val - ra_val;
+ set_register(rt, alu_out);
+ // todo - handle RC bit
+ break;
+ }
+ case CMPLI: {
+ int ra = instr->RAValue();
+ uint32_t im_val = instr->Bits(15, 0);
+ int cr = instr->Bits(25, 23);
+ uint32_t bf = 0;
+#if V8_TARGET_ARCH_PPC64
+ int L = instr->Bit(21);
+ if (L) {
+#endif
+ uintptr_t ra_val = get_register(ra);
+ if (ra_val < im_val) {
+ bf |= 0x80000000;
+ }
+ if (ra_val > im_val) {
+ bf |= 0x40000000;
+ }
+ if (ra_val == im_val) {
+ bf |= 0x20000000;
+ }
+#if V8_TARGET_ARCH_PPC64
+ } else {
+ uint32_t ra_val = get_register(ra);
+ if (ra_val < im_val) {
+ bf |= 0x80000000;
+ }
+ if (ra_val > im_val) {
+ bf |= 0x40000000;
+ }
+ if (ra_val == im_val) {
+ bf |= 0x20000000;
+ }
+ }
+#endif
+ uint32_t condition_mask = 0xF0000000U >> (cr * 4);
+ uint32_t condition = bf >> (cr * 4);
+ condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+ break;
+ }
+ case CMPI: {
+ int ra = instr->RAValue();
+ int32_t im_val = instr->Bits(15, 0);
+ im_val = SIGN_EXT_IMM16(im_val);
+ int cr = instr->Bits(25, 23);
+ uint32_t bf = 0;
+#if V8_TARGET_ARCH_PPC64
+ int L = instr->Bit(21);
+ if (L) {
+#endif
+ intptr_t ra_val = get_register(ra);
+ if (ra_val < im_val) {
+ bf |= 0x80000000;
+ }
+ if (ra_val > im_val) {
+ bf |= 0x40000000;
+ }
+ if (ra_val == im_val) {
+ bf |= 0x20000000;
+ }
+#if V8_TARGET_ARCH_PPC64
+ } else {
+ int32_t ra_val = get_register(ra);
+ if (ra_val < im_val) {
+ bf |= 0x80000000;
+ }
+ if (ra_val > im_val) {
+ bf |= 0x40000000;
+ }
+ if (ra_val == im_val) {
+ bf |= 0x20000000;
+ }
+ }
+#endif
+ uint32_t condition_mask = 0xF0000000U >> (cr * 4);
+ uint32_t condition = bf >> (cr * 4);
+ condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
+ break;
+ }
+ case ADDIC: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ uintptr_t ra_val = get_register(ra);
+ uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ uintptr_t alu_out = ra_val + im_val;
+ // Check overflow
+ if (~ra_val < im_val) {
+ special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
+ } else {
+ special_reg_xer_ &= ~0xF0000000;
+ }
+ set_register(rt, alu_out);
+ break;
+ }
+ case ADDI: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t alu_out;
+ if (ra == 0) {
+ alu_out = im_val;
+ } else {
+ intptr_t ra_val = get_register(ra);
+ alu_out = ra_val + im_val;
+ }
+ set_register(rt, alu_out);
+ // todo - handle RC bit
+ break;
+ }
+ case ADDIS: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int32_t im_val = (instr->Bits(15, 0) << 16);
+ intptr_t alu_out;
+ if (ra == 0) { // treat r0 as zero
+ alu_out = im_val;
+ } else {
+ intptr_t ra_val = get_register(ra);
+ alu_out = ra_val + im_val;
+ }
+ set_register(rt, alu_out);
+ break;
+ }
+ case BCX: {
+ ExecuteBranchConditional(instr, BC_OFFSET);
+ break;
+ }
+ case BX: {
+ int offset = (instr->Bits(25, 2) << 8) >> 6;
+ if (instr->Bit(0) == 1) { // LK flag set
+ special_reg_lr_ = get_pc() + 4;
+ }
+ set_pc(get_pc() + offset);
+ // todo - AA flag
+ break;
+ }
case MCRF:
UNIMPLEMENTED(); // Not used by V8.
case BCLRX:
@@ -1668,69 +1811,192 @@ void Simulator::ExecuteExt1(Instruction* instr) {
case CRNAND:
case CRAND:
case CRORC:
- case CROR:
- default: {
+ case CROR: {
UNIMPLEMENTED(); // Not used by V8.
+ break;
}
- }
-}
-
-
-bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
- bool found = true;
-
- uint32_t opcode = EXT2 | instr->BitField(10, 1);
- switch (opcode) {
- case SRWX: {
- int rs = instr->RSValue();
+ case RLWIMIX: {
int ra = instr->RAValue();
- int rb = instr->RBValue();
+ int rs = instr->RSValue();
uint32_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb) & 0x3f;
- intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val;
+ int32_t ra_val = get_register(ra);
+ int sh = instr->Bits(15, 11);
+ int mb = instr->Bits(10, 6);
+ int me = instr->Bits(5, 1);
+ uint32_t result = base::bits::RotateLeft32(rs_val, sh);
+ int mask = 0;
+ if (mb < me + 1) {
+ int bit = 0x80000000 >> mb;
+ for (; mb <= me; mb++) {
+ mask |= bit;
+ bit >>= 1;
+ }
+ } else if (mb == me + 1) {
+ mask = 0xffffffff;
+ } else { // mb > me+1
+ int bit = 0x80000000 >> (me + 1); // needs to be tested
+ mask = 0xffffffff;
+ for (; me < mb; me++) {
+ mask ^= bit;
+ bit >>= 1;
+ }
+ }
+ result &= mask;
+ ra_val &= ~mask;
+ result |= ra_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
}
break;
}
-#if V8_TARGET_ARCH_PPC64
- case SRDX: {
- int rs = instr->RSValue();
+ case RLWINMX:
+ case RLWNMX: {
int ra = instr->RAValue();
- int rb = instr->RBValue();
- uintptr_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb) & 0x7f;
- intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val;
+ int rs = instr->RSValue();
+ uint32_t rs_val = get_register(rs);
+ int sh = 0;
+ if (opcode == RLWINMX) {
+ sh = instr->Bits(15, 11);
+ } else {
+ int rb = instr->RBValue();
+ uint32_t rb_val = get_register(rb);
+ sh = (rb_val & 0x1f);
+ }
+ int mb = instr->Bits(10, 6);
+ int me = instr->Bits(5, 1);
+ uint32_t result = base::bits::RotateLeft32(rs_val, sh);
+ int mask = 0;
+ if (mb < me + 1) {
+ int bit = 0x80000000 >> mb;
+ for (; mb <= me; mb++) {
+ mask |= bit;
+ bit >>= 1;
+ }
+ } else if (mb == me + 1) {
+ mask = 0xffffffff;
+ } else { // mb > me+1
+ int bit = 0x80000000 >> (me + 1); // needs to be tested
+ mask = 0xffffffff;
+ for (; me < mb; me++) {
+ mask ^= bit;
+ bit >>= 1;
+ }
+ }
+ result &= mask;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
}
break;
}
-#endif
- case MODUW: {
- int rt = instr->RTValue();
+ case ORI: {
+ int rs = instr->RSValue();
int ra = instr->RAValue();
- int rb = instr->RBValue();
- uint32_t ra_val = get_register(ra);
- uint32_t rb_val = get_register(rb);
- uint32_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
- set_register(rt, alu_out);
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val | im_val;
+ set_register(ra, alu_out);
break;
}
-#if V8_TARGET_ARCH_PPC64
- case MODUD: {
- int rt = instr->RTValue();
+ case ORIS: {
+ int rs = instr->RSValue();
int ra = instr->RAValue();
- int rb = instr->RBValue();
- uint64_t ra_val = get_register(ra);
- uint64_t rb_val = get_register(rb);
- uint64_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
- set_register(rt, alu_out);
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val | (im_val << 16);
+ set_register(ra, alu_out);
break;
}
-#endif
+ case XORI: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val ^ im_val;
+ set_register(ra, alu_out);
+ // todo - set condition based SO bit
+ break;
+ }
+ case XORIS: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val ^ (im_val << 16);
+ set_register(ra, alu_out);
+ break;
+ }
+ case ANDIx: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val & im_val;
+ set_register(ra, alu_out);
+ SetCR0(alu_out);
+ break;
+ }
+ case ANDISx: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ intptr_t rs_val = get_register(rs);
+ uint32_t im_val = instr->Bits(15, 0);
+ intptr_t alu_out = rs_val & (im_val << 16);
+ set_register(ra, alu_out);
+ SetCR0(alu_out);
+ break;
+ }
+ case SRWX: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ uint32_t rs_val = get_register(rs);
+ uintptr_t rb_val = get_register(rb) & 0x3f;
+ intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val;
+ set_register(ra, result);
+ if (instr->Bit(0)) { // RC bit set
+ SetCR0(result);
+ }
+ break;
+ }
+#if V8_TARGET_ARCH_PPC64
+ case SRDX: {
+ int rs = instr->RSValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ uintptr_t rs_val = get_register(rs);
+ uintptr_t rb_val = get_register(rb) & 0x7f;
+ intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val;
+ set_register(ra, result);
+ if (instr->Bit(0)) { // RC bit set
+ SetCR0(result);
+ }
+ break;
+ }
+#endif
+ case MODUW: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ uint32_t ra_val = get_register(ra);
+ uint32_t rb_val = get_register(rb);
+ uint32_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
+ set_register(rt, alu_out);
+ break;
+ }
+#if V8_TARGET_ARCH_PPC64
+ case MODUD: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ uint64_t ra_val = get_register(ra);
+ uint64_t rb_val = get_register(rb);
+ uint64_t alu_out = (rb_val == 0) ? -1 : ra_val % rb_val;
+ set_register(rt, alu_out);
+ break;
+ }
+#endif
case MODSW: {
int rt = instr->RTValue();
int ra = instr->RAValue();
@@ -1941,17 +2207,49 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
// todo - simulate icbi
break;
}
- default: {
- found = false;
+
+ case LWZU:
+ case LWZ: {
+ int ra = instr->RAValue();
+ int rt = instr->RTValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ set_register(rt, ReadWU(ra_val + offset, instr));
+ if (opcode == LWZU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
break;
}
- }
- if (found) return found;
+ case LBZU:
+ case LBZ: {
+ int ra = instr->RAValue();
+ int rt = instr->RTValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ set_register(rt, ReadB(ra_val + offset) & 0xFF);
+ if (opcode == LBZU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
- found = true;
- opcode = EXT2 | instr->BitField(10, 2);
- switch (opcode) {
+ case STWU:
+ case STW: {
+ int ra = instr->RAValue();
+ int rs = instr->RSValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int32_t rs_val = get_register(rs);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ WriteW(ra_val + offset, rs_val, instr);
+ if (opcode == STWU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
case SRADIX: {
int ra = instr->RAValue();
int rs = instr->RSValue();
@@ -1964,21 +2262,6 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
}
break;
}
- default: {
- found = false;
- break;
- }
- }
-
- return found;
-}
-
-
-bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
- bool found = true;
-
- uint32_t opcode = EXT2 | instr->BitField(9, 1);
- switch (opcode) {
case TW: {
// used for call redirection in simulation mode
SoftwareInterrupt(instr);
@@ -2223,20 +2506,6 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
break;
}
#endif
- default: {
- found = false;
- break;
- }
- }
-
- return found;
-}
-
-
-bool Simulator::ExecuteExt2_9bit_part2(Instruction* instr) {
- bool found = true;
- uint32_t opcode = EXT2 | instr->BitField(9, 1);
- switch (opcode) {
case CNTLZWX: {
int rs = instr->RSValue();
int ra = instr->RAValue();
@@ -2742,19 +3011,6 @@ bool Simulator::ExecuteExt2_9bit_part2(Instruction* instr) {
// todo - simulate dcbf
break;
}
- default: {
- found = false;
- break;
- }
- }
-
- return found;
-}
-
-
-void Simulator::ExecuteExt2_5bit(Instruction* instr) {
- uint32_t opcode = EXT2 | instr->BitField(5, 1);
- switch (opcode) {
case ISEL: {
int rt = instr->RTValue();
int ra = instr->RAValue();
@@ -2767,64 +3023,184 @@ void Simulator::ExecuteExt2_5bit(Instruction* instr) {
set_register(rt, value);
break;
}
- default: {
- PrintF("Unimplemented: %08x\n", instr->InstructionBits());
- UNIMPLEMENTED(); // Not used by V8.
- }
- }
-}
+ case STBU:
+ case STB: {
+ int ra = instr->RAValue();
+ int rs = instr->RSValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int8_t rs_val = get_register(rs);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ WriteB(ra_val + offset, rs_val);
+ if (opcode == STBU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
-void Simulator::ExecuteExt2(Instruction* instr) {
- // Check first the 10-1 bit versions
- if (ExecuteExt2_10bit(instr)) return;
- // Now look at the lesser encodings
- if (ExecuteExt2_9bit_part1(instr)) return;
- if (ExecuteExt2_9bit_part2(instr)) return;
- ExecuteExt2_5bit(instr);
-}
-
+ case LHZU:
+ case LHZ: {
+ int ra = instr->RAValue();
+ int rt = instr->RTValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ uintptr_t result = ReadHU(ra_val + offset, instr) & 0xffff;
+ set_register(rt, result);
+ if (opcode == LHZU) {
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
-void Simulator::ExecuteExt3(Instruction* instr) {
- uint32_t opcode = EXT3 | instr->BitField(10, 1);
- switch (opcode) {
- case FCFIDS: {
- // fcfids
- int frt = instr->RTValue();
- int frb = instr->RBValue();
- int64_t frb_val = get_d_register(frb);
- double frt_val = static_cast<float>(frb_val);
- set_d_register_from_double(frt, frt_val);
- return;
+ case LHA:
+ case LHAU: {
+ int ra = instr->RAValue();
+ int rt = instr->RTValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t result = ReadH(ra_val + offset, instr);
+ set_register(rt, result);
+ if (opcode == LHAU) {
+ set_register(ra, ra_val + offset);
+ }
+ break;
}
- case FCFIDUS: {
- // fcfidus
- int frt = instr->RTValue();
- int frb = instr->RBValue();
- uint64_t frb_val = get_d_register(frb);
- double frt_val = static_cast<float>(frb_val);
- set_d_register_from_double(frt, frt_val);
- return;
+
+ case STHU:
+ case STH: {
+ int ra = instr->RAValue();
+ int rs = instr->RSValue();
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int16_t rs_val = get_register(rs);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ WriteH(ra_val + offset, rs_val, instr);
+ if (opcode == STHU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
}
- }
- UNIMPLEMENTED(); // Not used by V8.
-}
+ case LMW:
+ case STMW: {
+ UNIMPLEMENTED();
+ break;
+ }
-void Simulator::ExecuteExt4(Instruction* instr) {
- uint32_t opcode = EXT4 | instr->BitField(5, 1);
- switch (opcode) {
- case FDIV: {
+ case LFSU:
+ case LFS: {
int frt = instr->RTValue();
- int fra = instr->RAValue();
- int frb = instr->RBValue();
- double fra_val = get_double_from_d_register(fra);
- double frb_val = get_double_from_d_register(frb);
- double frt_val = fra_val / frb_val;
- set_d_register_from_double(frt, frt_val);
- return;
- }
- case FSUB: {
+ int ra = instr->RAValue();
+ int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int32_t val = ReadW(ra_val + offset, instr);
+ float* fptr = reinterpret_cast<float*>(&val);
+// Conversion using double changes sNan to qNan on ia32/x64
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+ if (val == 0x7fa00000) {
+ set_d_register(frt, 0x7ff4000000000000);
+ } else {
+#endif
+ set_d_register_from_double(frt, static_cast<double>(*fptr));
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+ }
+#endif
+ if (opcode == LFSU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
+
+ case LFDU:
+ case LFD: {
+ int frt = instr->RTValue();
+ int ra = instr->RAValue();
+ int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int64_t* dptr = reinterpret_cast<int64_t*>(ReadDW(ra_val + offset));
+ set_d_register(frt, *dptr);
+ if (opcode == LFDU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
+
+ case STFSU: {
+ case STFS:
+ int frs = instr->RSValue();
+ int ra = instr->RAValue();
+ int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ float frs_val = static_cast<float>(get_double_from_d_register(frs));
+ int32_t* p;
+// Conversion using double changes sNan to qNan on ia32/x64
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+ int64_t frs_isnan = get_d_register(frs);
+ int32_t frs_nan_single = 0x7fa00000;
+ if (frs_isnan == 0x7ff4000000000000) {
+ p = &frs_nan_single;
+ } else {
+#endif
+ p = reinterpret_cast<int32_t*>(&frs_val);
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+ }
+#endif
+ WriteW(ra_val + offset, *p, instr);
+ if (opcode == STFSU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
+
+ case STFDU:
+ case STFD: {
+ int frs = instr->RSValue();
+ int ra = instr->RAValue();
+ int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
+ intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int64_t frs_val = get_d_register(frs);
+ WriteDW(ra_val + offset, frs_val);
+ if (opcode == STFDU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
+
+ case FCFIDS: {
+ // fcfids
+ int frt = instr->RTValue();
+ int frb = instr->RBValue();
+ int64_t frb_val = get_d_register(frb);
+ double frt_val = static_cast<float>(frb_val);
+ set_d_register_from_double(frt, frt_val);
+ return;
+ }
+ case FCFIDUS: {
+ // fcfidus
+ int frt = instr->RTValue();
+ int frb = instr->RBValue();
+ uint64_t frb_val = get_d_register(frb);
+ double frt_val = static_cast<float>(frb_val);
+ set_d_register_from_double(frt, frt_val);
+ return;
+ }
+
+ case FDIV: {
+ int frt = instr->RTValue();
+ int fra = instr->RAValue();
+ int frb = instr->RBValue();
+ double fra_val = get_double_from_d_register(fra);
+ double frb_val = get_double_from_d_register(frb);
+ double frt_val = fra_val / frb_val;
+ set_d_register_from_double(frt, frt_val);
+ return;
+ }
+ case FSUB: {
int frt = instr->RTValue();
int fra = instr->RAValue();
int frb = instr->RBValue();
@@ -2899,9 +3275,6 @@ void Simulator::ExecuteExt4(Instruction* instr) {
set_d_register_from_double(frt, frt_val);
return;
}
- }
- opcode = EXT4 | instr->BitField(10, 1);
- switch (opcode) {
case FCMPU: {
int fra = instr->RAValue();
int frb = instr->RBValue();
@@ -3232,14 +3605,9 @@ void Simulator::ExecuteExt4(Instruction* instr) {
set_d_register_from_double(frt, frt_val);
return;
}
- }
- UNIMPLEMENTED(); // Not used by V8.
-}
+
#if V8_TARGET_ARCH_PPC64
-void Simulator::ExecuteExt5(Instruction* instr) {
- uint32_t opcode = EXT5 | instr->BitField(4, 2);
- switch (opcode) {
case RLDICL: {
int ra = instr->RAValue();
int rs = instr->RSValue();
@@ -3326,9 +3694,6 @@ void Simulator::ExecuteExt5(Instruction* instr) {
}
return;
}
- }
- opcode = EXT5 | instr->BitField(4, 1);
- switch (opcode) {
case RLDCL: {
int ra = instr->RAValue();
int rs = instr->RSValue();
@@ -3348,14 +3713,52 @@ void Simulator::ExecuteExt5(Instruction* instr) {
}
return;
}
- }
- UNIMPLEMENTED(); // Not used by V8.
-}
+
+ case LD:
+ case LDU:
+ case LWA: {
+ int ra = instr->RAValue();
+ int rt = instr->RTValue();
+ int64_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+ switch (instr->Bits(1, 0)) {
+ case 0: { // ld
+ intptr_t* result = ReadDW(ra_val + offset);
+ set_register(rt, *result);
+ break;
+ }
+ case 1: { // ldu
+ intptr_t* result = ReadDW(ra_val + offset);
+ set_register(rt, *result);
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ break;
+ }
+ case 2: { // lwa
+ intptr_t result = ReadW(ra_val + offset, instr);
+ set_register(rt, result);
+ break;
+ }
+ }
+ break;
+ }
+
+ case STD:
+ case STDU: {
+ int ra = instr->RAValue();
+ int rs = instr->RSValue();
+ int64_t ra_val = ra == 0 ? 0 : get_register(ra);
+ int64_t rs_val = get_register(rs);
+ int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
+ WriteDW(ra_val + offset, rs_val);
+ if (opcode == STDU) {
+ DCHECK(ra != 0);
+ set_register(ra, ra_val + offset);
+ }
+ break;
+ }
#endif
-void Simulator::ExecuteExt6(Instruction* instr) {
- uint32_t opcode = EXT6 | instr->BitField(10, 3);
- switch (opcode) {
case XSADDDP: {
int frt = instr->RTValue();
int fra = instr->RAValue();
@@ -3396,551 +3799,9 @@ void Simulator::ExecuteExt6(Instruction* instr) {
set_d_register_from_double(frt, frt_val);
return;
}
- }
- UNIMPLEMENTED(); // Not used by V8.
-}
-
-void Simulator::ExecuteGeneric(Instruction* instr) {
- uint32_t opcode = instr->OpcodeField();
- switch (opcode) {
- case SUBFIC: {
- int rt = instr->RTValue();
- int ra = instr->RAValue();
- intptr_t ra_val = get_register(ra);
- int32_t im_val = instr->Bits(15, 0);
- im_val = SIGN_EXT_IMM16(im_val);
- intptr_t alu_out = im_val - ra_val;
- set_register(rt, alu_out);
- // todo - handle RC bit
- break;
- }
- case CMPLI: {
- int ra = instr->RAValue();
- uint32_t im_val = instr->Bits(15, 0);
- int cr = instr->Bits(25, 23);
- uint32_t bf = 0;
-#if V8_TARGET_ARCH_PPC64
- int L = instr->Bit(21);
- if (L) {
-#endif
- uintptr_t ra_val = get_register(ra);
- if (ra_val < im_val) {
- bf |= 0x80000000;
- }
- if (ra_val > im_val) {
- bf |= 0x40000000;
- }
- if (ra_val == im_val) {
- bf |= 0x20000000;
- }
-#if V8_TARGET_ARCH_PPC64
- } else {
- uint32_t ra_val = get_register(ra);
- if (ra_val < im_val) {
- bf |= 0x80000000;
- }
- if (ra_val > im_val) {
- bf |= 0x40000000;
- }
- if (ra_val == im_val) {
- bf |= 0x20000000;
- }
- }
-#endif
- uint32_t condition_mask = 0xF0000000U >> (cr * 4);
- uint32_t condition = bf >> (cr * 4);
- condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
- break;
- }
- case CMPI: {
- int ra = instr->RAValue();
- int32_t im_val = instr->Bits(15, 0);
- im_val = SIGN_EXT_IMM16(im_val);
- int cr = instr->Bits(25, 23);
- uint32_t bf = 0;
-#if V8_TARGET_ARCH_PPC64
- int L = instr->Bit(21);
- if (L) {
-#endif
- intptr_t ra_val = get_register(ra);
- if (ra_val < im_val) {
- bf |= 0x80000000;
- }
- if (ra_val > im_val) {
- bf |= 0x40000000;
- }
- if (ra_val == im_val) {
- bf |= 0x20000000;
- }
-#if V8_TARGET_ARCH_PPC64
- } else {
- int32_t ra_val = get_register(ra);
- if (ra_val < im_val) {
- bf |= 0x80000000;
- }
- if (ra_val > im_val) {
- bf |= 0x40000000;
- }
- if (ra_val == im_val) {
- bf |= 0x20000000;
- }
- }
-#endif
- uint32_t condition_mask = 0xF0000000U >> (cr * 4);
- uint32_t condition = bf >> (cr * 4);
- condition_reg_ = (condition_reg_ & ~condition_mask) | condition;
- break;
- }
- case ADDIC: {
- int rt = instr->RTValue();
- int ra = instr->RAValue();
- uintptr_t ra_val = get_register(ra);
- uintptr_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
- uintptr_t alu_out = ra_val + im_val;
- // Check overflow
- if (~ra_val < im_val) {
- special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
- } else {
- special_reg_xer_ &= ~0xF0000000;
- }
- set_register(rt, alu_out);
- break;
- }
- case ADDI: {
- int rt = instr->RTValue();
- int ra = instr->RAValue();
- int32_t im_val = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t alu_out;
- if (ra == 0) {
- alu_out = im_val;
- } else {
- intptr_t ra_val = get_register(ra);
- alu_out = ra_val + im_val;
- }
- set_register(rt, alu_out);
- // todo - handle RC bit
- break;
- }
- case ADDIS: {
- int rt = instr->RTValue();
- int ra = instr->RAValue();
- int32_t im_val = (instr->Bits(15, 0) << 16);
- intptr_t alu_out;
- if (ra == 0) { // treat r0 as zero
- alu_out = im_val;
- } else {
- intptr_t ra_val = get_register(ra);
- alu_out = ra_val + im_val;
- }
- set_register(rt, alu_out);
- break;
- }
- case BCX: {
- ExecuteBranchConditional(instr, BC_OFFSET);
- break;
- }
- case BX: {
- int offset = (instr->Bits(25, 2) << 8) >> 6;
- if (instr->Bit(0) == 1) { // LK flag set
- special_reg_lr_ = get_pc() + 4;
- }
- set_pc(get_pc() + offset);
- // todo - AA flag
- break;
- }
- case EXT1: {
- ExecuteExt1(instr);
- break;
- }
- case RLWIMIX: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- uint32_t rs_val = get_register(rs);
- int32_t ra_val = get_register(ra);
- int sh = instr->Bits(15, 11);
- int mb = instr->Bits(10, 6);
- int me = instr->Bits(5, 1);
- uint32_t result = base::bits::RotateLeft32(rs_val, sh);
- int mask = 0;
- if (mb < me + 1) {
- int bit = 0x80000000 >> mb;
- for (; mb <= me; mb++) {
- mask |= bit;
- bit >>= 1;
- }
- } else if (mb == me + 1) {
- mask = 0xffffffff;
- } else { // mb > me+1
- int bit = 0x80000000 >> (me + 1); // needs to be tested
- mask = 0xffffffff;
- for (; me < mb; me++) {
- mask ^= bit;
- bit >>= 1;
- }
- }
- result &= mask;
- ra_val &= ~mask;
- result |= ra_val;
- set_register(ra, result);
- if (instr->Bit(0)) { // RC bit set
- SetCR0(result);
- }
- break;
- }
- case RLWINMX:
- case RLWNMX: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- uint32_t rs_val = get_register(rs);
- int sh = 0;
- if (opcode == RLWINMX) {
- sh = instr->Bits(15, 11);
- } else {
- int rb = instr->RBValue();
- uint32_t rb_val = get_register(rb);
- sh = (rb_val & 0x1f);
- }
- int mb = instr->Bits(10, 6);
- int me = instr->Bits(5, 1);
- uint32_t result = base::bits::RotateLeft32(rs_val, sh);
- int mask = 0;
- if (mb < me + 1) {
- int bit = 0x80000000 >> mb;
- for (; mb <= me; mb++) {
- mask |= bit;
- bit >>= 1;
- }
- } else if (mb == me + 1) {
- mask = 0xffffffff;
- } else { // mb > me+1
- int bit = 0x80000000 >> (me + 1); // needs to be tested
- mask = 0xffffffff;
- for (; me < mb; me++) {
- mask ^= bit;
- bit >>= 1;
- }
- }
- result &= mask;
- set_register(ra, result);
- if (instr->Bit(0)) { // RC bit set
- SetCR0(result);
- }
- break;
- }
- case ORI: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val | im_val;
- set_register(ra, alu_out);
- break;
- }
- case ORIS: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val | (im_val << 16);
- set_register(ra, alu_out);
- break;
- }
- case XORI: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val ^ im_val;
- set_register(ra, alu_out);
- // todo - set condition based SO bit
- break;
- }
- case XORIS: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val ^ (im_val << 16);
- set_register(ra, alu_out);
- break;
- }
- case ANDIx: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val & im_val;
- set_register(ra, alu_out);
- SetCR0(alu_out);
- break;
- }
- case ANDISx: {
- int rs = instr->RSValue();
- int ra = instr->RAValue();
- intptr_t rs_val = get_register(rs);
- uint32_t im_val = instr->Bits(15, 0);
- intptr_t alu_out = rs_val & (im_val << 16);
- set_register(ra, alu_out);
- SetCR0(alu_out);
- break;
- }
- case EXT2: {
- ExecuteExt2(instr);
- break;
- }
-
- case LWZU:
- case LWZ: {
- int ra = instr->RAValue();
- int rt = instr->RTValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- set_register(rt, ReadWU(ra_val + offset, instr));
- if (opcode == LWZU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case LBZU:
- case LBZ: {
- int ra = instr->RAValue();
- int rt = instr->RTValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- set_register(rt, ReadB(ra_val + offset) & 0xFF);
- if (opcode == LBZU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case STWU:
- case STW: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int32_t rs_val = get_register(rs);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- WriteW(ra_val + offset, rs_val, instr);
- if (opcode == STWU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- // printf("r%d %08x -> %08x\n", rs, rs_val, offset); // 0xdead
- break;
- }
-
- case STBU:
- case STB: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int8_t rs_val = get_register(rs);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- WriteB(ra_val + offset, rs_val);
- if (opcode == STBU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case LHZU:
- case LHZ: {
- int ra = instr->RAValue();
- int rt = instr->RTValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- uintptr_t result = ReadHU(ra_val + offset, instr) & 0xffff;
- set_register(rt, result);
- if (opcode == LHZU) {
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case LHA:
- case LHAU: {
- int ra = instr->RAValue();
- int rt = instr->RTValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t result = ReadH(ra_val + offset, instr);
- set_register(rt, result);
- if (opcode == LHAU) {
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case STHU:
- case STH: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int16_t rs_val = get_register(rs);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- WriteH(ra_val + offset, rs_val, instr);
- if (opcode == STHU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case LMW:
- case STMW: {
- UNIMPLEMENTED();
- break;
- }
-
- case LFSU:
- case LFS: {
- int frt = instr->RTValue();
- int ra = instr->RAValue();
- int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int32_t val = ReadW(ra_val + offset, instr);
- float* fptr = reinterpret_cast<float*>(&val);
-// Conversion using double changes sNan to qNan on ia32/x64
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
- if (val == 0x7fa00000) {
- set_d_register(frt, 0x7ff4000000000000);
- } else {
-#endif
- set_d_register_from_double(frt, static_cast<double>(*fptr));
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
- }
-#endif
- if (opcode == LFSU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case LFDU:
- case LFD: {
- int frt = instr->RTValue();
- int ra = instr->RAValue();
- int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int64_t* dptr = reinterpret_cast<int64_t*>(ReadDW(ra_val + offset));
- set_d_register(frt, *dptr);
- if (opcode == LFDU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case STFSU: {
- case STFS:
- int frs = instr->RSValue();
- int ra = instr->RAValue();
- int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- float frs_val = static_cast<float>(get_double_from_d_register(frs));
- int32_t* p;
-// Conversion using double changes sNan to qNan on ia32/x64
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
- int64_t frs_isnan = get_d_register(frs);
- int32_t frs_nan_single = 0x7fa00000;
- if (frs_isnan == 0x7ff4000000000000) {
- p = &frs_nan_single;
- } else {
-#endif
- p = reinterpret_cast<int32_t*>(&frs_val);
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
- }
-#endif
- WriteW(ra_val + offset, *p, instr);
- if (opcode == STFSU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case STFDU:
- case STFD: {
- int frs = instr->RSValue();
- int ra = instr->RAValue();
- int32_t offset = SIGN_EXT_IMM16(instr->Bits(15, 0));
- intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
- int64_t frs_val = get_d_register(frs);
- WriteDW(ra_val + offset, frs_val);
- if (opcode == STFDU) {
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-
- case EXT3: {
- ExecuteExt3(instr);
- break;
- }
- case EXT4: {
- ExecuteExt4(instr);
- break;
- }
-
-#if V8_TARGET_ARCH_PPC64
- case EXT5: {
- ExecuteExt5(instr);
- break;
- }
- case LD: {
- int ra = instr->RAValue();
- int rt = instr->RTValue();
- int64_t ra_val = ra == 0 ? 0 : get_register(ra);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
- switch (instr->Bits(1, 0)) {
- case 0: { // ld
- intptr_t* result = ReadDW(ra_val + offset);
- set_register(rt, *result);
- break;
- }
- case 1: { // ldu
- intptr_t* result = ReadDW(ra_val + offset);
- set_register(rt, *result);
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- break;
- }
- case 2: { // lwa
- intptr_t result = ReadW(ra_val + offset, instr);
- set_register(rt, result);
- break;
- }
- }
- break;
- }
-
- case STD: {
- int ra = instr->RAValue();
- int rs = instr->RSValue();
- int64_t ra_val = ra == 0 ? 0 : get_register(ra);
- int64_t rs_val = get_register(rs);
- int offset = SIGN_EXT_IMM16(instr->Bits(15, 0) & ~3);
- WriteDW(ra_val + offset, rs_val);
- if (instr->Bit(0) == 1) { // This is the STDU form
- DCHECK(ra != 0);
- set_register(ra, ra_val + offset);
- }
- break;
- }
-#endif
- case EXT6: {
- ExecuteExt6(instr);
- break;
- }
default: {
+printf("opcode = %x \n", instr->InstructionBits());
UNIMPLEMENTED();
break;
}
« no previous file with comments | « src/ppc/constants-ppc.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698