From ba592044bc04610d6fa14d0a95931bac303ace37 Mon Sep 17 00:00:00 2001 From: Alessandro Marzocchi Date: Wed, 17 Jun 2015 12:56:17 +0100 Subject: [PATCH] Add support for converting VLDR ,= to a VMOV instruction when appropriate. PR gas/18500 gas * config/tc-arm.c (is_double_a_single): New function. (double_to_single): New function. (move_or_literal_pool): Add support for converting VLDR to VMOV. tests * gas/arm/vfpv2-ldr_immediate.s: New test case. * gas/arm/vfpv2-ldr_immediate.d: Expected disassembly. * gas/arm/vfpv3-ldr_immediate.s: New test case. * gas/arm/vfpv3-ldr_immediate.d: Expected disassembly. * gas/arm/vfpv3xd-ldr_immediate.s: New test case. * gas/arm/vfpv3xd-ldr_immediate.d: Expected disassembly. --- gas/ChangeLog | 7 + gas/config/tc-arm.c | 217 +++++++++++++----- gas/testsuite/ChangeLog | 10 + gas/testsuite/gas/arm/vfpv2-ldr_immediate.d | 50 ++++ gas/testsuite/gas/arm/vfpv2-ldr_immediate.s | 48 ++++ gas/testsuite/gas/arm/vfpv3-ldr_immediate.d | 35 +++ gas/testsuite/gas/arm/vfpv3-ldr_immediate.s | 46 ++++ gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d | 42 ++++ gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s | 47 ++++ gas/write.c | 11 +- 10 files changed, 452 insertions(+), 61 deletions(-) create mode 100644 gas/testsuite/gas/arm/vfpv2-ldr_immediate.d create mode 100644 gas/testsuite/gas/arm/vfpv2-ldr_immediate.s create mode 100644 gas/testsuite/gas/arm/vfpv3-ldr_immediate.d create mode 100644 gas/testsuite/gas/arm/vfpv3-ldr_immediate.s create mode 100644 gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d create mode 100644 gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 7acc12a7567..b751117a3a2 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2015-06-17 Alessandro Marzocchi + + PR gas/18500 + * config/tc-arm.c (is_double_a_single): New function. + (double_to_single): New function. + (move_or_literal_pool): Add support for converting VLDR to VMOV. + 2015-06-17 Nicolas Pitre * as.c (show_usage): Document --sectname-subst. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 7ad55bf78db..84e95d414ac 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -4924,7 +4924,9 @@ parse_fpa_immediate (char ** str) { /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it. Ditto for 15. */ - if (gen_to_words (words, 5, (long) 15) == 0) +#define X_PRECISION 5 +#define E_PRECISION 15L + if (gen_to_words (words, X_PRECISION, E_PRECISION) == 0) { for (i = 0; i < NUM_FLOAT_VALS; i++) { @@ -7750,6 +7752,52 @@ neon_cmode_for_move_imm (unsigned immlo, unsigned immhi, int float_p, return FAIL; } +/* Returns TRUE if double precision value V may be cast + to single precision without loss of accuracy. */ + +static bfd_boolean +is_double_a_single (long int v) +{ + int exp = (int) (v >> 52) & 0x7FF; + long int mantissa = (v & 0xFFFFFFFFFFFFFl); + + return (exp == 0 || exp == 0x7FF + || (exp >= 1023 - 126 && exp <= 1023 + 127)) + && (mantissa & 0x1FFFFFFFl) == 0; +} + +/* Returns a double precision value casted to single precision + (ignoring the least significant bits in exponent and mantissa). */ + +static int +double_to_single (long int v) +{ + int sign = (int) ((v >> 63) & 1l); + int exp = (int) (v >> 52) & 0x7FF; + long int mantissa = (v & 0xFFFFFFFFFFFFFl); + + if (exp == 0x7FF) + exp = 0xFF; + else + { + exp = exp - 1023 + 127; + if (exp >= 0xFF) + { + /* Infinity. */ + exp = 0x7F; + mantissa = 0; + } + else if (exp < 0) + { + /* No denormalized numbers. */ + exp = 0; + mantissa = 0; + } + } + mantissa >>= 29; + return (sign << 31) | (exp << 23) | mantissa; +} + enum lit_type { CONST_THUMB, @@ -7757,6 +7805,8 @@ enum lit_type CONST_VEC }; +static void do_vfp_nsyn_opcode (const char *); + /* inst.reloc.exp describes an "=expr" load pseudo-operation. Determine whether it can be performed with a move instruction; if it can, convert inst.instruction to that move instruction and @@ -7772,7 +7822,6 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) unsigned long tbit; bfd_boolean thumb_p = (t == CONST_THUMB); bfd_boolean arm_p = (t == CONST_ARM); - bfd_boolean vec64_p = (t == CONST_VEC) && !inst.operands[i].issingle; if (thumb_p) tbit = (inst.instruction > 0xffff) ? THUMB2_LOAD_BIT : THUMB_LOAD_BIT; @@ -7784,6 +7833,7 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) inst.error = _("invalid pseudo operation"); return TRUE; } + if (inst.reloc.exp.X_op != O_constant && inst.reloc.exp.X_op != O_symbol && inst.reloc.exp.X_op != O_big) @@ -7791,76 +7841,129 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) inst.error = _("constant expression expected"); return TRUE; } - if ((inst.reloc.exp.X_op == O_constant - || inst.reloc.exp.X_op == O_big) - && !inst.operands[i].issingle) + + if (inst.reloc.exp.X_op == O_constant + || inst.reloc.exp.X_op == O_big) { - if (thumb_p && inst.reloc.exp.X_op == O_constant) + offsetT v; + + if (inst.reloc.exp.X_op == O_big) { - if (!unified_syntax && (inst.reloc.exp.X_add_number & ~0xFF) == 0) + LITTLENUM_TYPE w[X_PRECISION]; + LITTLENUM_TYPE * l; + + if (inst.reloc.exp.X_add_number == -1) { - /* This can be done with a mov(1) instruction. */ - inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8); - inst.instruction |= inst.reloc.exp.X_add_number; - return TRUE; + gen_to_words (w, X_PRECISION, E_PRECISION); + l = w; + /* FIXME: Should we check words w[2..5] ? */ } + else + l = generic_bignum; + + v = ((l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) + | (l[0] & LITTLENUM_MASK); } - else if (arm_p && inst.reloc.exp.X_op == O_constant) + else + v = inst.reloc.exp.X_add_number; + + if (!inst.operands[i].issingle) { - int value = encode_arm_immediate (inst.reloc.exp.X_add_number); - if (value != FAIL) + if (thumb_p && inst.reloc.exp.X_op == O_constant) { - /* This can be done with a mov instruction. */ - inst.instruction &= LITERAL_MASK; - inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); - inst.instruction |= value & 0xfff; - return TRUE; + if (!unified_syntax && (v & ~0xFF) == 0) + { + /* This can be done with a mov(1) instruction. */ + inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8); + inst.instruction |= v; + return TRUE; + } } + else if (arm_p && inst.reloc.exp.X_op == O_constant) + { + int value = encode_arm_immediate (v); + if (value != FAIL) + { + /* This can be done with a mov instruction. */ + inst.instruction &= LITERAL_MASK; + inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); + inst.instruction |= value & 0xfff; + return TRUE; + } - value = encode_arm_immediate (~inst.reloc.exp.X_add_number); - if (value != FAIL) + value = encode_arm_immediate (~ v); + if (value != FAIL) + { + /* This can be done with a mvn instruction. */ + inst.instruction &= LITERAL_MASK; + inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT); + inst.instruction |= value & 0xfff; + return TRUE; + } + } + else if (t == CONST_VEC) { - /* This can be done with a mvn instruction. */ - inst.instruction &= LITERAL_MASK; - inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT); - inst.instruction |= value & 0xfff; - return TRUE; + int op = 0; + unsigned immbits = 0; + unsigned immlo = inst.operands[1].imm; + unsigned immhi = inst.operands[1].regisimm + ? inst.operands[1].reg + : inst.reloc.exp.X_unsigned + ? 0 + : ((bfd_int64_t)((int) immlo)) >> 32; + int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, + &op, 64, NT_invtype); + + if (cmode == FAIL) + { + neon_invert_size (&immlo, &immhi, 64); + op = !op; + cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, + &op, 64, NT_invtype); + } + + if (cmode != FAIL) + { + inst.instruction = (inst.instruction & VLDR_VMOV_SAME) + | (1 << 23) + | (cmode << 8) + | (op << 5) + | (1 << 4); + + /* Fill other bits in vmov encoding for both thumb and arm. */ + if (thumb_mode) + inst.instruction |= (0x7 << 29) | (0xF << 24); + else + inst.instruction |= (0xF << 28) | (0x1 << 25); + neon_write_immbits (immbits); + return TRUE; + } } } - else if (vec64_p) - { - int op = 0; - unsigned immbits = 0; - unsigned immlo = inst.operands[1].imm; - unsigned immhi = inst.operands[1].regisimm - ? inst.operands[1].reg - : inst.reloc.exp.X_unsigned - ? 0 - : ((bfd_int64_t)((int) immlo)) >> 32; - int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, - &op, 64, NT_invtype); - if (cmode == FAIL) + if (t == CONST_VEC) + { + /* Check if vldr Rx, =constant could be optimized to vmov Rx, #constant. */ + if (inst.operands[i].issingle + && is_quarter_float (inst.operands[1].imm) + && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3xd)) { - neon_invert_size (&immlo, &immhi, 64); - op = !op; - cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, - &op, 64, NT_invtype); + inst.operands[1].imm = + neon_qfloat_bits (v); + do_vfp_nsyn_opcode ("fconsts"); + return TRUE; } - if (cmode != FAIL) + else if (!inst.operands[1].issingle + && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3)) { - inst.instruction = (inst.instruction & VLDR_VMOV_SAME) - | (1 << 23) - | (cmode << 8) - | (op << 5) - | (1 << 4); - /* Fill other bits in vmov encoding for both thumb and arm. */ - if (thumb_mode) - inst.instruction |= (0x7 << 29) | (0xF << 24); - else - inst.instruction |= (0xF << 28) | (0x1 << 25); - neon_write_immbits (immbits); - return TRUE; + if (is_double_a_single (v) + && is_quarter_float (double_to_single (v))) + { + inst.operands[1].imm = + neon_qfloat_bits (double_to_single (v)); + do_vfp_nsyn_opcode ("fconstd"); + return TRUE; + } } } } @@ -8799,8 +8902,6 @@ do_mov16 (void) } } -static void do_vfp_nsyn_opcode (const char *); - static int do_vfp_nsyn_mrs (void) { diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 245f6c34565..fae6e95e9f5 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2015-06-17 Alessandro Marzocchi + + PR gas/18500 + * gas/arm/vfpv2-ldr_immediate.s: New test case. + * gas/arm/vfpv2-ldr_immediate.d: Expected disassembly. + * gas/arm/vfpv3-ldr_immediate.s: New test case. + * gas/arm/vfpv3-ldr_immediate.d: Expected disassembly. + * gas/arm/vfpv3xd-ldr_immediate.s: New test case. + * gas/arm/vfpv3xd-ldr_immediate.d: Expected disassembly. + 2015-06-16 Matthew Wahab * sysreg.d: Add id_mmfr4_el1, update expected output. diff --git a/gas/testsuite/gas/arm/vfpv2-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.d new file mode 100644 index 00000000000..109d4437166 --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.d @@ -0,0 +1,50 @@ +# name: VFPv2 vldr to vmov +# as: -mfpu=vfpv2 +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section \.text: + +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fbe0000 .* +0[0-9a-fx]+ .*3df00000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*bfc00000 .* +0[0-9a-fx]+ .*be000000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fc00000 .* +0[0-9a-fx]+ .*3e000000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fe08000 .* +0[0-9a-fx]+ .*3f040000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fef0000 .* +0[0-9a-fx]+ .*3f780000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*403f0000 .* +0[0-9a-fx]+ .*41f80000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*40400000 .* +0[0-9a-fx]+ .*42000000 .* +#pass diff --git a/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s new file mode 100644 index 00000000000..650d9b89678 --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv2-ldr_immediate.s @@ -0,0 +1,48 @@ +.arm +.syntax unified + # VFPv2 has no VMOV instruction... all vldr will be kept + + # 15 * 2^-7 =0.1171875 VMOV does not exists + .align 3 + vldr d0,=0x3FBE000000000000 + vldr s0,=0x3df00000 + .pool + + # -16 * 2^-7 =0.125 VMOV does not exists + .align 3 + vldr d0,=0xbfc0000000000000 + vldr s0,=0xbe000000 + .pool + + # 16 * 2^-7 =0.125 VMOV does not exists + .align 3 + vldr d0,=0x3fc0000000000000 + vldr s0,=0x3e000000 + .pool + + # 16.5 * 2^-7 =0.125 VMOV does not exists + .align 3 + vldr d0,=0x3fe0800000000000 + vldr s0,=0x3f040000 + .pool + + # 31 * 2^-5 = 0.96875 VMOV does not exists + .align 3 + vldr d0,=0x3fef000000000000 + vldr s0,=0x3f780000 + .pool + + # 31 * 2^ 0 = 31 VMOV does not exists + .align 3 + vldr d0,=0x403F000000000000 + vldr s0,=0x41f80000 + .pool + + # 16 * 2^ 1 = 32 VMOV does not exists + .align 3 + vldr d0,=0x4040000000000000 + vldr s0,=0x42000000 + .pool + + nop + diff --git a/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d new file mode 100644 index 00000000000..5f0e925c662 --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.d @@ -0,0 +1,35 @@ +# name: VFPv3 vldr to vmov +# as: -mfpu=vfp3 +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section \.text: + +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fbe0000 .* +0[0-9a-fx]+ .*3df00000 .* +.* + +0[0-9a-fx]+ .*eebc0b00 (vmov\.f64|fconstd) d0, #192.* +0[0-9a-fx]+ .*eebc0a00 (vmov\.f32|fconsts) s0, #192.* +0[0-9a-fx]+ .*eeb40b00 (vmov\.f64|fconstd) d0, #64.* +0[0-9a-fx]+ .*eeb40a00 (vmov\.f32|fconsts) s0, #64.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fe08000 .* +0[0-9a-fx]+ .*3f040000 .* +.* +0[0-9a-fx]+ .*eeb60b0f (vmov\.f64|fconstd) d0, #111.* +0[0-9a-fx]+ .*eeb60a0f (vmov\.f32|fconsts) s0, #111.* +0[0-9a-fx]+ .*eeb30b0f (vmov\.f64|fconstd) d0, #63.* +0[0-9a-fx]+ .*eeb30a0f (vmov\.f32|fconsts) s0, #63.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*40400000 .* +0[0-9a-fx]+ .*42000000 .* +#pass diff --git a/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s new file mode 100644 index 00000000000..172b57d62d5 --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv3-ldr_immediate.s @@ -0,0 +1,46 @@ +.arm +.syntax unified + # 15 * 2^-7 =0.1171875 Not convertible to VMOV + .align 3 + vldr d0,=0x3FBE000000000000 + vldr s0,=0x3df00000 + .pool + + # -16 * 2^-7 =-0.125 Convertible to VMOV + .align 3 + vldr d0,=0xbfc0000000000000 + vldr s0,=0xbe000000 + .pool + + # 16 * 2^-7 =0.125 Convertible to VMOV + .align 3 + vldr d0,=0x3fc0000000000000 + vldr s0,=0x3e000000 + .pool + + # 16.5 * 2^-7 =0.125 Not convertible to VMOV + .align 3 + vldr d0,=0x3fe0800000000000 + vldr s0,=0x3f040000 + .pool + + # 31 * 2^-5 = 0.96875 Convertible to VMOV + .align 3 + vldr d0,=0x3fef000000000000 + vldr s0,=0x3f780000 + .pool + + # 31 * 2^ 0 = 31 Convertible to VMOV + .align 3 + vldr d0,=0x403F000000000000 + vldr s0,=0x41f80000 + .pool + + # 16 * 2^ 1 = 32 Not convertible to VMOV + .align 3 + vldr d0,=0x4040000000000000 + vldr s0,=0x42000000 + .pool + + nop + diff --git a/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d new file mode 100644 index 00000000000..5df3d26ecf8 --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.d @@ -0,0 +1,42 @@ +# name: VFPv3xd vldr to vmov +# as: -mfpu=vfpv3xd +# objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section \.text: + +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fbe0000 .* +0[0-9a-fx]+ .*3df00000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*eebc0a00 (vmov\.f32|fconsts) s0, #192.* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*bfc00000 .* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*eeb40a00 (vmov\.f32|fconsts) s0, #64.* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fc00000 .* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fe08000 .* +0[0-9a-fx]+ .*3f040000 .* +.* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*eeb60a0f (vmov\.f32|fconsts) s0, #111.* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*3fef0000 .* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*eeb30a0f (vmov\.f32|fconsts) s0, #63.* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*403f0000 .* +0[0-9a-fx]+ .*ed9f0b00 vldr d0, \[pc\].* +0[0-9a-fx]+ .*ed9f0a01 vldr s0, \[pc, #4\].* +0[0-9a-fx]+ .*00000000 .* +0[0-9a-fx]+ .*40400000 .* +0[0-9a-fx]+ .*42000000 .* +#pass diff --git a/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s new file mode 100644 index 00000000000..130e49b188a --- /dev/null +++ b/gas/testsuite/gas/arm/vfpv3xd-ldr_immediate.s @@ -0,0 +1,47 @@ +.arm +.syntax unified + # VFPv3xD has no VMOV instruction for double precision registers... + # 15 * 2^-7 =0.1171875 Not convertible to VMOV + .align 3 + vldr d0,=0x3FBE000000000000 + vldr s0,=0x3df00000 + .pool + + # -16 * 2^-7 =0.125 Convertible to VMOV + .align 3 + vldr d0,=0xbfc0000000000000 + vldr s0,=0xbe000000 + .pool + + # 16 * 2^-7 =0.125 Convertible to VMOV + .align 3 + vldr d0,=0x3fc0000000000000 + vldr s0,=0x3e000000 + .pool + + # 16.5 * 2^-7 =0.125 Not convertible to VMOV + .align 3 + vldr d0,=0x3fe0800000000000 + vldr s0,=0x3f040000 + .pool + + # 31 * 2^-5 = 0.96875 Convertible to VMOV + .align 3 + vldr d0,=0x3fef000000000000 + vldr s0,=0x3f780000 + .pool + + # 31 * 2^ 0 = 31 Convertible to VMOV + .align 3 + vldr d0,=0x403F000000000000 + vldr s0,=0x41f80000 + .pool + + # 16 * 2^ 1 = 32 Not convertible to VMOV + .align 3 + vldr d0,=0x4040000000000000 + vldr s0,=0x42000000 + .pool + + nop + diff --git a/gas/write.c b/gas/write.c index 894b271f776..a76813dac11 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1585,7 +1585,9 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED, f->fr_literal, (file_ptr) offset, (bfd_size_type) f->fr_fix); if (!x) - as_fatal (_("can't write %s: %s"), stdoutput->filename, + as_fatal (_("can't write %ld bytes to section %s of %s because: '%s'"), + (long) f->fr_fix, sec->name, + stdoutput->filename, bfd_errmsg (bfd_get_error ())); offset += f->fr_fix; } @@ -1606,7 +1608,9 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED, (file_ptr) offset, (bfd_size_type) fill_size); if (!x) - as_fatal (_("can't write %s: %s"), stdoutput->filename, + as_fatal (_("can't fill %ld bytes in section %s of %s because '%s'"), + (long) fill_size, sec->name, + stdoutput->filename, bfd_errmsg (bfd_get_error ())); offset += fill_size; } @@ -1636,7 +1640,8 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED, (stdoutput, sec, buf, (file_ptr) offset, (bfd_size_type) n_per_buf * fill_size); if (!x) - as_fatal (_("cannot write to output file '%s': %s"), + as_fatal (_("cannot fill %ld bytes in section %s of %s because: '%s'"), + (long)(n_per_buf * fill_size), sec->name, stdoutput->filename, bfd_errmsg (bfd_get_error ())); offset += n_per_buf * fill_size; -- 2.30.2