* jit-gen-arm.h: add floating-point instruction macros.
+ * jit/jit-gen-arm.h, jit/jit-rules-arm.c, jit/jit-rules-arm.h,
+ jit/jit-rules-arm.sel: expand floating-point instructions for ARM.
+
2004-06-06 Miroslaw Dobrzanski-Neumann <mne@mosaic-ag.com>
* jit/jit-alloc.c (jit_flush_exec): flush cache lines properly
/*
* Load a floating-point value from an address into a register.
*/
-#define arm_load_membase_float_either(inst,reg,basereg,imm,mask) \
+#define arm_load_membase_float(inst,reg,basereg,imm,mask) \
do { \
int __mb_offset = (int)(imm); \
if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
*(inst)++ = arm_prefix(0x0D100000 | (mask)) | \
(((unsigned int)(basereg)) << 16) | \
(((unsigned int)(reg)) << 12) | \
- ((unsigned int)((__mb_offset / 4) & 0xFF); \
+ ((unsigned int)((__mb_offset / 4) & 0xFF)); \
} \
else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
(__mb_offset & 3) == 0) \
/*
* Store a floating-point value to a memory address.
*/
-#define arm_store_membase_float_either(inst,reg,basereg,imm,mask) \
+#define arm_store_membase_float(inst,reg,basereg,imm,mask) \
do { \
int __mb_offset = (int)(imm); \
if(__mb_offset >= 0 && __mb_offset < (1 << 10) && \
*(inst)++ = arm_prefix(0x0D800000 | (mask)) | \
(((unsigned int)(basereg)) << 16) | \
(((unsigned int)(reg)) << 12) | \
- ((unsigned int)((__mb_offset / 4) & 0xFF); \
+ ((unsigned int)((__mb_offset / 4) & 0xFF)); \
} \
else if(__mb_offset > -(1 << 10) && __mb_offset < 0 && \
(__mb_offset & 3) == 0) \
#include "jit-setjmp.h"
#include <stdio.h>
-/*
- * Determine if we actually have floating-point registers.
- */
-#if JIT_APPLY_NUM_FLOAT_REGS != 0 || JIT_APPLY_RETURN_FLOATS_AFTER != 0
- #define JIT_ARM_HAS_FLOAT_REGS 1
-#endif
-
/*
* Round a size up to a multiple of the stack word size.
*/
void _jit_init_backend(void)
{
-#ifndef JIT_ARM_HAS_FLOAT_REGS
- /* Turn off floating-point registers, as this ARM core doesn't have them */
- int reg;
- for(reg = 16; reg < JIT_NUM_REGS; ++reg)
- {
- _jit_reg_info[reg].flags = JIT_REG_FIXED;
- }
-#endif
+ /* Nothing to do here */
}
void _jit_gen_get_elf_info(jit_elf_info_t *info)
return 0;
}
}
+#ifdef JIT_ARM_HAS_FLOAT_REGS
+ else if(return_type->kind == JIT_TYPE_FLOAT32 ||
+ return_type->kind == JIT_TYPE_FLOAT64 ||
+ return_type->kind == JIT_TYPE_NFLOAT)
+ {
+ if(!jit_insn_return_reg(func, return_value, 16 /* f0 */))
+ {
+ return 0;
+ }
+ }
+#endif
else if(return_type->kind != JIT_TYPE_VOID)
{
- if(!jit_insn_return_reg(func, return_value, ARM_R0))
+ if(!jit_insn_return_reg(func, return_value, 0 /* r0 */))
{
return 0;
}
/* Output an appropriate instruction to spill the value */
offset = (int)(value->frame_offset);
- arm_store_membase(inst, ARM_FP, offset, reg);
- if(other_reg != -1)
+ if(reg < 16)
{
- /* Spill the other word register in a pair */
- offset += sizeof(void *);
- arm_store_membase(inst, ARM_FP, offset, reg);
+ arm_store_membase(inst, reg, ARM_FP, offset);
+ if(other_reg != -1)
+ {
+ /* Spill the other word register in a pair */
+ offset += sizeof(void *);
+ arm_store_membase(inst, other_reg, ARM_FP, offset);
+ }
+ }
+ else if(jit_type_normalize(value->type)->kind == JIT_TYPE_FLOAT32)
+ {
+ arm_store_membase_float32(inst, reg - 16, ARM_FP, offset);
+ }
+ else
+ {
+ arm_store_membase_float64(inst, reg - 16, ARM_FP, offset);
}
/* End the code output process */
void _jit_gen_load_value
(jit_gencode_t gen, int reg, int other_reg, jit_value_t value)
{
- void *ptr;
int offset;
/* Make sure that we have sufficient space */
jit_cache_mark_full(&(gen->posn));
return;
}
- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float32));
- jit_memcpy(ptr, &float32_value, sizeof(float32_value));
- /* TODO */
- /*x86_fld(inst, ptr, 0);*/
+ if(reg < 16)
+ {
+ arm_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
+ *((int *)&float32_value));
+ }
+ else
+ {
+ arm_load_membase_float32
+ (inst, _jit_reg_info[reg].cpu_reg, ARM_PC, 0);
+ arm_jump_imm(inst, 0);
+ *(inst)++ = *((int *)&float32_value);
+ }
}
break;
jit_cache_mark_full(&(gen->posn));
return;
}
- ptr = _jit_cache_alloc(&(gen->posn), sizeof(jit_float64));
- jit_memcpy(ptr, &float64_value, sizeof(float64_value));
- /* TODO */
- /*x86_fld(inst, ptr, 1);*/
+ if(reg < 16)
+ {
+ arm_mov_reg_imm(inst, _jit_reg_info[reg].cpu_reg,
+ ((int *)&float64_value)[0]);
+ arm_mov_reg_imm(inst, _jit_reg_info[other_reg].cpu_reg,
+ ((int *)&float64_value)[1]);
+ }
+ else if((((int)inst) & 7) == 0)
+ {
+ arm_load_membase_float64
+ (inst, _jit_reg_info[reg].cpu_reg, ARM_PC, 0);
+ arm_jump_imm(inst, 4);
+ *(inst)++ = ((int *)&float64_value)[0];
+ *(inst)++ = ((int *)&float64_value)[1];
+ }
+ else
+ {
+ arm_load_membase_float64
+ (inst, _jit_reg_info[reg].cpu_reg, ARM_PC, 4);
+ arm_jump_imm(inst, 8);
+ *(inst)++ = 0;
+ *(inst)++ = ((int *)&float64_value)[0];
+ *(inst)++ = ((int *)&float64_value)[1];
+ }
}
break;
}
case JIT_TYPE_FLOAT32:
{
- /* TODO */
- /*x86_fld_membase(inst, X86_EBP, offset, 0);*/
+ if(reg < 16)
+ {
+ arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
+ ARM_FP, offset);
+ }
+ else
+ {
+ arm_load_membase_float32
+ (inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
+ }
}
break;
case JIT_TYPE_FLOAT64:
case JIT_TYPE_NFLOAT:
{
- /* TODO */
- /*x86_fld_membase(inst, X86_EBP, offset, 1);*/
+ if(reg < 16)
+ {
+ arm_load_membase(inst, _jit_reg_info[reg].cpu_reg,
+ ARM_FP, offset);
+ arm_load_membase(inst, _jit_reg_info[other_reg].cpu_reg,
+ ARM_FP, offset + 4);
+ }
+ else
+ {
+ arm_load_membase_float64
+ (inst, _jit_reg_info[reg].cpu_reg, ARM_FP, offset);
+ }
}
break;
}
#ifndef _JIT_RULES_ARM_H
#define _JIT_RULES_ARM_H
+#include "jit-apply-rules.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+/*
+ * Determine if this ARM core has floating point registers available.
+ */
+#if JIT_APPLY_NUM_FLOAT_REGS != 0 || JIT_APPLY_RETURN_FLOATS_AFTER != 0
+ #define JIT_ARM_HAS_FLOAT_REGS 1
+#endif
+
/*
* Information about all of the registers, in allocation order.
* We use r0-r5 for general-purpose values and r6-r8 for globals.
* Of the floating-point registers, we only use f0-f3 at present,
* so that we don't have to worry about saving the values of f4-f7.
* The floating-point registers are only present on some ARM cores.
- * "_jit_init_backend" will disable the FP registers if they don't exist.
*/
+#ifdef JIT_ARM_HAS_FLOAT_REGS
+ #define JIT_REG_ARM_FLOAT JIT_REG_FLOAT | JIT_REG_CALL_USED
+#else
+ #define JIT_REG_ARM_FLOAT JIT_REG_FIXED
+#endif
#define JIT_REG_INFO \
{"r0", 0, 1, JIT_REG_WORD | JIT_REG_CALL_USED}, \
{"r1", 1, -1, JIT_REG_WORD | JIT_REG_CALL_USED}, \
{"sp", 13, -1, JIT_REG_FIXED | JIT_REG_STACK_PTR}, \
{"lr", 14, -1, JIT_REG_FIXED}, \
{"pc", 15, -1, JIT_REG_FIXED}, \
- {"f0", 0, -1, JIT_REG_FLOAT | JIT_REG_CALL_USED}, \
- {"f1", 1, -1, JIT_REG_FLOAT | JIT_REG_CALL_USED}, \
- {"f2", 2, -1, JIT_REG_FLOAT | JIT_REG_CALL_USED}, \
- {"f3", 3, -1, JIT_REG_FLOAT | JIT_REG_CALL_USED},
+ {"f0", 0, -1, JIT_REG_ARM_FLOAT}, \
+ {"f1", 1, -1, JIT_REG_ARM_FLOAT}, \
+ {"f2", 2, -1, JIT_REG_ARM_FLOAT}, \
+ {"f3", 3, -1, JIT_REG_ARM_FLOAT},
#define JIT_NUM_REGS 20
#define JIT_NUM_GLOBAL_REGS 3
arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
}
+JIT_OP_FADD: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2);
+ }
+
+JIT_OP_FSUB: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2);
+ }
+
+JIT_OP_FMUL: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2);
+ }
+
+JIT_OP_FDIV: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2);
+ }
+
+JIT_OP_FNEG: unary
+ [freg] -> {
+ arm_alu_freg_32(inst, ARM_MNF, $1, $1);
+ }
+
+JIT_OP_DADD: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
+ }
+
+JIT_OP_DSUB: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
+ }
+
+JIT_OP_DMUL: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
+ }
+
+JIT_OP_DDIV: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
+ }
+
+JIT_OP_DNEG: unary
+ [freg] -> {
+ arm_alu_freg(inst, ARM_MNF, $1, $1);
+ }
+
+JIT_OP_NFADD: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
+ }
+
+JIT_OP_NFSUB: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
+ }
+
+JIT_OP_NFMUL: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
+ }
+
+JIT_OP_NFDIV: binary
+ [freg, freg] -> {
+ arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
+ }
+
+JIT_OP_NFNEG: unary
+ [freg] -> {
+ arm_alu_freg(inst, ARM_MNF, $1, $1);
+ }
+
/*
* Bitwise opcodes.
*/
inst = jump_to_epilog(gen, inst, block);
}
-JIT_OP_RETURN_FLOAT32: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_RETURN_FLOAT32: unary_note
+ [freg] -> {
+ if($1 != 0)
+ {
+ arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
+ }
}
-JIT_OP_RETURN_FLOAT64: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_RETURN_FLOAT64: unary_note
+ [freg] -> {
+ if($1 != 0)
+ {
+ arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
+ }
}
-JIT_OP_RETURN_NFLOAT: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_RETURN_NFLOAT: unary_note
+ [freg] -> {
+ if($1 != 0)
+ {
+ arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
+ }
}
JIT_OP_RETURN_SMALL_STRUCT: spill_before
TODO();
}
-JIT_OP_COPY_FLOAT32: manual
- [] -> {
- /* TODO */
- TODO();
- }
+JIT_OP_COPY_FLOAT32: unary
+ [freg] -> {}
-JIT_OP_COPY_FLOAT64: manual
- [] -> {
- /* TODO */
- TODO();
- }
+JIT_OP_COPY_FLOAT64: unary
+ [freg] -> {}
-JIT_OP_COPY_NFLOAT: manual
- [] -> {
- /* TODO */
- TODO();
- }
+JIT_OP_COPY_NFLOAT: unary
+ [freg] -> {}
JIT_OP_COPY_STRUCT: manual
[] -> {
TODO();
}
-JIT_OP_PUSH_FLOAT32: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_PUSH_FLOAT32: unary_note
+ [freg] -> {
+ arm_push_reg_float32(inst, $1);
}
-JIT_OP_PUSH_FLOAT64: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_PUSH_FLOAT64: unary_note
+ [freg] -> {
+ arm_push_reg_float64(inst, $1);
}
-JIT_OP_PUSH_NFLOAT: manual
- [] -> {
- /* TODO */
- TODO();
+JIT_OP_PUSH_NFLOAT: unary_note
+ [freg] -> {
+ arm_push_reg_float64(inst, $1);
}
JIT_OP_PUSH_STRUCT: unary_note