Fix compile time warning for tc-h8300.c when using gcc 5+.
[binutils-gdb.git] / gas / config / tc-h8300.c
index 62af18033944089562a331e8e146dd9e19013a49..9ff813809b7c2b097aa9020fb49e704831113b2f 100644 (file)
@@ -1,7 +1,5 @@
 /* tc-h8300.c -- Assemble code for the Renesas H8/300
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 
 const char comment_chars[] = ";";
 const char line_comment_chars[] = "#";
+#ifdef TE_LINUX
+const char line_separator_chars[] = "!";
+#else
 const char line_separator_chars[] = "";
+#endif
 
 static void sbranch (int);
 static void h8300hmode (int);
@@ -53,6 +55,8 @@ int Smode;
 int Nmode;
 int SXmode;
 
+static int default_mach = bfd_mach_h8300;
+
 #define PSIZE (Hmode && !Nmode ? L_32 : L_16)
 
 static int bsize = L_8;                /* Default branch displacement.  */
@@ -146,7 +150,7 @@ static void
 h8300_elf_section (int push)
 {
   static const char * known_data_sections [] = { ".rodata", ".tdata", ".tbss" };
-  static const char * known_data_prefixes [] = { ".debug", ".gnu.warning" };
+  static const char * known_data_prefixes [] = { ".debug", ".zdebug", ".gnu.warning" };
   char * saved_ilp = input_line_pointer;
   char * name;
 
@@ -240,7 +244,7 @@ md_begin (void)
   char prev_buffer[100];
   int idx = 0;
 
-  if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300))
+  if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, default_mach))
     as_warn (_("could not set architecture and machine"));
 
   opcode_hash_control = hash_new ();
@@ -359,7 +363,6 @@ static int parse_reg (char *, op_type *, unsigned *, int);
 static char *skip_colonthing (char *, int *);
 static char *parse_exp (char *, struct h8_op *);
 
-static int constant_fits_width_p (struct h8_op *, unsigned int);
 static int constant_fits_size_p (struct h8_op *, int, int);
 
 /*
@@ -556,19 +559,23 @@ skip_colonthing (char *src, int *mode)
    @@aa[:8]            memory indirect.  */
 
 static int
-constant_fits_width_p (struct h8_op *operand, unsigned int width)
+constant_fits_width_p (struct h8_op *operand, offsetT width)
 {
-  return ((operand->exp.X_add_number & ~width) == 0
-         || (operand->exp.X_add_number | width) == (unsigned)(~0));
+  offsetT num;
+
+  num = ((operand->exp.X_add_number & 0xffffffff) ^ 0x80000000) - 0x80000000;
+  return (num & ~width) == 0 || (num | width) == ~0;
 }
 
 static int
 constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
 {
-  offsetT num = operand->exp.X_add_number;
+  offsetT num;
+
   if (no_symbols
       && (operand->exp.X_add_symbol != 0 || operand->exp.X_op_symbol != 0))
     return 0;
+  num = operand->exp.X_add_number & 0xffffffff;
   switch (size)
     {
     case L_2:
@@ -582,11 +589,13 @@ constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
     case L_5:
       return num >= 1 && num < 32;
     case L_8:
-      return (num & ~0xFF) == 0 || ((unsigned)num | 0x7F) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFF) == 0 || (num | 0x7F) == ~0;
     case L_8U:
       return (num & ~0xFF) == 0;
     case L_16:
-      return (num & ~0xFFFF) == 0 || ((unsigned)num | 0x7FFF) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFFFF) == 0 || (num | 0x7FFF) == ~0;
     case L_16U:
       return (num & ~0xFFFF) == 0;
     case L_32:
@@ -1184,7 +1193,7 @@ get_specific (const struct h8_instruction *instruction,
                }
              else if (x_mode == IMM && op_mode != IMM)
                {
-                 offsetT num = operands[i].exp.X_add_number;
+                 offsetT num = operands[i].exp.X_add_number & 0xffffffff;
                  if (op_mode == KBIT || op_mode == DBIT)
                    /* This is ok if the immediate value is sensible.  */;
                  else if (op_mode == CONST_2)
@@ -1391,7 +1400,12 @@ do_a_fix_imm (int offset, int nibble, struct h8_op *operand, int relaxmode, cons
          bytes[3] |= operand->exp.X_add_number >> 0;
          if (relaxmode != 0)
            {
-             idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1;
+#ifdef OBJ_ELF
+             if ((operand->mode & MODE) == DISP && relaxmode == 1)
+               idx = BFD_RELOC_H8_DISP32A16;
+             else
+#endif
+               idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1;
              fix_new_exp (frag_now, offset, 4, &operand->exp, 0, idx);
            }
          break;
@@ -1405,6 +1419,11 @@ do_a_fix_imm (int offset, int nibble, struct h8_op *operand, int relaxmode, cons
        case L_32:
          size = 4;
          where = (operand->mode & SIZE) == L_24 ? -1 : 0;
+#ifdef OBJ_ELF
+         if ((operand->mode & MODE) == DISP && relaxmode == 1)
+           idx = BFD_RELOC_H8_DISP32A16;
+         else
+#endif
          if (relaxmode == 2)
            idx = R_MOV24B1;
          else if (relaxmode == 1)
@@ -1611,7 +1630,7 @@ build_bytes (const struct h8_instruction *this_try, struct h8_op *operand)
   for (i = 0; i < this_try->length; i++)
     output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
 
-  /* Note if this is a movb or a bit manipulation instruction
+  /* Note if this is a mov.b or a bit manipulation instruction
      there is a special relaxation which only applies.  */
   if (   this_try->opcode->how == O (O_MOV,   SB)
       || this_try->opcode->how == O (O_BCLR,  SB)
@@ -1637,10 +1656,17 @@ build_bytes (const struct h8_instruction *this_try, struct h8_op *operand)
       int x_mode = x & MODE;
 
       if (x_mode == IMM || x_mode == DISP)
-       do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
-                     op_at[i] & 1, operand + i, (x & MEMRELAX) != 0,
-                     this_try);
-
+       {
+#ifndef OBJ_ELF
+         /* Remove MEMRELAX flag added in h8300.h on mov with
+            addressing mode "register indirect with displacement".  */
+         if (x_mode == DISP)
+           x &= ~MEMRELAX;
+#endif
+         do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
+                       op_at[i] & 1, operand + i, (x & MEMRELAX) != 0,
+                       this_try);
+       }
       else if (x_mode == ABS)
        do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
                      op_at[i] & 1, operand + i,
@@ -1866,8 +1892,8 @@ fix_operand_size (struct h8_op *operand, int size)
           necessary.  */
        if (Hmode
            && !Nmode 
-           && (operand->exp.X_add_number < -32768
-               || operand->exp.X_add_number > 32767
+           && ((((addressT) operand->exp.X_add_number + 0x8000)
+                & 0xffffffff) > 0xffff
                || operand->exp.X_add_symbol != 0
                || operand->exp.X_op_symbol != 0))
          operand->mode |= L_24;
@@ -1876,9 +1902,8 @@ fix_operand_size (struct h8_op *operand, int size)
        break;
 
       case PCREL:
-       /* This condition is long standing, though somewhat suspect.  */
-       if (operand->exp.X_add_number > -128
-           && operand->exp.X_add_number < 127)
+       if ((((addressT) operand->exp.X_add_number + 0x80)
+            & 0xffffffff) <= 0xff)
          {
            if (operand->exp.X_add_symbol != NULL)
              operand->mode |= bsize;
@@ -2083,24 +2108,115 @@ md_atof (int type, char *litP, int *sizeP)
 }
 \f
 #define OPTION_H_TICK_HEX      (OPTION_MD_BASE)
+#define OPTION_MACH            (OPTION_MD_BASE+1)
 
 const char *md_shortopts = "";
-struct option md_longopts[] = {
+struct option md_longopts[] =
+{
   { "h-tick-hex", no_argument,       NULL, OPTION_H_TICK_HEX  },
+  { "mach", required_argument, NULL, OPTION_MACH },
   {NULL, no_argument, NULL, 0}
 };
 
 size_t md_longopts_size = sizeof (md_longopts);
 
+struct mach_func
+{
+  const char *name;
+  void (*func) (void);
+};
+
+static void
+mach_h8300h (void)
+{
+  Hmode = 1;
+  Smode = 0;
+  Nmode = 0;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300h;
+}
+
+static void
+mach_h8300hn (void)
+{
+  Hmode = 1;
+  Smode = 0;
+  Nmode = 1;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300hn;
+}
+
+static void
+mach_h8300s (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 0;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300s;
+}
+
+static void
+mach_h8300sn (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 1;
+  SXmode = 0;
+  default_mach = bfd_mach_h8300sn;
+}
+
+static void
+mach_h8300sx (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 0;
+  SXmode = 1;
+  default_mach = bfd_mach_h8300sx;
+}
+
+static void
+mach_h8300sxn (void)
+{
+  Hmode = 1;
+  Smode = 1;
+  Nmode = 1;
+  SXmode = 1;
+  default_mach = bfd_mach_h8300sxn;
+}
+
+const struct mach_func mach_table[] =
+{
+  {"h8300h",  mach_h8300h},
+  {"h8300hn", mach_h8300hn},
+  {"h8300s",  mach_h8300s},
+  {"h8300sn", mach_h8300sn},
+  {"h8300sx", mach_h8300sx},
+  {"h8300sxn", mach_h8300sxn}
+};
+
 int
 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
 {
+  unsigned int i;
   switch (c)
     {
     case OPTION_H_TICK_HEX:
       enable_h_tick_hex = 1;
       break;
-
+    case OPTION_MACH:
+      for (i = 0; i < sizeof(mach_table) / sizeof(struct mach_func); i++)
+       {
+         if (strcasecmp (arg, mach_table[i].name) == 0)
+           {
+             mach_table[i].func();
+             break;
+           }
+       }
+      if (i >= sizeof(mach_table) / sizeof(struct mach_func))
+       as_bad (_("Invalid argument to --mach option: %s"), arg);
+      break;
     default:
       return 0;
     }
@@ -2108,8 +2224,14 @@ md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
 }
 
 void
-md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
+md_show_usage (FILE *stream)
 {
+  fprintf (stream, _(" H8300-specific assembler options:\n"));
+  fprintf (stream, _("\
+  -mach=<name>             Set the H8300 machine type to one of:\n\
+                           h8300h, h8300hn, h8300s, h8300sn, h8300sx, h8300sxn\n"));
+  fprintf (stream, _("\
+  -h-tick-hex              Support H'00 style hex constants\n"));
 }
 \f
 void tc_aout_fix_to_chars (void);
@@ -2134,7 +2256,7 @@ valueT
 md_section_align (segT segment, valueT size)
 {
   int align = bfd_get_section_alignment (stdoutput, segment);
-  return ((size + (1 << align) - 1) & (-1 << align));
+  return ((size + (1 << align) - 1) & (-1U << align));
 }
 
 void