Support for cross compilation.
Refactor architecture specific files into arm and x86 name spaces. Make
assemblers and calling conventions use the factory pattern and an
instruction set specifier.
Change-Id: I20cd7aecacc1ae3d418221d98bbe1d69be9162a7
diff --git a/src/assembler_x86.h b/src/assembler_x86.h
index 372c61b..c893633 100644
--- a/src/assembler_x86.h
+++ b/src/assembler_x86.h
@@ -7,12 +7,13 @@
#include "assembler.h"
#include "constants.h"
#include "globals.h"
-#include "managed_register.h"
+#include "managed_register_x86.h"
#include "macros.h"
#include "offsets.h"
#include "utils.h"
namespace art {
+namespace x86 {
class Immediate {
public:
@@ -113,7 +114,7 @@
return encoding_[index];
}
- friend class Assembler;
+ friend class X86Assembler;
DISALLOW_COPY_AND_ASSIGN(Operand);
};
@@ -195,14 +196,10 @@
};
-class Assembler {
+class X86Assembler : public Assembler {
public:
- Assembler() : buffer_() {}
- ~Assembler() {}
-
- InstructionSet GetInstructionSet() const {
- return kX86;
- }
+ X86Assembler() {}
+ virtual ~X86Assembler() {}
/*
* Emit Machine Instructions.
@@ -407,100 +404,15 @@
void jmp(Register reg);
void jmp(Label* label);
- Assembler* lock();
+ X86Assembler* lock();
void cmpxchgl(const Address& address, Register reg);
- Assembler* fs();
+ X86Assembler* fs();
//
// Macros for High-level operations.
//
- // Emit code that will create an activation on the stack
- void BuildFrame(size_t frame_size, ManagedRegister method_reg,
- const std::vector<ManagedRegister>& spill_regs);
-
- // Emit code that will remove an activation from the stack
- void RemoveFrame(size_t frame_size,
- const std::vector<ManagedRegister>& spill_regs);
-
- // Fill registers from spill area - no-op on x86
- void FillFromSpillArea(const std::vector<ManagedRegister>& spill_regs,
- size_t displacement);
-
- void IncreaseFrameSize(size_t adjust);
- void DecreaseFrameSize(size_t adjust);
-
- // Store bytes from the given register onto the stack
- void Store(FrameOffset offs, ManagedRegister src, size_t size);
- void StoreRef(FrameOffset dest, ManagedRegister src);
- void StoreRawPtr(FrameOffset dest, ManagedRegister src);
- void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
- ManagedRegister scratch) {
- UNIMPLEMENTED(FATAL); // this case only currently exists for ARM
- }
-
- void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch);
-
- void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
- ManagedRegister scratch);
-
- void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
- ManagedRegister scratch);
-
- void Load(ManagedRegister dest, FrameOffset src, size_t size);
-
- void LoadRef(ManagedRegister dest, FrameOffset src);
-
- void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs);
-
- void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs);
-
- void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset offs);
-
- void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
- ManagedRegister scratch);
-
- void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
- ManagedRegister scratch);
-
- void StoreStackOffsetToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
- ManagedRegister scratch);
- void StoreStackPointerToThread(ThreadOffset thr_offs);
-
- void Move(ManagedRegister dest, ManagedRegister src);
-
- void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
- unsigned int size);
-
- void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
- ManagedRegister in_reg, bool null_allowed);
-
- void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
- ManagedRegister scratch, bool null_allowed);
-
- void LoadReferenceFromSirt(ManagedRegister dst, ManagedRegister src);
-
- void VerifyObject(ManagedRegister src, bool could_be_null);
- void VerifyObject(FrameOffset src, bool could_be_null);
-
- void Call(ManagedRegister base, Offset offset, ManagedRegister scratch);
- void Call(FrameOffset base, Offset offset, ManagedRegister scratch);
- void Call(uintptr_t addr, ManagedRegister scratch);
-
- void GetCurrentThread(ManagedRegister tr);
- void GetCurrentThread(FrameOffset offset, ManagedRegister scratch);
-
- // Generate code to check if Thread::Current()->suspend_count_ is non-zero
- // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
- // at the next instruction.
- void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
- FrameOffset return_save_location, size_t return_size);
-
- // Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(ManagedRegister scratch);
-
void AddImmediate(Register reg, const Immediate& imm);
void LoadDoubleConstant(XmmRegister dst, double value);
@@ -521,22 +433,124 @@
void Align(int alignment, int offset);
void Bind(Label* label);
- void EmitSlowPaths() { buffer_.EmitSlowPaths(this); }
-
- size_t CodeSize() const { return buffer_.Size(); }
-
- void FinalizeInstructions(const MemoryRegion& region) {
- buffer_.FinalizeInstructions(region);
- }
-
// Debugging and bringup support.
void Stop(const char* message);
static void InitializeMemoryWithBreakpoints(byte* data, size_t length);
- private:
- AssemblerBuffer buffer_;
+ //
+ // Overridden common assembler high-level functionality
+ //
+ // Emit code that will create an activation on the stack
+ virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
+ const std::vector<ManagedRegister>& spill_regs);
+
+ // Emit code that will remove an activation from the stack
+ virtual void RemoveFrame(size_t frame_size,
+ const std::vector<ManagedRegister>& spill_regs);
+
+ // Fill list of registers from spill area
+ virtual void FillFromSpillArea(const std::vector<ManagedRegister>& spill_regs,
+ size_t displacement);
+
+ virtual void IncreaseFrameSize(size_t adjust);
+ virtual void DecreaseFrameSize(size_t adjust);
+
+ // Store routines
+ virtual void Store(FrameOffset offs, ManagedRegister src, size_t size);
+ virtual void StoreRef(FrameOffset dest, ManagedRegister src);
+ virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src);
+
+ virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
+ ManagedRegister scratch);
+
+ virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
+ ManagedRegister scratch);
+
+ virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
+ FrameOffset fr_offs,
+ ManagedRegister scratch);
+
+ virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
+
+ virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
+ FrameOffset in_off, ManagedRegister scratch);
+
+ // Load routines
+ virtual void Load(ManagedRegister dest, FrameOffset src, size_t size);
+
+ virtual void LoadRef(ManagedRegister dest, FrameOffset src);
+
+ virtual void LoadRef(ManagedRegister dest, ManagedRegister base,
+ MemberOffset offs);
+
+ virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base,
+ Offset offs);
+
+ virtual void LoadRawPtrFromThread(ManagedRegister dest,
+ ThreadOffset offs);
+
+ // Copying routines
+ virtual void Move(ManagedRegister dest, ManagedRegister src);
+
+ virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
+ ManagedRegister scratch);
+
+ virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
+ ManagedRegister scratch);
+
+ virtual void CopyRef(FrameOffset dest, FrameOffset src,
+ ManagedRegister scratch);
+
+ virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch,
+ size_t size);
+
+ // Exploit fast access in managed code to Thread::Current()
+ virtual void GetCurrentThread(ManagedRegister tr);
+ virtual void GetCurrentThread(FrameOffset dest_offset,
+ ManagedRegister scratch);
+
+ // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
+ // value is null and null_allowed. in_reg holds a possibly stale reference
+ // that can be used to avoid loading the SIRT entry to see if the value is
+ // NULL.
+ virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
+ ManagedRegister in_reg, bool null_allowed);
+
+ // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
+ // value is null and null_allowed.
+ virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
+ ManagedRegister scratch, bool null_allowed);
+
+ // src holds a SIRT entry (Object**) load this into dst
+ virtual void LoadReferenceFromSirt(ManagedRegister dst,
+ ManagedRegister src);
+
+ // Heap::VerifyObject on src. In some cases (such as a reference to this) we
+ // know that src may not be null.
+ virtual void VerifyObject(ManagedRegister src, bool could_be_null);
+ virtual void VerifyObject(FrameOffset src, bool could_be_null);
+
+ // Call to address held at [base+offset]
+ virtual void Call(ManagedRegister base, Offset offset,
+ ManagedRegister scratch);
+ virtual void Call(FrameOffset base, Offset offset,
+ ManagedRegister scratch);
+ virtual void Call(uintptr_t addr, ManagedRegister scratch);
+
+ // Generate code to check if Thread::Current()->suspend_count_ is non-zero
+ // and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
+ // at the next instruction.
+ virtual void SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
+ FrameOffset return_save_location,
+ size_t return_size);
+
+ // Generate code to check if Thread::Current()->exception_ is non-null
+ // and branch to a ExceptionSlowPath if it is.
+ virtual void ExceptionPoll(ManagedRegister scratch);
+
+ private:
inline void EmitUint8(uint8_t value);
inline void EmitInt32(int32_t value);
inline void EmitRegisterOperand(int rm, int reg);
@@ -554,41 +568,60 @@
void EmitGenericShift(int rm, Register reg, const Immediate& imm);
void EmitGenericShift(int rm, Register operand, Register shifter);
- DISALLOW_COPY_AND_ASSIGN(Assembler);
+ DISALLOW_COPY_AND_ASSIGN(X86Assembler);
};
-
-inline void Assembler::EmitUint8(uint8_t value) {
+inline void X86Assembler::EmitUint8(uint8_t value) {
buffer_.Emit<uint8_t>(value);
}
-
-inline void Assembler::EmitInt32(int32_t value) {
+inline void X86Assembler::EmitInt32(int32_t value) {
buffer_.Emit<int32_t>(value);
}
-
-inline void Assembler::EmitRegisterOperand(int rm, int reg) {
+inline void X86Assembler::EmitRegisterOperand(int rm, int reg) {
CHECK_GE(rm, 0);
CHECK_LT(rm, 8);
buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
}
-
-inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
+inline void X86Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
EmitRegisterOperand(rm, static_cast<Register>(reg));
}
-
-inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
+inline void X86Assembler::EmitFixup(AssemblerFixup* fixup) {
buffer_.EmitFixup(fixup);
}
-
-inline void Assembler::EmitOperandSizeOverride() {
+inline void X86Assembler::EmitOperandSizeOverride() {
EmitUint8(0x66);
}
+// Slowpath entered when Thread::Current()->_exception is non-null
+class X86ExceptionSlowPath : public SlowPath {
+ public:
+ X86ExceptionSlowPath() {}
+ virtual void Emit(Assembler *sp_asm);
+};
+
+// Slowpath entered when Thread::Current()->_suspend_count is non-zero
+class X86SuspendCountSlowPath : public SlowPath {
+ public:
+ X86SuspendCountSlowPath(X86ManagedRegister return_reg,
+ FrameOffset return_save_location,
+ size_t return_size) :
+ return_register_(return_reg), return_save_location_(return_save_location),
+ return_size_(return_size) {}
+ virtual void Emit(Assembler *sp_asm);
+
+ private:
+ // Remember how to save the return value
+ const X86ManagedRegister return_register_;
+ const FrameOffset return_save_location_;
+ const size_t return_size_;
+};
+
+} // namespace x86
} // namespace art
#endif // ART_SRC_ASSEMBLER_X86_H_