z80, gas: follow historical assemblers and allow "op A,x" and "op x"

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>
This commit is contained in:
H. Peter Anvin
2025-10-24 15:12:39 +02:00
committed by Jan Beulich
parent a04b91a641
commit f861f82cd9

View 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 },