From cf86120bae8973340583a0613ad622f0ca013efd Mon Sep 17 00:00:00 2001 From: Matthew Wahab Date: Fri, 27 Nov 2015 16:25:52 +0000 Subject: [PATCH] [AArch64][PATCH 2/3] Adjust a utility function for floating point values. ARMv8.2 adds 16-bit floating point operations as an optional extension. This patch adjusts the utility function expand_fp_imm to support 16-bit values. The function is intended to convert an 8-bit immediate representing a floating point value to a representation that can be passed to fprintf. Because of the limited use of the results, the only change made to the function is to treat a request for a 16-bit float as a request for a 32-bit float. opcodes/ 2015-11-27 Matthew Wahab * aarch64-opc.c (half_conv_t): New. (expand_fp_imm): Replace is_dp flag with the parameter size to specify the number of bytes for the required expansion. Treat a 16-bit expansion like a 32-bit expansion. Add check for an unsupported size request. Update comment. (aarch64_print_operand): Update to support 16-bit floating point values. Update for changes to expand_fp_imm. Change-Id: I1ae3df3864be375d71925197ab03397ed1ad2d15 --- opcodes/ChangeLog | 10 ++++++++++ opcodes/aarch64-opc.c | 34 +++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index afdd7e7cf9..36b3d568ef 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,13 @@ +2015-11-27 Matthew Wahab + + * aarch64-opc.c (half_conv_t): New. + (expand_fp_imm): Replace is_dp flag with the parameter size to + specify the number of bytes for the required expansion. Treat + a 16-bit expansion like a 32-bit expansion. Add check for an + unsupported size request. Update comment. + (aarch64_print_operand): Update to support 16-bit floating point + values. Update for changes to expand_fp_imm. + 2015-11-27 Matthew Wahab * aarch64-tbl.h (aarch64_feature_fp_f16): New. diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index 9d1aa56aec..db14ce2363 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -2172,14 +2172,22 @@ typedef union float f; } single_conv_t; +typedef union +{ + uint32_t i; + float f; +} half_conv_t; + /* IMM8 is an 8-bit floating-point constant with sign, 3-bit exponent and normalized 4 bits of precision, encoded in "a:b:c:d:e:f:g:h" or FLD_imm8 (depending on the type of the instruction). IMM8 will be expanded to a - single-precision floating-point value (IS_DP == 0) or a double-precision - floating-point value (IS_DP == 1). The expanded value is returned. */ + single-precision floating-point value (SIZE == 4) or a double-precision + floating-point value (SIZE == 8). A half-precision floating-point value + (SIZE == 2) is expanded to a single-precision floating-point value. The + expanded value is returned. */ static uint64_t -expand_fp_imm (int is_dp, uint32_t imm8) +expand_fp_imm (int size, uint32_t imm8) { uint64_t imm; uint32_t imm8_7, imm8_6_0, imm8_6, imm8_6_repl4; @@ -2189,7 +2197,7 @@ expand_fp_imm (int is_dp, uint32_t imm8) imm8_6 = imm8_6_0 >> 6; /* imm8<6> */ imm8_6_repl4 = (imm8_6 << 3) | (imm8_6 << 2) | (imm8_6 << 1) | imm8_6; /* Replicate(imm8<6>,4) */ - if (is_dp) + if (size == 8) { imm = (imm8_7 << (63-32)) /* imm8<7> */ | ((imm8_6 ^ 1) << (62-32)) /* NOT(imm8<6) */ @@ -2198,13 +2206,18 @@ expand_fp_imm (int is_dp, uint32_t imm8) | (imm8_6_0 << (48-32)); /* imm8<6>:imm8<5:0> */ imm <<= 32; } - else + else if (size == 4 || size == 2) { imm = (imm8_7 << 31) /* imm8<7> */ | ((imm8_6 ^ 1) << 30) /* NOT(imm8<6>) */ | (imm8_6_repl4 << 26) /* Replicate(imm8<6>,4) */ | (imm8_6_0 << 19); /* imm8<6>:imm8<5:0> */ } + else + { + /* An unsupported size. */ + assert (0); + } return imm; } @@ -2533,17 +2546,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc, case AARCH64_OPND_SIMD_FPIMM: switch (aarch64_get_qualifier_esize (opnds[0].qualifier)) { + case 2: /* e.g. FMOV , #. */ + { + half_conv_t c; + c.i = expand_fp_imm (2, opnd->imm.value); + snprintf (buf, size, "#%.18e", c.f); + } + break; case 4: /* e.g. FMOV .4S, #. */ { single_conv_t c; - c.i = expand_fp_imm (0, opnd->imm.value); + c.i = expand_fp_imm (4, opnd->imm.value); snprintf (buf, size, "#%.18e", c.f); } break; case 8: /* e.g. FMOV , #. */ { double_conv_t c; - c.i = expand_fp_imm (1, opnd->imm.value); + c.i = expand_fp_imm (8, opnd->imm.value); snprintf (buf, size, "#%.18e", c.d); } break; -- 2.34.1