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]

Re: how to embed an arbitrary opcode


Hi Richard,

Yay! Something I've wanted for a long time...

:-)


One question.  What happens if .iword is used in Thumb mode, or .ishort
in ARM mode?

Well the new pseudos explicitly set the mapping state based on their size, so for example if .iword were used in Thumb mode it would cause a $a symbol to be emitted at point. Ie:


  % cat fred.s
        .text
        .global foo
  foo:
        nop
        .iword  0xe320f003
        nop
        .ishort 0x1234
        nop

        .thumb
        .global bar
  bar:
        nop
        .ishort 0x1234
        nop
        .iword 0xe320f003
        nop

  % as fred.s -o fred.o
  % objdump -d fred.o
  00000000 <foo>:
   0:   e1a00000        nop                     (mov r0,r0)
   4:   e320f003        wfi
   8:   e1a00000        nop                     (mov r0,r0)
   c:   1234            asrs    r4, r6, #8
   e:   e1a00000        nop                     (mov r0,r0)

  00000012 <bar>:
  12:   46c0            nop                     (mov r8, r8)
  14:   1234            asrs    r4, r6, #8
  16:   46c0            nop                     (mov r8, r8)
  18:   e320f003        wfi
  1c:   46c0            nop                     (mov r8, r8)


I think it would be better to just have .insn (or .inst),
which takes 32-bit numbers in ARM state and 16-bit numbers in thumb.
The assembler has to know what state it's in anyway in order to generate
the correct mapping symbol information.

I suspect that users are going to want to be able to use this mechanism to insert arbitrary ARM or THUMB opcodes at arbitrary places without regard to whether the assembler is currently in arm mode or thumb mode.


It would be quite easy to extend the patch however to add a third pseudo op (.inst is fine by me) which chooses it size based on the current mode. So attached is an improved version of the patch which does just that. Let me know what you think and if everyone likes it I will check it in. (Along with a testcase based on the fred.s file above).

Cheers
  Nick

Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.387
diff -c -3 -p -r1.387 tc-arm.c
*** gas/config/tc-arm.c	18 Jun 2009 16:36:02 -0000	1.387
--- gas/config/tc-arm.c	19 Jun 2009 14:15:35 -0000
*************** static void add_unwind_opcode (valueT, i
*** 2951,2979 ****
  static void flush_pending_unwind (void);
  
  /* Directives: Data.  */
- 
  static void
! s_arm_elf_cons (int nbytes)
  {
-   expressionS exp;
- 
- #ifdef md_flush_pending_output
-   md_flush_pending_output ();
- #endif
- 
-   if (is_it_end_of_statement ())
-     {
-       demand_empty_rest_of_line ();
-       return;
-     }
- 
- #ifdef md_cons_align
-   md_cons_align (nbytes);
- #endif
- 
-   mapping_state (MAP_DATA);
    do
      {
        int reloc;
        char *base = input_line_pointer;
  
--- 2951,2962 ----
  static void flush_pending_unwind (void);
  
  /* Directives: Data.  */
  static void
! arm_elf_cons_worker (int nbytes)
  {
    do
      {
+       expressionS exp;
        int reloc;
        char *base = input_line_pointer;
  
*************** s_arm_elf_cons (int nbytes)
*** 2984,2989 ****
--- 2967,2973 ----
        else
  	{
  	  char *before_reloc = input_line_pointer;
+ 
  	  reloc = parse_reloc (&input_line_pointer);
  	  if (reloc == -1)
  	    {
*************** s_arm_elf_cons (int nbytes)
*** 3017,3022 ****
--- 3001,3007 ----
  		  char *p = input_line_pointer;
  		  int offset;
  		  char *save_buf = alloca (input_line_pointer - base);
+ 
  		  memcpy (save_buf, base, input_line_pointer - base);
  		  memmove (base + (input_line_pointer - before_reloc),
  			   base, before_reloc - base);
*************** s_arm_elf_cons (int nbytes)
*** 3040,3045 ****
--- 3025,3064 ----
    demand_empty_rest_of_line ();
  }
  
+ static void
+ s_arm_elf_cons (int nbytes)
+ {
+   if (is_it_end_of_statement ())
+     {
+       demand_empty_rest_of_line ();
+       return;
+     }
+ 
+   md_cons_align (nbytes); /* Sets mapping state to MAPPING_DATA.  */
+ 
+   arm_elf_cons_worker (nbytes);
+ }
+ 
+ /* Like s_arm_elf_cons but do not use md_cons_align and
+    set the mapping state to MAP_ARM (if nbytes == 4) or
+    MAP_THUMB (if nbytes == 2) or neither (if nbytes == 0).  */
+ 
+ static void
+ s_arm_elf_iword (int nbytes)
+ {
+   if (is_it_end_of_statement ())
+     {
+       demand_empty_rest_of_line ();
+       return;
+     }
+ 
+   if (nbytes)
+     mapping_state (nbytes == 4 ? MAP_ARM : MAP_THUMB);
+   else
+     nbytes = mapstate == MAP_ARM ? 4 : 2;
+ 
+   arm_elf_cons_worker (nbytes);
+ }
  
  /* Parse a .rel31 directive.  */
  
*************** const pseudo_typeS md_pseudo_table[] =
*** 3958,3966 ****
    { "object_arch", s_arm_object_arch,	0 },
    { "fpu",	   s_arm_fpu,	  0 },
  #ifdef OBJ_ELF
!   { "word",	   s_arm_elf_cons, 4 },
!   { "long",	   s_arm_elf_cons, 4 },
!   { "rel31",	   s_arm_rel31,	  0 },
    { "fnstart",		s_arm_unwind_fnstart,	0 },
    { "fnend",		s_arm_unwind_fnend,	0 },
    { "cantunwind",	s_arm_unwind_cantunwind, 0 },
--- 3977,3988 ----
    { "object_arch", s_arm_object_arch,	0 },
    { "fpu",	   s_arm_fpu,	  0 },
  #ifdef OBJ_ELF
!   { "word",	        s_arm_elf_cons, 4 },
!   { "long",	        s_arm_elf_cons, 4 },
!   { "inst",             s_arm_elf_iword, 0 },
!   { "ishort",           s_arm_elf_iword, 2 },  
!   { "iword",            s_arm_elf_iword, 4 },
!   { "rel31",	        s_arm_rel31,	  0 },
    { "fnstart",		s_arm_unwind_fnstart,	0 },
    { "fnend",		s_arm_unwind_fnend,	0 },
    { "cantunwind",	s_arm_unwind_cantunwind, 0 },
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.56
diff -c -3 -p -r1.56 c-arm.texi
*** gas/doc/c-arm.texi	2 Apr 2009 09:43:56 -0000	1.56
--- gas/doc/c-arm.texi	19 Jun 2009 14:15:35 -0000
*************** Must be preceded by a @code{.personality
*** 564,569 ****
--- 564,595 ----
  directive.
  
  @c IIIIIIIIIIIIIIIIIIIIIIIIII
+ 
+ @cindex @code{.inst} directive, ARM
+ @item .inst @var{expression} [, @var{expression}]*
+ Inserts one or more comma separated expressions into the output stream
+ without changing the mapping state (@pxref{ARM Mapping Symbols}).  The
+ size of the values inserted depends upon whether the assembler is
+ currently in ARM mode (32-bit values are inserted) or Thumb mode
+ (16-bit values are inserted) as set by the @var{.code} directive.  
+ This directive is only supported in ELF based ARM toolchains.
+ 
+ @cindex @code{.ishort} directive, ARM
+ @item .ishort @var{expression} [, @var{expression}]*
+ Inserts one or more comma separated expressions into the output stream
+ as 16-bit values and marks them as being THUMB instructions.  This
+ directive is only supported in ELF based ARM toolchains.  Note: the
+ generic GAS directive @code{.short} does the same thing, but it marks
+ the values as being data not instructions.
+ 
+ @cindex @code{.iword} directive, ARM
+ @item .iword @var{expression} [, @var{expression}]*
+ Inserts one or more comma separated expressions into the output stream
+ as 32-bit values and marks them as being ARM instructions.  This
+ directive is only supported in ELF based ARM toolchains.  Note: the
+ generic GAS directive @code{.word} does the same thing, but it marks
+ the values as being data not instructions.
+ 
  @c JJJJJJJJJJJJJJJJJJJJJJJJJJ
  @c KKKKKKKKKKKKKKKKKKKKKKKKKK
  @c LLLLLLLLLLLLLLLLLLLLLLLLLL

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