* config/tc-m68hc11.c (m68hc11_elf_final_processing): New function.
authorStephane Carrez <stcarrez@nerim.fr>
Tue, 13 Aug 2002 21:52:57 +0000 (21:52 +0000)
committerStephane Carrez <stcarrez@nerim.fr>
Tue, 13 Aug 2002 21:52:57 +0000 (21:52 +0000)
(md_pseudo_table): Add .mode, .far and .interrupt pseudo op.
(s_m68hc11_mode): New function for .mode pseudo op.
(s_m68hc11_mark_symbol): New function for .far and .interrupt
pseudo op.
* config/tc-m68hc11.h (elf_tc_final_processing): Define.
(m68hc11_elf_final_processing): Declare.

gas/ChangeLog
gas/config/tc-m68hc11.c
gas/config/tc-m68hc11.h

index a8455bedd8464fccaa54d89f14c4770fced5a2d0..3d08c0bce046fb0b8d20cab8a4d2e6d02636143a 100644 (file)
@@ -1,3 +1,13 @@
+2002-08-13  Stephane Carrez  <stcarrez@nerim.fr>
+
+       * config/tc-m68hc11.c (m68hc11_elf_final_processing): New function.
+       (md_pseudo_table): Add .mode, .far and .interrupt pseudo op.
+       (s_m68hc11_mode): New function for .mode pseudo op.
+       (s_m68hc11_mark_symbol): New function for .far and .interrupt
+       pseudo op.
+       * config/tc-m68hc11.h (elf_tc_final_processing): Define.
+       (m68hc11_elf_final_processing): Declare.
+
 2002-08-13  Stephane Carrez  <stcarrez@nerim.fr>
 
        * config/tc-m68hc11.c (md_begin): Take into account additional
index e50e72871f4b143cc80a3c558d36fc282e2198ca..d5707845089da51bb7d104ddbb638b4d9ce1bf1b 100644 (file)
@@ -182,6 +182,15 @@ static void build_insn
   PARAMS ((struct m68hc11_opcode *, operand *, int));
 static int relaxable_symbol PARAMS ((symbolS *));
 
+/* Pseudo op to control the ELF flags.  */
+static void s_m68hc11_mode PARAMS ((int));
+
+/* Mark the symbols with STO_M68HC12_FAR to indicate the functions
+   are using 'rtc' for returning.  It is necessary to use 'call'
+   to invoke them.  This is also used by the debugger to correctly
+   find the stack frame.  */
+static void s_m68hc11_mark_symbol PARAMS ((int));
+
 /* Controls whether relative branches can be turned into long branches.
    When the relative offset is too large, the insn are changed:
     bra -> jmp
@@ -229,6 +238,9 @@ static int num_opcodes;
 /* The opcodes sorted by name and filtered by current cpu.  */
 static struct m68hc11_opcode *m68hc11_sorted_opcodes;
 
+/* ELF flags to set in the output file header.  */
+static int elf_flags = 0;
+
 /* These are the machine dependent pseudo-ops.  These are included so
    the assembler can work on the output from the SUN C compiler, which
    generates these.  */
@@ -252,6 +264,15 @@ const pseudo_typeS md_pseudo_table[] = {
   /* Motorola ALIS.  */
   {"xrefb", s_ignore, 0}, /* Same as xref  */
 
+  /* .mode instruction (ala SH).  */
+  {"mode", s_m68hc11_mode, 0},
+
+  /* .far instruction.  */
+  {"far", s_m68hc11_mark_symbol, STO_M68HC12_FAR},
+
+  /* .interrupt instruction.  */
+  {"interrupt", s_m68hc11_mark_symbol, STO_M68HC12_INTERRUPT},
+
   {0, 0, 0}
 };
 \f
@@ -2488,6 +2509,89 @@ md_assemble (str)
   else
     build_insn (opcode, operands, nb_operands);
 }
+
+\f
+/* Pseudo op to control the ELF flags.  */
+static void
+s_m68hc11_mode (x)
+     int x ATTRIBUTE_UNUSED;
+{
+  char *name = input_line_pointer, ch;
+
+  while (!is_end_of_line[(unsigned char) *input_line_pointer])
+    input_line_pointer++;
+  ch = *input_line_pointer;
+  *input_line_pointer = '\0';
+
+  if (strcmp (name, "mshort") == 0)
+    {
+      elf_flags &= ~E_M68HC11_I32;
+    }
+  else if (strcmp (name, "mlong") == 0)
+    {
+      elf_flags |= E_M68HC11_I32;
+    }
+  else if (strcmp (name, "mshort-double") == 0)
+    {
+      elf_flags &= ~E_M68HC11_F64;
+    }
+  else if (strcmp (name, "mlong-double") == 0)
+    {
+      elf_flags |= E_M68HC11_F64;
+    }
+  else
+    {
+      as_warn (_("Invalid mode: %s\n"), name);
+    }
+  *input_line_pointer = ch;
+  demand_empty_rest_of_line ();
+}
+
+/* Mark the symbols with STO_M68HC12_FAR to indicate the functions
+   are using 'rtc' for returning.  It is necessary to use 'call'
+   to invoke them.  This is also used by the debugger to correctly
+   find the stack frame.  */
+static void
+s_m68hc11_mark_symbol (mark)
+     int mark;
+{
+  char *name;
+  int c;
+  symbolS *symbolP;
+  asymbol *bfdsym;
+  elf_symbol_type *elfsym;
+
+  do
+    {
+      name = input_line_pointer;
+      c = get_symbol_end ();
+      symbolP = symbol_find_or_make (name);
+      *input_line_pointer = c;
+
+      SKIP_WHITESPACE ();
+
+      bfdsym = symbol_get_bfdsym (symbolP);
+      elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
+
+      assert (elfsym);
+
+      /* Mark the symbol far (using rtc for function return).  */
+      elfsym->internal_elf_sym.st_other |= mark;
+
+      if (c == ',')
+       {
+         input_line_pointer ++;
+
+         SKIP_WHITESPACE ();
+
+         if (*input_line_pointer == '\n')
+           c = '\n';
+       }
+    }
+  while (c == ',');
+
+  demand_empty_rest_of_line ();
+}
 \f
 /* Relocation, relaxation and frag conversions.  */
 long
@@ -2938,3 +3042,11 @@ md_apply_fix3 (fixP, valP, seg)
                fixP->fx_line, fixP->fx_r_type);
     }
 }
+
+/* Set the ELF specific flags.  */
+void
+m68hc11_elf_final_processing ()
+{
+  elf_elfheader (stdoutput)->e_flags &= ~EF_M68HC11_ABI;
+  elf_elfheader (stdoutput)->e_flags |= elf_flags;
+}
index 08cae5114120917ba7082f1dc5dcddfd7a15f8c0..418b7b5afda4ce0804fc596aa3ecffae8499e7e0 100644 (file)
@@ -104,5 +104,8 @@ extern struct relax_type md_relax_table[];
   S_SET_VALUE (sym, (valueT) frag_now_fix ()); \
 } while (0)
 
+#define elf_tc_final_processing        m68hc11_elf_final_processing
+extern void m68hc11_elf_final_processing PARAMS ((void));
+
 #define tc_print_statistics(FILE) m68hc11_print_statistics (FILE)
 extern void m68hc11_print_statistics PARAMS ((FILE *));