Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1366)

Unified Diff: src/sh4/macro-assembler-sh4.h

Issue 11275184: First draft of the sh4 port Base URL: http://github.com/v8/v8.git@master
Patch Set: Use GYP and fixe some typos Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/sh4/lithium-sh4.cc ('k') | src/sh4/macro-assembler-sh4.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/sh4/macro-assembler-sh4.h
diff --git a/src/arm/macro-assembler-arm.h b/src/sh4/macro-assembler-sh4.h
similarity index 71%
copy from src/arm/macro-assembler-arm.h
copy to src/sh4/macro-assembler-sh4.h
index e3e39a3879e1b717296fbc466d7423336f852eeb..81756ff326ebe7b564e8a05084ccf736ea246afd 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/sh4/macro-assembler-sh4.h
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2011-2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -25,8 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
-#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
+#ifndef V8_SH4_MACRO_ASSEMBLER_SH4_H_
+#define V8_SH4_MACRO_ASSEMBLER_SH4_H_
#include "assembler.h"
#include "frames.h"
@@ -43,17 +43,6 @@ inline MemOperand FieldMemOperand(Register object, int offset) {
return MemOperand(object, offset - kHeapObjectTag);
}
-
-inline Operand SmiUntagOperand(Register object) {
- return Operand(object, ASR, kSmiTagSize);
-}
-
-
-
-// Give alias names to registers
-const Register cp = { 8 }; // JavaScript context pointer
-const Register kRootRegister = { 10 }; // Roots array pointer.
-
// Flags used for the AllocateInNewSpace functions.
enum AllocationFlags {
// No special flags.
@@ -68,13 +57,6 @@ enum AllocationFlags {
SIZE_IN_WORDS = 1 << 2
};
-// Flags used for AllocateHeapNumber
-enum TaggingMode {
- // Tag the result.
- TAG_RESULT,
- // Don't tag
- DONT_TAG_RESULT
-};
// Flags used for the ObjectToDoubleVFPRegister function.
enum ObjectToDoubleFlags {
@@ -102,11 +84,6 @@ bool AreAliased(Register reg1,
#endif
-enum TargetAddressStorageMode {
- CAN_INLINE_TARGET_ADDRESS,
- NEVER_INLINE_TARGET_ADDRESS
-};
-
// MacroAssembler implements a collection of frequently used macros.
class MacroAssembler: public Assembler {
public:
@@ -116,78 +93,12 @@ class MacroAssembler: public Assembler {
// macro assembler.
MacroAssembler(Isolate* isolate, void* buffer, int size);
- // Jump, Call, and Ret pseudo instructions implementing inter-working.
- void Jump(Register target, Condition cond = al);
- void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al);
- void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
- static int CallSize(Register target, Condition cond = al);
- void Call(Register target, Condition cond = al);
- int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
- static int CallSizeNotPredictableCodeSize(Address target,
- RelocInfo::Mode rmode,
- Condition cond = al);
- void Call(Address target, RelocInfo::Mode rmode,
- Condition cond = al,
- TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
- int CallSize(Handle<Code> code,
- RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
- TypeFeedbackId ast_id = TypeFeedbackId::None(),
- Condition cond = al);
- void Call(Handle<Code> code,
- RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
- TypeFeedbackId ast_id = TypeFeedbackId::None(),
- Condition cond = al,
- TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
- void Ret(Condition cond = al);
-
- // Emit code to discard a non-negative number of pointer-sized elements
- // from the stack, clobbering only the sp register.
- void Drop(int count, Condition cond = al);
-
- void Ret(int drop, Condition cond = al);
-
- // Swap two registers. If the scratch register is omitted then a slightly
- // less efficient form using xor instead of mov is emitted.
- void Swap(Register reg1,
- Register reg2,
- Register scratch = no_reg,
- Condition cond = al);
-
-
- void And(Register dst, Register src1, const Operand& src2,
- Condition cond = al);
- void Ubfx(Register dst, Register src, int lsb, int width,
- Condition cond = al);
- void Sbfx(Register dst, Register src, int lsb, int width,
- Condition cond = al);
- // The scratch register is not used for ARMv7.
- // scratch can be the same register as src (in which case it is trashed), but
- // not the same as dst.
- void Bfi(Register dst,
- Register src,
- Register scratch,
- int lsb,
- int width,
- Condition cond = al);
- void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
- void Usat(Register dst, int satpos, const Operand& src,
- Condition cond = al);
-
- void Call(Label* target);
-
- // Register move. May do nothing if the registers are identical.
- void Move(Register dst, Handle<Object> value);
- void Move(Register dst, Register src, Condition cond = al);
- void Move(DoubleRegister dst, DoubleRegister src);
-
// Load an object from the root table.
void LoadRoot(Register destination,
- Heap::RootListIndex index,
- Condition cond = al);
+ Heap::RootListIndex index);
// Store an object to the root table.
void StoreRoot(Register source,
- Heap::RootListIndex index,
- Condition cond = al);
+ Heap::RootListIndex index);
void LoadHeapObject(Register dst, Handle<HeapObject> object);
@@ -202,10 +113,6 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// GC Support
- void IncrementalMarkingRecordWriteHelper(Register object,
- Register value,
- Register address);
-
enum RememberedSetFinalAction {
kReturnAtEnd,
kFallThroughAtEnd
@@ -266,11 +173,13 @@ class MacroAssembler: public Assembler {
Register scratch3,
Label* object_is_white_and_not_data);
- // Detects conservatively whether an object is data-only, i.e. it does need to
- // be scanned by the garbage collector.
- void JumpIfDataObject(Register value,
- Register scratch,
- Label* not_data_object);
+ // Check if object is in new space.
+ // scratch can be object itself, but it will be clobbered.
+ void InNewSpace(Register object,
+ Register scratch,
+ // eq for "in new space?", ne for "not in new space?"
+ Condition cond,
+ Label* branch);
// Notify the garbage collector that we wrote a pointer into an object.
// |object| is the object being stored into, |value| is the object being
@@ -320,131 +229,85 @@ class MacroAssembler: public Assembler {
RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
SmiCheck smi_check = INLINE_SMI_CHECK);
- // Push a handle.
- void Push(Handle<Object> handle);
+
+ // Mark the register as dead. Put the pattern 0xFFFFFFDE into the register.
+ void Dead(Register dead) {
+ // Fit in a single SH4 mov_imm_ instruction
+ mov(dead, Operand(static_cast<int>(0xFFFFFFDE)));
+ }
+
+ // Mark up to four registers dead at a time.
+ void Dead(Register d1, Register d2, Register d3 = no_reg,
+ Register d4 = no_reg) {
+ Dead(d1);
+ Dead(d2);
+ if (d3.is_valid()) Dead(d3);
+ if (d4.is_valid()) Dead(d4);
+ }
+
+ void Push(Handle<Object> handle) { push(Operand(handle), sh4_ip); }
// Push two registers. Pushes leftmost register first (to highest address).
- void Push(Register src1, Register src2, Condition cond = al) {
+ void Push(Register src1, Register src2) {
ASSERT(!src1.is(src2));
- if (src1.code() > src2.code()) {
- stm(db_w, sp, src1.bit() | src2.bit(), cond);
- } else {
- str(src1, MemOperand(sp, 4, NegPreIndex), cond);
- str(src2, MemOperand(sp, 4, NegPreIndex), cond);
- }
+ push(src1);
+ push(src2);
}
// Push three registers. Pushes leftmost register first (to highest address).
- void Push(Register src1, Register src2, Register src3, Condition cond = al) {
+ void Push(Register src1, Register src2, Register src3) {
ASSERT(!src1.is(src2));
ASSERT(!src2.is(src3));
ASSERT(!src1.is(src3));
- if (src1.code() > src2.code()) {
- if (src2.code() > src3.code()) {
- stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
- } else {
- stm(db_w, sp, src1.bit() | src2.bit(), cond);
- str(src3, MemOperand(sp, 4, NegPreIndex), cond);
- }
- } else {
- str(src1, MemOperand(sp, 4, NegPreIndex), cond);
- Push(src2, src3, cond);
- }
+ push(src1);
+ push(src2);
+ push(src3);
}
// Push four registers. Pushes leftmost register first (to highest address).
- void Push(Register src1,
- Register src2,
- Register src3,
- Register src4,
- Condition cond = al) {
+ void Push(Register src1, Register src2,
+ Register src3, Register src4) {
ASSERT(!src1.is(src2));
ASSERT(!src2.is(src3));
ASSERT(!src1.is(src3));
ASSERT(!src1.is(src4));
ASSERT(!src2.is(src4));
ASSERT(!src3.is(src4));
- if (src1.code() > src2.code()) {
- if (src2.code() > src3.code()) {
- if (src3.code() > src4.code()) {
- stm(db_w,
- sp,
- src1.bit() | src2.bit() | src3.bit() | src4.bit(),
- cond);
- } else {
- stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
- str(src4, MemOperand(sp, 4, NegPreIndex), cond);
- }
- } else {
- stm(db_w, sp, src1.bit() | src2.bit(), cond);
- Push(src3, src4, cond);
- }
- } else {
- str(src1, MemOperand(sp, 4, NegPreIndex), cond);
- Push(src2, src3, src4, cond);
- }
+ push(src1);
+ push(src2);
+ push(src3);
+ push(src4);
}
// Pop two registers. Pops rightmost register first (from lower address).
- void Pop(Register src1, Register src2, Condition cond = al) {
+ void Pop(Register src1, Register src2) {
ASSERT(!src1.is(src2));
- if (src1.code() > src2.code()) {
- ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
- } else {
- ldr(src2, MemOperand(sp, 4, PostIndex), cond);
- ldr(src1, MemOperand(sp, 4, PostIndex), cond);
- }
+ pop(src2);
+ pop(src1);
}
- // Pop three registers. Pops rightmost register first (from lower address).
- void Pop(Register src1, Register src2, Register src3, Condition cond = al) {
+ // Pop three registers. Pops rightmost register first (from lower address).
+ void Pop(Register src1, Register src2, Register src3) {
ASSERT(!src1.is(src2));
ASSERT(!src2.is(src3));
ASSERT(!src1.is(src3));
- if (src1.code() > src2.code()) {
- if (src2.code() > src3.code()) {
- ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
- } else {
- ldr(src3, MemOperand(sp, 4, PostIndex), cond);
- ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
- }
- } else {
- Pop(src2, src3, cond);
- str(src1, MemOperand(sp, 4, PostIndex), cond);
- }
+ pop(src3);
+ pop(src2);
+ pop(src1);
}
- // Pop four registers. Pops rightmost register first (from lower address).
- void Pop(Register src1,
- Register src2,
- Register src3,
- Register src4,
- Condition cond = al) {
+ // Pop four registers. Pops rightmost register first (from lower address).
+ void Pop(Register src1, Register src2, Register src3, Register src4) {
ASSERT(!src1.is(src2));
ASSERT(!src2.is(src3));
ASSERT(!src1.is(src3));
ASSERT(!src1.is(src4));
ASSERT(!src2.is(src4));
ASSERT(!src3.is(src4));
- if (src1.code() > src2.code()) {
- if (src2.code() > src3.code()) {
- if (src3.code() > src4.code()) {
- ldm(ia_w,
- sp,
- src1.bit() | src2.bit() | src3.bit() | src4.bit(),
- cond);
- } else {
- ldr(src4, MemOperand(sp, 4, PostIndex), cond);
- ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
- }
- } else {
- Pop(src3, src4, cond);
- ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
- }
- } else {
- Pop(src2, src3, src4, cond);
- ldr(src1, MemOperand(sp, 4, PostIndex), cond);
- }
+ pop(src4);
+ pop(src3);
+ pop(src2);
+ pop(src1);
}
// Push and pop the registers that can hold pointers, as defined by the
@@ -464,57 +327,60 @@ class MacroAssembler: public Assembler {
// Load two consecutive registers with two consecutive memory locations.
void Ldrd(Register dst1,
Register dst2,
- const MemOperand& src,
- Condition cond = al);
+ const MemOperand& src);
// Store two consecutive registers to two consecutive memory locations.
void Strd(Register src1,
Register src2,
- const MemOperand& dst,
- Condition cond = al);
-
- // Clear specified FPSCR bits.
- void ClearFPSCRBits(const uint32_t bits_to_clear,
- const Register scratch,
- const Condition cond = al);
-
- // Compare double values and move the result to the normal condition flags.
- void VFPCompareAndSetFlags(const DwVfpRegister src1,
- const DwVfpRegister src2,
- const Condition cond = al);
- void VFPCompareAndSetFlags(const DwVfpRegister src1,
- const double src2,
- const Condition cond = al);
-
- // Compare double values and then load the fpscr flags to a register.
- void VFPCompareAndLoadFlags(const DwVfpRegister src1,
- const DwVfpRegister src2,
- const Register fpscr_flags,
- const Condition cond = al);
- void VFPCompareAndLoadFlags(const DwVfpRegister src1,
- const double src2,
- const Register fpscr_flags,
- const Condition cond = al);
-
- void Vmov(const DwVfpRegister dst,
- const double imm,
- const Register scratch = no_reg,
- const Condition cond = al);
+ const MemOperand& dst);
+
+ void IsObjectJSStringType(Register object,
+ Register scratch,
+ Label* fail);
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ // ---------------------------------------------------------------------------
+ // Debugger Support
+
+ void DebugBreak();
+#endif
+
+ // ---------------------------------------------------------------------------
+ // Support for marking unimplemented code generator function
+ // Should be called with UNIMPLEMENTED_BREAK define below.
+ void UnimplementedBreak(const char *file, int line);
+#ifdef DEBUG
+#define UNIMPLEMENTED_BREAK() UnimplementedBreak(__FILE__, __LINE__)
+#else
+#define UNIMPLEMENTED_BREAK() UnimplementedBreak("", 0)
+#endif
+
+ // ---------------------------------------------------------------------------
+ // Activation frames
+
+ void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+ void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+ void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+ void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
+
+ // Expects object in r0 and returns map with validated enum cache
+ // in r0. Assumes that any other register can be used as a scratch.
+ void CheckEnumCache(Register null_value, Label* call_runtime);
// Enter exit frame.
// stack_space - extra stack space, used for alignment before call to C.
- void EnterExitFrame(bool save_doubles, int stack_space = 0);
+ void EnterExitFrame(bool save_doubles, int stack_space = 0,
+ Register scratch = sh4_ip);
// Leave the current exit frame. Expects the return value in r0.
// Expect the number of values, pushed prior to the exit frame, to
// remove in a register (or no_reg, if there is nothing to remove).
void LeaveExitFrame(bool save_doubles, Register argument_count);
- // Get the actual activation frame alignment for target environment.
- static int ActivationFrameAlignment();
-
void LoadContext(Register dst, int context_chain_length);
+
// Conditionally load the cached Array transitioned map of type
// transitioned_kind from the native context if the map in register
// map_in_out is the cached Array map in the native context of
@@ -543,7 +409,7 @@ class MacroAssembler: public Assembler {
void InitializeRootRegister() {
ExternalReference roots_array_start =
ExternalReference::roots_array_start(isolate());
- mov(kRootRegister, Operand(roots_array_start));
+ mov(roots, Operand(roots_array_start));
}
// ---------------------------------------------------------------------------
@@ -583,25 +449,128 @@ class MacroAssembler: public Assembler {
const CallWrapper& call_wrapper,
CallKind call_kind);
+ // Expression support
+ void Set(Register dst, const Operand& x);
+ void Set(const Operand& dst, const Operand& x);
+
+ // Compare object type for heap object.
+ // Incoming register is heap_object and outgoing register is map.
+ void CmpObjectType(Register heap_object, InstanceType type, Register map);
+
+ // Compare instance type for map.
+ void CmpInstanceType(Register map, InstanceType type);
+
+ // Check if the map of an object is equal to a specified map and branch to a
+ // specified target if equal. Skip the smi check if not required (object is
+ // known to be a heap object)
+ void DispatchMap(Register obj,
+ Register scratch,
+ Handle<Map> map,
+ Handle<Code> success,
+ SmiCheckType smi_check_type);
+
+ // Compare the object in a register to a value from the root list.
+ // Uses the ip register as scratch.
+ void CompareRoot(Register obj, Heap::RootListIndex index);
+
+ // Check if a heap object's type is in the JSObject range, not including
+ // JSFunction. The object's map will be loaded in the map register.
+ // Any or all of the three registers may be the same.
+ // The contents of the scratch register will always be overwritten.
void IsObjectJSObjectType(Register heap_object,
Register map,
Register scratch,
Label* fail);
- void IsInstanceJSObjectType(Register map,
- Register scratch,
- Label* fail);
+ // The contents of the scratch register will be overwritten.
+ void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
- void IsObjectJSStringType(Register object,
- Register scratch,
- Label* fail);
+ // ---------------------------------------------------------------------------
+ // String utilities
+
+ // Checks if both objects are sequential ASCII strings and jumps to label
+ // if either is not. Assumes that neither object is a smi.
+ void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
+ Register object2,
+ Register scratch1,
+ Register scratch2,
+ Label* failure);
+
+ // Checks if both objects are sequential ASCII strings and jumps to label
+ // if either is not.
+ void JumpIfNotBothSequentialAsciiStrings(Register first,
+ Register second,
+ Register scratch1,
+ Register scratch2,
+ Label* not_flat_ascii_strings);
+
+ // Checks if both instance types are sequential ASCII strings and jumps to
+ // label if either is not.
+ void JumpIfBothInstanceTypesAreNotSequentialAscii(
+ Register first_object_instance_type,
+ Register second_object_instance_type,
+ Register scratch1,
+ Register scratch2,
+ Label* failure);
+
+ // Check if instance type is sequential ASCII string and jump to label if
+ // it is not.
+ void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
+ Register scratch,
+ Label* failure);
+
+ // Abort execution if argument is not a number. Used in debug code.
+ void AbortIfNotNumber(Register object);
+
+ // Abort execution if argument is not a smi. Used in debug code.
+ void AbortIfNotSmi(Register object);
+
+ // Abort execution if argument is a smi. Used in debug code.
+ void AbortIfSmi(Register object);
+
+ // Abort execution if argument is a string. Used in debug code.
+ void AbortIfNotString(Register object);
+
+ // Abort execution if argument is not the root value with the given index.
+ void AbortIfNotRootValue(Register src,
+ Heap::RootListIndex root_value_index,
+ const char* message);
+
+ // Prints the value of the register to stdout. Use for debug only.
+ void PrintRegisterValue(Register reg);
-#ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
- // Debugger Support
+ // Patching helpers.
+
+ // Get the location of a relocated constant (its address in the constant pool)
+ // from its load site.
+ void GetRelocatedValueLocation(Register ldr_location,
+ Register result);
+
+ void LoadInstanceDescriptors(Register map,
+ Register descriptors,
+ Register scratch);
+ void EnumLength(Register dst, Register map);
+ void NumberOfOwnDescriptors(Register dst, Register map);
+
+ template<typename Field>
+ void DecodeField(Register reg) {
+ static const int shift = Field::kShift;
+ static const int mask = (Field::kMask >> shift) << kSmiTagSize;
+ lsr(reg, reg, Operand(shift));
+ land(reg, reg, Operand(mask));
+ }
+
+
+
+ // ---------------------------------------------------------------------------
+ // HeapNumber utilities
+
+ void JumpIfNotHeapNumber(Register object,
+ Register heap_number_map,
+ Register scratch,
+ Label* on_not_heap_number);
- void DebugBreak();
-#endif
// ---------------------------------------------------------------------------
// Exception handling
@@ -613,7 +582,7 @@ class MacroAssembler: public Assembler {
// Must preserve the result register.
void PopTryHandler();
- // Passes thrown value to the handler of top of the try handler chain.
+ // Activate the top handler in the try hander chain.
void Throw(Register value);
// Propagates an uncatchable exception to the top of the current JS stack's
@@ -640,62 +609,39 @@ class MacroAssembler: public Assembler {
Register t1,
Register t2);
-
- inline void MarkCode(NopMarkerTypes type) {
- nop(type);
- }
-
- // Check if the given instruction is a 'type' marker.
- // i.e. check if is is a mov r<type>, r<type> (referenced as nop(type))
- // These instructions are generated to mark special location in the code,
- // like some special IC code.
- static inline bool IsMarkedCode(Instr instr, int type) {
- ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
- return IsNop(instr, type);
- }
-
-
- static inline int GetCodeMarker(Instr instr) {
- int dst_reg_offset = 12;
- int dst_mask = 0xf << dst_reg_offset;
- int src_mask = 0xf;
- int dst_reg = (instr & dst_mask) >> dst_reg_offset;
- int src_reg = instr & src_mask;
- uint32_t non_register_mask = ~(dst_mask | src_mask);
- uint32_t mov_mask = al | 13 << 21;
-
- // Return <n> if we have a mov rn rn, else return -1.
- int type = ((instr & non_register_mask) == mov_mask) &&
- (dst_reg == src_reg) &&
- (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
- ? src_reg
- : -1;
- ASSERT((type == -1) ||
- ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
- return type;
- }
-
-
// ---------------------------------------------------------------------------
// Allocation support
- // Allocate an object in new space. The object_size is specified
- // either in bytes or in words if the allocation flag SIZE_IN_WORDS
- // is passed. If the new space is exhausted control continues at the
- // gc_required label. The allocated object is returned in result. If
- // the flag tag_allocated_object is true the result is tagged as as
- // a heap object. All registers are clobbered also when control
- // continues at the gc_required label.
+ // Allocate an object in new space. If the new space is exhausted control
+ // continues at the gc_required label. The allocated object is returned in
+ // result and end of the new object is returned in result_end. The register
+ // scratch can be passed as no_reg in which case an additional object
+ // reference will be added to the reloc info. The returned pointers in result
+ // and result_end have not yet been tagged as heap objects. If
+ // result_contains_top_on_entry is true the content of result is known to be
+ // the allocation top on entry (could be result_end from a previous call to
+ // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
+ // should be no_reg as it is never used.
void AllocateInNewSpace(int object_size,
Register result,
- Register scratch1,
- Register scratch2,
+ Register result_end,
+ Register scratch,
Label* gc_required,
AllocationFlags flags);
+
+ void AllocateInNewSpace(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
+
void AllocateInNewSpace(Register object_size,
Register result,
- Register scratch1,
- Register scratch2,
+ Register result_end,
+ Register scratch,
Label* gc_required,
AllocationFlags flags);
@@ -706,6 +652,18 @@ class MacroAssembler: public Assembler {
void UndoAllocationInNewSpace(Register object, Register scratch);
+ // Allocate a heap number in new space with undefined value. The
+ // register scratch2 can be passed as no_reg; the others must be
+ // valid registers. Returns tagged pointer in result register, or
+ // jumps to gc_required if new space is full.
+ void AllocateHeapNumber(Register result,
+ Register scratch1,
+ Register scratch2,
+ Register heap_number_map,
+ Label* gc_required);
+
+ // Allocate a sequential string. All the header fields of the string object
+ // are initialized.
void AllocateTwoByteString(Register result,
Register length,
Register scratch1,
@@ -718,11 +676,20 @@ class MacroAssembler: public Assembler {
Register scratch2,
Register scratch3,
Label* gc_required);
+ void AllocateAsciiString(Register result,
+ int length,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required);
+
+ // Allocate a raw cons string object. Only the map field of the result is
+ // initialized.
void AllocateTwoByteConsString(Register result,
Register length,
Register scratch1,
Register scratch2,
Label* gc_required);
+
void AllocateAsciiConsString(Register result,
Register length,
Register scratch1,
@@ -739,30 +706,14 @@ class MacroAssembler: public Assembler {
Register scratch2,
Label* gc_required);
- // Allocates a heap number or jumps to the gc_required label if the young
- // space is full and a scavenge is needed. All registers are clobbered also
- // when control continues at the gc_required label.
- void AllocateHeapNumber(Register result,
- Register scratch1,
- Register scratch2,
- Register heap_number_map,
- Label* gc_required,
- TaggingMode tagging_mode = TAG_RESULT);
- void AllocateHeapNumberWithValue(Register result,
- DwVfpRegister value,
- Register scratch1,
- Register scratch2,
- Register heap_number_map,
- Label* gc_required);
-
// Copies a fixed number of fields of heap objects from src to dst.
void CopyFields(Register dst, Register src, RegList temps, int field_count);
- // Copies a number of bytes from src to dst. All registers are clobbered. On
- // exit src and dst will point to the place just after where the last byte was
- // read or written and length will be zero.
- void CopyBytes(Register src,
- Register dst,
+ // Copy memory, byte-by-byte, from source to destination. Not optimized for
+ // long or aligned copies.
+ // The contents of index and scratch are destroyed.
+ void CopyBytes(Register source,
+ Register destination,
Register length,
Register scratch);
@@ -797,15 +748,18 @@ class MacroAssembler: public Assembler {
void CompareObjectType(Register heap_object,
Register map,
Register type_reg,
- InstanceType type);
+ InstanceType type,
+ Condition cond);
// Compare instance type in a map. map contains a valid map object whose
// object type should be compared with the given type. This both
- // sets the flags and leaves the object type in the type_reg register.
+ // sets the flags and leaves the object type in the type_reg register. It
+ // leaves the heap object in the heap_object register unless the heap_object
+ // register is the same register as type_reg.
void CompareInstanceType(Register map,
Register type_reg,
- InstanceType type);
-
+ InstanceType type,
+ Condition cond);
// Check if a map for a JSObject indicates that the object has fast elements.
// Jump to the specified label if it does not.
@@ -876,20 +830,6 @@ class MacroAssembler: public Assembler {
SmiCheckType smi_check_type);
- // Check if the map of an object is equal to a specified map and branch to a
- // specified target if equal. Skip the smi check if not required (object is
- // known to be a heap object)
- void DispatchMap(Register obj,
- Register scratch,
- Handle<Map> map,
- Handle<Code> success,
- SmiCheckType smi_check_type);
-
-
- // Compare the object in a register to a value from the root list.
- // Uses the ip register as scratch.
- void CompareRoot(Register obj, Heap::RootListIndex index);
-
// Load and check the instance type of an object for being a string.
// Loads the type into the second argument register.
@@ -918,36 +858,10 @@ class MacroAssembler: public Assembler {
void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
- // Uses VFP instructions to Convert a Smi to a double.
- void IntegerToDoubleConversionWithVFP3(Register inReg,
- Register outHighReg,
- Register outLowReg);
-
- // Load the value of a number object into a VFP double register. If the object
- // is not a number a jump to the label not_number is performed and the VFP
- // double register is unchanged.
- void ObjectToDoubleVFPRegister(
- Register object,
- DwVfpRegister value,
- Register scratch1,
- Register scratch2,
- Register heap_number_map,
- SwVfpRegister scratch3,
- Label* not_number,
- ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
-
- // Load the value of a smi object into a VFP double register. The register
- // scratch1 can be the same register as smi in which case smi will hold the
- // untagged value afterwards.
- void SmiToDoubleVFPRegister(Register smi,
- DwVfpRegister value,
- Register scratch1,
- SwVfpRegister scratch2);
-
// Convert the HeapNumber pointed to by source to a 32bits signed integer
// dest. If the HeapNumber does not fit into a 32bits signed integer branch
// to not_int32 label. If VFP3 is available double_scratch is used but not
- // scratch2.
+ // scratch2. TODO: SH4, use fp reg.
void ConvertToInt32(Register source,
Register dest,
Register scratch,
@@ -955,22 +869,29 @@ class MacroAssembler: public Assembler {
DwVfpRegister double_scratch,
Label *not_int32);
- // Truncates a double using a specific rounding mode, and writes the value
- // to the result register.
+ // Load the value of a smi object into a FPU double register. The register
+ // scratch1 can be the same register as smi in which case smi will hold the
+ // untagged value afterwards.
+ void SmiToDoubleFPURegister(Register smi,
+ DwVfpRegister value,
+ Register scratch1);
+
+
+
+ // Truncates a double using a specific rounding mode.
// Clears the z flag (ne condition) if an overflow occurs.
- // If kCheckForInexactConversion is passed, the z flag is also cleared if the
- // conversion was inexact, i.e. if the double value could not be converted
- // exactly to a 32-bit integer.
- void EmitVFPTruncate(VFPRoundingMode rounding_mode,
+ // If exact_conversion is true, the z flag is also cleared if the conversion
+ // was inexact, ie. if the double value could not be converted exactly
+ // to a 32bit integer.
+ void EmitFPUTruncate(FPURoundingMode rounding_mode,
Register result,
DwVfpRegister double_input,
Register scratch,
- DwVfpRegister double_scratch,
CheckForInexactConversion check
= kDontCheckForInexactConversion);
// Helper for EmitECMATruncate.
- // This will truncate a floating-point value outside of the signed 32bit
+ // This will truncate a floating-point value outside of the singed 32bit
// integer range to a 32bit signed integer.
// Expects the double value loaded in input_high and input_low.
// Exits with the answer in 'result'.
@@ -1003,10 +924,10 @@ class MacroAssembler: public Assembler {
// Runtime calls
// Call a code stub.
- void CallStub(CodeStub* stub, Condition cond = al);
+ void CallStub(CodeStub* stub);
// Call a code stub.
- void TailCallStub(CodeStub* stub, Condition cond = al);
+ void TailCallStub(CodeStub* stub);
// Call a runtime routine.
void CallRuntime(const Runtime::Function* f, int num_arguments);
@@ -1050,29 +971,14 @@ class MacroAssembler: public Assembler {
void PrepareCallCFunction(int num_reg_arguments,
Register scratch);
- // There are two ways of passing double arguments on ARM, depending on
- // whether soft or hard floating point ABI is used. These functions
- // abstract parameter passing for the three different ways we call
- // C functions from generated code.
- void SetCallCDoubleArguments(DoubleRegister dreg);
- void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
- void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
-
// Calls a C function and cleans up the space for arguments allocated
// by PrepareCallCFunction. The called function is not allowed to trigger a
// garbage collection, since that might move the code and invalidate the
// return address (unless this is somehow accounted for by the called
// function).
- void CallCFunction(ExternalReference function, int num_arguments);
+ void CallCFunction(ExternalReference function, int num_reg_arguments,
+ int num_double_arguments = 0);
void CallCFunction(Register function, int num_arguments);
- void CallCFunction(ExternalReference function,
- int num_reg_arguments,
- int num_double_arguments);
- void CallCFunction(Register function,
- int num_reg_arguments,
- int num_double_arguments);
-
- void GetCFunctionDoubleResult(const DoubleRegister dst);
// Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context. stack_space
@@ -1096,11 +1002,51 @@ class MacroAssembler: public Assembler {
// Store the function for the given builtin in the target register.
void GetBuiltinFunction(Register target, Builtins::JavaScript id);
+ // ---------------------------------------------------------------------------
+ // Utilities
+
+ void Ret(Condition cond = al);
+
+ void Drop(int stack_elements);
+ void Ret(int drop);
+
+ void Jump(Register target);
+ void Jump(intptr_t target, RelocInfo::Mode rmode);
+ void Jump(Handle<Code> code, RelocInfo::Mode rmode);
+ void Call(Label* target) { call(target); }
+ void Call(Handle<Code> code,
+ RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+ TypeFeedbackId ast_id = TypeFeedbackId::None());
+
+ // Emit call to the code we are currently generating.
+ void CallSelf() {
+ UNIMPLEMENTED();
+ }
+
+ void Move(Register dst, Handle<Object> value);
+ // Move if the registers are not identical.
+ void Move(Register target, Register source);
+
+ void Usat(Register dst, int satpos, Register src);
+ void Ubfx(Register dst, Register src, int lsb, int width);
+ void Sbfx(Register dst, Register src, int lsb, int width);
+ void Bfc(Register dst, int lsb, int width);
+ // scratch can be the same register as src (in which case it is trashed), but
+ // not the same as dst.
+ void Bfi(Register dst,
+ Register src,
+ Register scratch,
+ int lsb,
+ int width);
+
Handle<Object> CodeObject() {
ASSERT(!code_object_.is_null());
return code_object_;
}
+ // Record code generator line mapping through comments.
+ // Use -code_comments to enable.
+ MacroAssembler* RecordFunctionLine(const char* function, int line);
// ---------------------------------------------------------------------------
// StatsCounter support
@@ -1119,7 +1065,9 @@ class MacroAssembler: public Assembler {
// Calls Abort(msg) if the condition cond is not satisfied.
// Use --debug_code to enable.
void Assert(Condition cond, const char* msg);
- void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
+
+ void AssertRegisterIsRoot(Register reg, Register scratch,
+ Heap::RootListIndex index);
void AssertFastElements(Register elements);
// Like Assert(), but always enabled.
@@ -1128,6 +1076,12 @@ class MacroAssembler: public Assembler {
// Print a message to stdout and abort execution.
void Abort(const char* msg);
+ // Print an object to stdout.
+ void DebugPrint(Register obj);
+
+ // Check that the stack is aligned.
+ void CheckStackAlignment();
+
// Verify restrictions about code generated in stubs.
void set_generating_stub(bool value) { generating_stub_ = value; }
bool generating_stub() { return generating_stub_; }
@@ -1137,14 +1091,6 @@ class MacroAssembler: public Assembler {
bool has_frame() { return has_frame_; }
inline bool AllowThisStubCall(CodeStub* stub);
- // EABI variant for double arguments in use.
- bool use_eabi_hardfloat() {
-#if USE_EABI_HARDFLOAT
- return true;
-#else
- return false;
-#endif
- }
// ---------------------------------------------------------------------------
// Number utilities
@@ -1170,28 +1116,27 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// Smi utilities
- void SmiTag(Register reg, SBit s = LeaveCC) {
- add(reg, reg, Operand(reg), s);
+ void SmiTag(Register reg) {
+ add(reg, reg, reg);
}
- void SmiTag(Register dst, Register src, SBit s = LeaveCC) {
- add(dst, src, Operand(src), s);
+ void SmiTag(Register dst, Register src) {
+ add(dst, src, src);
}
// Try to convert int32 to smi. If the value is to large, preserve
// the original value and jump to not_a_smi. Destroys scratch and
// sets flags.
void TrySmiTag(Register reg, Label* not_a_smi, Register scratch) {
- mov(scratch, reg);
- SmiTag(scratch, SetCC);
- b(vs, not_a_smi);
+ addv(scratch, reg, reg);
+ b(t, not_a_smi);
mov(reg, scratch);
}
- void SmiUntag(Register reg, SBit s = LeaveCC) {
- mov(reg, Operand(reg, ASR, kSmiTagSize), s);
+ void SmiUntag(Register reg) {
+ asr(reg, reg, Operand(kSmiTagSize));
}
- void SmiUntag(Register dst, Register src, SBit s = LeaveCC) {
- mov(dst, Operand(src, ASR, kSmiTagSize), s);
+ void SmiUntag(Register dst, Register src) {
+ asr(dst, src, Operand(kSmiTagSize));
}
// Untag the source value into destination and jump if source is a smi.
@@ -1203,118 +1148,40 @@ class MacroAssembler: public Assembler {
void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
// Jump the register contains a smi.
- inline void JumpIfSmi(Register value, Label* smi_label) {
+ inline void JumpIfSmi(Register value, Label* smi_label,
+ Label::Distance distance = Label::kFar) {
tst(value, Operand(kSmiTagMask));
- b(eq, smi_label);
+ if (distance == Label::kFar)
+ bt(smi_label);
+ else
+ bt_near(smi_label);
}
// Jump if either of the registers contain a non-smi.
- inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
+ inline void JumpIfNotSmi(Register value, Label* not_smi_label,
+ Label::Distance distance = Label::kFar) {
tst(value, Operand(kSmiTagMask));
- b(ne, not_smi_label);
+ if (distance == Label::kFar)
+ bf(not_smi_label);
+ else
+ bf_near(not_smi_label);
}
+
// Jump if either of the registers contain a non-smi.
- void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
+ void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi,
+ Label::Distance distance = Label::kFar);
// Jump if either of the registers contain a smi.
- void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
-
- // Abort execution if argument is a smi, enabled via --debug-code.
- void AssertNotSmi(Register object);
- void AssertSmi(Register object);
-
- // Abort execution if argument is a string, enabled via --debug-code.
- void AssertString(Register object);
-
- // Abort execution if argument is not the root value with the given index,
- // enabled via --debug-code.
- void AssertRootValue(Register src,
- Heap::RootListIndex root_value_index,
- const char* message);
-
- // ---------------------------------------------------------------------------
- // HeapNumber utilities
-
- void JumpIfNotHeapNumber(Register object,
- Register heap_number_map,
- Register scratch,
- Label* on_not_heap_number);
-
- // ---------------------------------------------------------------------------
- // String utilities
-
- // Checks if both objects are sequential ASCII strings and jumps to label
- // if either is not. Assumes that neither object is a smi.
- void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
- Register object2,
- Register scratch1,
- Register scratch2,
- Label* failure);
-
- // Checks if both objects are sequential ASCII strings and jumps to label
- // if either is not.
- void JumpIfNotBothSequentialAsciiStrings(Register first,
- Register second,
- Register scratch1,
- Register scratch2,
- Label* not_flat_ascii_strings);
-
- // Checks if both instance types are sequential ASCII strings and jumps to
- // label if either is not.
- void JumpIfBothInstanceTypesAreNotSequentialAscii(
- Register first_object_instance_type,
- Register second_object_instance_type,
- Register scratch1,
- Register scratch2,
- Label* failure);
-
- // Check if instance type is sequential ASCII string and jump to label if
- // it is not.
- void JumpIfInstanceTypeIsNotSequentialAscii(Register type,
- Register scratch,
- Label* failure);
-
-
- // ---------------------------------------------------------------------------
- // Patching helpers.
-
- // Get the location of a relocated constant (its address in the constant pool)
- // from its load site.
- void GetRelocatedValueLocation(Register ldr_location,
- Register result);
-
-
- void ClampUint8(Register output_reg, Register input_reg);
-
- void ClampDoubleToUint8(Register result_reg,
- DoubleRegister input_reg,
- DoubleRegister temp_double_reg);
-
-
- void LoadInstanceDescriptors(Register map, Register descriptors);
- void EnumLength(Register dst, Register map);
- void NumberOfOwnDescriptors(Register dst, Register map);
-
- template<typename Field>
- void DecodeField(Register reg) {
- static const int shift = Field::kShift;
- static const int mask = (Field::kMask >> shift) << kSmiTagSize;
- mov(reg, Operand(reg, LSR, shift));
- and_(reg, reg, Operand(mask));
- }
-
+ void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi,
+ Label::Distance distance = Label::kFar);
// Activation support.
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
- // Expects object in r0 and returns map with validated enum cache
- // in r0. Assumes that any other register can be used as a scratch.
- void CheckEnumCache(Register null_value, Label* call_runtime);
private:
void CallCFunctionHelper(Register function,
int num_reg_arguments,
int num_double_arguments);
- void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
// Helper functions for generating invokes.
void InvokePrologue(const ParameterCount& expected,
@@ -1327,18 +1194,14 @@ class MacroAssembler: public Assembler {
const CallWrapper& call_wrapper,
CallKind call_kind);
+ void LeaveExitFrameEpilogue();
+
void InitializeNewString(Register string,
Register length,
Heap::RootListIndex map_index,
Register scratch1,
Register scratch2);
- // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
- void InNewSpace(Register object,
- Register scratch,
- Condition cond, // eq for new space, ne otherwise.
- Label* branch);
-
// Helper for finding the mark bits for an address. Afterwards, the
// bitmap register points at the word with the mark bits and the mask
// the position of the first bit. Leaves addr_reg unchanged.
@@ -1346,6 +1209,19 @@ class MacroAssembler: public Assembler {
Register bitmap_reg,
Register mask_reg);
+ // Allocation support helpers.
+ void LoadAllocationTopHelper(Register result,
+ Register scratch,
+ AllocationFlags flags);
+ void UpdateAllocationTopHelper(Register result_end, Register scratch);
+
+ // Helper for PopHandleScope. Allowed to perform a GC and returns
+ // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
+ // possibly returns a failure object indicating an allocation failure.
+ MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
+ Register scratch,
+ bool gc_allowed);
+
// Helper for throwing exceptions. Compute a handler address and jump to
// it. See the implementation for register usage.
void JumpToHandlerEntry();
@@ -1380,12 +1256,6 @@ class CodePatcher {
// Macro assembler to emit code.
MacroAssembler* masm() { return &masm_; }
- // Emit an instruction directly.
- void Emit(Instr instr);
-
- // Emit an address directly.
- void Emit(Address addr);
-
// Emit the condition part of an instruction leaving the rest of the current
// instruction unchanged.
void EmitCondition(Condition cond);
@@ -1411,16 +1281,13 @@ inline MemOperand GlobalObjectOperand() {
}
-#ifdef GENERATED_CODE_COVERAGE
-#define CODE_COVERAGE_STRINGIFY(x) #x
-#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
-#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
-#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
+#ifdef DEBUG
+# define ACCESS_MASM(masm) masm->RecordFunctionLine(__FUNCTION__, __LINE__)->
#else
-#define ACCESS_MASM(masm) masm->
+# define ACCESS_MASM(masm) masm->
#endif
} } // namespace v8::internal
-#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_
+#endif // V8_SH4_MACRO_ASSEMBLER_SH4_H_
« no previous file with comments | « src/sh4/lithium-sh4.cc ('k') | src/sh4/macro-assembler-sh4.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698