Commit b81b9015 by Karl Schimpf

Add TST(register, immediate) to ARM32 integrated assembler.

Also cleans up instructions that use emitType01 to share more common code. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1413473005 .
parent 69e9290c
...@@ -255,11 +255,12 @@ void Assembler::rsc(Register rd, Register rn, Operand o, Condition cond) { ...@@ -255,11 +255,12 @@ void Assembler::rsc(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), RSC, 0, rn, rd, o); EmitType01(cond, o.type(), RSC, 0, rn, rd, o);
} }
#if 0
// Moved to ARM32::AssemblerARM32::tst()
void Assembler::tst(Register rn, Operand o, Condition cond) { void Assembler::tst(Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), TST, 1, rn, R0, o); EmitType01(cond, o.type(), TST, 1, rn, R0, o);
} }
#endif
void Assembler::teq(Register rn, Operand o, Condition cond) { void Assembler::teq(Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), TEQ, 1, rn, R0, o); EmitType01(cond, o.type(), TEQ, 1, rn, R0, o);
......
...@@ -480,7 +480,10 @@ class Assembler : public ValueObject { ...@@ -480,7 +480,10 @@ class Assembler : public ValueObject {
void rsc(Register rd, Register rn, Operand o, Condition cond = AL); void rsc(Register rd, Register rn, Operand o, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::tst();
void tst(Register rn, Operand o, Condition cond = AL); void tst(Register rn, Operand o, Condition cond = AL);
#endif
void teq(Register rn, Operand o, Condition cond = AL); void teq(Register rn, Operand o, Condition cond = AL);
......
...@@ -382,15 +382,33 @@ void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type, ...@@ -382,15 +382,33 @@ void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type,
void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd,
const Operand *OpRn, const Operand *OpSrc1, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond) { bool SetFlags, CondARM32::Cond Cond,
Type01Checks RuleChecks) {
IValueT Rd; IValueT Rd;
if (decodeOperand(OpRd, Rd) != DecodedAsRegister) if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup(); return setNeedsTextFixup();
IValueT Rn; IValueT Rn;
if (decodeOperand(OpRn, Rn) != DecodedAsRegister) if (decodeOperand(OpRn, Rn) != DecodedAsRegister)
return setNeedsTextFixup(); 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; IValueT Src1Value;
// TODO(kschimpf) Other possible decodings of add. // TODO(kschimpf) Other possible decodings of data operations.
switch (decodeOperand(OpSrc1, Src1Value)) { switch (decodeOperand(OpSrc1, Src1Value)) {
default: default:
return setNeedsTextFixup(); return setNeedsTextFixup();
...@@ -402,22 +420,25 @@ void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd, ...@@ -402,22 +420,25 @@ void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd,
// mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags. // mmmm=Rm, iiiii=Shift, tt=ShiftKind, and s=SetFlags.
constexpr IValueT Imm5 = 0; constexpr IValueT Imm5 = 0;
Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5); 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, emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd,
Src1Value); Src1Value);
return; 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: { case DecodedAsRotatedImm8: {
// XXX (Immediate) // XXX (Immediate)
// xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8> // xxx{s}<c> <Rd>, <Rn>, #<RotatedImm8>
// //
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. // 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, emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd,
Src1Value); Src1Value);
return; return;
...@@ -453,6 +474,29 @@ void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) { ...@@ -453,6 +474,29 @@ void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
L->linkTo(Position); 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, void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
bool IsLoad, bool IsByte, IValueT Rt, bool IsLoad, bool IsByte, IValueT Rt,
IValueT Address) { IValueT Address) {
...@@ -599,48 +643,19 @@ void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) { ...@@ -599,48 +643,19 @@ void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1, void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1,
CondARM32::Cond Cond) { 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 (register) - ARM section A8.8.38, encoding A1:
// cmp<c> <Rn>, <Rm>{, <shift>} // cmp<c> <Rn>, <Rm>{, <shift>}
// //
// cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, // cccc00010101nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
// iiiii=Shift, and tt=ShiftKind. // 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 (immediate) - ARM section A8.8.37
// cmp<c: <Rn>, #<RotatedImm8> // cmp<c: <Rn>, #<RotatedImm8>
// //
// cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, // cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
emitType01(Cond, kInstTypeDataImmediate, Cmp, SetFlags, Rn, Rd, Src1Value); constexpr IValueT Opcode = B3 | B1; // ie. 1010
return; emitCompareOp(Opcode, OpRn, OpSrc1, Cond);
}
}
setNeedsTextFixup();
} }
void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn, void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn,
...@@ -699,43 +714,25 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, ...@@ -699,43 +714,25 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
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 (register) - ARM section A8.8.104, encoding A1:
// mov{S}<c> <Rd>, <Rn> // mov{S}<c> <Rd>, <Rn>
// //
// cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, // cccc0001101s0000dddd00000000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// and nnnn=Rn. // 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 (immediate) - ARM section A8.8.102, encoding A1:
// mov{S}<c> <Rd>, #<RotatedImm8> // mov{S}<c> <Rd>, #<RotatedImm8>
// //
// cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd,
// and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this
// assembler. // assembler.
if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) IValueT Rd;
// Conditions of rule violated. if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup(); return setNeedsTextFixup();
emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); constexpr bool SetFlags = false;
return; constexpr IValueT Rn = 0;
} constexpr IValueT Mov = B3 | B2 | B0; // 1101.
} emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond);
} }
void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
...@@ -746,7 +743,7 @@ 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); auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc);
if (Src == nullptr) if (Src == nullptr)
return setNeedsTextFixup(); return setNeedsTextFixup();
// MOV (immediate) - ARM section A8.8.102, encoding A2: // MOVW (immediate) - ARM section A8.8.102, encoding A2:
// movw<c> <Rd>, #<imm16> // movw<c> <Rd>, #<imm16>
// //
// cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
...@@ -875,45 +872,19 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, ...@@ -875,45 +872,19 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn, void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags, const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
IValueT Rd;
if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup();
IValueT Rn;
if (decodeOperand(OpRn, Rn) != DecodedAsRegister)
return setNeedsTextFixup();
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 (register) - ARM Section A8.8.123, encoding A1:
// orr{s}<c> <Rd>, <Rn>, <Rm> // orr{s}<c> <Rd>, <Rn>, <Rm>
// //
// cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn, // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags. // 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 (register) - ARM Section A8.8.123, encoding A1:
// orr{s}<c> <Rd>, <Rn>, #<RotatedImm8> // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8>
// //
// cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn, // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8. // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
if (Rd == RegARM32::Encoded_Reg_pc && SetFlags) constexpr IValueT Orr = B3 | B2; // i.e. 1100
// Conditions of rule violated. emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond);
return setNeedsTextFixup();
emitType01(Cond, kInstTypeDataImmediate, Orr, SetFlags, Rn, Rd, Src1Value);
return;
}
}
} }
void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
...@@ -987,5 +958,22 @@ void AssemblerARM32::sub(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); 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 ARM32
} // end of namespace Ice } // end of namespace Ice
...@@ -168,13 +168,13 @@ public: ...@@ -168,13 +168,13 @@ public:
void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond); bool SetFlags, CondARM32::Cond Cond);
...@@ -189,6 +189,8 @@ public: ...@@ -189,6 +189,8 @@ public:
void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond); bool SetFlags, CondARM32::Cond Cond);
void tst(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
CondARM32::Cond Cond); CondARM32::Cond Cond);
...@@ -216,10 +218,23 @@ private: ...@@ -216,10 +218,23 @@ private:
void emitType01(CondARM32::Cond Cond, IValueT Type, IValueT Opcode, void emitType01(CondARM32::Cond Cond, IValueT Type, IValueT Opcode,
bool SetCc, IValueT Rn, IValueT Rd, IValueT imm12); bool SetCc, IValueT Rn, IValueT Rd, IValueT imm12);
// Converts arguments to appropriate representation on a data operation, // List of possible checks to apply when calling emitType01() (below).
// and then calls emitType01 above. enum Type01Checks {
NoChecks,
RdIsPcAndSetFlags,
};
// Converts appropriate representation on a data operation, and then calls
// emitType01 above.
void emitType01(IValueT Opcode, const Operand *OpRd, const Operand *OpRn, void emitType01(IValueT Opcode, const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags, CondARM32::Cond Cond); const Operand *OpSrc1, bool SetFlags, CondARM32::Cond Cond,
Type01Checks RuleChecks = RdIsPcAndSetFlags);
// Same as above, but the value for Rd and Rn have already been converted
// into instruction values.
void emitType01(IValueT Opcode, IValueT OpRd, IValueT OpRn,
const Operand *OpSrc1, bool SetFlags, CondARM32::Cond Cond,
Type01Checks RuleChecks = RdIsPcAndSetFlags);
void emitType05(CondARM32::Cond COnd, int32_t Offset, bool Link); void emitType05(CondARM32::Cond COnd, int32_t Offset, bool Link);
...@@ -240,6 +255,12 @@ private: ...@@ -240,6 +255,12 @@ private:
void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn, void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
IValueT Rm, IValueT Rs, bool SetCc); IValueT Rm, IValueT Rs, bool SetCc);
// Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn,
// ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from
// OpSrc1, and xxxx=Opcode.
void emitCompareOp(IValueT Opcode, const Operand *OpRn, const Operand *OpSrc1,
CondARM32::Cond Cond);
void emitBranch(Label *L, CondARM32::Cond, bool Link); void emitBranch(Label *L, CondARM32::Cond, bool Link);
// Encodes the given Offset into the branch instruction Inst. // Encodes the given Offset into the branch instruction Inst.
......
...@@ -527,6 +527,14 @@ template <> void InstARM32Cmp::emitIAS(const Cfg *Func) const { ...@@ -527,6 +527,14 @@ template <> void InstARM32Cmp::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func); emitUsingTextFixup(Func);
} }
template <> void InstARM32Tst::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 2);
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->tst(getSrc(0), getSrc(1), getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1,
CondARM32::Cond Predicate) CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
......
...@@ -81,9 +81,15 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) { ...@@ -81,9 +81,15 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) {
; IASM-NEXT: .byte 0x50 ; IASM-NEXT: .byte 0x50
; IASM-NEXT: .byte 0xe1 ; IASM-NEXT: .byte 0xe1
; IASM-NEXT: movge r0, #0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xa3
; IASM-NEXT: movlt r0, #1 ; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xb3
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
......
...@@ -44,17 +44,24 @@ define internal i32 @SdivTwoRegs(i32 %a, i32 %b) { ...@@ -44,17 +44,24 @@ define internal i32 @SdivTwoRegs(i32 %a, i32 %b) {
; IASM-LABEL:SdivTwoRegs: ; IASM-LABEL:SdivTwoRegs:
; IASM-NEXT:.LSdivTwoRegs$__0: ; IASM-NEXT:.LSdivTwoRegs$__0:
; IASM-NEXT: tst r1, r1
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x11
; IASM-NEXT: .byte 0xe1
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a ; IASM-NEXT: .byte 0x1a
; IASM-NEXT: .long 0xe7fedef0 ; IASM-NEXT: .long 0xe7fedef0
; IASM-NEXT:.LSdivTwoRegs$local$__0: ; IASM-NEXT:.LSdivTwoRegs$local$__0:
; IASM-NEXT: .byte 0x10 ; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xf1 ; IASM-NEXT: .byte 0xf1
; IASM-NEXT: .byte 0x10 ; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xe7 ; IASM-NEXT: .byte 0xe7
; IASM-NEXT: .byte 0x1e ; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff ; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f ; IASM-NEXT: .byte 0x2f
......
...@@ -44,17 +44,24 @@ define internal i32 @UdivTwoRegs(i32 %a, i32 %b) { ...@@ -44,17 +44,24 @@ define internal i32 @UdivTwoRegs(i32 %a, i32 %b) {
; IASM-LABEL:UdivTwoRegs: ; IASM-LABEL:UdivTwoRegs:
; IASM-NEXT:.LUdivTwoRegs$__0: ; IASM-NEXT:.LUdivTwoRegs$__0:
; IASM-NEXT: tst r1, r1
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x11
; IASM-NEXT: .byte 0xe1
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a ; IASM-NEXT: .byte 0x1a
; IASM-NEXT: .long 0xe7fedef0 ; IASM-NEXT: .long 0xe7fedef0
; IASM-NEXT:.LUdivTwoRegs$local$__0: ; IASM-NEXT:.LUdivTwoRegs$local$__0:
; IASM-NEXT: .byte 0x10 ; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xf1 ; IASM-NEXT: .byte 0xf1
; IASM-NEXT: .byte 0x30 ; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0xe7 ; IASM-NEXT: .byte 0xe7
; IASM-NEXT: .byte 0x1e ; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff ; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f ; IASM-NEXT: .byte 0x2f
......
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