Commit ee2f07b6 authored by bjaideep's avatar bjaideep Committed by Commit bot

PPC: Implement VSX instructions

Add VSX instructions to perform add/sub/mul/div

R=jyan@ca.ibm.com, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com, danno@chromium.org, jkummerow@chromium.org, jochen@chromium.org
BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2619763003
Cr-Commit-Position: refs/heads/master@{#42272}
parent b4654bf3
......@@ -1990,16 +1990,32 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
DoubleRegister result = ToDoubleRegister(instr->result());
switch (instr->op()) {
case Token::ADD:
__ fadd(result, left, right);
if (CpuFeatures::IsSupported(VSX)) {
__ xsadddp(result, left, right);
} else {
__ fadd(result, left, right);
}
break;
case Token::SUB:
__ fsub(result, left, right);
if (CpuFeatures::IsSupported(VSX)) {
__ xssubdp(result, left, right);
} else {
__ fsub(result, left, right);
}
break;
case Token::MUL:
__ fmul(result, left, right);
if (CpuFeatures::IsSupported(VSX)) {
__ xsmuldp(result, left, right);
} else {
__ fmul(result, left, right);
}
break;
case Token::DIV:
__ fdiv(result, left, right);
if (CpuFeatures::IsSupported(VSX)) {
__ xsdivdp(result, left, right);
} else {
__ fdiv(result, left, right);
}
break;
case Token::MOD: {
__ PrepareCallCFunction(0, 2, scratch0());
......
......@@ -784,6 +784,7 @@ enum CpuFeature {
FPR_GPR_MOV,
LWSYNC,
ISELECT,
VSX,
// S390
DISTINCT_OPS,
GENERAL_INSTR_EXT,
......
......@@ -79,6 +79,7 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
if (cpu.part() == base::CPU::PPC_POWER7 ||
cpu.part() == base::CPU::PPC_POWER8) {
supported_ |= (1u << ISELECT);
supported_ |= (1u << VSX);
}
#if V8_OS_LINUX
if (!(cpu.part() == base::CPU::PPC_G5 || cpu.part() == base::CPU::PPC_G4)) {
......@@ -96,6 +97,7 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
supported_ |= (1u << FPU);
supported_ |= (1u << LWSYNC);
supported_ |= (1u << ISELECT);
supported_ |= (1u << VSX);
#if V8_TARGET_ARCH_PPC64
supported_ |= (1u << FPR_GPR_MOV);
#endif
......@@ -646,6 +648,14 @@ void Assembler::xo_form(Instr instr, Register rt, Register ra, Register rb,
emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 | o | r);
}
void Assembler::xx3_form(Instr instr, DoubleRegister t, DoubleRegister a,
DoubleRegister b) {
int AX = ((a.code() & 0x20) >> 5) & 0x1;
int BX = ((b.code() & 0x20) >> 5) & 0x1;
int TX = ((t.code() & 0x20) >> 5) & 0x1;
emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 | (b.code()
& 0x1F) * B11 | AX * B2 | BX * B1 | TX);
}
void Assembler::md_form(Instr instr, Register ra, Register rs, int shift,
int maskbit, RCBit r) {
......@@ -2327,6 +2337,24 @@ void Assembler::fmsub(const DoubleRegister frt, const DoubleRegister fra,
frc.code() * B6 | rc);
}
// Support for VSX instructions
void Assembler::xsadddp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb) {
xx3_form(EXT6 | XSADDDP, frt, fra, frb);
}
void Assembler::xssubdp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb) {
xx3_form(EXT6 | XSSUBDP, frt, fra, frb);
}
void Assembler::xsdivdp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb) {
xx3_form(EXT6 | XSDIVDP, frt, fra, frb);
}
void Assembler::xsmuldp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb) {
xx3_form(EXT6 | XSMULDP, frt, fra, frb);
}
// Pseudo instructions.
void Assembler::nop(int type) {
......
......@@ -1104,6 +1104,17 @@ class Assembler : public AssemblerBase {
const DoubleRegister frc, const DoubleRegister frb,
RCBit rc = LeaveRC);
// Support for VSX instructions
void xsadddp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb);
void xssubdp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb);
void xsdivdp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frb);
void xsmuldp(const DoubleRegister frt, const DoubleRegister fra,
const DoubleRegister frc);
// Pseudo instructions
// Different nop operations are used by the code generator to detect certain
......@@ -1406,6 +1417,8 @@ class Assembler : public AssemblerBase {
void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
RCBit r);
void xx3_form(Instr instr, DoubleRegister t, DoubleRegister a,
DoubleRegister b);
void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
RCBit r);
void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
......
......@@ -145,6 +145,7 @@ enum Opcode {
STFDU = 55 << 26, // Store Floating-Point Double with Update
LD = 58 << 26, // Load Double Word
EXT3 = 59 << 26, // Extended code set 3
EXT6 = 60 << 26, // Extended code set 6
STD = 62 << 26, // Store Double Word (optionally with Update)
EXT4 = 63 << 26 // Extended code set 4
};
......@@ -314,10 +315,37 @@ enum OpcodeExt5 {
RLDCR = 9 << 1 // Rotate Left Double Word then Clear Right
};
// Bits 10-3
#define XX3_OPCODE_LIST(V) \
V(xsaddsp, XSADDSP, 0 << 3) /* VSX Scalar Add SP */ \
V(xssubsp, XSSUBSP, 8 << 3) /* VSX Scalar Subtract SP */ \
V(xsmulsp, XSMULSP, 16 << 3) /* VSX Scalar Multiply SP */ \
V(xsdivsp, XSDIVSP, 24 << 3) /* VSX Scalar Divide SP */ \
V(xsadddp, XSADDDP, 32 << 3) /* VSX Scalar Add DP */ \
V(xssubdp, XSSUBDP, 40 << 3) /* VSX Scalar Subtract DP */ \
V(xsmuldp, XSMULDP, 48 << 3) /* VSX Scalar Multiply DP */ \
V(xsdivdp, XSDIVDP, 56 << 3) /* VSX Scalar Divide DP */ \
V(xsmaxdp, XSMAXDP, 160 << 3) /* VSX Scalar Maximum DP */ \
V(xsmindp, XSMINDP, 168 << 3) /* VSX Scalar Minimum DP */
// Bits 10-2
#define XX2_OPCODE_LIST(V) \
V(XSCVDPSP, XSCVDPSP, 265 << 2) /* VSX Scalar Convert DP to SP */ \
V(XSCVSPDP, XSCVSPDP, 329 << 2) /* VSX Scalar Convert SP to DP */
enum OpcodeExt6 {
#define DECLARE_OPCODES(name, opcode_name, opcode_value) \
opcode_name = opcode_value,
XX3_OPCODE_LIST(DECLARE_OPCODES) XX2_OPCODE_LIST(DECLARE_OPCODES)
#undef DECLARE_OPCODES
};
// Instruction encoding bits and masks.
enum {
// Instruction encoding bit
B1 = 1 << 1,
B2 = 1 << 2,
B3 = 1 << 3,
B4 = 1 << 4,
B5 = 1 << 5,
B7 = 1 << 7,
......
......@@ -82,6 +82,7 @@ class Decoder {
void DecodeExt3(Instruction* instr);
void DecodeExt4(Instruction* instr);
void DecodeExt5(Instruction* instr);
void DecodeExt6(Instruction* instr);
const disasm::NameConverter& converter_;
Vector<char> out_buffer_;
......@@ -1073,6 +1074,28 @@ void Decoder::DecodeExt5(Instruction* instr) {
Unknown(instr); // not used by V8
}
void Decoder::DecodeExt6(Instruction* instr) {
switch (instr->Bits(10, 3) << 3) {
#define DECODE_XX3_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: { \
Format(instr, #name" 'Dt, 'Da, 'Db"); \
return; \
}
XX3_OPCODE_LIST(DECODE_XX3_INSTRUCTIONS)
#undef DECODE_XX3_INSTRUCTIONS
}
switch (instr->Bits(10, 2) << 2) {
#define DECODE_XX2_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: { \
Format(instr, #name" 'Dt, 'Db"); \
return; \
}
XX2_OPCODE_LIST(DECODE_XX2_INSTRUCTIONS)
}
#undef DECODE_XX3_INSTRUCTIONS
Unknown(instr); // not used by V8
}
#undef VERIFIY
// Disassemble the instruction at *instr_ptr into the output buffer.
......@@ -1360,6 +1383,10 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
DecodeExt5(instr);
break;
}
case EXT6: {
DecodeExt6(instr);
break;
}
#if V8_TARGET_ARCH_PPC64
case LD: {
switch (instr->Bits(1, 0)) {
......
......@@ -3295,6 +3295,51 @@ void Simulator::ExecuteExt5(Instruction* instr) {
}
#endif
void Simulator::ExecuteExt6(Instruction* instr) {
switch (instr->Bits(10, 3) << 3) {
case XSADDDP: {
int frt = instr->RTValue();
int fra = instr->RAValue();
int frb = instr->RBValue();
double fra_val = get_double_from_d_register(fra);
double frb_val = get_double_from_d_register(frb);
double frt_val = fra_val + frb_val;
set_d_register_from_double(frt, frt_val);
return;
}
case XSSUBDP: {
int frt = instr->RTValue();
int fra = instr->RAValue();
int frb = instr->RBValue();
double fra_val = get_double_from_d_register(fra);
double frb_val = get_double_from_d_register(frb);
double frt_val = fra_val - frb_val;
set_d_register_from_double(frt, frt_val);
return;
}
case XSMULDP: {
int frt = instr->RTValue();
int fra = instr->RAValue();
int frb = instr->RBValue();
double fra_val = get_double_from_d_register(fra);
double frb_val = get_double_from_d_register(frb);
double frt_val = fra_val * frb_val;
set_d_register_from_double(frt, frt_val);
return;
}
case XSDIVDP: {
int frt = instr->RTValue();
int fra = instr->RAValue();
int frb = instr->RBValue();
double fra_val = get_double_from_d_register(fra);
double frb_val = get_double_from_d_register(frb);
double frt_val = fra_val / frb_val;
set_d_register_from_double(frt, frt_val);
return;
}
}
UNIMPLEMENTED(); // Not used by V8.
}
void Simulator::ExecuteGeneric(Instruction* instr) {
int opcode = instr->OpcodeValue() << 26;
......@@ -3810,6 +3855,10 @@ void Simulator::ExecuteGeneric(Instruction* instr) {
break;
}
#endif
case EXT6: {
ExecuteExt6(instr);
break;
}
default: {
UNIMPLEMENTED();
......
......@@ -321,6 +321,7 @@ class Simulator {
#if V8_TARGET_ARCH_PPC64
void ExecuteExt5(Instruction* instr);
#endif
void ExecuteExt6(Instruction* instr);
void ExecuteGeneric(Instruction* instr);
void SetFPSCR(int bit) { fp_condition_reg_ |= (1 << (31 - bit)); }
......
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