]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
z80, gas: follow historical assemblers and allow "op A,x" and "op x"
authorH. Peter Anvin <hpa@zytor.com>
Fri, 24 Oct 2025 13:12:39 +0000 (15:12 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 24 Oct 2025 13:12:39 +0000 (15:12 +0200)
For arithmetic ops, Z80 syntax wants "op A,x" for ADD, ADC and SBC and
"op x" for SUB, AND, OR, XOR, and CP. Many historical assemblers
simply treat them orthogonally; allowing but not requiring the "A,"
operand for any of these operations. This is widely used in legacy
source code, and there is no reason not to.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
gas/config/tc-z80.c

index add28a39119ccdfaff2d744da73836bae01116ec..72689256f0f2112398a82bdbd278f9e389ddf387 100644 (file)
@@ -1463,9 +1463,8 @@ emit_s (char prefix, char opcode, const char *args)
 
   p = parse_exp (args, & arg_s);
   if (*p == ',' && arg_s.X_md == 0 && arg_s.X_op == O_register && arg_s.X_add_number == REG_A)
-    { /* possible instruction in generic format op A,x */
-      if (!(ins_ok & INS_EZ80) && !sdcc_compat)
-        ill_op ();
+    {
+      /* Allow both op A,x and op x */
       ++p;
       p = parse_exp (p, & arg_s);
     }
@@ -1473,30 +1472,6 @@ emit_s (char prefix, char opcode, const char *args)
   return p;
 }
 
-static const char *
-emit_sub (char prefix, char opcode, const char *args)
-{
-  expressionS arg_s;
-  const char *p;
-
-  if (!(ins_ok & INS_GBZ80))
-    return emit_s (prefix, opcode, args);
-  p = parse_exp (args, & arg_s);
-  if (*p++ != ',')
-    {
-      error (_("bad instruction syntax"));
-      return p;
-    }
-
-  if (arg_s.X_md != 0 || arg_s.X_op != O_register || arg_s.X_add_number != REG_A)
-    ill_op ();
-
-  p = parse_exp (p, & arg_s);
-
-  emit_sx (prefix, opcode, & arg_s);
-  return p;
-}
-
 static const char *
 emit_swap (char prefix, char opcode, const char *args)
 {
@@ -1731,8 +1706,8 @@ emit_adc (char prefix, char opcode, const char * args)
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
-      error (_("bad instruction syntax"));
-      return p;
+      /* "op x" -> "op A,x" */
+      return emit_s (prefix, opcode, args);
     }
 
   if ((term.X_md) || (term.X_op != O_register))
@@ -1774,8 +1749,8 @@ emit_add (char prefix, char opcode, const char * args)
   p = parse_exp (args, &term);
   if (*p++ != ',')
     {
-      error (_("bad instruction syntax"));
-      return p;
+      /* "op x" -> "op A,x" */
+      return emit_s (prefix, opcode, args);
     }
 
   if ((term.X_md) || (term.X_op != O_register))
@@ -3389,7 +3364,7 @@ static int
 assemble_suffix (const char **suffix)
 {
   static
-  const char sf[8][4] = 
+  const char sf[8][4] =
     {
       "il",
       "is",
@@ -3664,7 +3639,7 @@ static table_t instab[] =
   { "srl",  0xCB, 0x38, emit_mr,   INS_ALL },
   { "stmix",0xED, 0x7D, emit_insn, INS_EZ80 },
   { "stop", 0x00, 0x10, emit_insn, INS_GBZ80 },
-  { "sub",  0x00, 0x90, emit_sub,  INS_ALL },
+  { "sub",  0x00, 0x90, emit_s,    INS_ALL },
   { "swap", 0xCB, 0x30, emit_swap, INS_GBZ80|INS_Z80N },
   { "swapnib",0xED,0x23,emit_insn, INS_Z80N },
   { "test", 0xED, 0x27, emit_insn_n, INS_Z80N },