Commit 479e5267 authored by Yang Qin's avatar Yang Qin Committed by Commit Bot

s390: cleanup TM family instructions

Change-Id: I3541750049c4a17a294f819f278d69943565a2a0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1707933Reviewed-by: 's avatarJunliang Yan <jyan@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#62851}
parent 980f0902
......@@ -5149,27 +5149,6 @@ EVALUATE(STM) {
return length;
}
EVALUATE(TM) {
DCHECK_OPCODE(TM);
// Test Under Mask (Mem - Imm) (8)
DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
intptr_t addr = b1_val + d1_val;
uint8_t mem_val = ReadB(addr);
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(MVI) {
UNIMPLEMENTED();
USE(instr);
......@@ -5595,7 +5574,8 @@ EVALUATE(LLILL) {
return 0;
}
inline static int TestUnderMask(uint16_t val, uint16_t mask) {
inline static int TestUnderMask(uint16_t val, uint16_t mask,
bool is_tm_or_tmy) {
// Test if all selected bits are zeros or mask is zero
if (0 == (mask & val)) {
return 0x8;
......@@ -5607,6 +5587,13 @@ inline static int TestUnderMask(uint16_t val, uint16_t mask) {
}
// Now we know selected bits mixed zeros and ones
// Test if it is TM or TMY since they have
// different CC result from TMLL/TMLH/TMHH/TMHL
if (is_tm_or_tmy) {
return 0x4;
}
// Now we know the instruction is TMLL/TMLH/TMHH/TMHL
// Test if the leftmost bit is zero or one
#if defined(__GNUC__)
int leadingZeros = __builtin_clz(mask);
......@@ -5639,7 +5626,8 @@ EVALUATE(TMLH) {
DECODE_RI_A_INSTRUCTION(instr, r1, i2);
uint32_t value = get_low_register<uint32_t>(r1) >> 16;
uint32_t mask = i2 & 0x0000FFFF;
condition_reg_ = TestUnderMask(value, mask);
bool is_tm_or_tmy = 0;
condition_reg_ = TestUnderMask(value, mask, is_tm_or_tmy);
return length; // DONE
}
......@@ -5648,20 +5636,29 @@ EVALUATE(TMLL) {
DECODE_RI_A_INSTRUCTION(instr, r1, i2);
uint32_t value = get_low_register<uint32_t>(r1) & 0x0000FFFF;
uint32_t mask = i2 & 0x0000FFFF;
condition_reg_ = TestUnderMask(value, mask);
bool is_tm_or_tmy = 0;
condition_reg_ = TestUnderMask(value, mask, is_tm_or_tmy);
return length; // DONE
}
EVALUATE(TMHH) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(TMHH);
DECODE_RI_A_INSTRUCTION(instr, r1, i2);
uint32_t value = get_high_register<uint32_t>(r1) >> 16;
uint32_t mask = i2 & 0x0000FFFF;
bool is_tm_or_tmy = 0;
condition_reg_ = TestUnderMask(value, mask, is_tm_or_tmy);
return length;
}
EVALUATE(TMHL) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(TMHL);
DECODE_RI_A_INSTRUCTION(instr, r1, i2);
uint32_t value = get_high_register<uint32_t>(r1) & 0x0000FFFF;
uint32_t mask = i2 & 0x0000FFFF;
bool is_tm_or_tmy = 0;
condition_reg_ = TestUnderMask(value, mask, is_tm_or_tmy);
return length;
}
EVALUATE(BRAS) {
......@@ -9972,26 +9969,31 @@ EVALUATE(ECAG) {
return 0;
}
EVALUATE(TM) {
DCHECK_OPCODE(TM);
// Test Under Mask (Mem - Imm) (8)
DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
intptr_t addr = b1_val + d1_val;
uint8_t mem_val = ReadB(addr);
uint8_t selected_bits = mem_val & imm_val;
// is TM
bool is_tm_or_tmy = 1;
condition_reg_ = TestUnderMask(selected_bits, imm_val, is_tm_or_tmy);
return length;
}
EVALUATE(TMY) {
DCHECK_OPCODE(TMY);
// Test Under Mask (Mem - Imm) (8)
DECODE_SIY_INSTRUCTION(b1, d1, i2);
DECODE_SIY_INSTRUCTION(b1, d1_val, imm_val);
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
}
// is TMY
bool is_tm_or_tmy = 1;
condition_reg_ = TestUnderMask(selected_bits, imm_val, is_tm_or_tmy);
return length;
}
......
......@@ -934,6 +934,98 @@ TEST(17) {
CHECK_EQ(0, static_cast<int>(res));
}
//TMHH, TMHL
TEST(18) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
Assembler assm(AssemblerOptions{});
Label done, error;
Label continue1, continue2, continue3, continue4;
Label continue5, continue6, continue7, continue8, continue9;
// selected bits all 0
__ lgfi(r1, Operand(0));
__ tmhh(r1, Operand(1));
__ beq(&done); //8
__ b(&error);
__ bind(&continue1);
__ tmhl(r1, Operand(1));
__ beq(&continue2); //8
__ b(&error);
// mask = 0
__ bind(&continue2);
__ lgfi(r1, Operand(-1));
__ tmhh(r1, Operand(0));
__ beq(&continue3); //8
__ b(&error);
__ bind(&continue3);
__ tmhh(r1, Operand(0));
__ beq(&continue4); //8
__ b(&error);
// selected bits all 1
__ bind(&continue4);
__ tmhh(r1, Operand(1));
__ b(Condition(1), &continue5); //1
__ b(&error);
__ bind(&continue5);
__ tmhl(r1, Operand(1));
__ b(Condition(1), &continue6); //1
__ b(&error);
// leftmost = 1
__ bind(&continue6);
__ lgfi(r1, Operand(0xF000F000));
__ slag(r2, r1, Operand(32));
__ tmhh(r2, Operand(0xFFFF));
__ b(Condition(2), &done); //2
__ b(&error);
__ bind(&continue7);
__ tmhl(r1, Operand(0xFFFF));
__ b(Condition(2), &continue8); //2
__ b(&error);
// leftmost = 0
__ bind(&continue8);
__ lgfi(r1, Operand(0x0FF00FF0));
__ slag(r2, r1, Operand(32));
__ tmhh(r2, Operand(0xFFFF));
__ b(Condition(4), &done); //4
__ b(&error);
__ bind(&continue9);
__ tmhl(r1, Operand(0xFFFF));
__ b(Condition(4), &done); //4
__ b(&error);
__ bind(&error);
__ lgfi(r2, Operand(1));
__ b(r14);
__ bind(&done);
__ lgfi(r2, Operand::Zero());
__ b(r14);
CodeDesc desc;
assm.GetCode(isolate, &desc);
Handle<Code> code = Factory::CodeBuilder(isolate, desc, Code::STUB).Build();
#ifdef DEBUG
code->Print();
#endif
auto f = GeneratedCode<F1>::FromCode(*code);
// f.Call(reg2, reg3, reg4, reg5, reg6) -> set the register value
intptr_t res = reinterpret_cast<intptr_t>(f.Call(0, 0, 0, 0, 0));
::printf("f() = %" V8PRIxPTR "\n", res);
CHECK_EQ(0, static_cast<int>(res));
}
#undef __
} // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment