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]

[Patch] (z80): def24 for three byte constants and more


Hello,
I am committing the following patch for the z80 target. 
It adds a def24 and a def32 pseudo-op for 24 and 32 bit constants. 
The way pseudo-ops for constants are handled is cleaned up a bit to make the assembler more consistent.

include/coff/ChangeLog:
	* internal.h: Add relocation number R_IMM24 for Z80.

bfd/ChangeLog:
	* coff-z80.c (r_imm24): New howto. 
	(rtype2howto): New case R_IMM24.
	(coff_z80_reloc_type_lookup): New case BFD_RELOC_24.
	(extra_case): Use bfd_get_8 for R_IMM8, new case R_IMM24.

gas/ChangeLog:
	* config/tc-z80.c (z80_start_line_hook): allow .equ and .defl as 
	synonyms for equ and defl. 
	(z80_cons_fix_new): New function.
	(emit_byte): Disallow relative jumps to absolute locations.
	(emit_data): Only handle defb, prototype changed, because defb is 
	now handled as pseudo-op rather than an instruction.
	(instab): Entries for defb,defw,db,dw moved from here...
	(md_pseudo_table): ... to here, use generic cons() for defw,dw. 
	Add entries for def24,def32,d24,d32.
	(md_assemble): Improved error handling.
	(md_apply_fix): New case BFD_RELOC_24, set fixP->fx_no_overflow to one.
	* config/tc-z80.h (TC_CONS_FIX_NEW): Define.
	(z80_cons_fix_new): Declare.
	* doc/c-z80.texi (defb, db): Mention warning on overflow. 
	(def24,d24,def32,d32): New pseudo-ops.
Index: include/coff/internal.h
===================================================================
RCS file: /cvs/src/src/include/coff/internal.h,v
retrieving revision 1.17
diff -u -p -r1.17 internal.h
--- include/coff/internal.h	25 Oct 2005 17:40:19 -0000	1.17
+++ include/coff/internal.h	5 Feb 2006 11:41:05 -0000
@@ -717,6 +717,7 @@ struct internal_reloc
 
 /* Z80 modes */
 #define R_OFF8    0x32		/* 8 bit signed abs, for (i[xy]+d) */
+#define R_IMM24   0x33          /* 24 bit abs */
 /* R_JR, R_IMM8, R_IMM16, R_IMM32 - as for Z8k */
 
 /* H8500 modes */
Index: bfd/coff-z80.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-z80.c,v
retrieving revision 1.2
diff -u -p -r1.2 coff-z80.c
--- bfd/coff-z80.c	27 Dec 2005 03:06:27 -0000	1.2
+++ bfd/coff-z80.c	5 Feb 2006 11:41:05 -0000
@@ -34,6 +34,11 @@ HOWTO (R_IMM32, 0, 1, 32, FALSE, 0,
        complain_overflow_dont, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff,
        FALSE);
 
+static reloc_howto_type r_imm24 =
+HOWTO (R_IMM24, 0, 1, 24, FALSE, 0,
+       complain_overflow_dont, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff,
+       FALSE);
+
 static reloc_howto_type r_imm16 =
 HOWTO (R_IMM16, 0, 1, 16, FALSE, 0,
        complain_overflow_dont, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff,
@@ -84,6 +89,9 @@ rtype2howto (arelent *internal, struct i
     case R_IMM16:
       internal->howto = &r_imm16;
       break;
+    case R_IMM24:
+      internal->howto = &r_imm24;
+      break;
     case R_IMM32:
       internal->howto = &r_imm32;
       break;
@@ -106,6 +114,7 @@ coff_z80_reloc_type_lookup (bfd *abfd AT
     {
     case BFD_RELOC_8:		return & r_imm8;
     case BFD_RELOC_16:		return & r_imm16;
+    case BFD_RELOC_24:		return & r_imm24;
     case BFD_RELOC_32:		return & r_imm32;
     case BFD_RELOC_8_PCREL:	return & r_jr;
     case BFD_RELOC_Z80_DISP8:	return & r_off8;
@@ -173,7 +182,7 @@ extra_case (bfd *in_abfd,
       break;
 
     case R_IMM8:
-      val = bfd_get_16 ( in_abfd, data+*src_ptr)
+      val = bfd_get_8 ( in_abfd, data+*src_ptr)
 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
       bfd_put_8 (in_abfd, val, data + *dst_ptr);
       (*dst_ptr) += 1;
@@ -188,6 +197,16 @@ extra_case (bfd *in_abfd,
       (*src_ptr) += 2;
       break;
 
+    case R_IMM24:
+      val = bfd_get_16 ( in_abfd, data+*src_ptr)
+	+ (bfd_get_8 ( in_abfd, data+*src_ptr+2) << 16)
+	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+      bfd_put_16 (in_abfd, val, data + *dst_ptr);
+      bfd_put_8 (in_abfd, val >> 16, data + *dst_ptr+2);
+      (*dst_ptr) += 3;
+      (*src_ptr) += 3;
+      break;
+
     case R_IMM32:
       val = bfd_get_32 ( in_abfd, data+*src_ptr)
 	+ bfd_coff_reloc16_get_value (reloc, link_info, input_section);
Index: gas/config/tc-z80.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-z80.c,v
retrieving revision 1.3
diff -u -p -r1.3 tc-z80.c
--- gas/config/tc-z80.c	2 Dec 2005 22:31:16 -0000	1.3
+++ gas/config/tc-z80.c	5 Feb 2006 11:41:07 -0000
@@ -210,16 +210,6 @@ z80_md_end (void)
   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_type);
 }
 
-/* Port specific features.  */
-const pseudo_typeS md_pseudo_table[] =
-{
-  { "defs",  s_space, 1}, /* Synonym for ds on some assemblers.  */
-  { "ds",    s_space, 1}, /* Fill with bytes rather than words.  */
-  { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
-  { "set", 0, 0}, 		/* Real instruction on z80.  */
-  { NULL, 0, 0 }
-} ;
-
 static const char *
 skip_space (const char *s)
 {
@@ -262,7 +252,7 @@ z80_start_line_hook (void)
 	  break;
 	}
     }
-  /* Check for <label>[:] (EQU|DEFL) <value>.  */
+  /* Check for <label>[:] [.](EQU|DEFL) <value>.  */
   if (is_name_beginner (*input_line_pointer))
     {
       char c, *rest, *line_start;
@@ -281,6 +271,8 @@ z80_start_line_hook (void)
 	++rest;
       if (*rest == ' ' || *rest == '\t')
 	++rest;
+      if (*rest == '.')
+	++rest;
       if (strncasecmp (rest, "EQU", 3) == 0)
 	len = 3;
       else if (strncasecmp (rest, "DEFL", 4) == 0)
@@ -300,7 +292,6 @@ z80_start_line_hook (void)
 	      if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
 		as_bad (_("symbol `%s' is already defined"), line_start);
 	    }
-	  /* All symbols may be redefined.  */
 	  equals (line_start, 1);
 	  return 1;
 	}
@@ -452,7 +443,7 @@ wrong_mach (int ins_type)
       p = "instruction only works R800";
       break;
     default:
-      p = 0; /* Not reachables.  */
+      p = 0; /* Not reachable.  */
     }
 
   if (ins_type & ins_err)
@@ -733,6 +724,26 @@ emit_insn (char prefix, char opcode, con
   return args;
 }
 
+void z80_cons_fix_new (fragS *frag_p, int offset, int nbytes, expressionS *exp)
+{
+  bfd_reloc_code_real_type r[4] =
+    {
+      BFD_RELOC_8,
+      BFD_RELOC_16,
+      BFD_RELOC_24,
+      BFD_RELOC_32
+    };
+
+  if (nbytes < 1 || nbytes > 4) 
+    {
+      as_bad (_("unsupported BFD relocation size %u"), nbytes);
+    }
+  else
+    {
+      fix_new_exp (frag_p, offset, nbytes, exp, 0, r[nbytes-1]);
+    }
+}
+
 static void
 emit_byte (expressionS * val, bfd_reloc_code_real_type r_type)
 {
@@ -742,7 +753,11 @@ emit_byte (expressionS * val, bfd_reloc_
 
   p = frag_more (1);
   *p = val->X_add_number;
-  if ((r_type != BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
+  if ((r_type == BFD_RELOC_8_PCREL) && (val->X_op == O_constant))
+    {
+      as_bad(_("cannot make a relative jump to an absolute location"));
+    }
+  else if (val->X_op == O_constant)
     {
       lo = -128;
       hi = (BFD_RELOC_8 == r_type) ? 255 : 127;
@@ -1717,38 +1732,33 @@ emit_ld (char prefix_in ATTRIBUTE_UNUSED
   return p;
 }
 
-static const char *
-emit_data (char prefix ATTRIBUTE_UNUSED, char opcode, const char * args)
+static void
+emit_data (int size ATTRIBUTE_UNUSED)
 {
   const char *p, *q;
   char *u, quote;
   int cnt;
   expressionS exp;
 
-  p = skip_space (args);
-  if (!*p)
-    error (_("missing operand"));
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+  p = skip_space (input_line_pointer);
 
-  while (*p)
+  do
     {
       if (*p == '\"' || *p == '\'')
 	{
-	  if (opcode == 1)
-	    {
-	      for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
-		;
-	      u = frag_more (cnt);
-	      memcpy (u, q, cnt);
-	      if (!*p)
-		as_warn (_("unterminated string"));
-	      else
-		p = skip_space (p+1);
-	    }
-	  else
-	    {
-	      ill_op ();
-	      break;
-	    }
+	    for (quote = *p, q = ++p, cnt = 0; *p && quote != *p; ++p, ++cnt)
+	      ;
+	    u = frag_more (cnt);
+	    memcpy (u, q, cnt);
+	    if (!*p)
+	      as_warn (_("unterminated string"));
+	    else
+	      p = skip_space (p+1);
 	}
       else
 	{
@@ -1760,21 +1770,12 @@ emit_data (char prefix ATTRIBUTE_UNUSED,
 	    }
 	  if (exp.X_md)
 	    as_warn (_("parentheses ignored"));
-	  if (opcode == 1)
-	    emit_byte (&exp, BFD_RELOC_8);
-	  else
-	    emit_word (&exp);
+	  emit_byte (&exp, BFD_RELOC_8);
 	  p = skip_space (p);
 	}
-      if (*p)
-	{
-	  if (*p != ',')
-	    as_warn (_("missing ','"));
-	  else
-	    ++p;
-	}
     }
-  return p;
+  while (*p++ == ',') ;
+  input_line_pointer = (char *)(p-1);
 }
 
 static const char *
@@ -1843,6 +1844,24 @@ emit_muluw (char prefix ATTRIBUTE_UNUSED
   return p;
 }
 
+/* Port specific pseudo ops.  */
+const pseudo_typeS md_pseudo_table[] =
+{
+  { "db" , emit_data, 1},
+  { "d24", cons, 3},
+  { "d32", cons, 4},
+  { "def24", cons, 3},
+  { "def32", cons, 4},
+  { "defb", emit_data, 1},  
+  { "defs", s_space, 1}, /* Synonym for ds on some assemblers.  */
+  { "defw", cons, 2},
+  { "ds",   s_space, 1}, /* Fill with bytes rather than words.  */
+  { "dw", cons, 2},
+  { "psect", obj_coff_section, 0}, /* TODO: Translate attributes.  */
+  { "set", 0, 0}, 		/* Real instruction on z80.  */
+  { NULL, 0, 0 }
+} ;
+
 static table_t instab[] =
 {
   { "adc",  0x88, 0x4A, emit_adc },
@@ -1858,13 +1877,9 @@ static table_t instab[] =
   { "cpir", 0xED, 0xB1, emit_insn },
   { "cpl",  0x00, 0x2F, emit_insn },
   { "daa",  0x00, 0x27, emit_insn },
-  { "db",   0x00, 0x01, emit_data },
   { "dec",  0x0B, 0x05, emit_incdec },
-  { "defb", 0x00, 0x01, emit_data },
-  { "defw", 0x00, 0x02, emit_data },
   { "di",   0x00, 0xF3, emit_insn },
   { "djnz", 0x00, 0x10, emit_jr },
-  { "dw",   0x00, 0x02, emit_data },
   { "ei",   0x00, 0xFB, emit_insn },
   { "ex",   0x00, 0x00, emit_ex},
   { "exx",  0x00, 0xD9, emit_insn },
@@ -1936,25 +1951,32 @@ md_assemble (char* str)
   for (i = 0; (i < BUFLEN) && (ISALPHA (*p));)
     buf[i++] = TOLOWER (*p++);
 
-  if ((i == BUFLEN)
-      || ((*p) && (!ISSPACE (*p))))
-    as_bad (_("illegal instruction '%s'"), buf);
-
-  buf[i] = 0;
-  p = skip_space (p);
-  key = buf;
-
-  insp = bsearch (&key, instab, ARRAY_SIZE (instab),
-		  sizeof (instab[0]), key_cmp);
-  if (!insp)
-    as_bad (_("illegal instruction '%s'"), buf);
-  else
+  if (i == BUFLEN)
     {
-      p = insp->fp (insp->prefix, insp->opcode, p);
+      buf[BUFLEN-3] = buf[BUFLEN-2] = '.'; /* Mark opcode as abbreviated.  */
+      buf[BUFLEN-1] = 0;
+      as_bad (_("Unknown instruction '%s'"), buf);
+    }
+  else if ((*p) && (!ISSPACE (*p)))
+    as_bad (_("syntax error"));
+  else 
+    {
+      buf[i] = 0;
       p = skip_space (p);
-      if ((!err_flag) && *p)
-	as_bad (_("junk at end of line, first unrecognized character is `%c'"),
-		*p);
+      key = buf;
+      
+      insp = bsearch (&key, instab, ARRAY_SIZE (instab),
+		    sizeof (instab[0]), key_cmp);
+      if (!insp)
+	as_bad (_("Unknown instruction '%s'"), buf);
+      else
+	{
+	  p = insp->fp (insp->prefix, insp->opcode, p);
+	  p = skip_space (p);
+	if ((!err_flag) && *p)
+	  as_bad (_("junk at end of line, first unrecognized character is `%c'"),
+		  *p);
+	}
     }
   input_line_pointer = old_ptr;
 }
@@ -2005,6 +2027,7 @@ md_apply_fix (fixS * fixP, valueT* valP,
       if (val > 255 || val < -128)
 	as_warn_where (fixP->fx_file, fixP->fx_line, _("overflow"));
       *buf++ = val;
+      fixP->fx_no_overflow = 1; 
       if (fixP->fx_addsy == NULL)
 	fixP->fx_done = 1;
       break;
@@ -2012,11 +2035,21 @@ md_apply_fix (fixS * fixP, valueT* valP,
     case BFD_RELOC_16:
       *buf++ = val;
       *buf++ = (val >> 8);
+      fixP->fx_no_overflow = 1; 
+      if (fixP->fx_addsy == NULL)
+	fixP->fx_done = 1;
+      break;
+
+    case BFD_RELOC_24: /* Def24 may produce this.  */
+      *buf++ = val;
+      *buf++ = (val >> 8);
+      *buf++ = (val >> 16);
+      fixP->fx_no_overflow = 1; 
       if (fixP->fx_addsy == NULL)
 	fixP->fx_done = 1;
       break;
 
-    case BFD_RELOC_32: /* .Long may produce this.  */
+    case BFD_RELOC_32: /* Def32 and .long may produce this.  */
       *buf++ = val;
       *buf++ = (val >> 8);
       *buf++ = (val >> 16);
Index: gas/config/tc-z80.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-z80.h,v
retrieving revision 1.2
diff -u -p -r1.2 tc-z80.h
--- gas/config/tc-z80.h	7 Nov 2005 02:15:47 -0000	1.2
+++ gas/config/tc-z80.h	5 Feb 2006 11:41:07 -0000
@@ -56,10 +56,12 @@
 #define md_end               z80_md_end
 #define md_start_line_hook() { if (z80_start_line_hook ()) continue; }
 #define md_optimize_expr     z80_optimize_expr
+#define TC_CONS_FIX_NEW z80_cons_fix_new
 
 extern void z80_md_end (void);
 extern int z80_start_line_hook (void);
 extern int z80_optimize_expr (expressionS *, operatorT, expressionS *);
+extern void z80_cons_fix_new (fragS *, int, int, expressionS *);
 
 #define WORKING_DOT_WORD
 
Index: gas/doc/c-z80.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-z80.texi,v
retrieving revision 1.2
diff -u -p -r1.2 c-z80.texi
--- gas/doc/c-z80.texi	26 Nov 2005 20:03:53 -0000	1.2
+++ gas/doc/c-z80.texi	5 Feb 2006 11:41:07 -0000
@@ -150,14 +150,24 @@ These are the additional directives in @
 @item db @var{expression}|@var{string}[,@var{expression}|@var{string}...]
 @itemx defb @var{expression}|@var{string}[,@var{expression}|@var{string}...]
 For each @var{string} the characters are copied to the object file, for
-each other @var{expression} the value is stored in one byte, ignoring
-overflow. 
+each other @var{expression} the value is stored in one byte. 
+A warning is issued in case of an overflow. 
 
 @item dw @var{expression}[,@var{expression}...]
 @itemx defw @var{expression}[,@var{expression}...]
 For each @var{expression} the value is stored in two bytes, ignoring
 overflow. 
 
+@item d24 @var{expression}[,@var{expression}...]
+@itemx def24 @var{expression}[,@var{expression}...]
+For each @var{expression} the value is stored in three bytes, ignoring
+overflow. 
+
+@item d32 @var{expression}[,@var{expression}...]
+@itemx def32 @var{expression}[,@var{expression}...]
+For each @var{expression} the value is stored in four bytes, ignoring
+overflow. 
+
 @item ds @var{count}[, @var{value}]
 @itemx defs @var{count}[, @var{value}]
 @c Synonyms for @code{ds.b}, 

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