mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-14 15:37:55 +00:00
Push-and-pray to try to fix ARM build breaks. (r=red).
This commit is contained in:
parent
3830538ae6
commit
cd014beba1
@ -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);
|
||||
dtr_d(isLoad, srcDst, base, offset | transferFlag);
|
||||
else if (offset <= 0xfffff) {
|
||||
sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
|
||||
dtr_d(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
|
||||
dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag);
|
||||
} else {
|
||||
ARMWord reg = getImm(offset, ARMRegisters::S0);
|
||||
dtr_dr(isLoad, srcDst, base, reg);
|
||||
dtr_dr(isLoad, srcDst, base, reg | transferFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,10 +356,17 @@ 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 offset = *getLdrImmAddress(ldrAddr);
|
||||
if (offset != 0xffffffff) {
|
||||
JmpSrc jmpSrc(pos);
|
||||
linkBranch(data, jmpSrc, data + offset, ((*iter) & 1));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -37,7 +37,6 @@
|
||||
#include "AssemblerBufferWithConstantPool.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
|
||||
#define IPFX " "
|
||||
|
||||
namespace JSC {
|
||||
|
||||
@ -74,13 +73,46 @@ namespace JSC {
|
||||
d1,
|
||||
d2,
|
||||
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;
|
||||
|
||||
} // 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;
|
||||
@ -88,6 +120,8 @@ namespace JSC {
|
||||
|
||||
ARMAssembler() { }
|
||||
|
||||
unsigned char *buffer() const { return m_buffer.buffer(); }
|
||||
|
||||
// ARM conditional constants
|
||||
typedef enum {
|
||||
EQ = 0x00000000, // Zero
|
||||
@ -128,10 +162,12 @@ 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,
|
||||
@ -139,11 +175,11 @@ namespace JSC {
|
||||
LDMIA = 0x08b00000,
|
||||
FDTR = 0x0d000b00,
|
||||
B = 0x0a000000,
|
||||
BL = 0x0b000000,
|
||||
#ifndef __ARM_ARCH_4__
|
||||
BX = 0x012fff10, // Only on ARMv4T+!
|
||||
BL = 0x0b000000
|
||||
#if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
|
||||
,BX = 0x012fff10
|
||||
#endif
|
||||
FMSR = 0x0e000a10,
|
||||
,FMSR = 0x0e000a10,
|
||||
FMRS = 0x0e100a10,
|
||||
FSITOD = 0x0eb80bc0,
|
||||
FTOSID = 0x0ebd0b40,
|
||||
@ -151,7 +187,7 @@ namespace JSC {
|
||||
#if WTF_ARM_ARCH_VERSION >= 5
|
||||
,CLZ = 0x016f0f10,
|
||||
BKPT = 0xe120070,
|
||||
BLX_R = 0x012fff30
|
||||
BLX = 0x012fff30
|
||||
#endif
|
||||
#if WTF_ARM_ARCH_VERSION >= 7
|
||||
,MOVW = 0x03000000,
|
||||
@ -166,6 +202,7 @@ 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),
|
||||
@ -201,6 +238,8 @@ namespace JSC {
|
||||
} Shift;
|
||||
|
||||
static const ARMWord INVALID_IMM = 0xf0000000;
|
||||
static const ARMWord InvalidBranchTarget = 0xffffffff;
|
||||
static const int DefaultPrefetching = 2;
|
||||
|
||||
class JmpSrc {
|
||||
friend class ARMAssembler;
|
||||
@ -446,34 +485,36 @@ 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];
|
||||
@ -546,14 +587,12 @@ 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);
|
||||
}
|
||||
@ -582,31 +621,26 @@ 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);
|
||||
}
|
||||
|
||||
@ -628,37 +662,28 @@ namespace JSC {
|
||||
#endif
|
||||
}
|
||||
|
||||
// BX is emitted where possible, or an equivalent sequence on ARMv4.
|
||||
void bx_r(int rm, Condition cc = AL)
|
||||
void bx(int rm, Condition cc = AL)
|
||||
{
|
||||
#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);
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
|
||||
// BLX is emitted where possible, or an equivalent (slower) sequence on
|
||||
// ARMv4 or ARMv4T.
|
||||
void blx_r(int rm, Condition cc = AL)
|
||||
JmpSrc blx(int rm, Condition cc = AL)
|
||||
{
|
||||
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.
|
||||
#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 != 14);
|
||||
ensureSpace(2 * sizeof(ARMWord), 0);
|
||||
mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
|
||||
bx_r(rm, cc);
|
||||
int s = m_buffer.uncheckedSize();
|
||||
bx(rm, cc);
|
||||
#endif
|
||||
return JmpSrc(s);
|
||||
}
|
||||
|
||||
static ARMWord lsl(int reg, ARMWord value)
|
||||
@ -737,7 +762,7 @@ namespace JSC {
|
||||
{
|
||||
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
|
||||
int s = m_buffer.uncheckedSize();
|
||||
ldr_un_imm(rd, 0xffffffff, cc);
|
||||
ldr_un_imm(rd, InvalidBranchTarget, cc);
|
||||
m_jumps.append(s | (useConstantPool & 0x1));
|
||||
return JmpSrc(s);
|
||||
}
|
||||
@ -751,15 +776,40 @@ namespace JSC {
|
||||
|
||||
// Patching helpers
|
||||
|
||||
static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
|
||||
static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0);
|
||||
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 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)
|
||||
@ -816,12 +866,13 @@ namespace JSC {
|
||||
void linkJump(JmpSrc from, JmpDst to)
|
||||
{
|
||||
ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
|
||||
*getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset);
|
||||
ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
|
||||
*addr = static_cast<ARMWord>(to.m_offset);
|
||||
}
|
||||
|
||||
static void linkJump(void* code, JmpSrc from, void* to)
|
||||
{
|
||||
linkBranch(code, from, to);
|
||||
patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
|
||||
}
|
||||
|
||||
static void relinkJump(void* from, void* to)
|
||||
@ -831,12 +882,12 @@ namespace JSC {
|
||||
|
||||
static void linkCall(void* code, JmpSrc from, void* to)
|
||||
{
|
||||
linkBranch(code, from, to, true);
|
||||
patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
|
||||
}
|
||||
|
||||
static void relinkCall(void* from, void* to)
|
||||
{
|
||||
relinkJump(from, to);
|
||||
patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
|
||||
}
|
||||
|
||||
// Address operations
|
||||
@ -890,9 +941,18 @@ 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);
|
||||
void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false);
|
||||
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);
|
||||
|
||||
@ -919,6 +979,23 @@ 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);
|
||||
@ -1046,6 +1123,27 @@ 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;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
@ -33,6 +34,7 @@
|
||||
#include "AssemblerBuffer.h"
|
||||
#include "assembler/wtf/Assertions.h"
|
||||
#include "assembler/wtf/Vector.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace JSC {
|
||||
|
||||
@ -581,11 +583,13 @@ 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,
|
||||
@ -630,12 +634,15 @@ 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,
|
||||
@ -1079,6 +1086,52 @@ 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));
|
||||
@ -1717,7 +1770,20 @@ 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));
|
||||
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'.
|
||||
if (relative >= 0)
|
||||
relative ^= 0xC00000;
|
||||
|
@ -53,6 +53,12 @@ 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
|
||||
//
|
||||
|
@ -188,6 +188,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)
|
||||
{
|
||||
m_assembler.subs_r(dest, dest, src);
|
||||
@ -227,6 +241,17 @@ 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);
|
||||
@ -263,11 +288,16 @@ public:
|
||||
|
||||
void load16(BaseIndex address, RegisterID dest)
|
||||
{
|
||||
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));
|
||||
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));
|
||||
else
|
||||
m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
|
||||
m_assembler.ldrh_d(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(-address.offset, ARMRegisters::S0));
|
||||
}
|
||||
|
||||
DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
|
||||
@ -381,6 +411,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);
|
||||
@ -444,6 +480,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));
|
||||
@ -481,7 +523,7 @@ public:
|
||||
|
||||
void jump(RegisterID target)
|
||||
{
|
||||
m_assembler.bx_r(target);
|
||||
m_assembler.bx(target);
|
||||
}
|
||||
|
||||
void jump(Address address)
|
||||
@ -503,6 +545,13 @@ 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) {
|
||||
@ -552,6 +601,20 @@ 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));
|
||||
@ -568,7 +631,7 @@ public:
|
||||
{
|
||||
#if WTF_ARM_ARCH_VERSION >= 5
|
||||
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::LinkableNear);
|
||||
m_assembler.blx_r(ARMRegisters::S1);
|
||||
m_assembler.blx(ARMRegisters::S1);
|
||||
return call;
|
||||
#else
|
||||
prepareCall();
|
||||
@ -578,7 +641,7 @@ public:
|
||||
|
||||
Call call(RegisterID target)
|
||||
{
|
||||
m_assembler.blx_r(target);
|
||||
m_assembler.blx(target);
|
||||
JmpSrc jmpSrc;
|
||||
return Call(jmpSrc, Call::None);
|
||||
}
|
||||
@ -590,7 +653,7 @@ public:
|
||||
|
||||
void ret()
|
||||
{
|
||||
m_assembler.bx_r(linkRegister);
|
||||
m_assembler.bx(linkRegister);
|
||||
}
|
||||
|
||||
void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
|
||||
@ -619,6 +682,12 @@ 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
|
||||
@ -717,7 +786,7 @@ public:
|
||||
{
|
||||
#if WTF_ARM_ARCH_VERSION >= 5
|
||||
Call call(m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true), Call::Linkable);
|
||||
m_assembler.blx_r(ARMRegisters::S1);
|
||||
m_assembler.blx(ARMRegisters::S1);
|
||||
return call;
|
||||
#else
|
||||
prepareCall();
|
||||
@ -780,12 +849,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);
|
||||
@ -841,6 +915,16 @@ 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);
|
||||
@ -927,46 +1011,58 @@ 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, 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_VERSION >= 5
|
||||
m_assembler.blx(targetReg);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void call32(RegisterID base, int32_t offset)
|
||||
@ -1011,7 +1107,7 @@ protected:
|
||||
m_assembler.dtr_dr(true, ARMRegisters::S0, base, reg);
|
||||
}
|
||||
}
|
||||
m_assembler.blx_r(ARMRegisters::S0);
|
||||
m_assembler.blx(ARMRegisters::S0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -260,6 +260,21 @@ 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)
|
||||
{
|
||||
m_assembler.sub(dest, dest, src);
|
||||
@ -369,6 +384,20 @@ 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)
|
||||
@ -405,6 +434,11 @@ 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);
|
||||
@ -425,6 +459,11 @@ 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)
|
||||
{
|
||||
DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
|
||||
@ -477,6 +516,11 @@ public:
|
||||
// In short, FIXME:.
|
||||
bool supportsFloatingPointTruncate() const { return false; }
|
||||
|
||||
bool supportsFloatingPointSqrt() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void loadDouble(ImplicitAddress address, FPRegisterID dest)
|
||||
{
|
||||
RegisterID base = address.base;
|
||||
@ -540,6 +584,11 @@ public:
|
||||
mulDouble(fpTempRegister, dest);
|
||||
}
|
||||
|
||||
void sqrtDouble(FPRegisterID, FPRegisterID)
|
||||
{
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
|
||||
{
|
||||
m_assembler.vmov(fpTempRegister, src);
|
||||
@ -794,6 +843,19 @@ 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));
|
||||
@ -824,6 +886,21 @@ 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());
|
||||
@ -974,6 +1051,14 @@ 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)
|
||||
{
|
||||
|
@ -69,3 +69,6 @@ private:
|
||||
};
|
||||
|
||||
} // namespace JSC
|
||||
|
||||
#endif /* _include_assembler_moco_stubs_h_ */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user