This is the mail archive of the binutils@sources.redhat.com 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]

ARM: Add support for aligning with no-ops in code section.


Hi Guys,

  I am applying the following patch to the ARM port of GAS to allow
  the .p2align directive to pad code with no-op instructions.

  Since the no-op instruction is different for the ARM and the THUMB,
  the code has to mark frags with the type of the code region in which 
  they were created.  The patch uses the tc_frag_data field to do
  this.

Cheers
        Nick

2001-04-26  Nick Clifton  <nickc@cambridge.redhat.com>

	* config/tc-arm.c (arm_handle_align): New Function:  Generate
	no-op filled alignment frags.
	(arm_frag_align_code): New Function: Create a code alignment frag.
	(arm_init_frag): New Function: Initialise the target dependent
	parts of a frag.

	* config/tc-arm.h (TC_FRAG_TYPE): Define.
	(TC_FRAG_INIT): Define.
	(HANDLE_ALIGN): Define.
	(md_do_align): Define.

Index: gas/config/tc-arm.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/config/tc-arm.h,v
retrieving revision 1.40.96.1
diff -p -r1.40.96.1 tc-arm.h
*** tc-arm.h	2000/10/20 22:07:08	1.40.96.1
--- tc-arm.h	2001/04/26 14:09:52
*************** void armelf_frob_symbol PARAMS ((symbolS
*** 212,216 ****
  #else
  #define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
  #endif
!      
  /* end of tc-arm.h */
--- 212,233 ----
  #else
  #define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_"
  #endif
! 
! /* For frags in code sections we need to record whether they contain
!    ARM code or THUMB code.  This is that if they have to be aligned,
!    they can contain the correct type of no-op instruction.  */
! #define TC_FRAG_TYPE	int
! #define TC_FRAG_INIT(fragp)	arm_init_frag (fragp)
! extern void arm_init_frag PARAMS ((struct frag *));
! 
! #define HANDLE_ALIGN(fragp) arm_handle_align (fragp)
! extern void arm_handle_align PARAMS ((struct frag *));
! 
! #define md_do_align(N, FILL, LEN, MAX, LABEL) \
!   if (FILL == NULL && (N) != 0 && ! need_pass_2 && subseg_text_p (now_seg)) \
!     { \
!       arm_frag_align_code (N, MAX); \
!       goto LABEL; \
!     }
! extern void arm_frag_align_code PARAMS ((int, int));
  /* end of tc-arm.h */
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gas/config/tc-arm.c,v
retrieving revision 1.118.2.15.2.14
diff -p -r1.118.2.15.2.14 tc-arm.c
*** tc-arm.c	2001/04/10 17:45:41	1.118.2.15.2.14
--- tc-arm.c	2001/04/26 14:10:01
*************** arm_end_of_source ()
*** 8630,8632 ****
--- 8630,8728 ----
  }
  
  #endif /* OBJ_ELF */
+ 
+ /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
+    of an rs_align_code fragment.  */
+ 
+ void
+ arm_handle_align (fragp)
+      fragS *fragp;
+ {
+   static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
+   static char const thumb_noop[2] = { 0xc0, 0x46 };
+   static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
+   static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
+ 
+   int bytes, fix, noop_size;
+   char * p;
+   const char * noop;
+   
+   if (fragp->fr_type != rs_align_code)
+     return;
+ 
+   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+   p = fragp->fr_literal + fragp->fr_fix;
+   fix = 0;
+   
+   if (fragp->tc_frag_data)
+     {
+       if (target_big_endian)
+ 	noop = thumb_bigend_noop;
+       else
+ 	noop = thumb_noop;
+       noop_size = sizeof (thumb_noop);
+     }
+   else
+     {
+       if (target_big_endian)
+ 	noop = arm_bigend_noop;
+       else
+ 	noop = arm_noop;
+       noop_size = sizeof (arm_noop);
+     }
+   
+   if (bytes & (noop_size - 1))
+     {
+       fix = bytes & (noop_size - 1);
+       memset (p, 0, fix);
+       p += fix;
+       bytes -= fix;
+     }
+ 
+   while (bytes >= noop_size)
+     {
+       memcpy (p, noop, noop_size);
+       p += noop_size;
+       bytes -= noop_size;
+       fix += noop_size;
+     }
+   
+   fragp->fr_fix += fix;
+   fragp->fr_var = noop_size;
+ }
+ 
+ /* Called from md_do_align.  Used to create an alignment
+    frag in a code section.  */
+ 
+ void
+ arm_frag_align_code (n, max)
+      int n;
+      int max;
+ {
+   char * p;
+ 
+   /* We assume that there will never be a requirment
+      to support alignments greater than 32 bytes.  */
+   if (max > 31)
+     as_fatal (_("alignments in code section > 32 not supported."));
+   
+   p = frag_var (rs_align_code,
+ 		31,
+ 		1,
+ 		(relax_substateT) max,
+ 		(symbolS *) NULL,
+ 		(offsetT) n,
+ 		(char *) NULL);
+   *p = 0;/*thumb_mode ? 0 : 0x11;*/
+ 
+ }
+ 
+ /* Perform target specific initialisation of a frag.  */
+ 
+ void
+ arm_init_frag (fragp)
+      fragS *fragp;
+ {
+   /* Record whether this frag is in an ARM or a THUMB area.  */
+   fragp->tc_frag_data = thumb_mode;
+ }
Index: gcc/config/xscale/xscale-coff.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/config/xscale/Attic/xscale-coff.h,v
retrieving revision 1.1.2.1.2.2
diff -p -r1.1.2.1.2.2 xscale-coff.h
*** xscale-coff.h	2001/04/25 19:25:31	1.1.2.1.2.2
--- xscale-coff.h	2001/04/26 14:10:01
*************** Boston, MA 02111-1307, USA.  */
*** 46,57 ****
  #define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP)		\
    if ((LOG) != 0)						\
      {								\
-       int noop = TARGET_THUMB ? 0 : arm_arch5 ? 0x11 : 0xff;	\
        if ((MAX_SKIP) == 0)					\
!         fprintf ((FILE), "\t.p2align %d,%d\n", (LOG), noop);	\
        else							\
!         fprintf ((FILE), "\t.p2align %d,%d,%d\n",		\
!                  (LOG), noop, (MAX_SKIP));			\
      }
  #endif
  
--- 46,56 ----
  #define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP)		\
    if ((LOG) != 0)						\
      {								\
        if ((MAX_SKIP) == 0)					\
!         fprintf ((FILE), "\t.p2align %d\n", (LOG));		\
        else							\
!         fprintf ((FILE), "\t.p2align %d,,%d\n",			\
!                  (LOG), (MAX_SKIP));				\
      }
  #endif
  


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