| Index: src/s390/simulator-s390.cc
|
| diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc
|
| index 57806d5393f58e85475377177addf805112ae907..7503b477116920d6a1c7fcc51f08dc5bdcb381bb 100644
|
| --- a/src/s390/simulator-s390.cc
|
| +++ b/src/s390/simulator-s390.cc
|
| @@ -5948,6 +5948,18 @@ uintptr_t Simulator::PopAddress() {
|
| uint8_t imm_val = AS(SIInstruction)->I2Value(); \
|
| int length = 4;
|
|
|
| +#define DECODE_SIL_INSTRUCTION(b1, d1, i2) \
|
| + int b1 = AS(SILInstruction)->B1Value(); \
|
| + intptr_t d1 = AS(SILInstruction)->D1Value(); \
|
| + int16_t i2 = AS(SILInstruction)->I2Value(); \
|
| + int length = 6;
|
| +
|
| +#define DECODE_SIY_INSTRUCTION(b1, d1, i2) \
|
| + int b1 = AS(SIYInstruction)->B1Value(); \
|
| + intptr_t d1 = AS(SIYInstruction)->D1Value(); \
|
| + uint8_t i2 = AS(SIYInstruction)->I2Value(); \
|
| + int length = 6;
|
| +
|
| #define DECODE_RRE_INSTRUCTION(r1, r2) \
|
| int r1 = AS(RREInstruction)->R1Value(); \
|
| int r2 = AS(RREInstruction)->R2Value(); \
|
| @@ -6017,6 +6029,13 @@ uintptr_t Simulator::PopAddress() {
|
| int16_t i2 = AS(RIInstruction)->I2Value(); \
|
| int length = 4;
|
|
|
| +#define DECODE_RXE_INSTRUCTION(r1, b2, x2, d2) \
|
| + int r1 = AS(RXEInstruction)->R1Value(); \
|
| + int b2 = AS(RXEInstruction)->B2Value(); \
|
| + int x2 = AS(RXEInstruction)->X2Value(); \
|
| + int d2 = AS(RXEInstruction)->D2Value(); \
|
| + int length = 6;
|
| +
|
| #define GET_ADDRESS(index_reg, base_reg, offset) \
|
| (((index_reg) == 0) ? 0 : get_register(index_reg)) + \
|
| (((base_reg) == 0) ? 0 : get_register(base_reg)) + offset
|
| @@ -9164,13 +9183,49 @@ EVALUATE(LGH) {
|
| return length;
|
| }
|
|
|
| -EVALUATE(LLGF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LLGF) {
|
| + DCHECK_OPCODE(LLGF);
|
| + 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 mem_val = static_cast<uint64_t>(ReadWU(addr, instr));
|
| + set_register(r1, mem_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LLGT) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(AGF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AGF) {
|
| + DCHECK_OPCODE(AGF);
|
| + 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;
|
| + uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
|
| + alu_out += mem_val;
|
| + SetS390ConditionCode<int64_t>(alu_out, 0);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SGF) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SGF) {
|
| + DCHECK_OPCODE(SGF);
|
| + 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;
|
| + uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
|
| + alu_out -= mem_val;
|
| + SetS390ConditionCode<int64_t>(alu_out, 0);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(ALGF) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9180,13 +9235,54 @@ EVALUATE(MSGF) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(DSGF) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LRV) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LRV) {
|
| + DCHECK_OPCODE(LRV);
|
| + 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 mem_addr = b2_val + x2_val + d2;
|
| + int32_t mem_val = ReadW(mem_addr, instr);
|
| + set_low_register(r1, ByteReverse(mem_val));
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LRVH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LRVH) {
|
| + DCHECK_OPCODE(LRVH);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + intptr_t mem_addr = b2_val + x2_val + d2;
|
| + int16_t mem_val = ReadH(mem_addr, instr);
|
| + int32_t result = ByteReverse(mem_val) & 0x0000ffff;
|
| + result |= r1_val & 0xffff0000;
|
| + set_low_register(r1, result);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CG) {
|
| + DCHECK_OPCODE(CG);
|
| + 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);
|
| + SetS390ConditionCode<int64_t>(alu_out, mem_val);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CLG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLG) {
|
| + DCHECK_OPCODE(CLG);
|
| + 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);
|
| + SetS390ConditionCode<uint64_t>(alu_out, mem_val);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(NTSTG) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9206,9 +9302,28 @@ EVALUATE(CGH) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(PFD) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STRV) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STRV) {
|
| + DCHECK_OPCODE(STRV);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + intptr_t mem_addr = b2_val + x2_val + d2;
|
| + WriteW(mem_addr, ByteReverse(r1_val), instr);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(STRVH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STRVH) {
|
| + DCHECK_OPCODE(STRVH);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + int32_t r1_val = get_low_register<int32_t>(r1);
|
| + int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + intptr_t mem_addr = b2_val + x2_val + d2;
|
| + int16_t result = static_cast<int16_t>(r1_val >> 16);
|
| + WriteH(mem_addr, ByteReverse(result), instr);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(BCTG) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9224,25 +9339,126 @@ EVALUATE(MSY) {
|
| return length;
|
| }
|
|
|
| -EVALUATE(NY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NY) {
|
| + DCHECK_OPCODE(NY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + alu_out &= mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CLY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLY) {
|
| + DCHECK_OPCODE(CLY);
|
| + 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);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
|
| + SetS390ConditionCode<uint32_t>(alu_out, mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OY) {
|
| + DCHECK_OPCODE(OY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + alu_out |= mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(XY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(XY) {
|
| + DCHECK_OPCODE(XY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + alu_out ^= mem_val;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(CY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CY) {
|
| + DCHECK_OPCODE(CY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + SetS390ConditionCode<int32_t>(alu_out, mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(AY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AY) {
|
| + DCHECK_OPCODE(AY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntAdd(alu_out, mem_val, int32_t);
|
| + alu_out += mem_val;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SY) {
|
| + DCHECK_OPCODE(SY);
|
| + 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);
|
| + int32_t alu_out = get_low_register<int32_t>(r1);
|
| + int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForIntSub(alu_out, mem_val, int32_t);
|
| + alu_out -= mem_val;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MFY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(ALY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ALY) {
|
| + DCHECK_OPCODE(ALY);
|
| + 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);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
|
| + alu_out += mem_val;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<uint32_t>(alu_out, 0);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLY) {
|
| + DCHECK_OPCODE(SLY);
|
| + 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);
|
| + uint32_t alu_out = get_low_register<uint32_t>(r1);
|
| + uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
|
| + alu_out -= mem_val;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<uint32_t>(alu_out, 0);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(STHY) {
|
| DCHECK_OPCODE(STHY);
|
| @@ -9256,7 +9472,18 @@ EVALUATE(STHY) {
|
| return length;
|
| }
|
|
|
| -EVALUATE(LAY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LAY) {
|
| + DCHECK_OPCODE(LAY);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + // Load Address
|
| + int rb = b2;
|
| + int rx = x2;
|
| + int offset = d2;
|
| + int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
|
| + int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
|
| + set_register(r1, rx_val + rb_val + offset);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(STCY) {
|
| DCHECK_OPCODE(STCY);
|
| @@ -9274,7 +9501,17 @@ EVALUATE(ICY) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(LAEY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LB) {
|
| + DCHECK_OPCODE(LB);
|
| + // Miscellaneous Loads and Stores
|
| + 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 mem_val = ReadB(addr);
|
| + set_low_register(r1, mem_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LGB) {
|
| DCHECK_OPCODE(LGB);
|
| @@ -9302,17 +9539,84 @@ EVALUATE(LHY) {
|
|
|
| EVALUATE(CHY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(AHY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AHY) {
|
| + DCHECK_OPCODE(AHY);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + int32_t r1_val = get_low_register<int32_t>(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;
|
| + int32_t mem_val =
|
| + static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr));
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r1_val + mem_val;
|
| + isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SHY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SHY) {
|
| + DCHECK_OPCODE(SHY);
|
| + DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
|
| + int32_t r1_val = get_low_register<int32_t>(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;
|
| + int32_t mem_val =
|
| + static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr));
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r1_val - mem_val;
|
| + isOF = CheckOverflowForIntSub(r1_val, mem_val, int64_t);
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MHY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(NG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(NG) {
|
| + DCHECK_OPCODE(NG);
|
| + 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;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(OG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(OG) {
|
| + DCHECK_OPCODE(OG);
|
| + 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;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(XG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(XG) {
|
| + DCHECK_OPCODE(XG);
|
| + 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;
|
| + SetS390BitWiseConditionCode<uint32_t>(alu_out);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LGAT) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9328,9 +9632,29 @@ EVALUATE(STPQ) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(LPQ) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LLGH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LLGH) {
|
| + DCHECK_OPCODE(LLGH);
|
| + // Load Logical Halfword
|
| + 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;
|
| + uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
|
| + set_register(r1, mem_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(LLH) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LLH) {
|
| + DCHECK_OPCODE(LLH);
|
| + // Load Logical Halfword
|
| + 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;
|
| + uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
|
| + set_low_register(r1, mem_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(ML) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9370,9 +9694,25 @@ EVALUATE(MVCDK) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(MVHHI) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(MVGHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MVGHI) {
|
| + DCHECK_OPCODE(MVGHI);
|
| + // Move Integer (64)
|
| + DECODE_SIL_INSTRUCTION(b1, d1, i2);
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t src_addr = b1_val + d1;
|
| + WriteDW(src_addr, i2);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(MVHI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(MVHI) {
|
| + DCHECK_OPCODE(MVHI);
|
| + // Move Integer (32)
|
| + DECODE_SIL_INSTRUCTION(b1, d1, i2);
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t src_addr = b1_val + d1;
|
| + WriteW(src_addr, i2, instr);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(CHHSI) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9386,21 +9726,143 @@ EVALUATE(TBEGIN) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(TBEGINC) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LMG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LMG) {
|
| + DCHECK_OPCODE(LMG);
|
| + // Store Multiple 64-bits.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + int rb = b2;
|
| + int offset = d2;
|
| +
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
|
|
|
| -EVALUATE(SRAG) { return DecodeInstructionOriginal(instr); }
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int64_t value = ReadDW(rb_val + offset + 8 * i);
|
| + set_register((r1 + i) % 16, value);
|
| + }
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(SRAG) {
|
| + DCHECK_OPCODE(SRAG);
|
| + // 64-bit non-clobbering shift-left/right arithmetic
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int64_t r3_val = get_register(r3);
|
| + intptr_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r3_val >> shiftBits;
|
| + set_register(r1, alu_out);
|
| + SetS390ConditionCode<intptr_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLAG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLAG) {
|
| + DCHECK_OPCODE(SLAG);
|
| + // 64-bit non-clobbering shift-left/right arithmetic
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int64_t r3_val = get_register(r3);
|
| + intptr_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
|
| + alu_out = r3_val << shiftBits;
|
| + set_register(r1, alu_out);
|
| + SetS390ConditionCode<intptr_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SRLG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRLG) {
|
| + DCHECK_OPCODE(SRLG);
|
| + // For SLLG/SRLG, the 64-bit third operand is shifted the number
|
| + // of bits specified by the second-operand address, and the result is
|
| + // placed at the first-operand location. Except for when the R1 and R3
|
| + // fields designate the same register, the third operand remains
|
| + // unchanged in general register R3.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + // unsigned
|
| + uint64_t r3_val = get_register(r3);
|
| + uint64_t alu_out = 0;
|
| + alu_out = r3_val >> shiftBits;
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLLG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLLG) {
|
| + DCHECK_OPCODE(SLLG);
|
| + // For SLLG/SRLG, the 64-bit third operand is shifted the number
|
| + // of bits specified by the second-operand address, and the result is
|
| + // placed at the first-operand location. Except for when the R1 and R3
|
| + // fields designate the same register, the third operand remains
|
| + // unchanged in general register R3.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + // unsigned
|
| + uint64_t r3_val = get_register(r3);
|
| + uint64_t alu_out = 0;
|
| + alu_out = r3_val << shiftBits;
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(CSY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(RLLG) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(RLLG) {
|
| + DCHECK_OPCODE(RLLG);
|
| + // For SLLG/SRLG, the 64-bit third operand is shifted the number
|
| + // of bits specified by the second-operand address, and the result is
|
| + // placed at the first-operand location. Except for when the R1 and R3
|
| + // fields designate the same register, the third operand remains
|
| + // unchanged in general register R3.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + // unsigned
|
| + uint64_t r3_val = get_register(r3);
|
| + uint64_t alu_out = 0;
|
| + uint64_t rotateBits = r3_val >> (64 - shiftBits);
|
| + alu_out = (r3_val << shiftBits) | (rotateBits);
|
| + set_register(r1, alu_out);
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(STMG) {
|
| + DCHECK_OPCODE(STMG);
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + int rb = b2;
|
| + int offset = d2;
|
|
|
| -EVALUATE(STMG) { return DecodeInstructionOriginal(instr); }
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
|
| +
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int64_t value = get_register((r1 + i) % 16);
|
| + WriteDW(rb_val + offset + 8 * i, value);
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(STMH) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9418,23 +9880,97 @@ EVALUATE(BXLEG) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(ECAG) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(TMY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(TMY) {
|
| + DCHECK_OPCODE(TMY);
|
| + // Test Under Mask (Mem - Imm) (8)
|
| + DECODE_SIY_INSTRUCTION(b1, d1, i2);
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t d1_val = d1;
|
| + intptr_t addr = b1_val + d1_val;
|
| + uint8_t mem_val = ReadB(addr);
|
| + uint8_t imm_val = i2;
|
| + uint8_t selected_bits = mem_val & imm_val;
|
| + // CC0: Selected bits are zero
|
| + // CC1: Selected bits mixed zeros and ones
|
| + // CC3: Selected bits all ones
|
| + if (0 == selected_bits) {
|
| + condition_reg_ = CC_EQ; // CC0
|
| + } else if (selected_bits == imm_val) {
|
| + condition_reg_ = 0x1; // CC3
|
| + } else {
|
| + condition_reg_ = 0x4; // CC1
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MVIY) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(NIY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(CLIY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CLIY) {
|
| + DCHECK_OPCODE(CLIY);
|
| + DECODE_SIY_INSTRUCTION(b1, d1, i2);
|
| + // Compare Immediate (Mem - Imm) (8)
|
| + int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| + intptr_t d1_val = d1;
|
| + intptr_t addr = b1_val + d1_val;
|
| + uint8_t mem_val = ReadB(addr);
|
| + uint8_t imm_val = i2;
|
| + SetS390ConditionCode<uint8_t>(mem_val, imm_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(OIY) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(XIY) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(ASI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ASI) {
|
| + DCHECK_OPCODE(ASI);
|
| + // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
|
| + // The below static cast to 8 bit and then to 32 bit is necessary
|
| + // because siyInstr->I2Value() returns a uint8_t, which a direct
|
| + // cast to int32_t could incorrectly interpret.
|
| + DECODE_SIY_INSTRUCTION(b1, d1, i2_unsigned);
|
| + int8_t i2_8bit = static_cast<int8_t>(i2_unsigned);
|
| + int32_t i2 = static_cast<int32_t>(i2_8bit);
|
| + intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| +
|
| + int d1_val = d1;
|
| + intptr_t addr = b1_val + d1_val;
|
| +
|
| + int32_t mem_val = ReadW(addr, instr);
|
| + bool isOF = CheckOverflowForIntAdd(mem_val, i2, int32_t);
|
| + int32_t alu_out = mem_val + i2;
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + WriteW(addr, alu_out, instr);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(ALSI) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(AGSI) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(AGSI) {
|
| + DCHECK_OPCODE(AGSI);
|
| + // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
|
| + // The below static cast to 8 bit and then to 32 bit is necessary
|
| + // because siyInstr->I2Value() returns a uint8_t, which a direct
|
| + // cast to int32_t could incorrectly interpret.
|
| + DECODE_SIY_INSTRUCTION(b1, d1, i2_unsigned);
|
| + int8_t i2_8bit = static_cast<int8_t>(i2_unsigned);
|
| + int64_t i2 = static_cast<int64_t>(i2_8bit);
|
| + intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
|
| +
|
| + int d1_val = d1;
|
| + intptr_t addr = b1_val + d1_val;
|
| +
|
| + int64_t mem_val = ReadDW(addr);
|
| + int isOF = CheckOverflowForIntAdd(mem_val, i2, int64_t);
|
| + int64_t alu_out = mem_val + i2;
|
| + SetS390ConditionCode<uint64_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + WriteDW(addr, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(ALGSI) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9446,21 +9982,124 @@ EVALUATE(MVCLU) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(CLCLU) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(STMY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(STMY) {
|
| + DCHECK_OPCODE(STMY);
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // Load/Store Multiple (32)
|
| + int offset = d2;
|
| +
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
|
| +
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int32_t value = get_low_register<int32_t>((r1 + i) % 16);
|
| + WriteW(b2_val + offset + 4 * i, value, instr);
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LMH) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LMY) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LMY) {
|
| + DCHECK_OPCODE(LMY);
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // Load/Store Multiple (32)
|
| + int offset = d2;
|
| +
|
| + // Regs roll around if r3 is less than r1.
|
| + // Artifically increase r3 by 16 so we can calculate
|
| + // the number of regs stored properly.
|
| + if (r3 < r1) r3 += 16;
|
| +
|
| + int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
|
| +
|
| + // Store each register in ascending order.
|
| + for (int i = 0; i <= r3 - r1; i++) {
|
| + int32_t value = ReadW(b2_val + offset + 4 * i, instr);
|
| + set_low_register((r1 + i) % 16, value);
|
| + }
|
| + return length;
|
| +}
|
|
|
| EVALUATE(TP) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(SRAK) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRAK) {
|
| + DCHECK_OPCODE(SRAK);
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // 32-bit non-clobbering shift-left/right arithmetic
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int32_t r3_val = get_low_register<int32_t>(r3);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + alu_out = r3_val >> shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLAK) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLAK) {
|
| + DCHECK_OPCODE(SLAK);
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // 32-bit non-clobbering shift-left/right arithmetic
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + int32_t r3_val = get_low_register<int32_t>(r3);
|
| + int32_t alu_out = 0;
|
| + bool isOF = false;
|
| + isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
|
| + alu_out = r3_val << shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + SetS390ConditionCode<int32_t>(alu_out, 0);
|
| + SetS390OverflowCode(isOF);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SRLK) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SRLK) {
|
| + DCHECK_OPCODE(SRLK);
|
| + // For SLLK/SRLL, the 32-bit third operand is shifted the number
|
| + // of bits specified by the second-operand address, and the result is
|
| + // placed at the first-operand location. Except for when the R1 and R3
|
| + // fields designate the same register, the third operand remains
|
| + // unchanged in general register R3.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + // unsigned
|
| + uint32_t r3_val = get_low_register<uint32_t>(r3);
|
| + uint32_t alu_out = 0;
|
| + alu_out = r3_val >> shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SLLK) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SLLK) {
|
| + DCHECK_OPCODE(SLLK);
|
| + // For SLLK/SRLL, the 32-bit third operand is shifted the number
|
| + // of bits specified by the second-operand address, and the result is
|
| + // placed at the first-operand location. Except for when the R1 and R3
|
| + // fields designate the same register, the third operand remains
|
| + // unchanged in general register R3.
|
| + DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
|
| + // only takes rightmost 6 bits
|
| + int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
|
| + int shiftBits = (b2_val + d2) & 0x3F;
|
| + // unsigned
|
| + uint32_t r3_val = get_low_register<uint32_t>(r3);
|
| + uint32_t alu_out = 0;
|
| + alu_out = r3_val << shiftBits;
|
| + set_low_register(r1, alu_out);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LOCG) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9528,7 +10167,20 @@ EVALUATE(CGIB) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(CIB) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(LDEB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(LDEB) {
|
| + DCHECK_OPCODE(LDEB);
|
| + // Load Float
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
|
| + int rb = b2;
|
| + int rx = x2;
|
| + int offset = d2;
|
| + int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
|
| + int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
|
| + double ret =
|
| + static_cast<double>(*reinterpret_cast<float*>(rx_val + rb_val + offset));
|
| + set_d_register_from_double(r1, ret);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(LXDB) { return DecodeInstructionOriginal(instr); }
|
|
|
| @@ -9560,21 +10212,92 @@ EVALUATE(TCXB) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(SQEB) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(SQDB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SQDB) {
|
| + DCHECK_OPCODE(SQDB);
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + r1_val = std::sqrt(dbl_val);
|
| + set_d_register_from_double(r1, r1_val);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MEEB) { return DecodeInstructionOriginal(instr); }
|
|
|
| EVALUATE(KDB) { return DecodeInstructionOriginal(instr); }
|
|
|
| -EVALUATE(CDB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(CDB) {
|
| + DCHECK_OPCODE(CDB);
|
|
|
| -EVALUATE(ADB) { return DecodeInstructionOriginal(instr); }
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + SetS390ConditionCode<double>(r1_val, dbl_val);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(SDB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(ADB) {
|
| + DCHECK_OPCODE(ADB);
|
|
|
| -EVALUATE(MDB) { return DecodeInstructionOriginal(instr); }
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + r1_val += dbl_val;
|
| + set_d_register_from_double(r1, r1_val);
|
| + SetS390ConditionCode<double>(r1_val, 0);
|
| + return length;
|
| +}
|
|
|
| -EVALUATE(DDB) { return DecodeInstructionOriginal(instr); }
|
| +EVALUATE(SDB) {
|
| + DCHECK_OPCODE(SDB);
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + r1_val -= dbl_val;
|
| + set_d_register_from_double(r1, r1_val);
|
| + SetS390ConditionCode<double>(r1_val, 0);
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(MDB) {
|
| + DCHECK_OPCODE(MDB);
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + r1_val *= dbl_val;
|
| + set_d_register_from_double(r1, r1_val);
|
| + SetS390ConditionCode<double>(r1_val, 0);
|
| + return length;
|
| +}
|
| +
|
| +EVALUATE(DDB) {
|
| + DCHECK_OPCODE(DDB);
|
| + DECODE_RXE_INSTRUCTION(r1, b2, x2, 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;
|
| + double r1_val = get_double_from_d_register(r1);
|
| + double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
|
| + r1_val /= dbl_val;
|
| + set_d_register_from_double(r1, r1_val);
|
| + SetS390ConditionCode<double>(r1_val, 0);
|
| + return length;
|
| +}
|
|
|
| EVALUATE(MADB) { return DecodeInstructionOriginal(instr); }
|
|
|
|
|