Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: src/IceAssemblerARM32.cpp

Issue 1486263002: More coverage of load/stores in ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix remaining issue in patch set 2. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceAssemblerARM32.cpp
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index c429e8be0c72e7a00f9b44873d77d669adfeee75..8f87c920b3d03f339d5f019a1a194b4104dcb052 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -191,13 +191,17 @@ enum DecodedResult {
// p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
// Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
DecodedAsImmRegOffset,
+ // Value=00000000pu0w0nnnn0000iiii0000jjjj where nnnn=Rn, iiiijjjj=Imm8, p=1
+ // if pre-indexed addressing, u=1 if offset positive, and w=1 if writeback to
+ // Rn.
+ DecodedAsImmRegOffsetEnc3,
// Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn,
// mmmm is the index register Rm, iiiii is the shift amount, ss is the shift
// kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
// writeback to Rn.
DecodedAsShiftRotateImm5,
- // Value=000000000000000000000iiiii0000000 iiii defines the Imm5 value to
- // shift.
+ // Value=000000000000000000000iiiii0000000 where iiii defines the Imm5 value
+ // to shift.
DecodedAsShiftImm5,
// i.e. iiiiiss0mmmm where mmmm is the register to rotate, ss is the shift
// kind, and iiiii is the shift amount.
@@ -272,9 +276,9 @@ DecodedResult decodeOperand(const Operand *Opnd, IValueT &Value) {
return CantDecode;
}
-IValueT decodeImmRegOffset(RegARM32::GPRRegister Reg, IOffsetT Offset,
+IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset,
OperandARM32Mem::AddrMode Mode) {
- IValueT Value = Mode | (encodeGPRRegister(Reg) << kRnShift);
+ IValueT Value = Mode | (Reg << kRnShift);
if (Offset < 0) {
Value = (Value ^ U) | -Offset; // Flip U to adjust sign.
} else {
@@ -283,10 +287,33 @@ IValueT decodeImmRegOffset(RegARM32::GPRRegister Reg, IOffsetT Offset,
return Value;
}
+// Encodes immediate register offset using encoding 3.
+IValueT encodeImmRegOffsetEnc3(IValueT Rn, IOffsetT Imm8,
+ OperandARM32Mem::AddrMode Mode) {
+ IValueT Value = Mode | (Rn << kRnShift);
+ if (Imm8 < 0) {
+ Imm8 = -Imm8;
+ Value = (Value ^ U);
+ }
+ assert(Imm8 < (1 << 8));
+ Value = Value | B22 | ((Imm8 & 0xf0) << 4) | (Imm8 & 0x0f);
+ return Value;
+}
+
+// Defines alternate layouts of instruction operands, should the (common)
+// default pattern not be used.
+enum OpEncoding {
+ // No alternate layout specified.
+ DefaultOpEncoding,
+ // Alternate encoding 3.
+ OpEncoding3
+};
+
// Decodes memory address Opnd, and encodes that information into Value,
// based on how ARM represents the address. Returns how the value was encoded.
DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value,
- const AssemblerARM32::TargetInfo &TInfo) {
+ const AssemblerARM32::TargetInfo &TInfo,
+ OpEncoding AddressEncoding = DefaultOpEncoding) {
Value = 0; // Make sure initialized.
if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
// Should be a stack variable, with an offset.
@@ -298,8 +325,7 @@ DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value,
int32_t BaseRegNum = Var->getBaseRegNum();
if (BaseRegNum == Variable::NoRegister)
BaseRegNum = TInfo.FrameOrStackReg;
- Value = decodeImmRegOffset(decodeGPRRegister(BaseRegNum), Offset,
- OperandARM32Mem::Offset);
+ Value = encodeImmRegOffset(BaseRegNum, Offset, OperandARM32Mem::Offset);
return DecodedAsImmRegOffset;
}
if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
@@ -318,9 +344,15 @@ DecodedResult decodeAddress(const Operand *Opnd, IValueT &Value,
}
// Decoded as immediate register offset.
ConstantInteger32 *Offset = Mem->getOffset();
- Value = decodeImmRegOffset(decodeGPRRegister(Rn), Offset->getValue(),
- Mem->getAddrMode());
- return DecodedAsImmRegOffset;
+ switch (AddressEncoding) {
+ case DefaultOpEncoding:
+ Value = encodeImmRegOffset(Rn, Offset->getValue(), Mem->getAddrMode());
+ return DecodedAsImmRegOffset;
+ case OpEncoding3:
+ Value =
+ encodeImmRegOffsetEnc3(Rn, Offset->getValue(), Mem->getAddrMode());
+ return DecodedAsImmRegOffsetEnc3;
+ }
}
return CantDecode;
}
@@ -607,6 +639,128 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
emitInst(Encoding);
}
+void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
+ IValueT Rt, const Operand *OpAddress,
+ const TargetInfo &TInfo) {
+ IValueT Address;
+ switch (decodeAddress(OpAddress, Address, TInfo)) {
+ default:
+ return setNeedsTextFixup();
+ case DecodedAsImmRegOffset: {
+ // XXX{B} (immediate):
+ // xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
+ // xxx{b}<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
+ // xxx{b}<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ //
+ // cccc010pubwlnnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiiiiiii=imm12, b=IsByte, pu0w<<21 is a BlockAddr, l=IsLoad, and
+ // pu0w0nnnn0000iiiiiiiiiiii=Address.
+ RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
+
+ // Check if conditions of rules violated.
+ if (Rn == RegARM32::Encoded_Reg_pc)
+ return setNeedsTextFixup();
+ if (!isBitSet(P, Address) && isBitSet(W, Address))
+ return setNeedsTextFixup();
+ if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) &&
+ isBitSet(U, Address) & !isBitSet(W, Address) &&
+ (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
+ return setNeedsTextFixup();
+
+ return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
+ }
+ case DecodedAsShiftRotateImm5: {
+ // XXX{B} (register)
+ // xxx{b}<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
+ // xxx{b}<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
+ //
+ // cccc011pubwlnnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt,
+ // b=IsByte, U=1 if +, pu0b is a BlockAddr, l=IsLoad, and
+ // pu0w0nnnn0000iiiiiss0mmmm=Address.
+ RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
+ RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address);
+
+ // Check if conditions of rules violated.
+ if (isBitSet(P, Address) && isBitSet(W, Address))
+ // Instruction XXXBT!
+ return setNeedsTextFixup();
+ if (IsByte &&
+ ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc)))
+ // Unpredictable.
+ return setNeedsTextFixup();
+ if (!IsByte && Rm == RegARM32::Encoded_Reg_pc)
+ // Unpredictable.
+ return setNeedsTextFixup();
+ if (isBitSet(W, Address) &&
+ ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt))
+ // Unpredictable
+ return setNeedsTextFixup();
+
+ return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address);
+ }
+ }
+}
+
+void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
+ IValueT Rt, const Operand *OpAddress,
+ const TargetInfo &TInfo) {
+ IValueT Address;
+ switch (decodeAddress(OpAddress, Address, TInfo, OpEncoding3)) {
+ default:
+ return setNeedsTextFixup();
+ case DecodedAsImmRegOffsetEnc3: {
+ // XXXH (immediate)
+ // xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
+ // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]
+ // xxxh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
+ //
+ // cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
+ // iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
+ // and pu0w0nnnn0000iiii0000jjjj=Address.
+ if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
+ return setNeedsTextFixup();
+ if (!isBitSet(P, Address) && isBitSet(W, Address))
+ return setNeedsTextFixup();
+ if ((Rt == RegARM32::Encoded_Reg_pc) ||
+ (isBitSet(W, Address) &&
+ (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt))))
+ return setNeedsTextFixup();
+ const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
+ Opcode | (Rt << kRdShift) | Address;
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ return emitInst(Encoding);
+ }
+ case DecodedAsShiftRotateImm5: {
+ // XXXH (register)
+ // xxxh<c> <Rt>, [<Rn>, +/-<Rm>]{!}
+ // xxxh<c> <Rt>, [<Rn>], +/-<Rm>
+ //
+ // cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and
+ // pu0w0nnnn000000000000mmmm=Address.
+ if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
+ return setNeedsTextFixup();
+ if (!isBitSet(P, Address) && isBitSet(W, Address))
+ return setNeedsTextFixup();
+ if (Rt == RegARM32::Encoded_Reg_pc)
+ return setNeedsTextFixup();
+ if (getGPRReg(kRmShift, Address) == RegARM32::Encoded_Reg_pc)
+ return setNeedsTextFixup();
+ const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
+ if (isBitSet(W, Address) &&
+ ((Rn == RegARM32::Encoded_Reg_pc) || (encodeGPRRegister(Rn) == Rt)))
+ return setNeedsTextFixup();
+ if (mask(Address, kShiftImmShift, 5) != 0)
+ // For encoding 3, no shift is allowed.
+ return setNeedsTextFixup();
+ const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
+ Opcode | (Rt << kRdShift) | Address;
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+ return emitInst(Encoding);
+ }
+ }
+}
+
void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
IValueT Rn, IValueT Rm) {
if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) ||
@@ -840,75 +994,68 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
if (decodeOperand(OpRt, Rt) != DecodedAsRegister)
return setNeedsTextFixup();
const Type Ty = OpRt->getType();
- if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
- return setNeedsTextFixup();
- const bool IsByte = isByteSizedType(Ty);
- IValueT Address;
- switch (decodeAddress(OpAddress, Address, TInfo)) {
+ switch (typeWidthInBytesLog2(Ty)) {
+ case 3:
+ // LDRD is not implemented because target lowering handles i64 and double by
+ // using two (32-bit) load instructions. Note: Intenionally drop to default
+ // case.
default:
- return setNeedsTextFixup();
- case DecodedAsImmRegOffset: {
- // LDR (immediate) - ARM section A8.8.63, encoding A1:
- // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
- // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
- // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ llvm::report_fatal_error(std::string("Type ") + typeString(Ty) +
+ " not implementable using ldr\n");
+ case 0: {
+ // Handles i1 and i8 loads.
//
// LDRB (immediate) - ARM section A8.8.68, encoding A1:
// ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
// ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
// ldrb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
//
- // cccc010pubw1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
- // iiiiiiiiiiii=imm12, b=1 if LDRB, u=1 if +, pu0w is a BlockAddr, and
+ // cccc010pu1w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
// pu0w0nnnn0000iiiiiiiiiiii=Address.
-
- RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
-
- // Check if conditions of rules violated.
- if (Rn == RegARM32::Encoded_Reg_pc)
- return setNeedsTextFixup();
- if (!isBitSet(P, Address) && isBitSet(W, Address))
- return setNeedsTextFixup();
- if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) &&
- isBitSet(U, Address) & !isBitSet(W, Address) &&
- (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
- return setNeedsTextFixup();
-
- return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
+ //
+ // LDRB (register) - ARM section A8.8.66, encoding A1:
+ // ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
+ // ldrb<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
+ //
+ // cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
+ // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
+ constexpr bool IsByte = true;
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
}
- case DecodedAsShiftRotateImm5: {
- // LDR (register) - ARM section A8.8.66, encoding A1:
- // ldr<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
- // ldr<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
+ case 1: {
+ // Handles i16 loads.
+ //
+ // LDRH (immediate) - ARM section A8.8.80, encoding A1:
+ // ldrh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
+ // ldrh<c> <Rt>, [<Rn>], #+/-<Imm8>
+ // ldrh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
+ //
+ // cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
+ // pu0w0nnnn0000iiiiiiiiiiii=Address.
+ return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo);
+ }
+ case 2: {
+ // Note: Handles i32 and float loads. Target lowering handles i64 and
+ // double by using two (32 bit) load instructions.
+ //
+ // LDR (immediate) - ARM section A8.8.63, encoding A1:
+ // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
+ // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
+ // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ //
+ // cccc010pu0w1nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiiiiiii=imm12, u=1 if +, pu0w is a BlockAddr, and
//
- // LDRB (register) - ARM section A8.8.70, encoding A1:
+ // LDR (register) - ARM section A8.8.70, encoding A1:
// ldrb<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
// ldrb<c> <Rt>, [<Rn>], +-<Rm>{, <shift>}
//
- // cccc011pubw1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt,
- // b=1 if LDRB, U=1 if +, pu0b is a BlockAddr, and
- // pu0w0nnnn0000iiiiiss0mmmm=Address.
-
- RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
- RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address);
-
- // Check if conditions of rules violated.
- if (isBitSet(P, Address) && isBitSet(W, Address))
- // Instruction LDRBT!
- return setNeedsTextFixup();
- if (IsByte &&
- ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc)))
- // Unpredictable.
- return setNeedsTextFixup();
- if (!IsByte && Rm == RegARM32::Encoded_Reg_pc)
- // Unpredictable.
- return setNeedsTextFixup();
- if (isBitSet(W, Address) &&
- ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt))
- // Unpredictable
- return setNeedsTextFixup();
-
- return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address);
+ // cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
+ // is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
+ constexpr bool IsByte = false;
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
}
}
}
@@ -1127,38 +1274,61 @@ void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn,
void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
CondARM32::Cond Cond, const TargetInfo &TInfo) {
+ constexpr bool IsLoad = false;
IValueT Rt;
if (decodeOperand(OpRt, Rt) != DecodedAsRegister)
return setNeedsTextFixup();
- IValueT Address;
- if (decodeAddress(OpAddress, Address, TInfo) != DecodedAsImmRegOffset)
- return setNeedsTextFixup();
- // STR (immediate) - ARM section A8.8.204, encoding A1:
- // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
- // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
- // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
- // STRB (immediate) - ARM section A8.8.207, encoding A1:
- // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
- // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
- // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
- //
- // cccc010pubw0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
- // iiiiiiiiiiii=imm12, b=1 if STRB, u=1 if +.
- constexpr bool IsLoad = false;
const Type Ty = OpRt->getType();
- if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
- return setNeedsTextFixup();
- const bool IsByte = isByteSizedType(Ty);
- // Check for rule violations.
- if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc))
- return setNeedsTextFixup();
- if (!isBitSet(P, Address) && isBitSet(W, Address))
- return setNeedsTextFixup();
- if (!IsByte && (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) &&
- isBitSet(P, Address) && !isBitSet(U, Address) && isBitSet(W, Address) &&
- (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
+ switch (typeWidthInBytesLog2(Ty)) {
+ case 3:
+ // STRD is not implemented because target lowering handles i64 and double by
+ // using two (32-bit) store instructions. Note: Intenionally drop to
+ // default case.
+ default:
+ llvm::report_fatal_error(std::string("Type ") + typeString(Ty) +
+ " not implementable using str\n");
+ case 0: {
+ // Handles i1 and i8 stores.
+ //
+ // STRB (immediate) - ARM section A8.8.207, encoding A1:
+ // strb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
+ // strb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
+ // strb<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ //
+ // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiiiiiii=imm12, u=1 if +.
+ constexpr bool IsByte = true;
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
+ }
+ case 1: {
+ // Handles i16 stores.
+ //
+ // STRH (immediate) - ARM section A8.*.217, encoding A1:
+ // strh<c> <Rt>, [<Rn>{, #+/-<Imm8>}]
+ // strh<c> <Rt>, [<Rn>], #+/-<Imm8>
+ // strh<c> <Rt>, [<Rn>, #+/-<Imm8>]!
+ //
+ // cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
+ // pu0w0nnnn0000iiiiiiiiiiii=Address.
+ return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo);
+ }
+ case 2: {
+ // Note: Handles i32 and float stores. Target lowering handles i64 and
+ // double by using two (32 bit) store instructions.
+ //
+ // STR (immediate) - ARM section A8.8.207, encoding A1:
+ // str<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
+ // str<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
+ // str<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ //
+ // cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
+ // iiiiiiiiiiii=imm12, u=1 if +.
+ constexpr bool IsByte = false;
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
return setNeedsTextFixup();
- emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
+ }
+ }
}
void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
@@ -1191,7 +1361,7 @@ void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) {
// Same as load instruction.
constexpr bool IsLoad = true;
constexpr bool IsByte = false;
- IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize,
+ IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize,
OperandARM32Mem::PostIndex);
emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
}
@@ -1218,7 +1388,7 @@ void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) {
// Same as store instruction.
constexpr bool isLoad = false;
constexpr bool isByte = false;
- IValueT Address = decodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize,
+ IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize,
OperandARM32Mem::PreIndex);
emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address);
}
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | src/IceInstARM32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698