Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index fc60e0d9c6c0a8f5a2942b782b6b5da7105392ee..06ba9c466e55a85a98b74024c3b66229b3117ce8 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -70,6 +70,11 @@ static constexpr uint32_t kShiftShift = 5; |
static constexpr uint32_t kImmed12Bits = 12; |
static constexpr uint32_t kImm12Shift = 0; |
+// Type of instruction encoding (bits 25-27). See ARM section A5.1 |
+static constexpr uint32_t kInstTypeDataRegister = 0; // i.e. 000 |
+static constexpr uint32_t kInstTypeDataImmediate = 1; // i.e. 001 |
+static constexpr uint32_t kInstTypeMemImmediate = 2; // i.e. 010 |
+ |
inline uint32_t encodeBool(bool b) { return b ? 1 : 0; } |
inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) { |
@@ -231,6 +236,14 @@ void ARM32::AssemblerARM32::bind(Label *label) { |
label->bindTo(bound); |
} |
+void ARM32::AssemblerARM32::emitTextInst(const std::string &Text) { |
+ static constexpr uint32_t Placeholder = 0; |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ AssemblerFixup *F = createTextFixup(Text, sizeof(Placeholder)); |
+ emitFixup(F); |
+ emitInst(Placeholder); |
+} |
+ |
void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type, |
uint32_t Opcode, bool SetCc, uint32_t Rn, |
uint32_t Rd, uint32_t Imm12) { |
@@ -261,54 +274,48 @@ void ARM32::AssemblerARM32::emitMemOp(CondARM32::Cond Cond, uint32_t InstType, |
void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |
- // Note: Loop is used so that we can short circuit using break; |
- do { |
- uint32_t Rd; |
- if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
- break; |
- uint32_t Rn; |
- if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
- break; |
- constexpr uint32_t Add = B2; // 0100 |
- uint32_t Src1Value; |
- // TODO(kschimpf) Other possible decodings of add. |
- switch (decodeOperand(OpSrc1, Src1Value)) { |
- default: |
- break; |
- case DecodedAsRegister: { |
- // ADD (register) - ARM section A8.8.7, encoding A1: |
- // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
- // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
- // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
- // |
- // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags |
- Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
- if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
- // Conditions of rule violated. |
- break; |
- constexpr uint32_t InstTypeRegister = 0; |
- emitType01(Cond, InstTypeRegister, Add, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- case DecodedAsRotatedImm8: { |
- // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
- // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
- // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
- // add{s}<c> <Rd>, sp, #<RotatedImm8> |
- // |
- // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. |
- if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
- // Conditions of rule violated. |
- break; |
- constexpr uint32_t InstTypeImmediate = 1; |
- emitType01(Cond, InstTypeImmediate, Add, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- } |
- } while (0); |
- UnimplementedError(Ctx->getFlags()); |
+ uint32_t Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ uint32_t Rn; |
+ if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ constexpr uint32_t Add = B2; // 0100 |
+ uint32_t Src1Value; |
+ // TODO(kschimpf) Other possible decodings of add. |
+ switch (decodeOperand(OpSrc1, Src1Value)) { |
+ default: |
+ return setNeedsTextFixup(); |
+ case DecodedAsRegister: { |
+ // ADD (register) - ARM section A8.8.7, encoding A1: |
+ // add{s}<c> <Rd>, <Rn>, <Rm>{, <shiff>} |
+ // ADD (Sp plus register) - ARM section A8.8.11, encoding A1: |
+ // add{s}<c> sp, <Rn>, <Rm>{, <shiff>} |
+ // |
+ // cccc0000100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags |
+ Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
+ if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ emitType01(Cond, kInstTypeDataRegister, Add, SetFlags, Rn, Rd, Src1Value); |
+ return; |
+ } |
+ case DecodedAsRotatedImm8: { |
+ // ADD (Immediate) - ARM section A8.8.5, encoding A1: |
+ // add{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
+ // ADD (SP plus immediate) - ARM section A8.8.9, encoding A1. |
+ // add{s}<c> <Rd>, sp, #<RotatedImm8> |
+ // |
+ // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8. |
+ if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ emitType01(Cond, kInstTypeDataImmediate, Add, SetFlags, Rn, Rd, Src1Value); |
+ return; |
+ } |
+ }; |
} |
void ARM32::AssemblerARM32::bkpt(uint16_t Imm16) { |
@@ -327,11 +334,8 @@ void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
// bx<c> <Rm> |
// |
// cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond. |
- assert(isGPRRegisterDefined(Rm)); |
- // TODO(kschimpf): Remove void cast when MINIMAL build allows. |
- (void)isGPRRegisterDefined(Rm); |
- assert(isConditionDefined(Cond)); |
- (void)isConditionDefined(Cond); |
+ if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond))) |
+ return setNeedsTextFixup(); |
AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
const uint32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | |
B21 | (0xfff << 8) | B4 | |
@@ -341,169 +345,145 @@ void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
void ARM32::AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
CondARM32::Cond Cond) { |
- // Note: Loop is used so that we can short ciruit using break; |
- do { |
- uint32_t Rt; |
- if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
- break; |
- uint32_t Address; |
- if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
- break; |
- // 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 |
- // 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 STRB, u=1 if +. |
- constexpr uint32_t InstType = B1; // 010 |
- constexpr bool IsLoad = true; |
- const Type Ty = OpRt->getType(); |
- if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
- break; |
- const bool IsByte = typeWidthInBytes(Ty) == 1; |
- if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
- (!isBitSet(P, Address) && isBitSet(W, Address)) || |
- (!IsByte && |
- (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
- !isBitSet(P, Address) && |
- isBitSet(U, Address) & !isBitSet(W, Address) && |
- (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
- break; |
- emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
- return; |
- } while (0); |
- UnimplementedError(Ctx->getFlags()); |
+ uint32_t Rt; |
+ if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ uint32_t Address; |
+ if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
+ return setNeedsTextFixup(); |
+ // 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 |
+ // 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 STRB, u=1 if +. |
+ constexpr bool IsLoad = true; |
+ const Type Ty = OpRt->getType(); |
+ if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
+ return setNeedsTextFixup(); |
+ const bool IsByte = typeWidthInBytes(Ty) == 1; |
+ // Check conditions of rules violated. |
+ 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 */)) |
+ return setNeedsTextFixup(); |
+ emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
} |
void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
CondARM32::Cond Cond) { |
- // Note: Loop is used so that we can short ciruit using break; |
- do { |
- uint32_t Rd; |
- if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
- break; |
- uint32_t Src; |
- // TODO(kschimpf) Handle other forms of mov. |
- if (decodeOperand(OpSrc, Src) == DecodedAsRotatedImm8) { |
- // MOV (immediate) - ARM section A8.8.102, encoding A1: |
- // mov{S}<c> <Rd>, #<RotatedImm8> |
- // |
- // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
- // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
- // assembler. |
- constexpr bool SetFlags = false; |
- if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
- // Conditions of rule violated. |
- break; |
- constexpr uint32_t Rn = 0; |
- constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
- constexpr uint32_t InstType = 1; |
- emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src); |
- return; |
- } |
- } while (0); |
- UnimplementedError(Ctx->getFlags()); |
+ uint32_t Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ uint32_t Src; |
+ // TODO(kschimpf) Handle other forms of mov. |
+ if (decodeOperand(OpSrc, Src) != DecodedAsRotatedImm8) |
+ return setNeedsTextFixup(); |
+ // MOV (immediate) - ARM section A8.8.102, encoding A1: |
+ // mov{S}<c> <Rd>, #<RotatedImm8> |
+ // |
+ // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
+ // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
+ // assembler. |
+ constexpr bool SetFlags = false; |
+ if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ constexpr uint32_t Rn = 0; |
+ constexpr uint32_t Mov = B3 | B2 | B0; // 1101. |
+ emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
} |
void ARM32::AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
CondARM32::Cond Cond) { |
- // Note: Loop is used so that we can short ciruit using break; |
- do { |
- uint32_t Rt; |
- if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
- break; |
- uint32_t Address; |
- if (decodeAddress(OpAddress, Address) != DecodedAsImmRegOffset) |
- break; |
- // 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 uint32_t InstType = B1; // 010 |
- constexpr bool IsLoad = false; |
- const Type Ty = OpRt->getType(); |
- if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? |
- break; |
- const bool IsByte = typeWidthInBytes(Ty) == 1; |
- // Check for rule violations. |
- if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) || |
- (!isBitSet(P, Address) && isBitSet(W, Address)) || |
- (!IsByte && |
- (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_sp) && |
- isBitSet(P, Address) && !isBitSet(U, Address) && |
- isBitSet(W, Address) && |
- (mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))) |
- // Conditions of rule violated. |
- break; |
- emitMemOp(Cond, InstType, IsLoad, IsByte, Rt, Address); |
- return; |
- } while (0); |
- UnimplementedError(Ctx->getFlags()); |
+ uint32_t Rt; |
+ if (decodeOperand(OpRt, Rt) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ uint32_t Address; |
+ if (decodeAddress(OpAddress, Address) != 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 = typeWidthInBytes(Ty) == 1; |
+ // 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 */)) |
+ return setNeedsTextFixup(); |
+ emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
} |
void ARM32::AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |
- // Note: Loop is used so that we can short circuit using break; |
- do { |
- uint32_t Rd; |
- if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
- break; |
- uint32_t Rn; |
- if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
- break; |
- constexpr uint32_t Sub = B1; // 0010 |
- uint32_t Src1Value; |
- // TODO(kschimpf) Other possible decodings of sub. |
- switch (decodeOperand(OpSrc1, Src1Value)) { |
- default: |
- break; |
- case DecodedAsRegister: { |
- // SUB (register) - ARM section A8.8.223, encoding A1: |
- // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
- // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
- // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
- // |
- // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
- Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
- constexpr uint32_t InstType = 0; // i.e. register |
- if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
- // Conditions of rule violated. |
- break; |
- emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- case DecodedAsRotatedImm8: { |
- // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
- // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
- // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
- // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
- // |
- // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 |
- if (Rd == RegARM32::Encoded_Reg_pc) |
- // Conditions of rule violated. |
- break; |
- constexpr uint32_t InstType = 1; |
- emitType01(Cond, InstType, Sub, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- } |
- } while (0); |
- UnimplementedError(Ctx->getFlags()); |
+ uint32_t Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ uint32_t Rn; |
+ if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ constexpr uint32_t Sub = B1; // 0010 |
+ uint32_t Src1Value; |
+ // TODO(kschimpf) Other possible decodings of sub. |
+ switch (decodeOperand(OpSrc1, Src1Value)) { |
+ default: |
+ return setNeedsTextFixup(); |
+ case DecodedAsRegister: { |
+ // SUB (register) - ARM section A8.8.223, encoding A1: |
+ // sub{s}<c> <Rd>, <Rn>, <Rm>{, <shift>} |
+ // SUB (SP minus register): See ARM section 8.8.226, encoding A1: |
+ // sub{s}<c> <Rd>, sp, <Rm>{, <Shift>} |
+ // |
+ // cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags. |
+ Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0); |
+ if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ emitType01(Cond, kInstTypeDataRegister, Sub, SetFlags, Rn, Rd, Src1Value); |
+ return; |
+ } |
+ case DecodedAsRotatedImm8: { |
+ // Sub (Immediate) - ARM section A8.8.222, encoding A1: |
+ // sub{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
+ // Sub (Sp minus immediate) - ARM section A8.*.225, encoding A1: |
+ // sub{s}<c> sp, <Rn>, #<RotatedImm8> |
+ // |
+ // cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8 |
+ if (Rd == RegARM32::Encoded_Reg_pc) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ emitType01(Cond, kInstTypeDataImmediate, Sub, SetFlags, Rn, Rd, Src1Value); |
+ return; |
+ } |
+ } |
} |
} // end of namespace Ice |