Commit d5f0178a authored by andrew-cc-chen's avatar andrew-cc-chen Committed by Commit Bot

[s390] added SIMD assembler and simulator instructions

Change-Id: I2bc21a353c871652daeac87eae62e1e6ae740b49
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1529638Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#60955}
parent 49954eb5
......@@ -48,6 +48,7 @@ enum CpuFeature {
GENERAL_INSTR_EXT,
FLOATING_POINT_EXT,
VECTOR_FACILITY,
VECTOR_ENHANCE_FACILITY_1,
MISC_INSTR_EXT2,
NUMBER_OF_CPU_FEATURES,
......
......@@ -210,6 +210,11 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
supportsCPUFeature("vx")) {
supported_ |= (1u << VECTOR_FACILITY);
}
// Test for Vector Enhancement Facility 1 - Bit 135
if (facilities[2] & (one << (63 - (135 - 128))) &&
supportsCPUFeature("vx")) {
supported_ |= (1u << VECTOR_ENHANCE_FACILITY_1);
}
// Test for Miscellaneous Instruction Extension Facility - Bit 58
if (facilities[0] & (1lu << (63 - 58))) {
supported_ |= (1u << MISC_INSTR_EXT2);
......@@ -225,6 +230,7 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
USE(performSTFLE); // To avoid assert
USE(supportsCPUFeature);
supported_ |= (1u << VECTOR_FACILITY);
supported_ |= (1u << VECTOR_ENHANCE_FACILITY_1);
#endif
supported_ |= (1u << FPU);
}
......
......@@ -1151,6 +1151,7 @@ inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
(static_cast<uint64_t>(m5 & 0xF)) * B20 | \
(static_cast<uint64_t>(m4 & 0xF)) * B16 | \
(static_cast<uint64_t>(m3 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
......@@ -1167,12 +1168,141 @@ inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
(static_cast<uint64_t>(m6 & 0xF)) * B20 | \
(static_cast<uint64_t>(m5 & 0xF)) * B16 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)
#undef DECLARE_VRR_C_INSTRUCTIONS
#define DECLARE_VRR_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3, \
Condition m5, Condition m4) { \
uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(v2.code())) * B32 | \
(static_cast<uint64_t>(v3.code())) * B28 | \
(static_cast<uint64_t>(m5 & 0xF)) * B20 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRR_B_OPCODE_LIST(DECLARE_VRR_B_INSTRUCTIONS)
#undef DECLARE_VRR_B_INSTRUCTIONS
#define DECLARE_VRR_E_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3, \
DoubleRegister v4, Condition m6, Condition m5) { \
uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(v2.code())) * B32 | \
(static_cast<uint64_t>(v3.code())) * B28 | \
(static_cast<uint64_t>(m6 & 0xF)) * B24 | \
(static_cast<uint64_t>(m5 & 0xF)) * B16 | \
(static_cast<uint64_t>(v4.code())) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRR_E_OPCODE_LIST(DECLARE_VRR_E_INSTRUCTIONS)
#undef DECLARE_VRR_E_INSTRUCTIONS
#define DECLARE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, const MemOperand& opnd, Condition m3) { \
uint64_t code = \
(static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(opnd.getIndexRegister().code())) * B32 | \
(static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
(static_cast<uint64_t>(opnd.getDisplacement())) * B16 | \
(static_cast<uint64_t>(m3 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRX_OPCODE_LIST(DECLARE_VRX_INSTRUCTIONS)
#undef DECLARE_VRX_INSTRUCTIONS
#define DECLARE_VRS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, DoubleRegister v2, const MemOperand& opnd, \
Condition m4 = Condition(0)) { \
uint64_t code = \
(static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(v2.code())) * B32 | \
(static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
(static_cast<uint64_t>(opnd.getDisplacement())) * B16 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRS_A_OPCODE_LIST(DECLARE_VRS_A_INSTRUCTIONS)
#undef DECLARE_VRS_A_INSTRUCTIONS
#define DECLARE_VRS_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, Register r1, const MemOperand& opnd, \
Condition m4 = Condition(0)) { \
uint64_t code = \
(static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(r1.code())) * B32 | \
(static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
(static_cast<uint64_t>(opnd.getDisplacement())) * B16 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRS_B_OPCODE_LIST(DECLARE_VRS_B_INSTRUCTIONS)
#undef DECLARE_VRS_B_INSTRUCTIONS
#define DECLARE_VRS_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(Register r1, DoubleRegister v1, const MemOperand& opnd, \
Condition m4 = Condition(0)) { \
uint64_t code = \
(static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(r1.code())) * B36 | \
(static_cast<uint64_t>(v1.code())) * B32 | \
(static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
(static_cast<uint64_t>(opnd.getDisplacement())) * B16 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRS_C_OPCODE_LIST(DECLARE_VRS_C_INSTRUCTIONS)
#undef DECLARE_VRS_C_INSTRUCTIONS
#define DECLARE_VRI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, const Operand& i2, Condition m3) { \
uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint32_t>(i2.immediate())) * B16 | \
(static_cast<uint64_t>(m3 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRI_A_OPCODE_LIST(DECLARE_VRI_A_INSTRUCTIONS)
#undef DECLARE_VRI_A_INSTRUCTIONS
#define DECLARE_VRI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
void name(DoubleRegister v1, DoubleRegister v2, const Operand& i2, \
Condition m4) { \
uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
(static_cast<uint64_t>(v1.code())) * B36 | \
(static_cast<uint64_t>(v2.code())) * B32 | \
(static_cast<uint16_t>(i2.immediate())) * B16 | \
(static_cast<uint64_t>(m4 & 0xF)) * B12 | \
(static_cast<uint64_t>(0)) * B8 | \
(static_cast<uint64_t>(opcode_value & 0x00FF)); \
emit6bytes(code); \
}
S390_VRI_C_OPCODE_LIST(DECLARE_VRI_C_INSTRUCTIONS)
#undef DECLARE_VRI_C_INSTRUCTIONS
// Single Element format
void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
......
......@@ -559,6 +559,8 @@ typedef uint64_t SixByteInstr;
V(vfce, VFCE, 0xE7E8) /* type = VRR_C VECTOR FP COMPARE EQUAL */ \
V(vfche, VFCHE, 0xE7EA) /* type = VRR_C VECTOR FP COMPARE HIGH OR EQUAL */ \
V(vfch, VFCH, 0xE7EB) /* type = VRR_C VECTOR FP COMPARE HIGH */ \
V(vfmax, VFMAX, 0xE7EF) /* type = VRR_C VECTOR FP MAXIMUM */ \
V(vfmin, VFMIN, 0xE7EE) /* type = VRR_C VECTOR FP MINIMUM */ \
V(vavgl, VAVGL, 0xE7F0) /* type = VRR_C VECTOR AVERAGE LOGICAL */ \
V(vacc, VACC, 0xE7F1) /* type = VRR_C VECTOR ADD COMPUTE CARRY */ \
V(vavg, VAVG, 0xE7F2) /* type = VRR_C VECTOR AVERAGE */ \
......@@ -2288,6 +2290,24 @@ class RIEInstruction : Instruction {
};
// VRR Instruction
class VRR_A_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R2Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M5Value, uint32_t, 24, 28)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M4Value, uint32_t, 28, 32)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M3Value, uint32_t, 32, 36)
};
class VRR_B_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R2Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R3Value, int, 16, 20)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M5Value, uint32_t, 24, 28)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M4Value, uint32_t, 32, 36)
};
class VRR_C_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
......@@ -2298,6 +2318,49 @@ class VRR_C_Instruction : SixByteInstruction {
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M4Value, uint32_t, 32, 36)
};
class VRR_E_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R2Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R3Value, int, 16, 20)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R4Value, int, 32, 36)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M6Value, uint32_t, 20, 24)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M5Value, uint32_t, 28, 32)
};
class VRX_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(X2Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(B2Value, int, 16, 20)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(D2Value, int, 20, 32)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M3Value, uint32_t, 32, 36)
};
class VRS_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R3Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(B2Value, int, 16, 20)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(D2Value, int, 20, 32)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M4Value, uint32_t, 32, 36)
};
class VRI_A_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(I2Value, int, 16, 32)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M3Value, uint32_t, 32, 36)
};
class VRI_C_Instruction : SixByteInstruction {
public:
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R1Value, int, 8, 12)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(R3Value, int, 12, 16)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(I2Value, int, 16, 32)
DECLARE_FIELD_FOR_SIX_BYTE_INSTR(M4Value, uint32_t, 32, 36)
};
// Helper functions for converting between register numbers and names.
class Registers {
public:
......
......@@ -210,6 +210,11 @@ int Decoder::FormatFloatingRegister(Instruction* instr, const char* format) {
int reg = rreinstr->R2Value();
PrintDRegister(reg);
return 2;
} else if (format[1] == '4') {
VRR_E_Instruction* vrreinstr = reinterpret_cast<VRR_E_Instruction*>(instr);
int reg = vrreinstr->R4Value();
PrintDRegister(reg);
return 2;
}
UNREACHABLE();
}
......@@ -311,8 +316,19 @@ int Decoder::FormatMask(Instruction* instr, const char* format) {
value = reinterpret_cast<RRFInstruction*>(instr)->M4Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
return 2;
} else if (format[1] == '4') { // mask format in bits 32-35
value = reinterpret_cast<VRR_C_Instruction*>(instr)->M4Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
return 2;
} else if (format[1] == '5') { // mask format in bits 28-31
value = reinterpret_cast<VRR_C_Instruction*>(instr)->M5Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
return 2;
} else if (format[1] == '6') { // mask format in bits 24-27
value = reinterpret_cast<VRR_C_Instruction*>(instr)->M6Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", value);
return 2;
}
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", value);
return 2;
}
......@@ -784,13 +800,76 @@ bool Decoder::DecodeGeneric(Instruction* instr) {
#undef DECODE_SI_INSTRUCTIONS
/* 6 bytes */
#define DECODE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'m4,'m5,'m6"); \
break;
S390_VRR_A_OPCODE_LIST(DECODE_VRR_A_INSTRUCTIONS)
#undef DECODE_VRR_A_INSTRUCTIONS
#define DECODE_VRR_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'f3,'m4,'m6"); \
break;
S390_VRR_B_OPCODE_LIST(DECODE_VRR_B_INSTRUCTIONS)
#undef DECODE_VRR_B_INSTRUCTIONS
#define DECODE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'f3"); \
Format(instr, #name "\t'f1,'f2,'f3,'m4"); \
break;
S390_VRR_C_OPCODE_LIST(DECODE_VRR_C_INSTRUCTIONS)
#undef DECODE_VRR_C_INSTRUCTIONS
#define DECODE_VRR_E_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'f3,'f4,'m5,'m3"); \
break;
S390_VRR_E_OPCODE_LIST(DECODE_VRR_E_INSTRUCTIONS)
#undef DECODE_VRR_E_INSTRUCTIONS
#define DECODE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'d1('r2d,'r3),'m4"); \
break;
S390_VRX_OPCODE_LIST(DECODE_VRX_INSTRUCTIONS)
#undef DECODE_VRX_INSTRUCTIONS
#define DECODE_VRS_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'d1('r3),'m4"); \
break;
S390_VRS_A_OPCODE_LIST(DECODE_VRS_A_INSTRUCTIONS)
#undef DECODE_VRS_A_INSTRUCTIONS
#define DECODE_VRS_B_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'r2,'d1('r3),'m4"); \
break;
S390_VRS_B_OPCODE_LIST(DECODE_VRS_B_INSTRUCTIONS)
#undef DECODE_VRS_B_INSTRUCTIONS
#define DECODE_VRS_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'r1,'f2,'d1('r3),'m4"); \
break;
S390_VRS_C_OPCODE_LIST(DECODE_VRS_C_INSTRUCTIONS)
#undef DECODE_VRS_C_INSTRUCTIONS
#define DECODE_VRI_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'i1,'m4"); \
break;
S390_VRI_A_OPCODE_LIST(DECODE_VRI_A_INSTRUCTIONS)
#undef DECODE_VRI_A_INSTRUCTIONS
#define DECODE_VRI_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'f2,'i1,'m4"); \
break;
S390_VRI_C_OPCODE_LIST(DECODE_VRI_C_INSTRUCTIONS)
#undef DECODE_VRI_C_INSTRUCTIONS
#define DECODE_RIL_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'r1,'i7"); \
......
......@@ -3864,6 +3864,11 @@ void TurboAssembler::LoadFloat32ConvertToDouble(DoubleRegister dst,
ldebr(dst, dst);
}
void TurboAssembler::LoadSimd128(Simd128Register dst, const MemOperand& mem) {
DCHECK(is_uint12(mem.offset()));
vl(dst, mem, Condition(0));
}
// Store Double Precision (64-bit) Floating Point number to memory
void TurboAssembler::StoreDouble(DoubleRegister dst, const MemOperand& mem) {
if (is_uint12(mem.offset())) {
......@@ -3891,6 +3896,11 @@ void TurboAssembler::StoreDoubleAsFloat32(DoubleRegister src,
StoreFloat32(scratch, mem);
}
void TurboAssembler::StoreSimd128(Simd128Register src, const MemOperand& mem) {
DCHECK(is_uint12(mem.offset()));
vst(src, mem, Condition(0));
}
void TurboAssembler::AddFloat32(DoubleRegister dst, const MemOperand& opnd,
DoubleRegister scratch) {
if (is_uint12(opnd.offset())) {
......@@ -4330,6 +4340,31 @@ void TurboAssembler::SwapDouble(MemOperand src, MemOperand dst,
StoreDouble(scratch_1, src);
}
void TurboAssembler::SwapSimd128(Simd128Register src, Simd128Register dst,
Simd128Register scratch) {
if (src == dst) return;
vlr(scratch, src, Condition(0), Condition(0), Condition(0));
vlr(src, dst, Condition(0), Condition(0), Condition(0));
vlr(dst, scratch, Condition(0), Condition(0), Condition(0));
}
void TurboAssembler::SwapSimd128(Simd128Register src, MemOperand dst,
Simd128Register scratch) {
DCHECK(!AreAliased(src, scratch));
vlr(scratch, src, Condition(0), Condition(0), Condition(0));
LoadSimd128(src, dst);
StoreSimd128(scratch, dst);
}
void TurboAssembler::SwapSimd128(MemOperand src, MemOperand dst,
Simd128Register scratch_0,
Simd128Register scratch_1) {
LoadSimd128(scratch_0, src);
LoadSimd128(scratch_1, dst);
StoreSimd128(scratch_0, dst);
StoreSimd128(scratch_1, src);
}
void TurboAssembler::ResetSpeculationPoisonRegister() {
mov(kSpeculationPoisonRegister, Operand(-1));
}
......
......@@ -413,6 +413,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void LoadDouble(DoubleRegister dst, const MemOperand& opnd);
void LoadFloat32(DoubleRegister dst, const MemOperand& opnd);
void LoadFloat32ConvertToDouble(DoubleRegister dst, const MemOperand& mem);
void LoadSimd128(Simd128Register dst, const MemOperand& mem);
void AddFloat32(DoubleRegister dst, const MemOperand& opnd,
DoubleRegister scratch);
......@@ -444,6 +445,7 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void StoreFloat32(DoubleRegister dst, const MemOperand& opnd);
void StoreDoubleAsFloat32(DoubleRegister src, const MemOperand& mem,
DoubleRegister scratch);
void StoreSimd128(Simd128Register src, const MemOperand& mem);
void Branch(Condition c, const Operand& opnd);
void BranchOnCount(Register r1, Label* l);
......@@ -508,12 +510,21 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
#endif
}
void push(DoubleRegister src) {
lay(sp, MemOperand(sp, -kPointerSize));
StoreDouble(src, MemOperand(sp));
}
void push(Register src) {
lay(sp, MemOperand(sp, -kPointerSize));
StoreP(src, MemOperand(sp));
}
void pop(DoubleRegister dst) {
LoadDouble(dst, MemOperand(sp));
la(sp, MemOperand(sp, kPointerSize));
}
void pop(Register dst) {
LoadP(dst, MemOperand(sp));
la(sp, MemOperand(sp, kPointerSize));
......@@ -774,6 +785,12 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void SwapDouble(DoubleRegister src, MemOperand dst, DoubleRegister scratch);
void SwapDouble(MemOperand src, MemOperand dst, DoubleRegister scratch_0,
DoubleRegister scratch_1);
void SwapSimd128(Simd128Register src, Simd128Register dst,
Simd128Register scratch);
void SwapSimd128(Simd128Register src, MemOperand dst,
Simd128Register scratch);
void SwapSimd128(MemOperand src, MemOperand dst, Simd128Register scratch_0,
Simd128Register scratch_1);
// Cleanse pointer address on 31bit by zero out top bit.
// This is a NOP on 64-bit.
......
This diff is collapsed.
......@@ -108,7 +108,8 @@ class Simulator : public SimulatorBase {
// Accessors for register state.
void set_register(int reg, uint64_t value);
uint64_t get_register(int reg) const;
const uint64_t& get_register(int reg) const;
uint64_t& get_register(int reg);
template <typename T>
T get_low_register(int reg) const;
template <typename T>
......@@ -119,20 +120,22 @@ class Simulator : public SimulatorBase {
double get_double_from_register_pair(int reg);
void set_d_register_from_double(int dreg, const double dbl) {
DCHECK(dreg >= 0 && dreg < kNumFPRs);
*bit_cast<double*>(&fp_registers_[dreg]) = dbl;
set_simd_register_by_lane<double>(dreg, 0, dbl);
}
double get_double_from_d_register(int dreg) {
DCHECK(dreg >= 0 && dreg < kNumFPRs);
return *bit_cast<double*>(&fp_registers_[dreg]);
return get_simd_register_by_lane<double>(dreg, 0);
}
void set_d_register(int dreg, int64_t value) {
DCHECK(dreg >= 0 && dreg < kNumFPRs);
fp_registers_[dreg] = value;
set_simd_register_by_lane<int64_t>(dreg, 0, value);
}
int64_t get_d_register(int dreg) {
DCHECK(dreg >= 0 && dreg < kNumFPRs);
return fp_registers_[dreg];
return get_simd_register_by_lane<int64_t>(dreg, 0);
}
void set_d_register_from_float32(int dreg, const float f) {
......@@ -411,7 +414,43 @@ class Simulator : public SimulatorBase {
// On z9 and higher and supported Linux on z Systems platforms, all registers
// are 64-bit, even in 31-bit mode.
uint64_t registers_[kNumGPRs];
int64_t fp_registers_[kNumFPRs];
union fpr_t {
int8_t int8[16];
uint8_t uint8[16];
int16_t int16[8];
uint16_t uint16[8];
int32_t int32[4];
uint32_t uint32[4];
int64_t int64[2];
uint64_t uint64[2];
float f32[4];
double f64[2];
};
fpr_t fp_registers_[kNumFPRs];
static constexpr fpr_t fp_zero = {{0}};
fpr_t& get_simd_register(int reg) {
return fp_registers_[reg];
}
void set_simd_register(int reg, const fpr_t& v) {
get_simd_register(reg) = v;
}
template<class T>
T& get_simd_register_by_lane(int reg, int lane) {
DCHECK_LE(lane, kSimd128Size / sizeof(T));
DCHECK_LT(reg, kNumFPRs);
DCHECK_GE(lane, 0);
DCHECK_GE(reg, 0);
return (reinterpret_cast<T*>(&get_simd_register(reg)))[lane];
}
template<class T>
void set_simd_register_by_lane(int reg, int lane, const T& value) {
get_simd_register_by_lane<T>(reg, lane) = value;
}
// Condition Code register. In S390, the last 4 bits are used.
int32_t condition_reg_;
......@@ -461,10 +500,18 @@ class Simulator : public SimulatorBase {
static void EvalTableInit();
#define EVALUATE(name) int Evaluate_##name(Instruction* instr)
#define EVALUATE_VRR_INSTRUCTIONS(name, op_name, op_value) EVALUATE(op_name);
S390_VRR_C_OPCODE_LIST(EVALUATE_VRR_INSTRUCTIONS)
S390_VRR_A_OPCODE_LIST(EVALUATE_VRR_INSTRUCTIONS)
#undef EVALUATE_VRR_INSTRUCTIONS
#define EVALUATE_VR_INSTRUCTIONS(name, op_name, op_value) EVALUATE(op_name);
S390_VRR_A_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRR_C_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRR_E_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRX_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRS_A_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRS_B_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRS_C_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRR_B_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRI_A_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
S390_VRI_C_OPCODE_LIST(EVALUATE_VR_INSTRUCTIONS)
#undef EVALUATE_VR_INSTRUCTIONS
EVALUATE(DUMY);
EVALUATE(BKPT);
......
This diff is collapsed.
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