Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index 1147f71898eb1a7d87d2546bbee21f83a04be2f4..135e1b94dfcac5b582661747841a413e2e76433e 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -382,15 +382,33 @@ void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type, |
void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, |
const Operand *OpRn, const Operand *OpSrc1, |
- bool SetFlags, CondARM32::Cond Cond) { |
+ bool SetFlags, CondARM32::Cond Cond, |
+ Type01Checks RuleChecks) { |
IValueT Rd; |
if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
return setNeedsTextFixup(); |
IValueT Rn; |
if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
return setNeedsTextFixup(); |
+ emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks); |
+} |
+ |
+void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, |
+ IValueT Rn, const Operand *OpSrc1, |
+ bool SetFlags, CondARM32::Cond Cond, |
+ Type01Checks RuleChecks) { |
+ switch (RuleChecks) { |
+ case NoChecks: |
+ break; |
+ case RdIsPcAndSetFlags: |
+ if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ break; |
+ } |
+ |
IValueT Src1Value; |
- // TODO(kschimpf) Other possible decodings of add. |
+ // TODO(kschimpf) Other possible decodings of data operations. |
switch (decodeOperand(OpSrc1, Src1Value)) { |
default: |
return setNeedsTextFixup(); |
@@ -402,22 +420,25 @@ void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, |
// mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. |
constexpr IValueT Imm5 = 0; |
Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); |
- if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, |
Src1Value); |
return; |
} |
+ case DecodedAsConstI32: { |
+ // See if we can convert this to an XXX (immediate). |
+ IValueT RotateAmt; |
+ IValueT Imm8; |
+ if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) |
+ return setNeedsTextFixup(); |
+ Src1Value = encodeRotatedImm8(RotateAmt, Imm8); |
+ // Intentionally fall to next case! |
+ } |
case DecodedAsRotatedImm8: { |
// XXX (Immediate) |
// xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
// |
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
- if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd, |
Src1Value); |
return; |
@@ -453,6 +474,29 @@ void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) { |
L->linkTo(Position); |
} |
+void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn, |
+ const Operand *OpSrc1, |
+ CondARM32::Cond Cond) { |
+ // XXX (register) |
+ // XXX<c> <Rn>, <Rm>{, <shift>} |
+ // |
+ // ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
+ // iiiii=Shift, tt=ShiftKind, yyy=kInstTypeDataRegister, and xxxx=Opcode. |
+ // |
+ // XXX (immediate) |
+ // XXX<c> <Rn>, #<RotatedImm8> |
+ // |
+ // ccccyyyxxxx1nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // yyy=kInstTypeDataImmdiate, xxxx=Opcode, and iiiiiiiiiiii=Src1Value |
+ // defining RotatedImm8. |
+ constexpr bool SetFlags = true; |
+ constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; |
+ IValueT Rn; |
+ if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, NoChecks); |
+} |
+ |
void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, |
bool IsLoad, bool IsByte, IValueT Rt, |
IValueT Address) { |
@@ -599,48 +643,19 @@ void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { |
void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1, |
CondARM32::Cond Cond) { |
- IValueT Rn; |
- if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
- return setNeedsTextFixup(); |
- constexpr IValueT Cmp = B3 | B1; // ie. 1010 |
- constexpr bool SetFlags = true; |
- constexpr IValueT Rd = RegARM32::Encoded_Reg_r0; |
- IValueT Src1Value; |
- // TODO(kschimpf) Other possible decodings of cmp. |
- switch (decodeOperand(OpSrc1, Src1Value)) { |
- default: |
- return setNeedsTextFixup(); |
- case DecodedAsRegister: { |
- // CMP (register) - ARM section A8.8.38, encoding A1: |
- // cmp<c> <Rn>, <Rm>{, <shift>} |
- // |
- // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
- // iiiii=Shift, and tt=ShiftKind. |
- constexpr IValueT Imm5 = 0; |
- Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); |
- emitType01(Cond, kInstTypeDataRegister, Cmp, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- case DecodedAsConstI32: { |
- // See if we can convert this to an CMP (immediate). |
- IValueT RotateAmt; |
- IValueT Imm8; |
- if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8)) |
- return setNeedsTextFixup(); |
- Src1Value = encodeRotatedImm8(RotateAmt, Imm8); |
- // Intentionally fall to next case! |
- } |
- case DecodedAsRotatedImm8: { |
- // CMP (immediate) - ARM section A8.8.37 |
- // cmp<c: <Rn>, #<RotatedImm8> |
- // |
- // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
- emitType01(Cond, kInstTypeDataImmediate, Cmp, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- } |
- setNeedsTextFixup(); |
+ // CMP (register) - ARM section A8.8.38, encoding A1: |
+ // cmp<c> <Rn>, <Rm>{, <shift>} |
+ // |
+ // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
+ // iiiii=Shift, and tt=ShiftKind. |
+ // |
+ // CMP (immediate) - ARM section A8.8.37 |
+ // cmp<c: <Rn>, #<RotatedImm8> |
+ // |
+ // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
+ constexpr IValueT Opcode = B3 | B1; // ie. 1010 |
+ emitCompareOp(Opcode, OpRn, OpSrc1, Cond); |
} |
void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn, |
@@ -699,43 +714,25 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, |
void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
CondARM32::Cond Cond) { |
+ // MOV (register) - ARM section A8.8.104, encoding A1: |
+ // mov{S}<c> <Rd>, <Rn> |
+ // |
+ // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
+ // and nnnn=Rn. |
+ // |
+ // 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. |
IValueT Rd; |
if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
return setNeedsTextFixup(); |
- IValueT Src; |
- // TODO(kschimpf) Handle other forms of mov. |
constexpr bool SetFlags = false; |
constexpr IValueT Rn = 0; |
constexpr IValueT Mov = B3 | B2 | B0; // 1101. |
- switch (decodeOperand(OpSrc, Src)) { |
- default: |
- return setNeedsTextFixup(); |
- case DecodedAsRegister: { |
- // MOV (register) - ARM section A8.8.104, encoding A1: |
- // mov{S}<c> <Rd>, <Rn> |
- // |
- // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, |
- // and nnnn=Rn. |
- if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
- emitType01(Cond, kInstTypeDataRegister, Mov, SetFlags, Rn, Rd, Src); |
- return; |
- } |
- case 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. |
- if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
- emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
- return; |
- } |
- } |
+ emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond); |
} |
void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, |
@@ -746,7 +743,7 @@ void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, |
auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); |
if (Src == nullptr) |
return setNeedsTextFixup(); |
- // MOV (immediate) - ARM section A8.8.102, encoding A2: |
+ // MOVW (immediate) - ARM section A8.8.102, encoding A2: |
// movw<c> <Rd>, #<imm16> |
// |
// cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
@@ -875,45 +872,19 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |
- IValueT Rd; |
- if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
- return setNeedsTextFixup(); |
- IValueT Rn; |
- if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
- return setNeedsTextFixup(); |
+ // ORR (register) - ARM Section A8.8.123, encoding A1: |
+ // orr{s}<c> <Rd>, <Rn>, <Rm> |
+ // |
+ // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
+ // |
+ // ORR (register) - ARM Section A8.8.123, encoding A1: |
+ // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
+ // |
+ // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
constexpr IValueT Orr = B3 | B2; // i.e. 1100 |
- IValueT Src1Value; |
- // TODO(kschimpf) Handle other possible decodings of orr. |
- switch (decodeOperand(OpSrc1, Src1Value)) { |
- default: |
- return setNeedsTextFixup(); |
- case DecodedAsRegister: { |
- // ORR (register) - ARM Section A8.8.123, encoding A1: |
- // orr{s}<c> <Rd>, <Rn>, <Rm> |
- // |
- // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. |
- constexpr IValueT Shift = 0; |
- Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Shift); |
- if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
- emitType01(Cond, kInstTypeDataRegister, Orr, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- case DecodedAsRotatedImm8: { |
- // ORR (register) - ARM Section A8.8.123, encoding A1: |
- // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> |
- // |
- // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, |
- // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. |
- if (Rd == RegARM32::Encoded_Reg_pc && SetFlags) |
- // Conditions of rule violated. |
- return setNeedsTextFixup(); |
- emitType01(Cond, kInstTypeDataImmediate, Orr, SetFlags, Rn, Rd, Src1Value); |
- return; |
- } |
- } |
+ emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond); |
} |
void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, |
@@ -987,5 +958,22 @@ void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
emitType01(Sub, OpRd, OpRn, OpSrc1, SetFlags, Cond); |
} |
+void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1, |
+ CondARM32::Cond Cond) { |
+ // TST (register) - ARM section A8.8.241, encoding A1: |
+ // tst<c> <Rn>, <Rm>(, <shift>} |
+ // |
+ // cccc00010001nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, |
+ // iiiii=Shift, and tt=ShiftKind. |
+ // |
+ // TST (immediate) - ARM section A8.8.240, encoding A1: |
+ // tst<c> <Rn>, #<RotatedImm8> |
+ // |
+ // cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and |
+ // iiiiiiiiiiii defines RotatedImm8. |
+ constexpr IValueT Opcode = B3; // ie. 1000 |
+ emitCompareOp(Opcode, OpRn, OpSrc1, Cond); |
+} |
+ |
} // end of namespace ARM32 |
} // end of namespace Ice |