Skip to content

Commit 2e6e1cc

Browse files
authored
Show specific messages for some more invalid instructions, not just "syntax error" (#1679)
1 parent 081f484 commit 2e6e1cc

File tree

7 files changed

+113
-42
lines changed

7 files changed

+113
-42
lines changed

src/asm/parser.y

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999

100100
// REG_AF == REG_SP since LD/INC/ADD/DEC allow SP, while PUSH/POP allow AF
101101
enum { REG_BC, REG_DE, REG_HL, REG_SP, REG_AF = REG_SP };
102+
// Names are not needed for AF or SP
103+
static char const *reg_tt_names[] = { "BC", "DE", "HL" };
104+
static char const *reg_tt_high_names[] = { "B", "D", "H" };
105+
static char const *reg_tt_low_names[] = { "C", "E", "L" };
102106

103107
// CC_NZ == CC_Z ^ 1, and CC_NC == CC_C ^ 1, so `!` can toggle them
104108
enum { CC_NZ, CC_Z, CC_NC, CC_C };
@@ -380,6 +384,8 @@
380384
%type <int32_t> reg_ss
381385
%type <int32_t> reg_rr
382386
%type <int32_t> reg_tt
387+
%type <int32_t> reg_tt_no_af
388+
%type <int32_t> reg_bc_or_de
383389
%type <int32_t> ccode_expr
384390
%type <int32_t> ccode
385391
%type <Expression> op_a_n
@@ -2115,16 +2121,30 @@ sm83_ld_hl:
21152121
sect_ConstByte(0xF8);
21162122
sect_RelByte($5, 1);
21172123
}
2124+
| SM83_LD MODE_HL COMMA MODE_SP {
2125+
::error("LD HL, SP is not a valid instruction; use LD HL, SP + 0\n");
2126+
}
21182127
| SM83_LD MODE_HL COMMA reloc_16bit {
21192128
sect_ConstByte(0x01 | (REG_HL << 4));
21202129
sect_RelWord($4, 1);
21212130
}
2131+
| SM83_LD MODE_HL COMMA reg_tt_no_af {
2132+
::error(
2133+
"LD HL, %s is not a valid instruction; use LD H, %s and LD L, %s\n",
2134+
reg_tt_names[$4],
2135+
reg_tt_high_names[$4],
2136+
reg_tt_low_names[$4]
2137+
);
2138+
}
21222139
;
21232140

21242141
sm83_ld_sp:
21252142
SM83_LD MODE_SP COMMA MODE_HL {
21262143
sect_ConstByte(0xF9);
21272144
}
2145+
| SM83_LD MODE_SP COMMA reg_bc_or_de {
2146+
::error("LD SP, %s is not a valid instruction\n", reg_tt_names[$4]);
2147+
}
21282148
| SM83_LD MODE_SP COMMA reloc_16bit {
21292149
sect_ConstByte(0x01 | (REG_SP << 4));
21302150
sect_RelWord($4, 1);
@@ -2197,13 +2217,20 @@ sm83_ld_a:
21972217
;
21982218

21992219
sm83_ld_ss:
2200-
SM83_LD MODE_BC COMMA reloc_16bit {
2201-
sect_ConstByte(0x01 | (REG_BC << 4));
2220+
SM83_LD reg_bc_or_de COMMA reloc_16bit {
2221+
sect_ConstByte(0x01 | ($2 << 4));
22022222
sect_RelWord($4, 1);
22032223
}
2204-
| SM83_LD MODE_DE COMMA reloc_16bit {
2205-
sect_ConstByte(0x01 | (REG_DE << 4));
2206-
sect_RelWord($4, 1);
2224+
| SM83_LD reg_bc_or_de COMMA reg_tt_no_af {
2225+
::error(
2226+
"LD %s, %s is not a valid instruction; use LD %s, %s and LD %s, %s\n",
2227+
reg_tt_names[$2],
2228+
reg_tt_names[$4],
2229+
reg_tt_high_names[$2],
2230+
reg_tt_high_names[$4],
2231+
reg_tt_low_names[$2],
2232+
reg_tt_low_names[$4]
2233+
);
22072234
}
22082235
// HL is taken care of in sm83_ld_hl
22092236
// SP is taken care of in sm83_ld_sp
@@ -2532,33 +2559,33 @@ reg_a:
25322559
;
25332560

25342561
reg_tt:
2535-
MODE_BC {
2536-
$$ = REG_BC;
2562+
reg_tt_no_af
2563+
| MODE_AF {
2564+
$$ = REG_AF;
25372565
}
2538-
| MODE_DE {
2539-
$$ = REG_DE;
2566+
;
2567+
2568+
reg_ss:
2569+
reg_tt_no_af
2570+
| MODE_SP {
2571+
$$ = REG_SP;
25402572
}
2573+
;
2574+
2575+
reg_tt_no_af:
2576+
reg_bc_or_de
25412577
| MODE_HL {
25422578
$$ = REG_HL;
25432579
}
2544-
| MODE_AF {
2545-
$$ = REG_AF;
2546-
}
25472580
;
25482581

2549-
reg_ss:
2582+
reg_bc_or_de:
25502583
MODE_BC {
25512584
$$ = REG_BC;
25522585
}
25532586
| MODE_DE {
25542587
$$ = REG_DE;
25552588
}
2556-
| MODE_HL {
2557-
$$ = REG_HL;
2558-
}
2559-
| MODE_SP {
2560-
$$ = REG_SP;
2561-
}
25622589
;
25632590

25642591
reg_rr:

src/asm/rpn.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ void Expression::makeCheckBitIndex(uint8_t mask) {
582582
// Checks that an RPN expression's value fits within N bits (signed or unsigned)
583583
void Expression::checkNBit(uint8_t n) const {
584584
if (isKnown()) {
585-
::checkNBit(value(), n, "Expression");
585+
::checkNBit(value(), n, nullptr);
586586
}
587587
}
588588

@@ -591,11 +591,23 @@ bool checkNBit(int32_t v, uint8_t n, char const *name) {
591591
assume(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
592592

593593
if (v < -(1 << n) || v >= 1 << n) {
594-
warning(WARNING_TRUNCATION_1, "%s must be %u-bit\n", name, n);
594+
warning(
595+
WARNING_TRUNCATION_1,
596+
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
597+
: "%s must be %u-bit\n",
598+
name ? name : "Expression",
599+
n
600+
);
595601
return false;
596602
}
597603
if (v < -(1 << (n - 1))) {
598-
warning(WARNING_TRUNCATION_2, "%s must be %u-bit\n", name, n);
604+
warning(
605+
WARNING_TRUNCATION_2,
606+
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
607+
: "%s must be %u-bit\n",
608+
name ? name : "Expression",
609+
n
610+
);
599611
return false;
600612
}
601613

src/bison.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ fi
1515
BISON_FLAGS="-Wall -Dparse.lac=full -Dlr.type=ielr"
1616

1717
# Set some optimization flags on versions that support them
18-
if [ "$BISON_MAJOR" -eq 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 5 ]; then
18+
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 5 ]; then
1919
BISON_FLAGS="$BISON_FLAGS -Dapi.token.raw=true"
2020
fi
21-
if [ "$BISON_MAJOR" -eq 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 6 ]; then
21+
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 6 ]; then
2222
BISON_FLAGS="$BISON_FLAGS -Dparse.error=detailed"
2323
else
2424
BISON_FLAGS="$BISON_FLAGS -Dparse.error=verbose"
2525
fi
26+
if [ "$BISON_MAJOR" -ge 4 ] || [ "$BISON_MAJOR" -eq 3 ] && [ "$BISON_MINOR" -ge 7 ]; then
27+
BISON_FLAGS="$BISON_FLAGS -Wcounterexamples"
28+
fi
2629

2730
# Replace the arguments to this script ($@) with the ones in $BISON_FLAGS
2831
eval "set -- $BISON_FLAGS"

test/asm/ds-bad.err

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: ds-bad.asm(3):
22
Expected constant expression: 'unknown' is not constant at assembly time
33
warning: ds-bad.asm(4): [-Wtruncation]
4-
Expression must be 8-bit
4+
Expression must be 8-bit; use LOW() to force 8-bit
55
error: Assembly aborted (1 error)!

test/asm/invalid-instructions.asm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,16 @@ SECTION "invalid", ROM0[$10000]
66
ld b, [$4000]
77
bit 8, a
88
rst $40
9+
10+
ld bc, bc
11+
ld de, hl
12+
ld hl, de
13+
14+
ld hl, sp ; no offset!
15+
; ld sp, hl is valid
16+
17+
ld sp, bc
18+
ld bc, sp
19+
20+
ld af, bc
21+
ld bc, af

test/asm/invalid-instructions.err

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,20 @@ error: invalid-instructions.asm(7):
1616
Invalid bit index 8 for BIT
1717
error: invalid-instructions.asm(8):
1818
Invalid address $40 for RST
19-
error: Assembly aborted (8 errors)!
19+
error: invalid-instructions.asm(10):
20+
LD BC, BC is not a valid instruction; use LD B, B and LD C, C
21+
error: invalid-instructions.asm(11):
22+
LD DE, HL is not a valid instruction; use LD D, H and LD E, L
23+
error: invalid-instructions.asm(12):
24+
LD HL, DE is not a valid instruction; use LD H, D and LD L, E
25+
error: invalid-instructions.asm(14):
26+
LD HL, SP is not a valid instruction; use LD HL, SP + 0
27+
error: invalid-instructions.asm(17):
28+
LD SP, BC is not a valid instruction
29+
error: invalid-instructions.asm(18):
30+
syntax error, unexpected sp
31+
error: invalid-instructions.asm(20):
32+
syntax error, unexpected af
33+
error: invalid-instructions.asm(21):
34+
syntax error, unexpected af
35+
error: Assembly aborted (16 errors)!

test/asm/warn-truncation.err

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,64 @@
11
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(23): [-Wtruncation]
2-
Expression must be 8-bit
2+
Expression must be 8-bit; use LOW() to force 8-bit
33
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(24): [-Wtruncation]
4-
Expression must be 8-bit
4+
Expression must be 8-bit; use LOW() to force 8-bit
55
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(25): [-Wtruncation]
66
Expression must be 16-bit
77
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(26): [-Wtruncation]
88
Expression must be 16-bit
99
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(28): [-Wtruncation]
10-
Expression must be 8-bit
10+
Expression must be 8-bit; use LOW() to force 8-bit
1111
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(29): [-Wtruncation]
1212
Expression must be 16-bit
1313
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(30): [-Wtruncation]
14-
Expression must be 8-bit
14+
Expression must be 8-bit; use LOW() to force 8-bit
1515
warning: warn-truncation.asm(35) -> warn-truncation.asm::try(31): [-Wtruncation]
1616
Expression must be 16-bit
1717
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(23): [-Wtruncation]
18-
Expression must be 8-bit
18+
Expression must be 8-bit; use LOW() to force 8-bit
1919
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(24): [-Wtruncation]
20-
Expression must be 8-bit
20+
Expression must be 8-bit; use LOW() to force 8-bit
2121
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(25): [-Wtruncation]
2222
Expression must be 16-bit
2323
warning: warn-truncation.asm(37) -> warn-truncation.asm::try(26): [-Wtruncation]
2424
Expression must be 16-bit
2525
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(23): [-Wtruncation]
26-
Expression must be 8-bit
26+
Expression must be 8-bit; use LOW() to force 8-bit
2727
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(24): [-Wtruncation]
28-
Expression must be 8-bit
28+
Expression must be 8-bit; use LOW() to force 8-bit
2929
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(25): [-Wtruncation]
3030
Expression must be 16-bit
3131
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(26): [-Wtruncation]
3232
Expression must be 16-bit
3333
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(28): [-Wtruncation]
34-
Expression must be 8-bit
34+
Expression must be 8-bit; use LOW() to force 8-bit
3535
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(29): [-Wtruncation]
3636
Expression must be 16-bit
3737
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(30): [-Wtruncation]
38-
Expression must be 8-bit
38+
Expression must be 8-bit; use LOW() to force 8-bit
3939
warning: warn-truncation.asm(38) -> warn-truncation.asm::try(31): [-Wtruncation]
4040
Expression must be 16-bit
4141
error: warn-truncation.asm(39) -> warn-truncation.asm::try(23): [-Werror=truncation]
42-
Expression must be 8-bit
42+
Expression must be 8-bit; use LOW() to force 8-bit
4343
error: warn-truncation.asm(39) -> warn-truncation.asm::try(24): [-Werror=truncation]
44-
Expression must be 8-bit
44+
Expression must be 8-bit; use LOW() to force 8-bit
4545
error: warn-truncation.asm(39) -> warn-truncation.asm::try(25): [-Werror=truncation]
4646
Expression must be 16-bit
4747
error: warn-truncation.asm(39) -> warn-truncation.asm::try(26): [-Werror=truncation]
4848
Expression must be 16-bit
4949
error: warn-truncation.asm(40) -> warn-truncation.asm::try(23): [-Werror=truncation]
50-
Expression must be 8-bit
50+
Expression must be 8-bit; use LOW() to force 8-bit
5151
error: warn-truncation.asm(40) -> warn-truncation.asm::try(24): [-Werror=truncation]
52-
Expression must be 8-bit
52+
Expression must be 8-bit; use LOW() to force 8-bit
5353
error: warn-truncation.asm(40) -> warn-truncation.asm::try(25): [-Werror=truncation]
5454
Expression must be 16-bit
5555
error: warn-truncation.asm(40) -> warn-truncation.asm::try(26): [-Werror=truncation]
5656
Expression must be 16-bit
5757
error: warn-truncation.asm(40) -> warn-truncation.asm::try(28): [-Werror=truncation]
58-
Expression must be 8-bit
58+
Expression must be 8-bit; use LOW() to force 8-bit
5959
error: warn-truncation.asm(40) -> warn-truncation.asm::try(29): [-Werror=truncation]
6060
Expression must be 16-bit
6161
error: warn-truncation.asm(40) -> warn-truncation.asm::try(30): [-Werror=truncation]
62-
Expression must be 8-bit
62+
Expression must be 8-bit; use LOW() to force 8-bit
6363
error: warn-truncation.asm(40) -> warn-truncation.asm::try(31): [-Werror=truncation]
6464
Expression must be 16-bit

0 commit comments

Comments
 (0)