This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] ARM half-precision support


This patch adds the binutils support for arm half-precision instructions. Does this look okay to install? I will post the additions to the gas testsuite separately. Thanks,
Catherine


        gas/
        * config/tc-arm.c (neon_type_mask): Renumber.
        (type_chk_of_el_type): Handle F_F16.
        (neon_cvt_flavour): Recognize half-precision conversions.
        (do_neon_cvt): New shapes NS_QD and NS_DQ.  Encode half-precision
        conversions.
        (do_neon_cvtt): Encode the T bit.
        (asm_opcode_insns): vcvt, vcvtt support.
        (arm_option_cpu_value): Add neon-fp16 support.

        include/
        * opcode/arm.h (FPU_NEON_FP16): New.
        (FPU_ARCH_NEON_FP16): New.
        * elf/arm.h (Tag_ABI_FP_16bit_format): Define.

        opcodes/
        * arm-dis.c (coprocessor_opcodes): Add half-precision vcvt
        instructions.
        (neon_opcodes): Likewise.
        (print_insn_coprocessor): Print 't' or 'b' for
        vcvt instructions.

        binutils/
        * readelf.c (arm_attr_tag_ABI_FP_16bit_format): New.
        (arm_attr_tag_VFP_HP_extension): New.
        (arm_attr_public_tag arm_attr_public_tags): Support new
        attributes.

        bfd/
        * elf32-arm.c (elf32_arm_merge_eabi_attributes): Merge
        half-precision attributes.
        (elf32_arm_copy_one_eabi_other_attribute): New.
        (elf32_arm_copy_other_attribute_list): New.
Index: src/bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.157
diff -p -r1.157 elf32-arm.c
*** src/bfd/elf32-arm.c	26 Aug 2008 14:40:18 -0000	1.157
--- src/bfd/elf32-arm.c	14 Nov 2008 17:07:01 -0000
*************** elf32_arm_obj_attrs_arg_type (int tag)
*** 8163,8168 ****
--- 8163,8195 ----
      return (tag & 1) != 0 ? 2 : 1;
  }
  
+ static void
+ elf32_arm_copy_one_eabi_other_attribute (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
+ {
+   switch (in_list->tag)
+     {
+     case Tag_VFP_HP_extension:
+     case Tag_ABI_FP_16bit_format:
+       bfd_elf_add_obj_attr_int (obfd, OBJ_ATTR_PROC, in_list->tag, in_list->attr.i);
+       break;
+ 
+     default:
+       if ((in_list->tag & 127) < 64)
+ 	{
+ 	  _bfd_error_handler
+ 	      (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
+ 	  break;
+ 	}
+     }
+ }
+ 
+ static void 
+ elf32_arm_copy_eabi_other_attribute_list (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
+ {
+   for (; in_list; in_list = in_list->next )
+     elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
+ }
+ 
  /* Merge EABI object attributes from IBFD into OBFD.  Raise an error if there
     are conflicting attributes.  */
  
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8172,8177 ****
--- 8199,8205 ----
    obj_attribute *in_attr;
    obj_attribute *out_attr;
    obj_attribute_list *in_list;
+   obj_attribute_list *out_list;
    /* Some tags have 0 = don't care, 1 = strong requirement,
       2 = weak requirement.  */
    static const int order_312[3] = {3, 1, 2};
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8196,8202 ****
    /* This needs to happen before Tag_ABI_FP_number_model is merged.  */
    if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i)
      {
!       /* Ignore mismatches if teh object doesn't use floating point.  */
        if (out_attr[Tag_ABI_FP_number_model].i == 0)
  	out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i;
        else if (in_attr[Tag_ABI_FP_number_model].i != 0)
--- 8224,8230 ----
    /* This needs to happen before Tag_ABI_FP_number_model is merged.  */
    if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i)
      {
!       /* Ignore mismatches if the object doesn't use floating point.  */
        if (out_attr[Tag_ABI_FP_number_model].i == 0)
  	out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i;
        else if (in_attr[Tag_ABI_FP_number_model].i != 0)
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8362,8367 ****
--- 8390,8396 ----
  	      return FALSE;
  	    }
  	  break;
+ 
  	default: /* All known attributes should be explicitly covered.   */
  	  abort ();
  	}
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8392,8406 ****
    while (in_list && in_list->tag == Tag_compatibility)
      in_list = in_list->next;
  
!   for (; in_list; in_list = in_list->next)
      {
!       if ((in_list->tag & 128) < 64)
  	{
! 	  _bfd_error_handler
! 	    (_("Warning: %B: Unknown EABI object attribute %d"),
! 	     ibfd, in_list->tag);
! 	  break;
  	}
      }
    return TRUE;
  }
--- 8421,8487 ----
    while (in_list && in_list->tag == Tag_compatibility)
      in_list = in_list->next;
  
!   out_list = elf_other_obj_attributes_proc (obfd);
!   while (out_list && out_list->tag == Tag_compatibility)
!     out_list = out_list->next;
! 
!   for (; in_list != NULL; )
      {
!       if (out_list == NULL)
  	{
! 	  elf32_arm_copy_eabi_other_attribute_list (ibfd, obfd, in_list);
! 	  return TRUE;
! 	}
! 
!       /* The tags for each list are in numerical order.  */
!       /* If the tags are equal, then merge.  */
!       if (in_list->tag == out_list->tag)
!         {
! 	  switch (in_list->tag)
! 	    {
! 	    case Tag_VFP_HP_extension:
! 	      if (out_list->attr.i == 0)
! 	    	out_list->attr.i = in_list->attr.i;
! 	      break;
! 
! 	    case Tag_ABI_FP_16bit_format:
! 	      if (in_list->attr.i != 0 && out_list->attr.i != 0)
! 		{
! 	          if (in_list->attr.i != out_list->attr.i)
! 	            {
! 		      _bfd_error_handler
! 		        (_("ERROR: fp16 format mismatch between %B and %B"),
! 		         ibfd, obfd);
! 		      return FALSE;
! 	            }
! 		}
! 	      if (in_list->attr.i != 0)
! 		out_list->attr.i = in_list->attr.i;
! 	      break;
! 
! 	    default:
! 	      if ((in_list->tag & 127) < 64)
! 	        {
! 	          _bfd_error_handler
! 		    (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
! 	          break;
! 	        }
! 	    }
! 	}
!       else if (in_list->tag < out_list->tag)
! 	{
! 	  /* This attribute is in ibfd, but not obfd.  Copy to obfd and advance to
!             next input attribute.  */
! 	  elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
! 	}
!       if (in_list->tag <= out_list->tag)
! 	{
! 	  in_list = in_list->next;
! 	  if (in_list == NULL)
! 	    continue;
  	}
+       while (out_list && out_list->tag < in_list->tag)
+         out_list = out_list->next;
      }
    return TRUE;
  }
Index: src/binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.429
diff -p -r1.429 readelf.c
*** src/binutils/readelf.c	20 Oct 2008 12:40:58 -0000	1.429
--- src/binutils/readelf.c	14 Nov 2008 17:07:01 -0000
*************** static const char *arm_attr_tag_ABI_opti
*** 8784,8789 ****
--- 8784,8793 ----
  static const char *arm_attr_tag_ABI_FP_optimization_goals[] =
    {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
      "Aggressive Size", "Prefer Accuracy", "Aggressive Accuracy"};
+ static const char *arm_attr_tag_VFP_HP_extension[] =
+   {"Not Allowed", "Allowed"};
+ static const char *arm_attr_tag_ABI_FP_16bit_format[] =
+   {"None", "IEEE 754", "Alternative Format"};
  
  #define LOOKUP(id, name) \
    {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
*************** static arm_attr_public_tag arm_attr_publ
*** 8817,8823 ****
    LOOKUP(29, ABI_WMMX_args),
    LOOKUP(30, ABI_optimization_goals),
    LOOKUP(31, ABI_FP_optimization_goals),
!   {32, "compatibility", 0, NULL}
  };
  #undef LOOKUP
  
--- 8821,8829 ----
    LOOKUP(29, ABI_WMMX_args),
    LOOKUP(30, ABI_optimization_goals),
    LOOKUP(31, ABI_FP_optimization_goals),
!   {32, "compatibility", 0, NULL},
!   LOOKUP(36, VFP_HP_extension),
!   LOOKUP(38, ABI_FP_16bit_format),
  };
  #undef LOOKUP
  
Index: src/gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.361
diff -p -r1.361 tc-arm.c
*** src/gas/config/tc-arm.c	12 Aug 2008 23:39:30 -0000	1.361
--- src/gas/config/tc-arm.c	14 Nov 2008 17:07:01 -0000
*************** static const arm_feature_set fpu_vfp_ext
*** 226,231 ****
--- 226,232 ----
  static const arm_feature_set fpu_neon_ext_v1 = ARM_FEATURE (0, FPU_NEON_EXT_V1);
  static const arm_feature_set fpu_vfp_v3_or_neon_ext =
    ARM_FEATURE (0, FPU_NEON_EXT_V1 | FPU_VFP_EXT_V3);
+ static const arm_feature_set fpu_neon_fp16 = ARM_FEATURE (0, FPU_NEON_FP16);
  
  static int mfloat_abi_opt = -1;
  /* Record user cpu selection for object attributes.  */
*************** static struct neon_shape_info neon_shape
*** 10682,10717 ****
  
  enum neon_type_mask
  {
!   N_S8   = 0x000001,
!   N_S16  = 0x000002,
!   N_S32  = 0x000004,
!   N_S64  = 0x000008,
!   N_U8   = 0x000010,
!   N_U16  = 0x000020,
!   N_U32  = 0x000040,
!   N_U64  = 0x000080,
!   N_I8   = 0x000100,
!   N_I16  = 0x000200,
!   N_I32  = 0x000400,
!   N_I64  = 0x000800,
!   N_8    = 0x001000,
!   N_16   = 0x002000,
!   N_32   = 0x004000,
!   N_64   = 0x008000,
!   N_P8   = 0x010000,
!   N_P16  = 0x020000,
!   N_F32  = 0x040000,
!   N_F64  = 0x080000,
!   N_KEY  = 0x100000, /* key element (main type specifier).  */
!   N_EQK  = 0x200000, /* given operand has the same type & size as the key.  */
!   N_VFP  = 0x400000, /* VFP mode: operand size must match register width.  */
!   N_DBL  = 0x000001, /* if N_EQK, this operand is twice the size.  */
!   N_HLF  = 0x000002, /* if N_EQK, this operand is half the size.  */
!   N_SGN  = 0x000004, /* if N_EQK, this operand is forced to be signed.  */
!   N_UNS  = 0x000008, /* if N_EQK, this operand is forced to be unsigned.  */
!   N_INT  = 0x000010, /* if N_EQK, this operand is forced to be integer.  */
!   N_FLT  = 0x000020, /* if N_EQK, this operand is forced to be float.  */
!   N_SIZ  = 0x000040, /* if N_EQK, this operand is forced to be size-only.  */
    N_UTYP = 0,
    N_MAX_NONSPECIAL = N_F64
  };
--- 10683,10719 ----
  
  enum neon_type_mask
  {
!   N_S8   = 0x0000001,
!   N_S16  = 0x0000002,
!   N_S32  = 0x0000004,
!   N_S64  = 0x0000008,
!   N_U8   = 0x0000010,
!   N_U16  = 0x0000020,
!   N_U32  = 0x0000040,
!   N_U64  = 0x0000080,
!   N_I8   = 0x0000100,
!   N_I16  = 0x0000200,
!   N_I32  = 0x0000400,
!   N_I64  = 0x0000800,
!   N_8    = 0x0001000,
!   N_16   = 0x0002000,
!   N_32   = 0x0004000,
!   N_64   = 0x0008000,
!   N_P8   = 0x0010000,
!   N_P16  = 0x0020000,
!   N_F16  = 0x0040000,
!   N_F32  = 0x0080000,
!   N_F64  = 0x0100000,
!   N_KEY  = 0x1000000, /* key element (main type specifier).  */
!   N_EQK  = 0x2000000, /* given operand has the same type & size as the key.  */
!   N_VFP  = 0x4000000, /* VFP mode: operand size must match register width.  */
!   N_DBL  = 0x0000001, /* if N_EQK, this operand is twice the size.  */
!   N_HLF  = 0x0000002, /* if N_EQK, this operand is half the size.  */
!   N_SGN  = 0x0000004, /* if N_EQK, this operand is forced to be signed.  */
!   N_UNS  = 0x0000008, /* if N_EQK, this operand is forced to be unsigned.  */
!   N_INT  = 0x0000010, /* if N_EQK, this operand is forced to be integer.  */
!   N_FLT  = 0x0000020, /* if N_EQK, this operand is forced to be float.  */
!   N_SIZ  = 0x0000040, /* if N_EQK, this operand is forced to be size-only.  */
    N_UTYP = 0,
    N_MAX_NONSPECIAL = N_F64
  };
*************** type_chk_of_el_type (enum neon_el_type t
*** 10905,10910 ****
--- 10907,10913 ----
      case NT_float:
        switch (size)
          {
+ 	case 16: return N_F16;
          case 32: return N_F32;
          case 64: return N_F64;
          default: ;
*************** neon_cvt_flavour (enum neon_shape rs)
*** 12598,12622 ****
    CVT_VAR (1, N_U32, N_F32);
    CVT_VAR (2, N_F32, N_S32);
    CVT_VAR (3, N_F32, N_U32);
  
    whole_reg = N_VFP;
  
    /* VFP instructions.  */
!   CVT_VAR (4, N_F32, N_F64);
!   CVT_VAR (5, N_F64, N_F32);
!   CVT_VAR (6, N_S32, N_F64 | key);
!   CVT_VAR (7, N_U32, N_F64 | key);
!   CVT_VAR (8, N_F64 | key, N_S32);
!   CVT_VAR (9, N_F64 | key, N_U32);
    /* VFP instructions with bitshift.  */
!   CVT_VAR (10, N_F32 | key, N_S16);
!   CVT_VAR (11, N_F32 | key, N_U16);
!   CVT_VAR (12, N_F64 | key, N_S16);
!   CVT_VAR (13, N_F64 | key, N_U16);
!   CVT_VAR (14, N_S16, N_F32 | key);
!   CVT_VAR (15, N_U16, N_F32 | key);
!   CVT_VAR (16, N_S16, N_F64 | key);
!   CVT_VAR (17, N_U16, N_F64 | key);
  
    return -1;
  #undef CVT_VAR
--- 12601,12628 ----
    CVT_VAR (1, N_U32, N_F32);
    CVT_VAR (2, N_F32, N_S32);
    CVT_VAR (3, N_F32, N_U32);
+   /* Half-precision conversions.  */
+   CVT_VAR (4, N_F32, N_F16);
+   CVT_VAR (5, N_F16, N_F32);
  
    whole_reg = N_VFP;
  
    /* VFP instructions.  */
!   CVT_VAR (6, N_F32, N_F64);
!   CVT_VAR (7, N_F64, N_F32);
!   CVT_VAR (8, N_S32, N_F64 | key);
!   CVT_VAR (9, N_U32, N_F64 | key);
!   CVT_VAR (10, N_F64 | key, N_S32);
!   CVT_VAR (11, N_F64 | key, N_U32);
    /* VFP instructions with bitshift.  */
!   CVT_VAR (12, N_F32 | key, N_S16);
!   CVT_VAR (13, N_F32 | key, N_U16);
!   CVT_VAR (14, N_F64 | key, N_S16);
!   CVT_VAR (15, N_F64 | key, N_U16);
!   CVT_VAR (16, N_S16, N_F32 | key);
!   CVT_VAR (17, N_U16, N_F32 | key);
!   CVT_VAR (18, N_S16, N_F64 | key);
!   CVT_VAR (19, N_U16, N_F64 | key);
  
    return -1;
  #undef CVT_VAR
*************** do_vfp_nsyn_cvt (enum neon_shape rs, int
*** 12640,12645 ****
--- 12646,12653 ----
            "fultos",
            NULL,
            NULL,
+ 	  NULL,
+ 	  NULL,
            "ftosld",
            "ftould",
            "fsltod",
*************** do_vfp_nsyn_cvt (enum neon_shape rs, int
*** 12672,12677 ****
--- 12680,12687 ----
            "ftouis",
            "fsitos",
            "fuitos",
+ 	  "NULL",
+ 	  "NULL",
            "fcvtsd",
            "fcvtds",
            "ftosid",
*************** do_vfp_nsyn_cvtz (void)
*** 12701,12706 ****
--- 12711,12718 ----
        NULL,
        NULL,
        NULL,
+       NULL,
+       NULL,
        "ftosizd",
        "ftouizd"
      };
*************** do_vfp_nsyn_cvtz (void)
*** 12708,12723 ****
    if (flavour >= 0 && flavour < (int) ARRAY_SIZE (enc) && enc[flavour])
      do_vfp_nsyn_opcode (enc[flavour]);
  }
- 
  static void
  do_neon_cvt (void)
  {
    enum neon_shape rs = neon_select_shape (NS_DDI, NS_QQI, NS_FFI, NS_DD, NS_QQ,
!     NS_FD, NS_DF, NS_FF, NS_NULL);
    int flavour = neon_cvt_flavour (rs);
  
    /* VFP rather than Neon conversions.  */
!   if (flavour >= 4)
      {
        do_vfp_nsyn_cvt (rs, flavour);
        return;
--- 12720,12734 ----
    if (flavour >= 0 && flavour < (int) ARRAY_SIZE (enc) && enc[flavour])
      do_vfp_nsyn_opcode (enc[flavour]);
  }
  static void
  do_neon_cvt (void)
  {
    enum neon_shape rs = neon_select_shape (NS_DDI, NS_QQI, NS_FFI, NS_DD, NS_QQ,
!     NS_FD, NS_DF, NS_FF, NS_QD, NS_DQ, NS_NULL);
    int flavour = neon_cvt_flavour (rs);
  
    /* VFP rather than Neon conversions.  */
!   if (flavour >= 6)
      {
        do_vfp_nsyn_cvt (rs, flavour);
        return;
*************** do_neon_cvt (void)
*** 12779,12784 ****
--- 12790,12825 ----
        }
      break;
  
+     /* Half-precision conversions for Advanced SIMD -- neon.  */
+     case NS_QD:
+     case NS_DQ:
+ 
+       if ((rs == NS_DQ)
+ 	  && (inst.vectype.el[0].size != 16 || inst.vectype.el[1].size != 32))
+ 	  {
+ 	    as_bad (_("operand size must match register width"));
+ 	    break;
+ 	  }
+ 
+       if ((rs == NS_QD)
+ 	  && ((inst.vectype.el[0].size != 32 || inst.vectype.el[1].size != 16)))
+ 	  {
+ 	    as_bad (_("operand size must match register width"));
+ 	    break;
+ 	  }
+ 
+       if (rs == NS_DQ)
+         inst.instruction = 0x3b60600;
+       else
+ 	inst.instruction = 0x3b60700;
+ 
+       inst.instruction |= LOW4 (inst.operands[0].reg) << 12;
+       inst.instruction |= HI1 (inst.operands[0].reg) << 22;
+       inst.instruction |= LOW4 (inst.operands[1].reg);
+       inst.instruction |= HI1 (inst.operands[1].reg) << 5;
+       inst.instruction = neon_dp_fixup (inst.instruction);
+       break;
+ 
      default:
        /* Some VFP conversions go here (s32 <-> f32, u32 <-> f32).  */
        do_vfp_nsyn_cvt (rs, flavour);
*************** do_neon_cvt (void)
*** 12786,12791 ****
--- 12827,12860 ----
  }
  
  static void
+ do_neon_cvtb (void)
+ {
+   inst.instruction = 0xeb20a40;
+ 
+   /* The sizes are attached to the mnemonic.  */
+   if (inst.vectype.el[0].type != NT_invtype
+       && inst.vectype.el[0].size == 16)
+     inst.instruction |= 0x00010000;
+ 
+   /* Programmer's syntax: the sizes are attached to the operands.  */
+   else if (inst.operands[0].vectype.type != NT_invtype
+ 	   && inst.operands[0].vectype.size == 16)
+     inst.instruction |= 0x00010000;
+ 
+   encode_arm_vfp_reg (inst.operands[0].reg, VFP_REG_Sd);
+   encode_arm_vfp_reg (inst.operands[1].reg, VFP_REG_Sm);
+   do_vfp_cond_or_thumb ();
+ }
+ 
+ 
+ static void
+ do_neon_cvtt (void)
+ {
+   do_neon_cvtb ();
+   inst.instruction |= 0x80;
+ }
+ 
+ static void
  neon_move_immediate (void)
  {
    enum neon_shape rs = neon_select_shape (NS_DI, NS_QI, NS_NULL);
*************** static const struct asm_opcode insns[] =
*** 15950,15955 ****
--- 16019,16027 ----
   NCE(vstr,      d000b00, 2, (RVSD, ADDRGLDC), neon_ldr_str),
  
   nCEF(vcvt,     vcvt,    3, (RNSDQ, RNSDQ, oI32b), neon_cvt),
+  nCEF(vcvtb,	vcvt,	 2, (RVS, RVS), neon_cvtb),
+  nCEF(vcvtt,	vcvt,	 2, (RVS, RVS), neon_cvtt),
+  
  
    /* NOTE: All VMOV encoding is special-cased!  */
   NCE(vmov,      0,       1, (VMOV), neon_mov),
*************** static const struct arm_option_cpu_value
*** 20258,20263 ****
--- 20330,20336 ----
    {"arm1136jf-s",	FPU_ARCH_VFP_V2},
    {"maverick",		FPU_ARCH_MAVERICK},
    {"neon",              FPU_ARCH_VFP_V3_PLUS_NEON_V1},
+   {"neon-fp16",		FPU_ARCH_NEON_FP16},
    {NULL,		ARM_ARCH_NONE}
  };
  
*************** aeabi_set_public_attributes (void)
*** 20731,20739 ****
        || ARM_CPU_HAS_FEATURE (arm_arch_used, arm_cext_iwmmxt))
      bfd_elf_add_proc_attr_int (stdoutput, 11, 1);
    /* Tag_NEON_arch.  */
!   if (ARM_CPU_HAS_FEATURE (thumb_arch_used, fpu_neon_ext_v1)
!       || ARM_CPU_HAS_FEATURE (arm_arch_used, fpu_neon_ext_v1))
      bfd_elf_add_proc_attr_int (stdoutput, 12, 1);
  }
  
  /* Add the default contents for the .ARM.attributes section.  */
--- 20804,20814 ----
        || ARM_CPU_HAS_FEATURE (arm_arch_used, arm_cext_iwmmxt))
      bfd_elf_add_proc_attr_int (stdoutput, 11, 1);
    /* Tag_NEON_arch.  */
!   if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_ext_v1))
      bfd_elf_add_proc_attr_int (stdoutput, 12, 1);
+   /* Tag_NEON_FP16_arch.  */
+   if (ARM_CPU_HAS_FEATURE (flags, fpu_neon_fp16))
+     bfd_elf_add_proc_attr_int (stdoutput, 36, 1);
  }
  
  /* Add the default contents for the .ARM.attributes section.  */
Index: src/include/elf/arm.h
===================================================================
RCS file: /cvs/src/src/include/elf/arm.h,v
retrieving revision 1.33
diff -p -r1.33 arm.h
*** src/include/elf/arm.h	21 May 2008 14:50:07 -0000	1.33
--- src/include/elf/arm.h	14 Nov 2008 17:07:03 -0000
*************** enum
*** 272,277 ****
--- 272,283 ----
    Tag_ABI_optimization_goals,
    Tag_ABI_FP_optimization_goals,
    /* 32 is generic.  */
+   Tag_undefined33 = 33,
+   Tag_CPU_unaligned_access,
+   Tag_undefined35, 
+   Tag_VFP_HP_extension,
+   Tag_undefined37,
+   Tag_ABI_FP_16bit_format = 38,
  };
  
  #endif
Index: src/include/opcode/arm.h
===================================================================
RCS file: /cvs/src/src/include/opcode/arm.h,v
retrieving revision 1.13
diff -p -r1.13 arm.h
*** src/include/opcode/arm.h	9 Mar 2008 13:23:29 -0000	1.13
--- src/include/opcode/arm.h	14 Nov 2008 17:07:03 -0000
***************
*** 65,70 ****
--- 65,71 ----
  #define FPU_VFP_EXT_V3	 0x01000000	/* VFPv3 insns.	              */
  #define FPU_NEON_EXT_V1	 0x00800000	/* Neon (SIMD) insns.	      */
  #define FPU_VFP_EXT_D32  0x00400000	/* Registers D16-D31.	      */
+ #define FPU_NEON_FP16	 0x00200000	/* Half-precision extensions. */
  
  /* Architectures are the sum of the base and extensions.  The ARM ARM (rev E)
     defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
***************
*** 139,144 ****
--- 140,147 ----
  #define FPU_ARCH_NEON_V1  ARM_FEATURE (0, FPU_NEON_EXT_V1)
  #define FPU_ARCH_VFP_V3_PLUS_NEON_V1 \
    ARM_FEATURE (0, FPU_VFP_V3 | FPU_NEON_EXT_V1)
+ #define FPU_ARCH_NEON_FP16 \
+   ARM_FEATURE (0, FPU_VFP_V3 | FPU_NEON_EXT_V1 | FPU_NEON_FP16)
  #define FPU_ARCH_VFP_HARD ARM_FEATURE (0, FPU_VFP_HARD)
  
  #define FPU_ARCH_ENDIAN_PURE ARM_FEATURE (0, FPU_ENDIAN_PURE)
Index: src/opcodes/arm-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/arm-dis.c,v
retrieving revision 1.89
diff -p -r1.89 arm-dis.c
*** src/opcodes/arm-dis.c	7 Jul 2008 18:35:24 -0000	1.89
--- src/opcodes/arm-dis.c	14 Nov 2008 17:07:04 -0000
*************** static const struct opcode32 coprocessor
*** 264,269 ****
--- 264,272 ----
    {FPU_NEON_EXT_V1, 0x0e100b30, 0x0f500f30, "vmov%c.%23?us16\t%12-15r, %16-19,7D[%6,21d]"},
    {FPU_NEON_EXT_V1, 0x0e400b10, 0x0fd00f10, "vmov%c.8\t%16-19,7D[%5,6,21d], %12-15r"},
    {FPU_NEON_EXT_V1, 0x0e500b10, 0x0f500f10, "vmov%c.%23?us8\t%12-15r, %16-19,7D[%5,6,21d]"},
+   /* Half-precision conversion instructions.  */
+   {FPU_NEON_FP16,   0x0eb20a40, 0x0fbf0f50, "vcvt%7?tb%c.f32.f16\t%y1, %y0"},
+   {FPU_NEON_FP16,   0x0eb30a40, 0x0fbf0f50, "vcvt%7?tb%c.f16.f32\t%y1, %y0"},
  
    /* Floating point coprocessor (VFP) instructions */
    {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"},
*************** static const struct opcode32 neon_opcode
*** 504,509 ****
--- 507,516 ----
    {FPU_NEON_EXT_V1, 0xf3b00800, 0xffb00c50, "vtbl%c.8\t%12-15,22D, %F, %0-3,5D"},
    {FPU_NEON_EXT_V1, 0xf3b00840, 0xffb00c50, "vtbx%c.8\t%12-15,22D, %F, %0-3,5D"},
    
+   /* Half-precision conversions.  */
+   {FPU_NEON_FP16,   0xf3b60600, 0xffbf0fd0, "vcvt%c.f16.f32\t%12-15,22D, %0-3,5Q"},
+   {FPU_NEON_FP16,   0xf3b60700, 0xffbf0fd0, "vcvt%c.f32.f16\t%12-15,22Q, %0-3,5D"},
+ 
    /* Two registers, miscellaneous */
    {FPU_NEON_EXT_V1, 0xf2880a10, 0xfebf0fd0, "vmovl%c.%24?us8\t%12-15,22Q, %0-3,5D"},
    {FPU_NEON_EXT_V1, 0xf2900a10, 0xfebf0fd0, "vmovl%c.%24?us16\t%12-15,22Q, %0-3,5D"},

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]