Commit db098880 by Karl Schimpf

Add ADC (immediate) instruction to ARM integrated assembler.

parent 137e62bd
......@@ -225,16 +225,17 @@ void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) {
void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SUB, 1, rn, rd, o);
}
#endif
// Moved to ARM32::AssemberARM32::adc()
void Assembler::adc(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADC, 0, rn, rd, o);
}
// Moved to ARM32::AssemberARM32::adc()
void Assembler::adcs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADC, 1, rn, rd, o);
}
#endif
void Assembler::sbc(Register rd, Register rn, Operand o, Condition cond) {
......
......@@ -457,11 +457,12 @@ class Assembler : public ValueObject {
void add(Register rd, Register rn, Operand o, Condition cond = AL);
void adds(Register rd, Register rn, Operand o, Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::adc()
void adc(Register rd, Register rn, Operand o, Condition cond = AL);
void adcs(Register rd, Register rn, Operand o, Condition cond = AL);
#endif
void sbc(Register rd, Register rn, Operand o, Condition cond = AL);
......
......@@ -297,10 +297,8 @@ void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) {
void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type,
IValueT Opcode, bool SetCc, IValueT Rn,
IValueT Rd, IValueT Imm12) {
assert(isGPRRegisterDefined(Rd));
// TODO(kschimpf): Remove void cast when MINIMAL build allows.
(void)isGPRRegisterDefined(Rd);
assert(Cond != CondARM32::kNone);
if (!isGPRRegisterDefined(Rd) || !isConditionDefined(Cond))
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
(Type << kTypeShift) | (Opcode << kOpcodeShift) |
......@@ -340,8 +338,8 @@ void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
bool IsLoad, bool IsByte, IValueT Rt,
IValueT Address) {
assert(isGPRRegisterDefined(Rt));
assert(Cond != CondARM32::kNone);
if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
(InstType << kTypeShift) | (IsLoad ? L : 0) |
......@@ -349,6 +347,36 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
emitInst(Encoding);
}
void AssemblerARM32::adc(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();
constexpr IValueT Adc = B2 | B0; // 0101
IValueT Src1Value;
// TODO(kschimpf) Other possible decodings of adc.
switch (decodeOperand(OpSrc1, Src1Value)) {
default:
return setNeedsTextFixup();
case DecodedAsRotatedImm8: {
// ADC (Immediated) = ARM section A8.8.1, encoding A1:
// adc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
//
// cccc0010101snnnnddddiiiiiiiiiiii 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, Adc, SetFlags, Rn, Rd, Src1Value);
return;
}
};
}
void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
......
......@@ -124,6 +124,9 @@ public:
// List of instructions implemented by integrated assembler.
void adc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
......
......@@ -345,6 +345,14 @@ void InstARM32ThreeAddrGPR<K>::emitIAS(const Cfg *Func) const {
}
template <>
void InstARM32ThreeAddrGPR<InstARM32::Adc>::emitIAS(const Cfg *Func) const {
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->adc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
template <>
void InstARM32ThreeAddrGPR<InstARM32::Add>::emitIAS(const Cfg *Func) const {
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->add(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
......
......@@ -71,3 +71,28 @@ define internal i32 @Add2Regs(i32 %p1, i32 %p2) {
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
define internal i64 @addI64ToR0R1(i64 %p) {
%v = add i64 %p, 1
ret i64 %v
}
; ASM-LABEL:addI64ToR0R1:
; ASM-NEXT:.LaddI64ToR0R1$__0:
; ASM-NEXT: adds r0, r0, #1
; ASM-NEXT: adc r1, r1, #0
; DIS-LABEL:00000020 <addI64ToR0R1>:
; DIS-NEXT: 20: e2900001
; DIS-NEXT: 24: e2a11000
; IASM-LABEL:addI64ToR0R1:
; IASM-NEXT:.LaddI64ToR0R1$__0:
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x90
; IASM-NEXT: .byte 0xe2
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xa1
; IASM-NEXT: .byte 0xe2
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