]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gas/config/tc-z80.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / gas / config / tc-z80.c
index e5dc877674264f59fec72dac2c9a1f3ce82defde..577c58479dad7b60a39e447ed0aeae062c51035b 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-z80.c -- Assemble code for the Zilog Z80, Z180, EZ80 and ASCII R800
-   Copyright (C) 2005-2020 Free Software Foundation, Inc.
+   Copyright (C) 2005-2023 Free Software Foundation, Inc.
    Contributed by Arnold Metselaar <arnold_m@operamail.com>
 
    This file is part of GAS, the GNU Assembler.
@@ -175,6 +175,11 @@ match_ext_table [] =
   {"xdcb",    INS_ROT_II_LD, 0, 0, "instructions like RL (IX+d),R (DD/FD CB dd oo)" }
 };
 
+
+static int signed_overflow (signed long value, unsigned bitsize);
+static int unsigned_overflow (unsigned long value, unsigned bitsize);
+static int is_overflow (long value, unsigned bitsize);
+
 static void
 setup_march (const char *name, int *ok, int *err, int *mode)
 {
@@ -533,7 +538,7 @@ md_begin (void)
 }
 
 void
-z80_md_end (void)
+z80_md_finish (void)
 {
   int mach_type;
 
@@ -720,7 +725,7 @@ md_atof (int type, char *litP, int *sizeP)
        return str_to_double (litP, sizeP);
       break;
     }
-  return ieee_md_atof (type, litP, sizeP, FALSE);
+  return ieee_md_atof (type, litP, sizeP, false);
 }
 
 valueT
@@ -842,7 +847,7 @@ is_indir (const char *s)
 }
 
 /* Check whether a symbol involves a register.  */
-static bfd_boolean
+static bool
 contains_register (symbolS *sym)
 {
   if (sym)
@@ -852,17 +857,17 @@ contains_register (symbolS *sym)
       switch (ex->X_op)
        {
        case O_register:
-         return TRUE;
+         return true;
 
        case O_add:
        case O_subtract:
          if (ex->X_op_symbol && contains_register (ex->X_op_symbol))
-           return TRUE;
+           return true;
          /* Fall through.  */
        case O_uminus:
        case O_symbol:
          if (ex->X_add_symbol && contains_register (ex->X_add_symbol))
-           return TRUE;
+           return true;
          break;
 
        default:
@@ -870,7 +875,7 @@ contains_register (symbolS *sym)
        }
     }
 
-  return FALSE;
+  return false;
 }
 
 /* Parse general expression, not looking for indexed addressing.  */
@@ -921,6 +926,7 @@ parse_exp_not_indexed (const char *s, expressionS *op)
     }
   input_line_pointer = (char*) s ;
   expression (op);
+  resolve_register (op);
   switch (op->X_op)
     {
     case O_absent:
@@ -1129,6 +1135,16 @@ emit_data_val (expressionS * val, int size)
   if (val->X_op == O_constant)
     {
       int i;
+
+       /* PR 28791:
+         Check for overflow, but ignore values that were generated by bit
+         manipulation operators (eg ~0xe6 and -7).  This does mean that
+         manipluated overlarge values will not be reported (eg ~0x1234),
+         but it does help to maintain compatibility with earlier versions
+         of the assembler.  */
+      if (! val->X_extrabit
+         && is_overflow (val->X_add_number, size*8))
+       as_warn ( _("%d-bit overflow (%+ld)"), size*8, val->X_add_number);
       for (i = 0; i < size; ++i)
        p[i] = (char)(val->X_add_number >> (i*8));
       return;
@@ -1153,7 +1169,7 @@ emit_data_val (expressionS * val, int size)
 
   if (size <= 2 && val->X_op_symbol)
     {
-      bfd_boolean simplify = TRUE;
+      bool simplify = true;
       int shift = symbol_get_value_expression (val->X_op_symbol)->X_add_number;
       if (val->X_op == O_bit_and && shift == (1 << (size*8))-1)
        shift = 0;
@@ -1168,7 +1184,7 @@ emit_data_val (expressionS * val, int size)
            case 8: r_type = BFD_RELOC_Z80_BYTE1; break;
            case 16: r_type = BFD_RELOC_Z80_BYTE2; break;
            case 24: r_type = BFD_RELOC_Z80_BYTE3; break;
-           default: simplify = FALSE;
+           default: simplify = false;
            }
        }
       else /* if (size == 2) */
@@ -1177,7 +1193,24 @@ emit_data_val (expressionS * val, int size)
            {
            case 0: r_type = BFD_RELOC_Z80_WORD0; break;
            case 16: r_type = BFD_RELOC_Z80_WORD1; break;
-           default: simplify = FALSE;
+           case 8:
+           case 24: /* add two byte fixups */
+             val->X_op = O_symbol;
+             val->X_op_symbol = NULL;
+             val->X_add_number = 0;
+             if (shift == 8)
+               {
+                 fix_new_exp (frag_now, p++ - frag_now->fr_literal, 1, val, false,
+                              BFD_RELOC_Z80_BYTE1);
+                 /* prepare to next byte */
+                 r_type = BFD_RELOC_Z80_BYTE2;
+               }
+             else
+               r_type = BFD_RELOC_Z80_BYTE3; /* high byte will be 0 */
+             size = 1;
+             simplify = false;
+             break;
+           default: simplify = false;
            }
        }
 
@@ -1189,7 +1222,7 @@ emit_data_val (expressionS * val, int size)
        }
     }
 
-  fix_new_exp (frag_now, p - frag_now->fr_literal, size, val, FALSE, r_type);
+  fix_new_exp (frag_now, p - frag_now->fr_literal, size, val, false, r_type);
 }
 
 static void
@@ -1226,7 +1259,7 @@ emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
     {
       /* For symbols only, constants are stored at begin of function.  */
       fix_new_exp (frag_now, p - frag_now->fr_literal, 1, val,
-                  (r_type == BFD_RELOC_8_PCREL) ? TRUE : FALSE, r_type);
+                  r_type == BFD_RELOC_8_PCREL, r_type);
     }
 }
 
@@ -1636,7 +1669,7 @@ emit_push (char prefix, char opcode, const char * args)
   *q = 0x8A;
 
   q = frag_more (2);
-  fix_new_exp (frag_now, q - frag_now->fr_literal, 2, &arg, FALSE,
+  fix_new_exp (frag_now, q - frag_now->fr_literal, 2, &arg, false,
                BFD_RELOC_Z80_16_BE);
 
   return p;
@@ -2374,6 +2407,8 @@ emit_ld_r_m (expressionS *dst, expressionS *src)
          *q = (ins_ok & INS_GBZ80) ? 0xFA : 0x3A;
           emit_word (src);
         }
+      else
+       ill_op ();
     }
 }
 
@@ -3445,6 +3480,15 @@ area (int arg)
     psect (arg);
 }
 
+/* Handle the .bss pseudo-op.  */
+
+static void
+s_bss (int ignore ATTRIBUTE_UNUSED)
+{
+  subseg_set (bss_section, 0);
+  demand_empty_rest_of_line ();
+}
+
 /* Port specific pseudo ops.  */
 const pseudo_typeS md_pseudo_table[] =
 {
@@ -3460,6 +3504,7 @@ const pseudo_typeS md_pseudo_table[] =
   { ".hd64", set_inss, INS_Z180},
   { ".z80", set_inss, INS_Z80},
   { ".z80n", set_inss, INS_Z80N},
+  { "bss", s_bss, 0},
   { "db" , emit_data, 1},
   { "d24", z80_cons, 3},
   { "d32", z80_cons, 4},
@@ -3664,16 +3709,25 @@ md_assemble (char *str)
   input_line_pointer = old_ptr;
 }
 
+static int
+signed_overflow (signed long value, unsigned bitsize)
+{
+  signed long max = (signed long) ((1UL << (bitsize - 1)) - 1);
+  return value < -max - 1 || value > max;
+}
+
+static int
+unsigned_overflow (unsigned long value, unsigned bitsize)
+{
+  return value >> (bitsize - 1) >> 1 != 0;
+}
+
 static int
 is_overflow (long value, unsigned bitsize)
 {
-  long fieldmask = (2UL << (bitsize - 1)) - 1;
-  long signmask = ~fieldmask;
-  long a = value & fieldmask;
-  long ss = a & signmask;
-  if (ss != 0 && ss != (signmask & fieldmask))
-    return 1;
-  return 0;
+  if (value < 0)
+    return signed_overflow (value, bitsize);
+  return unsigned_overflow ((unsigned long)value, bitsize);
 }
 
 void
@@ -3714,7 +3768,7 @@ md_apply_fix (fixS * fixP, valueT* valP, segT seg)
     {
     case BFD_RELOC_8_PCREL:
     case BFD_RELOC_Z80_DISP8:
-      if (fixP->fx_done && (val < -0x80 || val > 0x7f))
+      if (fixP->fx_done && signed_overflow (val, 8))
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("8-bit signed offset out of range (%+ld)"), val);
       *p_lit++ = val;
@@ -3808,7 +3862,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED , fixS *fixp)
 
   if (fixp->fx_subsy != NULL)
     {
-      as_bad_where (fixp->fx_file, fixp->fx_line, _("expression too complex"));
+      as_bad_subtract (fixp);
       return NULL;
     }
 
@@ -3857,11 +3911,11 @@ z80_tc_label_is_local (const char *name)
 #define EXP_MIN -0x10000
 #define EXP_MAX 0x10000
 static int
-str_to_broken_float (bfd_boolean *signP, bfd_uint64_t *mantissaP, int *expP)
+str_to_broken_float (bool *signP, uint64_t *mantissaP, int *expP)
 {
   char *p;
-  bfd_boolean sign;
-  bfd_uint64_t mantissa = 0;
+  bool sign;
+  uint64_t mantissa = 0;
   int exponent = 0;
   int i;
 
@@ -3976,8 +4030,8 @@ str_to_broken_float (bfd_boolean *signP, bfd_uint64_t *mantissaP, int *expP)
 static const char *
 str_to_zeda32(char *litP, int *sizeP)
 {
-  bfd_uint64_t mantissa;
-  bfd_boolean sign;
+  uint64_t mantissa;
+  bool sign;
   int exponent;
   unsigned i;
 
@@ -4035,8 +4089,8 @@ str_to_zeda32(char *litP, int *sizeP)
 static const char *
 str_to_float48(char *litP, int *sizeP)
 {
-  bfd_uint64_t mantissa;
-  bfd_boolean sign;
+  uint64_t mantissa;
+  bool sign;
   int exponent;
   unsigned i;
 
@@ -4073,19 +4127,19 @@ str_to_float48(char *litP, int *sizeP)
 static const char *
 str_to_ieee754_h(char *litP, int *sizeP)
 {
-  return ieee_md_atof ('h', litP, sizeP, FALSE);
+  return ieee_md_atof ('h', litP, sizeP, false);
 }
 
 static const char *
 str_to_ieee754_s(char *litP, int *sizeP)
 {
-  return ieee_md_atof ('s', litP, sizeP, FALSE);
+  return ieee_md_atof ('s', litP, sizeP, false);
 }
 
 static const char *
 str_to_ieee754_d(char *litP, int *sizeP)
 {
-  return ieee_md_atof ('d', litP, sizeP, FALSE);
+  return ieee_md_atof ('d', litP, sizeP, false);
 }
 
 #ifdef TARGET_USE_CFIPOP