summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/assembler/MacroAssemblerARM.h
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/assembler/MacroAssemblerARM.h')
-rw-r--r--JavaScriptCore/assembler/MacroAssemblerARM.h113
1 files changed, 95 insertions, 18 deletions
diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h
index 21b8de8..40d2e4a 100644
--- a/JavaScriptCore/assembler/MacroAssemblerARM.h
+++ b/JavaScriptCore/assembler/MacroAssemblerARM.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 Apple Inc.
- * Copyright (C) 2009 University of Szeged
+ * Copyright (C) 2009, 2010 University of Szeged
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,8 +28,6 @@
#ifndef MacroAssemblerARM_h
#define MacroAssemblerARM_h
-#include <wtf/Platform.h>
-
#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
#include "ARMAssembler.h"
@@ -180,6 +178,20 @@ public:
{
m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
}
+
+ void urshift32(RegisterID shift_amount, RegisterID dest)
+ {
+ ARMWord w = ARMAssembler::getOp2(0x1f);
+ ASSERT(w != ARMAssembler::INVALID_IMM);
+ m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
+
+ m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0));
+ }
+
+ void urshift32(Imm32 imm, RegisterID dest)
+ {
+ m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
+ }
void sub32(RegisterID src, RegisterID dest)
{
@@ -214,6 +226,11 @@ public:
m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
+ void load8(ImplicitAddress address, RegisterID dest)
+ {
+ m_assembler.dataTransfer32(true, dest, address.base, address.offset, true);
+ }
+
void load32(ImplicitAddress address, RegisterID dest)
{
m_assembler.dataTransfer32(true, dest, address.base, address.offset);
@@ -256,6 +273,14 @@ public:
else
m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
}
+
+ void load16(ImplicitAddress address, RegisterID dest)
+ {
+ if (address.offset >= 0)
+ m_assembler.ldrh_u(dest, address.base, ARMAssembler::getOp2Byte(address.offset));
+ else
+ m_assembler.ldrh_d(dest, address.base, ARMAssembler::getOp2Byte(-address.offset));
+ }
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
{
@@ -359,6 +384,12 @@ public:
move(src, dest);
}
+ Jump branch8(Condition cond, Address left, Imm32 right)
+ {
+ load8(left, ARMRegisters::S1);
+ return branch32(cond, ARMRegisters::S1, right);
+ }
+
Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
{
m_assembler.cmp_r(left, right);
@@ -422,6 +453,12 @@ public:
return m_assembler.jmp(ARMCondition(cond));
}
+ Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+ {
+ load8(address, ARMRegisters::S1);
+ return branchTest32(cond, ARMRegisters::S1, mask);
+ }
+
Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
{
ASSERT((cond == Zero) || (cond == NonZero));
@@ -459,7 +496,7 @@ public:
void jump(RegisterID target)
{
- move(target, ARMRegisters::pc);
+ m_assembler.bx(target);
}
void jump(Address address)
@@ -530,6 +567,13 @@ public:
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
+ Jump branchNeg32(Condition cond, RegisterID srcDest)
+ {
+ ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+ neg32(srcDest);
+ return Jump(m_assembler.jmp(ARMCondition(cond)));
+ }
+
Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
{
ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -544,14 +588,19 @@ public:
Call nearCall()
{
+#if WTF_ARM_ARCH_AT_LEAST(5)
+ ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
+ m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
+ return Call(m_assembler.blx(ARMRegisters::S1), Call::LinkableNear);
+#else
prepareCall();
return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear);
+#endif
}
Call call(RegisterID target)
{
- prepareCall();
- move(ARMRegisters::pc, target);
+ m_assembler.blx(target);
JmpSrc jmpSrc;
return Call(jmpSrc, Call::None);
}
@@ -563,7 +612,7 @@ public:
void ret()
{
- m_assembler.mov_r(ARMRegisters::pc, linkRegister);
+ m_assembler.bx(linkRegister);
}
void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
@@ -659,8 +708,14 @@ public:
Call call()
{
+#if WTF_ARM_ARCH_AT_LEAST(5)
+ ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
+ m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
+ return Call(m_assembler.blx(ARMRegisters::S1), Call::Linkable);
+#else
prepareCall();
return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable);
+#endif
}
Call tailRecursiveCall()
@@ -718,12 +773,17 @@ public:
return false;
}
+ bool supportsFloatingPointSqrt() const
+ {
+ return s_isVFPPresent;
+ }
+
void loadDouble(ImplicitAddress address, FPRegisterID dest)
{
m_assembler.doubleTransfer(true, dest, address.base, address.offset);
}
- void loadDouble(void* address, FPRegisterID dest)
+ void loadDouble(const void* address, FPRegisterID dest)
{
m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
@@ -779,6 +839,11 @@ public:
mulDouble(ARMRegisters::SD0, dest);
}
+ void sqrtDouble(FPRegisterID src, FPRegisterID dest)
+ {
+ m_assembler.fsqrtd_r(dest, src);
+ }
+
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.fmsr_r(dest, src);
@@ -864,44 +929,56 @@ protected:
void prepareCall()
{
+#if WTF_ARM_ARCH_VERSION < 5
ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
m_assembler.mov_r(linkRegister, ARMRegisters::pc);
+#endif
}
void call32(RegisterID base, int32_t offset)
{
+#if WTF_ARM_ARCH_AT_LEAST(5)
+ int targetReg = ARMRegisters::S1;
+#else
+ int targetReg = ARMRegisters::pc;
+#endif
+ int tmpReg = ARMRegisters::S1;
+
if (base == ARMRegisters::sp)
offset += 4;
if (offset >= 0) {
if (offset <= 0xfff) {
prepareCall();
- m_assembler.dtr_u(true, ARMRegisters::pc, base, offset);
+ m_assembler.dtr_u(true, targetReg, base, offset);
} else if (offset <= 0xfffff) {
- m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
+ m_assembler.add_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
prepareCall();
- m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
+ m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
} else {
- ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
+ ARMWord reg = m_assembler.getImm(offset, tmpReg);
prepareCall();
- m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg);
+ m_assembler.dtr_ur(true, targetReg, base, reg);
}
} else {
offset = -offset;
if (offset <= 0xfff) {
prepareCall();
- m_assembler.dtr_d(true, ARMRegisters::pc, base, offset);
+ m_assembler.dtr_d(true, targetReg, base, offset);
} else if (offset <= 0xfffff) {
- m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
+ m_assembler.sub_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
prepareCall();
- m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
+ m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
} else {
- ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
+ ARMWord reg = m_assembler.getImm(offset, tmpReg);
prepareCall();
- m_assembler.dtr_dr(true, ARMRegisters::pc, base, reg);
+ m_assembler.dtr_dr(true, targetReg, base, reg);
}
}
+#if WTF_ARM_ARCH_AT_LEAST(5)
+ m_assembler.blx(targetReg);
+#endif
}
private: