dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and to


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. 9b3edaec6fc3ea76276f178b8a89d93ab2484ddd
Date: Mon, 05 Apr 2010 16:42:13 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "DotGNU Portable.NET engine, compilers and tools (pnet)".

The branch, master has been updated
       via  9b3edaec6fc3ea76276f178b8a89d93ab2484ddd (commit)
      from  8b5c977f1598c5effbe71a1ae0cb8b350414f9ab (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/pnet.git/commit/?id=9b3edaec6fc3ea76276f178b8a89d93ab2484ddd

commit 9b3edaec6fc3ea76276f178b8a89d93ab2484ddd
Author: Klaus Treichel <address@hidden>
Date:   Mon Apr 5 18:41:51 2010 +0200

    Add float support for arm unroller if vfp coprocessor is available.

diff --git a/ChangeLog b/ChangeLog
index b8b9c02..5d4573b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2010-04-05  Klaus Treichel  <address@hidden>
+
+       * engine/arm_codegen.h: Add code generation macros for arm vfp support.
+
+       * engine/md_arm.c (_md_arm_cmp_float): Added.
+
+       * engine/md_arm.h: Add unroller code generation macros for arm float
+       support.
+
+       * engine/unroll_arith.c (COP_PREFIX_ABS_R4, COP_PREFIX_ABS_R8,
+       COP_PREFIX_SQRT): Add unroller support for these cvm opcodes.
+
 2010-04-02  Klaus Treichel  <address@hidden>
 
        * support/interlocked_arm.h (ILInterlockedCompareAndExchangeI4): Use a
diff --git a/engine/arm_codegen.h b/engine/arm_codegen.h
index a7b04e0..b918010 100644
--- a/engine/arm_codegen.h
+++ b/engine/arm_codegen.h
@@ -1,7 +1,7 @@
 /*
  * arm_codegen.h - Code generation macros for the ARM processor.
  *
- * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2003, 2010  Southern Storm Software, Pty Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,6 +54,117 @@ typedef enum
 
 } ARM_REG;
 
+#ifdef __VFP_FP__
+
+#define ARM_HAS_FLOAT 1
+
+/*
+ * Register definitions for the arm vfp coprocessor.
+ *
+ * NOTE: Double precision operations are available only in D variants.
+ * Arm: Variant VFPv1D supports double precision while VFP1xD doesn't.
+ *      By default double precision support is present.
+ */
+
+/*
+ * VFP Coprocessor numbers.
+ */
+#define ARMVFP_CSINGLE         10
+#define ARMVFP_CDOUBLE         11
+
+/*
+ * VFP Register numbers.
+ */
+typedef enum
+{
+       /*
+        * Single precision registers.
+        */
+       ARMVFP_S0       = 0,
+       ARMVFP_S1       = 1,
+       ARMVFP_S2       = 2,
+       ARMVFP_S3       = 3,
+       ARMVFP_S4       = 4,
+       ARMVFP_S5       = 5,
+       ARMVFP_S6       = 6,
+       ARMVFP_S7       = 7,
+       ARMVFP_S8       = 8,
+       ARMVFP_S9       = 9,
+       ARMVFP_S10      = 10,
+       ARMVFP_S11      = 11,
+       ARMVFP_S12      = 12,
+       ARMVFP_S13      = 13,
+       ARMVFP_S14      = 14,
+       ARMVFP_S15      = 15,
+       ARMVFP_S16      = 16,
+       ARMVFP_S17      = 17,
+       ARMVFP_S18      = 18,
+       ARMVFP_S19      = 19,
+       ARMVFP_S20      = 20,
+       ARMVFP_S21      = 21,
+       ARMVFP_S22      = 22,
+       ARMVFP_S23      = 23,
+       ARMVFP_S24      = 24,
+       ARMVFP_S25      = 25,
+       ARMVFP_S26      = 26,
+       ARMVFP_S27      = 27,
+       ARMVFP_S28      = 28,
+       ARMVFP_S29      = 29,
+       ARMVFP_S30      = 30,
+       ARMVFP_S31      = 31,
+       /*
+        * Double precision registers.
+        * NOTE: The double precision registers overlap with the single
+        * precision registers.
+        * For example ARMVFP_D0 overlaps with ARMVFP_S0 and ARMVFP_S1,
+        * ARMVFP_D1 overlaps with ARMVFP_S2 and ARMVFP_S3, ...
+        * ARMVFP_Dn overlaps with ARMVFP_S(2n) and ARMVFP_S(2n+1)
+        */
+       ARMVFP_D0       = 0,
+       ARMVFP_D1       = 1,
+       ARMVFP_D2       = 2,
+       ARMVFP_D3       = 3,
+       ARMVFP_D4       = 4,
+       ARMVFP_D5       = 5,
+       ARMVFP_D6       = 6,
+       ARMVFP_D7       = 7,
+       ARMVFP_D8       = 8,
+       ARMVFP_D9       = 9,
+       ARMVFP_D10      = 10,
+       ARMVFP_D11      = 11,
+       ARMVFP_D12      = 12,
+       ARMVFP_D13      = 13,
+       ARMVFP_D14      = 14,
+       ARMVFP_D15      = 15,
+       /*
+        * VFP system registers for moving a vfp system register to one
+        * of the regular arm registers.
+        */
+       ARMVFP_FPSID    = 0,
+       ARMVFP_FPSCR    = 1,
+       ARMVFP_FPEXC    = 8
+
+} ARMVFP_REG;
+
+#define ARM_D0 ARMVFP_D0
+#define ARM_D1 ARMVFP_D1
+#define ARM_D2 ARMVFP_D2
+#define ARM_D3 ARMVFP_D3
+#define ARM_D4 ARMVFP_D4
+#define ARM_D5 ARMVFP_D5
+#define ARM_D6 ARMVFP_D6
+#define ARM_D7 ARMVFP_D7
+#define ARM_D8 ARMVFP_D8
+#define ARM_D9 ARMVFP_D9
+#define ARM_D10        ARMVFP_D10
+#define ARM_D11        ARMVFP_D11
+#define ARM_D12        ARMVFP_D12
+#define ARM_D13        ARMVFP_D13
+#define ARM_D14        ARMVFP_D14
+#define ARM_D15        ARMVFP_D15
+
+#endif /* __VFP_FP__ */
+
 /*
  * Condition codes.
  */
@@ -715,6 +826,497 @@ extern arm_inst_ptr _arm_mov_reg_imm(arm_inst_ptr inst, 
int reg, int value);
                                                                                
 (basereg), (indexreg)); \
                        } while (0)
 
+#ifdef __VFP_FP__
+
+/*
+ * Instructions valid only with VFP support.
+ */
+
+/*
+ * Move a vfp system register to an arm register
+ */
+#define arm_mov_vfpsreg_reg(inst,cond,reg,vfpsreg) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0ef00a10) | \
+                                                        ((vfpsreg) << 16) | \
+                                                        ((reg) << 12)); \
+                       } while (0)
+
+/*
+ * Move the vfp status register to the arm's cpsr
+ */
+#define arm_mov_vfpstatus(inst) \
+                       do { \
+                               arm_mov_vfpsreg_reg(inst, ARM_CC_AL, ARM_R15, 
ARMVFP_FPSCR); \
+                       } while (0)
+
+/*
+ * Load a floatingpoint value from one or two arm registers.
+ */
+#define arm_load_reg_single(inst,cond,vfpreg,reg) \
+                       do { \
+                               int __load_reg = (int)(vfpreg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e000010) | \
+                                                       ((__load_reg) & 0x1e) 
<< 15 | \
+                                                       (reg) << 12 | \
+                                                       ((__load_reg) & 1) << 7 
| \
+                                                       (ARMVFP_CSINGLE) << 8); 
\
+                       } while (0)
+
+#define arm_load_reg_double(inst,cond,vfpreg,regl,regh) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e000010) | \
+                                                       (vfpreg) << 16 | \
+                                                       (regl) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8); 
\
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e200010) | \
+                                                       (vfpreg) << 16 | \
+                                                       (regh) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8); 
\
+                       } while (0)
+
+/*
+ * Load a floatingpoint value from an address in a register
+ */
+#define arm_load_regbase_single(inst, cond, reg, basereg) \
+                       do { \
+                               int __load_reg = (reg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0d100000) | \
+                                                       ((__load_reg) & 1) << 
22 | \
+                                                       (basereg) << 16 | \
+                                                       ((__load_reg) & 0x1e) 
<< 11 | \
+                                                       (ARMVFP_CSINGLE) << 8); 
\
+                       } while (0)
+
+#define arm_load_regbase_double(inst, cond, reg, basereg) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0d100000) | \
+                                                       (basereg) << 16 | \
+                                                       (reg) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8 | 
\
+                                                       0); \
+                       } while (0)
+
+/*
+ * Load a floatingpoint value from an absolute address.
+ */
+#define arm_load_mem_single(inst, cond, reg, mem) \
+                       do { \
+                               arm_mov_reg_imm((inst), ARM_WORK, (mem)); \
+                               arm_load_regbase_single((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+#define arm_load_mem_double(inst, cond, reg, mem) \
+                       do { \
+                               arm_mov_reg_imm((inst), ARM_WORK, (mem)); \
+                               arm_load_regbase_double((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+/*
+ * Load a floatingpoint value from an address in a register and an offset.
+ */
+#define arm_load_membase_single(inst, cond, reg, basereg, imm) \
+                       do { \
+                               int __load_reg = (reg); \
+                               int __mb_imm = (int)(imm); \
+                               if(((__mb_imm & 3) == 0) && \
+                                       (__mb_imm < (1 << 10)) && \
+                                       (__mb_imm > -(1 << 10))) \
+                               { \
+                                       int __load_u = ((__mb_imm > 0) ? 1 : 
0); \
+                                       if(!__load_u) \
+                                       { \
+                                               __mb_imm = -__mb_imm; \
+                                       } \
+                                       __mb_imm >>= 2; \
+                                       *(inst)++ = (arm_build_prefix((cond), 
0x0d100000) | \
+                                                               (__load_u << 
23) | \
+                                                               ((__load_reg) & 
1) << 22 | \
+                                                               (basereg) << 16 
| \
+                                                               ((__load_reg) & 
0x1e) << 11 | \
+                                                               
(ARMVFP_CSINGLE) << 8 | \
+                                                               __mb_imm); \
+                               } \
+                               else \
+                               { \
+                                       arm_mov_reg_imm((inst), ARM_WORK, 
__mb_imm); \
+                                       arm_alu_reg_reg((inst), ARM_ADD, 
ARM_WORK, ARM_WORK, \
+                                                                       
(basereg)); \
+                                       arm_load_regbase_single((inst), (cond), 
(reg), ARM_WORK); \
+                               } \
+                       } while (0)
+
+#define arm_load_membase_double(inst, cond, reg, basereg, imm) \
+                       do { \
+                               int __sm_imm = (int)(imm); \
+                               if(((__sm_imm & 3) == 0) && \
+                                       (__sm_imm < (1 << 10)) && \
+                                       (__sm_imm > -(1 << 10))) \
+                               { \
+                                       int __u = ((__sm_imm > 0) ? 1 : 0); \
+                                       if(!__u) \
+                                       { \
+                                               __sm_imm = -__sm_imm; \
+                                       } \
+                                       __sm_imm >>= 2; \
+                                       *(inst)++ = (arm_build_prefix((cond), 
0x0d100000) | \
+                                                               (__u << 23) | \
+                                                               (basereg) << 16 
| \
+                                                               (reg) << 12 | \
+                                                               
(ARMVFP_CDOUBLE) << 8 | \
+                                                               __sm_imm); \
+                               } \
+                               else \
+                               { \
+                                       arm_mov_reg_imm((inst), ARM_WORK, 
__sm_imm); \
+                                       arm_alu_reg_reg((inst), ARM_ADD, 
ARM_WORK, ARM_WORK, \
+                                                                       
(basereg)); \
+                                       arm_load_regbase_double((inst), (cond), 
(reg), ARM_WORK); \
+                               } \
+                       } while (0)
+
+/*
+ * Load a floatingpoint value from a register and an index.
+ */
+#define arm_load_memindex_single(inst, cond, reg, basereg, indexreg) \
+                       do { \
+                arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), 2); \
+                               arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, 
ARM_WORK, \
+                                                               (basereg)); \
+                               arm_load_regbase_single((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+#define arm_load_memindex_double(inst, cond, reg, basereg, indexreg) \
+                       do { \
+                arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), 3); \
+                               arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, 
ARM_WORK, \
+                                                               (basereg)); \
+                               arm_load_regbase_double((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+
+/*
+ * Store a floatingpoint register to one or two arm registers.
+ */
+#define arm_store_reg_single(inst, cond, reg, vfpreg) \
+                       do { \
+                               int __reg = (int)(vfpreg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e100010) | \
+                                                       ((__reg) & 0x1e) << 15 
| \
+                                                       (reg) << 12 | \
+                                                       (ARMVFP_CSINGLE) << 8 | 
\
+                                                       ((__reg) & 1) << 7); \
+                               } while (0)
+
+#define arm_store_reg_double(inst, cond, regl, regh, vfpreg) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e100010) | \
+                                                       (vfpreg) << 16 | \
+                                                       (regl) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8); 
\
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0e300010) | \
+                                                       (vfpreg) << 16 | \
+                                                       (regh) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8); 
\
+                               } while (0)
+
+
+/*
+ * Store a floatingpoint value to an address in a register.
+ */
+#define arm_store_regbase_single(inst, cond, reg, basereg) \
+                       do { \
+                               int __reg = (reg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0d000000) | \
+                                                       ((__reg) & 1) << 22 | \
+                                                       (basereg) << 16 | \
+                                                       ((__reg) & 0x1e) << 11 
| \
+                                                       (ARMVFP_CSINGLE) << 8 | 
\
+                                                       0); \
+                       } while (0)
+
+#define arm_store_regbase_double(inst, cond, reg, basereg) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0d000000) | \
+                                                       (basereg) << 16 | \
+                                                       (reg) << 12 | \
+                                                       (ARMVFP_CDOUBLE) << 8 | 
\
+                                                       0); \
+                       } while (0)
+
+#define arm_store_membase_single(inst, cond, reg, basereg, imm) \
+                       do { \
+                               int __reg = (reg); \
+                               int __sm_imm = (int)(imm); \
+                               if(((__sm_imm & 3) == 0) && \
+                                       (__sm_imm < (1 << 10)) && \
+                                       (__sm_imm > -(1 << 10))) \
+                               { \
+                                       int __u = ((__sm_imm > 0) ? 1 : 0); \
+                                       if(!__u) \
+                                       { \
+                                               __sm_imm = -__sm_imm; \
+                                       } \
+                                       __sm_imm >>= 2; \
+                                       *(inst)++ = (arm_build_prefix((cond), 
0x0d000000) | \
+                                                               (__u << 23) | \
+                                                               ((__reg) & 1) 
<< 22 | \
+                                                               (basereg) << 16 
| \
+                                                               ((__reg) & 
0x1e) << 11 | \
+                                                               
(ARMVFP_CSINGLE) << 8 | \
+                                                               __sm_imm); \
+                               } \
+                               else \
+                               { \
+                                       arm_mov_reg_imm((inst), ARM_WORK, 
__sm_imm); \
+                                       arm_alu_reg_reg((inst), ARM_ADD, 
ARM_WORK, ARM_WORK, \
+                                                                       
(basereg)); \
+                                       arm_store_regbase_single((inst), 
(cond), (reg), ARM_WORK); \
+                               } \
+                       } while (0)
+
+#define arm_store_membase_double(inst, cond, reg, basereg, imm) \
+                       do { \
+                               int __sm_imm = (int)(imm); \
+                               if(((__sm_imm & 3) == 0) && \
+                                       (__sm_imm < (1 << 10)) && \
+                                       (__sm_imm > -(1 << 10))) \
+                               { \
+                                       int __u = ((__sm_imm > 0) ? 1 : 0); \
+                                       if(!__u) \
+                                       { \
+                                               __sm_imm = -__sm_imm; \
+                                       } \
+                                       __sm_imm >>= 2; \
+                                       *(inst)++ = (arm_build_prefix((cond), 
0x0d000000) | \
+                                                               (__u << 23) | \
+                                                               (basereg) << 16 
| \
+                                                               (reg) << 12 | \
+                                                               
(ARMVFP_CDOUBLE) << 8 | \
+                                                               __sm_imm); \
+                               } \
+                               else \
+                               { \
+                                       arm_mov_reg_imm((inst), ARM_WORK, 
__sm_imm); \
+                                       arm_alu_reg_reg((inst), ARM_ADD, 
ARM_WORK, ARM_WORK, \
+                                                                       
(basereg)); \
+                                       arm_store_regbase_double((inst), 
(cond), (reg), ARM_WORK); \
+                               } \
+                       } while (0)
+
+#define arm_store_memindex_single(inst, cond, reg, basereg, indexreg) \
+                       do { \
+                arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), 2); \
+                               arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, 
ARM_WORK, \
+                                                               (basereg)); \
+                               arm_store_regbase_single((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+#define arm_store_memindex_double(inst, cond, reg, basereg, indexreg) \
+                       do { \
+                arm_shift_reg_imm8((inst), ARM_SHL, ARM_WORK, (indexreg), 3); \
+                               arm_alu_reg_reg((inst), ARM_ADD, ARM_WORK, 
ARM_WORK, \
+                                                               (basereg)); \
+                               arm_store_regbase_double((inst), (cond), (reg), 
ARM_WORK); \
+                       } while (0)
+
+/*
+ * Conversion macros
+ */
+
+/*
+ * Convert from single precision to double precision
+ */
+#define arm_cvt_single_double_reg_reg(inst, cond, dreg, sreg) \
+                       do { \
+                               int __cvt_sreg = (int)(sreg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb700c0) | \
+                                                       ((dreg) << 12) | \
+                                                       ((__cvt_sreg & 1) << 5) 
| \
+                                                       ((__cvt_sreg & 0x1e) >> 
1) | \
+                                                       ((ARMVFP_CSINGLE) << 
8)); \
+                       } while (0)
+
+/*
+ * Convert from double precision to single precision
+ */
+#define arm_cvt_double_single_reg_reg(inst, cond, sreg, dreg) \
+                       do { \
+                               int __cvt_sreg = (int)(sreg); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb700c0) | \
+                                                       ((__cvt_sreg & 1) << 
22) | \
+                                                       ((__cvt_sreg & 0x1e) << 
11) | \
+                                                       ((ARMVFP_CDOUBLE) << 8) 
| \
+                                                       (dreg)); \
+                       } while (0)
+
+/*
+ * Compare two floatingpoint values (nonsignaling)  FCMPx.
+ */
+#define arm_cmpn_single_reg_reg(inst,cond,sreg1,sreg2) \
+                       do { \
+                               int __cmpn_sreg1 = (int)(sreg1); \
+                               int __cmpn_sreg2 = (int)(sreg2); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb40040) | \
+                                                       ((__cmpn_sreg1 & 1) << 
22) | \
+                                                       ((__cmpn_sreg1 & 0x1e) 
<< 11) | \
+                                                       ((ARMVFP_CSINGLE) << 8) 
| \
+                                                       ((__cmpn_sreg2 & 1) << 
5) | \
+                                                       ((__cmpn_sreg2 & 0x1e) 
>> 1)); \
+                       } while (0)
+
+#define arm_cmpn_double_reg_reg(inst,cond,sreg1,sreg2) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb40040) | \
+                                                       ((sreg1) << 12) | \
+                                                       ((ARMVFP_CDOUBLE) << 8) 
| \
+                                                       (sreg2)); \
+                       } while (0)
+
+/*
+ * Compare two floatingpoint values (signaling)  FCMPEx.
+ */
+#define arm_cmps_single_reg_reg(inst,cond,sreg1,sreg2) \
+                       do { \
+                               int __cmps_sreg1 = (int)(sreg1); \
+                               int __cmps_sreg2 = (int)(sreg2); \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb400c0) | \
+                                                       ((__cmps_sreg1 & 1) << 
22) | \
+                                                       ((__cmps_sreg1 & 0x1e) 
<< 11) | \
+                                                       ((ARMVFP_CSINGLE) << 8) 
| \
+                                                       ((__cmps_sreg2 & 1) << 
5) | \
+                                                       ((__cmps_sreg2 & 0x1e) 
>> 1)); \
+                       } while (0)
+
+#define arm_cmps_double_reg_reg(inst,cond,sreg1,sreg2) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), 
0x0eb400c0) | \
+                                                       ((sreg1) << 12) | \
+                                                       ((ARMVFP_CDOUBLE) << 8) 
| \
+                                                       (sreg2)); \
+                       } while (0)
+
+/*
+ * Emit an unary operation for single precision floatingpoint values.
+ */
+#define arm_unary_single_reg(inst,cond,dreg,sreg,mask) \
+                       do { \
+                               int __uns_dreg = (int)(dreg); \
+                               int __uns_sreg = (int)(sreg); \
+                               *(inst)++ = (arm_build_prefix((cond), (mask)) | 
\
+                                                       ((__uns_dreg & 1) << 
22) | \
+                                                       ((__uns_dreg & 0x1e) << 
11) | \
+                                                       (ARMVFP_CSINGLE) << 8 | 
\
+                                                       ((__uns_sreg & 1) << 5) 
| \
+                                                       ((__uns_sreg & 0x1e) >> 
1)); \
+                       } while (0)
+
+/*
+ * Emit an unary operation for double precision floatingpoint values.
+ */
+#define arm_unary_double_reg(inst,cond,dreg,sreg,mask) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), (mask)) | 
\
+                                                       ((dreg) << 12) | \
+                                                       ((ARMVFP_CDOUBLE) << 8) 
| \
+                                                       (sreg)); \
+                       } while (0)
+
+/*
+ * Emit a binary operation for single precision floatingpoint values.
+ */
+#define arm_binary_single_reg_reg(inst,cond,dreg,sreg1,sreg2,mask) \
+                       do { \
+                               int __bins_dreg = (int)(dreg); \
+                               int __bins_sreg1 = (int)(sreg1); \
+                               int __bins_sreg2 = (int)(sreg2); \
+                               *(inst)++ = (arm_build_prefix((cond), (mask)) | 
\
+                                                       ((__bins_dreg & 1) << 
22) | \
+                                                       ((__bins_sreg1 & 0x1e) 
<< 15) | \
+                                                       ((__bins_dreg & 0x1e) 
<< 11) | \
+                                                       (ARMVFP_CSINGLE) << 8 | 
\
+                                                       ((__bins_sreg1 & 1) << 
7) | \
+                                                       ((__bins_sreg2 & 1) << 
5) | \
+                                                       ((__bins_sreg2 & 0x1e) 
>> 1)); \
+                       } while (0)
+
+/*
+ * Emit a binary operation for double precision floatingpoint values.
+ */
+#define arm_binary_double_reg_reg(inst,cond,dreg,sreg1,sreg2,mask) \
+                       do { \
+                               *(inst)++ = (arm_build_prefix((cond), (mask)) | 
\
+                                                       ((sreg1) << 16) | \
+                                                       ((dreg) << 12) | \
+                                                       (ARMVFP_CDOUBLE) << 8 | 
\
+                                                       (sreg2)); \
+                       } while (0)
+
+/*
+ * Add two floatingpoint values.
+ */
+#define arm_add_single_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_single_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e300000)
+
+#define arm_add_double_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_double_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e300000)
+
+/*
+ * Subtract two floatingpoint values.
+ */
+#define arm_sub_single_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_single_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e300040)
+
+#define arm_sub_double_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_double_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e300040)
+
+/*
+ * Multiply two floatingpoint values.
+ */
+#define arm_mul_single_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_single_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e200000)
+
+#define arm_mul_double_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_double_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e200000)
+
+/*
+ * Divide two floatingpoint values.
+ */
+#define arm_div_single_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_single_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e800000)
+
+#define arm_div_double_reg_reg(inst,cond,dreg,sreg1,sreg2) \
+                       arm_binary_double_reg_reg((inst), (cond), (dreg), 
(sreg1), (sreg2), 0x0e800000)
+
+/*
+ * Get the absolute of a floatingpoint value.
+ */
+#define arm_abs_single_reg(inst,cond,dreg,sreg) \
+                       arm_unary_single_reg((inst), (cond), (dreg), (sreg), 
0x0eb000c0)
+
+#define arm_abs_double_reg(inst,cond,dreg,sreg) \
+                       arm_unary_double_reg((inst), (cond), (dreg), (sreg), 
0x0eb000c0)
+
+/*
+ * Negate a floatingpoint value.
+ */
+#define arm_neg_single_reg(inst,cond,dreg,sreg) \
+                       arm_unary_single_reg((inst), (cond), (dreg), (sreg), 
0x0eb10040)
+
+#define arm_neg_double_reg(inst,cond,dreg,sreg) \
+                       arm_unary_double_reg((inst), (cond), (dreg), (sreg), 
0x0eb10040)
+
+/*
+ * Get the sqare root of a floatingpoint value.
+ */
+#define arm_sqrt_single_reg(inst,cond,dreg,sreg) \
+                       arm_unary_single_reg((inst), (cond), (dreg), (sreg), 
0x0eb100c0)
+
+#define arm_sqrt_double_reg(inst,cond,dreg,sreg) \
+                       arm_unary_double_reg((inst), (cond), (dreg), (sreg), 
0x0eb100c0)
+
+#endif /* __VFP_FP__ */
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/engine/md_arm.c b/engine/md_arm.c
index 6eedcfe..facb51b 100644
--- a/engine/md_arm.c
+++ b/engine/md_arm.c
@@ -1,7 +1,7 @@
 /*
  * md_arm.c - Machine-dependent definitions for ARM.
  *
- * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2003, 2010  Southern Storm Software, Pty Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -168,6 +168,42 @@ md_inst_ptr _md_arm_setcc(md_inst_ptr inst, int reg, int 
cond, int invcond)
        return inst;
 }
 
+#ifdef ARM_HAS_FLOAT
+
+md_inst_ptr _md_arm_cmp_float(md_inst_ptr inst, int dreg, int sreg1,
+                                                         int sreg2, int lessop)
+{
+       /* Remove the MD_FP_REG flag from the source registers */
+       sreg1 &= ~MD_FREG_MASK;
+       sreg2 &= ~MD_FREG_MASK;
+       /* perform a nonsignaling compare */
+       arm_cmpn_double_reg_reg(inst, ARM_CC_AL, sreg1, sreg2);
+       /* Initialize result with 0. This handles the equal result */
+       arm_mov_reg_imm8(inst, dreg, 0);
+       /* Move the float condition flags to arm */
+       arm_mov_vfpstatus(inst);
+       if(lessop)
+       {
+               /* Do it just how specified for now */
+               /* Set the result to 1 if C is set and Z is not set */
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, dreg, dreg, 1, ARM_CC_HI);
+               /* Set the result to -1 if either N or V are set */
+               arm_alu_reg_imm8_cond(inst, ARM_MVN, dreg, dreg, 0, ARM_CC_LT);
+       }
+       else
+       {
+               /* Set the result to 1 if C is set and Z is not set */
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, dreg, dreg, 1, ARM_CC_HI);
+               /* Set the result to -1 if N is set */
+               arm_alu_reg_imm8_cond(inst, ARM_MVN, dreg, dreg, 0, ARM_CC_MI);
+               /* Set the result to 1 if V is set */
+               arm_alu_reg_imm8_cond(inst, ARM_MOV, dreg, dreg, 1, ARM_CC_VS);
+       }
+       return inst;
+}
+
+#endif /* ARM_HAS_FLOAT */
+
 #endif /* CVM_ARM */
 
 #ifdef __cplusplus
diff --git a/engine/md_arm.h b/engine/md_arm.h
index 512b240..0b2aed9 100644
--- a/engine/md_arm.h
+++ b/engine/md_arm.h
@@ -1,7 +1,7 @@
 /*
  * md_arm.h - Machine-dependent definitions for ARM.
  *
- * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2003, 2010  Southern Storm Software, Pty Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,6 +58,27 @@ extern       "C" {
  * -1 is the list terminator.  The floating point register numbers
  * must include the MD_FREG_MASK value.
  */
+#ifdef ARM_HAS_FLOAT
+
+#define        MD_FREG_0               (ARM_D0 | MD_FREG_MASK)
+#define        MD_FREG_1               (ARM_D1 | MD_FREG_MASK)
+#define        MD_FREG_2               (ARM_D2 | MD_FREG_MASK)
+#define        MD_FREG_3               (ARM_D3 | MD_FREG_MASK)
+#define        MD_FREG_4               (ARM_D4 | MD_FREG_MASK)
+#define        MD_FREG_5               (ARM_D5 | MD_FREG_MASK)
+#define        MD_FREG_6               (ARM_D6 | MD_FREG_MASK)
+#define        MD_FREG_7               (ARM_D7 | MD_FREG_MASK)
+#define        MD_FREG_8               -1
+#define        MD_FREG_9               -1
+#define        MD_FREG_10              -1
+#define        MD_FREG_11              -1
+#define        MD_FREG_12              -1
+#define        MD_FREG_13              -1
+#define        MD_FREG_14              -1
+#define        MD_FREG_15              -1
+
+#else /* !ARM_HAS_FLOAT */
+
 #define        MD_FREG_0               -1
 #define        MD_FREG_1               -1
 #define        MD_FREG_2               -1
@@ -75,6 +96,8 @@ extern        "C" {
 #define        MD_FREG_14              -1
 #define        MD_FREG_15              -1
 
+#endif /* !ARM_HAS_FLOAT */
+
 /*
  * Set this to a non-zero value if floating-point registers are organised
  * in a stack (e.g. the x87 FPU).
@@ -172,15 +195,41 @@ typedef arm_inst_ptr      md_inst_ptr;
  * is at a particular memory location.  If the system does not use
  * floating-point registers, then load onto the top of the stack.
  */
+#ifdef ARM_HAS_FLOAT
+
+#define md_load_const_float_32(inst,reg,mem) \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __sreg = __dreg << 1; \
+                               arm_load_mem_single((inst), ARM_CC_AL, __sreg, 
(mem)); \
+                               arm_cvt_single_double_reg_reg((inst), 
ARM_CC_AL, __dreg, __sreg); \
+                       } while (0)
+
+#else /* !ARM_HAS_FLOAT */
+
 #define        md_load_const_float_32(inst,reg,mem)    do { ; } while (0)
 
+#endif /* !ARM_HAS_FLOAT */
+
 /*
  * Load a 64-bit floating-point constant into a register.  The constant
  * is at a particular memory location.  If the system does not use
  * floating-point registers, then load onto the top of the stack.
  */
+#ifdef ARM_HAS_FLOAT
+
+#define md_load_const_float_64(inst,reg,mem) \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_load_mem_double((inst), ARM_CC_AL, __dreg, 
(mem)); \
+                       } while (0)
+
+#else /* !ARM_HAS_FLOAT */
+
 #define        md_load_const_float_64(inst,reg,mem)    do { ; } while (0)
 
+#endif /* !ARM_HAS_FLOAT */
+
 /*
  * Load the 32-bit constant zero into a register.  This will zero-extend
  * if the native word size is larger.
@@ -247,6 +296,27 @@ typedef arm_inst_ptr       md_inst_ptr;
  * loaded into "reg".  Otherwise it is loaded onto the top of the
  * floating-point stack.
  */
+#ifdef ARM_HAS_FLOAT
+
+#define        md_load_membase_float_32(inst,reg,basereg,offset)       \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __sreg = __dreg << 1; \
+                               arm_load_membase_single((inst), ARM_CC_AL, 
__sreg, (basereg), (offset)); \
+                               arm_cvt_single_double_reg_reg((inst), 
ARM_CC_AL, __dreg, __sreg); \
+                       } while (0)
+
+#define md_load_membase_float_64(inst,reg,basereg,offset)      \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_load_membase_double((inst), ARM_CC_AL, 
__dreg, (basereg), (offset)); \
+                       } while (0)
+
+#define        md_load_membase_float_native(inst,reg,basereg,offset) \
+                       md_load_membase_float_64(inst,reg,basereg,offset)
+
+#else /* !ARM_HAS_FLOAT */
+
 #define        md_load_membase_float_32(inst,reg,basereg,offset)       \
                        do { ; } while (0)
 #define        md_load_membase_float_64(inst,reg,basereg,offset)       \
@@ -254,6 +324,8 @@ typedef arm_inst_ptr        md_inst_ptr;
 #define        md_load_membase_float_native(inst,reg,basereg,offset)   \
                        do { ; } while (0)
 
+#endif /* !ARM_HAS_FLOAT */
+
 /*
  * Store a 32-bit word register to an offset from a pointer register.
  */
@@ -306,6 +378,27 @@ typedef arm_inst_ptr       md_inst_ptr;
  * stored from "reg".  Otherwise it is stored from the top of the
  * floating-point stack.
  */
+#ifdef ARM_HAS_FLOAT
+
+#define        md_store_membase_float_32(inst,reg,basereg,offset)      \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __sreg = __dreg << 1; \
+                               arm_cvt_double_single_reg_reg((inst), 
ARM_CC_AL, __sreg, __dreg); \
+                               arm_store_membase_single((inst), ARM_CC_AL, 
__sreg, (basereg), (offset)); \
+                       } while (0)
+
+#define md_store_membase_float_64(inst,reg,basereg,offset)     \
+                       do { \
+                               int __dreg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_store_membase_double((inst), ARM_CC_AL, 
__dreg, (basereg), (offset)); \
+                       } while (0)
+
+#define        md_store_membase_float_native(inst,reg,basereg,offset) \
+                       md_store_membase_float_64(inst,reg,basereg,offset)
+
+#else /* !ARM_HAS_FLOAT */
+
 #define        md_store_membase_float_32(inst,reg,basereg,offset)      \
                        do { ; } while (0)
 #define        md_store_membase_float_64(inst,reg,basereg,offset)      \
@@ -313,6 +406,8 @@ typedef arm_inst_ptr        md_inst_ptr;
 #define        md_store_membase_float_native(inst,reg,basereg,offset)  \
                        do { ; } while (0)
 
+#endif /* !ARM_HAS_FLOAT */
+
 /*
  * Add an immediate value to a register.
  */
@@ -549,6 +644,15 @@ extern md_inst_ptr _md_arm_setcc(md_inst_ptr inst, int reg,
                                                                 ARM_CC_LT_UN); 
\
                        } while (0)
 
+#ifdef ARM_HAS_FLOAT
+
+#define md_cmp_reg_reg_float(inst,dreg,sreg1,sreg2,lessop) \
+                       do { \
+                               inst = _md_arm_cmp_float((inst), (dreg), 
(sreg1), (sreg2), \
+                                                                               
 (lessop)); \
+                       } while (0)
+#endif /* ARM_HAS_FLOAT */
+
 /*
  * Set the condition codes based on comparing two values.
  * The "cond" value indicates the type of condition that we
@@ -726,6 +830,64 @@ extern md_inst_ptr _md_arm_setcc(md_inst_ptr inst, int reg,
 #define        md_store_memindex_ushort(inst,reg,basereg,indexreg,disp)        
\
                        arm_store_memindex_ushort((inst), (reg), (basereg), 
(indexreg))
 
+#ifdef ARM_HAS_FLOAT
+
+#define md_add_reg_reg_float(inst,reg,reg2) \
+                       do { \
+                               int __add_reg1 = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __add_reg2 = ((int)(reg2) & ~MD_FREG_MASK); 
\
+                               arm_add_double_reg_reg(inst, ARM_CC_AL, 
__add_reg1, \
+                                                                               
                                __add_reg1, \
+                                                                               
                                __add_reg2); \
+                       } while (0)
+
+#define md_sub_reg_reg_float(inst,reg,reg2) \
+                       do { \
+                               int __sub_reg1 = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __sub_reg2 = ((int)(reg2) & ~MD_FREG_MASK); 
\
+                               arm_sub_double_reg_reg(inst, ARM_CC_AL, 
__sub_reg1, \
+                                                                               
                                __sub_reg1, \
+                                                                               
                                __sub_reg2); \
+                       } while (0)
+
+#define md_mul_reg_reg_float(inst,reg,reg2) \
+                       do { \
+                               int __mul_reg1 = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __mul_reg2 = ((int)(reg2) & ~MD_FREG_MASK); 
\
+                               arm_mul_double_reg_reg(inst, ARM_CC_AL, 
__mul_reg1, \
+                                                                               
                                __mul_reg1, \
+                                                                               
                                __mul_reg2); \
+                       } while (0)
+
+#define md_div_reg_reg_float(inst,reg,reg2) \
+                       do { \
+                               int __div_reg1 = ((int)(reg) & ~MD_FREG_MASK); \
+                               int __div_reg2 = ((int)(reg2) & ~MD_FREG_MASK); 
\
+                               arm_div_double_reg_reg(inst, ARM_CC_AL, 
__div_reg1, \
+                                                                               
                                __div_reg1, \
+                                                                               
                                __div_reg2); \
+                       } while (0)
+
+#define md_neg_reg_float(inst,reg) \
+                       do { \
+                               int __neg_reg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_neg_double_reg(inst, ARM_CC_AL, __neg_reg, 
__neg_reg); \
+                       } while (0)
+
+#define md_abs_reg_float(inst,reg) \
+                       do { \
+                               int __abs_reg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_abs_double_reg(inst, ARM_CC_AL, __abs_reg, 
__abs_reg); \
+                       } while (0)
+
+#define md_sqrt_reg_float(inst,reg) \
+                       do { \
+                               int __sqrt_reg = ((int)(reg) & ~MD_FREG_MASK); \
+                               arm_sqrt_double_reg(inst, ARM_CC_AL, 
__sqrt_reg, __sqrt_reg); \
+                       } while (0)
+
+#endif /* ARM_HAS_FLOAT */
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/engine/unroll_arith.c b/engine/unroll_arith.c
index 6358d90..40fe574 100644
--- a/engine/unroll_arith.c
+++ b/engine/unroll_arith.c
@@ -1,7 +1,7 @@
 /*
  * unroll_arith.c - Arithmetic handling for generic CVM unrolling.
  *
- * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2003, 2010  Southern Storm Software, Pty Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -553,6 +553,8 @@ case COP_FDIV:
 }
 break;
 
+#ifdef md_rem_reg_reg_float
+
 case COP_FREM:
 {
        /* Remainder floating point */
@@ -564,6 +566,8 @@ case COP_FREM:
 }
 break;
 
+#endif /* md_rem_reg_reg_float */
+
 case COP_FNEG:
 {
        /* Negate floating point */
@@ -654,6 +658,8 @@ break;
 
 #ifdef MD_HAS_FP
 
+#ifdef md_cmp_reg_reg_float
+
 case 0x100 + COP_PREFIX_FCMPL:
 {
        /* Compare floating point values */
@@ -686,7 +692,10 @@ case 0x100 + COP_PREFIX_FCMPG:
 }
 break;
 
+#endif /* md_cmp_reg_reg_float */
+
 #endif /* MD_HAS_FP */
+
 case 0x100 + COP_PREFIX_ICMP:
 {
        /* Compare integer values with -1, 0, or 1 result */
@@ -781,4 +790,37 @@ case 0x100 + COP_PREFIX_SETGE:
 }
 break;
 
+#ifdef MD_HAS_FP
+
+#ifdef md_abs_reg_float
+
+case 0x100 + COP_PREFIX_ABS_R4:
+case 0x100 + COP_PREFIX_ABS_R8:
+{
+       /* Absolute value of a floating point */
+       UNROLL_START();
+       reg = GetTopFPRegister(&unroll);
+       md_abs_reg_float(unroll.out, reg);
+       MODIFY_UNROLL_PC(CVM_LEN_NONE);
+}
+break;
+
+#endif /* md_abs_reg_float */
+
+#ifdef md_sqrt_reg_float
+
+case 0x100 + COP_PREFIX_SQRT:
+{
+       /* Sqare root of a floating point */
+       UNROLL_START();
+       reg = GetTopFPRegister(&unroll);
+       md_sqrt_reg_float(unroll.out, reg);
+       MODIFY_UNROLL_PC(CVM_LEN_NONE);
+}
+break;
+
+#endif /* md_sqrt_reg_float */
+
+#endif /* MD_HAS_FP */
+
 #endif /* IL_UNROLL_CASES */

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog             |   12 +
 engine/arm_codegen.h  |  604 ++++++++++++++++++++++++++++++++++++++++++++++++-
 engine/md_arm.c       |   38 +++-
 engine/md_arm.h       |  164 +++++++++++++-
 engine/unroll_arith.c |   44 ++++-
 5 files changed, 858 insertions(+), 4 deletions(-)


hooks/post-receive
-- 
DotGNU Portable.NET engine, compilers and tools (pnet)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]