Index: src/s390/simulator-s390.cc |
diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc |
index e819556048d7652b7a02dacd9decfd1a750ff4a9..57806d5393f58e85475377177addf805112ae907 100644 |
--- a/src/s390/simulator-s390.cc |
+++ b/src/s390/simulator-s390.cc |
@@ -5953,6 +5953,29 @@ uintptr_t Simulator::PopAddress() { |
int r2 = AS(RREInstruction)->R2Value(); \ |
int length = 4; |
+#define DECODE_RRE_INSTRUCTION_NO_R2(r1) \ |
+ int r1 = AS(RREInstruction)->R1Value(); \ |
+ int length = 4; |
+ |
+#define DECODE_RRD_INSTRUCTION(r1, r2, r3) \ |
+ int r1 = AS(RRDInstruction)->R1Value(); \ |
+ int r2 = AS(RRDInstruction)->R2Value(); \ |
+ int r3 = AS(RRDInstruction)->R3Value(); \ |
+ int length = 4; |
+ |
+#define DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4) \ |
+ int r1 = AS(RRFInstruction)->R1Value(); \ |
+ int r2 = AS(RRFInstruction)->R2Value(); \ |
+ int m3 = AS(RRFInstruction)->M3Value(); \ |
+ int m4 = AS(RRFInstruction)->M4Value(); \ |
+ int length = 4; |
+ |
+#define DECODE_RRF_A_INSTRUCTION(r1, r2, r3) \ |
+ int r1 = AS(RRFInstruction)->R1Value(); \ |
+ int r2 = AS(RRFInstruction)->R2Value(); \ |
+ int r3 = AS(RRFInstruction)->R3Value(); \ |
+ int length = 4; |
+ |
#define DECODE_RR_INSTRUCTION(r1, r2) \ |
int r1 = AS(RRInstruction)->R1Value(); \ |
int r2 = AS(RRInstruction)->R2Value(); \ |
@@ -7961,27 +7984,109 @@ EVALUATE(LCDBR) { |
return length; |
} |
-EVALUATE(SQEBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SQEBR) { |
+ DCHECK_OPCODE(SQEBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ float fr1_val = get_float32_from_d_register(r1); |
+ float fr2_val = get_float32_from_d_register(r2); |
+ fr1_val = std::sqrt(fr2_val); |
+ set_d_register_from_float32(r1, fr1_val); |
+ return length; |
+} |
-EVALUATE(SQDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SQDBR) { |
+ DCHECK_OPCODE(SQDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ r1_val = std::sqrt(r2_val); |
+ set_d_register_from_double(r1, r1_val); |
+ return length; |
+} |
EVALUATE(SQXBR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(MEEBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MEEBR) { |
+ DCHECK_OPCODE(MEEBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ float fr1_val = get_float32_from_d_register(r1); |
+ float fr2_val = get_float32_from_d_register(r2); |
+ fr1_val *= fr2_val; |
+ set_d_register_from_float32(r1, fr1_val); |
+ SetS390ConditionCode<float>(fr1_val, 0); |
+ return length; |
+} |
EVALUATE(KDBR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CDBR) { |
+ DCHECK_OPCODE(CDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ if (isNaN(r1_val) || isNaN(r2_val)) { |
+ condition_reg_ = CC_OF; |
+ } else { |
+ SetS390ConditionCode<double>(r1_val, r2_val); |
+ } |
+ return length; |
+} |
-EVALUATE(ADBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ADBR) { |
+ DCHECK_OPCODE(ADBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ r1_val += r2_val; |
+ set_d_register_from_double(r1, r1_val); |
+ SetS390ConditionCode<double>(r1_val, 0); |
+ return length; |
+} |
-EVALUATE(SDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SDBR) { |
+ DCHECK_OPCODE(SDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ r1_val -= r2_val; |
+ set_d_register_from_double(r1, r1_val); |
+ SetS390ConditionCode<double>(r1_val, 0); |
+ return length; |
+} |
-EVALUATE(MDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MDBR) { |
+ DCHECK_OPCODE(MDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ r1_val *= r2_val; |
+ set_d_register_from_double(r1, r1_val); |
+ SetS390ConditionCode<double>(r1_val, 0); |
+ return length; |
+} |
-EVALUATE(DDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(DDBR) { |
+ DCHECK_OPCODE(DDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ r1_val /= r2_val; |
+ set_d_register_from_double(r1, r1_val); |
+ SetS390ConditionCode<double>(r1_val, 0); |
+ return length; |
+} |
-EVALUATE(MADBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MADBR) { |
+ DCHECK_OPCODE(MADBR); |
+ DECODE_RRD_INSTRUCTION(r1, r2, r3); |
+ double r1_val = get_double_from_d_register(r1); |
+ double r2_val = get_double_from_d_register(r2); |
+ double r3_val = get_double_from_d_register(r3); |
+ r1_val += r2_val * r3_val; |
+ set_d_register_from_double(r1, r1_val); |
+ SetS390ConditionCode<double>(r1_val, 0); |
+ return length; |
+} |
EVALUATE(MSDBR) { return DecodeInstructionOriginal(instr); } |
@@ -8019,7 +8124,30 @@ EVALUATE(TBDR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(DIEBR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(FIEBRA) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(FIEBRA) { |
+ DCHECK_OPCODE(FIEBRA); |
+ DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4); |
+ float r2_val = get_float32_from_d_register(r2); |
+ CHECK(m4 == 0); |
+ switch (m3) { |
+ case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0: |
+ set_d_register_from_float32(r1, round(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_0: |
+ set_d_register_from_float32(r1, trunc(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_POS_INF: |
+ set_d_register_from_float32(r1, std::ceil(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF: |
+ set_d_register_from_float32(r1, std::floor(r2_val)); |
+ break; |
+ default: |
+ UNIMPLEMENTED(); |
+ break; |
+ } |
+ return length; |
+} |
EVALUATE(THDER) { return DecodeInstructionOriginal(instr); } |
@@ -8027,7 +8155,30 @@ EVALUATE(THDR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(DIDBR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(FIDBRA) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(FIDBRA) { |
+ DCHECK_OPCODE(FIDBRA); |
+ DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4); |
+ double r2_val = get_double_from_d_register(r2); |
+ CHECK(m4 == 0); |
+ switch (m3) { |
+ case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0: |
+ set_d_register_from_double(r1, round(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_0: |
+ set_d_register_from_double(r1, trunc(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_POS_INF: |
+ set_d_register_from_double(r1, std::ceil(r2_val)); |
+ break; |
+ case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF: |
+ set_d_register_from_double(r1, std::floor(r2_val)); |
+ break; |
+ default: |
+ UNIMPLEMENTED(); |
+ break; |
+ } |
+ return length; |
+} |
EVALUATE(LXR) { return DecodeInstructionOriginal(instr); } |
@@ -8039,7 +8190,12 @@ EVALUATE(LCDFR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LZER) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LZDR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LZDR) { |
+ DCHECK_OPCODE(LZDR); |
+ DECODE_RRE_INSTRUCTION_NO_R2(r1); |
+ set_d_register_from_double(r1, 0.0); |
+ return length; |
+} |
EVALUATE(LZXR) { return DecodeInstructionOriginal(instr); } |
@@ -8049,9 +8205,23 @@ EVALUATE(SFASR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(EFPC) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CELFBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CELFBR) { |
+ DCHECK_OPCODE(CELFBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ float r1_val = static_cast<float>(r2_val); |
+ set_d_register_from_float32(r1, r1_val); |
+ return length; |
+} |
-EVALUATE(CDLFBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CDLFBR) { |
+ DCHECK_OPCODE(CDLFBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ double r1_val = static_cast<double>(r2_val); |
+ set_d_register_from_double(r1, r1_val); |
+ return length; |
+} |
EVALUATE(CXLFBR) { return DecodeInstructionOriginal(instr); } |
@@ -8067,15 +8237,45 @@ EVALUATE(CFDBRA) { return DecodeInstructionOriginal(instr); } |
EVALUATE(CFXBRA) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CLFEBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CLFEBR) { |
+ DCHECK_OPCODE(CLFEBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ float r2_val = get_float32_from_d_register(r2); |
+ uint32_t r1_val = static_cast<uint32_t>(r2_val); |
+ set_low_register(r1, r1_val); |
+ SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX); |
+ return length; |
+} |
-EVALUATE(CLFDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CLFDBR) { |
+ DCHECK_OPCODE(CLFDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r2_val = get_double_from_d_register(r2); |
+ uint32_t r1_val = static_cast<uint32_t>(r2_val); |
+ set_low_register(r1, r1_val); |
+ SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX); |
+ return length; |
+} |
EVALUATE(CLFXBR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CELGBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CELGBR) { |
+ DCHECK_OPCODE(CELGBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint64_t r2_val = get_register(r2); |
+ float r1_val = static_cast<float>(r2_val); |
+ set_d_register_from_float32(r1, r1_val); |
+ return length; |
+} |
-EVALUATE(CDLGBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CDLGBR) { |
+ DCHECK_OPCODE(CDLGBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint64_t r2_val = get_register(r2); |
+ double r1_val = static_cast<double>(r2_val); |
+ set_d_register_from_double(r1, r1_val); |
+ return length; |
+} |
EVALUATE(CXLGBR) { return DecodeInstructionOriginal(instr); } |
@@ -8091,9 +8291,25 @@ EVALUATE(CGDBRA) { return DecodeInstructionOriginal(instr); } |
EVALUATE(CGXBRA) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CLGEBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CLGEBR) { |
+ DCHECK_OPCODE(CLGEBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ float r2_val = get_float32_from_d_register(r2); |
+ uint64_t r1_val = static_cast<uint64_t>(r2_val); |
+ set_register(r1, r1_val); |
+ SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX); |
+ return length; |
+} |
-EVALUATE(CLGDBR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CLGDBR) { |
+ DCHECK_OPCODE(CLGDBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ double r2_val = get_double_from_d_register(r2); |
+ uint64_t r1_val = static_cast<uint64_t>(r2_val); |
+ set_register(r1, r1_val); |
+ SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX); |
+ return length; |
+} |
EVALUATE(CFER) { return DecodeInstructionOriginal(instr); } |
@@ -8101,7 +8317,16 @@ EVALUATE(CFDR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(CFXR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LDGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LDGR) { |
+ DCHECK_OPCODE(LDGR); |
+ // Load FPR from GPR (L <- 64) |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint64_t int_val = get_register(r2); |
+ // double double_val = bit_cast<double, uint64_t>(int_val); |
+ // set_d_register_from_double(rreInst->R1Value(), double_val); |
+ set_d_register(r1, int_val); |
+ return length; |
+} |
EVALUATE(CGER) { return DecodeInstructionOriginal(instr); } |
@@ -8109,7 +8334,14 @@ EVALUATE(CGDR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(CGXR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LGDR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LGDR) { |
+ DCHECK_OPCODE(LGDR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Load GPR from FPR (64 <- L) |
+ int64_t double_val = get_d_register(r2); |
+ set_register(r1, double_val); |
+ return length; |
+} |
EVALUATE(MDTR) { return DecodeInstructionOriginal(instr); } |
@@ -8201,21 +8433,82 @@ EVALUATE(RRXTR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LPGR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LNGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LNGR) { |
+ DCHECK_OPCODE(LNGR); |
+ // Load Negative (64) |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r2_val = get_register(r2); |
+ r2_val = (r2_val >= 0) ? -r2_val : r2_val; // If pos, then negate it. |
+ set_register(r1, r2_val); |
+ condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT; // CC0 - result is zero |
+ // CC1 - result is negative |
+ return length; |
+} |
-EVALUATE(LTGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LTGR) { |
+ DCHECK_OPCODE(LTGR); |
+ // Load Register (64) |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r2_val = get_register(r2); |
+ SetS390ConditionCode<int64_t>(r2_val, 0); |
+ set_register(r1, get_register(r2)); |
+ return length; |
+} |
-EVALUATE(LCGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LCGR) { |
+ DCHECK_OPCODE(LCGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r2_val = get_register(r2); |
+ r2_val = ~r2_val; |
+ r2_val = r2_val + 1; |
+ set_register(r1, r2_val); |
+ SetS390ConditionCode<int64_t>(r2_val, 0); |
+ // if the input is INT_MIN, loading its compliment would be overflowing |
+ if (r2_val < 0 && (r2_val + 1) > 0) { |
+ SetS390OverflowCode(true); |
+ } |
+ return length; |
+} |
-EVALUATE(SGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SGR) { |
+ DCHECK_OPCODE(SGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ bool isOF = false; |
+ isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); |
+ r1_val -= r2_val; |
+ SetS390ConditionCode<int64_t>(r1_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
EVALUATE(ALGR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(SLGR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(MSGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MSGR) { |
+ DCHECK_OPCODE(MSGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ set_register(r1, r1_val * r2_val); |
+ return length; |
+} |
+ |
+EVALUATE(DSGR) { |
+ DCHECK_OPCODE(DSGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
-EVALUATE(DSGR) { return DecodeInstructionOriginal(instr); } |
+ DCHECK(r1 % 2 == 0); |
+ |
+ int64_t dividend = get_register(r1 + 1); |
+ int64_t divisor = get_register(r2); |
+ set_register(r1, dividend % divisor); |
+ set_register(r1 + 1, dividend / divisor); |
+ return length; |
+} |
EVALUATE(LRVGR) { return DecodeInstructionOriginal(instr); } |
@@ -8223,17 +8516,61 @@ EVALUATE(LPGFR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LNGFR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LTGFR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LTGFR) { |
+ DCHECK_OPCODE(LTGFR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Load and Test Register (64 <- 32) (Sign Extends 32-bit val) |
+ // Load Register (64 <- 32) (Sign Extends 32-bit val) |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int64_t result = static_cast<int64_t>(r2_val); |
+ set_register(r1, result); |
+ SetS390ConditionCode<int64_t>(result, 0); |
+ return length; |
+} |
-EVALUATE(LCGFR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LCGFR) { |
+ DCHECK_OPCODE(LCGFR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Load and Test Register (64 <- 32) (Sign Extends 32-bit val) |
+ // Load Register (64 <- 32) (Sign Extends 32-bit val) |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int64_t result = static_cast<int64_t>(r2_val); |
+ set_register(r1, result); |
+ return length; |
+} |
EVALUATE(LLGFR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LLGTR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(AGFR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(AGFR) { |
+ DCHECK_OPCODE(AGFR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Add Register (64 <- 32) (Sign Extends 32-bit val) |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2)); |
+ bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t); |
+ r1_val += r2_val; |
+ SetS390ConditionCode<int64_t>(r1_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
-EVALUATE(SGFR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SGFR) { |
+ DCHECK_OPCODE(SGFR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Sub Reg (64 <- 32) |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2)); |
+ bool isOF = false; |
+ isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t); |
+ r1_val -= r2_val; |
+ SetS390ConditionCode<int64_t>(r1_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
EVALUATE(ALGFR) { return DecodeInstructionOriginal(instr); } |
@@ -8247,9 +8584,25 @@ EVALUATE(KMAC) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LRVR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(CGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CGR) { |
+ DCHECK_OPCODE(CGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Compare (64) |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ SetS390ConditionCode<int64_t>(r1_val, r2_val); |
+ return length; |
+} |
-EVALUATE(CLGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(CLGR) { |
+ DCHECK_OPCODE(CLGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ // Compare Logical (64) |
+ uint64_t r1_val = static_cast<uint64_t>(get_register(r1)); |
+ uint64_t r2_val = static_cast<uint64_t>(get_register(r2)); |
+ SetS390ConditionCode<uint64_t>(r1_val, r2_val); |
+ return length; |
+} |
EVALUATE(KMF) { return DecodeInstructionOriginal(instr); } |
@@ -8295,13 +8648,60 @@ EVALUATE(CXLFTR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(CGRT) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(NGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(NGR) { |
+ DCHECK_OPCODE(NGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ r1_val &= r2_val; |
+ SetS390BitWiseConditionCode<uint64_t>(r1_val); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
+ |
+EVALUATE(OGR) { |
+ DCHECK_OPCODE(OGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ r1_val |= r2_val; |
+ SetS390BitWiseConditionCode<uint64_t>(r1_val); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
+ |
+EVALUATE(XGR) { |
+ DCHECK_OPCODE(XGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ int64_t r1_val = get_register(r1); |
+ int64_t r2_val = get_register(r2); |
+ r1_val ^= r2_val; |
+ SetS390BitWiseConditionCode<uint64_t>(r1_val); |
+ set_register(r1, r1_val); |
+ return length; |
+} |
+ |
+EVALUATE(FLOGR) { |
+ DCHECK_OPCODE(FLOGR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
-EVALUATE(OGR) { return DecodeInstructionOriginal(instr); } |
+ DCHECK(r1 % 2 == 0); |
-EVALUATE(XGR) { return DecodeInstructionOriginal(instr); } |
+ int64_t r2_val = get_register(r2); |
-EVALUATE(FLOGR) { return DecodeInstructionOriginal(instr); } |
+ int i = 0; |
+ for (; i < 64; i++) { |
+ if (r2_val < 0) break; |
+ r2_val <<= 1; |
+ } |
+ |
+ r2_val = get_register(r2); |
+ |
+ int64_t mask = ~(1 << (63 - i)); |
+ set_register(r1, i); |
+ set_register(r1 + 1, r2_val & mask); |
+ return length; |
+} |
EVALUATE(LLGCR) { return DecodeInstructionOriginal(instr); } |
@@ -8309,7 +8709,25 @@ EVALUATE(LLGHR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(MLGR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(DLGR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(DLGR) { |
+ DCHECK_OPCODE(DLGR); |
+#ifdef V8_TARGET_ARCH_S390X |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint64_t r1_val = get_register(r1); |
+ uint64_t r2_val = get_register(r2); |
+ DCHECK(r1 % 2 == 0); |
+ unsigned __int128 dividend = static_cast<unsigned __int128>(r1_val) << 64; |
+ dividend += get_register(r1 + 1); |
+ uint64_t remainder = dividend % r2_val; |
+ uint64_t quotient = dividend / r2_val; |
+ r1_val = remainder; |
+ set_register(r1, remainder); |
+ set_register(r1 + 1, quotient); |
+ return length; |
+#else |
+ UNREACHABLE(); |
+#endif |
+} |
EVALUATE(ALCGR) { return DecodeInstructionOriginal(instr); } |
@@ -8329,13 +8747,79 @@ EVALUATE(LLCR) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LLHR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(MLR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MLR) { |
+ DCHECK_OPCODE(MLR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ DCHECK(r1 % 2 == 0); |
+ |
+ uint32_t r1_val = get_low_register<uint32_t>(r1 + 1); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ uint64_t product = |
+ static_cast<uint64_t>(r1_val) * static_cast<uint64_t>(r2_val); |
+ int32_t high_bits = product >> 32; |
+ int32_t low_bits = product & 0x00000000FFFFFFFF; |
+ set_low_register(r1, high_bits); |
+ set_low_register(r1 + 1, low_bits); |
+ return length; |
+} |
+ |
+EVALUATE(DLR) { |
+ DCHECK_OPCODE(DLR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint32_t r1_val = get_low_register<uint32_t>(r1); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ DCHECK(r1 % 2 == 0); |
+ uint64_t dividend = static_cast<uint64_t>(r1_val) << 32; |
+ dividend += get_low_register<uint32_t>(r1 + 1); |
+ uint32_t remainder = dividend % r2_val; |
+ uint32_t quotient = dividend / r2_val; |
+ r1_val = remainder; |
+ set_low_register(r1, remainder); |
+ set_low_register(r1 + 1, quotient); |
+ return length; |
+} |
-EVALUATE(DLR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ALCR) { |
+ DCHECK_OPCODE(ALCR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint32_t r1_val = get_low_register<uint32_t>(r1); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ uint32_t alu_out = 0; |
+ bool isOF = false; |
+ |
+ alu_out = r1_val + r2_val; |
+ bool isOF_original = CheckOverflowForUIntAdd(r1_val, r2_val); |
+ if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) { |
+ alu_out = alu_out + 1; |
+ isOF = isOF_original || CheckOverflowForUIntAdd(alu_out, 1); |
+ } else { |
+ isOF = isOF_original; |
+ } |
+ set_low_register(r1, alu_out); |
+ SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); |
+ return length; |
+} |
-EVALUATE(ALCR) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SLBR) { |
+ DCHECK_OPCODE(SLBR); |
+ DECODE_RRE_INSTRUCTION(r1, r2); |
+ uint32_t r1_val = get_low_register<uint32_t>(r1); |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ uint32_t alu_out = 0; |
+ bool isOF = false; |
-EVALUATE(SLBR) { return DecodeInstructionOriginal(instr); } |
+ alu_out = r1_val - r2_val; |
+ bool isOF_original = CheckOverflowForUIntSub(r1_val, r2_val); |
+ if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) { |
+ alu_out = alu_out - 1; |
+ isOF = isOF_original || CheckOverflowForUIntSub(alu_out, 1); |
+ } else { |
+ isOF = isOF_original; |
+ } |
+ set_low_register(r1, alu_out); |
+ SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF); |
+ return length; |
+} |
EVALUATE(CU14) { return DecodeInstructionOriginal(instr); } |
@@ -8375,49 +8859,280 @@ EVALUATE(POPCNT_Z) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LOCGR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(NGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(NGRK) { |
+ DCHECK_OPCODE(NGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ uint64_t bitwise_result = 0; |
+ bitwise_result = r2_val & r3_val; |
+ SetS390BitWiseConditionCode<uint64_t>(bitwise_result); |
+ set_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(OGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(OGRK) { |
+ DCHECK_OPCODE(OGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ uint64_t bitwise_result = 0; |
+ bitwise_result = r2_val | r3_val; |
+ SetS390BitWiseConditionCode<uint64_t>(bitwise_result); |
+ set_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(XGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(XGRK) { |
+ DCHECK_OPCODE(XGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ uint64_t bitwise_result = 0; |
+ bitwise_result = r2_val ^ r3_val; |
+ SetS390BitWiseConditionCode<uint64_t>(bitwise_result); |
+ set_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(AGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(AGRK) { |
+ DCHECK_OPCODE(AGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t); |
+ SetS390ConditionCode<int64_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val + r3_val); |
+ return length; |
+} |
-EVALUATE(SGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SGRK) { |
+ DCHECK_OPCODE(SGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering arithmetics / bitwise ops. |
+ int64_t r2_val = get_register(r2); |
+ int64_t r3_val = get_register(r3); |
+ bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t); |
+ SetS390ConditionCode<int64_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val - r3_val); |
+ return length; |
+} |
-EVALUATE(ALGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ALGRK) { |
+ DCHECK_OPCODE(ALGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering unsigned arithmetics |
+ uint64_t r2_val = get_register(r2); |
+ uint64_t r3_val = get_register(r3); |
+ bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); |
+ SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val + r3_val); |
+ return length; |
+} |
-EVALUATE(SLGRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SLGRK) { |
+ DCHECK_OPCODE(SLGRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 64-bit Non-clobbering unsigned arithmetics |
+ uint64_t r2_val = get_register(r2); |
+ uint64_t r3_val = get_register(r3); |
+ bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); |
+ SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_register(r1, r2_val - r3_val); |
+ return length; |
+} |
EVALUATE(LOCR) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(NRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(NRK) { |
+ DCHECK_OPCODE(NRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering arithmetics / bitwise ops |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int32_t r3_val = get_low_register<int32_t>(r3); |
+ // Assume bitwise operation here |
+ uint32_t bitwise_result = 0; |
+ bitwise_result = r2_val & r3_val; |
+ SetS390BitWiseConditionCode<uint32_t>(bitwise_result); |
+ set_low_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(ORK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ORK) { |
+ DCHECK_OPCODE(ORK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering arithmetics / bitwise ops |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int32_t r3_val = get_low_register<int32_t>(r3); |
+ // Assume bitwise operation here |
+ uint32_t bitwise_result = 0; |
+ bitwise_result = r2_val | r3_val; |
+ SetS390BitWiseConditionCode<uint32_t>(bitwise_result); |
+ set_low_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(XRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(XRK) { |
+ DCHECK_OPCODE(XRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering arithmetics / bitwise ops |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int32_t r3_val = get_low_register<int32_t>(r3); |
+ // Assume bitwise operation here |
+ uint32_t bitwise_result = 0; |
+ bitwise_result = r2_val ^ r3_val; |
+ SetS390BitWiseConditionCode<uint32_t>(bitwise_result); |
+ set_low_register(r1, bitwise_result); |
+ return length; |
+} |
-EVALUATE(ARK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ARK) { |
+ DCHECK_OPCODE(ARK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering arithmetics / bitwise ops |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int32_t r3_val = get_low_register<int32_t>(r3); |
+ bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t); |
+ SetS390ConditionCode<int32_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_low_register(r1, r2_val + r3_val); |
+ return length; |
+} |
-EVALUATE(SRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SRK) { |
+ DCHECK_OPCODE(SRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering arithmetics / bitwise ops |
+ int32_t r2_val = get_low_register<int32_t>(r2); |
+ int32_t r3_val = get_low_register<int32_t>(r3); |
+ bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int32_t); |
+ SetS390ConditionCode<int32_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_low_register(r1, r2_val - r3_val); |
+ return length; |
+} |
-EVALUATE(ALRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ALRK) { |
+ DCHECK_OPCODE(ALRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering unsigned arithmetics |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ uint32_t r3_val = get_low_register<uint32_t>(r3); |
+ bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val); |
+ SetS390ConditionCode<uint32_t>(r2_val + r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_low_register(r1, r2_val + r3_val); |
+ return length; |
+} |
-EVALUATE(SLRK) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SLRK) { |
+ DCHECK_OPCODE(SLRK); |
+ DECODE_RRF_A_INSTRUCTION(r1, r2, r3); |
+ // 32-bit Non-clobbering unsigned arithmetics |
+ uint32_t r2_val = get_low_register<uint32_t>(r2); |
+ uint32_t r3_val = get_low_register<uint32_t>(r3); |
+ bool isOF = CheckOverflowForUIntSub(r2_val, r3_val); |
+ SetS390ConditionCode<uint32_t>(r2_val - r3_val, 0); |
+ SetS390OverflowCode(isOF); |
+ set_low_register(r1, r2_val - r3_val); |
+ return length; |
+} |
-EVALUATE(LTG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LTG) { |
+ DCHECK_OPCODE(LTG); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int64_t value = ReadDW(addr); |
+ set_register(r1, value); |
+ SetS390ConditionCode<int64_t>(value, 0); |
+ return length; |
+} |
EVALUATE(CVBY) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(AG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(AG) { |
+ DCHECK_OPCODE(AG); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t alu_out = get_register(r1); |
+ int64_t mem_val = ReadDW(b2_val + x2_val + d2); |
+ alu_out += mem_val; |
+ SetS390ConditionCode<int32_t>(alu_out, 0); |
+ set_register(r1, alu_out); |
+ return length; |
+} |
-EVALUATE(SG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SG) { |
+ DCHECK_OPCODE(SG); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t alu_out = get_register(r1); |
+ int64_t mem_val = ReadDW(b2_val + x2_val + d2); |
+ alu_out -= mem_val; |
+ SetS390ConditionCode<int32_t>(alu_out, 0); |
+ set_register(r1, alu_out); |
+ return length; |
+} |
-EVALUATE(ALG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(ALG) { |
+ DCHECK_OPCODE(ALG); |
+#ifndef V8_TARGET_ARCH_S390X |
+ DCHECK(false); |
+#endif |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ uint64_t r1_val = get_register(r1); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ intptr_t d2_val = d2; |
+ uint64_t alu_out = r1_val; |
+ uint64_t mem_val = static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val)); |
+ alu_out += mem_val; |
+ SetS390ConditionCode<uint64_t>(alu_out, 0); |
+ set_register(r1, alu_out); |
+ return length; |
+} |
-EVALUATE(SLG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(SLG) { |
+ DCHECK_OPCODE(SLG); |
+#ifndef V8_TARGET_ARCH_S390X |
+ DCHECK(false); |
+#endif |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ uint64_t r1_val = get_register(r1); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ intptr_t d2_val = d2; |
+ uint64_t alu_out = r1_val; |
+ uint64_t mem_val = static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val)); |
+ alu_out -= mem_val; |
+ SetS390ConditionCode<uint64_t>(alu_out, 0); |
+ set_register(r1, alu_out); |
+ return length; |
+} |
-EVALUATE(MSG) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MSG) { |
+ DCHECK_OPCODE(MSG); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ intptr_t d2_val = d2; |
+ int64_t mem_val = ReadDW(b2_val + d2_val + x2_val); |
+ int64_t r1_val = get_register(r1); |
+ set_register(r1, mem_val * r1_val); |
+ return length; |
+} |
EVALUATE(DSG) { return DecodeInstructionOriginal(instr); } |
@@ -8425,9 +9140,29 @@ EVALUATE(CVBG) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LRVG) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LT) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LT) { |
+ DCHECK_OPCODE(LT); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int32_t value = ReadW(addr, instr); |
+ set_low_register(r1, value); |
+ SetS390ConditionCode<int32_t>(value, 0); |
+ return length; |
+} |
-EVALUATE(LGH) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LGH) { |
+ DCHECK_OPCODE(LGH); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int64_t mem_val = static_cast<int64_t>(ReadH(addr, instr)); |
+ set_register(r1, mem_val); |
+ return length; |
+} |
EVALUATE(LLGF) { return DecodeInstructionOriginal(instr); } |
@@ -8477,7 +9212,17 @@ EVALUATE(STRVH) { return DecodeInstructionOriginal(instr); } |
EVALUATE(BCTG) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(MSY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(MSY) { |
+ DCHECK_OPCODE(MSY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ intptr_t d2_val = d2; |
+ int32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr); |
+ int32_t r1_val = get_low_register<int32_t>(r1); |
+ set_low_register(r1, mem_val * r1_val); |
+ return length; |
+} |
EVALUATE(NY) { return DecodeInstructionOriginal(instr); } |
@@ -8499,11 +9244,31 @@ EVALUATE(ALY) { return DecodeInstructionOriginal(instr); } |
EVALUATE(SLY) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(STHY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(STHY) { |
+ DCHECK_OPCODE(STHY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ uint16_t value = get_low_register<uint32_t>(r1); |
+ WriteH(addr, value, instr); |
+ return length; |
+} |
EVALUATE(LAY) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(STCY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(STCY) { |
+ DCHECK_OPCODE(STCY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ uint8_t value = get_low_register<uint32_t>(r1); |
+ WriteB(addr, value); |
+ return length; |
+} |
EVALUATE(ICY) { return DecodeInstructionOriginal(instr); } |
@@ -8511,9 +9276,29 @@ EVALUATE(LAEY) { return DecodeInstructionOriginal(instr); } |
EVALUATE(LB) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LGB) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LGB) { |
+ DCHECK_OPCODE(LGB); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int64_t mem_val = ReadB(addr); |
+ set_register(r1, mem_val); |
+ return length; |
+} |
-EVALUATE(LHY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LHY) { |
+ DCHECK_OPCODE(LHY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int32_t result = static_cast<int32_t>(ReadH(addr, instr)); |
+ set_low_register(r1, result); |
+ return length; |
+} |
EVALUATE(CHY) { return DecodeInstructionOriginal(instr); } |
@@ -8815,13 +9600,53 @@ EVALUATE(TDCXT) { return DecodeInstructionOriginal(instr); } |
EVALUATE(TDGXT) { return DecodeInstructionOriginal(instr); } |
-EVALUATE(LEY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LEY) { |
+ DCHECK_OPCODE(LEY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ float float_val = *reinterpret_cast<float*>(addr); |
+ set_d_register_from_float32(r1, float_val); |
+ return length; |
+} |
-EVALUATE(LDY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(LDY) { |
+ DCHECK_OPCODE(LDY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ uint64_t dbl_val = *reinterpret_cast<uint64_t*>(addr); |
+ set_d_register(r1, dbl_val); |
+ return length; |
+} |
-EVALUATE(STEY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(STEY) { |
+ DCHECK_OPCODE(STEY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int64_t frs_val = get_d_register(r1) >> 32; |
+ WriteW(addr, static_cast<int32_t>(frs_val), instr); |
+ return length; |
+} |
-EVALUATE(STDY) { return DecodeInstructionOriginal(instr); } |
+EVALUATE(STDY) { |
+ DCHECK_OPCODE(STDY); |
+ DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2); |
+ // Miscellaneous Loads and Stores |
+ int64_t x2_val = (x2 == 0) ? 0 : get_register(x2); |
+ int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); |
+ intptr_t addr = x2_val + b2_val + d2; |
+ int64_t frs_val = get_d_register(r1); |
+ WriteDW(addr, frs_val); |
+ return length; |
+} |
EVALUATE(CZDT) { return DecodeInstructionOriginal(instr); } |