Show specific messages for some more invalid instructions, not just "syntax error" (#1679)

This commit is contained in:
Rangi
2025-05-03 12:31:00 -04:00
committed by GitHub
parent 081f48404c
commit 2e6e1ccf06
7 changed files with 114 additions and 43 deletions

View File

@@ -99,6 +99,10 @@
// REG_AF == REG_SP since LD/INC/ADD/DEC allow SP, while PUSH/POP allow AF
enum { REG_BC, REG_DE, REG_HL, REG_SP, REG_AF = REG_SP };
// Names are not needed for AF or SP
static char const *reg_tt_names[] = { "BC", "DE", "HL" };
static char const *reg_tt_high_names[] = { "B", "D", "H" };
static char const *reg_tt_low_names[] = { "C", "E", "L" };
// CC_NZ == CC_Z ^ 1, and CC_NC == CC_C ^ 1, so `!` can toggle them
enum { CC_NZ, CC_Z, CC_NC, CC_C };
@@ -380,6 +384,8 @@
%type <int32_t> reg_ss
%type <int32_t> reg_rr
%type <int32_t> reg_tt
%type <int32_t> reg_tt_no_af
%type <int32_t> reg_bc_or_de
%type <int32_t> ccode_expr
%type <int32_t> ccode
%type <Expression> op_a_n
@@ -2115,16 +2121,30 @@ sm83_ld_hl:
sect_ConstByte(0xF8);
sect_RelByte($5, 1);
}
| SM83_LD MODE_HL COMMA MODE_SP {
::error("LD HL, SP is not a valid instruction; use LD HL, SP + 0\n");
}
| SM83_LD MODE_HL COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_HL << 4));
sect_RelWord($4, 1);
}
| SM83_LD MODE_HL COMMA reg_tt_no_af {
::error(
"LD HL, %s is not a valid instruction; use LD H, %s and LD L, %s\n",
reg_tt_names[$4],
reg_tt_high_names[$4],
reg_tt_low_names[$4]
);
}
;
sm83_ld_sp:
SM83_LD MODE_SP COMMA MODE_HL {
sect_ConstByte(0xF9);
}
| SM83_LD MODE_SP COMMA reg_bc_or_de {
::error("LD SP, %s is not a valid instruction\n", reg_tt_names[$4]);
}
| SM83_LD MODE_SP COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_SP << 4));
sect_RelWord($4, 1);
@@ -2197,13 +2217,20 @@ sm83_ld_a:
;
sm83_ld_ss:
SM83_LD MODE_BC COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_BC << 4));
SM83_LD reg_bc_or_de COMMA reloc_16bit {
sect_ConstByte(0x01 | ($2 << 4));
sect_RelWord($4, 1);
}
| SM83_LD MODE_DE COMMA reloc_16bit {
sect_ConstByte(0x01 | (REG_DE << 4));
sect_RelWord($4, 1);
| SM83_LD reg_bc_or_de COMMA reg_tt_no_af {
::error(
"LD %s, %s is not a valid instruction; use LD %s, %s and LD %s, %s\n",
reg_tt_names[$2],
reg_tt_names[$4],
reg_tt_high_names[$2],
reg_tt_high_names[$4],
reg_tt_low_names[$2],
reg_tt_low_names[$4]
);
}
// HL is taken care of in sm83_ld_hl
// SP is taken care of in sm83_ld_sp
@@ -2532,33 +2559,33 @@ reg_a:
;
reg_tt:
MODE_BC {
$$ = REG_BC;
}
| MODE_DE {
$$ = REG_DE;
}
| MODE_HL {
$$ = REG_HL;
}
reg_tt_no_af
| MODE_AF {
$$ = REG_AF;
}
;
reg_ss:
reg_tt_no_af
| MODE_SP {
$$ = REG_SP;
}
;
reg_tt_no_af:
reg_bc_or_de
| MODE_HL {
$$ = REG_HL;
}
;
reg_bc_or_de:
MODE_BC {
$$ = REG_BC;
}
| MODE_DE {
$$ = REG_DE;
}
| MODE_HL {
$$ = REG_HL;
}
| MODE_SP {
$$ = REG_SP;
}
;
reg_rr:

View File

@@ -582,7 +582,7 @@ void Expression::makeCheckBitIndex(uint8_t mask) {
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
void Expression::checkNBit(uint8_t n) const {
if (isKnown()) {
::checkNBit(value(), n, "Expression");
::checkNBit(value(), n, nullptr);
}
}
@@ -591,11 +591,23 @@ bool checkNBit(int32_t v, uint8_t n, char const *name) {
assume(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (v < -(1 << n) || v >= 1 << n) {
warning(WARNING_TRUNCATION_1, "%s must be %u-bit\n", name, n);
warning(
WARNING_TRUNCATION_1,
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
: "%s must be %u-bit\n",
name ? name : "Expression",
n
);
return false;
}
if (v < -(1 << (n - 1))) {
warning(WARNING_TRUNCATION_2, "%s must be %u-bit\n", name, n);
warning(
WARNING_TRUNCATION_2,
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
: "%s must be %u-bit\n",
name ? name : "Expression",
n
);
return false;
}

View File

@@ -15,14 +15,17 @@ fi
BISON_FLAGS="-Wall -Dparse.lac=full -Dlr.type=ielr"
# Set some optimization flags on versions that support them
if [ "$BISON_MAJOR" -eq 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 5 ]; then
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 5 ]; then
BISON_FLAGS="$BISON_FLAGS -Dapi.token.raw=true"
fi
if [ "$BISON_MAJOR" -eq 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 6 ]; then
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 6 ]; then
BISON_FLAGS="$BISON_FLAGS -Dparse.error=detailed"
else
BISON_FLAGS="$BISON_FLAGS -Dparse.error=verbose"
fi
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 7 ]; then
BISON_FLAGS="$BISON_FLAGS -Wcounterexamples"
fi
# Replace the arguments to this script ($@) with the ones in $BISON_FLAGS
eval "set -- $BISON_FLAGS"

View File

@@ -1,5 +1,5 @@
error: ds-bad.asm(3):
Expected constant expression: 'unknown' is not constant at assembly time
warning: ds-bad.asm(4): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: Assembly aborted (1 error)!

View File

@@ -6,3 +6,16 @@ SECTION "invalid", ROM0[$10000]
ld b, [$4000]
bit 8, a
rst $40
ld bc, bc
ld de, hl
ld hl, de
ld hl, sp ; no offset!
; ld sp, hl is valid
ld sp, bc
ld bc, sp
ld af, bc
ld bc, af

View File

@@ -16,4 +16,20 @@ error: invalid-instructions.asm(7):
Invalid bit index 8 for BIT
error: invalid-instructions.asm(8):
Invalid address $40 for RST
error: Assembly aborted (8 errors)!
error: invalid-instructions.asm(10):
LD BC, BC is not a valid instruction; use LD B, B and LD C, C
error: invalid-instructions.asm(11):
LD DE, HL is not a valid instruction; use LD D, H and LD E, L
error: invalid-instructions.asm(12):
LD HL, DE is not a valid instruction; use LD H, D and LD L, E
error: invalid-instructions.asm(14):
LD HL, SP is not a valid instruction; use LD HL, SP + 0
error: invalid-instructions.asm(17):
LD SP, BC is not a valid instruction
error: invalid-instructions.asm(18):
syntax error, unexpected sp
error: invalid-instructions.asm(20):
syntax error, unexpected af
error: invalid-instructions.asm(21):
syntax error, unexpected af
error: Assembly aborted (16 errors)!

View File

@@ -1,64 +1,64 @@
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(23): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(24): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(25): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(26): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(28): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(29): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(30): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(31): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(23): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(24): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(25): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(26): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(23): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(24): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(25): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(26): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(28): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(29): [-Wtruncation]
Expression must be 16-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(30): [-Wtruncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(31): [-Wtruncation]
Expression must be 16-bit
error: warn-truncation.asm(39) -> warn-truncation.asm::try(23): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(39) -> warn-truncation.asm::try(24): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(39) -> warn-truncation.asm::try(25): [-Werror=truncation]
Expression must be 16-bit
error: warn-truncation.asm(39) -> warn-truncation.asm::try(26): [-Werror=truncation]
Expression must be 16-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(23): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(24): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(25): [-Werror=truncation]
Expression must be 16-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(26): [-Werror=truncation]
Expression must be 16-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(28): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(29): [-Werror=truncation]
Expression must be 16-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(30): [-Werror=truncation]
Expression must be 8-bit
Expression must be 8-bit; use LOW() to force 8-bit
error: warn-truncation.asm(40) -> warn-truncation.asm::try(31): [-Werror=truncation]
Expression must be 16-bit