Back out Yarr until I can unbreak ARM build. (r=red)

This commit is contained in:
Chris Leary 2010-07-03 01:54:21 -07:00
parent cd014beba1
commit 7d5b8294f0
7 changed files with 81 additions and 442 deletions

View File

@ -278,13 +278,13 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas
} else {
offset = -offset;
if (offset <= 0xfff)
dtr_d(isLoad, srcDst, base, offset | transferFlag);
dtr_d(isLoad, srcDst, base, offset);
else if (offset <= 0xfffff) {
sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag);
dtr_d(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
} else {
ARMWord reg = getImm(offset, ARMRegisters::S0);
dtr_dr(isLoad, srcDst, base, reg | transferFlag);
dtr_dr(isLoad, srcDst, base, reg);
}
}
}
@ -356,17 +356,10 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator)
// The last bit is set if the constant must be placed on constant pool.
int pos = (*iter) & (~0x1);
ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
ARMWord* addr = getLdrImmAddress(ldrAddr);
if (*addr != InvalidBranchTarget) {
if (!(*iter & 1)) {
int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
*ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK);
continue;
}
}
*addr = reinterpret_cast<ARMWord>(data + *addr);
ARMWord offset = *getLdrImmAddress(ldrAddr);
if (offset != 0xffffffff) {
JmpSrc jmpSrc(pos);
linkBranch(data, jmpSrc, data + offset, ((*iter) & 1));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009, 2010 University of Szeged
* Copyright (C) 2009 University of Szeged
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -37,6 +37,7 @@
#include "AssemblerBufferWithConstantPool.h"
#include "assembler/wtf/Assertions.h"
#define IPFX " "
namespace JSC {
@ -73,46 +74,13 @@ namespace JSC {
d1,
d2,
d3,
SD0 = d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
d16,
d17,
d18,
d19,
d20,
d21,
d22,
d23,
d24,
d25,
d26,
d27,
d28,
d29,
d30,
d31
SD0 = d3
} FPRegisterID;
} // namespace ARMRegisters
class ARMAssembler {
public:
#ifdef DEBUG
bool isOOLPath;
#endif
typedef ARMRegisters::RegisterID RegisterID;
typedef ARMRegisters::FPRegisterID FPRegisterID;
typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
@ -120,8 +88,6 @@ namespace JSC {
ARMAssembler() { }
unsigned char *buffer() const { return m_buffer.buffer(); }
// ARM conditional constants
typedef enum {
EQ = 0x00000000, // Zero
@ -162,12 +128,10 @@ namespace JSC {
MUL = 0x00000090,
MULL = 0x00c00090,
FADDD = 0x0e300b00,
FNEGD = 0x0eb10b40,
FDIVD = 0x0e800b00,
FSUBD = 0x0e300b40,
FMULD = 0x0e200b00,
FCMPD = 0x0eb40b40,
FSQRTD = 0x0eb10bc0,
DTR = 0x05000000,
LDRH = 0x00100090,
STRH = 0x00000090,
@ -175,11 +139,11 @@ namespace JSC {
LDMIA = 0x08b00000,
FDTR = 0x0d000b00,
B = 0x0a000000,
BL = 0x0b000000
#if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
,BX = 0x012fff10
BL = 0x0b000000,
#ifndef __ARM_ARCH_4__
BX = 0x012fff10, // Only on ARMv4T+!
#endif
,FMSR = 0x0e000a10,
FMSR = 0x0e000a10,
FMRS = 0x0e100a10,
FSITOD = 0x0eb80bc0,
FTOSID = 0x0ebd0b40,
@ -187,7 +151,7 @@ namespace JSC {
#if WTF_ARM_ARCH_VERSION >= 5
,CLZ = 0x016f0f10,
BKPT = 0xe120070,
BLX = 0x012fff30
BLX_R = 0x012fff30
#endif
#if WTF_ARM_ARCH_VERSION >= 7
,MOVW = 0x03000000,
@ -202,7 +166,6 @@ namespace JSC {
SET_CC = (1 << 20),
OP2_OFSREG = (1 << 25),
DT_UP = (1 << 23),
DT_BYTE = (1 << 22),
DT_WB = (1 << 21),
// This flag is inlcuded in LDR and STR
DT_PRE = (1 << 24),
@ -238,8 +201,6 @@ namespace JSC {
} Shift;
static const ARMWord INVALID_IMM = 0xf0000000;
static const ARMWord InvalidBranchTarget = 0xffffffff;
static const int DefaultPrefetching = 2;
class JmpSrc {
friend class ARMAssembler;
@ -485,36 +446,34 @@ namespace JSC {
void faddd_r(int dd, int dn, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
}
void fdivd_r(int dd, int dn, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm);
}
void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
}
void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
}
void fcmpd_r(int dd, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
}
void fsqrtd_r(int dd, int dm, Condition cc = AL)
{
// TODO: emitInst doesn't work for VFP instructions, though it
// seems to work for current usage.
emitInst(static_cast<ARMWord>(cc) | FSQRTD, dd, 0, dm);
}
void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
{
char mnemonic[16];
@ -587,12 +546,14 @@ namespace JSC {
void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
{
FIXME_INSN_PRINTING;
ASSERT(op2 <= 0xff);
emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2);
}
void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
{
FIXME_INSN_PRINTING;
ASSERT(op2 <= 0xff);
emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
}
@ -621,26 +582,31 @@ namespace JSC {
void fmsr_r(int dd, int rn, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
}
void fmrs_r(int rd, int dn, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0);
}
void fsitod_r(int dd, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
}
void ftosid_r(int fd, int dm, Condition cc = AL)
{
FIXME_INSN_PRINTING;
emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
}
void fmstat(Condition cc = AL)
{
FIXME_INSN_PRINTING;
m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
}
@ -662,28 +628,37 @@ namespace JSC {
#endif
}
void bx(int rm, Condition cc = AL)
// BX is emitted where possible, or an equivalent sequence on ARMv4.
void bx_r(int rm, Condition cc = AL)
{
#if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm));
#else
mov_r(ARMRegisters::pc, RM(rm), cc);
#if (WTF_ARM_ARCH_VERSION >= 5) || defined(__ARM_ARCH_4T__)
// ARMv4T+ has BX <reg>.
m_buffer.putInt(static_cast<ARMWord>(cc) | BX | RM(rm));
#else // defined(__ARM_ARCH_4__)
// ARMv4 has to do "MOV pc, rm". This works on newer architectures
// too, but breaks return stack prediction and doesn't interwork on
// ARMv4T, so this becomes a special case of ARMv4.
mov_r(ARMRegisters::pc, rm, cc);
#endif
}
JmpSrc blx(int rm, Condition cc = AL)
// BLX is emitted where possible, or an equivalent (slower) sequence on
// ARMv4 or ARMv4T.
void blx_r(int rm, Condition cc = AL)
{
#if WTF_ARM_ARCH_AT_LEAST(5)
int s = m_buffer.uncheckedSize();
emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm));
#else
ASSERT((rm >= 0) && (rm <= 14));
#if WTF_ARM_ARCH_VERSION >= 5
// ARMv5+ is the ideal (fast) case, and can use a proper "BLX rm".
m_buffer.putInt(static_cast<ARMWord>(cc) | BLX_R | RM(rm));
#else // defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
// ARMv4T must do "MOV lr, pc; BX rm".
// ARMv4 must do "MOV lr, pc; MOV pc, rm".
// Both cases are handled here and by bx_r.
ASSERT(rm != 14);
ensureSpace(2 * sizeof(ARMWord), 0);
mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
int s = m_buffer.uncheckedSize();
bx(rm, cc);
bx_r(rm, cc);
#endif
return JmpSrc(s);
}
static ARMWord lsl(int reg, ARMWord value)
@ -762,7 +737,7 @@ namespace JSC {
{
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
int s = m_buffer.uncheckedSize();
ldr_un_imm(rd, InvalidBranchTarget, cc);
ldr_un_imm(rd, 0xffffffff, cc);
m_jumps.append(s | (useConstantPool & 0x1));
return JmpSrc(s);
}
@ -776,40 +751,15 @@ namespace JSC {
// Patching helpers
static ARMWord* getLdrImmAddress(ARMWord* insn)
{
#if WTF_ARM_ARCH_AT_LEAST(5)
// Check for call
if ((*insn & 0x0f7f0000) != 0x051f0000) {
// Must be BLX
ASSERT((*insn & 0x012fff30) == 0x012fff30);
insn--;
}
#endif
// Must be an ldr ..., [pc +/- imm]
ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord);
if (*insn & DT_UP)
return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK));
return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK));
}
static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool)
{
// Must be an ldr ..., [pc +/- imm]
ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
if (*insn & 0x1)
return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1));
return getLdrImmAddress(insn);
}
static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0);
static void patchPointerInternal(intptr_t from, void* to)
{
ARMWord* insn = reinterpret_cast<ARMWord*>(from);
ARMWord* addr = getLdrImmAddress(insn);
*addr = reinterpret_cast<ARMWord>(to);
ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord));
}
static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
@ -866,13 +816,12 @@ namespace JSC {
void linkJump(JmpSrc from, JmpDst to)
{
ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
*addr = static_cast<ARMWord>(to.m_offset);
*getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset);
}
static void linkJump(void* code, JmpSrc from, void* to)
{
patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
linkBranch(code, from, to);
}
static void relinkJump(void* from, void* to)
@ -882,12 +831,12 @@ namespace JSC {
static void linkCall(void* code, JmpSrc from, void* to)
{
patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
linkBranch(code, from, to, true);
}
static void relinkCall(void* from, void* to)
{
patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
relinkJump(from, to);
}
// Address operations
@ -941,18 +890,9 @@ namespace JSC {
void moveImm(ARMWord imm, int dest);
ARMWord encodeComplexImm(ARMWord imm, int dest);
ARMWord getOffsetForHalfwordDataTransfer(ARMWord imm, int tmpReg)
{
// Encode immediate data in the instruction if it is possible
if (imm <= 0xff)
return getOp2Byte(imm);
// Otherwise, store the data in a temporary register
return encodeComplexImm(imm, tmpReg);
}
// Memory load/store helpers
void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false);
void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset);
void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset);
void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
@ -979,23 +919,6 @@ namespace JSC {
return names[reg];
}
static char const * nameFpRegD(int reg)
{
ASSERT(reg <= 31);
ASSERT(reg >= 0);
static char const * names[] = {
"d0", "d1", "d2", "d3",
"d4", "d5", "d6", "d7",
"d8", "d9", "d10", "d11",
"d12", "d13", "d14", "d15",
"d16", "d17", "d18", "d19",
"d20", "d21", "d22", "d23",
"d24", "d25", "d26", "d27",
"d28", "d29", "d30", "d31"
};
return names[reg];
}
static char const * nameCC(Condition cc)
{
ASSERT(cc <= AL);
@ -1123,27 +1046,6 @@ namespace JSC {
return reg << 16;
}
ARMWord DD(int reg)
{
ASSERT(reg <= ARMRegisters::d31);
// Endoded as bits [22,15:12].
return ((reg << 12) | (reg << 18)) & 0x0040f000;
}
ARMWord DN(int reg)
{
ASSERT(reg <= ARMRegisters::d31);
// Endoded as bits [7,19:16].
return ((reg << 16) | (reg << 3)) & 0x000f0080;
}
ARMWord DM(int reg)
{
ASSERT(reg <= ARMRegisters::d31);
// Encoded as bits [5,3:0].
return ((reg << 1) & 0x20) | (reg & 0xf);
}
static ARMWord getConditionalField(ARMWord i)
{
return i & 0xf0000000;

View File

@ -1,6 +1,5 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 University of Szeged
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -34,7 +33,6 @@
#include "AssemblerBuffer.h"
#include "assembler/wtf/Assertions.h"
#include "assembler/wtf/Vector.h"
#include <stdint.h>
namespace JSC {
@ -583,13 +581,11 @@ private:
OP_MOV_reg_T1 = 0x4600,
OP_BLX = 0x4700,
OP_BX = 0x4700,
OP_LDRH_reg_T1 = 0x5A00,
OP_STR_reg_T1 = 0x5000,
OP_LDR_reg_T1 = 0x5800,
OP_LDRH_reg_T1 = 0x5A00,
OP_LDRB_reg_T1 = 0x5C00,
OP_STR_imm_T1 = 0x6000,
OP_LDR_imm_T1 = 0x6800,
OP_LDRB_imm_T1 = 0x7800,
OP_LDRH_imm_T1 = 0x8800,
OP_STR_imm_T2 = 0x9000,
OP_LDR_imm_T2 = 0x9800,
@ -634,15 +630,12 @@ private:
OP_SUB_imm_T4 = 0xF2A0,
OP_MOVT = 0xF2C0,
OP_NOP_T2a = 0xF3AF,
OP_LDRB_imm_T3 = 0xF810,
OP_LDRB_reg_T2 = 0xF810,
OP_LDRH_reg_T2 = 0xF830,
OP_LDRH_imm_T3 = 0xF830,
OP_STR_imm_T4 = 0xF840,
OP_STR_reg_T2 = 0xF840,
OP_LDR_imm_T4 = 0xF850,
OP_LDR_reg_T2 = 0xF850,
OP_LDRB_imm_T2 = 0xF890,
OP_LDRH_imm_T2 = 0xF8B0,
OP_STR_imm_T3 = 0xF8C0,
OP_LDR_imm_T3 = 0xF8D0,
@ -1086,52 +1079,6 @@ public:
m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
}
void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
{
ASSERT(rn != ARMRegisters::pc); // LDR (literal)
ASSERT(imm.isUInt12());
if (!((rt | rn) & 8) && imm.isUInt5())
m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt);
else
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12());
}
void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
{
ASSERT(rt != ARMRegisters::pc);
ASSERT(rn != ARMRegisters::pc);
ASSERT(index || wback);
ASSERT(!wback | (rt != rn));
bool add = true;
if (offset < 0) {
add = false;
offset = -offset;
}
ASSERT(!(offset & ~0xff));
offset |= (wback << 8);
offset |= (add << 9);
offset |= (index << 10);
offset |= (1 << 11);
m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
}
void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
{
ASSERT(rn != ARMRegisters::pc); // LDR (literal)
ASSERT(!BadReg(rm));
ASSERT(shift <= 3);
if (!shift && !((rt | rn | rm) & 8))
m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt);
else
m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
}
void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
{
ASSERT(!BadReg(rd));
@ -1770,20 +1717,7 @@ private:
|| (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
// From Cortex-A8 errata:
// If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
// the target of the branch falls within the first region it is
// possible for the processor to incorrectly determine the branch
// instruction, and it is also possible in some cases for the processor
// to enter a deadlock state.
// The instruction is spanning two pages if it ends at an address ending 0x002
bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
// The target is in the first page if the jump branch back by [3..0x1002] bytes
bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
if (((relative << 7) >> 7) == relative && !wouldTriggerA8Errata) {
if (((relative << 7) >> 7) == relative) {
// ARM encoding for the top two bits below the sign bit is 'peculiar'.
if (relative >= 0)
relative ^= 0xC00000;

View File

@ -53,12 +53,6 @@ public:
typedef typename AssemblerType::JmpSrc JmpSrc;
typedef typename AssemblerType::JmpDst JmpDst;
#ifdef DEBUG
void setSpewPath(bool isOOLPath)
{
m_assembler.isOOLPath = isOOLPath;
}
#endif
// Section 1: MacroAssembler operand types
//

View File

@ -187,20 +187,6 @@ 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)
{
@ -241,17 +227,6 @@ public:
m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
}
void xor32(Address src, RegisterID dest)
{
load32(src, ARMRegisters::S1);
m_assembler.eors_r(dest, dest, ARMRegisters::S1);
}
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);
@ -288,16 +263,11 @@ public:
void load16(BaseIndex address, RegisterID dest)
{
m_assembler.add_r(ARMRegisters::S1, address.base, m_assembler.lsl(address.index, address.scale));
load16(Address(ARMRegisters::S1, address.offset), dest);
}
void load16(ImplicitAddress address, RegisterID dest)
{
if (address.offset >= 0)
m_assembler.ldrh_u(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(address.offset, ARMRegisters::S0));
m_assembler.add_r(ARMRegisters::S0, address.base, m_assembler.lsl(address.index, address.scale));
if (address.offset>=0)
m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
else
m_assembler.ldrh_d(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(-address.offset, ARMRegisters::S0));
m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
}
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
@ -411,12 +381,6 @@ 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);
@ -480,12 +444,6 @@ 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));
@ -523,7 +481,7 @@ public:
void jump(RegisterID target)
{
m_assembler.bx(target);
m_assembler.bx_r(target);
}
void jump(Address address)
@ -545,13 +503,6 @@ public:
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
Jump branchAdd32(Condition cond, Address src, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
add32(src, dest);
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
{
if (src1 == dest) {
@ -601,20 +552,6 @@ public:
return Jump(m_assembler.jmp(ARMCondition(cond)));
}
Jump branchSub32(Condition cond, Address src, RegisterID dest)
{
ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
sub32(src, dest);
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));
@ -631,7 +568,7 @@ public:
{
#if WTF_ARM_ARCH_VERSION >= 5
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::LinkableNear);
m_assembler.blx(ARMRegisters::S1);
m_assembler.blx_r(ARMRegisters::S1);
return call;
#else
prepareCall();
@ -641,7 +578,7 @@ public:
Call call(RegisterID target)
{
m_assembler.blx(target);
m_assembler.blx_r(target);
JmpSrc jmpSrc;
return Call(jmpSrc, Call::None);
}
@ -653,7 +590,7 @@ public:
void ret()
{
m_assembler.bx(linkRegister);
m_assembler.bx_r(linkRegister);
}
void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
@ -682,12 +619,6 @@ public:
m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
}
void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
{
load32(left, ARMRegisters::S1);
set32(cond, ARMRegisters::S1, right, dest);
}
void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
{
// ARM doesn't have byte registers
@ -786,7 +717,7 @@ public:
{
#if WTF_ARM_ARCH_VERSION >= 5
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::Linkable);
m_assembler.blx(ARMRegisters::S1);
m_assembler.blx_r(ARMRegisters::S1);
return call;
#else
prepareCall();
@ -849,17 +780,12 @@ 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(const void* address, FPRegisterID dest)
void loadDouble(void* address, FPRegisterID dest)
{
m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
@ -915,16 +841,6 @@ public:
mulDouble(ARMRegisters::SD0, dest);
}
void negDouble(FPRegisterID src, FPRegisterID dest)
{
m_assembler.fnegd_r(dest, src);
}
void sqrtDouble(FPRegisterID src, FPRegisterID dest)
{
m_assembler.fsqrtd_r(dest, src);
}
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.fmsr_r(dest, src);
@ -1011,58 +927,46 @@ protected:
#if WTF_ARM_ARCH_VERSION < 5
void prepareCall()
{
#if WTF_ARM_ARCH_VERSION < 5
ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
m_assembler.mov_r(linkRegister, ARMRegisters::pc);
#endif
}
#endif
#if WTF_ARM_ARCH_VERSION < 5
void call32(RegisterID base, int32_t offset)
{
#if WTF_ARM_ARCH_VERSION >= 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, targetReg, base, offset);
m_assembler.dtr_u(true, ARMRegisters::pc, base, offset);
} else if (offset <= 0xfffff) {
m_assembler.add_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
prepareCall();
m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
} else {
ARMWord reg = m_assembler.getImm(offset, tmpReg);
ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
prepareCall();
m_assembler.dtr_ur(true, targetReg, base, reg);
m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg);
}
} else {
offset = -offset;
if (offset <= 0xfff) {
prepareCall();
m_assembler.dtr_d(true, targetReg, base, offset);
m_assembler.dtr_d(true, ARMRegisters::pc, base, offset);
} else if (offset <= 0xfffff) {
m_assembler.sub_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
prepareCall();
m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
} else {
ARMWord reg = m_assembler.getImm(offset, tmpReg);
ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
prepareCall();
m_assembler.dtr_dr(true, targetReg, base, reg);
m_assembler.dtr_dr(true, ARMRegisters::pc, base, reg);
}
}
#if WTF_ARM_ARCH_VERSION >= 5
m_assembler.blx(targetReg);
#endif
}
#else
void call32(RegisterID base, int32_t offset)
@ -1107,7 +1011,7 @@ protected:
m_assembler.dtr_dr(true, ARMRegisters::S0, base, reg);
}
}
m_assembler.blx(ARMRegisters::S0);
m_assembler.blx_r(ARMRegisters::S0);
}
#endif

View File

@ -259,21 +259,6 @@ public:
{
m_assembler.asr(dest, dest, imm.m_value & 0x1f);
}
void urshift32(RegisterID shift_amount, RegisterID dest)
{
// Clamp the shift to the range 0..31
ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
ASSERT(armImm.isValid());
m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
m_assembler.lsr(dest, dest, dataTempRegister);
}
void urshift32(Imm32 imm, RegisterID dest)
{
m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
}
void sub32(RegisterID src, RegisterID dest)
{
@ -384,20 +369,6 @@ private:
}
}
void load8(ArmAddress address, RegisterID dest)
{
if (address.type == ArmAddress::HasIndex)
m_assembler.ldrb(dest, address.base, address.u.index, address.u.scale);
else if (address.u.offset >= 0) {
ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
ASSERT(armImm.isValid());
m_assembler.ldrb(dest, address.base, armImm);
} else {
ASSERT(address.u.offset >= -255);
m_assembler.ldrb(dest, address.base, address.u.offset, true, false);
}
}
void store32(RegisterID src, ArmAddress address)
{
if (address.type == ArmAddress::HasIndex)
@ -434,11 +405,6 @@ public:
m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
}
void load8(ImplicitAddress address, RegisterID dest)
{
load8(setupArmAddress(address), dest);
}
DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
{
DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
@ -458,11 +424,6 @@ public:
{
m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
}
void load16(ImplicitAddress address, RegisterID dest)
{
m_assembler.ldrh(dest, address.base, address.offset);
}
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
{
@ -516,11 +477,6 @@ public:
// In short, FIXME:.
bool supportsFloatingPointTruncate() const { return false; }
bool supportsFloatingPointSqrt() const
{
return false;
}
void loadDouble(ImplicitAddress address, FPRegisterID dest)
{
RegisterID base = address.base;
@ -584,11 +540,6 @@ public:
mulDouble(fpTempRegister, dest);
}
void sqrtDouble(FPRegisterID, FPRegisterID)
{
ASSERT_NOT_REACHED();
}
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.vmov(fpTempRegister, src);
@ -843,19 +794,6 @@ public:
return branch32(cond, addressTempRegister, Imm32(right.m_value << 16));
}
Jump branch8(Condition cond, RegisterID left, Imm32 right)
{
compare32(left, right);
return Jump(makeBranch(cond));
}
Jump branch8(Condition cond, Address left, Imm32 right)
{
// use addressTempRegister incase the branch8 we call uses dataTempRegister. :-/
load8(left, addressTempRegister);
return branch8(cond, addressTempRegister, right);
}
Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
{
ASSERT((cond == Zero) || (cond == NonZero));
@ -886,21 +824,6 @@ public:
return branchTest32(cond, addressTempRegister, mask);
}
Jump branchTest8(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
{
ASSERT((cond == Zero) || (cond == NonZero));
test32(reg, mask);
return Jump(makeBranch(cond));
}
Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
{
ASSERT((cond == Zero) || (cond == NonZero));
// use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
load8(address, addressTempRegister);
return branchTest8(cond, addressTempRegister, mask);
}
Jump jump()
{
return Jump(makeJump());
@ -1051,14 +974,6 @@ public:
m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
}
void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
{
load8(address, dataTempRegister);
test32(dataTempRegister, mask);
m_assembler.it(armV7Condition(cond), false);
m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1));
m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
}
DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst)
{

View File

@ -69,6 +69,3 @@ private:
};
} // namespace JSC
#endif /* _include_assembler_moco_stubs_h_ */