| Index: src/assembler_ia32.cpp
|
| diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
|
| index 3775cc865221a0014a3a035ea81cc57a05d69a29..a245ca99dcbe948e25e76fbad62a698a35665698 100644
|
| --- a/src/assembler_ia32.cpp
|
| +++ b/src/assembler_ia32.cpp
|
| @@ -537,6 +537,34 @@ void AssemblerX86::pandn(Type /* Ty */, XmmRegister dst, const Address &src) {
|
| EmitOperand(dst, src);
|
| }
|
|
|
| +void AssemblerX86::pmull(Type Ty, XmmRegister dst, XmmRegister src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xD5);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0x38);
|
| + EmitUint8(0x40);
|
| + }
|
| + EmitXmmRegisterOperand(dst, src);
|
| +}
|
| +
|
| +void AssemblerX86::pmull(Type Ty, XmmRegister dst, const Address &src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xD5);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0x38);
|
| + EmitUint8(0x40);
|
| + }
|
| + EmitOperand(dst, src);
|
| +}
|
| +
|
| void AssemblerX86::pmuludq(Type /* Ty */, XmmRegister dst, XmmRegister src) {
|
| AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| EmitUint8(0x66);
|
| @@ -613,6 +641,88 @@ void AssemblerX86::pxor(Type /* Ty */, XmmRegister dst, const Address &src) {
|
| EmitOperand(dst, src);
|
| }
|
|
|
| +void AssemblerX86::psll(Type Ty, XmmRegister dst, XmmRegister src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xF1);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0xF2);
|
| + }
|
| + EmitXmmRegisterOperand(dst, src);
|
| +}
|
| +
|
| +void AssemblerX86::psll(Type Ty, XmmRegister dst, const Address &src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xF1);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0xF2);
|
| + }
|
| + EmitOperand(dst, src);
|
| +}
|
| +
|
| +void AssemblerX86::psll(Type Ty, XmmRegister dst, const Immediate &imm) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + assert(imm.is_int8());
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0x71);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0x72);
|
| + }
|
| + EmitRegisterOperand(6, dst);
|
| + EmitUint8(imm.value() & 0xFF);
|
| +}
|
| +
|
| +void AssemblerX86::psra(Type Ty, XmmRegister dst, XmmRegister src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xE1);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0xE2);
|
| + }
|
| + EmitXmmRegisterOperand(dst, src);
|
| +}
|
| +
|
| +void AssemblerX86::psra(Type Ty, XmmRegister dst, const Address &src) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0xE1);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0xE2);
|
| + }
|
| + EmitOperand(dst, src);
|
| +}
|
| +
|
| +void AssemblerX86::psra(Type Ty, XmmRegister dst, const Immediate &imm) {
|
| + AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| + assert(imm.is_int8());
|
| + EmitUint8(0x66);
|
| + EmitUint8(0x0F);
|
| + if (Ty == IceType_i16) {
|
| + EmitUint8(0x71);
|
| + } else {
|
| + assert(Ty == IceType_i32);
|
| + EmitUint8(0x72);
|
| + }
|
| + EmitRegisterOperand(4, dst);
|
| + EmitUint8(imm.value() & 0xFF);
|
| +}
|
| +
|
| // {add,sub,mul,div}ps are given a Ty parameter for consistency with
|
| // {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows
|
| // addpd, etc., we can use the Ty parameter to decide on adding
|
| @@ -1639,36 +1749,52 @@ void AssemblerX86::decl(const Address &address) {
|
| EmitOperand(1, address);
|
| }
|
|
|
| -void AssemblerX86::shll(GPRRegister reg, const Immediate &imm) {
|
| - EmitGenericShift(4, reg, imm);
|
| +void AssemblerX86::rol(Type Ty, GPRRegister reg, const Immediate &imm) {
|
| + EmitGenericShift(0, Ty, reg, imm);
|
| +}
|
| +
|
| +void AssemblerX86::rol(Type Ty, GPRRegister operand, GPRRegister shifter) {
|
| + EmitGenericShift(0, Ty, Operand(operand), shifter);
|
| +}
|
| +
|
| +void AssemblerX86::rol(Type Ty, const Address &operand, GPRRegister shifter) {
|
| + EmitGenericShift(0, Ty, operand, shifter);
|
| +}
|
| +
|
| +void AssemblerX86::shl(Type Ty, GPRRegister reg, const Immediate &imm) {
|
| + EmitGenericShift(4, Ty, reg, imm);
|
| +}
|
| +
|
| +void AssemblerX86::shl(Type Ty, GPRRegister operand, GPRRegister shifter) {
|
| + EmitGenericShift(4, Ty, Operand(operand), shifter);
|
| }
|
|
|
| -void AssemblerX86::shll(GPRRegister operand, GPRRegister shifter) {
|
| - EmitGenericShift(4, Operand(operand), shifter);
|
| +void AssemblerX86::shl(Type Ty, const Address &operand, GPRRegister shifter) {
|
| + EmitGenericShift(4, Ty, operand, shifter);
|
| }
|
|
|
| -void AssemblerX86::shll(const Address &operand, GPRRegister shifter) {
|
| - EmitGenericShift(4, Operand(operand), shifter);
|
| +void AssemblerX86::shr(Type Ty, GPRRegister reg, const Immediate &imm) {
|
| + EmitGenericShift(5, Ty, reg, imm);
|
| }
|
|
|
| -void AssemblerX86::shrl(GPRRegister reg, const Immediate &imm) {
|
| - EmitGenericShift(5, reg, imm);
|
| +void AssemblerX86::shr(Type Ty, GPRRegister operand, GPRRegister shifter) {
|
| + EmitGenericShift(5, Ty, Operand(operand), shifter);
|
| }
|
|
|
| -void AssemblerX86::shrl(GPRRegister operand, GPRRegister shifter) {
|
| - EmitGenericShift(5, Operand(operand), shifter);
|
| +void AssemblerX86::shr(Type Ty, const Address &operand, GPRRegister shifter) {
|
| + EmitGenericShift(5, Ty, operand, shifter);
|
| }
|
|
|
| -void AssemblerX86::sarl(GPRRegister reg, const Immediate &imm) {
|
| - EmitGenericShift(7, reg, imm);
|
| +void AssemblerX86::sar(Type Ty, GPRRegister reg, const Immediate &imm) {
|
| + EmitGenericShift(7, Ty, reg, imm);
|
| }
|
|
|
| -void AssemblerX86::sarl(GPRRegister operand, GPRRegister shifter) {
|
| - EmitGenericShift(7, Operand(operand), shifter);
|
| +void AssemblerX86::sar(Type Ty, GPRRegister operand, GPRRegister shifter) {
|
| + EmitGenericShift(7, Ty, Operand(operand), shifter);
|
| }
|
|
|
| -void AssemblerX86::sarl(const Address &address, GPRRegister shifter) {
|
| - EmitGenericShift(7, Operand(address), shifter);
|
| +void AssemblerX86::sar(Type Ty, const Address &address, GPRRegister shifter) {
|
| + EmitGenericShift(7, Ty, address, shifter);
|
| }
|
|
|
| void AssemblerX86::shld(GPRRegister dst, GPRRegister src) {
|
| @@ -2129,27 +2255,31 @@ void AssemblerX86::EmitNearLabelLink(Label *label) {
|
| label->NearLinkTo(position);
|
| }
|
|
|
| -void AssemblerX86::EmitGenericShift(int rm, GPRRegister reg,
|
| +void AssemblerX86::EmitGenericShift(int rm, Type Ty, GPRRegister reg,
|
| const Immediate &imm) {
|
| AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| assert(imm.is_int8());
|
| + if (Ty == IceType_i16)
|
| + EmitOperandSizeOverride();
|
| if (imm.value() == 1) {
|
| - EmitUint8(0xD1);
|
| + EmitUint8(isByteSizedArithType(Ty) ? 0xD0 : 0xD1);
|
| EmitOperand(rm, Operand(reg));
|
| } else {
|
| - EmitUint8(0xC1);
|
| + EmitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1);
|
| EmitOperand(rm, Operand(reg));
|
| EmitUint8(imm.value() & 0xFF);
|
| }
|
| }
|
|
|
| -void AssemblerX86::EmitGenericShift(int rm, const Operand &operand,
|
| +void AssemblerX86::EmitGenericShift(int rm, Type Ty, const Operand &operand,
|
| GPRRegister shifter) {
|
| AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
| assert(shifter == RegX8632::Encoded_Reg_ecx);
|
| (void)shifter;
|
| - EmitUint8(0xD3);
|
| - EmitOperand(rm, Operand(operand));
|
| + if (Ty == IceType_i16)
|
| + EmitOperandSizeOverride();
|
| + EmitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3);
|
| + EmitOperand(rm, operand);
|
| }
|
|
|
| } // end of namespace x86
|
|
|