/*
- * 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
#ifndef ARMAssembler_h
#define ARMAssembler_h
-#include <wtf/Platform.h>
-
#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
#include "AssemblerBufferWithConstantPool.h"
FSUBD = 0x0e300b40,
FMULD = 0x0e200b00,
FCMPD = 0x0eb40b40,
+ FSQRTD = 0x0eb10bc0,
DTR = 0x05000000,
LDRH = 0x00100090,
STRH = 0x00000090,
FDTR = 0x0d000b00,
B = 0x0a000000,
BL = 0x0b000000,
+#if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
+ BX = 0x012fff10,
+#endif
FMSR = 0x0e000a10,
FMRS = 0x0e100a10,
FSITOD = 0x0eb80bc0,
#if WTF_ARM_ARCH_AT_LEAST(5)
CLZ = 0x016f0f10,
BKPT = 0xe120070,
+ BLX = 0x012fff30,
#endif
#if WTF_ARM_ARCH_AT_LEAST(7)
MOVW = 0x03000000,
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),
};
static const ARMWord INVALID_IMM = 0xf0000000;
+ static const ARMWord InvalidBranchTarget = 0xffffffff;
static const int DefaultPrefetching = 2;
class JmpSrc {
emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
}
+ void fsqrtd_r(int dd, int dm, Condition cc = AL)
+ {
+ emitInst(static_cast<ARMWord>(cc) | FSQRTD, dd, 0, dm);
+ }
+
void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
{
m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true);
#endif
}
+ void bx(int rm, Condition cc = AL)
+ {
+#if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
+ emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm));
+#else
+ mov_r(ARMRegisters::pc, RM(rm), cc);
+#endif
+ }
+
+ JmpSrc blx(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 != 14);
+ ensureSpace(2 * sizeof(ARMWord), 0);
+ mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
+ int s = m_buffer.uncheckedSize();
+ bx(rm, cc);
+#endif
+ return JmpSrc(s);
+ }
+
static ARMWord lsl(int reg, ARMWord value)
{
ASSERT(reg <= ARMRegisters::pc);
return label();
}
- JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
+ JmpSrc loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0)
{
ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
int s = m_buffer.uncheckedSize();
- ldr_un_imm(ARMRegisters::pc, 0xffffffff, cc);
+ ldr_un_imm(rd, InvalidBranchTarget, cc);
m_jumps.append(s | (useConstantPool & 0x1));
return JmpSrc(s);
}
+ JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
+ {
+ return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
+ }
+
void* executableCopy(ExecutablePool* allocator);
// 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);
// 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);