зеркало из https://github.com/mozilla/gecko-dev.git
Back out Yarr until I can unbreak ARM build. (r=red)
This commit is contained in:
Родитель
cd014beba1
Коммит
7d5b8294f0
|
@ -278,13 +278,13 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas
|
||||||
} else {
|
} else {
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
if (offset <= 0xfff)
|
if (offset <= 0xfff)
|
||||||
dtr_d(isLoad, srcDst, base, offset | transferFlag);
|
dtr_d(isLoad, srcDst, base, offset);
|
||||||
else if (offset <= 0xfffff) {
|
else if (offset <= 0xfffff) {
|
||||||
sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
|
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 {
|
} else {
|
||||||
ARMWord reg = getImm(offset, ARMRegisters::S0);
|
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.
|
// The last bit is set if the constant must be placed on constant pool.
|
||||||
int pos = (*iter) & (~0x1);
|
int pos = (*iter) & (~0x1);
|
||||||
ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
|
ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
|
||||||
ARMWord* addr = getLdrImmAddress(ldrAddr);
|
ARMWord offset = *getLdrImmAddress(ldrAddr);
|
||||||
if (*addr != InvalidBranchTarget) {
|
if (offset != 0xffffffff) {
|
||||||
if (!(*iter & 1)) {
|
JmpSrc jmpSrc(pos);
|
||||||
int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
|
linkBranch(data, jmpSrc, data + offset, ((*iter) & 1));
|
||||||
|
|
||||||
if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
|
|
||||||
*ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*addr = reinterpret_cast<ARMWord>(data + *addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009, 2010 University of Szeged
|
* Copyright (C) 2009 University of Szeged
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
#include "AssemblerBufferWithConstantPool.h"
|
#include "AssemblerBufferWithConstantPool.h"
|
||||||
#include "assembler/wtf/Assertions.h"
|
#include "assembler/wtf/Assertions.h"
|
||||||
|
|
||||||
|
#define IPFX " "
|
||||||
|
|
||||||
namespace JSC {
|
namespace JSC {
|
||||||
|
|
||||||
|
@ -73,46 +74,13 @@ namespace JSC {
|
||||||
d1,
|
d1,
|
||||||
d2,
|
d2,
|
||||||
d3,
|
d3,
|
||||||
SD0 = 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
|
|
||||||
} FPRegisterID;
|
} FPRegisterID;
|
||||||
|
|
||||||
} // namespace ARMRegisters
|
} // namespace ARMRegisters
|
||||||
|
|
||||||
class ARMAssembler {
|
class ARMAssembler {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
bool isOOLPath;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef ARMRegisters::RegisterID RegisterID;
|
typedef ARMRegisters::RegisterID RegisterID;
|
||||||
typedef ARMRegisters::FPRegisterID FPRegisterID;
|
typedef ARMRegisters::FPRegisterID FPRegisterID;
|
||||||
typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
|
typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
|
||||||
|
@ -120,8 +88,6 @@ namespace JSC {
|
||||||
|
|
||||||
ARMAssembler() { }
|
ARMAssembler() { }
|
||||||
|
|
||||||
unsigned char *buffer() const { return m_buffer.buffer(); }
|
|
||||||
|
|
||||||
// ARM conditional constants
|
// ARM conditional constants
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EQ = 0x00000000, // Zero
|
EQ = 0x00000000, // Zero
|
||||||
|
@ -162,12 +128,10 @@ namespace JSC {
|
||||||
MUL = 0x00000090,
|
MUL = 0x00000090,
|
||||||
MULL = 0x00c00090,
|
MULL = 0x00c00090,
|
||||||
FADDD = 0x0e300b00,
|
FADDD = 0x0e300b00,
|
||||||
FNEGD = 0x0eb10b40,
|
|
||||||
FDIVD = 0x0e800b00,
|
FDIVD = 0x0e800b00,
|
||||||
FSUBD = 0x0e300b40,
|
FSUBD = 0x0e300b40,
|
||||||
FMULD = 0x0e200b00,
|
FMULD = 0x0e200b00,
|
||||||
FCMPD = 0x0eb40b40,
|
FCMPD = 0x0eb40b40,
|
||||||
FSQRTD = 0x0eb10bc0,
|
|
||||||
DTR = 0x05000000,
|
DTR = 0x05000000,
|
||||||
LDRH = 0x00100090,
|
LDRH = 0x00100090,
|
||||||
STRH = 0x00000090,
|
STRH = 0x00000090,
|
||||||
|
@ -175,11 +139,11 @@ namespace JSC {
|
||||||
LDMIA = 0x08b00000,
|
LDMIA = 0x08b00000,
|
||||||
FDTR = 0x0d000b00,
|
FDTR = 0x0d000b00,
|
||||||
B = 0x0a000000,
|
B = 0x0a000000,
|
||||||
BL = 0x0b000000
|
BL = 0x0b000000,
|
||||||
#if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
|
#ifndef __ARM_ARCH_4__
|
||||||
,BX = 0x012fff10
|
BX = 0x012fff10, // Only on ARMv4T+!
|
||||||
#endif
|
#endif
|
||||||
,FMSR = 0x0e000a10,
|
FMSR = 0x0e000a10,
|
||||||
FMRS = 0x0e100a10,
|
FMRS = 0x0e100a10,
|
||||||
FSITOD = 0x0eb80bc0,
|
FSITOD = 0x0eb80bc0,
|
||||||
FTOSID = 0x0ebd0b40,
|
FTOSID = 0x0ebd0b40,
|
||||||
|
@ -187,7 +151,7 @@ namespace JSC {
|
||||||
#if WTF_ARM_ARCH_VERSION >= 5
|
#if WTF_ARM_ARCH_VERSION >= 5
|
||||||
,CLZ = 0x016f0f10,
|
,CLZ = 0x016f0f10,
|
||||||
BKPT = 0xe120070,
|
BKPT = 0xe120070,
|
||||||
BLX = 0x012fff30
|
BLX_R = 0x012fff30
|
||||||
#endif
|
#endif
|
||||||
#if WTF_ARM_ARCH_VERSION >= 7
|
#if WTF_ARM_ARCH_VERSION >= 7
|
||||||
,MOVW = 0x03000000,
|
,MOVW = 0x03000000,
|
||||||
|
@ -202,7 +166,6 @@ namespace JSC {
|
||||||
SET_CC = (1 << 20),
|
SET_CC = (1 << 20),
|
||||||
OP2_OFSREG = (1 << 25),
|
OP2_OFSREG = (1 << 25),
|
||||||
DT_UP = (1 << 23),
|
DT_UP = (1 << 23),
|
||||||
DT_BYTE = (1 << 22),
|
|
||||||
DT_WB = (1 << 21),
|
DT_WB = (1 << 21),
|
||||||
// This flag is inlcuded in LDR and STR
|
// This flag is inlcuded in LDR and STR
|
||||||
DT_PRE = (1 << 24),
|
DT_PRE = (1 << 24),
|
||||||
|
@ -238,8 +201,6 @@ namespace JSC {
|
||||||
} Shift;
|
} Shift;
|
||||||
|
|
||||||
static const ARMWord INVALID_IMM = 0xf0000000;
|
static const ARMWord INVALID_IMM = 0xf0000000;
|
||||||
static const ARMWord InvalidBranchTarget = 0xffffffff;
|
|
||||||
static const int DefaultPrefetching = 2;
|
|
||||||
|
|
||||||
class JmpSrc {
|
class JmpSrc {
|
||||||
friend class ARMAssembler;
|
friend class ARMAssembler;
|
||||||
|
@ -485,36 +446,34 @@ namespace JSC {
|
||||||
|
|
||||||
void faddd_r(int dd, int dn, int dm, Condition cc = AL)
|
void faddd_r(int dd, int dn, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
|
emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fdivd_r(int dd, int dn, int dm, Condition cc = AL)
|
void fdivd_r(int dd, int dn, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm);
|
emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
|
void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
|
emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
|
void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
|
emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fcmpd_r(int dd, int dm, Condition cc = AL)
|
void fcmpd_r(int dd, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
|
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)
|
void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
char mnemonic[16];
|
char mnemonic[16];
|
||||||
|
@ -587,12 +546,14 @@ namespace JSC {
|
||||||
|
|
||||||
void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
|
void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
ASSERT(op2 <= 0xff);
|
ASSERT(op2 <= 0xff);
|
||||||
emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2);
|
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)
|
void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
ASSERT(op2 <= 0xff);
|
ASSERT(op2 <= 0xff);
|
||||||
emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
|
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)
|
void fmsr_r(int dd, int rn, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
|
emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fmrs_r(int rd, int dn, Condition cc = AL)
|
void fmrs_r(int rd, int dn, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0);
|
emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsitod_r(int dd, int dm, Condition cc = AL)
|
void fsitod_r(int dd, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
|
emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ftosid_r(int fd, int dm, Condition cc = AL)
|
void ftosid_r(int fd, int dm, Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
|
emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fmstat(Condition cc = AL)
|
void fmstat(Condition cc = AL)
|
||||||
{
|
{
|
||||||
|
FIXME_INSN_PRINTING;
|
||||||
m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
|
m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,28 +628,37 @@ namespace JSC {
|
||||||
#endif
|
#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__)
|
#if (WTF_ARM_ARCH_VERSION >= 5) || defined(__ARM_ARCH_4T__)
|
||||||
emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm));
|
// ARMv4T+ has BX <reg>.
|
||||||
#else
|
m_buffer.putInt(static_cast<ARMWord>(cc) | BX | RM(rm));
|
||||||
mov_r(ARMRegisters::pc, RM(rm), cc);
|
#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
|
#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)
|
ASSERT((rm >= 0) && (rm <= 14));
|
||||||
int s = m_buffer.uncheckedSize();
|
#if WTF_ARM_ARCH_VERSION >= 5
|
||||||
emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm));
|
// ARMv5+ is the ideal (fast) case, and can use a proper "BLX rm".
|
||||||
#else
|
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);
|
ASSERT(rm != 14);
|
||||||
ensureSpace(2 * sizeof(ARMWord), 0);
|
ensureSpace(2 * sizeof(ARMWord), 0);
|
||||||
mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
|
mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
|
||||||
int s = m_buffer.uncheckedSize();
|
bx_r(rm, cc);
|
||||||
bx(rm, cc);
|
|
||||||
#endif
|
#endif
|
||||||
return JmpSrc(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARMWord lsl(int reg, ARMWord value)
|
static ARMWord lsl(int reg, ARMWord value)
|
||||||
|
@ -762,7 +737,7 @@ namespace JSC {
|
||||||
{
|
{
|
||||||
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
|
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
|
||||||
int s = m_buffer.uncheckedSize();
|
int s = m_buffer.uncheckedSize();
|
||||||
ldr_un_imm(rd, InvalidBranchTarget, cc);
|
ldr_un_imm(rd, 0xffffffff, cc);
|
||||||
m_jumps.append(s | (useConstantPool & 0x1));
|
m_jumps.append(s | (useConstantPool & 0x1));
|
||||||
return JmpSrc(s);
|
return JmpSrc(s);
|
||||||
}
|
}
|
||||||
|
@ -776,40 +751,15 @@ namespace JSC {
|
||||||
|
|
||||||
// Patching helpers
|
// Patching helpers
|
||||||
|
|
||||||
static ARMWord* getLdrImmAddress(ARMWord* insn)
|
static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
|
||||||
{
|
static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0);
|
||||||
#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 void patchPointerInternal(intptr_t from, void* to)
|
static void patchPointerInternal(intptr_t from, void* to)
|
||||||
{
|
{
|
||||||
ARMWord* insn = reinterpret_cast<ARMWord*>(from);
|
ARMWord* insn = reinterpret_cast<ARMWord*>(from);
|
||||||
ARMWord* addr = getLdrImmAddress(insn);
|
ARMWord* addr = getLdrImmAddress(insn);
|
||||||
*addr = reinterpret_cast<ARMWord>(to);
|
*addr = reinterpret_cast<ARMWord>(to);
|
||||||
|
ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
|
static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
|
||||||
|
@ -866,13 +816,12 @@ namespace JSC {
|
||||||
void linkJump(JmpSrc from, JmpDst to)
|
void linkJump(JmpSrc from, JmpDst to)
|
||||||
{
|
{
|
||||||
ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
|
ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
|
||||||
ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
|
*getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset);
|
||||||
*addr = static_cast<ARMWord>(to.m_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linkJump(void* code, JmpSrc from, void* to)
|
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)
|
static void relinkJump(void* from, void* to)
|
||||||
|
@ -882,12 +831,12 @@ namespace JSC {
|
||||||
|
|
||||||
static void linkCall(void* code, JmpSrc from, void* to)
|
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)
|
static void relinkCall(void* from, void* to)
|
||||||
{
|
{
|
||||||
patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
|
relinkJump(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address operations
|
// Address operations
|
||||||
|
@ -941,18 +890,9 @@ namespace JSC {
|
||||||
void moveImm(ARMWord imm, int dest);
|
void moveImm(ARMWord imm, int dest);
|
||||||
ARMWord encodeComplexImm(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
|
// 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 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);
|
void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
|
||||||
|
|
||||||
|
@ -979,23 +919,6 @@ namespace JSC {
|
||||||
return names[reg];
|
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)
|
static char const * nameCC(Condition cc)
|
||||||
{
|
{
|
||||||
ASSERT(cc <= AL);
|
ASSERT(cc <= AL);
|
||||||
|
@ -1123,27 +1046,6 @@ namespace JSC {
|
||||||
return reg << 16;
|
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)
|
static ARMWord getConditionalField(ARMWord i)
|
||||||
{
|
{
|
||||||
return i & 0xf0000000;
|
return i & 0xf0000000;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 Apple Inc. All rights reserved.
|
* 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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -34,7 +33,6 @@
|
||||||
#include "AssemblerBuffer.h"
|
#include "AssemblerBuffer.h"
|
||||||
#include "assembler/wtf/Assertions.h"
|
#include "assembler/wtf/Assertions.h"
|
||||||
#include "assembler/wtf/Vector.h"
|
#include "assembler/wtf/Vector.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace JSC {
|
namespace JSC {
|
||||||
|
|
||||||
|
@ -583,13 +581,11 @@ private:
|
||||||
OP_MOV_reg_T1 = 0x4600,
|
OP_MOV_reg_T1 = 0x4600,
|
||||||
OP_BLX = 0x4700,
|
OP_BLX = 0x4700,
|
||||||
OP_BX = 0x4700,
|
OP_BX = 0x4700,
|
||||||
|
OP_LDRH_reg_T1 = 0x5A00,
|
||||||
OP_STR_reg_T1 = 0x5000,
|
OP_STR_reg_T1 = 0x5000,
|
||||||
OP_LDR_reg_T1 = 0x5800,
|
OP_LDR_reg_T1 = 0x5800,
|
||||||
OP_LDRH_reg_T1 = 0x5A00,
|
|
||||||
OP_LDRB_reg_T1 = 0x5C00,
|
|
||||||
OP_STR_imm_T1 = 0x6000,
|
OP_STR_imm_T1 = 0x6000,
|
||||||
OP_LDR_imm_T1 = 0x6800,
|
OP_LDR_imm_T1 = 0x6800,
|
||||||
OP_LDRB_imm_T1 = 0x7800,
|
|
||||||
OP_LDRH_imm_T1 = 0x8800,
|
OP_LDRH_imm_T1 = 0x8800,
|
||||||
OP_STR_imm_T2 = 0x9000,
|
OP_STR_imm_T2 = 0x9000,
|
||||||
OP_LDR_imm_T2 = 0x9800,
|
OP_LDR_imm_T2 = 0x9800,
|
||||||
|
@ -634,15 +630,12 @@ private:
|
||||||
OP_SUB_imm_T4 = 0xF2A0,
|
OP_SUB_imm_T4 = 0xF2A0,
|
||||||
OP_MOVT = 0xF2C0,
|
OP_MOVT = 0xF2C0,
|
||||||
OP_NOP_T2a = 0xF3AF,
|
OP_NOP_T2a = 0xF3AF,
|
||||||
OP_LDRB_imm_T3 = 0xF810,
|
|
||||||
OP_LDRB_reg_T2 = 0xF810,
|
|
||||||
OP_LDRH_reg_T2 = 0xF830,
|
OP_LDRH_reg_T2 = 0xF830,
|
||||||
OP_LDRH_imm_T3 = 0xF830,
|
OP_LDRH_imm_T3 = 0xF830,
|
||||||
OP_STR_imm_T4 = 0xF840,
|
OP_STR_imm_T4 = 0xF840,
|
||||||
OP_STR_reg_T2 = 0xF840,
|
OP_STR_reg_T2 = 0xF840,
|
||||||
OP_LDR_imm_T4 = 0xF850,
|
OP_LDR_imm_T4 = 0xF850,
|
||||||
OP_LDR_reg_T2 = 0xF850,
|
OP_LDR_reg_T2 = 0xF850,
|
||||||
OP_LDRB_imm_T2 = 0xF890,
|
|
||||||
OP_LDRH_imm_T2 = 0xF8B0,
|
OP_LDRH_imm_T2 = 0xF8B0,
|
||||||
OP_STR_imm_T3 = 0xF8C0,
|
OP_STR_imm_T3 = 0xF8C0,
|
||||||
OP_LDR_imm_T3 = 0xF8D0,
|
OP_LDR_imm_T3 = 0xF8D0,
|
||||||
|
@ -1086,52 +1079,6 @@ public:
|
||||||
m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
|
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)
|
void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
|
||||||
{
|
{
|
||||||
ASSERT(!BadReg(rd));
|
ASSERT(!BadReg(rd));
|
||||||
|
@ -1770,20 +1717,7 @@ private:
|
||||||
|| (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
|
|| (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
|
||||||
|
|
||||||
intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
|
intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
|
||||||
|
if (((relative << 7) >> 7) == relative) {
|
||||||
// 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) {
|
|
||||||
// ARM encoding for the top two bits below the sign bit is 'peculiar'.
|
// ARM encoding for the top two bits below the sign bit is 'peculiar'.
|
||||||
if (relative >= 0)
|
if (relative >= 0)
|
||||||
relative ^= 0xC00000;
|
relative ^= 0xC00000;
|
||||||
|
|
|
@ -53,12 +53,6 @@ public:
|
||||||
typedef typename AssemblerType::JmpSrc JmpSrc;
|
typedef typename AssemblerType::JmpSrc JmpSrc;
|
||||||
typedef typename AssemblerType::JmpDst JmpDst;
|
typedef typename AssemblerType::JmpDst JmpDst;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
void setSpewPath(bool isOOLPath)
|
|
||||||
{
|
|
||||||
m_assembler.isOOLPath = isOOLPath;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Section 1: MacroAssembler operand types
|
// Section 1: MacroAssembler operand types
|
||||||
//
|
//
|
||||||
|
|
|
@ -187,20 +187,6 @@ public:
|
||||||
{
|
{
|
||||||
m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
|
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)
|
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));
|
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)
|
void load32(ImplicitAddress address, RegisterID dest)
|
||||||
{
|
{
|
||||||
m_assembler.dataTransfer32(true, dest, address.base, address.offset);
|
m_assembler.dataTransfer32(true, dest, address.base, address.offset);
|
||||||
|
@ -288,16 +263,11 @@ public:
|
||||||
|
|
||||||
void load16(BaseIndex address, RegisterID dest)
|
void load16(BaseIndex address, RegisterID dest)
|
||||||
{
|
{
|
||||||
m_assembler.add_r(ARMRegisters::S1, address.base, m_assembler.lsl(address.index, address.scale));
|
m_assembler.add_r(ARMRegisters::S0, address.base, m_assembler.lsl(address.index, address.scale));
|
||||||
load16(Address(ARMRegisters::S1, address.offset), dest);
|
if (address.offset>=0)
|
||||||
}
|
m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
|
||||||
|
|
||||||
void load16(ImplicitAddress address, RegisterID dest)
|
|
||||||
{
|
|
||||||
if (address.offset >= 0)
|
|
||||||
m_assembler.ldrh_u(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(address.offset, ARMRegisters::S0));
|
|
||||||
else
|
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)
|
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
|
||||||
|
@ -411,12 +381,6 @@ public:
|
||||||
move(src, dest);
|
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)
|
Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
|
||||||
{
|
{
|
||||||
m_assembler.cmp_r(left, right);
|
m_assembler.cmp_r(left, right);
|
||||||
|
@ -480,12 +444,6 @@ public:
|
||||||
return m_assembler.jmp(ARMCondition(cond));
|
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)
|
Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
|
||||||
{
|
{
|
||||||
ASSERT((cond == Zero) || (cond == NonZero));
|
ASSERT((cond == Zero) || (cond == NonZero));
|
||||||
|
@ -523,7 +481,7 @@ public:
|
||||||
|
|
||||||
void jump(RegisterID target)
|
void jump(RegisterID target)
|
||||||
{
|
{
|
||||||
m_assembler.bx(target);
|
m_assembler.bx_r(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jump(Address address)
|
void jump(Address address)
|
||||||
|
@ -545,13 +503,6 @@ public:
|
||||||
return Jump(m_assembler.jmp(ARMCondition(cond)));
|
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)
|
void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
|
||||||
{
|
{
|
||||||
if (src1 == dest) {
|
if (src1 == dest) {
|
||||||
|
@ -601,20 +552,6 @@ public:
|
||||||
return Jump(m_assembler.jmp(ARMCondition(cond)));
|
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)
|
Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
|
||||||
{
|
{
|
||||||
ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
|
ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
|
||||||
|
@ -631,7 +568,7 @@ public:
|
||||||
{
|
{
|
||||||
#if WTF_ARM_ARCH_VERSION >= 5
|
#if WTF_ARM_ARCH_VERSION >= 5
|
||||||
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::LinkableNear);
|
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;
|
return call;
|
||||||
#else
|
#else
|
||||||
prepareCall();
|
prepareCall();
|
||||||
|
@ -641,7 +578,7 @@ public:
|
||||||
|
|
||||||
Call call(RegisterID target)
|
Call call(RegisterID target)
|
||||||
{
|
{
|
||||||
m_assembler.blx(target);
|
m_assembler.blx_r(target);
|
||||||
JmpSrc jmpSrc;
|
JmpSrc jmpSrc;
|
||||||
return Call(jmpSrc, Call::None);
|
return Call(jmpSrc, Call::None);
|
||||||
}
|
}
|
||||||
|
@ -653,7 +590,7 @@ public:
|
||||||
|
|
||||||
void ret()
|
void ret()
|
||||||
{
|
{
|
||||||
m_assembler.bx(linkRegister);
|
m_assembler.bx_r(linkRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
|
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));
|
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)
|
void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
|
||||||
{
|
{
|
||||||
// ARM doesn't have byte registers
|
// ARM doesn't have byte registers
|
||||||
|
@ -786,7 +717,7 @@ public:
|
||||||
{
|
{
|
||||||
#if WTF_ARM_ARCH_VERSION >= 5
|
#if WTF_ARM_ARCH_VERSION >= 5
|
||||||
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::Linkable);
|
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;
|
return call;
|
||||||
#else
|
#else
|
||||||
prepareCall();
|
prepareCall();
|
||||||
|
@ -849,17 +780,12 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsFloatingPointSqrt() const
|
|
||||||
{
|
|
||||||
return s_isVFPPresent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
||||||
{
|
{
|
||||||
m_assembler.doubleTransfer(true, dest, address.base, address.offset);
|
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.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
|
||||||
m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
|
m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
|
||||||
|
@ -915,16 +841,6 @@ public:
|
||||||
mulDouble(ARMRegisters::SD0, dest);
|
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)
|
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
|
||||||
{
|
{
|
||||||
m_assembler.fmsr_r(dest, src);
|
m_assembler.fmsr_r(dest, src);
|
||||||
|
@ -1011,58 +927,46 @@ protected:
|
||||||
#if WTF_ARM_ARCH_VERSION < 5
|
#if WTF_ARM_ARCH_VERSION < 5
|
||||||
void prepareCall()
|
void prepareCall()
|
||||||
{
|
{
|
||||||
#if WTF_ARM_ARCH_VERSION < 5
|
|
||||||
ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
|
ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
|
||||||
|
|
||||||
m_assembler.mov_r(linkRegister, ARMRegisters::pc);
|
m_assembler.mov_r(linkRegister, ARMRegisters::pc);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WTF_ARM_ARCH_VERSION < 5
|
#if WTF_ARM_ARCH_VERSION < 5
|
||||||
void call32(RegisterID base, int32_t offset)
|
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)
|
if (base == ARMRegisters::sp)
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
if (offset >= 0) {
|
if (offset >= 0) {
|
||||||
if (offset <= 0xfff) {
|
if (offset <= 0xfff) {
|
||||||
prepareCall();
|
prepareCall();
|
||||||
m_assembler.dtr_u(true, targetReg, base, offset);
|
m_assembler.dtr_u(true, ARMRegisters::pc, base, offset);
|
||||||
} else if (offset <= 0xfffff) {
|
} 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();
|
prepareCall();
|
||||||
m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
|
m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
|
||||||
} else {
|
} else {
|
||||||
ARMWord reg = m_assembler.getImm(offset, tmpReg);
|
ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
|
||||||
prepareCall();
|
prepareCall();
|
||||||
m_assembler.dtr_ur(true, targetReg, base, reg);
|
m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
if (offset <= 0xfff) {
|
if (offset <= 0xfff) {
|
||||||
prepareCall();
|
prepareCall();
|
||||||
m_assembler.dtr_d(true, targetReg, base, offset);
|
m_assembler.dtr_d(true, ARMRegisters::pc, base, offset);
|
||||||
} else if (offset <= 0xfffff) {
|
} 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();
|
prepareCall();
|
||||||
m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
|
m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
|
||||||
} else {
|
} else {
|
||||||
ARMWord reg = m_assembler.getImm(offset, tmpReg);
|
ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
|
||||||
prepareCall();
|
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
|
#else
|
||||||
void call32(RegisterID base, int32_t offset)
|
void call32(RegisterID base, int32_t offset)
|
||||||
|
@ -1107,7 +1011,7 @@ protected:
|
||||||
m_assembler.dtr_dr(true, ARMRegisters::S0, base, reg);
|
m_assembler.dtr_dr(true, ARMRegisters::S0, base, reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_assembler.blx(ARMRegisters::S0);
|
m_assembler.blx_r(ARMRegisters::S0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -259,21 +259,6 @@ public:
|
||||||
{
|
{
|
||||||
m_assembler.asr(dest, dest, imm.m_value & 0x1f);
|
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)
|
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)
|
void store32(RegisterID src, ArmAddress address)
|
||||||
{
|
{
|
||||||
if (address.type == ArmAddress::HasIndex)
|
if (address.type == ArmAddress::HasIndex)
|
||||||
|
@ -434,11 +405,6 @@ public:
|
||||||
m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
|
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 load32WithAddressOffsetPatch(Address address, RegisterID dest)
|
||||||
{
|
{
|
||||||
DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
|
DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
|
||||||
|
@ -458,11 +424,6 @@ public:
|
||||||
{
|
{
|
||||||
m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
|
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)
|
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
|
||||||
{
|
{
|
||||||
|
@ -516,11 +477,6 @@ public:
|
||||||
// In short, FIXME:.
|
// In short, FIXME:.
|
||||||
bool supportsFloatingPointTruncate() const { return false; }
|
bool supportsFloatingPointTruncate() const { return false; }
|
||||||
|
|
||||||
bool supportsFloatingPointSqrt() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
||||||
{
|
{
|
||||||
RegisterID base = address.base;
|
RegisterID base = address.base;
|
||||||
|
@ -584,11 +540,6 @@ public:
|
||||||
mulDouble(fpTempRegister, dest);
|
mulDouble(fpTempRegister, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqrtDouble(FPRegisterID, FPRegisterID)
|
|
||||||
{
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
|
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
|
||||||
{
|
{
|
||||||
m_assembler.vmov(fpTempRegister, src);
|
m_assembler.vmov(fpTempRegister, src);
|
||||||
|
@ -843,19 +794,6 @@ public:
|
||||||
return branch32(cond, addressTempRegister, Imm32(right.m_value << 16));
|
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)
|
Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
|
||||||
{
|
{
|
||||||
ASSERT((cond == Zero) || (cond == NonZero));
|
ASSERT((cond == Zero) || (cond == NonZero));
|
||||||
|
@ -886,21 +824,6 @@ public:
|
||||||
return branchTest32(cond, addressTempRegister, mask);
|
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()
|
Jump jump()
|
||||||
{
|
{
|
||||||
return Jump(makeJump());
|
return Jump(makeJump());
|
||||||
|
@ -1051,14 +974,6 @@ public:
|
||||||
m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
|
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)
|
DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,3 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace JSC
|
} // namespace JSC
|
||||||
|
|
||||||
#endif /* _include_assembler_moco_stubs_h_ */
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче