| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| * |
| * ***** BEGIN LICENSE BLOCK ***** |
| * Copyright (C) 2009 University of Szeged |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * ***** END LICENSE BLOCK ***** */ |
| |
| #include "assembler/wtf/Platform.h" |
| |
| #if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL |
| |
| #include "MacroAssemblerARM.h" |
| |
| #if WTF_OS_LINUX || WTF_OS_ANDROID |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <elf.h> |
| |
| // lame check for kernel version |
| // see bug 586550 |
| #include <linux/version.h> |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) |
| #include <asm/procinfo.h> |
| #else |
| #include <asm/hwcap.h> |
| #endif |
| |
| #endif |
| |
| namespace JSC { |
| |
| static bool isVFPPresent() |
| { |
| #if WTF_OS_LINUX |
| int fd = open("/proc/self/auxv", O_RDONLY); |
| if (fd > 0) { |
| Elf32_auxv_t aux; |
| while (read(fd, &aux, sizeof(Elf32_auxv_t))) { |
| if (aux.a_type == AT_HWCAP) { |
| close(fd); |
| return aux.a_un.a_val & HWCAP_VFP; |
| } |
| } |
| close(fd); |
| } |
| #endif |
| |
| #if defined(__GNUC__) && defined(__VFP_FP__) |
| return true; |
| #endif |
| |
| #ifdef WTF_OS_ANDROID |
| FILE *fp = fopen("/proc/cpuinfo", "r"); |
| if (!fp) |
| return false; |
| |
| char buf[1024]; |
| fread(buf, sizeof(char), sizeof(buf), fp); |
| fclose(fp); |
| if (strstr(buf, "vfp")) |
| return true; |
| #endif |
| |
| return false; |
| } |
| |
| const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent(); |
| |
| #if WTF_CPU_ARMV5_OR_LOWER |
| /* On ARMv5 and below, natural alignment is required. */ |
| void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) |
| { |
| ARMWord op2; |
| |
| ASSERT(address.scale >= 0 && address.scale <= 3); |
| op2 = m_assembler.lsl(address.index, static_cast<int>(address.scale)); |
| |
| if (address.offset >= 0 && address.offset + 0x2 <= 0xff) { |
| m_assembler.add_r(ARMRegisters::S0, address.base, op2); |
| m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset)); |
| m_assembler.ldrh_u(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset + 0x2)); |
| } else if (address.offset < 0 && address.offset >= -0xff) { |
| m_assembler.add_r(ARMRegisters::S0, address.base, op2); |
| m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset)); |
| m_assembler.ldrh_d(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset - 0x2)); |
| } else { |
| m_assembler.ldr_un_imm(ARMRegisters::S0, address.offset); |
| m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, op2); |
| m_assembler.ldrh_r(dest, address.base, ARMRegisters::S0); |
| m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::OP2_IMM | 0x2); |
| m_assembler.ldrh_r(ARMRegisters::S0, address.base, ARMRegisters::S0); |
| } |
| m_assembler.orr_r(dest, dest, m_assembler.lsl(ARMRegisters::S0, 16)); |
| } |
| #endif |
| |
| } |
| |
| #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) |