Commit 81e75305 authored by Vasili Skurydzin's avatar Vasili Skurydzin Committed by Commit Bot

s390: assembler-s390 instruction format cleanup

Change-Id: I7736314257bba44b4336d584020744c05874aa64
Reviewed-on: https://chromium-review.googlesource.com/1067607Reviewed-by: 's avatarJunliang Yan <jyan@ca.ibm.com>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#53591}
parent afd6351d
......@@ -900,12 +900,12 @@ static inline int AssembleUnaryOp(Instruction* instr, _R _r, _M _m, _I _i) {
{ \
__ LoadlW(temp0, MemOperand(addr, offset)); \
__ llgfr(temp1, temp0); \
__ risbg(temp0, old_val, Operand(start), Operand(end), \
Operand(shift_amount), false); \
__ risbg(temp1, new_val, Operand(start), Operand(end), \
Operand(shift_amount), false); \
__ RotateInsertSelectBits(temp0, old_val, Operand(start), \
Operand(end), Operand(shift_amount), false); \
__ RotateInsertSelectBits(temp1, new_val, Operand(start), \
Operand(end), Operand(shift_amount), false); \
__ CmpAndSwap(temp0, temp1, MemOperand(addr, offset)); \
__ risbg(output, temp0, Operand(start+shift_amount), \
__ RotateInsertSelectBits(output, temp0, Operand(start+shift_amount), \
Operand(end+shift_amount), Operand(64-shift_amount), true); \
}
......@@ -1036,12 +1036,12 @@ static inline int AssembleUnaryOp(Instruction* instr, _R _r, _M _m, _I _i) {
Label do_cs; \
__ LoadlW(prev, MemOperand(addr, offset)); \
__ bind(&do_cs); \
__ risbg(temp, value, Operand(start), Operand(end), \
__ RotateInsertSelectBits(temp, value, Operand(start), Operand(end), \
Operand(static_cast<intptr_t>(shift_amount)), true); \
__ bin_inst(new_val, prev, temp); \
__ lr(temp, prev); \
__ risbg(temp, new_val, Operand(start), Operand(end), \
Operand::Zero(), false); \
__ RotateInsertSelectBits(temp, new_val, Operand(start), \
Operand(end), Operand::Zero(), false); \
__ CmpAndSwap(prev, temp, MemOperand(addr, offset)); \
__ bne(&do_cs, Label::kNear); \
} while (false)
......@@ -1807,8 +1807,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
int shiftAmount = i.InputInt32(1);
int endBit = 63 - shiftAmount;
int startBit = 63 - i.InputInt32(2);
__ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
Operand(endBit), Operand(shiftAmount), true);
__ RotateInsertSelectBits(i.OutputRegister(), i.InputRegister(0),
Operand(startBit), Operand(endBit), Operand(shiftAmount), true);
} else {
int shiftAmount = i.InputInt32(1);
int clearBit = 63 - i.InputInt32(2);
......@@ -1824,8 +1824,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
int shiftAmount = i.InputInt32(1);
int endBit = 63;
int startBit = 63 - i.InputInt32(2);
__ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
Operand(endBit), Operand(shiftAmount), true);
__ RotateInsertSelectBits(i.OutputRegister(), i.InputRegister(0),
Operand(startBit), Operand(endBit), Operand(shiftAmount), true);
} else {
int shiftAmount = i.InputInt32(1);
int clearBit = 63 - i.InputInt32(2);
......@@ -1839,8 +1839,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
int shiftAmount = i.InputInt32(1);
int endBit = 63 - i.InputInt32(2);
int startBit = 0;
__ risbg(i.OutputRegister(), i.InputRegister(0), Operand(startBit),
Operand(endBit), Operand(shiftAmount), true);
__ RotateInsertSelectBits(i.OutputRegister(), i.InputRegister(0),
Operand(startBit), Operand(endBit), Operand(shiftAmount), true);
} else {
int shiftAmount = i.InputInt32(1);
int clearBit = i.InputInt32(2);
......@@ -1971,16 +1971,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_UNARY_OP(D_DInstr(sqdbr), nullInstr, nullInstr);
break;
case kS390_FloorFloat:
__ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF);
__ fiebra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_CeilFloat:
__ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF);
__ fiebra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_TruncateFloat:
__ fiebra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
__ fiebra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
// Double operations
case kS390_ModDouble:
......@@ -2074,20 +2074,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ lpdbr(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_FloorDouble:
__ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF);
__ fidbra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_NEG_INF,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_CeilDouble:
__ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF);
__ fidbra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_POS_INF,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_TruncateDouble:
__ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0);
__ fidbra(v8::internal::Assembler::FIDBRA_ROUND_TOWARD_0,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_RoundDouble:
__ fidbra(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
v8::internal::Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0);
__ fidbra(v8::internal::Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0,
i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kS390_NegFloat:
ASSEMBLE_UNARY_OP(D_DInstr(lcebr), nullInstr, nullInstr);
......@@ -2550,8 +2550,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ LoadlW(output, MemOperand(r1, offset)); \
__ bind(&do_cs); \
__ llgfr(r0, output); \
__ risbg(r0, value, Operand(start), Operand(end), Operand(shift_amount), \
false); \
__ RotateInsertSelectBits(r0, value, Operand(start), Operand(end), \
Operand(shift_amount), false); \
__ csy(output, r0, MemOperand(r1, offset)); \
__ bne(&do_cs, Label::kNear); \
__ srl(output, Operand(shift_amount)); \
......@@ -2700,8 +2700,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kWord32Atomic##op##Uint8: \
ASSEMBLE_ATOMIC_BINOP_BYTE(inst, [&]() { \
int rotate_left = shift_amount == 0 ? 0 : 64 - shift_amount; \
__ risbg(result, prev, Operand(56), Operand(63), \
Operand(static_cast<intptr_t>(rotate_left)), true); \
__ RotateInsertSelectBits(result, prev, Operand(56), \
Operand(63), Operand(static_cast<intptr_t>(rotate_left)), \
true); \
}); \
break; \
case kWord32Atomic##op##Int16: \
......@@ -2714,8 +2715,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kWord32Atomic##op##Uint16: \
ASSEMBLE_ATOMIC_BINOP_HALFWORD(inst, [&]() { \
int rotate_left = shift_amount == 0 ? 0 : 64 - shift_amount; \
__ risbg(result, prev, Operand(48), Operand(63), \
Operand(static_cast<intptr_t>(rotate_left)), true); \
__ RotateInsertSelectBits(result, prev, Operand(48), \
Operand(63), Operand(static_cast<intptr_t>(rotate_left)), \
true); \
}); \
break;
ATOMIC_BINOP_CASE(Add, Add32)
......
......@@ -593,11 +593,6 @@ void Assembler::branchOnCond(Condition c, int branch_offset, bool is_bound) {
}
}
// 32-bit Store Multiple - short displacement (12-bits unsigned)
void Assembler::stm(Register r1, Register r2, const MemOperand& src) {
rs_form(STM, r1, r2, src.rb(), src.offset());
}
// Exception-generating instructions and debugging support.
// Stops with a non-negative code less than kNumOfWatchedStops support
// enabling/disabling and a counter feature. See simulator-s390.h .
......@@ -633,617 +628,6 @@ void Assembler::nop(int type) {
}
}
// RI1 format: <insn> R1,I2
// +--------+----+----+------------------+
// | OpCode | R1 |OpCd| I2 |
// +--------+----+----+------------------+
// 0 8 12 16 31
#define RI1_FORM_EMIT(name, op) \
void Assembler::name(Register r, const Operand& i2) { ri_form(op, r, i2); }
void Assembler::ri_form(Opcode op, Register r1, const Operand& i2) {
DCHECK(is_uint12(op));
DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate()));
emit4bytes((op & 0xFF0) * B20 | r1.code() * B20 | (op & 0xF) * B16 |
(i2.immediate() & 0xFFFF));
}
// RI2 format: <insn> M1,I2
// +--------+----+----+------------------+
// | OpCode | M1 |OpCd| I2 |
// +--------+----+----+------------------+
// 0 8 12 16 31
#define RI2_FORM_EMIT(name, op) \
void Assembler::name(Condition m, const Operand& i2) { ri_form(op, m, i2); }
void Assembler::ri_form(Opcode op, Condition m1, const Operand& i2) {
DCHECK(is_uint12(op));
DCHECK(is_uint4(m1));
DCHECK(op == BRC ? is_int16(i2.immediate()) : is_uint16(i2.immediate()));
emit4bytes((op & 0xFF0) * B20 | m1 * B20 | (op & 0xF) * B16 |
(i2.immediate() & 0xFFFF));
}
// RIE-f format: <insn> R1,R2,I3,I4,I5
// +--------+----+----+------------------+--------+--------+
// | OpCode | R1 | R2 | I3 | I4 | I5 | OpCode |
// +--------+----+----+------------------+--------+--------+
// 0 8 12 16 24 32 40 47
void Assembler::rie_f_form(Opcode op, Register r1, Register r2,
const Operand& i3, const Operand& i4,
const Operand& i5) {
DCHECK(is_uint16(op));
DCHECK(is_uint8(i3.immediate()));
DCHECK(is_uint8(i4.immediate()));
DCHECK(is_uint8(i5.immediate()));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(r2.code())) * B32 |
(static_cast<uint64_t>(i3.immediate())) * B24 |
(static_cast<uint64_t>(i4.immediate())) * B16 |
(static_cast<uint64_t>(i5.immediate())) * B8 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// RIE format: <insn> R1,R3,I2
// +--------+----+----+------------------+--------+--------+
// | OpCode | R1 | R3 | I2 |////////| OpCode |
// +--------+----+----+------------------+--------+--------+
// 0 8 12 16 32 40 47
#define RIE_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, const Operand& i2) { \
rie_form(op, r1, r3, i2); \
}
void Assembler::rie_form(Opcode op, Register r1, Register r3,
const Operand& i2) {
DCHECK(is_uint16(op));
DCHECK(is_int16(i2.immediate()));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(r3.code())) * B32 |
(static_cast<uint64_t>(i2.immediate() & 0xFFFF)) * B16 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// RS1 format: <insn> R1,R3,D2(B2)
// +--------+----+----+----+-------------+
// | OpCode | R1 | R3 | B2 | D2 |
// +--------+----+----+----+-------------+
// 0 8 12 16 20 31
#define RS1_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, Register b2, Disp d2) { \
rs_form(op, r1, r3, b2, d2); \
} \
void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \
name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \
}
void Assembler::rs_form(Opcode op, Register r1, Register r3, Register b2,
const Disp d2) {
DCHECK(is_uint12(d2));
emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 | b2.code() * B12 |
d2);
}
// RS2 format: <insn> R1,M3,D2(B2)
// +--------+----+----+----+-------------+
// | OpCode | R1 | M3 | B2 | D2 |
// +--------+----+----+----+-------------+
// 0 8 12 16 20 31
#define RS2_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Condition m3, Register b2, Disp d2) { \
rs_form(op, r1, m3, b2, d2); \
} \
void Assembler::name(Register r1, Condition m3, const MemOperand& opnd) { \
name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \
}
void Assembler::rs_form(Opcode op, Register r1, Condition m3, Register b2,
const Disp d2) {
DCHECK(is_uint12(d2));
emit4bytes(op * B24 | r1.code() * B20 | m3 * B16 | b2.code() * B12 | d2);
}
// RSI format: <insn> R1,R3,I2
// +--------+----+----+------------------+
// | OpCode | R1 | R3 | RI2 |
// +--------+----+----+------------------+
// 0 8 12 16 31
#define RSI_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, const Operand& i2) { \
rsi_form(op, r1, r3, i2); \
}
void Assembler::rsi_form(Opcode op, Register r1, Register r3,
const Operand& i2) {
DCHECK(is_uint8(op));
DCHECK(is_uint16(i2.immediate()));
emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 |
(i2.immediate() & 0xFFFF));
}
// RSL format: <insn> R1,R3,D2(B2)
// +--------+----+----+----+-------------+--------+--------+
// | OpCode | L1 | | B2 | D2 | | OpCode |
// +--------+----+----+----+-------------+--------+--------+
// 0 8 12 16 20 32 40 47
#define RSL_FORM_EMIT(name, op) \
void Assembler::name(Length l1, Register b2, Disp d2) { \
rsl_form(op, l1, b2, d2); \
}
void Assembler::rsl_form(Opcode op, Length l1, Register b2, Disp d2) {
DCHECK(is_uint16(op));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(l1)) * B36 |
(static_cast<uint64_t>(b2.code())) * B28 |
(static_cast<uint64_t>(d2)) * B16 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// RXE format: <insn> R1,D2(X2,B2)
// +--------+----+----+----+-------------+--------+--------+
// | OpCode | R1 | X2 | B2 | D2 |////////| OpCode |
// +--------+----+----+----+-------------+--------+--------+
// 0 8 12 16 20 32 40 47
#define RXE_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register x2, Register b2, Disp d2) { \
rxe_form(op, r1, x2, b2, d2); \
} \
void Assembler::name(Register r1, const MemOperand& opnd) { \
name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \
opnd.getDisplacement()); \
}
void Assembler::rxe_form(Opcode op, Register r1, Register x2, Register b2,
Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint16(op));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(x2.code())) * B32 |
(static_cast<uint64_t>(b2.code())) * B28 |
(static_cast<uint64_t>(d2 & 0x0FFF)) * B16 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// RRS format: <insn> R1,R2,M3,D4(B4)
// +--------+----+----+----+-------------+----+---+--------+
// | OpCode | R1 | R2 | B4 | D4 | M3 |///| OpCode |
// +--------+----+----+----+-------------+----+---+--------+
// 0 8 12 16 20 32 36 40 47
#define RRS_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r2, Register b4, Disp d4, \
Condition m3) { \
rrs_form(op, r1, r2, b4, d4, m3); \
} \
void Assembler::name(Register r1, Register r2, Condition m3, \
const MemOperand& opnd) { \
name(r1, r2, opnd.getBaseRegister(), opnd.getDisplacement(), m3); \
}
void Assembler::rrs_form(Opcode op, Register r1, Register r2, Register b4,
Disp d4, Condition m3) {
DCHECK(is_uint12(d4));
DCHECK(is_uint16(op));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(r2.code())) * B32 |
(static_cast<uint64_t>(b4.code())) * B28 |
(static_cast<uint64_t>(d4)) * B16 |
(static_cast<uint64_t>(m3)) << 12 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// RIS format: <insn> R1,I2,M3,D4(B4)
// +--------+----+----+----+-------------+--------+--------+
// | OpCode | R1 | M3 | B4 | D4 | I2 | OpCode |
// +--------+----+----+----+-------------+--------+--------+
// 0 8 12 16 20 32 40 47
#define RIS_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Condition m3, Register b4, Disp d4, \
const Operand& i2) { \
ris_form(op, r1, m3, b4, d4, i2); \
} \
void Assembler::name(Register r1, const Operand& i2, Condition m3, \
const MemOperand& opnd) { \
name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement(), i2); \
}
void Assembler::ris_form(Opcode op, Register r1, Condition m3, Register b4,
Disp d4, const Operand& i2) {
DCHECK(is_uint12(d4));
DCHECK(is_uint16(op));
DCHECK(is_uint8(i2.immediate()));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(m3)) * B32 |
(static_cast<uint64_t>(b4.code())) * B28 |
(static_cast<uint64_t>(d4)) * B16 |
(static_cast<uint64_t>(i2.immediate())) << 8 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// S format: <insn> D2(B2)
// +------------------+----+-------------+
// | OpCode | B2 | D2 |
// +------------------+----+-------------+
// 0 16 20 31
#define S_FORM_EMIT(name, op) \
void Assembler::name(Register b1, Disp d2) { s_form(op, b1, d2); } \
void Assembler::name(const MemOperand& opnd) { \
name(opnd.getBaseRegister(), opnd.getDisplacement()); \
}
void Assembler::s_form(Opcode op, Register b1, Disp d2) {
DCHECK(is_uint12(d2));
emit4bytes(op << 16 | b1.code() * B12 | d2);
}
// SI format: <insn> D1(B1),I2
// +--------+---------+----+-------------+
// | OpCode | I2 | B1 | D1 |
// +--------+---------+----+-------------+
// 0 8 16 20 31
#define SI_FORM_EMIT(name, op) \
void Assembler::name(const Operand& i2, Register b1, Disp d1) { \
si_form(op, i2, b1, d1); \
} \
void Assembler::name(const MemOperand& opnd, const Operand& i2) { \
name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \
}
void Assembler::si_form(Opcode op, const Operand& i2, Register b1, Disp d1) {
emit4bytes((op & 0x00FF) << 24 | i2.immediate() * B16 | b1.code() * B12 | d1);
}
// SIY format: <insn> D1(B1),I2
// +--------+---------+----+-------------+--------+--------+
// | OpCode | I2 | B1 | DL1 | DH1 | OpCode |
// +--------+---------+----+-------------+--------+--------+
// 0 8 16 20 32 36 40 47
#define SIY_FORM_EMIT(name, op) \
void Assembler::name(const Operand& i2, Register b1, Disp d1) { \
siy_form(op, i2, b1, d1); \
} \
void Assembler::name(const MemOperand& opnd, const Operand& i2) { \
name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \
}
void Assembler::siy_form(Opcode op, const Operand& i2, Register b1, Disp d1) {
DCHECK(is_uint20(d1) || is_int20(d1));
DCHECK(is_uint16(op));
DCHECK(is_uint8(i2.immediate()));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(i2.immediate())) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1 & 0x0FFF)) * B16 |
(static_cast<uint64_t>(d1 & 0x0FF000)) >> 4 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// SIL format: <insn> D1(B1),I2
// +------------------+----+-------------+-----------------+
// | OpCode | B1 | D1 | I2 |
// +------------------+----+-------------+-----------------+
// 0 16 20 32 47
#define SIL_FORM_EMIT(name, op) \
void Assembler::name(Register b1, Disp d1, const Operand& i2) { \
sil_form(op, b1, d1, i2); \
} \
void Assembler::name(const MemOperand& opnd, const Operand& i2) { \
name(opnd.getBaseRegister(), opnd.getDisplacement(), i2); \
}
void Assembler::sil_form(Opcode op, Register b1, Disp d1, const Operand& i2) {
DCHECK(is_uint12(d1));
DCHECK(is_uint16(op));
DCHECK(is_uint16(i2.immediate()));
uint64_t code = (static_cast<uint64_t>(op)) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(i2.immediate()));
emit6bytes(code);
}
// RXF format: <insn> R1,R3,D2(X2,B2)
// +--------+----+----+----+-------------+----+---+--------+
// | OpCode | R3 | X2 | B2 | D2 | R1 |///| OpCode |
// +--------+----+----+----+-------------+----+---+--------+
// 0 8 12 16 20 32 36 40 47
#define RXF_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, Register b2, Register x2, \
Disp d2) { \
rxf_form(op, r1, r3, b2, x2, d2); \
} \
void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \
name(r1, r3, opnd.getBaseRegister(), opnd.getIndexRegister(), \
opnd.getDisplacement()); \
}
void Assembler::rxf_form(Opcode op, Register r1, Register r3, Register b2,
Register x2, Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint16(op));
uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 |
(static_cast<uint64_t>(r3.code())) * B36 |
(static_cast<uint64_t>(x2.code())) * B32 |
(static_cast<uint64_t>(b2.code())) * B28 |
(static_cast<uint64_t>(d2)) * B16 |
(static_cast<uint64_t>(r1.code())) * B12 |
(static_cast<uint64_t>(op & 0x00FF));
emit6bytes(code);
}
// SS1 format: <insn> D1(L,B1),D2(B3)
// +--------+----+----+----+-------------+----+------------+
// | OpCode | L | B1 | D1 | B2 | D2 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SS1_FORM_EMIT(name, op) \
void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l) { \
ss_form(op, l, b1, d1, b2, d2); \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \
Length length) { \
name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \
opnd2.getBaseRegister(), opnd2.getDisplacement(), length); \
}
void Assembler::ss_form(Opcode op, Length l, Register b1, Disp d1, Register b2,
Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint8(op));
DCHECK(is_uint8(l));
uint64_t code =
(static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l)) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2));
emit6bytes(code);
}
// SS2 format: <insn> D1(L1,B1), D2(L3,B3)
// +--------+----+----+----+-------------+----+------------+
// | OpCode | L1 | L2 | B1 | D1 | B2 | D2 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SS2_FORM_EMIT(name, op) \
void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l1, \
Length l2) { \
ss_form(op, l1, l2, b1, d1, b2, d2); \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \
Length length1, Length length2) { \
name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \
opnd2.getBaseRegister(), opnd2.getDisplacement(), length1, length2); \
}
void Assembler::ss_form(Opcode op, Length l1, Length l2, Register b1, Disp d1,
Register b2, Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint8(op));
DCHECK(is_uint4(l2));
DCHECK(is_uint4(l1));
uint64_t code =
(static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 |
(static_cast<uint64_t>(l2)) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2));
emit6bytes(code);
}
// SS3 format: <insn> D1(L1,B1), D2(I3,B2)
// +--------+----+----+----+-------------+----+------------+
// | OpCode | L1 | I3 | B1 | D1 | B2 | D2 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SS3_FORM_EMIT(name, op) \
void Assembler::name(const Operand& i3, Register b1, Disp d1, Register b2, \
Disp d2, Length l1) { \
ss_form(op, l1, i3, b1, d1, b2, d2); \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \
Length length) { \
DCHECK(false); \
}
void Assembler::ss_form(Opcode op, Length l1, const Operand& i3, Register b1,
Disp d1, Register b2, Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint8(op));
DCHECK(is_uint4(l1));
DCHECK(is_uint4(i3.immediate()));
uint64_t code =
(static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 |
(static_cast<uint64_t>(i3.immediate())) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2));
emit6bytes(code);
}
// SS4 format: <insn> D1(R1,B1), D2(R3,B2)
// +--------+----+----+----+-------------+----+------------+
// | OpCode | R1 | R3 | B1 | D1 | B2 | D2 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SS4_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, Register b1, Disp d1, \
Register b2, Disp d2) { \
ss_form(op, r1, r3, b1, d1, b2, d2); \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \
DCHECK(false); \
}
void Assembler::ss_form(Opcode op, Register r1, Register r3, Register b1,
Disp d1, Register b2, Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint8(op));
uint64_t code = (static_cast<uint64_t>(op)) * B40 |
(static_cast<uint64_t>(r1.code())) * B36 |
(static_cast<uint64_t>(r3.code())) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 |
(static_cast<uint64_t>(d2));
emit6bytes(code);
}
// SS5 format: <insn> D1(R1,B1), D2(R3,B2)
// +--------+----+----+----+-------------+----+------------+
// | OpCode | R1 | R3 | B2 | D2 | B4 | D4 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SS5_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r3, Register b2, Disp d2, \
Register b4, Disp d4) { \
ss_form(op, r1, r3, b2, d2, b4, d4); /*SS5 use the same form as SS4*/ \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \
DCHECK(false); \
}
#define SS6_FORM_EMIT(name, op) SS1_FORM_EMIT(name, op)
// SSE format: <insn> D1(B1),D2(B2)
// +------------------+----+-------------+----+------------+
// | OpCode | B1 | D1 | B2 | D2 |
// +------------------+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SSE_FORM_EMIT(name, op) \
void Assembler::name(Register b1, Disp d1, Register b2, Disp d2) { \
sse_form(op, b1, d1, b2, d2); \
} \
void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \
name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \
opnd2.getBaseRegister(), opnd2.getDisplacement()); \
}
void Assembler::sse_form(Opcode op, Register b1, Disp d1, Register b2,
Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint16(op));
uint64_t code = (static_cast<uint64_t>(op)) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 |
(static_cast<uint64_t>(d2));
emit6bytes(code);
}
// SSF format: <insn> R3, D1(B1),D2(B2),R3
// +--------+----+----+----+-------------+----+------------+
// | OpCode | R3 |OpCd| B1 | D1 | B2 | D2 |
// +--------+----+----+----+-------------+----+------------+
// 0 8 12 16 20 32 36 47
#define SSF_FORM_EMIT(name, op) \
void Assembler::name(Register r3, Register b1, Disp d1, Register b2, \
Disp d2) { \
ssf_form(op, r3, b1, d1, b2, d2); \
} \
void Assembler::name(Register r3, const MemOperand& opnd1, \
const MemOperand& opnd2) { \
name(r3, opnd1.getBaseRegister(), opnd1.getDisplacement(), \
opnd2.getBaseRegister(), opnd2.getDisplacement()); \
}
void Assembler::ssf_form(Opcode op, Register r3, Register b1, Disp d1,
Register b2, Disp d2) {
DCHECK(is_uint12(d2));
DCHECK(is_uint12(d1));
DCHECK(is_uint12(op));
uint64_t code = (static_cast<uint64_t>(op & 0xFF0)) * B36 |
(static_cast<uint64_t>(r3.code())) * B36 |
(static_cast<uint64_t>(op & 0x00F)) * B32 |
(static_cast<uint64_t>(b1.code())) * B28 |
(static_cast<uint64_t>(d1)) * B16 |
(static_cast<uint64_t>(b2.code())) * B12 |
(static_cast<uint64_t>(d2));
emit6bytes(code);
}
// RRF1 format: <insn> R1,R2,R3
// +------------------+----+----+----+----+
// | OpCode | R3 | | R1 | R2 |
// +------------------+----+----+----+----+
// 0 16 20 24 28 31
#define RRF1_FORM_EMIT(name, op) \
void Assembler::name(Register r1, Register r2, Register r3) { \
rrf1_form(op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code()); \
}
void Assembler::rrf1_form(Opcode op, Register r1, Register r2, Register r3) {
uint32_t code = op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code();
emit4bytes(code);
}
void Assembler::rrf1_form(uint32_t code) { emit4bytes(code); }
// RRF2 format: <insn> R1,R2,M3
// +------------------+----+----+----+----+
// | OpCode | M3 | | R1 | R2 |
// +------------------+----+----+----+----+
// 0 16 20 24 28 31
#define RRF2_FORM_EMIT(name, op) \
void Assembler::name(Condition m3, Register r1, Register r2) { \
rrf2_form(op << 16 | m3 * B12 | r1.code() * B4 | r2.code()); \
}
void Assembler::rrf2_form(uint32_t code) { emit4bytes(code); }
// RRF3 format: <insn> R1,R2,R3,M4
// +------------------+----+----+----+----+
// | OpCode | R3 | M4 | R1 | R2 |
// +------------------+----+----+----+----+
// 0 16 20 24 28 31
#define RRF3_FORM_EMIT(name, op) \
void Assembler::name(Register r3, Conition m4, Register r1, Register r2) { \
rrf3_form(op << 16 | r3.code() * B12 | m4 * B8 | r1.code() * B4 | \
r2.code()); \
}
void Assembler::rrf3_form(uint32_t code) { emit4bytes(code); }
// RRF-e format: <insn> R1,M3,R2,M4
// +------------------+----+----+----+----+
// | OpCode | M3 | M4 | R1 | R2 |
// +------------------+----+----+----+----+
// 0 16 20 24 28 31
void Assembler::rrfe_form(Opcode op, Condition m3, Condition m4, Register r1,
Register r2) {
uint32_t code = op << 16 | m3 * B12 | m4 * B8 | r1.code() * B4 | r2.code();
emit4bytes(code);
}
// end of S390 Instruction generation
// start of S390 instruction
SS1_FORM_EMIT(ed, ED)
SS1_FORM_EMIT(mvn, MVN)
SS1_FORM_EMIT(nc, NC)
SI_FORM_EMIT(ni, NI)
RI1_FORM_EMIT(nilh, NILH)
RI1_FORM_EMIT(nill, NILL)
RI1_FORM_EMIT(oill, OILL)
RI1_FORM_EMIT(tmll, TMLL)
SS1_FORM_EMIT(tr, TR)
S_FORM_EMIT(ts, TS)
// -------------------------
// Load Address Instructions
// -------------------------
......@@ -1252,381 +636,12 @@ void Assembler::larl(Register r1, Label* l) {
larl(r1, Operand(branch_offset(l)));
}
// -----------------
// Load Instructions
// -----------------
// Load Halfword Immediate (32)
void Assembler::lhi(Register r, const Operand& imm) { ri_form(LHI, r, imm); }
// Load Halfword Immediate (64)
void Assembler::lghi(Register r, const Operand& imm) { ri_form(LGHI, r, imm); }
// -------------------------
// Load Logical Instructions
// -------------------------
// Load On Condition R-R (32)
void Assembler::locr(Condition m3, Register r1, Register r2) {
rrf2_form(LOCR << 16 | m3 * B12 | r1.code() * B4 | r2.code());
}
// Load On Condition R-R (64)
void Assembler::locgr(Condition m3, Register r1, Register r2) {
rrf2_form(LOCGR << 16 | m3 * B12 | r1.code() * B4 | r2.code());
}
// -------------------
// Branch Instructions
// -------------------
// Branch on Count (64)
// Branch Relative and Save (32)
void Assembler::bras(Register r, const Operand& opnd) {
ri_form(BRAS, r, opnd);
}
// Branch relative on Condition (32)
void Assembler::brc(Condition c, const Operand& opnd) { ri_form(BRC, c, opnd); }
// Branch On Count (32)
void Assembler::brct(Register r1, const Operand& imm) {
// BRCT encodes # of halfwords, so divide by 2.
int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2;
Operand halfwordOp = Operand(numHalfwords);
halfwordOp.setBits(16);
ri_form(BRCT, r1, halfwordOp);
}
// Branch On Count (32)
void Assembler::brctg(Register r1, const Operand& imm) {
// BRCTG encodes # of halfwords, so divide by 2.
int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2;
Operand halfwordOp = Operand(numHalfwords);
halfwordOp.setBits(16);
ri_form(BRCTG, r1, halfwordOp);
}
// --------------------
// Compare Instructions
// --------------------
// Compare Halfword Immediate (32)
void Assembler::chi(Register r, const Operand& opnd) { ri_form(CHI, r, opnd); }
// Compare Halfword Immediate (64)
void Assembler::cghi(Register r, const Operand& opnd) {
ri_form(CGHI, r, opnd);
}
// ----------------------------
// Compare Logical Instructions
// ----------------------------
// Compare Immediate (Mem - Imm) (8)
void Assembler::cli(const MemOperand& opnd, const Operand& imm) {
si_form(CLI, imm, opnd.rb(), opnd.offset());
}
// Compare Immediate (Mem - Imm) (8)
void Assembler::cliy(const MemOperand& opnd, const Operand& imm) {
siy_form(CLIY, imm, opnd.rb(), opnd.offset());
}
// Compare logical - mem to mem operation
void Assembler::clc(const MemOperand& opnd1, const MemOperand& opnd2,
Length length) {
ss_form(CLC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(),
opnd2.getBaseRegister(), opnd2.getDisplacement());
}
// ----------------------------
// Test Under Mask Instructions
// ----------------------------
// Test Under Mask (Mem - Imm) (8)
void Assembler::tm(const MemOperand& opnd, const Operand& imm) {
si_form(TM, imm, opnd.rb(), opnd.offset());
}
// Test Under Mask (Mem - Imm) (8)
void Assembler::tmy(const MemOperand& opnd, const Operand& imm) {
siy_form(TMY, imm, opnd.rb(), opnd.offset());
}
// -------------------------------
// Rotate and Insert Selected Bits
// -------------------------------
// Rotate-And-Insert-Selected-Bits
void Assembler::risbg(Register dst, Register src, const Operand& startBit,
const Operand& endBit, const Operand& shiftAmt,
bool zeroBits) {
// High tag the top bit of I4/EndBit to zero out any unselected bits
if (zeroBits)
rie_f_form(RISBG, dst, src, startBit, Operand(endBit.immediate() | 0x80),
shiftAmt);
else
rie_f_form(RISBG, dst, src, startBit, endBit, shiftAmt);
}
// Rotate-And-Insert-Selected-Bits
void Assembler::risbgn(Register dst, Register src, const Operand& startBit,
const Operand& endBit, const Operand& shiftAmt,
bool zeroBits) {
// High tag the top bit of I4/EndBit to zero out any unselected bits
if (zeroBits)
rie_f_form(RISBGN, dst, src, startBit, Operand(endBit.immediate() | 0x80),
shiftAmt);
else
rie_f_form(RISBGN, dst, src, startBit, endBit, shiftAmt);
}
// ---------------------------
// Move Character Instructions
// ---------------------------
// Move character - mem to mem operation
void Assembler::mvc(const MemOperand& opnd1, const MemOperand& opnd2,
uint32_t length) {
ss_form(MVC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(),
opnd2.getBaseRegister(), opnd2.getDisplacement());
}
// -----------------------
// 32-bit Add Instructions
// -----------------------
// Add Halfword Immediate (32)
void Assembler::ahi(Register r1, const Operand& i2) { ri_form(AHI, r1, i2); }
// Add Halfword Immediate (32)
void Assembler::ahik(Register r1, Register r3, const Operand& i2) {
rie_form(AHIK, r1, r3, i2);
}
// Add Register-Register-Register (32)
void Assembler::ark(Register r1, Register r2, Register r3) {
rrf1_form(ARK, r1, r2, r3);
}
// Add Storage-Imm (32)
void Assembler::asi(const MemOperand& opnd, const Operand& imm) {
DCHECK(is_int8(imm.immediate()));
DCHECK(is_int20(opnd.offset()));
siy_form(ASI, Operand(0xFF & imm.immediate()), opnd.rb(),
0xFFFFF & opnd.offset());
}
// -----------------------
// 64-bit Add Instructions
// -----------------------
// Add Halfword Immediate (64)
void Assembler::aghi(Register r1, const Operand& i2) { ri_form(AGHI, r1, i2); }
// Add Halfword Immediate (64)
void Assembler::aghik(Register r1, Register r3, const Operand& i2) {
rie_form(AGHIK, r1, r3, i2);
}
// Add Register-Register-Register (64)
void Assembler::agrk(Register r1, Register r2, Register r3) {
rrf1_form(AGRK, r1, r2, r3);
}
// Add Storage-Imm (64)
void Assembler::agsi(const MemOperand& opnd, const Operand& imm) {
DCHECK(is_int8(imm.immediate()));
DCHECK(is_int20(opnd.offset()));
siy_form(AGSI, Operand(0xFF & imm.immediate()), opnd.rb(),
0xFFFFF & opnd.offset());
}
// -------------------------------
// 32-bit Add Logical Instructions
// -------------------------------
// Add Logical Register-Register-Register (32)
void Assembler::alrk(Register r1, Register r2, Register r3) {
rrf1_form(ALRK, r1, r2, r3);
}
// -------------------------------
// 64-bit Add Logical Instructions
// -------------------------------
// Add Logical Register-Register-Register (64)
void Assembler::algrk(Register r1, Register r2, Register r3) {
rrf1_form(ALGRK, r1, r2, r3);
}
// ----------------------------
// 32-bit Subtract Instructions
// ----------------------------
// Subtract Register-Register-Register (32)
void Assembler::srk(Register r1, Register r2, Register r3) {
rrf1_form(SRK, r1, r2, r3);
}
// ----------------------------
// 64-bit Subtract Instructions
// ----------------------------
// Subtract Register-Register-Register (64)
void Assembler::sgrk(Register r1, Register r2, Register r3) {
rrf1_form(SGRK, r1, r2, r3);
}
// ------------------------------------
// 32-bit Subtract Logical Instructions
// ------------------------------------
// Subtract Logical Register-Register-Register (32)
void Assembler::slrk(Register r1, Register r2, Register r3) {
rrf1_form(SLRK, r1, r2, r3);
}
// ------------------------------------
// 64-bit Subtract Logical Instructions
// ------------------------------------
// Subtract Logical Register-Register-Register (64)
void Assembler::slgrk(Register r1, Register r2, Register r3) {
rrf1_form(SLGRK, r1, r2, r3);
}
// ----------------------------
// 32-bit Multiply Instructions
// ----------------------------
// Multiply Halfword Immediate (32)
void Assembler::mhi(Register r1, const Operand& opnd) {
ri_form(MHI, r1, opnd);
}
// Multiply Single Register (32)
void Assembler::msrkc(Register r1, Register r2, Register r3) {
rrf1_form(MSRKC, r1, r2, r3);
}
// Multiply Single Register (64)
void Assembler::msgrkc(Register r1, Register r2, Register r3) {
rrf1_form(MSGRKC, r1, r2, r3);
}
// ----------------------------
// 64-bit Multiply Instructions
// ----------------------------
// Multiply Halfword Immediate (64)
void Assembler::mghi(Register r1, const Operand& opnd) {
ri_form(MGHI, r1, opnd);
}
// --------------------
// Bitwise Instructions
// --------------------
// AND Register-Register-Register (32)
void Assembler::nrk(Register r1, Register r2, Register r3) {
rrf1_form(NRK, r1, r2, r3);
}
// AND Register-Register-Register (64)
void Assembler::ngrk(Register r1, Register r2, Register r3) {
rrf1_form(NGRK, r1, r2, r3);
}
// OR Register-Register-Register (32)
void Assembler::ork(Register r1, Register r2, Register r3) {
rrf1_form(ORK, r1, r2, r3);
}
// OR Register-Register-Register (64)
void Assembler::ogrk(Register r1, Register r2, Register r3) {
rrf1_form(OGRK, r1, r2, r3);
}
// XOR Register-Register-Register (32)
void Assembler::xrk(Register r1, Register r2, Register r3) {
rrf1_form(XRK, r1, r2, r3);
}
// XOR Register-Register-Register (64)
void Assembler::xgrk(Register r1, Register r2, Register r3) {
rrf1_form(XGRK, r1, r2, r3);
}
// XOR Storage-Storage
void Assembler::xc(const MemOperand& opnd1, const MemOperand& opnd2,
Length length) {
ss_form(XC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(),
opnd2.getBaseRegister(), opnd2.getDisplacement());
}
void Assembler::EnsureSpaceFor(int space_needed) {
if (buffer_space() <= (kGap + space_needed)) {
GrowBuffer(space_needed);
}
}
// Shift Left Single Logical (32)
void Assembler::sll(Register r1, Register opnd) {
DCHECK(opnd != r0);
rs_form(SLL, r1, r0, opnd, 0);
}
// Shift Left Single Logical (32)
void Assembler::sll(Register r1, const Operand& opnd) {
rs_form(SLL, r1, r0, r0, opnd.immediate());
}
// Shift Left Double Logical (64)
void Assembler::sldl(Register r1, Register b2, const Operand& opnd) {
DCHECK_EQ(r1.code() % 2, 0);
rs_form(SLDL, r1, r0, b2, opnd.immediate());
}
// Shift Right Single Logical (32)
void Assembler::srl(Register r1, Register opnd) {
DCHECK(opnd != r0);
rs_form(SRL, r1, r0, opnd, 0);
}
// Shift Right Double Arith (64)
void Assembler::srda(Register r1, Register b2, const Operand& opnd) {
DCHECK_EQ(r1.code() % 2, 0);
rs_form(SRDA, r1, r0, b2, opnd.immediate());
}
// Shift Right Double Logical (64)
void Assembler::srdl(Register r1, Register b2, const Operand& opnd) {
DCHECK_EQ(r1.code() % 2, 0);
rs_form(SRDL, r1, r0, b2, opnd.immediate());
}
// Shift Right Single Logical (32)
void Assembler::srl(Register r1, const Operand& opnd) {
rs_form(SRL, r1, r0, r0, opnd.immediate());
}
// Shift Left Single (32)
void Assembler::sla(Register r1, Register opnd) {
DCHECK(opnd != r0);
rs_form(SLA, r1, r0, opnd, 0);
}
// Shift Left Single (32)
void Assembler::sla(Register r1, const Operand& opnd) {
rs_form(SLA, r1, r0, r0, opnd.immediate());
}
// Shift Right Single (32)
void Assembler::sra(Register r1, Register opnd) {
DCHECK(opnd != r0);
rs_form(SRA, r1, r0, opnd, 0);
}
// Shift Right Single (32)
void Assembler::sra(Register r1, const Operand& opnd) {
rs_form(SRA, r1, r0, r0, opnd.immediate());
}
// Shift Right Double
void Assembler::srda(Register r1, const Operand& opnd) {
DCHECK_EQ(r1.code() % 2, 0);
rs_form(SRDA, r1, r0, r0, opnd.immediate());
}
// Shift Right Double Logical
void Assembler::srdl(Register r1, const Operand& opnd) {
DCHECK_EQ(r1.code() % 2, 0);
rs_form(SRDL, r1, r0, r0, opnd.immediate());
}
void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
......@@ -1650,215 +665,6 @@ void Assembler::jump(Handle<Code> target, RelocInfo::Mode rmode,
brcl(cond, Operand(target_index));
}
// 32-bit Load Multiple - short displacement (12-bits unsigned)
void Assembler::lm(Register r1, Register r2, const MemOperand& src) {
rs_form(LM, r1, r2, src.rb(), src.offset());
}
// 32-bit Compare and Swap
void Assembler::cs(Register r1, Register r2, const MemOperand& src) {
rs_form(CS, r1, r2, src.rb(), src.offset());
}
// Move integer (32)
void Assembler::mvhi(const MemOperand& opnd1, const Operand& i2) {
sil_form(MVHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2);
}
// Move integer (64)
void Assembler::mvghi(const MemOperand& opnd1, const Operand& i2) {
sil_form(MVGHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2);
}
// Insert Immediate (high high)
void Assembler::iihh(Register r1, const Operand& opnd) {
ri_form(IIHH, r1, opnd);
}
// Insert Immediate (high low)
void Assembler::iihl(Register r1, const Operand& opnd) {
ri_form(IIHL, r1, opnd);
}
// Insert Immediate (low high)
void Assembler::iilh(Register r1, const Operand& opnd) {
ri_form(IILH, r1, opnd);
}
// Insert Immediate (low low)
void Assembler::iill(Register r1, const Operand& opnd) {
ri_form(IILL, r1, opnd);
}
// GPR <-> FPR Instructions
// Floating point instructions
//
// Add Register-Storage (LB)
void Assembler::adb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(ADB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Add Register-Storage (LB)
void Assembler::aeb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(AEB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Sub Register-Storage (LB)
void Assembler::seb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(SEB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Divide Register-Storage (LB)
void Assembler::ddb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(DDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Divide Register-Storage (LB)
void Assembler::deb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(DEB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Multiply Register-Storage (LB)
void Assembler::mdb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(MDB, Register::from_code(r1.code()), opnd.rb(), opnd.rx(),
opnd.offset());
}
// Multiply Register-Storage (LB)
void Assembler::meeb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(MEEB, Register::from_code(r1.code()), opnd.rb(), opnd.rx(),
opnd.offset());
}
// Subtract Register-Storage (LB)
void Assembler::sdb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(SDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
void Assembler::ceb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(CEB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
void Assembler::cdb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(CDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Square Root (LB)
void Assembler::sqdb(DoubleRegister r1, const MemOperand& opnd) {
rxe_form(SQDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Convert to Fixed point (64<-S)
void Assembler::cgebr(Condition m, Register r1, DoubleRegister r2) {
rrfe_form(CGEBR, m, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert to Fixed point (64<-L)
void Assembler::cgdbr(Condition m, Register r1, DoubleRegister r2) {
rrfe_form(CGDBR, m, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert to Fixed point (32<-L)
void Assembler::cfdbr(Condition m, Register r1, DoubleRegister r2) {
rrfe_form(CFDBR, m, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert to Fixed Logical (64<-L)
void Assembler::clgdbr(Condition m3, Condition m4, Register r1,
DoubleRegister r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CLGDBR, m3, m4, r1, Register::from_code(r2.code()));
}
// Convert to Fixed Logical (64<-F32)
void Assembler::clgebr(Condition m3, Condition m4, Register r1,
DoubleRegister r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CLGEBR, m3, m4, r1, Register::from_code(r2.code()));
}
// Convert to Fixed Logical (32<-F64)
void Assembler::clfdbr(Condition m3, Condition m4, Register r1,
DoubleRegister r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CLFDBR, m3, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert to Fixed Logical (32<-F32)
void Assembler::clfebr(Condition m3, Condition m4, Register r1,
DoubleRegister r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CLFEBR, m3, Condition(0), r1, Register::from_code(r2.code()));
}
// Convert from Fixed Logical (L<-64)
void Assembler::celgbr(Condition m3, Condition m4, DoubleRegister r1,
Register r2) {
DCHECK_EQ(m3, Condition(0));
DCHECK_EQ(m4, Condition(0));
rrfe_form(CELGBR, Condition(0), Condition(0), Register::from_code(r1.code()),
r2);
}
// Convert from Fixed Logical (F32<-32)
void Assembler::celfbr(Condition m3, Condition m4, DoubleRegister r1,
Register r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CELFBR, m3, Condition(0), Register::from_code(r1.code()), r2);
}
// Convert from Fixed Logical (L<-64)
void Assembler::cdlgbr(Condition m3, Condition m4, DoubleRegister r1,
Register r2) {
DCHECK_EQ(m3, Condition(0));
DCHECK_EQ(m4, Condition(0));
rrfe_form(CDLGBR, Condition(0), Condition(0), Register::from_code(r1.code()),
r2);
}
// Convert from Fixed Logical (L<-32)
void Assembler::cdlfbr(Condition m3, Condition m4, DoubleRegister r1,
Register r2) {
DCHECK_EQ(m4, Condition(0));
rrfe_form(CDLFBR, m3, Condition(0), Register::from_code(r1.code()), r2);
}
// Convert from Fixed point (S<-32)
void Assembler::cefbr(Condition m3, DoubleRegister r1, Register r2) {
rrfe_form(CEFBR, m3, Condition(0), Register::from_code(r1.code()), r2);
}
// Convert to Fixed point (32<-S)
void Assembler::cfebr(Condition m3, Register r1, DoubleRegister r2) {
rrfe_form(CFEBR, m3, Condition(0), r1, Register::from_code(r2.code()));
}
// Load (L <- S)
void Assembler::ldeb(DoubleRegister d1, const MemOperand& opnd) {
rxe_form(LDEB, Register::from_code(d1.code()), opnd.rx(), opnd.rb(),
opnd.offset());
}
// Load FP Integer
void Assembler::fiebra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) {
rrf2_form(FIEBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code());
}
// Load FP Integer
void Assembler::fidbra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) {
rrf2_form(FIDBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code());
}
// end of S390instructions
bool Assembler::IsNop(SixByteInstr instr, int type) {
......
......@@ -347,18 +347,6 @@ C_REGISTERS(DECLARE_C_REGISTER)
// Class Operand represents a shifter operand in data processing instructions
// defining immediate numbers and masks
typedef uint8_t Length;
struct Mask {
uint8_t mask;
uint8_t value() { return mask; }
static Mask from_value(uint8_t input) {
DCHECK_LE(input, 0x0F);
Mask m = {input};
return m;
}
};
class Operand BASE_EMBEDDED {
public:
// immediate
......@@ -608,10 +596,6 @@ class Assembler : public AssemblerBase {
static constexpr int kCallSequenceLength = 8;
#endif
static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
return ((cr.code() * CRWIDTH) + crbit);
}
// ---------------------------------------------------------------------------
// Code generation
......@@ -625,64 +609,6 @@ class Assembler : public AssemblerBase {
return (value & mask_value) << shift;
}
// Declare generic instruction formats by fields
inline void e_format(Opcode opcode) {
emit2bytes(getfield<uint16_t, 2, 0, 16>(opcode));
}
inline void i_format(Opcode opcode, int f1) {
emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) |
getfield<uint16_t, 2, 8, 16>(f1));
}
inline void ie_format(Opcode opcode, int f1, int f2) {
emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
getfield<uint32_t, 4, 24, 28>(f1) |
getfield<uint32_t, 4, 28, 32>(f2));
}
inline void mii_format(Opcode opcode, int f1, int f2, int f3) {
emit6bytes(
getfield<uint64_t, 6, 0, 8>(opcode) | getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 24>(f2) | getfield<uint64_t, 6, 24, 48>(f3));
}
inline void ri_format(Opcode opcode, int f1, int f2) {
uint32_t op1 = opcode >> 4;
uint32_t op2 = opcode & 0xf;
emit4bytes(
getfield<uint32_t, 4, 0, 8>(op1) | getfield<uint32_t, 4, 8, 12>(f1) |
getfield<uint32_t, 4, 12, 16>(op2) | getfield<uint32_t, 4, 16, 32>(f2));
}
inline void rie_1_format(Opcode opcode, int f1, int f2, int f3, int f4) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
emit6bytes(
getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) |
getfield<uint64_t, 6, 32, 36>(f4) | getfield<uint64_t, 6, 40, 48>(op2));
}
inline void rie_2_format(Opcode opcode, int f1, int f2, int f3, int f4) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
emit6bytes(
getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) |
getfield<uint64_t, 6, 32, 40>(f4) | getfield<uint64_t, 6, 40, 48>(op2));
}
inline void rie_3_format(Opcode opcode, int f1, int f2, int f3, int f4,
int f5) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
emit6bytes(
getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 24>(f3) |
getfield<uint64_t, 6, 24, 32>(f4) | getfield<uint64_t, 6, 32, 40>(f5) |
getfield<uint64_t, 6, 40, 48>(op2));
}
#define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \
template <class R1> \
inline void name(R1 r1, const Operand& i2) { \
......@@ -706,17 +632,6 @@ class Assembler : public AssemblerBase {
#undef DECLARE_S390_RIL_AB_INSTRUCTIONS
#undef DECLARE_S390_RIL_C_INSTRUCTIONS
inline void ris_format(Opcode opcode, int f1, int f2, int f3, int f4,
int f5) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
emit6bytes(
getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 20>(f3) |
getfield<uint64_t, 6, 20, 32>(f4) | getfield<uint64_t, 6, 32, 40>(f5) |
getfield<uint64_t, 6, 40, 48>(op2));
}
#define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \
inline void name(Register r1, Register r2) { \
rr_format(op_name, r1.code(), r2.code()); \
......@@ -765,22 +680,16 @@ class Assembler : public AssemblerBase {
void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
#undef DECLARE_S390_RRE_INSTRUCTIONS
inline void rrf_format(Opcode opcode, int f1, int f2, int f3, int f4) {
emit4bytes(
getfield<uint32_t, 4, 0, 16>(opcode) |
getfield<uint32_t, 4, 16, 20>(f1) | getfield<uint32_t, 4, 20, 24>(f2) |
getfield<uint32_t, 4, 24, 28>(f3) | getfield<uint32_t, 4, 28, 32>(f4));
}
#define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value) \
template <class R1> \
inline void name(R1 r1, Register x2, Register b2, Disp d2) { \
rx_format(op_name, r1.code(), x2.code(), b2.code(), d2); \
} \
template <class R1> \
inline void name(R1 r1, const MemOperand& opnd) { \
name(r1, opnd.getIndexRegister(), \
opnd.getBaseRegister(), opnd.getDisplacement()); \
#define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value) \
template <class R1> \
inline void name(R1 r1, Register x2, Register b2, const Operand& d2) { \
rx_format(op_name, r1.code(), x2.code(), b2.code(), \
d2.immediate()); \
} \
template <class R1> \
inline void name(R1 r1, const MemOperand& opnd) { \
name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \
Operand(opnd.getDisplacement())); \
}
inline void rx_format(Opcode opcode, int f1, int f2, int f3, int f4) {
......@@ -796,22 +705,22 @@ class Assembler : public AssemblerBase {
void bc(Condition cond, const MemOperand& opnd) {
bc(cond, opnd.getIndexRegister(),
opnd.getBaseRegister(), opnd.getDisplacement());
opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
}
void bc(Condition cond, Register x2, Register b2, Disp d2) {
rx_format(BC, cond, x2.code(), b2.code(), d2);
void bc(Condition cond, Register x2, Register b2, const Operand& d2) {
rx_format(BC, cond, x2.code(), b2.code(), d2.immediate());
}
#undef DECLARE_S390_RX_INSTRUCTIONS
#define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value) \
template <class R1, class R2> \
inline void name(R1 r1, R2 r2, Register b2, Disp d2) { \
rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2); \
} \
template <class R1> \
inline void name(R1 r1, const MemOperand& opnd) { \
name(r1, opnd.getIndexRegister(), \
opnd.getBaseRegister(), opnd.getDisplacement()); \
#define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value) \
template <class R1, class R2> \
inline void name(R1 r1, R2 r2, Register b2, const Operand& d2) { \
rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2.immediate()); \
} \
template <class R1> \
inline void name(R1 r1, const MemOperand& opnd) { \
name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \
Operand(opnd.getDisplacement())); \
}
inline void rxy_format(Opcode opcode, int f1, int f2, int f3, int f4) {
......@@ -829,14 +738,15 @@ class Assembler : public AssemblerBase {
void pfd(Condition cond, const MemOperand& opnd) {
pfd(cond, opnd.getIndexRegister(),
opnd.getBaseRegister(), opnd.getDisplacement());
opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
}
void pfd(Condition cond, Register x2, Register b2, Disp d2) {
rxy_format(PFD, cond, x2.code(), b2.code(), d2);
void pfd(Condition cond, Register x2, Register b2, const Operand& d2) {
rxy_format(PFD, cond, x2.code(), b2.code(), d2.immediate());
}
#undef DECLARE_S390_RXY_INSTRUCTIONS
inline void rsy_form(Opcode op, int f1, int f2, int f3, const int f4) {
inline void rsy_format(Opcode op, int f1, int f2, int f3, int f4) {
DCHECK(is_int20(f4));
DCHECK(is_uint16(op));
uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
......@@ -850,29 +760,502 @@ inline void rsy_form(Opcode op, int f1, int f2, int f3, const int f4) {
}
#define DECLARE_S390_RSY_A_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register r3, Register b2, Disp d2 = 0) { \
rsy_form(op_name, r1.code(), r3.code(), b2.code(), d2); \
void name(Register r1, Register r3, Register b2, \
const Operand& d2 = Operand::Zero()) { \
rsy_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \
} \
void name(Register r1, Register r3, Operand d2) { \
DCHECK_NE(d2.immediate(), 0); \
name(r1, r3, r0, d2.immediate()); \
name(r1, r3, r0, d2); \
} \
void name(Register r1, Register r3, const MemOperand& opnd) { \
name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \
name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_RSY_A_OPCODE_LIST(DECLARE_S390_RSY_A_INSTRUCTIONS);
#undef DECLARE_S390_RSY_A_INSTRUCTIONS
#define DECLARE_S390_RSY_B_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Condition m3, Register b2, Disp d2) { \
rsy_form(op_name, r1.code(), m3, b2.code(), d2); \
void name(Register r1, Condition m3, Register b2, const Operand& d2) { \
rsy_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \
} \
void name(Register r1, Condition m3, const MemOperand& opnd) { \
name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \
name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS);
#undef DECLARE_S390_RSY_B_INSTRUCTIONS
inline void rs_format(Opcode op, int f1, int f2, int f3, const int f4) {
DCHECK(is_uint12(d2));
uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
getfield<uint32_t, 4, 8, 12>(f1) |
getfield<uint32_t, 4, 12, 16>(f2) |
getfield<uint32_t, 4, 16, 20>(f3) |
getfield<uint32_t, 4, 20, 32>(f4);
emit4bytes(code);
}
#define DECLARE_S390_RS_A_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register r3, Register b2, const Operand& d2) { \
rs_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \
} \
void name(Register r1, Register r3, const MemOperand& opnd) { \
name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_RS_A_OPCODE_LIST(DECLARE_S390_RS_A_INSTRUCTIONS);
#undef DECLARE_S390_RS_A_INSTRUCTIONS
#define DECLARE_S390_RS_B_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Condition m3, Register b2, const Operand& d2) { \
rs_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \
} \
void name(Register r1, Condition m3, const MemOperand& opnd) { \
name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS);
#undef DECLARE_S390_RS_B_INSTRUCTIONS
#define DECLARE_S390_RS_SHIFT_FORMAT(name, opcode) \
void name(Register r1, Register r2, const Operand& opnd = \
Operand::Zero()) { \
DCHECK(r2 != r0); \
rs_format(opcode, r1.code(), r0.code(), r2.code(), opnd.immediate()); \
} \
void name(Register r1, const Operand& opnd) { \
rs_format(opcode, r1.code(), r0.code(), r0.code(), opnd.immediate()); \
}
DECLARE_S390_RS_SHIFT_FORMAT(sll, SLL)
DECLARE_S390_RS_SHIFT_FORMAT(srl, SRL)
DECLARE_S390_RS_SHIFT_FORMAT(sla, SLA)
DECLARE_S390_RS_SHIFT_FORMAT(sra, SRA)
DECLARE_S390_RS_SHIFT_FORMAT(sldl, SLDL)
DECLARE_S390_RS_SHIFT_FORMAT(srda, SRDA)
DECLARE_S390_RS_SHIFT_FORMAT(srdl, SRDL)
#undef DECLARE_S390_RS_SHIFT_FORMAT
inline void rxe_format(Opcode op, int f1, int f2, int f3, int f4, int f5 = 0) {
DCHECK(is_uint12(f4));
DCHECK(is_uint16(op));
uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) |
getfield<uint64_t, 6, 16, 20>(f3) |
getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
getfield<uint64_t, 6, 32, 36>(f5) |
getfield<uint64_t, 6, 40, 48>(op & 0xff));
emit6bytes(code);
}
#define DECLARE_S390_RXE_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register x2, Register b2, const Operand& d2, \
Condition m3 = static_cast<Condition>(0)) { \
rxe_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate(), \
m3); \
} \
template<class _R1Type> \
void name(_R1Type r1, const MemOperand& opnd) { \
name(Register::from_code(r1.code()), opnd.rx(), opnd.rb(), \
Operand(opnd.offset())); \
}
S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS);
#undef DECLARE_S390_RXE_INSTRUCTIONS
inline void ri_format(Opcode opcode, int f1, int f2) {
uint32_t op1 = opcode >> 4;
uint32_t op2 = opcode & 0xf;
emit4bytes(getfield<uint32_t, 4, 0, 8>(op1) |
getfield<uint32_t, 4, 8, 12>(f1) |
getfield<uint32_t, 4, 12, 16>(op2) |
getfield<uint32_t, 4, 16, 32>(f2));
}
#define DECLARE_S390_RI_A_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r, const Operand& i2) { \
DCHECK(is_uint12(op_name)); \
DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate())); \
ri_format(op_name, r.code(), i2.immediate()); \
}
S390_RI_A_OPCODE_LIST(DECLARE_S390_RI_A_INSTRUCTIONS);
#undef DECLARE_S390_RI_A_INSTRUCTIONS
#define DECLARE_S390_RI_B_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, const Operand& imm) { \
/* 2nd argument encodes # of halfwords, so divide by 2. */ \
int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; \
Operand halfwordOp = Operand(numHalfwords); \
halfwordOp.setBits(16); \
ri_format(op_name, r1.code(), halfwordOp.immediate()); \
}
S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS);
#undef DECLARE_S390_RI_B_INSTRUCTIONS
#define DECLARE_S390_RI_C_INSTRUCTIONS(name, op_name, op_value) \
void name(Condition m, const Operand& i2) { \
DCHECK(is_uint12(op_name)); \
DCHECK(is_uint4(m)); \
DCHECK(op_name == BRC ? \
is_int16(i2.immediate()) : is_uint16(i2.immediate())); \
ri_format(op_name, m, i2.immediate()); \
}
S390_RI_C_OPCODE_LIST(DECLARE_S390_RI_C_INSTRUCTIONS);
#undef DECLARE_S390_RI_C_INSTRUCTIONS
inline void rrf_format(Opcode op, int f1, int f2, int f3, int f4) {
uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
getfield<uint32_t, 4, 16, 20>(f1) |
getfield<uint32_t, 4, 20, 24>(f2) |
getfield<uint32_t, 4, 24, 28>(f3) |
getfield<uint32_t, 4, 28, 32>(f4);
emit4bytes(code);
}
#define DECLARE_S390_RRF_A_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Condition m4, Register r2, Register r3) { \
rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \
} \
void name(Register r1, Register r2, Register r3) { \
name(r1, Condition(0), r2, r3); \
}
S390_RRF_A_OPCODE_LIST(DECLARE_S390_RRF_A_INSTRUCTIONS);
#undef DECLARE_S390_RRF_A_INSTRUCTIONS
#define DECLARE_S390_RRF_B_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Condition m4, Register r2, Register r3) { \
rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \
} \
void name(Register r1, Register r2, Register r3) { \
name(r1, Condition(0), r2, r3); \
}
S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS);
#undef DECLARE_S390_RRF_B_INSTRUCTIONS
#define DECLARE_S390_RRF_C_INSTRUCTIONS(name, op_name, op_value) \
template <class R1, class R2> \
void name(Condition m3, Condition m4, R1 r1, R2 r2) { \
rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
} \
template <class R1, class R2> \
void name(Condition m3, R1 r1, R2 r2) { \
name(m3, Condition(0), r1, r2); \
}
S390_RRF_C_OPCODE_LIST(DECLARE_S390_RRF_C_INSTRUCTIONS);
#undef DECLARE_S390_RRF_C_INSTRUCTIONS
#define DECLARE_S390_RRF_D_INSTRUCTIONS(name, op_name, op_value) \
template <class R1, class R2> \
void name(Condition m3, Condition m4, R1 r1, R2 r2) { \
rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
} \
template <class R1, class R2> \
void name(Condition m3, R1 r1, R2 r2) { \
name(m3, Condition(0), r1, r2); \
}
S390_RRF_D_OPCODE_LIST(DECLARE_S390_RRF_D_INSTRUCTIONS);
#undef DECLARE_S390_RRF_D_INSTRUCTIONS
#define DECLARE_S390_RRF_E_INSTRUCTIONS(name, op_name, op_value) \
template <class M3, class M4, class R1, class R2> \
void name(M3 m3, M4 m4, R1 r1, R2 r2) { \
rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
} \
template <class M3, class R1, class R2> \
void name(M3 m3, R1 r1, R2 r2) { \
name(m3, Condition(0), r1, r2); \
}
S390_RRF_E_OPCODE_LIST(DECLARE_S390_RRF_E_INSTRUCTIONS);
#undef DECLARE_S390_RRF_E_INSTRUCTIONS
enum FIDBRA_FLAGS {
FIDBRA_CURRENT_ROUNDING_MODE = 0,
FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1,
// ...
FIDBRA_ROUND_TOWARD_0 = 5,
FIDBRA_ROUND_TOWARD_POS_INF = 6,
FIDBRA_ROUND_TOWARD_NEG_INF = 7
};
inline void rsi_format(Opcode op, int f1, int f2, int f3) {
DCHECK(is_uint8(op));
DCHECK(is_uint16(f3));
uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
getfield<uint32_t, 4, 8, 12>(f1) |
getfield<uint32_t, 4, 12, 16>(f2) |
getfield<uint32_t, 4, 16, 32>(f3);
emit4bytes(code);
}
#define DECLARE_S390_RSI_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register r3, const Operand& i2) { \
rsi_format(op_name, r1.code(), r3.code(), i2.immediate()); \
}
S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS);
#undef DECLARE_S390_RSI_INSTRUCTIONS
inline void rsl_format(Opcode op, uint16_t f1, int f2, int f3, int f4,
int f5) {
DCHECK(is_uint16(op));
uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
getfield<uint64_t, 6, 8, 16>(f1) |
getfield<uint64_t, 6, 16, 20>(f2) |
getfield<uint64_t, 6, 20, 32>(f3) |
getfield<uint64_t, 6, 32, 36>(f4) |
getfield<uint64_t, 6, 36, 40>(f5) |
getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
emit6bytes(code);
}
#define DECLARE_S390_RSL_A_INSTRUCTIONS(name, op_name, op_value) \
void name(const Operand& l1, Register b1, const Operand& d1) { \
uint16_t L = static_cast<uint16_t>(l1.immediate() << 8); \
rsl_format(op_name, L, b1.code(), d1.immediate(), 0, 0); \
}
S390_RSL_A_OPCODE_LIST(DECLARE_S390_RSL_A_INSTRUCTIONS);
#undef DECLARE_S390_RSL_A_INSTRUCTIONS
#define DECLARE_S390_RSL_B_INSTRUCTIONS(name, op_name, op_value) \
void name(const Operand& l2, Register b2, const Operand& d2, \
Register r1, Condition m3) { \
uint16_t L = static_cast<uint16_t>(l2.immediate()); \
rsl_format(op_name, L, b2.code(), d2.immediate(), r1.code(), m3); \
}
S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS);
#undef DECLARE_S390_RSL_B_INSTRUCTIONS
inline void s_format(Opcode op, int f1, int f2) {
DCHECK_NE(op & 0xff00, 0);
DCHECK(is_uint12(f2));
uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
getfield<uint32_t, 4, 16, 20>(f1) |
getfield<uint32_t, 4, 20, 32>(f2);
emit4bytes(code);
}
#define DECLARE_S390_S_INSTRUCTIONS(name, op_name, op_value) \
void name(Register b1, const Operand& d2) { \
Opcode op = op_name; \
if ((op & 0xFF00) == 0) { \
op = (Opcode)(op << 8); \
} \
s_format(op, b1.code(), d2.immediate()); \
} \
void name(const MemOperand& opnd) { \
Operand d2 = Operand(opnd.getDisplacement()); \
name(opnd.getBaseRegister(), d2); \
}
S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS);
#undef DECLARE_S390_S_INSTRUCTIONS
inline void si_format(Opcode op, int f1, int f2, int f3) {
uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
getfield<uint32_t, 4, 8, 16>(f1) |
getfield<uint32_t, 4, 16, 20>(f2) |
getfield<uint32_t, 4, 20, 32>(f3);
emit4bytes(code);
}
#define DECLARE_S390_SI_INSTRUCTIONS(name, op_name, op_value) \
void name(const Operand& i2, Register b1, const Operand& d1) { \
si_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \
} \
void name(const MemOperand& opnd, const Operand& i2) { \
name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS);
#undef DECLARE_S390_SI_INSTRUCTIONS
inline void siy_format(Opcode op, int f1, int f2, int f3) {
DCHECK(is_uint20(f3) || is_int20(f3));
DCHECK(is_uint16(op));
DCHECK(is_uint8(f1));
uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
getfield<uint64_t, 6, 8, 16>(f1) |
getfield<uint64_t, 6, 16, 20>(f2) |
getfield<uint64_t, 6, 20, 32>(f3) |
getfield<uint64_t, 6, 32, 40>(f3 >> 12) |
getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
emit6bytes(code);
}
#define DECLARE_S390_SIY_INSTRUCTIONS(name, op_name, op_value) \
void name(const Operand& i2, Register b1, const Operand& d1) { \
siy_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \
} \
void name(const MemOperand& opnd, const Operand& i2) { \
name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
}
S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS);
#undef DECLARE_S390_SIY_INSTRUCTIONS
inline void rrs_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
DCHECK(is_uint12(f4));
DCHECK(is_uint16(op));
uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) |
getfield<uint64_t, 6, 16, 20>(f3) |
getfield<uint64_t, 6, 20, 32>(f4) |
getfield<uint64_t, 6, 32, 36>(f5) |
getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
emit6bytes(code);
}
#define DECLARE_S390_RRS_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register r2, Register b4, const Operand& d4, \
Condition m3) { \
rrs_format(op_name, r1.code(), r2.code(), b4.code(), d4.immediate(), \
m3); \
} \
void name(Register r1, Register r2, Condition m3, \
const MemOperand& opnd) { \
name(r1, r2, opnd.getBaseRegister(), \
Operand(opnd.getDisplacement()), m3); \
}
S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS);
#undef DECLARE_S390_RRS_INSTRUCTIONS
inline void ris_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
DCHECK(is_uint12(f3));
DCHECK(is_uint16(op));
DCHECK(is_uint8(f5));
uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) |
getfield<uint64_t, 6, 16, 20>(f3) |
getfield<uint64_t, 6, 20, 32>(f4) |
getfield<uint64_t, 6, 32, 40>(f5) |
getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
emit6bytes(code);
}
#define DECLARE_S390_RIS_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Condition m3, Register b4, const Operand& d4, \
const Operand& i2) { \
ris_format(op_name, r1.code(), m3, b4.code(), d4.immediate(), \
i2.immediate()); \
} \
void name(Register r1, const Operand& i2, Condition m3, \
const MemOperand& opnd) { \
name(r1, m3, opnd.getBaseRegister(), \
Operand(opnd.getDisplacement()), i2); \
}
S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS);
#undef DECLARE_S390_RIS_INSTRUCTIONS
inline void sil_format(Opcode op, int f1, int f2, int f3) {
DCHECK(is_uint12(f2));
DCHECK(is_uint16(op));
DCHECK(is_uint16(f3));
uint64_t code = getfield<uint64_t, 6, 0, 16>(op) |
getfield<uint64_t, 6, 16, 20>(f1) |
getfield<uint64_t, 6, 20, 32>(f2) |
getfield<uint64_t, 6, 32, 48>(f3);
emit6bytes(code);
}
#define DECLARE_S390_SIL_INSTRUCTIONS(name, op_name, op_value) \
void name(Register b1, const Operand& d1, const Operand& i2) { \
sil_format(op_name, b1.code(), d1.immediate(), i2.immediate()); \
} \
void name(const MemOperand& opnd, const Operand& i2) { \
name(opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2); \
}
S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS);
#undef DECLARE_S390_SIL_INSTRUCTIONS
inline void rie_d_format(Opcode opcode, int f1, int f2, int f3, int f4) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) |
getfield<uint64_t, 6, 16, 32>(f3) |
getfield<uint64_t, 6, 32, 40>(f4) |
getfield<uint64_t, 6, 40, 48>(op2);
emit6bytes(code);
}
#define DECLARE_S390_RIE_D_INSTRUCTIONS(name, op_name, op_value) \
void name(Register r1, Register r3, const Operand& i2) { \
rie_d_format(op_name, r1.code(), r3.code(), i2.immediate(), 0); \
}
S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)
#undef DECLARE_S390_RIE_D_INSTRUCTIONS
inline void rie_f_format(Opcode opcode, int f1, int f2, int f3, int f4,
int f5) {
uint32_t op1 = opcode >> 8;
uint32_t op2 = opcode & 0xff;
uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
getfield<uint64_t, 6, 8, 12>(f1) |
getfield<uint64_t, 6, 12, 16>(f2) |
getfield<uint64_t, 6, 16, 24>(f3) |
getfield<uint64_t, 6, 24, 32>(f4) |
getfield<uint64_t, 6, 32, 40>(f5) |
getfield<uint64_t, 6, 40, 48>(op2);
emit6bytes(code);
}
#define DECLARE_S390_RIE_F_INSTRUCTIONS(name, op_name, op_value) \
void name(Register dst, Register src, const Operand& startBit, \
const Operand& endBit, const Operand& shiftAmt) { \
DCHECK(is_uint8(startBit.immediate())); \
DCHECK(is_uint8(endBit.immediate())); \
DCHECK(is_uint8(shiftAmt.immediate())); \
rie_f_format(op_name, dst.code(), src.code(), startBit.immediate(), \
endBit.immediate(), shiftAmt.immediate()); \
}
S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)
#undef DECLARE_S390_RIE_F_INSTRUCTIONS
inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
DCHECK(is_uint12(f5));
DCHECK(is_uint12(f3));
DCHECK(is_uint8(f1));
DCHECK(is_uint8(op));
uint64_t code = getfield<uint64_t, 6, 0, 8>(op) |
getfield<uint64_t, 6, 8, 16>(f1) |
getfield<uint64_t, 6, 16, 20>(f2) |
getfield<uint64_t, 6, 20, 32>(f3) |
getfield<uint64_t, 6, 32, 36>(f4) |
getfield<uint64_t, 6, 36, 48>(f5);
emit6bytes(code);
}
#define DECLARE_S390_SS_A_INSTRUCTIONS(name, op_name, op_value) \
void name(Register b1, const Operand& d1, Register b2, \
const Operand& d2, const Operand& length) { \
ss_a_format(op_name, length.immediate(), b1.code(), d1.immediate(), \
b2.code(), d2.immediate()); \
} \
void name(const MemOperand& opnd1, const MemOperand& opnd2, \
const Operand& length) { \
ss_a_format(op_name, length.immediate(), \
opnd1.getBaseRegister().code(), \
opnd1.getDisplacement(), opnd2.getBaseRegister().code(), \
opnd2.getDisplacement()); \
}
S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)
#undef DECLARE_S390_SS_A_INSTRUCTIONS
// Helper for unconditional branch to Label with update to save register
void b(Register r, Label* l) {
int32_t halfwords = branch_offset(l) / 2;
......@@ -955,121 +1338,6 @@ inline void rsy_form(Opcode op, int f1, int f2, int f3, const int f4) {
void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond);
// S390 instruction generation
#define I_FORM(name) void name(const Operand& i)
#define RR_FORM(name) void name(Register r1, Register r2)
#define RR2_FORM(name) void name(Condition m1, Register r2)
#define RI1_FORM(name) void name(Register r, const Operand& i)
#define RI2_FORM(name) void name(Condition m, const Operand& i)
#define RIE_FORM(name) void name(Register r1, Register R3, const Operand& i)
#define RIE_F_FORM(name) \
void name(Register r1, Register r2, const Operand& i3, const Operand& i4, \
const Operand& i5)
#define RXE_FORM(name) \
void name(Register r1, const MemOperand& opnd); \
void name(Register r1, Register b2, Register x2, Disp d2)
#define RXF_FORM(name) \
void name(Register r1, Register r3, const MemOperand& opnd); \
void name(Register r1, Register r3, Register b2, Register x2, Disp d2)
#define RSI_FORM(name) void name(Register r1, Register r3, const Operand& i)
#define RIS_FORM(name) \
void name(Register r1, Condition m3, Register b4, Disp d4, \
const Operand& i2); \
void name(Register r1, const Operand& i2, Condition m3, \
const MemOperand& opnd)
#define SI_FORM(name) \
void name(const MemOperand& opnd, const Operand& i); \
void name(const Operand& i2, Register b1, Disp d1)
#define SIL_FORM(name) \
void name(Register b1, Disp d1, const Operand& i2); \
void name(const MemOperand& opnd, const Operand& i2)
#define RRF1_FORM(name) void name(Register r1, Register r2, Register r3)
#define RRF2_FORM(name) void name(Condition m1, Register r1, Register r2)
#define RRF3_FORM(name) \
void name(Register r3, Condition m4, Register r1, Register r2)
#define RS1_FORM(name) \
void name(Register r1, Register r3, const MemOperand& opnd); \
void name(Register r1, Register r3, Register b2, Disp d2)
#define RS2_FORM(name) \
void name(Register r1, Condition m3, const MemOperand& opnd); \
void name(Register r1, Condition m3, Register b2, Disp d2)
#define RSE_FORM(name) \
void name(Register r1, Register r3, const MemOperand& opnd); \
void name(Register r1, Register r3, Register b2, Disp d2)
#define RSL_FORM(name) \
void name(Length l, Register b2, Disp d2); \
void name(const MemOperand& opnd)
#define RSY1_FORM(name) \
void name(Register r1, Register r3, Register b2, Disp d2); \
void name(Register r1, Register r3, const MemOperand& opnd)
#define RSY2_FORM(name) \
void name(Register r1, Condition m3, Register b2, Disp d2); \
void name(Register r1, Condition m3, const MemOperand& opnd)
#define RRS_FORM(name) \
void name(Register r1, Register r2, Register b4, Disp d4, Condition m3); \
void name(Register r1, Register r2, Condition m3, const MemOperand& opnd)
#define S_FORM(name) \
void name(Register b2, Disp d2); \
void name(const MemOperand& opnd)
#define SIY_FORM(name) \
void name(const Operand& i2, Register b1, Disp d1); \
void name(const MemOperand& opnd, const Operand& i)
#define SS1_FORM(name) \
void name(Register b1, Disp d1, Register b3, Disp d2, Length length); \
void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length)
#define SS2_FORM(name) \
void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length1, \
Length length2); \
void name(Register b1, Disp d1, Register b2, Disp d2, Length l1, Length l2)
#define SS3_FORM(name) \
void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length); \
void name(const Operand& i3, Register b1, Disp d1, Register b2, Disp d2, \
Length l1)
#define SS4_FORM(name) \
void name(const MemOperand& opnd1, const MemOperand& opnd2); \
void name(Register r1, Register r3, Register b1, Disp d1, Register b2, \
Disp d2)
#define SS5_FORM(name) \
void name(const MemOperand& opnd1, const MemOperand& opnd2); \
void name(Register r1, Register r3, Register b3, Disp d2, Register b4, \
Disp d4)
#define SSE_FORM(name) \
void name(Register b1, Disp d1, Register b2, Disp d2); \
void name(const MemOperand& opnd1, const MemOperand& opnd2)
#define SSF_FORM(name) \
void name(Register r3, Register b1, Disp d1, Register b2, Disp d2); \
void name(Register r3, const MemOperand& opnd1, const MemOperand& opnd2)
#define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \
Condition m3) { \
......@@ -1119,201 +1387,9 @@ inline void rsy_form(Opcode op, int f1, int f2, int f3, const int f4) {
static_cast<Condition>(3));
}
// S390 instruction sets
RXE_FORM(ddb);
SS1_FORM(ed);
RRF2_FORM(fidbr);
RI1_FORM(iihh);
RI1_FORM(iihl);
RI1_FORM(iilh);
RI1_FORM(iill);
RSY1_FORM(loc);
RXE_FORM(mdb);
SS4_FORM(mvck);
SSF_FORM(mvcos);
SS4_FORM(mvcs);
SS1_FORM(mvn);
SS1_FORM(nc);
SI_FORM(ni);
RI1_FORM(nilh);
RI1_FORM(nill);
RI1_FORM(oill);
RXE_FORM(sdb);
RS1_FORM(srdl);
RI1_FORM(tmll);
SS1_FORM(tr);
S_FORM(ts);
// Load Address Instructions
void larl(Register r, Label* l);
// Load Instructions
void lhi(Register r, const Operand& imm);
void lghi(Register r, const Operand& imm);
// Load Multiple Instructions
void lm(Register r1, Register r2, const MemOperand& src);
// Load On Condition Instructions
void locr(Condition m3, Register r1, Register r2);
void locgr(Condition m3, Register r1, Register r2);
// Store Instructions
// Store Multiple Instructions
void stm(Register r1, Register r2, const MemOperand& src);
// Compare Instructions
void chi(Register r, const Operand& opnd);
void cghi(Register r, const Operand& opnd);
// Compare Logical Instructions
void cli(const MemOperand& mem, const Operand& imm);
void cliy(const MemOperand& mem, const Operand& imm);
void clc(const MemOperand& opnd1, const MemOperand& opnd2, Length length);
// Compare and Swap Instructions
void cs(Register r1, Register r2, const MemOperand& src);
// Test Under Mask Instructions
void tm(const MemOperand& mem, const Operand& imm);
void tmy(const MemOperand& mem, const Operand& imm);
// Shift Instructions (32)
void sll(Register r1, Register opnd);
void sll(Register r1, const Operand& opnd);
void srl(Register r1, Register opnd);
void srl(Register r1, const Operand& opnd);
void sra(Register r1, Register opnd);
void sra(Register r1, const Operand& opnd);
void sla(Register r1, Register opnd);
void sla(Register r1, const Operand& opnd);
// Shift Instructions (64)
void srda(Register r1, const Operand& opnd);
void srdl(Register r1, const Operand& opnd);
void sldl(Register r1, Register b2, const Operand& opnd);
void srdl(Register r1, Register b2, const Operand& opnd);
void srda(Register r1, Register b2, const Operand& opnd);
// Rotate and Insert Selected Bits
void risbg(Register dst, Register src, const Operand& startBit,
const Operand& endBit, const Operand& shiftAmt,
bool zeroBits = true);
void risbgn(Register dst, Register src, const Operand& startBit,
const Operand& endBit, const Operand& shiftAmt,
bool zeroBits = true);
// Move Character (Mem to Mem)
void mvc(const MemOperand& opnd1, const MemOperand& opnd2, uint32_t length);
// Branch Instructions
void bras(Register r, const Operand& opnd);
void brc(Condition c, const Operand& opnd);
void brct(Register r1, const Operand& opnd);
void brctg(Register r1, const Operand& opnd);
// 32-bit Add Instructions
void ahi(Register r1, const Operand& opnd);
void ahik(Register r1, Register r3, const Operand& opnd);
void ark(Register r1, Register r2, Register r3);
void asi(const MemOperand&, const Operand&);
// 64-bit Add Instructions
void aghi(Register r1, const Operand& opnd);
void aghik(Register r1, Register r3, const Operand& opnd);
void agrk(Register r1, Register r2, Register r3);
void agsi(const MemOperand&, const Operand&);
// 32-bit Add Logical Instructions
void alrk(Register r1, Register r2, Register r3);
// 64-bit Add Logical Instructions
void algrk(Register r1, Register r2, Register r3);
// 32-bit Subtract Instructions
void srk(Register r1, Register r2, Register r3);
// 64-bit Subtract Instructions
void sgrk(Register r1, Register r2, Register r3);
// 32-bit Subtract Logical Instructions
void slrk(Register r1, Register r2, Register r3);
// 64-bit Subtract Logical Instructions
void slgrk(Register r1, Register r2, Register r3);
// 32-bit Multiply Instructions
void mhi(Register r1, const Operand& opnd);
void msrkc(Register r1, Register r2, Register r3);
void msgrkc(Register r1, Register r2, Register r3);
// 64-bit Multiply Instructions
void mghi(Register r1, const Operand& opnd);
// Bitwise Instructions (AND / OR / XOR)
void nrk(Register r1, Register r2, Register r3);
void ngrk(Register r1, Register r2, Register r3);
void ork(Register r1, Register r2, Register r3);
void ogrk(Register r1, Register r2, Register r3);
void xrk(Register r1, Register r2, Register r3);
void xgrk(Register r1, Register r2, Register r3);
void xc(const MemOperand& opnd1, const MemOperand& opnd2, Length length);
// Floating <-> Fixed Point Conversion Instructions
void cdlfbr(Condition m3, Condition m4, DoubleRegister fltReg,
Register fixReg);
void cdlgbr(Condition m3, Condition m4, DoubleRegister fltReg,
Register fixReg);
void celgbr(Condition m3, Condition m4, DoubleRegister fltReg,
Register fixReg);
void celfbr(Condition m3, Condition m4, DoubleRegister fltReg,
Register fixReg);
void clfdbr(Condition m3, Condition m4, Register fixReg,
DoubleRegister fltReg);
void clfebr(Condition m3, Condition m4, Register fixReg,
DoubleRegister fltReg);
void clgdbr(Condition m3, Condition m4, Register fixReg,
DoubleRegister fltReg);
void clgebr(Condition m3, Condition m4, Register fixReg,
DoubleRegister fltReg);
void cfdbr(Condition m, Register fixReg, DoubleRegister fltReg);
void cgebr(Condition m, Register fixReg, DoubleRegister fltReg);
void cgdbr(Condition m, Register fixReg, DoubleRegister fltReg);
void cfebr(Condition m3, Register fixReg, DoubleRegister fltReg);
void cefbr(Condition m3, DoubleRegister fltReg, Register fixReg);
// Floating Point Compare Instructions
void cdb(DoubleRegister r1, const MemOperand& opnd);
void ceb(DoubleRegister r1, const MemOperand& opnd);
// Floating Point Arithmetic Instructions
void adb(DoubleRegister r1, const MemOperand& opnd);
void aeb(DoubleRegister r1, const MemOperand& opnd);
void sdb(DoubleRegister r1, const MemOperand& opnd);
void seb(DoubleRegister r1, const MemOperand& opnd);
void mdb(DoubleRegister r1, const MemOperand& opnd);
void meeb(DoubleRegister r1, const MemOperand& opnd);
void ddb(DoubleRegister r1, const MemOperand& opnd);
void deb(DoubleRegister r1, const MemOperand& opnd);
void sqdb(DoubleRegister r1, const MemOperand& opnd);
void ldeb(DoubleRegister r1, const MemOperand& opnd);
enum FIDBRA_MASK3 {
FIDBRA_CURRENT_ROUNDING_MODE = 0,
FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1,
// ...
FIDBRA_ROUND_TOWARD_0 = 5,
FIDBRA_ROUND_TOWARD_POS_INF = 6,
FIDBRA_ROUND_TOWARD_NEG_INF = 7
};
void fiebra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3);
void fidbra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3);
// Move integer
void mvhi(const MemOperand& opnd1, const Operand& i2);
void mvghi(const MemOperand& opnd1, const Operand& i2);
// Exception-generating instructions and debugging support
void stop(const char* msg, Condition cond = al,
int32_t code = kDefaultStopCode, CRegister cr = cr7);
......@@ -1511,62 +1587,6 @@ inline void rsy_form(Opcode op, int f1, int f2, int f3, const int f4) {
pc_ += 6;
}
// Helpers to emit binary encoding for various instruction formats.
inline void rr2_form(uint8_t op, Condition m1, Register r2);
inline void ri_form(Opcode op, Register r1, const Operand& i2);
inline void ri_form(Opcode op, Condition m1, const Operand& i2);
inline void rie_form(Opcode op, Register r1, Register r3, const Operand& i2);
inline void rie_f_form(Opcode op, Register r1, Register r2, const Operand& i3,
const Operand& i4, const Operand& i5);
inline void ris_form(Opcode op, Register r1, Condition m3, Register b4,
Disp d4, const Operand& i2);
inline void rrf1_form(Opcode op, Register r1, Register r2, Register r3);
inline void rrf1_form(uint32_t x);
inline void rrf2_form(uint32_t x);
inline void rrf3_form(uint32_t x);
inline void rrfe_form(Opcode op, Condition m3, Condition m4, Register r1,
Register r2);
inline void rrs_form(Opcode op, Register r1, Register r2, Register b4,
Disp d4, Condition m3);
inline void rs_form(Opcode op, Register r1, Condition m3, Register b2,
const Disp d2);
inline void rs_form(Opcode op, Register r1, Register r3, Register b2,
const Disp d2);
inline void rsi_form(Opcode op, Register r1, Register r3, const Operand& i2);
inline void rsl_form(Opcode op, Length l1, Register b2, Disp d2);
inline void rxe_form(Opcode op, Register r1, Register x2, Register b2,
Disp d2);
inline void rxf_form(Opcode op, Register r1, Register r3, Register b2,
Register x2, Disp d2);
inline void s_form(Opcode op, Register b1, Disp d2);
inline void si_form(Opcode op, const Operand& i2, Register b1, Disp d1);
inline void siy_form(Opcode op, const Operand& i2, Register b1, Disp d1);
inline void sil_form(Opcode op, Register b1, Disp d1, const Operand& i2);
inline void ss_form(Opcode op, Length l, Register b1, Disp d1, Register b2,
Disp d2);
inline void ss_form(Opcode op, Length l1, Length l2, Register b1, Disp d1,
Register b2, Disp d2);
inline void ss_form(Opcode op, Length l1, const Operand& i3, Register b1,
Disp d1, Register b2, Disp d2);
inline void ss_form(Opcode op, Register r1, Register r2, Register b1, Disp d1,
Register b2, Disp d2);
inline void sse_form(Opcode op, Register b1, Disp d1, Register b2, Disp d2);
inline void ssf_form(Opcode op, Register r3, Register b1, Disp d1,
Register b2, Disp d2);
// Labels
void print(Label* L);
int max_reach_from(int pos);
......
......@@ -686,7 +686,11 @@ typedef uint64_t SixByteInstr;
0xEDAD) /* type = RSL_B CONVERT TO PACKED (from extended DFP) */ \
V(cdpt, CDPT, 0xEDAE) /* type = RSL_B CONVERT FROM PACKED (to long DFP) */ \
V(cxpt, CXPT, \
0xEDAF) /* type = RSL_B CONVERT FROM PACKED (to extended DFP) */
0xEDAF) /* type = RSL_B CONVERT FROM PACKED (to extended DFP) */ \
V(czdt, CZDT, 0xEDA8) /* type = RSL CONVERT TO ZONED (from long DFP) */ \
V(czxt, CZXT, 0xEDA9) /* type = RSL CONVERT TO ZONED (from extended DFP) */ \
V(cdzt, CDZT, 0xEDAA) /* type = RSL CONVERT FROM ZONED (to long DFP) */ \
V(cxzt, CXZT, 0xEDAB) /* type = RSL CONVERT FROM ZONED (to extended DFP) */
#define S390_SI_OPCODE_LIST(V) \
V(tm, TM, 0x91) /* type = SI TEST UNDER MASK */ \
......@@ -856,12 +860,6 @@ typedef uint64_t SixByteInstr;
#define S390_RI_C_OPCODE_LIST(V) \
V(brc, BRC, 0xA74) /* type = RI_C BRANCH RELATIVE ON CONDITION */
#define S390_RSL_OPCODE_LIST(V) \
V(czdt, CZDT, 0xEDA8) /* type = RSL CONVERT TO ZONED (from long DFP) */ \
V(czxt, CZXT, 0xEDA9) /* type = RSL CONVERT TO ZONED (from extended DFP) */ \
V(cdzt, CDZT, 0xEDAA) /* type = RSL CONVERT FROM ZONED (to long DFP) */ \
V(cxzt, CXZT, 0xEDAB) /* type = RSL CONVERT FROM ZONED (to extended DFP) */
#define S390_SMI_OPCODE_LIST(V) \
V(bpp, BPP, 0xC7) /* type = SMI BRANCH PREDICTION PRELOAD */
......@@ -1096,7 +1094,6 @@ typedef uint64_t SixByteInstr;
V(icm, ICM, 0xBF) /* type = RS_B INSERT CHARACTERS UNDER MASK (low) */
#define S390_S_OPCODE_LIST(V) \
V(awr, AWR, 0x2E) /* type = S ADD UNNORMALIZED (long HFP) */ \
V(lpsw, LPSW, 0x82) /* type = S LOAD PSW */ \
V(diagnose, DIAGNOSE, 0x83) /* type = S DIAGNOSE */ \
V(ts, TS, 0x93) /* type = S TEST AND SET */ \
......@@ -1541,6 +1538,7 @@ typedef uint64_t SixByteInstr;
0xEC45) /* type = RIE_E BRANCH RELATIVE ON INDEX LOW OR EQ. (64) */
#define S390_RR_OPCODE_LIST(V) \
V(awr, AWR, 0x2E) /* type = RR ADD UNNORMALIZED (long HFP) */ \
V(spm, SPM, 0x04) /* type = RR SET PROGRAM MASK */ \
V(balr, BALR, 0x05) /* type = RR BRANCH AND LINK */ \
V(bctr, BCTR, 0x06) /* type = RR BRANCH ON COUNT (32) */ \
......@@ -1684,7 +1682,6 @@ typedef uint64_t SixByteInstr;
S390_RSI_OPCODE_LIST(V) \
S390_RI_B_OPCODE_LIST(V) \
S390_RI_C_OPCODE_LIST(V) \
S390_RSL_OPCODE_LIST(V) \
S390_SMI_OPCODE_LIST(V) \
S390_RXY_A_OPCODE_LIST(V) \
S390_RXY_B_OPCODE_LIST(V) \
......
......@@ -432,6 +432,39 @@ void TurboAssembler::Move(DoubleRegister dst, DoubleRegister src) {
}
}
// Wrapper around Assembler::mvc (SS-a format)
void TurboAssembler::MoveChar(const MemOperand& opnd1,
const MemOperand& opnd2,
const Operand& length) {
mvc(opnd1, opnd2, Operand(static_cast<intptr_t>(length.immediate() - 1)));
}
// Wrapper around Assembler::clc (SS-a format)
void TurboAssembler::CompareLogicalChar(const MemOperand& opnd1,
const MemOperand& opnd2,
const Operand& length) {
clc(opnd1, opnd2, Operand(static_cast<intptr_t>(length.immediate() - 1)));
}
// Wrapper around Assembler::xc (SS-a format)
void TurboAssembler::ExclusiveOrChar(const MemOperand& opnd1,
const MemOperand& opnd2,
const Operand& length) {
xc(opnd1, opnd2, Operand(static_cast<intptr_t>(length.immediate() - 1)));
}
// Wrapper around Assembler::risbg(n) (RIE-f)
void TurboAssembler::RotateInsertSelectBits(Register dst, Register src,
const Operand& startBit, const Operand& endBit,
const Operand& shiftAmt, bool zeroBits) {
if (zeroBits)
// High tag the top bit of I4/EndBit to zero out any unselected bits
risbg(dst, src, startBit,
Operand(static_cast<intptr_t>(endBit.immediate() | 0x80)), shiftAmt);
else
risbg(dst, src, startBit, endBit, shiftAmt);
}
void TurboAssembler::MultiPush(RegList regs, Register location) {
int16_t num_to_push = base::bits::CountPopulation(regs);
int16_t stack_offset = num_to_push * kPointerSize;
......@@ -754,7 +787,7 @@ void TurboAssembler::ConvertUnsignedIntToDouble(DoubleRegister dst,
}
void TurboAssembler::ConvertIntToFloat(DoubleRegister dst, Register src) {
cefbr(Condition(4), dst, src);
cefbra(Condition(4), dst, src);
}
void TurboAssembler::ConvertUnsignedIntToFloat(DoubleRegister dst,
......@@ -1523,8 +1556,8 @@ void MacroAssembler::PushStackHandler() {
StoreP(r0, MemOperand(sp)); // Padding.
// Copy the old handler into the next handler slot.
mvc(MemOperand(sp, StackHandlerConstants::kNextOffset), MemOperand(r7),
kPointerSize);
MoveChar(MemOperand(sp, StackHandlerConstants::kNextOffset), MemOperand(r7),
Operand(kPointerSize));
// Set this new handler as the current one.
StoreP(sp, MemOperand(r7));
}
......@@ -2299,7 +2332,7 @@ void TurboAssembler::Div32(Register dst, Register src1, Register src2) {
#define Generate_DivU32(instr) \
{ \
lr(r0, src1); \
srdl(r0, Operand(32)); \
srdl(r0, r0, Operand(32)); \
instr(r0, src2); \
LoadlW(dst, r1); \
}
......@@ -2373,7 +2406,7 @@ void TurboAssembler::Mod32(Register dst, Register src1, Register src2) {
#define Generate_ModU32(instr) \
{ \
lr(r0, src1); \
srdl(r0, Operand(32)); \
srdl(r0, r0, Operand(32)); \
instr(r0, src2); \
LoadlW(dst, r0); \
}
......@@ -3067,14 +3100,15 @@ void TurboAssembler::AndP(Register dst, Register src, const Operand& opnd) {
base::bits::CountLeadingZeros64(shifted_value) - trailing_zeros;
int endBit = 63 - trailing_zeros;
// Start: startBit, End: endBit, Shift = 0, true = zero unselected bits.
risbg(dst, src, Operand(startBit), Operand(endBit), Operand::Zero(),
true);
RotateInsertSelectBits(dst, src, Operand(startBit), Operand(endBit),
Operand::Zero(), true);
return;
} else if (-1 == shifted_value) {
// A Special case in which all top bits up to MSB are 1's. In this case,
// we can set startBit to be 0.
int endBit = 63 - trailing_zeros;
risbg(dst, src, Operand::Zero(), Operand(endBit), Operand::Zero(), true);
RotateInsertSelectBits(dst, src, Operand::Zero(), Operand(endBit),
Operand::Zero(), true);
return;
}
}
......@@ -4291,7 +4325,8 @@ void TurboAssembler::ClearRightImm(Register dst, Register src,
// Try to use RISBG if possible
if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
int endBit = 63 - numBitsToClear;
risbg(dst, src, Operand::Zero(), Operand(endBit), Operand::Zero(), true);
RotateInsertSelectBits(dst, src, Operand::Zero(), Operand(endBit),
Operand::Zero(), true);
return;
}
......
......@@ -233,6 +233,19 @@ class TurboAssembler : public Assembler {
void Move(Register dst, Register src, Condition cond = al);
void Move(DoubleRegister dst, DoubleRegister src);
void MoveChar(const MemOperand& opnd1, const MemOperand& opnd2,
const Operand& length);
void CompareLogicalChar(const MemOperand& opnd1, const MemOperand& opnd2,
const Operand& length);
void ExclusiveOrChar(const MemOperand& opnd1, const MemOperand& opnd2,
const Operand& length);
void RotateInsertSelectBits(Register dst, Register src,
const Operand& startBit, const Operand& endBit,
const Operand& shiftAmt, bool zeroBits);
void SaveRegisters(RegList registers);
void RestoreRegisters(RegList registers);
......@@ -918,8 +931,8 @@ class TurboAssembler : public Assembler {
int shiftAmount = (64 - rangeEnd) % 64; // Convert to shift left.
int endBit = 63; // End is always LSB after shifting.
int startBit = 63 - rangeStart + rangeEnd;
risbg(dst, src, Operand(startBit), Operand(endBit), Operand(shiftAmount),
true);
RotateInsertSelectBits(dst, src, Operand(startBit), Operand(endBit),
Operand(shiftAmount), true);
} else {
if (rangeEnd > 0) // Don't need to shift if rangeEnd is zero.
ShiftRightP(dst, src, Operand(rangeEnd));
......
......@@ -197,7 +197,7 @@ TEST(3) {
__ brcl(Condition(14), Operand(-123));
__ iilf(r13, Operand(123456789));
__ iihf(r13, Operand(-123456789));
__ mvc(MemOperand(r0, 123), MemOperand(r4, 567), 89);
__ mvc(MemOperand(r0, 123), MemOperand(r4, 567), Operand(88));
__ sll(r13, Operand(10));
v8::internal::byte* bufPos = assm.buffer_pos();
......
......@@ -187,9 +187,9 @@ TEST(SixBytes) {
COMPARE(slag(r1, r3, r2), "eb132000000b slag\tr1,r3,0(r2)");
COMPARE(srag(r1, r3, r2), "eb132000000a srag\tr1,r3,0(r2)");
COMPARE(srag(r1, r3, Operand(2)), "eb130002000a srag\tr1,r3,2(r0)");
COMPARE(risbg(r1, r2, Operand(3), Operand(5), Operand(2), false),
COMPARE(risbg(r1, r2, Operand(3), Operand(5), Operand(2)),
"ec1203050255 risbg\tr1,r2,3,5,2");
COMPARE(risbgn(r1, r2, Operand(3), Operand(5), Operand(2), false),
COMPARE(risbgn(r1, r2, Operand(3), Operand(5), Operand(2)),
"ec1203050259 risbgn\tr1,r2,3,5,2");
COMPARE(stmg(r3, r4, MemOperand(sp, 10)),
"eb34f00a0024 stmg\tr3,r4,10(sp)");
......@@ -290,8 +290,8 @@ TEST(SixBytes) {
COMPARE(clg(r9, MemOperand(r6, r7, 19)), "e39670130021 clg\tr9,19(r6,r7)");
COMPARE(bctg(r8, MemOperand(sp, 10)), "e380f00a0046 bctg\tr8,10(sp)");
COMPARE(icy(r2, MemOperand(r3, 2)), "e32030020073 icy\tr2,2(r3)");
COMPARE(mvc(MemOperand(r9, 9), MemOperand(r3, 15), 10),
"d2099009300f mvc\t9(9,r9),15(r3)");
COMPARE(mvc(MemOperand(r9, 9), MemOperand(r3, 15), Operand(10)),
"d20a9009300f mvc\t9(10,r9),15(r3)");
COMPARE(nilf(r0, Operand(8000)), "c00b00001f40 nilf\tr0,8000");
COMPARE(oilf(r9, Operand(1000)), "c09d000003e8 oilf\tr9,1000");
......
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