Commit c411dbf1 by Karl Schimpf

Refactor PUSH/POP in ARM assemblers.

Refactors methods emit() and emitIAS() of InstARM32Push and InstARM32Pop to separate out the selection of assembler instructions from instruction emission, using template methods. Template method assemble() provides a single implementation for emit() and emitIAS(). This method calls template functions in the assembler to generate textual and binary forms of the instruction. BUG= None R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1535233002 .
parent d8777b0d
......@@ -192,7 +192,7 @@ IValueT getEncodedGPRegNum(const Variable *Var) {
assert(Var->hasReg());
int32_t Reg = Var->getRegNum();
return llvm::isa<Variable64On32>(Var) ? RegARM32::getI64PairFirstGPRNum(Reg)
: RegARM32::getEncodedGPReg(Reg);
: RegARM32::getEncodedGPR(Reg);
}
IValueT getEncodedSRegNum(const Variable *Var) {
......@@ -1728,7 +1728,7 @@ void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
OrrName);
}
void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) {
void AssemblerARM32::pop(const Variable *OpRt, CondARM32::Cond Cond) {
// POP - ARM section A8.8.132, encoding A2:
// pop<c> {Rt}
//
......
......@@ -38,12 +38,6 @@
namespace Ice {
namespace ARM32 {
/// Encoding of an ARM 32-bit instruction.
using IValueT = uint32_t;
/// An Offset value (+/-) used in an ARM 32-bit instruction.
using IOffsetT = int32_t;
/// Handles encoding of bottom/top 16 bits of an address using movw/movt.
class MoveRelocatableFixup final : public AssemblerFixup {
MoveRelocatableFixup &operator=(const MoveRelocatableFixup &) = delete;
......@@ -255,7 +249,7 @@ public:
void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void pop(const Operand *OpRt, CondARM32::Cond Cond);
void pop(const Variable *OpRt, CondARM32::Cond Cond);
// Note: Registers is a bitset, where bit n corresponds to register Rn.
void popList(const IValueT Registers, CondARM32::Cond Cond);
......
......@@ -27,6 +27,12 @@
namespace Ice {
namespace ARM32 {
/// Encoding of an ARM 32-bit instruction.
using IValueT = uint32_t;
/// An Offset value (+/-) used in an ARM 32-bit instruction.
using IOffsetT = int32_t;
class TargetARM32;
/// OperandARM32 extends the Operand hierarchy. Its subclasses are
......@@ -364,6 +370,9 @@ class InstARM32 : public InstTarget {
InstARM32 &operator=(const InstARM32 &) = delete;
public:
// Defines form that assembly instruction should be synthesized.
enum EmitForm { Emit_Text, Emit_Binary };
enum InstKindARM32 {
k__Start = Inst::Target,
Adc,
......@@ -1056,9 +1065,41 @@ private:
InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
};
class InstARM32RegisterStackOp : public InstARM32 {
InstARM32RegisterStackOp() = delete;
InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
InstARM32RegisterStackOp &
operator=(const InstARM32RegisterStackOp &) = delete;
public:
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
protected:
InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
Variable *Dest)
: InstARM32(Func, Kind, Maxsrcs, Dest) {}
void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
void emitGPRsAsText(const Cfg *Func) const;
void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
SizeT Regcount) const;
virtual const char *getDumpOpcode() const { return getGPROpcode(); }
virtual const char *getGPROpcode() const = 0;
virtual const char *getSRegOpcode() const = 0;
virtual Variable *getStackReg(SizeT Index) const = 0;
virtual SizeT getNumStackRegs() const = 0;
virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
const Variable *Reg) const = 0;
virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
IValueT Registers) const = 0;
virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
const Variable *BaseReg, SizeT RegCount) const = 0;
};
/// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
/// regs, but not both. In any case, the list must be sorted.
class InstARM32Pop : public InstARM32 {
class InstARM32Pop : public InstARM32RegisterStackOp {
InstARM32Pop() = delete;
InstARM32Pop(const InstARM32Pop &) = delete;
InstARM32Pop &operator=(const InstARM32Pop &) = delete;
......@@ -1067,20 +1108,27 @@ public:
static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Pop); }
private:
InstARM32Pop(Cfg *Func, const VarList &Dests);
virtual const char *getGPROpcode() const final;
virtual const char *getSRegOpcode() const final;
Variable *getStackReg(SizeT Index) const final;
SizeT getNumStackRegs() const final;
void emitSingleGPR(const Cfg *Func, const EmitForm Form,
const Variable *Reg) const final;
void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
IValueT Registers) const final;
void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
SizeT RegCount) const final;
VarList Dests;
};
/// Pushes a list of registers. Just like Pop (see above), the list may be of
/// GPRs, or VFP "s" registers, but not both.
class InstARM32Push : public InstARM32 {
class InstARM32Push : public InstARM32RegisterStackOp {
InstARM32Push() = delete;
InstARM32Push(const InstARM32Push &) = delete;
InstARM32Push &operator=(const InstARM32Push &) = delete;
......@@ -1089,13 +1137,20 @@ public:
static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Push); }
private:
InstARM32Push(Cfg *Func, const VarList &Srcs);
const char *getGPROpcode() const final;
const char *getSRegOpcode() const final;
Variable *getStackReg(SizeT Index) const final;
SizeT getNumStackRegs() const final;
void emitSingleGPR(const Cfg *Func, const EmitForm Form,
const Variable *Reg) const final;
void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
IValueT Registers) const final;
void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
SizeT RegCount) const final;
};
/// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
......
......@@ -157,7 +157,7 @@ public:
return Table[RegNum].IsGPR;
}
static constexpr inline SizeT getNumGPRegs() {
static constexpr SizeT getNumGPRegs() {
return 0
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
......@@ -167,11 +167,31 @@ public:
;
}
static inline GPRRegister getEncodedGPReg(int32_t RegNum) {
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(isGPRegister(RegNum));
return GPRRegister(Table[RegNum].Encoding);
}
static constexpr SizeT getNumGPRs() {
return 0
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
+(isGPR)
REGARM32_TABLE
#undef X
;
}
static inline bool isGPR(SizeT RegNum) {
assertRegisterDefined(RegNum);
return Table[RegNum].IsGPR;
}
static inline IceString getGPRName(SizeT RegNum) {
assert(isGPR(RegNum));
return Table[RegNum].Name;
}
static inline GPRRegister getI64PairFirstGPRNum(int32_t RegNum) {
assert(isI64RegisterPair(RegNum));
return GPRRegister(Table[RegNum].Encoding);
......@@ -192,7 +212,7 @@ public:
return Table[RegNum].IsFP32;
}
static constexpr inline SizeT getNumSRegs() {
static constexpr SizeT getNumSRegs() {
return 0
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
......@@ -202,6 +222,11 @@ public:
;
}
static inline IceString getSRegName(SizeT RegNum) {
assert(isEncodedSReg(RegNum));
return Table[RegNum].Name;
}
static inline SRegister getEncodedSReg(int32_t RegNum) {
assert(isEncodedSReg(RegNum));
return SRegister(Table[RegNum].Encoding);
......
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