gas reloc rewrite.
[binutils-gdb.git] / gas / config / tc-h8500.c
index 94301d22a0905531c0bf0ee53977c2518cfbcdeb..002854df848e05bace079216dbd15a18773992c6 100644 (file)
@@ -1,5 +1,6 @@
 /* tc-h8500.c -- Assemble code for the Hitachi H8/500
-   Copyright (C) 1993, 94, 95, 98, 2000 Free Software Foundation.
+   Copyright 1993, 1994, 1995, 1998, 2000, 2001, 2002
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
 
-/*
-  Written By Steve Chamberlain
-  sac@cygnus.com
-  */
+/* Written By Steve Chamberlain <sac@cygnus.com>.  */
 
 #include <stdio.h>
 #include "as.h"
@@ -30,7 +28,7 @@
 #define DEFINE_TABLE
 #define ASSEMBLER_TABLE
 #include "opcodes/h8500-opc.h"
-#include <ctype.h>
+#include "safe-ctype.h"
 
 const char comment_chars[] = "!";
 const char line_separator_chars[] = ";";
@@ -88,7 +86,31 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
 #define WORD_F 32767
 #define WORD_B 32768
 
-relax_typeS md_relax_table[C (END, 0)];
+relax_typeS md_relax_table[C (END, 0)] = {
+  { 0, 0, 0, 0 },
+  { 0, 0, 0, 0 },
+  { 0, 0, 0, 0 },
+  { 0, 0, 0, 0 },
+
+  /* BRANCH */
+  { 0,      0,       0, 0 },
+  { BYTE_F, BYTE_B,  2, C (BRANCH, WORD_DISP) },
+  { WORD_F, WORD_B,  3, 0 },
+  { 0,      0,       3, 0 },
+
+  /* SCB_F */
+  { 0,      0,       0, 0 },
+  { BYTE_F, BYTE_B,  3, C (SCB_F, WORD_DISP) },
+  { WORD_F, WORD_B,  8, 0 },
+  { 0,      0,       8, 0 },
+
+  /* SCB_TST */
+  { 0,      0,       0, 0 },
+  { BYTE_F, BYTE_B,  3, C (SCB_TST, WORD_DISP) },
+  { WORD_F, WORD_B, 10, 0 },
+  { 0,      0,      10, 0 }
+
+};
 
 static struct hash_control *opcode_hash_control;       /* Opcode mnemonics */
 
@@ -103,7 +125,6 @@ md_begin ()
   h8500_opcode_info *opcode;
   char prev_buffer[100];
   int idx = 0;
-  register relax_typeS *table;
 
   opcode_hash_control = hash_new ();
   prev_buffer[0] = 0;
@@ -117,40 +138,6 @@ md_begin ()
          idx++;
        }
     }
-
-  /* Initialize the relax table.  We use a local variable to avoid
-     warnings about modifying a supposedly const data structure.  */
-  table = (relax_typeS *) md_relax_table;
-  table[C (BRANCH, BYTE_DISP)].rlx_forward = BYTE_F;
-  table[C (BRANCH, BYTE_DISP)].rlx_backward = BYTE_B;
-  table[C (BRANCH, BYTE_DISP)].rlx_length = 2;
-  table[C (BRANCH, BYTE_DISP)].rlx_more = C (BRANCH, WORD_DISP);
-
-  table[C (BRANCH, WORD_DISP)].rlx_forward = WORD_F;
-  table[C (BRANCH, WORD_DISP)].rlx_backward = WORD_B;
-  table[C (BRANCH, WORD_DISP)].rlx_length = 3;
-  table[C (BRANCH, WORD_DISP)].rlx_more = 0;
-
-  table[C (SCB_F, BYTE_DISP)].rlx_forward = BYTE_F;
-  table[C (SCB_F, BYTE_DISP)].rlx_backward = BYTE_B;
-  table[C (SCB_F, BYTE_DISP)].rlx_length = 3;
-  table[C (SCB_F, BYTE_DISP)].rlx_more = C (SCB_F, WORD_DISP);
-
-  table[C (SCB_F, WORD_DISP)].rlx_forward = WORD_F;
-  table[C (SCB_F, WORD_DISP)].rlx_backward = WORD_B;
-  table[C (SCB_F, WORD_DISP)].rlx_length = 8;
-  table[C (SCB_F, WORD_DISP)].rlx_more = 0;
-
-  table[C (SCB_TST, BYTE_DISP)].rlx_forward = BYTE_F;
-  table[C (SCB_TST, BYTE_DISP)].rlx_backward = BYTE_B;
-  table[C (SCB_TST, BYTE_DISP)].rlx_length = 3;
-  table[C (SCB_TST, BYTE_DISP)].rlx_more = C (SCB_TST, WORD_DISP);
-
-  table[C (SCB_TST, WORD_DISP)].rlx_forward = WORD_F;
-  table[C (SCB_TST, WORD_DISP)].rlx_backward = WORD_B;
-  table[C (SCB_TST, WORD_DISP)].rlx_length = 10;
-  table[C (SCB_TST, WORD_DISP)].rlx_more = 0;
-
 }
 
 static int rn;                 /* register number used by RN */
@@ -305,7 +292,6 @@ typedef enum
     exp_signed, exp_unsigned, exp_sandu
   } sign_type;
 
-
 static char *
 skip_colonthing (sign, ptr, exp, def, size8, size16, size24)
      sign_type sign;
@@ -1213,7 +1199,7 @@ md_atof (type, litP, sizeP)
   return 0;
 }
 \f
-CONST char *md_shortopts = "";
+const char *md_shortopts = "";
 struct option md_longopts[] = {
   {NULL, no_argument, NULL, 0}
 };
@@ -1300,7 +1286,7 @@ wordify_scb (buffer, disp_size, inst_size)
   *buffer++ = 0x04;            /* cmp #0xff:8, rn */
   *buffer++ = 0xff;
   *buffer++ = 0x70 | rn;
-  *buffer++ = 0x36;            /* bne ... */
+  *buffer++ = 0x36;            /* bne ...  */
   *buffer++ = 0;
   *buffer++ = 0;
 }
@@ -1357,7 +1343,6 @@ md_convert_frag (headers, seg, fragP)
               R_H8500_PCREL16);
 
       fragP->fr_fix += disp_size + inst_size;
-      fragP->fr_var = 0;
       return;
       break;
     default:
@@ -1373,7 +1358,6 @@ md_convert_frag (headers, seg, fragP)
 
       md_number_to_chars (buffer + inst_size, disp, disp_size);
       fragP->fr_fix += disp_size + inst_size;
-      fragP->fr_var = 0;
     }
 }
 
@@ -1388,20 +1372,19 @@ md_section_align (seg, size)
 }
 
 void
-md_apply_fix (fixP, val)
+md_apply_fix3 (fixP, valP, seg)
      fixS *fixP;
-     long val;
+     valueT * valP;
+     segT seg ATTRIBUTE_UNUSED;
 {
+  long val = * (long *) valP;
   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 
   if (fixP->fx_r_type == 0)
-    {
-      fixP->fx_r_type = fixP->fx_size == 4 ? R_H8500_IMM32 : R_H8500_IMM16;
-    }
+    fixP->fx_r_type = fixP->fx_size == 4 ? R_H8500_IMM32 : R_H8500_IMM16;
 
   switch (fixP->fx_r_type)
     {
-
     case R_H8500_IMM8:
     case R_H8500_PCREL8:
       *buf++ = val;
@@ -1432,46 +1415,61 @@ md_apply_fix (fixP, val)
       break;
     default:
       abort ();
-
     }
+
+  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+    fixP->fx_done = 1;
 }
 
-/*
-called just before address relaxation, return the length
-by which a fragment must grow to reach it's destination
-*/
+/* Called just before address relaxation, return the length
+   by which a fragment must grow to reach it's destination.  */
+
 int
 md_estimate_size_before_relax (fragP, segment_type)
      register fragS *fragP;
      register segT segment_type;
 {
-  int what = GET_WHAT (fragP->fr_subtype);
+  int what;
 
   switch (fragP->fr_subtype)
     {
     default:
       abort ();
+
     case C (BRANCH, UNDEF_BYTE_DISP):
     case C (SCB_F, UNDEF_BYTE_DISP):
     case C (SCB_TST, UNDEF_BYTE_DISP):
+      what = GET_WHAT (fragP->fr_subtype);
       /* used to be a branch to somewhere which was unknown */
       if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
        {
          /* Got a symbol and it's defined in this segment, become byte
             sized - maybe it will fix up.  */
          fragP->fr_subtype = C (what, BYTE_DISP);
-         fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length;
        }
       else
        {
          /* Its got a segment, but its not ours, so it will always be
              long.  */
          fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
-         fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length;
-         return md_relax_table[C (what, WORD_DISP)].rlx_length;
        }
+      break;
+
+    case C (BRANCH, BYTE_DISP):
+    case C (BRANCH, WORD_DISP):
+    case C (BRANCH, UNDEF_WORD_DISP):
+    case C (SCB_F, BYTE_DISP):
+    case C (SCB_F, WORD_DISP):
+    case C (SCB_F, UNDEF_WORD_DISP):
+    case C (SCB_TST, BYTE_DISP):
+    case C (SCB_TST, WORD_DISP):
+    case C (SCB_TST, UNDEF_WORD_DISP):
+      /* When relaxing a section for the second time, we don't need to
+        do anything besides return the current size.  */
+      break;
     }
-  return fragP->fr_var;
+
+  return md_relax_table[fragP->fr_subtype].rlx_length;
 }
 
 /* Put number into target byte order.  */
@@ -1591,10 +1589,10 @@ start_label (ptr)
      char *ptr;
 {
   /* Check for :s.w */
-  if (isalpha (ptr[1]) && ptr[2] == '.')
+  if (ISALPHA (ptr[1]) && ptr[2] == '.')
     return 0;
   /* Check for :s */
-  if (isalpha (ptr[1]) && !isalpha (ptr[2]))
+  if (ISALPHA (ptr[1]) && !ISALPHA (ptr[2]))
     return 0;
   return 1;
 }