This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH gas/arm support for VFP
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: binutils at sources dot redhat dot com
- Cc: Richard dot Earnshaw at arm dot com
- Date: Tue, 15 Jan 2002 16:07:43 +0000
- Subject: PATCH gas/arm support for VFP
- Organization: ARM Ltd.
- Reply-to: Richard dot Earnshaw at arm dot com
Finally, this is what it has all been leading up to...
This patch adds support to the assembler for the new VFP instructions,
as defined in the ARM Architecture Reference Manual (second edition).
R.
2002-01-15 Richard Earnshaw <rearnsha@arm.com>
Support for VFP instructions
* tc-arm.c (CP_WB_OK, CP_NO_WB): New defines.
(cp_address_required_here): New argument wb_ok. When false, do not
accept write-back forms of addressing. Change all callers.
(FPU_VFP_EXT_NONE, FPU_VFP_EXT_V1xD, FPU_VFP_VFP_V1)
(FPU_VFP_EXT_V2): Define.
(FPU_ARCH_VFP, FPU_ARCH_VFP_V1xD, FPU_ARCH_VFP_V1, FPU_ARCH_VFP_V2):
Define in terms of above.
(vfp_dp_reg_pos, vfp_sp_reg_pos, vfp_ldstm_type): New enums.
(vfp_reg): New struct.
(vfp_regs): New array of registers.
(insns): Add VFP instructions.
(sn_table): New array of VFP single-precision register names.
(dn_table): New array of VFP double-precision register names.
(all_reg_maps): Add the new register tables.
(arm_reg_type): Add new values for above. Increase RET_TYPE_MAX.
(vfp_sp_reg_required_here, vfp_dp_reg_required_here, do_vfp_sp_monadic)
(do_vfp_dp_monadic, do_vfp_sp_dyadic, do_vfp_dp_dyadic)
(do_vfp_reg_from_sp, do_vfp_sp_reg2, do_vfp_sp_from_reg)
(do_vfp_reg_from_dp, do_vfp_reg2_from_dp, do_vfp_dp_from_reg)
(do_vfp_dp_from_reg2, vfp_psr_parse, vfp_psr_required_here)
(do_vfp_reg_from_ctrl, do_vfp_ctrl_from_reg, do_vfp_sp_ldst)
(do_vfp_dp_ldst, vfp_sp_reg_list, vfp_dp_reg_list, vfp_sp_ldstm)
(vfp_dp_ldstm, do_vfp_sp_ldstmia, do_vfp_sp_ldstmdb, do_vfp_ldstmia)
(do_vfp_dp_ldstmdb, do_vfp_xp_ldstmia, do_vfp_xp_ldstmdb)
(do_vfp_sp_compare_z, do_vfp_dp_compare_z, do_vfp_dp_sp_cvt)
(do_vfp_sp_dp_cvt): New functions.
(md_begin): Set soft-float flag for appropriate VFP work.
(md_atof): Handle VFP-format doubles.
(md_parse_option): Handle VFP command-line options.
(md_show_usage): Display VFP command-line options.
Testsuite:
2002-01-15 Richard Earnshaw <rearnsha@arm.com>
* gas/arm/vfp1.s gas/arm/vf1.d: New files.
* gas/arm/vfp1xD.s gas/arm/vf1xD.d: New files.
* gas/arm/vfp-bad.s gas/arm/vfp-bad.l: New files.
* gas/arm/arm.exp: Run new VFP tests.
Index: config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.111
diff -p -r1.111 tc-arm.c
*** tc-arm.c 2002/01/15 14:43:09 1.111
--- tc-arm.c 2002/01/15 15:50:32
***************
*** 82,94 ****
#define ARM_ANY 0x00ffffff
#define ARM_ALL ARM_ANY
! #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
! #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
! #define FPU_NONE 0
#define FPU_ARCH_FPE FPU_FPA_EXT_V1
#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
/* Some useful combinations. */
#define FPU_ANY 0xff000000 /* Note this is ~ARM_ANY. */
--- 82,103 ----
#define ARM_ANY 0x00ffffff
#define ARM_ALL ARM_ANY
! #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
! #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
! #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
! #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
! #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
! #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
! #define FPU_NONE 0
#define FPU_ARCH_FPE FPU_FPA_EXT_V1
#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
+ #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
+ #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
+ #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
+ #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
+
/* Some useful combinations. */
#define FPU_ANY 0xff000000 /* Note this is ~ARM_ANY. */
***************
*** 116,121 ****
--- 125,131 ----
#endif
#endif
+ /* For backwards compatibility we default to the FPA. */
#ifndef FPU_DEFAULT
#define FPU_DEFAULT FPU_ARCH_FPA
#endif
*************** LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS]
*** 264,269 ****
--- 274,283 ----
#define FAIL (-1)
#define SUCCESS (0)
+ /* Whether a Co-processor load/store operation accepts write-back forms. */
+ #define CP_WB_OK 1
+ #define CP_NO_WB 0
+
#define SUFF_S 1
#define SUFF_D 2
#define SUFF_E 3
*************** static const struct asm_psr psrs[] =
*** 468,473 ****
--- 482,519 ----
{"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f},
};
+ enum vfp_dp_reg_pos
+ {
+ VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
+ };
+
+ enum vfp_sp_reg_pos
+ {
+ VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
+ };
+
+ enum vfp_ldstm_type
+ {
+ VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
+ };
+
+ /* VFP system registers. */
+ struct vfp_reg
+ {
+ const char *name;
+ unsigned long regno;
+ };
+
+ static const struct vfp_reg vfp_regs[] =
+ {
+ {"fpsid", 0x00000000},
+ {"FPSID", 0x00000000},
+ {"fpscr", 0x00010000},
+ {"FPSCR", 0x00010000},
+ {"fpexc", 0x00080000},
+ {"FPEXC", 0x00080000}
+ };
+
/* Structure for a hash table entry for a register. */
struct reg_entry
{
*************** static const struct reg_entry fn_table[]
*** 532,537 ****
--- 578,607 ----
{NULL, 0}
};
+ /* VFP SP Registers. */
+ static const struct reg_entry sn_table[] =
+ {
+ {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
+ {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
+ {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
+ {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
+ {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
+ {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
+ {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
+ {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
+ {NULL, 0}
+ };
+
+ /* VFP DP Registers. */
+ static const struct reg_entry dn_table[] =
+ {
+ {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
+ {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
+ {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
+ {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
+ {NULL, 0}
+ };
+
/* Cirrus DSP coprocessor registers. */
static const struct reg_entry mav_mvf_table[] =
{
*************** struct reg_map all_reg_maps[] =
*** 595,600 ****
--- 665,672 ----
{cp_table, 15, NULL, N_("bad or missing co-processor number")},
{cn_table, 15, NULL, N_("co-processor register expected")},
{fn_table, 7, NULL, N_("FPA register expected")},
+ {sn_table, 31, NULL, N_("VFP single precision register expected")},
+ {dn_table, 15, NULL, N_("VFP double precision register expected")},
{mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
{mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
{mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
*************** enum arm_reg_type
*** 611,624 ****
REG_TYPE_CP = 1,
REG_TYPE_CN = 2,
REG_TYPE_FN = 3,
! REG_TYPE_MVF = 4,
! REG_TYPE_MVD = 5,
! REG_TYPE_MVFX = 6,
! REG_TYPE_MVDX = 7,
! REG_TYPE_MVAX = 8,
! REG_TYPE_DSPSC = 9,
! REG_TYPE_MAX = 10
};
/* Functions called by parser. */
--- 683,698 ----
REG_TYPE_CP = 1,
REG_TYPE_CN = 2,
REG_TYPE_FN = 3,
! REG_TYPE_SN = 4,
! REG_TYPE_DN = 5,
! REG_TYPE_MVF = 6,
! REG_TYPE_MVD = 7,
! REG_TYPE_MVFX = 8,
! REG_TYPE_MVDX = 9,
! REG_TYPE_MVAX = 10,
! REG_TYPE_DSPSC = 11,
! REG_TYPE_MAX = 12
};
/* Functions called by parser. */
*************** static void do_fpa_cmp PARAMS ((char *)
*** 691,696 ****
--- 765,797 ----
static void do_fpa_from_reg PARAMS ((char *));
static void do_fpa_to_reg PARAMS ((char *));
+ /* VFP instructions. */
+ static void do_vfp_sp_monadic PARAMS ((char *));
+ static void do_vfp_dp_monadic PARAMS ((char *));
+ static void do_vfp_sp_dyadic PARAMS ((char *));
+ static void do_vfp_dp_dyadic PARAMS ((char *));
+ static void do_vfp_reg_from_sp PARAMS ((char *));
+ static void do_vfp_sp_from_reg PARAMS ((char *));
+ static void do_vfp_sp_reg2 PARAMS ((char *));
+ static void do_vfp_reg_from_dp PARAMS ((char *));
+ static void do_vfp_reg2_from_dp PARAMS ((char *));
+ static void do_vfp_dp_from_reg PARAMS ((char *));
+ static void do_vfp_dp_from_reg2 PARAMS ((char *));
+ static void do_vfp_reg_from_ctrl PARAMS ((char *));
+ static void do_vfp_ctrl_from_reg PARAMS ((char *));
+ static void do_vfp_sp_ldst PARAMS ((char *));
+ static void do_vfp_dp_ldst PARAMS ((char *));
+ static void do_vfp_sp_ldstmia PARAMS ((char *));
+ static void do_vfp_sp_ldstmdb PARAMS ((char *));
+ static void do_vfp_dp_ldstmia PARAMS ((char *));
+ static void do_vfp_dp_ldstmdb PARAMS ((char *));
+ static void do_vfp_xp_ldstmia PARAMS ((char *));
+ static void do_vfp_xp_ldstmdb PARAMS ((char *));
+ static void do_vfp_sp_compare_z PARAMS ((char *));
+ static void do_vfp_dp_compare_z PARAMS ((char *));
+ static void do_vfp_dp_sp_cvt PARAMS ((char *));
+ static void do_vfp_sp_dp_cvt PARAMS ((char *));
+
/* XScale. */
static void do_mia PARAMS ((char *));
static void do_mar PARAMS ((char *));
*************** static int co_proc_number PARAMS ((char
*** 776,783 ****
static int cp_opc_expr PARAMS ((char **, int, int));
static int cp_reg_required_here PARAMS ((char **, int));
static int fp_reg_required_here PARAMS ((char **, int));
static int cp_address_offset PARAMS ((char **));
! static int cp_address_required_here PARAMS ((char **));
static int my_get_float_expression PARAMS ((char **));
static int skip_past_comma PARAMS ((char **));
static int walk_no_bignums PARAMS ((symbolS *));
--- 877,892 ----
static int cp_opc_expr PARAMS ((char **, int, int));
static int cp_reg_required_here PARAMS ((char **, int));
static int fp_reg_required_here PARAMS ((char **, int));
+ static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
+ static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
+ static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
+ static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
+ static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
+ static long vfp_dp_reg_list PARAMS ((char **));
+ static int vfp_psr_required_here PARAMS ((char **str));
+ static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
static int cp_address_offset PARAMS ((char **));
! static int cp_address_required_here PARAMS ((char **, int));
static int my_get_float_expression PARAMS ((char **));
static int skip_past_comma PARAMS ((char **));
static int walk_no_bignums PARAMS ((symbolS *));
*************** static const struct asm_opcode insns[] =
*** 1473,1478 ****
--- 1582,1700 ----
{"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
{"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
+ /* VFP V1xD (single precision). */
+ /* Moves and type conversions. */
+ {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
+ {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
+ {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
+ {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
+ {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
+
+ /* Memory operations. */
+ {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
+ {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
+ {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
+ {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
+ {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
+ {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
+ {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
+ {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
+ {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
+ {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
+ {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
+ {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
+ {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
+ {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
+ {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
+ {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
+ {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
+ {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
+
+ /* Monadic operations. */
+ {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+
+ /* Dyadic operations. */
+ {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+ {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
+
+ /* Comparisons. */
+ {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
+ {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
+ {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
+
+ /* VFP V1 (Double precision). */
+ /* Moves and type conversions. */
+ {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+ {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
+ {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
+ {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
+ {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
+ {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
+ {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
+ {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
+ {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
+ {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
+ {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
+ {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
+ {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
+
+ /* Memory operations. */
+ {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
+ {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
+ {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
+ {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
+ {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
+ {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
+ {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
+ {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
+ {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
+ {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
+
+ /* Monadic operations. */
+ {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+ {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+ {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+
+ /* Dyadic operations. */
+ {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+ {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
+
+ /* Comparisons. */
+ {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+ {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
+ {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
+ {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
+
+ /* VFP V2. */
+ {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
+ {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
+ {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
+ {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
+
/* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
{"mia", 0xee200010, 3, ARM_EXT_XSCALE, do_mia},
{"miaph", 0xee280010, 5, ARM_EXT_XSCALE, do_mia},
*************** cp_address_offset (str)
*** 2723,2730 ****
}
static int
! cp_address_required_here (str)
char ** str;
{
char * p = * str;
int pre_inc = 0;
--- 2945,2953 ----
}
static int
! cp_address_required_here (str, wb_ok)
char ** str;
+ int wb_ok;
{
char * p = * str;
int pre_inc = 0;
*************** cp_address_required_here (str)
*** 2746,2752 ****
{
p++;
! if (skip_past_comma (& p) == SUCCESS)
{
/* [Rn], #expr */
write_back = WRITE_BACK;
--- 2969,2975 ----
{
p++;
! if (wb_ok && skip_past_comma (& p) == SUCCESS)
{
/* [Rn], #expr */
write_back = WRITE_BACK;
*************** cp_address_required_here (str)
*** 2788,2794 ****
skip_whitespace (p);
! if (*p == '!')
{
if (reg == REG_PC)
{
--- 3011,3017 ----
skip_whitespace (p);
! if (wb_ok && *p == '!')
{
if (reg == REG_PC)
{
*************** do_lstc2 (str)
*** 3496,3502 ****
inst.error = BAD_ARGS;
}
else if (skip_past_comma (& str) == FAIL
! || cp_address_required_here (& str) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
--- 3719,3725 ----
inst.error = BAD_ARGS;
}
else if (skip_past_comma (& str) == FAIL
! || cp_address_required_here (&str, CP_WB_OK) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
*************** do_lstc (str)
*** 5724,5730 ****
}
if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
--- 5947,5953 ----
}
if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str, CP_WB_OK) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
*************** do_fpa_ldst (str)
*** 5831,5837 ****
}
if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
--- 6054,6060 ----
}
if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str, CP_WB_OK) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
*************** do_fpa_ldmstm (str)
*** 5970,5976 ****
inst.instruction |= offset;
}
else if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
--- 6193,6199 ----
inst.instruction |= offset;
}
else if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str, CP_WB_OK) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
*************** do_fpa_to_reg (str)
*** 6109,6285 ****
return;
}
- /* Thumb specific routines. */
-
- /* Parse and validate that a register is of the right form, this saves
- repeated checking of this information in many similar cases.
- Unlike the 32-bit case we do not insert the register into the opcode
- here, since the position is often unknown until the full instruction
- has been parsed. */
-
static int
! thumb_reg (strp, hi_lo)
! char ** strp;
! int hi_lo;
{
! int reg;
!
! if ((reg = reg_required_here (strp, -1)) == FAIL)
! return FAIL;
! switch (hi_lo)
{
! case THUMB_REG_LO:
! if (reg > 7)
{
! inst.error = _("lo register required");
! return FAIL;
}
! break;
! case THUMB_REG_HI:
! if (reg < 8)
{
! inst.error = _("hi register required");
! return FAIL;
! }
! break;
! default:
! break;
}
! return reg;
! }
! /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
! was SUB. */
static void
! thumb_add_sub (str, subtract)
! char * str;
! int subtract;
{
- int Rd, Rs, Rn = FAIL;
-
skip_whitespace (str);
! if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
! || skip_past_comma (&str) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
return;
}
! if (is_immediate_prefix (*str))
{
! Rs = Rd;
! str++;
! if (my_get_expression (&inst.reloc.exp, &str))
! return;
}
- else
- {
- if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
- return;
! if (skip_past_comma (&str) == FAIL)
! {
! /* Two operand format, shuffle the registers
! and pretend there are 3. */
! Rn = Rs;
! Rs = Rd;
! }
! else if (is_immediate_prefix (*str))
! {
! str++;
! if (my_get_expression (&inst.reloc.exp, &str))
! return;
! }
! else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
! return;
! }
! /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
! for the latter case, EXPR contains the immediate that was found. */
! if (Rn != FAIL)
! {
! /* All register format. */
! if (Rd > 7 || Rs > 7 || Rn > 7)
! {
! if (Rs != Rd)
! {
! inst.error = _("dest and source1 must be the same register");
! return;
! }
! /* Can't do this for SUB. */
! if (subtract)
! {
! inst.error = _("subtract valid only on lo regs");
! return;
! }
! inst.instruction = (T_OPCODE_ADD_HI
! | (Rd > 7 ? THUMB_H1 : 0)
! | (Rn > 7 ? THUMB_H2 : 0));
! inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
! }
! else
! {
! inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
! inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
! }
! }
! else
{
! /* Immediate expression, now things start to get nasty. */
! /* First deal with HI regs, only very restricted cases allowed:
! Adjusting SP, and using PC or SP to get an address. */
! if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
! || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
! {
! inst.error = _("invalid Hi register with immediate");
! return;
! }
! if (inst.reloc.exp.X_op != O_constant)
! {
! /* Value isn't known yet, all we can do is store all the fragments
! we know about in the instruction and let the reloc hacking
! work it all out. */
! inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
! inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
! }
! else
! {
! int offset = inst.reloc.exp.X_add_number;
! if (subtract)
! offset = -offset;
! if (offset < 0)
! {
! offset = -offset;
! subtract = 1;
! /* Quick check, in case offset is MIN_INT. */
! if (offset < 0)
! {
! inst.error = _("immediate value out of range");
! return;
! }
! }
! else
! subtract = 0;
! if (Rd == REG_SP)
! {
! if (offset & ~0x1fc)
! {
! inst.error = _("invalid immediate value for stack adjust");
return;
}
inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
--- 6332,7409 ----
return;
}
static int
! vfp_sp_reg_required_here (str, pos)
! char **str;
! enum vfp_sp_reg_pos pos;
{
! int reg;
! char *start = *str;
! if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
{
! switch (pos)
{
! case VFP_REG_Sd:
! inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
! break;
!
! case VFP_REG_Sn:
! inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
! break;
!
! case VFP_REG_Sm:
! inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
! break;
!
! default:
! abort ();
}
! return reg;
! }
! /* In the few cases where we might be able to accept something else
! this error can be overridden. */
! inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
!
! /* Restore the start point. */
! *str = start;
! return FAIL;
! }
!
! static int
! vfp_dp_reg_required_here (str, pos)
! char **str;
! enum vfp_sp_reg_pos pos;
! {
! int reg;
! char *start = *str;
!
! if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
! {
! switch (pos)
{
! case VFP_REG_Dd:
! inst.instruction |= reg << 12;
! break;
! case VFP_REG_Dn:
! inst.instruction |= reg << 16;
! break;
!
! case VFP_REG_Dm:
! inst.instruction |= reg << 0;
! break;
!
! default:
! abort ();
! }
! return reg;
}
! /* In the few cases where we might be able to accept something else
! this error can be overridden. */
! inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
! /* Restore the start point. */
! *str = start;
! return FAIL;
! }
static void
! do_vfp_sp_monadic (str)
! char *str;
{
skip_whitespace (str);
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
{
if (! inst.error)
inst.error = BAD_ARGS;
return;
}
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_monadic (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
{
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
}
! end_of_line (str);
! return;
! }
! static void
! do_vfp_sp_dyadic (str)
! char *str;
! {
! skip_whitespace (str);
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
! return;
! if (skip_past_comma (&str) == FAIL
! || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
! || skip_past_comma (&str) == FAIL
! || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
{
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
! end_of_line (str);
! return;
! }
! static void
! do_vfp_dp_dyadic (str)
! char *str;
! {
! skip_whitespace (str);
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
! return;
! if (skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
! || skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
! end_of_line (str);
! return;
! }
! static void
! do_vfp_reg_from_sp (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (reg_required_here (&str, 12) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_sp_reg2 (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (reg_required_here (&str, 12) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 16) == FAIL
! || skip_past_comma (&str) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! /* We require exactly two consecutive SP registers. */
! if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
! {
! if (! inst.error)
! inst.error = _("only two consecutive VFP SP registers allowed here");
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_sp_from_reg (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 12) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_reg_from_dp (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (reg_required_here (&str, 12) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_reg2_from_dp (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (reg_required_here (&str, 12) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 16) == FAIL
! || skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_from_reg (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 12) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_from_reg2 (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 12) == FAIL
! || skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 16))
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static const struct vfp_reg *
! vfp_psr_parse (str)
! char **str;
! {
! char *start = *str;
! char c;
! char *p;
! const struct vfp_reg *vreg;
!
! p = start;
!
! /* Find the end of the current token. */
! do
! {
! c = *p++;
! }
! while (ISALPHA (c));
!
! /* Mark it. */
! *--p = 0;
!
! for (vreg = vfp_regs + 0;
! vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
! vreg++)
! {
! if (strcmp (start, vreg->name) == 0)
! {
! *p = c;
! *str = p;
! return vreg;
! }
! }
!
! *p = c;
! return NULL;
! }
!
! static int
! vfp_psr_required_here (str)
! char **str;
! {
! char *start = *str;
! const struct vfp_reg *vreg;
!
! vreg = vfp_psr_parse (str);
!
! if (vreg)
! {
! inst.instruction |= vreg->regno;
! return SUCCESS;
! }
!
! inst.error = _("VFP system register expected");
!
! *str = start;
! return FAIL;
! }
!
! static void
! do_vfp_reg_from_ctrl (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (reg_required_here (&str, 12) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_psr_required_here (&str) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_ctrl_from_reg (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_psr_required_here (&str) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || reg_required_here (&str, 12) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_sp_ldst (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str, CP_NO_WB) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_ldst (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! if (skip_past_comma (&str) == FAIL
! || cp_address_required_here (&str, CP_NO_WB) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! /* Parse and encode a VFP SP register list, storing the initial
! register in position POS and returning the range as the result. If
! the string is invalid return FAIL (an invalid range). */
! static long
! vfp_sp_reg_list (str, pos)
! char **str;
! enum vfp_sp_reg_pos pos;
! {
! long range = 0;
! int base_reg = 0;
! int new_base;
! long base_bits = 0;
! int count = 0;
! long tempinst;
! unsigned long mask = 0;
! int warned = 0;
!
! if (**str != '{')
! return FAIL;
!
! (*str)++;
! skip_whitespace (*str);
!
! tempinst = inst.instruction;
!
! do
! {
! inst.instruction = 0;
!
! if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
! return FAIL;
!
! if (count == 0 || base_reg > new_base)
! {
! base_reg = new_base;
! base_bits = inst.instruction;
! }
!
! if (mask & (1 << new_base))
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! if ((mask >> new_base) != 0 && ! warned)
! {
! as_tsktsk (_("register list not in ascending order"));
! warned = 1;
! }
!
! mask |= 1 << new_base;
! count++;
!
! skip_whitespace (*str);
!
! if (**str == '-') /* We have the start of a range expression */
! {
! int high_range;
!
! (*str)++;
!
! if ((high_range
! = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
! == FAIL)
! {
! inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
! return FAIL;
! }
!
! if (high_range <= new_base)
! {
! inst.error = _("register range not in ascending order");
! return FAIL;
! }
!
! for (new_base++; new_base <= high_range; new_base++)
! {
! if (mask & (1 << new_base))
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! mask |= 1 << new_base;
! count++;
! }
! }
! }
! while (skip_past_comma (str) != FAIL);
!
! if (**str != '}')
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! (*str)++;
!
! range = count;
!
! /* Sanity check -- should have raised a parse error above. */
! if (count == 0 || count > 32)
! abort();
!
! /* Final test -- the registers must be consecutive. */
! while (count--)
! {
! if ((mask & (1 << base_reg++)) == 0)
! {
! inst.error = _("non-contiguous register range");
! return FAIL;
! }
! }
!
! inst.instruction = tempinst | base_bits;
! return range;
! }
!
! static long
! vfp_dp_reg_list (str)
! char **str;
! {
! long range = 0;
! int base_reg = 0;
! int new_base;
! int count = 0;
! long tempinst;
! unsigned long mask = 0;
! int warned = 0;
!
! if (**str != '{')
! return FAIL;
!
! (*str)++;
! skip_whitespace (*str);
!
! tempinst = inst.instruction;
!
! do
! {
! inst.instruction = 0;
!
! if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
! return FAIL;
!
! if (count == 0 || base_reg > new_base)
! {
! base_reg = new_base;
! range = inst.instruction;
! }
!
! if (mask & (1 << new_base))
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! if ((mask >> new_base) != 0 && ! warned)
! {
! as_tsktsk (_("register list not in ascending order"));
! warned = 1;
! }
!
! mask |= 1 << new_base;
! count++;
!
! skip_whitespace (*str);
!
! if (**str == '-') /* We have the start of a range expression */
! {
! int high_range;
!
! (*str)++;
!
! if ((high_range
! = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
! == FAIL)
! {
! inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
! return FAIL;
! }
!
! if (high_range <= new_base)
! {
! inst.error = _("register range not in ascending order");
! return FAIL;
! }
!
! for (new_base++; new_base <= high_range; new_base++)
! {
! if (mask & (1 << new_base))
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! mask |= 1 << new_base;
! count++;
! }
! }
! }
! while (skip_past_comma (str) != FAIL);
!
! if (**str != '}')
! {
! inst.error = _("invalid register list");
! return FAIL;
! }
!
! (*str)++;
!
! range |= 2 * count;
!
! /* Sanity check -- should have raised a parse error above. */
! if (count == 0 || count > 16)
! abort();
!
! /* Final test -- the registers must be consecutive. */
! while (count--)
! {
! if ((mask & (1 << base_reg++)) == 0)
! {
! inst.error = _("non-contiguous register range");
! return FAIL;
! }
! }
!
! inst.instruction = tempinst;
! return range;
! }
!
! static void
! vfp_sp_ldstm(str, ldstm_type)
! char *str;
! enum vfp_ldstm_type ldstm_type;
! {
! long range;
!
! skip_whitespace (str);
!
! if (reg_required_here (&str, 16) == FAIL)
! return;
!
! skip_whitespace (str);
!
! if (*str == '!')
! {
! inst.instruction |= WRITE_BACK;
! str++;
! }
! else if (ldstm_type != VFP_LDSTMIA)
! {
! inst.error = _("this addressing mode requires base-register writeback");
! return;
! }
!
! if (skip_past_comma (&str) == FAIL
! || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! inst.instruction |= range;
! end_of_line (str);
! }
!
! static void
! vfp_dp_ldstm(str, ldstm_type)
! char *str;
! enum vfp_ldstm_type ldstm_type;
! {
! long range;
!
! skip_whitespace (str);
!
! if (reg_required_here (&str, 16) == FAIL)
! return;
!
! skip_whitespace (str);
!
! if (*str == '!')
! {
! inst.instruction |= WRITE_BACK;
! str++;
! }
! else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
! {
! inst.error = _("this addressing mode requires base-register writeback");
! return;
! }
!
! if (skip_past_comma (&str) == FAIL
! || (range = vfp_dp_reg_list (&str)) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
! range += 1;
!
! inst.instruction |= range;
! end_of_line (str);
! }
!
! static void
! do_vfp_sp_ldstmia (str)
! char *str;
! {
! vfp_sp_ldstm (str, VFP_LDSTMIA);
! }
!
! static void
! do_vfp_sp_ldstmdb (str)
! char *str;
! {
! vfp_sp_ldstm (str, VFP_LDSTMDB);
! }
!
! static void
! do_vfp_dp_ldstmia (str)
! char *str;
! {
! vfp_dp_ldstm (str, VFP_LDSTMIA);
! }
!
! static void
! do_vfp_dp_ldstmdb (str)
! char *str;
! {
! vfp_dp_ldstm (str, VFP_LDSTMDB);
! }
!
! static void
! do_vfp_xp_ldstmia (str)
! char *str;
! {
! vfp_dp_ldstm (str, VFP_LDSTMIAX);
! }
!
! static void
! do_vfp_xp_ldstmdb (str)
! char *str;
! {
! vfp_dp_ldstm (str, VFP_LDSTMDBX);
! }
!
! static void
! do_vfp_sp_compare_z (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_compare_z (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
! {
! if (!inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_dp_sp_cvt (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! static void
! do_vfp_sp_dp_cvt (str)
! char *str;
! {
! skip_whitespace (str);
!
! if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL
! || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! end_of_line (str);
! return;
! }
!
! /* Thumb specific routines. */
!
! /* Parse and validate that a register is of the right form, this saves
! repeated checking of this information in many similar cases.
! Unlike the 32-bit case we do not insert the register into the opcode
! here, since the position is often unknown until the full instruction
! has been parsed. */
!
! static int
! thumb_reg (strp, hi_lo)
! char ** strp;
! int hi_lo;
! {
! int reg;
!
! if ((reg = reg_required_here (strp, -1)) == FAIL)
! return FAIL;
!
! switch (hi_lo)
! {
! case THUMB_REG_LO:
! if (reg > 7)
! {
! inst.error = _("lo register required");
! return FAIL;
! }
! break;
!
! case THUMB_REG_HI:
! if (reg < 8)
! {
! inst.error = _("hi register required");
! return FAIL;
! }
! break;
!
! default:
! break;
! }
!
! return reg;
! }
!
! /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
! was SUB. */
!
! static void
! thumb_add_sub (str, subtract)
! char * str;
! int subtract;
! {
! int Rd, Rs, Rn = FAIL;
!
! skip_whitespace (str);
!
! if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
! || skip_past_comma (&str) == FAIL)
! {
! if (! inst.error)
! inst.error = BAD_ARGS;
! return;
! }
!
! if (is_immediate_prefix (*str))
! {
! Rs = Rd;
! str++;
! if (my_get_expression (&inst.reloc.exp, &str))
! return;
! }
! else
! {
! if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
! return;
!
! if (skip_past_comma (&str) == FAIL)
! {
! /* Two operand format, shuffle the registers
! and pretend there are 3. */
! Rn = Rs;
! Rs = Rd;
! }
! else if (is_immediate_prefix (*str))
! {
! str++;
! if (my_get_expression (&inst.reloc.exp, &str))
! return;
! }
! else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
! return;
! }
!
! /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
! for the latter case, EXPR contains the immediate that was found. */
! if (Rn != FAIL)
! {
! /* All register format. */
! if (Rd > 7 || Rs > 7 || Rn > 7)
! {
! if (Rs != Rd)
! {
! inst.error = _("dest and source1 must be the same register");
! return;
! }
!
! /* Can't do this for SUB. */
! if (subtract)
! {
! inst.error = _("subtract valid only on lo regs");
! return;
! }
!
! inst.instruction = (T_OPCODE_ADD_HI
! | (Rd > 7 ? THUMB_H1 : 0)
! | (Rn > 7 ? THUMB_H2 : 0));
! inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
! }
! else
! {
! inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
! inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
! }
! }
! else
! {
! /* Immediate expression, now things start to get nasty. */
!
! /* First deal with HI regs, only very restricted cases allowed:
! Adjusting SP, and using PC or SP to get an address. */
! if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
! || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
! {
! inst.error = _("invalid Hi register with immediate");
! return;
! }
!
! if (inst.reloc.exp.X_op != O_constant)
! {
! /* Value isn't known yet, all we can do is store all the fragments
! we know about in the instruction and let the reloc hacking
! work it all out. */
! inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
! inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
! }
! else
! {
! int offset = inst.reloc.exp.X_add_number;
!
! if (subtract)
! offset = -offset;
!
! if (offset < 0)
! {
! offset = -offset;
! subtract = 1;
!
! /* Quick check, in case offset is MIN_INT. */
! if (offset < 0)
! {
! inst.error = _("immediate value out of range");
! return;
! }
! }
! else
! subtract = 0;
!
! if (Rd == REG_SP)
! {
! if (offset & ~0x1fc)
! {
! inst.error = _("invalid immediate value for stack adjust");
return;
}
inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
*************** md_begin ()
*** 8014,8020 ****
if (support_interwork) flags |= F_INTERWORK;
if (uses_apcs_float) flags |= F_APCS_FLOAT;
if (pic_code) flags |= F_PIC;
! if ((cpu_variant & FPU_ANY) == FPU_NONE) flags |= F_SOFT_FLOAT;
bfd_set_private_flags (stdoutput, flags);
--- 9138,9146 ----
if (support_interwork) flags |= F_INTERWORK;
if (uses_apcs_float) flags |= F_APCS_FLOAT;
if (pic_code) flags |= F_PIC;
! if ((cpu_variant & FPU_ANY) == FPU_NONE
! || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP)
! flags |= F_SOFT_FLOAT;
bfd_set_private_flags (stdoutput, flags);
*************** md_atof (type, litP, sizeP)
*** 8201,8214 ****
}
else
{
! /* For a 4 byte float the order of elements in `words' is 1 0. For an
! 8 byte float the order is 1 0 3 2. */
! for (i = 0; i < prec; i += 2)
! {
! md_number_to_chars (litP, (valueT) words[i + 1], 2);
! md_number_to_chars (litP + 2, (valueT) words[i], 2);
! litP += 4;
! }
}
return 0;
--- 9327,9347 ----
}
else
{
! if (cpu_variant & FPU_ARCH_VFP)
! for (i = prec - 1; i >= 0; i--)
! {
! md_number_to_chars (litP, (valueT) words[i], 2);
! litP += 2;
! }
! else
! /* For a 4 byte float the order of elements in `words' is 1 0.
! For an 8 byte float the order is 1 0 3 2. */
! for (i = 0; i < prec; i += 2)
! {
! md_number_to_chars (litP, (valueT) words[i + 1], 2);
! md_number_to_chars (litP + 2, (valueT) words[i], 2);
! litP += 4;
! }
}
return 0;
*************** md_assemble (str)
*** 9271,9276 ****
--- 10404,10411 ----
FP variants:
-mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
-mfpe-old (No float load/store multiples)
+ -mvfpxd VFP Single precision
+ -mvfp All VFP
-mno-fpu Disable all floating point instructions
Run-time endian selection:
-EB big endian cpu
*************** md_parse_option (c, arg)
*** 9378,9383 ****
--- 10513,10527 ----
goto bad;
break;
+ case 'v':
+ if (streq (str, "vfpxd"))
+ cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_VFP_V1xD;
+ else if (streq (str, "vfp"))
+ cpu_variant = (cpu_variant & ~FPU_ANY) | FPU_ARCH_VFP_V2;
+ else
+ goto bad;
+ break;
+
default:
if (streq (str, "all"))
{
*************** md_show_usage (fp)
*** 9676,9681 ****
--- 10820,10827 ----
-mall allow any instruction\n\
-mfpa10, -mfpa11 select floating point architecture\n\
-mfpe-old don't allow floating-point multiple instructions\n\
+ -mvfpxd allow vfp single-precision instructions\n\
+ -mvfp allow all vfp instructions\n\
-mno-fpu don't allow any floating-point instructions.\n\
-k generate PIC code.\n"));
#if defined OBJ_COFF || defined OBJ_ELF
Index: testsuite/gas/arm/arm.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/arm.exp,v
retrieving revision 1.10
diff -p -r1.10 arm.exp
*** arm.exp 2002/01/14 17:39:01 1.10
--- arm.exp 2002/01/15 15:50:32
*************** if {[istarget *arm*-*-*] || [istarget "x
*** 47,52 ****
--- 47,58 ----
run_dump_test "fpa-mem"
+ run_dump_test "vfp1xD"
+
+ run_dump_test "vfp1"
+
+ run_errors_test "vfp-bad" "-mvfp" "VFP errors"
+
run_dump_test "xscale"
run_dump_test "adrl"
Index: testsuite/gas/arm/vfp-bad.l
===================================================================
RCS file: vfp-bad.l
diff -N vfp-bad.l
*** /dev/null Tue May 5 13:32:27 1998
--- vfp-bad.l Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,9 ----
+ [^:]*: Assembler messages:
+ [^:]*:4: Error: garbage following instruction -- `fstd d0,\[r0\],#8'
+ [^:]*:5: Error: garbage following instruction -- `fstd d0,\[r0,#-8\]!'
+ [^:]*:6: Error: garbage following instruction -- `fsts s0,\[r0\],#8'
+ [^:]*:7: Error: garbage following instruction -- `fsts s0,\[r0,#-8\]!'
+ [^:]*:8: Error: garbage following instruction -- `fldd d0,\[r0\],#8'
+ [^:]*:9: Error: garbage following instruction -- `fldd d0,\[r0,#-8\]!'
+ [^:]*:10: Error: garbage following instruction -- `flds s0,\[r0\],#8'
+ [^:]*:11: Error: garbage following instruction -- `flds s0,\[r0,#-8\]!'
Index: testsuite/gas/arm/vfp-bad.s
===================================================================
RCS file: vfp-bad.s
diff -N vfp-bad.s
*** /dev/null Tue May 5 13:32:27 1998
--- vfp-bad.s Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,11 ----
+ .global entry
+ .text
+ entry:
+ fstd d0, [r0], #8
+ fstd d0, [r0, #-8]!
+ fsts s0, [r0], #8
+ fsts s0, [r0, #-8]!
+ fldd d0, [r0], #8
+ fldd d0, [r0, #-8]!
+ flds s0, [r0], #8
+ flds s0, [r0, #-8]!
Index: testsuite/gas/arm/vfp1.d
===================================================================
RCS file: vfp1.d
diff -N vfp1.d
*** /dev/null Tue May 5 13:32:27 1998
--- vfp1.d Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,190 ----
+ #objdump: -dr --prefix-addresses --show-raw-insn
+ #name: VFP Double-precision instructions
+ #as: -mvfp
+
+ # Test the ARM VFP Double Precision instructions
+
+ .*: +file format .*arm.*
+
+ Disassembly of section .text:
+ 0+000 <[^>]*> eeb40bc0 fcmped d0, d0
+ 0+004 <[^>]*> eeb50bc0 fcmpezd d0
+ 0+008 <[^>]*> eeb40b40 fcmpd d0, d0
+ 0+00c <[^>]*> eeb50b40 fcmpzd d0
+ 0+010 <[^>]*> eeb00bc0 fabsd d0, d0
+ 0+014 <[^>]*> eeb00b40 fcpyd d0, d0
+ 0+018 <[^>]*> eeb10b40 fnegd d0, d0
+ 0+01c <[^>]*> eeb10bc0 fsqrtd d0, d0
+ 0+020 <[^>]*> ee300b00 faddd d0, d0, d0
+ 0+024 <[^>]*> ee800b00 fdivd d0, d0, d0
+ 0+028 <[^>]*> ee000b00 fmacd d0, d0, d0
+ 0+02c <[^>]*> ee100b00 fmscd d0, d0, d0
+ 0+030 <[^>]*> ee200b00 fmuld d0, d0, d0
+ 0+034 <[^>]*> ee000b40 fnmacd d0, d0, d0
+ 0+038 <[^>]*> ee100b40 fnmscd d0, d0, d0
+ 0+03c <[^>]*> ee200b40 fnmuld d0, d0, d0
+ 0+040 <[^>]*> ee300b40 fsubd d0, d0, d0
+ 0+044 <[^>]*> ed900b00 fldd d0, \[r0\]
+ 0+048 <[^>]*> ed800b00 fstd d0, \[r0\]
+ 0+04c <[^>]*> ec900b02 fldmiad r0, {d0}
+ 0+050 <[^>]*> ec900b02 fldmiad r0, {d0}
+ 0+054 <[^>]*> ecb00b02 fldmiad r0!, {d0}
+ 0+058 <[^>]*> ecb00b02 fldmiad r0!, {d0}
+ 0+05c <[^>]*> ed300b02 fldmdbd r0!, {d0}
+ 0+060 <[^>]*> ed300b02 fldmdbd r0!, {d0}
+ 0+064 <[^>]*> ec800b02 fstmiad r0, {d0}
+ 0+068 <[^>]*> ec800b02 fstmiad r0, {d0}
+ 0+06c <[^>]*> eca00b02 fstmiad r0!, {d0}
+ 0+070 <[^>]*> eca00b02 fstmiad r0!, {d0}
+ 0+074 <[^>]*> ed200b02 fstmdbd r0!, {d0}
+ 0+078 <[^>]*> ed200b02 fstmdbd r0!, {d0}
+ 0+07c <[^>]*> eeb80bc0 fsitod d0, s0
+ 0+080 <[^>]*> eeb80b40 fuitod d0, s0
+ 0+084 <[^>]*> eebd0b40 ftosid s0, d0
+ 0+088 <[^>]*> eebd0bc0 ftosizd s0, d0
+ 0+08c <[^>]*> eebc0b40 ftouid s0, d0
+ 0+090 <[^>]*> eebc0bc0 ftouizd s0, d0
+ 0+094 <[^>]*> eeb70ac0 fcvtds d0, s0
+ 0+098 <[^>]*> eeb70bc0 fcvtsd s0, d0
+ 0+09c <[^>]*> ee300b10 fmrdh r0, d0
+ 0+0a0 <[^>]*> ee100b10 fmrdl r0, d0
+ 0+0a4 <[^>]*> ee200b10 fmdhr d0, r0
+ 0+0a8 <[^>]*> ee000b10 fmdlr d0, r0
+ 0+0ac <[^>]*> eeb51b40 fcmpzd d1
+ 0+0b0 <[^>]*> eeb52b40 fcmpzd d2
+ 0+0b4 <[^>]*> eeb5fb40 fcmpzd d15
+ 0+0b8 <[^>]*> eeb40b41 fcmpd d0, d1
+ 0+0bc <[^>]*> eeb40b42 fcmpd d0, d2
+ 0+0c0 <[^>]*> eeb40b4f fcmpd d0, d15
+ 0+0c4 <[^>]*> eeb41b40 fcmpd d1, d0
+ 0+0c8 <[^>]*> eeb42b40 fcmpd d2, d0
+ 0+0cc <[^>]*> eeb4fb40 fcmpd d15, d0
+ 0+0d0 <[^>]*> eeb45b4c fcmpd d5, d12
+ 0+0d4 <[^>]*> eeb10b41 fnegd d0, d1
+ 0+0d8 <[^>]*> eeb10b42 fnegd d0, d2
+ 0+0dc <[^>]*> eeb10b4f fnegd d0, d15
+ 0+0e0 <[^>]*> eeb11b40 fnegd d1, d0
+ 0+0e4 <[^>]*> eeb12b40 fnegd d2, d0
+ 0+0e8 <[^>]*> eeb1fb40 fnegd d15, d0
+ 0+0ec <[^>]*> eeb1cb45 fnegd d12, d5
+ 0+0f0 <[^>]*> ee300b01 faddd d0, d0, d1
+ 0+0f4 <[^>]*> ee300b02 faddd d0, d0, d2
+ 0+0f8 <[^>]*> ee300b0f faddd d0, d0, d15
+ 0+0fc <[^>]*> ee310b00 faddd d0, d1, d0
+ 0+100 <[^>]*> ee320b00 faddd d0, d2, d0
+ 0+104 <[^>]*> ee3f0b00 faddd d0, d15, d0
+ 0+108 <[^>]*> ee301b00 faddd d1, d0, d0
+ 0+10c <[^>]*> ee302b00 faddd d2, d0, d0
+ 0+110 <[^>]*> ee30fb00 faddd d15, d0, d0
+ 0+114 <[^>]*> ee39cb05 faddd d12, d9, d5
+ 0+118 <[^>]*> eeb70ae0 fcvtds d0, s1
+ 0+11c <[^>]*> eeb70ac1 fcvtds d0, s2
+ 0+120 <[^>]*> eeb70aef fcvtds d0, s31
+ 0+124 <[^>]*> eeb71ac0 fcvtds d1, s0
+ 0+128 <[^>]*> eeb72ac0 fcvtds d2, s0
+ 0+12c <[^>]*> eeb7fac0 fcvtds d15, s0
+ 0+130 <[^>]*> eef70bc0 fcvtsd s1, d0
+ 0+134 <[^>]*> eeb71bc0 fcvtsd s2, d0
+ 0+138 <[^>]*> eef7fbc0 fcvtsd s31, d0
+ 0+13c <[^>]*> eeb70bc1 fcvtsd s0, d1
+ 0+140 <[^>]*> eeb70bc2 fcvtsd s0, d2
+ 0+144 <[^>]*> eeb70bcf fcvtsd s0, d15
+ 0+148 <[^>]*> ee301b10 fmrdh r1, d0
+ 0+14c <[^>]*> ee30eb10 fmrdh lr, d0
+ 0+150 <[^>]*> ee310b10 fmrdh r0, d1
+ 0+154 <[^>]*> ee320b10 fmrdh r0, d2
+ 0+158 <[^>]*> ee3f0b10 fmrdh r0, d15
+ 0+15c <[^>]*> ee101b10 fmrdl r1, d0
+ 0+160 <[^>]*> ee10eb10 fmrdl lr, d0
+ 0+164 <[^>]*> ee110b10 fmrdl r0, d1
+ 0+168 <[^>]*> ee120b10 fmrdl r0, d2
+ 0+16c <[^>]*> ee1f0b10 fmrdl r0, d15
+ 0+170 <[^>]*> ee201b10 fmdhr d0, r1
+ 0+174 <[^>]*> ee20eb10 fmdhr d0, lr
+ 0+178 <[^>]*> ee210b10 fmdhr d1, r0
+ 0+17c <[^>]*> ee220b10 fmdhr d2, r0
+ 0+180 <[^>]*> ee2f0b10 fmdhr d15, r0
+ 0+184 <[^>]*> ee001b10 fmdlr d0, r1
+ 0+188 <[^>]*> ee00eb10 fmdlr d0, lr
+ 0+18c <[^>]*> ee010b10 fmdlr d1, r0
+ 0+190 <[^>]*> ee020b10 fmdlr d2, r0
+ 0+194 <[^>]*> ee0f0b10 fmdlr d15, r0
+ 0+198 <[^>]*> ed910b00 fldd d0, \[r1\]
+ 0+19c <[^>]*> ed9e0b00 fldd d0, \[lr\]
+ 0+1a0 <[^>]*> ed900b00 fldd d0, \[r0\]
+ 0+1a4 <[^>]*> ed900bff fldd d0, \[r0, #1020\]
+ 0+1a8 <[^>]*> ed100bff fldd d0, \[r0, -#1020\]
+ 0+1ac <[^>]*> ed901b00 fldd d1, \[r0\]
+ 0+1b0 <[^>]*> ed902b00 fldd d2, \[r0\]
+ 0+1b4 <[^>]*> ed90fb00 fldd d15, \[r0\]
+ 0+1b8 <[^>]*> ed8ccbc9 fstd d12, \[ip, #804\]
+ 0+1bc <[^>]*> ec901b02 fldmiad r0, {d1}
+ 0+1c0 <[^>]*> ec902b02 fldmiad r0, {d2}
+ 0+1c4 <[^>]*> ec90fb02 fldmiad r0, {d15}
+ 0+1c8 <[^>]*> ec900b04 fldmiad r0, {d0-d1}
+ 0+1cc <[^>]*> ec900b06 fldmiad r0, {d0-d2}
+ 0+1d0 <[^>]*> ec900b20 fldmiad r0, {d0-d15}
+ 0+1d4 <[^>]*> ec901b1e fldmiad r0, {d1-d15}
+ 0+1d8 <[^>]*> ec902b1c fldmiad r0, {d2-d15}
+ 0+1dc <[^>]*> ec90eb04 fldmiad r0, {d14-d15}
+ 0+1e0 <[^>]*> ec910b02 fldmiad r1, {d0}
+ 0+1e4 <[^>]*> ec9e0b02 fldmiad lr, {d0}
+ 0+1e8 <[^>]*> eeb50b40 fcmpzd d0
+ 0+1ec <[^>]*> eeb51b40 fcmpzd d1
+ 0+1f0 <[^>]*> eeb52b40 fcmpzd d2
+ 0+1f4 <[^>]*> eeb53b40 fcmpzd d3
+ 0+1f8 <[^>]*> eeb54b40 fcmpzd d4
+ 0+1fc <[^>]*> eeb55b40 fcmpzd d5
+ 0+200 <[^>]*> eeb56b40 fcmpzd d6
+ 0+204 <[^>]*> eeb57b40 fcmpzd d7
+ 0+208 <[^>]*> eeb58b40 fcmpzd d8
+ 0+20c <[^>]*> eeb59b40 fcmpzd d9
+ 0+210 <[^>]*> eeb5ab40 fcmpzd d10
+ 0+214 <[^>]*> eeb5bb40 fcmpzd d11
+ 0+218 <[^>]*> eeb5cb40 fcmpzd d12
+ 0+21c <[^>]*> eeb5db40 fcmpzd d13
+ 0+220 <[^>]*> eeb5eb40 fcmpzd d14
+ 0+224 <[^>]*> eeb5fb40 fcmpzd d15
+ 0+228 <[^>]*> 0eb41bcf fcmpedeq d1, d15
+ 0+22c <[^>]*> 0eb52bc0 fcmpezdeq d2
+ 0+230 <[^>]*> 0eb43b4e fcmpdeq d3, d14
+ 0+234 <[^>]*> 0eb54b40 fcmpzdeq d4
+ 0+238 <[^>]*> 0eb05bcd fabsdeq d5, d13
+ 0+23c <[^>]*> 0eb06b4c fcpydeq d6, d12
+ 0+240 <[^>]*> 0eb17b4b fnegdeq d7, d11
+ 0+244 <[^>]*> 0eb18bca fsqrtdeq d8, d10
+ 0+248 <[^>]*> 0e319b0f fadddeq d9, d1, d15
+ 0+24c <[^>]*> 0e832b0e fdivdeq d2, d3, d14
+ 0+250 <[^>]*> 0e0d4b0c fmacdeq d4, d13, d12
+ 0+254 <[^>]*> 0e165b0b fmscdeq d5, d6, d11
+ 0+258 <[^>]*> 0e2a7b09 fmuldeq d7, d10, d9
+ 0+25c <[^>]*> 0e098b4a fnmacdeq d8, d9, d10
+ 0+260 <[^>]*> 0e167b4b fnmscdeq d7, d6, d11
+ 0+264 <[^>]*> 0e245b4c fnmuldeq d5, d4, d12
+ 0+268 <[^>]*> 0e3d3b4e fsubdeq d3, d13, d14
+ 0+26c <[^>]*> 0d952b00 flddeq d2, \[r5\]
+ 0+270 <[^>]*> 0d8c1b00 fstdeq d1, \[ip\]
+ 0+274 <[^>]*> 0c911b02 fldmiadeq r1, {d1}
+ 0+278 <[^>]*> 0c922b02 fldmiadeq r2, {d2}
+ 0+27c <[^>]*> 0cb33b02 fldmiadeq r3!, {d3}
+ 0+280 <[^>]*> 0cb44b02 fldmiadeq r4!, {d4}
+ 0+284 <[^>]*> 0d355b02 fldmdbdeq r5!, {d5}
+ 0+288 <[^>]*> 0d366b02 fldmdbdeq r6!, {d6}
+ 0+28c <[^>]*> 0c87fb02 fstmiadeq r7, {d15}
+ 0+290 <[^>]*> 0c88eb02 fstmiadeq r8, {d14}
+ 0+294 <[^>]*> 0ca9db02 fstmiadeq r9!, {d13}
+ 0+298 <[^>]*> 0caacb02 fstmiadeq sl!, {d12}
+ 0+29c <[^>]*> 0d2bbb02 fstmdbdeq fp!, {d11}
+ 0+2a0 <[^>]*> 0d2cab02 fstmdbdeq ip!, {d10}
+ 0+2a4 <[^>]*> 0eb8fbe0 fsitodeq d15, s1
+ 0+2a8 <[^>]*> 0eb81b6f fuitodeq d1, s31
+ 0+2ac <[^>]*> 0efd0b4f ftosideq s1, d15
+ 0+2b0 <[^>]*> 0efdfbc2 ftosizdeq s31, d2
+ 0+2b4 <[^>]*> 0efc7b42 ftouideq s15, d2
+ 0+2b8 <[^>]*> 0efc5bc3 ftouizdeq s11, d3
+ 0+2bc <[^>]*> 0eb71ac5 fcvtdseq d1, s10
+ 0+2c0 <[^>]*> 0ef75bc1 fcvtsdeq s11, d1
+ 0+2c4 <[^>]*> 0e318b10 fmrdheq r8, d1
+ 0+2c8 <[^>]*> 0e1f7b10 fmrdleq r7, d15
+ 0+2cc <[^>]*> 0e21fb10 fmdhreq d1, pc
+ 0+2d0 <[^>]*> 0e0f1b10 fmdlreq d15, r1
Index: testsuite/gas/arm/vfp1.s
===================================================================
RCS file: vfp1.s
diff -N vfp1.s
*** /dev/null Tue May 5 13:32:27 1998
--- vfp1.s Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,278 ----
+ @ VFP Instructions for D variants (Double precision)
+ .text
+ .global F
+ F:
+ @ First we test the basic syntax and bit patterns of the opcodes.
+ @ Most of these tests deliberatly use d0/r0 to avoid setting
+ @ any more bits than necessary.
+
+ @ Comparison operations
+
+ fcmped d0, d0
+ fcmpezd d0
+ fcmpd d0, d0
+ fcmpzd d0
+
+ @ Monadic data operations
+
+ fabsd d0, d0
+ fcpyd d0, d0
+ fnegd d0, d0
+ fsqrtd d0, d0
+
+ @ Dyadic data operations
+
+ faddd d0, d0, d0
+ fdivd d0, d0, d0
+ fmacd d0, d0, d0
+ fmscd d0, d0, d0
+ fmuld d0, d0, d0
+ fnmacd d0, d0, d0
+ fnmscd d0, d0, d0
+ fnmuld d0, d0, d0
+ fsubd d0, d0, d0
+
+ @ Load/store operations
+
+ fldd d0, [r0]
+ fstd d0, [r0]
+
+ @ Load/store multiple operations
+
+ fldmiad r0, {d0}
+ fldmfdd r0, {d0}
+ fldmiad r0!, {d0}
+ fldmfdd r0!, {d0}
+ fldmdbd r0!, {d0}
+ fldmead r0!, {d0}
+
+ fstmiad r0, {d0}
+ fstmead r0, {d0}
+ fstmiad r0!, {d0}
+ fstmead r0!, {d0}
+ fstmdbd r0!, {d0}
+ fstmfdd r0!, {d0}
+
+ @ Conversion operations
+
+ fsitod d0, s0
+ fuitod d0, s0
+
+ ftosid s0, d0
+ ftosizd s0, d0
+ ftouid s0, d0
+ ftouizd s0, d0
+
+ fcvtds d0, s0
+ fcvtsd s0, d0
+
+ @ ARM from VFP operations
+
+ fmrdh r0, d0
+ fmrdl r0, d0
+
+ @ VFP From ARM operations
+
+ fmdhr d0, r0
+ fmdlr d0, r0
+
+ @ Now we test that the register fields are updated correctly for
+ @ each class of instruction.
+
+ @ Single register operations (compare-zero):
+
+ fcmpzd d1
+ fcmpzd d2
+ fcmpzd d15
+
+ @ Two register comparison operations:
+
+ fcmpd d0, d1
+ fcmpd d0, d2
+ fcmpd d0, d15
+ fcmpd d1, d0
+ fcmpd d2, d0
+ fcmpd d15, d0
+ fcmpd d5, d12
+
+ @ Two register data operations (monadic)
+
+ fnegd d0, d1
+ fnegd d0, d2
+ fnegd d0, d15
+ fnegd d1, d0
+ fnegd d2, d0
+ fnegd d15, d0
+ fnegd d12, d5
+
+ @ Three register data operations (dyadic)
+
+ faddd d0, d0, d1
+ faddd d0, d0, d2
+ faddd d0, d0, d15
+ faddd d0, d1, d0
+ faddd d0, d2, d0
+ faddd d0, d15, d0
+ faddd d1, d0, d0
+ faddd d2, d0, d0
+ faddd d15, d0, d0
+ faddd d12, d9, d5
+
+ @ Conversion operations
+
+ fcvtds d0, s1
+ fcvtds d0, s2
+ fcvtds d0, s31
+ fcvtds d1, s0
+ fcvtds d2, s0
+ fcvtds d15, s0
+ fcvtsd s1, d0
+ fcvtsd s2, d0
+ fcvtsd s31, d0
+ fcvtsd s0, d1
+ fcvtsd s0, d2
+ fcvtsd s0, d15
+
+ @ Move to VFP from ARM
+
+ fmrdh r1, d0
+ fmrdh r14, d0
+ fmrdh r0, d1
+ fmrdh r0, d2
+ fmrdh r0, d15
+ fmrdl r1, d0
+ fmrdl r14, d0
+ fmrdl r0, d1
+ fmrdl r0, d2
+ fmrdl r0, d15
+
+ @ Move to ARM from VFP
+
+ fmdhr d0, r1
+ fmdhr d0, r14
+ fmdhr d1, r0
+ fmdhr d2, r0
+ fmdhr d15, r0
+ fmdlr d0, r1
+ fmdlr d0, r14
+ fmdlr d1, r0
+ fmdlr d2, r0
+ fmdlr d15, r0
+
+ @ Load/store operations
+
+ fldd d0, [r1]
+ fldd d0, [r14]
+ fldd d0, [r0, #0]
+ fldd d0, [r0, #1020]
+ fldd d0, [r0, #-1020]
+ fldd d1, [r0]
+ fldd d2, [r0]
+ fldd d15, [r0]
+ fstd d12, [r12, #804]
+
+ @ Load/store multiple operations
+
+ fldmiad r0, {d1}
+ fldmiad r0, {d2}
+ fldmiad r0, {d15}
+ fldmiad r0, {d0-d1}
+ fldmiad r0, {d0-d2}
+ fldmiad r0, {d0-d15}
+ fldmiad r0, {d1-d15}
+ fldmiad r0, {d2-d15}
+ fldmiad r0, {d14-d15}
+ fldmiad r1, {d0}
+ fldmiad r14, {d0}
+
+ @ Check that we assemble all the register names correctly
+
+ fcmpzd d0
+ fcmpzd d1
+ fcmpzd d2
+ fcmpzd d3
+ fcmpzd d4
+ fcmpzd d5
+ fcmpzd d6
+ fcmpzd d7
+ fcmpzd d8
+ fcmpzd d9
+ fcmpzd d10
+ fcmpzd d11
+ fcmpzd d12
+ fcmpzd d13
+ fcmpzd d14
+ fcmpzd d15
+
+ @ Now we check the placement of the conditional execution substring.
+ @ On VFP this is always at the end of the instruction.
+
+ @ Comparison operations
+
+ fcmpedeq d1, d15
+ fcmpezdeq d2
+ fcmpdeq d3, d14
+ fcmpzdeq d4
+
+ @ Monadic data operations
+
+ fabsdeq d5, d13
+ fcpydeq d6, d12
+ fnegdeq d7, d11
+ fsqrtdeq d8, d10
+
+ @ Dyadic data operations
+
+ fadddeq d9, d1, d15
+ fdivdeq d2, d3, d14
+ fmacdeq d4, d13, d12
+ fmscdeq d5, d6, d11
+ fmuldeq d7, d10, d9
+ fnmacdeq d8, d9, d10
+ fnmscdeq d7, d6, d11
+ fnmuldeq d5, d4, d12
+ fsubdeq d3, d13, d14
+
+ @ Load/store operations
+
+ flddeq d2, [r5]
+ fstdeq d1, [r12]
+
+ @ Load/store multiple operations
+
+ fldmiadeq r1, {d1}
+ fldmfddeq r2, {d2}
+ fldmiadeq r3!, {d3}
+ fldmfddeq r4!, {d4}
+ fldmdbdeq r5!, {d5}
+ fldmeadeq r6!, {d6}
+
+ fstmiadeq r7, {d15}
+ fstmeadeq r8, {d14}
+ fstmiadeq r9!, {d13}
+ fstmeadeq r10!, {d12}
+ fstmdbdeq r11!, {d11}
+ fstmfddeq r12!, {d10}
+
+ @ Conversion operations
+
+ fsitodeq d15, s1
+ fuitodeq d1, s31
+
+ ftosideq s1, d15
+ ftosizdeq s31, d2
+ ftouideq s15, d2
+ ftouizdeq s11, d3
+
+ fcvtdseq d1, s10
+ fcvtsdeq s11, d1
+
+ @ ARM from VFP operations
+
+ fmrdheq r8, d1
+ fmrdleq r7, d15
+
+ @ VFP From ARM operations
+
+ fmdhreq d1, r15
+ fmdlreq d15, r1
Index: testsuite/gas/arm/vfp1xD.d
===================================================================
RCS file: vfp1xD.d
diff -N vfp1xD.d
*** /dev/null Tue May 5 13:32:27 1998
--- vfp1xD.d Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,241 ----
+ #objdump: -dr --prefix-addresses --show-raw-insn
+ #name: VFP Single-precision instructions
+ #as: -mvfpxd
+
+ # Test the ARM VFP Single Precision instructions
+
+ .*: +file format .*arm.*
+
+ Disassembly of section .text:
+ 0+000 <[^>]*> eef1fa10 fmstat
+ 0+004 <[^>]*> eeb40ac0 fcmpes s0, s0
+ 0+008 <[^>]*> eeb50ac0 fcmpezs s0
+ 0+00c <[^>]*> eeb40a40 fcmps s0, s0
+ 0+010 <[^>]*> eeb50a40 fcmpzs s0
+ 0+014 <[^>]*> eeb00ac0 fabss s0, s0
+ 0+018 <[^>]*> eeb00a40 fcpys s0, s0
+ 0+01c <[^>]*> eeb10a40 fnegs s0, s0
+ 0+020 <[^>]*> eeb10ac0 fsqrts s0, s0
+ 0+024 <[^>]*> ee300a00 fadds s0, s0, s0
+ 0+028 <[^>]*> ee800a00 fdivs s0, s0, s0
+ 0+02c <[^>]*> ee000a00 fmacs s0, s0, s0
+ 0+030 <[^>]*> ee100a00 fmscs s0, s0, s0
+ 0+034 <[^>]*> ee200a00 fmuls s0, s0, s0
+ 0+038 <[^>]*> ee000a40 fnmacs s0, s0, s0
+ 0+03c <[^>]*> ee100a40 fnmscs s0, s0, s0
+ 0+040 <[^>]*> ee200a40 fnmuls s0, s0, s0
+ 0+044 <[^>]*> ee300a40 fsubs s0, s0, s0
+ 0+048 <[^>]*> ed900a00 flds s0, \[r0\]
+ 0+04c <[^>]*> ed800a00 fsts s0, \[r0\]
+ 0+050 <[^>]*> ec900a01 fldmias r0, {s0}
+ 0+054 <[^>]*> ec900a01 fldmias r0, {s0}
+ 0+058 <[^>]*> ecb00a01 fldmias r0!, {s0}
+ 0+05c <[^>]*> ecb00a01 fldmias r0!, {s0}
+ 0+060 <[^>]*> ed300a01 fldmdbs r0!, {s0}
+ 0+064 <[^>]*> ed300a01 fldmdbs r0!, {s0}
+ 0+068 <[^>]*> ec900b03 fldmiax r0, {d0}
+ 0+06c <[^>]*> ec900b03 fldmiax r0, {d0}
+ 0+070 <[^>]*> ecb00b03 fldmiax r0!, {d0}
+ 0+074 <[^>]*> ecb00b03 fldmiax r0!, {d0}
+ 0+078 <[^>]*> ed300b03 fldmdbx r0!, {d0}
+ 0+07c <[^>]*> ed300b03 fldmdbx r0!, {d0}
+ 0+080 <[^>]*> ec800a01 fstmias r0, {s0}
+ 0+084 <[^>]*> ec800a01 fstmias r0, {s0}
+ 0+088 <[^>]*> eca00a01 fstmias r0!, {s0}
+ 0+08c <[^>]*> eca00a01 fstmias r0!, {s0}
+ 0+090 <[^>]*> ed200a01 fstmdbs r0!, {s0}
+ 0+094 <[^>]*> ed200a01 fstmdbs r0!, {s0}
+ 0+098 <[^>]*> ec800b03 fstmiax r0, {d0}
+ 0+09c <[^>]*> ec800b03 fstmiax r0, {d0}
+ 0+0a0 <[^>]*> eca00b03 fstmiax r0!, {d0}
+ 0+0a4 <[^>]*> eca00b03 fstmiax r0!, {d0}
+ 0+0a8 <[^>]*> ed200b03 fstmdbx r0!, {d0}
+ 0+0ac <[^>]*> ed200b03 fstmdbx r0!, {d0}
+ 0+0b0 <[^>]*> eeb80ac0 fsitos s0, s0
+ 0+0b4 <[^>]*> eeb80a40 fuitos s0, s0
+ 0+0b8 <[^>]*> eebd0a40 ftosis s0, s0
+ 0+0bc <[^>]*> eebd0ac0 ftosizs s0, s0
+ 0+0c0 <[^>]*> eebc0a40 ftouis s0, s0
+ 0+0c4 <[^>]*> eebc0ac0 ftouizs s0, s0
+ 0+0c8 <[^>]*> ee100a10 fmrs r0, s0
+ 0+0cc <[^>]*> eef00a10 fmrx r0, fpsid
+ 0+0d0 <[^>]*> eef10a10 fmrx r0, fpscr
+ 0+0d4 <[^>]*> eef80a10 fmrx r0, fpexc
+ 0+0d8 <[^>]*> ee000a10 fmsr s0, r0
+ 0+0dc <[^>]*> eee00a10 fmxr fpsid, r0
+ 0+0e0 <[^>]*> eee10a10 fmxr fpscr, r0
+ 0+0e4 <[^>]*> eee80a10 fmxr fpexc, r0
+ 0+0e8 <[^>]*> eef50a40 fcmpzs s1
+ 0+0ec <[^>]*> eeb51a40 fcmpzs s2
+ 0+0f0 <[^>]*> eef5fa40 fcmpzs s31
+ 0+0f4 <[^>]*> eeb40a60 fcmps s0, s1
+ 0+0f8 <[^>]*> eeb40a41 fcmps s0, s2
+ 0+0fc <[^>]*> eeb40a6f fcmps s0, s31
+ 0+100 <[^>]*> eef40a40 fcmps s1, s0
+ 0+104 <[^>]*> eeb41a40 fcmps s2, s0
+ 0+108 <[^>]*> eef4fa40 fcmps s31, s0
+ 0+10c <[^>]*> eef4aa46 fcmps s21, s12
+ 0+110 <[^>]*> eeb10a60 fnegs s0, s1
+ 0+114 <[^>]*> eeb10a41 fnegs s0, s2
+ 0+118 <[^>]*> eeb10a6f fnegs s0, s31
+ 0+11c <[^>]*> eef10a40 fnegs s1, s0
+ 0+120 <[^>]*> eeb11a40 fnegs s2, s0
+ 0+124 <[^>]*> eef1fa40 fnegs s31, s0
+ 0+128 <[^>]*> eeb16a6a fnegs s12, s21
+ 0+12c <[^>]*> ee300a20 fadds s0, s0, s0
+ 0+130 <[^>]*> ee300a01 fadds s0, s0, s0
+ 0+134 <[^>]*> ee300a2f fadds s0, s0, s0
+ 0+138 <[^>]*> ee300a80 fadds s0, s1, s0
+ 0+13c <[^>]*> ee310a00 fadds s0, s2, s0
+ 0+140 <[^>]*> ee3f0a80 fadds s0, s31, s0
+ 0+144 <[^>]*> ee700a00 fadds s1, s0, s1
+ 0+148 <[^>]*> ee301a00 fadds s2, s0, s2
+ 0+14c <[^>]*> ee70fa00 fadds s31, s0, s31
+ 0+150 <[^>]*> ee3a6aa2 fadds s12, s21, s12
+ 0+154 <[^>]*> eeb80ae0 fsitos s0, s1
+ 0+158 <[^>]*> eeb80ac1 fsitos s0, s2
+ 0+15c <[^>]*> eeb80aef fsitos s0, s31
+ 0+160 <[^>]*> eef80ac0 fsitos s1, s0
+ 0+164 <[^>]*> eeb81ac0 fsitos s2, s0
+ 0+168 <[^>]*> eef8fac0 fsitos s31, s0
+ 0+16c <[^>]*> eebd0a60 ftosis s0, s1
+ 0+170 <[^>]*> eebd0a41 ftosis s0, s2
+ 0+174 <[^>]*> eebd0a6f ftosis s0, s31
+ 0+178 <[^>]*> eefd0a40 ftosis s1, s0
+ 0+17c <[^>]*> eebd1a40 ftosis s2, s0
+ 0+180 <[^>]*> eefdfa40 ftosis s31, s0
+ 0+184 <[^>]*> ee001a10 fmsr s0, r1
+ 0+188 <[^>]*> ee007a10 fmsr s0, r7
+ 0+18c <[^>]*> ee00ea10 fmsr s0, lr
+ 0+190 <[^>]*> ee000a90 fmsr s1, r0
+ 0+194 <[^>]*> ee010a10 fmsr s2, r0
+ 0+198 <[^>]*> ee0f0a90 fmsr s31, r0
+ 0+19c <[^>]*> ee0a7a90 fmsr s21, r7
+ 0+1a0 <[^>]*> eee01a10 fmxr fpsid, r1
+ 0+1a4 <[^>]*> eee0ea10 fmxr fpsid, lr
+ 0+1a8 <[^>]*> ee100a90 fmrs r0, s1
+ 0+1ac <[^>]*> ee110a10 fmrs r0, s2
+ 0+1b0 <[^>]*> ee1f0a90 fmrs r0, s31
+ 0+1b4 <[^>]*> ee101a10 fmrs r1, s0
+ 0+1b8 <[^>]*> ee107a10 fmrs r7, s0
+ 0+1bc <[^>]*> ee10ea10 fmrs lr, s0
+ 0+1c0 <[^>]*> ee159a90 fmrs r9, s11
+ 0+1c4 <[^>]*> eef01a10 fmrx r1, fpsid
+ 0+1c8 <[^>]*> eef0ea10 fmrx lr, fpsid
+ 0+1cc <[^>]*> ed910a00 flds s0, \[r1\]
+ 0+1d0 <[^>]*> ed9e0a00 flds s0, \[lr\]
+ 0+1d4 <[^>]*> ed900a00 flds s0, \[r0\]
+ 0+1d8 <[^>]*> ed900aff flds s0, \[r0, #1020\]
+ 0+1dc <[^>]*> ed100aff flds s0, \[r0, -#1020\]
+ 0+1e0 <[^>]*> edd00a00 flds s1, \[r0\]
+ 0+1e4 <[^>]*> ed901a00 flds s2, \[r0\]
+ 0+1e8 <[^>]*> edd0fa00 flds s31, \[r0\]
+ 0+1ec <[^>]*> edccaac9 fsts s21, \[ip, #804\]
+ 0+1f0 <[^>]*> ecd00a01 fldmias r0, {s1}
+ 0+1f4 <[^>]*> ec901a01 fldmias r0, {s2}
+ 0+1f8 <[^>]*> ecd0fa01 fldmias r0, {s31}
+ 0+1fc <[^>]*> ec900a02 fldmias r0, {s0-s1}
+ 0+200 <[^>]*> ec900a03 fldmias r0, {s0-s2}
+ 0+204 <[^>]*> ec900a20 fldmias r0, {s0-s31}
+ 0+208 <[^>]*> ecd00a1f fldmias r0, {s1-s31}
+ 0+20c <[^>]*> ec901a1e fldmias r0, {s2-s31}
+ 0+210 <[^>]*> ec90fa02 fldmias r0, {s30-s31}
+ 0+214 <[^>]*> ec910a01 fldmias r1, {s0}
+ 0+218 <[^>]*> ec9e0a01 fldmias lr, {s0}
+ 0+21c <[^>]*> ec801b03 fstmiax r0, {d1}
+ 0+220 <[^>]*> ec802b03 fstmiax r0, {d2}
+ 0+224 <[^>]*> ec80fb03 fstmiax r0, {d15}
+ 0+228 <[^>]*> ec800b05 fstmiax r0, {d0-d1}
+ 0+22c <[^>]*> ec800b07 fstmiax r0, {d0-d2}
+ 0+230 <[^>]*> ec800b21 fstmiax r0, {d0-d15}
+ 0+234 <[^>]*> ec801b1f fstmiax r0, {d1-d15}
+ 0+238 <[^>]*> ec802b1d fstmiax r0, {d2-d15}
+ 0+23c <[^>]*> ec80eb05 fstmiax r0, {d14-d15}
+ 0+240 <[^>]*> ec810b03 fstmiax r1, {d0}
+ 0+244 <[^>]*> ec8e0b03 fstmiax lr, {d0}
+ 0+248 <[^>]*> eeb50a40 fcmpzs s0
+ 0+24c <[^>]*> eef50a40 fcmpzs s1
+ 0+250 <[^>]*> eeb51a40 fcmpzs s2
+ 0+254 <[^>]*> eef51a40 fcmpzs s3
+ 0+258 <[^>]*> eeb52a40 fcmpzs s4
+ 0+25c <[^>]*> eef52a40 fcmpzs s5
+ 0+260 <[^>]*> eeb53a40 fcmpzs s6
+ 0+264 <[^>]*> eef53a40 fcmpzs s7
+ 0+268 <[^>]*> eeb54a40 fcmpzs s8
+ 0+26c <[^>]*> eef54a40 fcmpzs s9
+ 0+270 <[^>]*> eeb55a40 fcmpzs s10
+ 0+274 <[^>]*> eef55a40 fcmpzs s11
+ 0+278 <[^>]*> eeb56a40 fcmpzs s12
+ 0+27c <[^>]*> eef56a40 fcmpzs s13
+ 0+280 <[^>]*> eeb57a40 fcmpzs s14
+ 0+284 <[^>]*> eef57a40 fcmpzs s15
+ 0+288 <[^>]*> eeb58a40 fcmpzs s16
+ 0+28c <[^>]*> eef58a40 fcmpzs s17
+ 0+290 <[^>]*> eeb59a40 fcmpzs s18
+ 0+294 <[^>]*> eef59a40 fcmpzs s19
+ 0+298 <[^>]*> eeb5aa40 fcmpzs s20
+ 0+29c <[^>]*> eef5aa40 fcmpzs s21
+ 0+2a0 <[^>]*> eeb5ba40 fcmpzs s22
+ 0+2a4 <[^>]*> eef5ba40 fcmpzs s23
+ 0+2a8 <[^>]*> eeb5ca40 fcmpzs s24
+ 0+2ac <[^>]*> eef5ca40 fcmpzs s25
+ 0+2b0 <[^>]*> eeb5da40 fcmpzs s26
+ 0+2b4 <[^>]*> eef5da40 fcmpzs s27
+ 0+2b8 <[^>]*> eeb5ea40 fcmpzs s28
+ 0+2bc <[^>]*> eef5ea40 fcmpzs s29
+ 0+2c0 <[^>]*> eeb5fa40 fcmpzs s30
+ 0+2c4 <[^>]*> eef5fa40 fcmpzs s31
+ 0+2c8 <[^>]*> 0ef1fa10 fmstateq
+ 0+2cc <[^>]*> 0ef41ae3 fcmpeseq s3, s7
+ 0+2d0 <[^>]*> 0ef52ac0 fcmpezseq s5
+ 0+2d4 <[^>]*> 0ef40a41 fcmpseq s1, s2
+ 0+2d8 <[^>]*> 0ef50a40 fcmpzseq s1
+ 0+2dc <[^>]*> 0ef00ae1 fabsseq s1, s3
+ 0+2e0 <[^>]*> 0ef0fa69 fcpyseq s31, s19
+ 0+2e4 <[^>]*> 0eb1aa44 fnegseq s20, s8
+ 0+2e8 <[^>]*> 0ef12ae3 fsqrtseq s5, s7
+ 0+2ec <[^>]*> 0e323a82 faddseq s6, s5, s6
+ 0+2f0 <[^>]*> 0ec11a20 fdivseq s3, s2, s1
+ 0+2f4 <[^>]*> 0e4ffa2e fmacseq s31, s30, s29
+ 0+2f8 <[^>]*> 0e1dea8d fmscseq s28, s27, s26
+ 0+2fc <[^>]*> 0e6cca2b fmulseq s25, s24, s23
+ 0+300 <[^>]*> 0e0abaca fnmacseq s22, s21, s20
+ 0+304 <[^>]*> 0e599a68 fnmscseq s19, s18, s17
+ 0+308 <[^>]*> 0e278ac7 fnmulseq s16, s15, s14
+ 0+30c <[^>]*> 0e766a65 fsubseq s13, s12, s11
+ 0+310 <[^>]*> 0d985a00 fldseq s10, \[r8\]
+ 0+314 <[^>]*> 0dc74a00 fstseq s9, \[r7\]
+ 0+318 <[^>]*> 0c914a01 fldmiaseq r1, {s8}
+ 0+31c <[^>]*> 0cd23a01 fldmiaseq r2, {s7}
+ 0+320 <[^>]*> 0cb33a01 fldmiaseq r3!, {s6}
+ 0+324 <[^>]*> 0cf42a01 fldmiaseq r4!, {s5}
+ 0+328 <[^>]*> 0d352a01 fldmdbseq r5!, {s4}
+ 0+32c <[^>]*> 0d761a01 fldmdbseq r6!, {s3}
+ 0+330 <[^>]*> 0c971b03 fldmiaxeq r7, {d1}
+ 0+334 <[^>]*> 0c982b03 fldmiaxeq r8, {d2}
+ 0+338 <[^>]*> 0cb93b03 fldmiaxeq r9!, {d3}
+ 0+33c <[^>]*> 0cba4b03 fldmiaxeq sl!, {d4}
+ 0+340 <[^>]*> 0d3b5b03 fldmdbxeq fp!, {d5}
+ 0+344 <[^>]*> 0d3c6b03 fldmdbxeq ip!, {d6}
+ 0+348 <[^>]*> 0c8d1a01 fstmiaseq sp, {s2}
+ 0+34c <[^>]*> 0cce0a01 fstmiaseq lr, {s1}
+ 0+350 <[^>]*> 0ce1fa01 fstmiaseq r1!, {s31}
+ 0+354 <[^>]*> 0ca2fa01 fstmiaseq r2!, {s30}
+ 0+358 <[^>]*> 0d63ea01 fstmdbseq r3!, {s29}
+ 0+35c <[^>]*> 0d24ea01 fstmdbseq r4!, {s28}
+ 0+360 <[^>]*> 0c857b03 fstmiaxeq r5, {d7}
+ 0+364 <[^>]*> 0c868b03 fstmiaxeq r6, {d8}
+ 0+368 <[^>]*> 0ca79b03 fstmiaxeq r7!, {d9}
+ 0+36c <[^>]*> 0ca8ab03 fstmiaxeq r8!, {d10}
+ 0+370 <[^>]*> 0d29bb03 fstmdbxeq r9!, {d11}
+ 0+374 <[^>]*> 0d2acb03 fstmdbxeq sl!, {d12}
+ 0+378 <[^>]*> 0ef8dac3 fsitoseq s27, s6
+ 0+37c <[^>]*> 0efdca62 ftosiseq s25, s5
+ 0+380 <[^>]*> 0efdbac2 ftosizseq s23, s4
+ 0+384 <[^>]*> 0efcaa61 ftouiseq s21, s3
+ 0+388 <[^>]*> 0efc9ac1 ftouizseq s19, s2
+ 0+38c <[^>]*> 0ef88a60 fuitoseq s17, s1
+ 0+390 <[^>]*> 0e11ba90 fmrseq fp, s3
+ 0+394 <[^>]*> 0ef09a10 fmrxeq r9, fpsid
+ 0+398 <[^>]*> 0e019a90 fmsreq s3, r9
+ 0+39c <[^>]*> 0ee08a10 fmxreq fpsid, r8
Index: testsuite/gas/arm/vfp1xD.s
===================================================================
RCS file: vfp1xD.s
diff -N vfp1xD.s
*** /dev/null Tue May 5 13:32:27 1998
--- vfp1xD.s Tue Jan 15 07:50:32 2002
***************
*** 0 ****
--- 1,339 ----
+ @ VFP Instructions for v1xD variants (Single precision only)
+ .text
+ .global F
+ F:
+ @ First we test the basic syntax and bit patterns of the opcodes.
+ @ Most of these tests deliberatly use s0/r0 to avoid setting
+ @ any more bits than necessary.
+
+ @ Comparison operations
+
+ fmstat
+
+ fcmpes s0, s0
+ fcmpezs s0
+ fcmps s0, s0
+ fcmpzs s0
+
+ @ Monadic data operations
+
+ fabss s0, s0
+ fcpys s0, s0
+ fnegs s0, s0
+ fsqrts s0, s0
+
+ @ Dyadic data operations
+
+ fadds s0, s0, s0
+ fdivs s0, s0, s0
+ fmacs s0, s0, s0
+ fmscs s0, s0, s0
+ fmuls s0, s0, s0
+ fnmacs s0, s0, s0
+ fnmscs s0, s0, s0
+ fnmuls s0, s0, s0
+ fsubs s0, s0, s0
+
+ @ Load/store operations
+
+ flds s0, [r0]
+ fsts s0, [r0]
+
+ @ Load/store multiple operations
+
+ fldmias r0, {s0}
+ fldmfds r0, {s0}
+ fldmias r0!, {s0}
+ fldmfds r0!, {s0}
+ fldmdbs r0!, {s0}
+ fldmeas r0!, {s0}
+
+ fldmiax r0, {d0}
+ fldmfdx r0, {d0}
+ fldmiax r0!, {d0}
+ fldmfdx r0!, {d0}
+ fldmdbx r0!, {d0}
+ fldmeax r0!, {d0}
+
+ fstmias r0, {s0}
+ fstmeas r0, {s0}
+ fstmias r0!, {s0}
+ fstmeas r0!, {s0}
+ fstmdbs r0!, {s0}
+ fstmfds r0!, {s0}
+
+ fstmiax r0, {d0}
+ fstmeax r0, {d0}
+ fstmiax r0!, {d0}
+ fstmeax r0!, {d0}
+ fstmdbx r0!, {d0}
+ fstmfdx r0!, {d0}
+
+ @ Conversion operations
+
+ fsitos s0, s0
+ fuitos s0, s0
+
+ ftosis s0, s0
+ ftosizs s0, s0
+ ftouis s0, s0
+ ftouizs s0, s0
+
+ @ ARM from VFP operations
+
+ fmrs r0, s0
+ fmrx r0, fpsid
+ fmrx r0, fpscr
+ fmrx r0, fpexc
+
+ @ VFP From ARM operations
+
+ fmsr s0, r0
+ fmxr fpsid, r0
+ fmxr fpscr, r0
+ fmxr fpexc, r0
+
+ @ Now we test that the register fields are updated correctly for
+ @ each class of instruction.
+
+ @ Single register operations (compare-zero):
+
+ fcmpzs s1
+ fcmpzs s2
+ fcmpzs s31
+
+ @ Two register comparison operations:
+
+ fcmps s0, s1
+ fcmps s0, s2
+ fcmps s0, s31
+ fcmps s1, s0
+ fcmps s2, s0
+ fcmps s31, s0
+ fcmps s21, s12
+
+ @ Two register data operations (monadic)
+
+ fnegs s0, s1
+ fnegs s0, s2
+ fnegs s0, s31
+ fnegs s1, s0
+ fnegs s2, s0
+ fnegs s31, s0
+ fnegs s12, s21
+
+ @ Three register data operations (dyadic)
+
+ fadds s0, s0, s1
+ fadds s0, s0, s2
+ fadds s0, s0, s31
+ fadds s0, s1, s0
+ fadds s0, s2, s0
+ fadds s0, s31, s0
+ fadds s1, s0, s0
+ fadds s2, s0, s0
+ fadds s31, s0, s0
+ fadds s12, s21, s5
+
+ @ Conversion operations
+
+ fsitos s0, s1
+ fsitos s0, s2
+ fsitos s0, s31
+ fsitos s1, s0
+ fsitos s2, s0
+ fsitos s31, s0
+
+ ftosis s0, s1
+ ftosis s0, s2
+ ftosis s0, s31
+ ftosis s1, s0
+ ftosis s2, s0
+ ftosis s31, s0
+
+ @ Move to VFP from ARM
+
+ fmsr s0, r1
+ fmsr s0, r7
+ fmsr s0, r14
+ fmsr s1, r0
+ fmsr s2, r0
+ fmsr s31, r0
+ fmsr s21, r7
+
+ fmxr fpsid, r1
+ fmxr fpsid, r14
+
+ @ Move to ARM from VFP
+
+ fmrs r0, s1
+ fmrs r0, s2
+ fmrs r0, s31
+ fmrs r1, s0
+ fmrs r7, s0
+ fmrs r14, s0
+ fmrs r9, s11
+
+ fmrx r1, fpsid
+ fmrx r14, fpsid
+
+ @ Load/store operations
+
+ flds s0, [r1]
+ flds s0, [r14]
+ flds s0, [r0, #0]
+ flds s0, [r0, #1020]
+ flds s0, [r0, #-1020]
+ flds s1, [r0]
+ flds s2, [r0]
+ flds s31, [r0]
+ fsts s21, [r12, #804]
+
+ @ Load/store multiple operations
+
+ fldmias r0, {s1}
+ fldmias r0, {s2}
+ fldmias r0, {s31}
+ fldmias r0, {s0-s1}
+ fldmias r0, {s0-s2}
+ fldmias r0, {s0-s31}
+ fldmias r0, {s1-s31}
+ fldmias r0, {s2-s31}
+ fldmias r0, {s30-s31}
+ fldmias r1, {s0}
+ fldmias r14, {s0}
+
+ fstmiax r0, {d1}
+ fstmiax r0, {d2}
+ fstmiax r0, {d15}
+ fstmiax r0, {d0-d1}
+ fstmiax r0, {d0-d2}
+ fstmiax r0, {d0-d15}
+ fstmiax r0, {d1-d15}
+ fstmiax r0, {d2-d15}
+ fstmiax r0, {d14-d15}
+ fstmiax r1, {d0}
+ fstmiax r14, {d0}
+
+ @ Check that we assemble all the register names correctly
+
+ fcmpzs s0
+ fcmpzs s1
+ fcmpzs s2
+ fcmpzs s3
+ fcmpzs s4
+ fcmpzs s5
+ fcmpzs s6
+ fcmpzs s7
+ fcmpzs s8
+ fcmpzs s9
+ fcmpzs s10
+ fcmpzs s11
+ fcmpzs s12
+ fcmpzs s13
+ fcmpzs s14
+ fcmpzs s15
+ fcmpzs s16
+ fcmpzs s17
+ fcmpzs s18
+ fcmpzs s19
+ fcmpzs s20
+ fcmpzs s21
+ fcmpzs s22
+ fcmpzs s23
+ fcmpzs s24
+ fcmpzs s25
+ fcmpzs s26
+ fcmpzs s27
+ fcmpzs s28
+ fcmpzs s29
+ fcmpzs s30
+ fcmpzs s31
+
+ @ Now we check the placement of the conditional execution substring.
+ @ On VFP this is always at the end of the instruction.
+ @ We use different register numbers here to check for correct
+ @ disassembly
+
+ @ Comparison operations
+
+ fmstateq
+
+ fcmpeseq s3, s7
+ fcmpezseq s5
+ fcmpseq s1, s2
+ fcmpzseq s1
+
+ @ Monadic data operations
+
+ fabsseq s1, s3
+ fcpyseq s31, s19
+ fnegseq s20, s8
+ fsqrtseq s5, s7
+
+ @ Dyadic data operations
+
+ faddseq s6, s5, s4
+ fdivseq s3, s2, s1
+ fmacseq s31, s30, s29
+ fmscseq s28, s27, s26
+ fmulseq s25, s24, s23
+ fnmacseq s22, s21, s20
+ fnmscseq s19, s18, s17
+ fnmulseq s16, s15, s14
+ fsubseq s13, s12, s11
+
+ @ Load/store operations
+
+ fldseq s10, [r8]
+ fstseq s9, [r7]
+
+ @ Load/store multiple operations
+
+ fldmiaseq r1, {s8}
+ fldmfdseq r2, {s7}
+ fldmiaseq r3!, {s6}
+ fldmfdseq r4!, {s5}
+ fldmdbseq r5!, {s4}
+ fldmeaseq r6!, {s3}
+
+ fldmiaxeq r7, {d1}
+ fldmfdxeq r8, {d2}
+ fldmiaxeq r9!, {d3}
+ fldmfdxeq r10!, {d4}
+ fldmdbxeq r11!, {d5}
+ fldmeaxeq r12!, {d6}
+
+ fstmiaseq r13, {s2}
+ fstmeaseq r14, {s1}
+ fstmiaseq r1!, {s31}
+ fstmeaseq r2!, {s30}
+ fstmdbseq r3!, {s29}
+ fstmfdseq r4!, {s28}
+
+ fstmiaxeq r5, {d7}
+ fstmeaxeq r6, {d8}
+ fstmiaxeq r7!, {d9}
+ fstmeaxeq r8!, {d10}
+ fstmdbxeq r9!, {d11}
+ fstmfdxeq r10!, {d12}
+
+ @ Conversion operations
+
+ fsitoseq s27, s6
+ ftosiseq s25, s5
+ ftosizseq s23, s4
+ ftouiseq s21, s3
+ ftouizseq s19, s2
+ fuitoseq s17, s1
+
+ @ ARM from VFP operations
+
+ fmrseq r11, s3
+ fmrxeq r9, fpsid
+
+ @ VFP From ARM operations
+
+ fmsreq s3, r9
+ fmxreq fpsid, r8
+