407 lines
18 KiB
C++
407 lines
18 KiB
C++
/*
|
|
* Copyright (C) 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM32_H_
|
|
#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM32_H_
|
|
|
|
#include <vector>
|
|
|
|
#include "base/logging.h"
|
|
#include "constants_arm.h"
|
|
#include "utils/arm/managed_register_arm.h"
|
|
#include "utils/arm/assembler_arm.h"
|
|
#include "offsets.h"
|
|
|
|
namespace art {
|
|
namespace arm {
|
|
|
|
class Arm32Assembler FINAL : public ArmAssembler {
|
|
public:
|
|
explicit Arm32Assembler(ArenaAllocator* arena) : ArmAssembler(arena) {}
|
|
virtual ~Arm32Assembler() {}
|
|
|
|
bool IsThumb() const OVERRIDE {
|
|
return false;
|
|
}
|
|
|
|
// Data-processing instructions.
|
|
virtual void and_(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void eor(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void sub(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void rsb(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void add(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void adc(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void sbc(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void rsc(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
|
|
|
|
void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
|
|
|
|
void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
|
|
|
|
void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE;
|
|
|
|
virtual void orr(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void orn(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void mov(Register rd, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void bic(Register rd, Register rn, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void mvn(Register rd, const ShifterOperand& so,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
// Miscellaneous data-processing instructions.
|
|
void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
|
|
void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE;
|
|
void rbit(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
void rev(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
void rev16(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
void revsh(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
|
|
// Multiply instructions.
|
|
void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
|
|
void mla(Register rd, Register rn, Register rm, Register ra,
|
|
Condition cond = AL) OVERRIDE;
|
|
void mls(Register rd, Register rn, Register rm, Register ra,
|
|
Condition cond = AL) OVERRIDE;
|
|
void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
|
|
Condition cond = AL) OVERRIDE;
|
|
void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
|
|
Condition cond = AL) OVERRIDE;
|
|
|
|
void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
|
|
void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE;
|
|
|
|
// Bit field extract instructions.
|
|
void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
|
|
void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE;
|
|
|
|
// Load/store instructions.
|
|
void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldm(BlockAddressMode am, Register base,
|
|
RegList regs, Condition cond = AL) OVERRIDE;
|
|
void stm(BlockAddressMode am, Register base,
|
|
RegList regs, Condition cond = AL) OVERRIDE;
|
|
|
|
void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE;
|
|
void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE;
|
|
void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
|
|
void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE;
|
|
|
|
// Miscellaneous instructions.
|
|
void clrex(Condition cond = AL) OVERRIDE;
|
|
void nop(Condition cond = AL) OVERRIDE;
|
|
|
|
// Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
|
|
void bkpt(uint16_t imm16) OVERRIDE;
|
|
void svc(uint32_t imm24) OVERRIDE;
|
|
|
|
void cbz(Register rn, Label* target) OVERRIDE;
|
|
void cbnz(Register rn, Label* target) OVERRIDE;
|
|
|
|
// Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
|
|
void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE;
|
|
void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE;
|
|
void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
|
|
void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE;
|
|
void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
|
|
// Returns false if the immediate cannot be encoded.
|
|
bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE;
|
|
bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE;
|
|
|
|
void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE;
|
|
|
|
void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
|
|
void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
|
|
void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
|
|
void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE;
|
|
void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE;
|
|
void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE;
|
|
void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE;
|
|
void vmstat(Condition cond = AL) OVERRIDE; // VMRS APSR_nzcv, FPSCR
|
|
|
|
void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
|
|
void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
|
|
void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE;
|
|
void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE;
|
|
|
|
// Branch instructions.
|
|
void b(Label* label, Condition cond = AL) OVERRIDE;
|
|
void bl(Label* label, Condition cond = AL) OVERRIDE;
|
|
void blx(Register rm, Condition cond = AL) OVERRIDE;
|
|
void bx(Register rm, Condition cond = AL) OVERRIDE;
|
|
virtual void Lsl(Register rd, Register rm, uint32_t shift_imm,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Lsr(Register rd, Register rm, uint32_t shift_imm,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Asr(Register rd, Register rm, uint32_t shift_imm,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Ror(Register rd, Register rm, uint32_t shift_imm,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Rrx(Register rd, Register rm,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
virtual void Lsl(Register rd, Register rm, Register rn,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Lsr(Register rd, Register rm, Register rn,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Asr(Register rd, Register rm, Register rn,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
virtual void Ror(Register rd, Register rm, Register rn,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
void Push(Register rd, Condition cond = AL) OVERRIDE;
|
|
void Pop(Register rd, Condition cond = AL) OVERRIDE;
|
|
|
|
void PushList(RegList regs, Condition cond = AL) OVERRIDE;
|
|
void PopList(RegList regs, Condition cond = AL) OVERRIDE;
|
|
|
|
void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
|
|
|
|
void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE;
|
|
void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE;
|
|
|
|
// Memory barriers.
|
|
void dmb(DmbOptions flavor) OVERRIDE;
|
|
|
|
// Get the final position of a label after local fixup based on the old position
|
|
// recorded before FinalizeCode().
|
|
uint32_t GetAdjustedPosition(uint32_t old_position) OVERRIDE;
|
|
|
|
Literal* NewLiteral(size_t size, const uint8_t* data) OVERRIDE;
|
|
void LoadLiteral(Register rt, Literal* literal) OVERRIDE;
|
|
void LoadLiteral(Register rt, Register rt2, Literal* literal) OVERRIDE;
|
|
void LoadLiteral(SRegister sd, Literal* literal) OVERRIDE;
|
|
void LoadLiteral(DRegister dd, Literal* literal) OVERRIDE;
|
|
|
|
// Add signed constant value to rd. May clobber IP.
|
|
void AddConstant(Register rd, Register rn, int32_t value,
|
|
Condition cond = AL, SetCc set_cc = kCcDontCare) OVERRIDE;
|
|
|
|
void CmpConstant(Register rn, int32_t value, Condition cond = AL) OVERRIDE;
|
|
|
|
// Load and Store. May clobber IP.
|
|
void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE;
|
|
void MarkExceptionHandler(Label* label) OVERRIDE;
|
|
void LoadFromOffset(LoadOperandType type,
|
|
Register reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
void StoreToOffset(StoreOperandType type,
|
|
Register reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
void LoadSFromOffset(SRegister reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
void StoreSToOffset(SRegister reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
void LoadDFromOffset(DRegister reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
void StoreDToOffset(DRegister reg,
|
|
Register base,
|
|
int32_t offset,
|
|
Condition cond = AL) OVERRIDE;
|
|
|
|
bool ShifterOperandCanHold(Register rd,
|
|
Register rn,
|
|
Opcode opcode,
|
|
uint32_t immediate,
|
|
SetCc set_cc,
|
|
ShifterOperand* shifter_op) OVERRIDE;
|
|
using ArmAssembler::ShifterOperandCanHold; // Don't hide the non-virtual override.
|
|
|
|
bool ShifterOperandCanAlwaysHold(uint32_t immediate) OVERRIDE;
|
|
|
|
static bool IsInstructionForExceptionHandling(uintptr_t pc);
|
|
|
|
// Emit data (e.g. encoded instruction or immediate) to the
|
|
// instruction stream.
|
|
void Emit(int32_t value);
|
|
void Bind(Label* label) OVERRIDE;
|
|
|
|
void MemoryBarrier(ManagedRegister scratch) OVERRIDE;
|
|
|
|
JumpTable* CreateJumpTable(std::vector<Label*>&& labels, Register base_reg) OVERRIDE;
|
|
void EmitJumpTableDispatch(JumpTable* jump_table, Register displacement_reg) OVERRIDE;
|
|
|
|
void FinalizeCode() OVERRIDE;
|
|
|
|
private:
|
|
void EmitType01(Condition cond,
|
|
int type,
|
|
Opcode opcode,
|
|
SetCc set_cc,
|
|
Register rn,
|
|
Register rd,
|
|
const ShifterOperand& so);
|
|
|
|
void EmitType5(Condition cond, int offset, bool link);
|
|
|
|
void EmitMemOp(Condition cond,
|
|
bool load,
|
|
bool byte,
|
|
Register rd,
|
|
const Address& ad);
|
|
|
|
void EmitMemOpAddressMode3(Condition cond,
|
|
int32_t mode,
|
|
Register rd,
|
|
const Address& ad);
|
|
|
|
void EmitMultiMemOp(Condition cond,
|
|
BlockAddressMode am,
|
|
bool load,
|
|
Register base,
|
|
RegList regs);
|
|
|
|
void EmitShiftImmediate(Condition cond,
|
|
Shift opcode,
|
|
Register rd,
|
|
Register rm,
|
|
const ShifterOperand& so);
|
|
|
|
void EmitShiftRegister(Condition cond,
|
|
Shift opcode,
|
|
Register rd,
|
|
Register rm,
|
|
const ShifterOperand& so);
|
|
|
|
void EmitMulOp(Condition cond,
|
|
int32_t opcode,
|
|
Register rd,
|
|
Register rn,
|
|
Register rm,
|
|
Register rs);
|
|
|
|
void EmitVFPsss(Condition cond,
|
|
int32_t opcode,
|
|
SRegister sd,
|
|
SRegister sn,
|
|
SRegister sm);
|
|
|
|
void EmitVFPddd(Condition cond,
|
|
int32_t opcode,
|
|
DRegister dd,
|
|
DRegister dn,
|
|
DRegister dm);
|
|
|
|
void EmitVFPsd(Condition cond,
|
|
int32_t opcode,
|
|
SRegister sd,
|
|
DRegister dm);
|
|
|
|
void EmitVFPds(Condition cond,
|
|
int32_t opcode,
|
|
DRegister dd,
|
|
SRegister sm);
|
|
|
|
void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond);
|
|
|
|
void EmitMiscellaneous(Condition cond, uint8_t op1, uint8_t op2,
|
|
uint32_t a_part, uint32_t rest);
|
|
void EmitReverseBytes(Register rd, Register rm, Condition cond,
|
|
uint8_t op1, uint8_t op2);
|
|
|
|
void EmitBranch(Condition cond, Label* label, bool link);
|
|
static int32_t EncodeBranchOffset(int offset, int32_t inst);
|
|
static int DecodeBranchOffset(int32_t inst);
|
|
bool ShifterOperandCanHoldArm32(uint32_t immediate, ShifterOperand* shifter_op);
|
|
};
|
|
|
|
} // namespace arm
|
|
} // namespace art
|
|
|
|
#endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM32_H_
|