#include "cpu.h"
-#include "gdbstub.h"
+#include "exec/gdbstub.h"
#include "helper.h"
-#include "host-utils.h"
-#include "sysemu.h"
+#include "qemu/host-utils.h"
+#include "sysemu/sysemu.h"
+#include "qemu/bitops.h"
#ifndef CONFIG_USER_ONLY
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int access_type, int is_user,
- target_phys_addr_t *phys_ptr, int *prot,
+ hwaddr *phys_ptr, int *prot,
target_ulong *page_size);
#endif
#ifndef CONFIG_USER_ONLY
/* get_phys_addr() isn't present for user-mode-only targets */
+
+/* Return true if extended addresses are enabled, ie this is an
+ * LPAE implementation and we are using the long-descriptor translation
+ * table format because the TTBCR EAE bit is set.
+ */
+static inline bool extended_addresses_enabled(CPUARMState *env)
+{
+ return arm_feature(env, ARM_FEATURE_LPAE)
+ && (env->cp15.c2_control & (1 << 31));
+}
+
static int ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- target_phys_addr_t phys_addr;
+ hwaddr phys_addr;
target_ulong page_size;
int prot;
int ret, is_user = ri->opc2 & 2;
}
ret = get_phys_addr(env, value, access_type, is_user,
&phys_addr, &prot, &page_size);
- if (ret == 0) {
- /* We do not set any attribute bits in the PAR */
- if (page_size == (1 << 24)
- && arm_feature(env, ARM_FEATURE_V7)) {
- env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+ if (extended_addresses_enabled(env)) {
+ /* ret is a DFSR/IFSR value for the long descriptor
+ * translation table format, but with WnR always clear.
+ * Convert it to a 64-bit PAR.
+ */
+ uint64_t par64 = (1 << 11); /* LPAE bit always set */
+ if (ret == 0) {
+ par64 |= phys_addr & ~0xfffULL;
+ /* We don't set the ATTR or SH fields in the PAR. */
} else {
- env->cp15.c7_par = phys_addr & 0xfffff000;
+ par64 |= 1; /* F */
+ par64 |= (ret & 0x3f) << 1; /* FS */
+ /* Note that S2WLK and FSTAGE are always zero, because we don't
+ * implement virtualization and therefore there can't be a stage 2
+ * fault.
+ */
}
+ env->cp15.c7_par = par64;
+ env->cp15.c7_par_hi = par64 >> 32;
} else {
- env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
- ((ret & (12 << 1)) >> 6) |
- ((ret & 0xf) << 1) | 1;
+ /* ret is a DFSR/IFSR value for the short descriptor
+ * translation table format (with WnR always clear).
+ * Convert it to a 32-bit PAR.
+ */
+ if (ret == 0) {
+ /* We do not set any attribute bits in the PAR */
+ if (page_size == (1 << 24)
+ && arm_feature(env, ARM_FEATURE_V7)) {
+ env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
+ } else {
+ env->cp15.c7_par = phys_addr & 0xfffff000;
+ }
+ } else {
+ env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
+ ((ret & (12 << 1)) >> 6) |
+ ((ret & 0xf) << 1) | 1;
+ }
+ env->cp15.c7_par_hi = 0;
}
- env->cp15.c7_par_hi = 0;
return 0;
}
#endif
static int arm946_prbs_read(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t *value)
{
- if (ri->crm > 8) {
+ if (ri->crm >= 8) {
return EXCP_UDEF;
}
*value = env->cp15.c6_region[ri->crm];
static int arm946_prbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- if (ri->crm > 8) {
+ if (ri->crm >= 8) {
return EXCP_UDEF;
}
env->cp15.c6_region[ri->crm] = value;
static int vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- value &= 7;
+ if (arm_feature(env, ARM_FEATURE_LPAE)) {
+ value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
+ /* With LPAE the TTBCR could result in a change of ASID
+ * via the TTBCR.A1 bit, so do a TLB flush.
+ */
+ tlb_flush(env, 1);
+ } else {
+ value &= 7;
+ }
+ /* Note that we always calculate c2_mask and c2_base_mask, but
+ * they are only used for short-descriptor tables (ie if EAE is 0);
+ * for long-descriptor tables the TTBCR fields are used differently
+ * and the c2_mask and c2_base_mask values are meaningless.
+ */
env->cp15.c2_control = value;
env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> value);
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> value);
uint64_t value)
{
/* Wait-for-interrupt (deprecated) */
- cpu_interrupt(env, CPU_INTERRUPT_HALT);
+ cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
return 0;
}
static int mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t *value)
{
- uint32_t mpidr = env->cpu_index;
+ CPUState *cs = CPU(arm_env_get_cpu(env));
+ uint32_t mpidr = cs->cpu_index;
/* We don't support setting cluster ID ([8..11])
* so these bits always RAZ.
*/
}
static const ARMCPRegInfo lpae_cp_reginfo[] = {
- /* NOP AMAIR0/1: the override is because these clash with tha rather
+ /* NOP AMAIR0/1: the override is because these clash with the rather
* broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
*/
{ .name = "AMAIR0", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
{
ARMCPU *cpu;
CPUARMState *env;
- static int inited = 0;
+ ObjectClass *oc;
- if (!object_class_by_name(cpu_model)) {
+ oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
+ if (!oc) {
return NULL;
}
- cpu = ARM_CPU(object_new(cpu_model));
+ cpu = ARM_CPU(object_new(object_class_get_name(oc)));
env = &cpu->env;
env->cpu_model_str = cpu_model;
- arm_cpu_realize(cpu);
- if (tcg_enabled() && !inited) {
- inited = 1;
- arm_translate_init();
- }
+ /* TODO this should be set centrally, once possible */
+ object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
+
+ return cpu;
+}
+
+void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
+{
+ CPUARMState *env = &cpu->env;
- cpu_reset(CPU(cpu));
if (arm_feature(env, ARM_FEATURE_NEON)) {
gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
51, "arm-neon.xml", 0);
gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
19, "arm-vfp.xml", 0);
}
- qemu_init_vcpu(env);
- return cpu;
}
-typedef struct ARMCPUListState {
- fprintf_function cpu_fprintf;
- FILE *file;
-} ARMCPUListState;
-
/* Sort alphabetically by type name, except for "any". */
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
{
name_a = object_class_get_name(class_a);
name_b = object_class_get_name(class_b);
- if (strcmp(name_a, "any") == 0) {
+ if (strcmp(name_a, "any-" TYPE_ARM_CPU) == 0) {
return 1;
- } else if (strcmp(name_b, "any") == 0) {
+ } else if (strcmp(name_b, "any-" TYPE_ARM_CPU) == 0) {
return -1;
} else {
return strcmp(name_a, name_b);
static void arm_cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
- ARMCPUListState *s = user_data;
+ CPUListState *s = user_data;
+ const char *typename;
+ char *name;
+ typename = object_class_get_name(oc);
+ name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU));
(*s->cpu_fprintf)(s->file, " %s\n",
- object_class_get_name(oc));
+ name);
+ g_free(name);
}
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
- ARMCPUListState s = {
+ CPUListState s = {
.file = f,
.cpu_fprintf = cpu_fprintf,
};
return x;
}
-uint32_t HELPER(abs)(uint32_t x)
-{
- return ((int32_t)x < 0) ? -x : x;
-}
-
#if defined(CONFIG_USER_ONLY)
-void do_interrupt (CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
env->exception_index = -1;
}
#else
/* Map CPU modes onto saved register banks. */
-static inline int bank_number(CPUARMState *env, int mode)
+int bank_number(int mode)
{
switch (mode) {
case ARM_CPU_MODE_USR:
case ARM_CPU_MODE_FIQ:
return 5;
}
- cpu_abort(env, "Bad mode %x\n", mode);
- return -1;
+ hw_error("bank number requested for bad CPSR mode value 0x%x\n", mode);
}
void switch_mode(CPUARMState *env, int mode)
memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
}
- i = bank_number(env, old_mode);
+ i = bank_number(old_mode);
env->banked_r13[i] = env->regs[13];
env->banked_r14[i] = env->regs[14];
env->banked_spsr[i] = env->spsr;
- i = bank_number(env, mode);
+ i = bank_number(mode);
env->regs[13] = env->banked_r13[i];
env->regs[14] = env->banked_r14[i];
env->spsr = env->banked_spsr[i];
pointer. */
}
-static void do_interrupt_v7m(CPUARMState *env)
+void arm_v7m_cpu_do_interrupt(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
uint32_t xpsr = xpsr_read(env);
uint32_t lr;
uint32_t addr;
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
return;
case EXCP_SWI:
- env->regs[15] += 2;
+ /* The PC already points to the next instruction. */
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
return;
case EXCP_PREFETCH_ABORT:
case EXCP_BKPT:
if (semihosting_enabled) {
int nr;
- nr = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
+ nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
if (nr == 0xab) {
env->regs[15] += 2;
env->regs[0] = do_arm_semihosting(env);
}
/* Handle a CPU exception. */
-void do_interrupt(CPUARMState *env)
+void arm_cpu_do_interrupt(CPUState *cs)
{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
uint32_t addr;
uint32_t mask;
int new_mode;
uint32_t offset;
- if (IS_M(env)) {
- do_interrupt_v7m(env);
- return;
- }
+ assert(!IS_M(env));
+
/* TODO: Vectored interrupt controller. */
switch (env->exception_index) {
case EXCP_UDEF:
if (semihosting_enabled) {
/* Check for semihosting interrupt. */
if (env->thumb) {
- mask = arm_lduw_code(env->regs[15] - 2, env->bswap_code) & 0xff;
+ mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
+ & 0xff;
} else {
- mask = arm_ldl_code(env->regs[15] - 4, env->bswap_code)
+ mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
& 0xffffff;
}
/* Only intercept calls from privileged modes, to provide some
case EXCP_BKPT:
/* See if this is a semihosting syscall. */
if (env->thumb && semihosting_enabled) {
- mask = arm_lduw_code(env->regs[15], env->bswap_code) & 0xff;
+ mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
if (mask == 0xab
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[15] += 2;
}
env->regs[14] = env->regs[15] + offset;
env->regs[15] = addr;
- env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
/* Check section/page access permissions.
}
static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
- int is_user, target_phys_addr_t *phys_ptr,
+ int is_user, hwaddr *phys_ptr,
int *prot, target_ulong *page_size)
{
int code;
int ap;
int domain;
int domain_prot;
- target_phys_addr_t phys_addr;
+ hwaddr phys_addr;
/* Pagetable walk. */
/* Lookup l1 descriptor. */
}
static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
- int is_user, target_phys_addr_t *phys_ptr,
+ int is_user, hwaddr *phys_ptr,
int *prot, target_ulong *page_size)
{
int code;
int ap;
int domain = 0;
int domain_prot;
- target_phys_addr_t phys_addr;
+ hwaddr phys_addr;
/* Pagetable walk. */
/* Lookup l1 descriptor. */
return code | (domain << 4);
}
+/* Fault type for long-descriptor MMU fault reporting; this corresponds
+ * to bits [5..2] in the STATUS field in long-format DFSR/IFSR.
+ */
+typedef enum {
+ translation_fault = 1,
+ access_fault = 2,
+ permission_fault = 3,
+} MMUFaultType;
+
+static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
+ int access_type, int is_user,
+ hwaddr *phys_ptr, int *prot,
+ target_ulong *page_size_ptr)
+{
+ /* Read an LPAE long-descriptor translation table. */
+ MMUFaultType fault_type = translation_fault;
+ uint32_t level = 1;
+ uint32_t epd;
+ uint32_t tsz;
+ uint64_t ttbr;
+ int ttbr_select;
+ int n;
+ hwaddr descaddr;
+ uint32_t tableattrs;
+ target_ulong page_size;
+ uint32_t attrs;
+
+ /* Determine whether this address is in the region controlled by
+ * TTBR0 or TTBR1 (or if it is in neither region and should fault).
+ * This is a Non-secure PL0/1 stage 1 translation, so controlled by
+ * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
+ */
+ uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
+ uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
+ if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
+ /* there is a ttbr0 region and we are in it (high bits all zero) */
+ ttbr_select = 0;
+ } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
+ /* there is a ttbr1 region and we are in it (high bits all one) */
+ ttbr_select = 1;
+ } else if (!t0sz) {
+ /* ttbr0 region is "everything not in the ttbr1 region" */
+ ttbr_select = 0;
+ } else if (!t1sz) {
+ /* ttbr1 region is "everything not in the ttbr0 region" */
+ ttbr_select = 1;
+ } else {
+ /* in the gap between the two regions, this is a Translation fault */
+ fault_type = translation_fault;
+ goto do_fault;
+ }
+
+ /* Note that QEMU ignores shareability and cacheability attributes,
+ * so we don't need to do anything with the SH, ORGN, IRGN fields
+ * in the TTBCR. Similarly, TTBCR:A1 selects whether we get the
+ * ASID from TTBR0 or TTBR1, but QEMU's TLB doesn't currently
+ * implement any ASID-like capability so we can ignore it (instead
+ * we will always flush the TLB any time the ASID is changed).
+ */
+ if (ttbr_select == 0) {
+ ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ epd = extract32(env->cp15.c2_control, 7, 1);
+ tsz = t0sz;
+ } else {
+ ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ epd = extract32(env->cp15.c2_control, 23, 1);
+ tsz = t1sz;
+ }
+
+ if (epd) {
+ /* Translation table walk disabled => Translation fault on TLB miss */
+ goto do_fault;
+ }
+
+ /* If the region is small enough we will skip straight to a 2nd level
+ * lookup. This affects the number of bits of the address used in
+ * combination with the TTBR to find the first descriptor. ('n' here
+ * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
+ * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
+ */
+ if (tsz > 1) {
+ level = 2;
+ n = 14 - tsz;
+ } else {
+ n = 5 - tsz;
+ }
+
+ /* Clear the vaddr bits which aren't part of the within-region address,
+ * so that we don't have to special case things when calculating the
+ * first descriptor address.
+ */
+ address &= (0xffffffffU >> tsz);
+
+ /* Now we can extract the actual base address from the TTBR */
+ descaddr = extract64(ttbr, 0, 40);
+ descaddr &= ~((1ULL << n) - 1);
+
+ tableattrs = 0;
+ for (;;) {
+ uint64_t descriptor;
+
+ descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
+ descriptor = ldq_phys(descaddr);
+ if (!(descriptor & 1) ||
+ (!(descriptor & 2) && (level == 3))) {
+ /* Invalid, or the Reserved level 3 encoding */
+ goto do_fault;
+ }
+ descaddr = descriptor & 0xfffffff000ULL;
+
+ if ((descriptor & 2) && (level < 3)) {
+ /* Table entry. The top five bits are attributes which may
+ * propagate down through lower levels of the table (and
+ * which are all arranged so that 0 means "no effect", so
+ * we can gather them up by ORing in the bits at each level).
+ */
+ tableattrs |= extract64(descriptor, 59, 5);
+ level++;
+ continue;
+ }
+ /* Block entry at level 1 or 2, or page entry at level 3.
+ * These are basically the same thing, although the number
+ * of bits we pull in from the vaddr varies.
+ */
+ page_size = (1 << (39 - (9 * level)));
+ descaddr |= (address & (page_size - 1));
+ /* Extract attributes from the descriptor and merge with table attrs */
+ attrs = extract64(descriptor, 2, 10)
+ | (extract64(descriptor, 52, 12) << 10);
+ attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
+ attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
+ /* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
+ * means "force PL1 access only", which means forcing AP[1] to 0.
+ */
+ if (extract32(tableattrs, 2, 1)) {
+ attrs &= ~(1 << 4);
+ }
+ /* Since we're always in the Non-secure state, NSTable is ignored. */
+ break;
+ }
+ /* Here descaddr is the final physical address, and attributes
+ * are all in attrs.
+ */
+ fault_type = access_fault;
+ if ((attrs & (1 << 8)) == 0) {
+ /* Access flag */
+ goto do_fault;
+ }
+ fault_type = permission_fault;
+ if (is_user && !(attrs & (1 << 4))) {
+ /* Unprivileged access not enabled */
+ goto do_fault;
+ }
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ if (attrs & (1 << 12) || (!is_user && (attrs & (1 << 11)))) {
+ /* XN or PXN */
+ if (access_type == 2) {
+ goto do_fault;
+ }
+ *prot &= ~PAGE_EXEC;
+ }
+ if (attrs & (1 << 5)) {
+ /* Write access forbidden */
+ if (access_type == 1) {
+ goto do_fault;
+ }
+ *prot &= ~PAGE_WRITE;
+ }
+
+ *phys_ptr = descaddr;
+ *page_size_ptr = page_size;
+ return 0;
+
+do_fault:
+ /* Long-descriptor format IFSR/DFSR value */
+ return (1 << 9) | (fault_type << 2) | level;
+}
+
static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
int access_type, int is_user,
- target_phys_addr_t *phys_ptr, int *prot)
+ hwaddr *phys_ptr, int *prot)
{
int n;
uint32_t mask;
return 0;
}
+/* get_phys_addr - get the physical address for this virtual address
+ *
+ * Find the physical address corresponding to the given virtual address,
+ * by doing a translation table walk on MMU based systems or using the
+ * MPU state on MPU based systems.
+ *
+ * Returns 0 if the translation was successful. Otherwise, phys_ptr,
+ * prot and page_size are not filled in, and the return value provides
+ * information on why the translation aborted, in the format of a
+ * DFSR/IFSR fault register, with the following caveats:
+ * * we honour the short vs long DFSR format differences.
+ * * the WnR bit is never set (the caller must do this).
+ * * for MPU based systems we don't bother to return a full FSR format
+ * value.
+ *
+ * @env: CPUARMState
+ * @address: virtual address to get physical address for
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @is_user: 0 for privileged access, 1 for user
+ * @phys_ptr: set to the physical address corresponding to the virtual address
+ * @prot: set to the permissions for the page containing phys_ptr
+ * @page_size: set to the size of the page containing phys_ptr
+ */
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
int access_type, int is_user,
- target_phys_addr_t *phys_ptr, int *prot,
+ hwaddr *phys_ptr, int *prot,
target_ulong *page_size)
{
/* Fast Context Switch Extension. */
*page_size = TARGET_PAGE_SIZE;
return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
prot);
+ } else if (extended_addresses_enabled(env)) {
+ return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr,
+ prot, page_size);
} else if (env->cp15.c1_sys & (1 << 23)) {
return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
prot, page_size);
int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
int access_type, int mmu_idx)
{
- target_phys_addr_t phys_addr;
+ hwaddr phys_addr;
target_ulong page_size;
int prot;
int ret, is_user;
&page_size);
if (ret == 0) {
/* Map a single [sub]page. */
- phys_addr &= ~(target_phys_addr_t)0x3ff;
+ phys_addr &= ~(hwaddr)0x3ff;
address &= ~(uint32_t)0x3ff;
tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
return 0;
return 1;
}
-target_phys_addr_t cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr)
+hwaddr cpu_get_phys_page_debug(CPUARMState *env, target_ulong addr)
{
- target_phys_addr_t phys_addr;
+ hwaddr phys_addr;
target_ulong page_size;
int prot;
int ret;
if ((env->uncached_cpsr & CPSR_M) == mode) {
env->regs[13] = val;
} else {
- env->banked_r13[bank_number(env, mode)] = val;
+ env->banked_r13[bank_number(mode)] = val;
}
}
if ((env->uncached_cpsr & CPSR_M) == mode) {
return env->regs[13];
} else {
- return env->banked_r13[bank_number(env, mode)];
+ return env->banked_r13[bank_number(mode)];
}
}
return (a & mask) | (b & ~mask);
}
-uint32_t HELPER(logicq_cc)(uint64_t val)
-{
- return (val >> 32) | (val != 0);
-}
-
-/* VFP support. We follow the convention used for VFP instrunctions:
- Single precition routines have a "s" suffix, double precision a
+/* VFP support. We follow the convention used for VFP instructions:
+ Single precision routines have a "s" suffix, double precision a
"d" suffix. */
/* Convert host exception flags to vfp form. */