Skip to content

Commit a7457e6

Browse files
author
H. Peter Anvin (Intel)
committed
Fix matching of branch instructions with prefixes and sizes
Matching of branch instructions with prefixes and sizes is, to say the least, tricky. Work through it, and add a new macro to help. Fixes: #144 Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
1 parent 2c71e67 commit a7457e6

22 files changed

+6877
-102
lines changed

asm/assemble.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,28 +1400,9 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
14001400
ins->itemp = temp; /* Instruction template */
14011401
eat = EA_SCALAR; /* Expect a scalar EA */
14021402

1403-
/* Default operand size */
1403+
/* Default operand size (prefixes are handled in the byte code) */
14041404
ins->op_size = bits != 16 ? 32 : 16;
14051405

1406-
if (bits == 64) {
1407-
if (ins->prefixes[PPS_ASIZE] == P_A16) {
1408-
nasm_warn(WARN_PREFIX_BADMODE_A16,
1409-
"a64 prefix invalid in 64-bit mode");
1410-
ins->prefixes[PPS_ASIZE] = 0;
1411-
}
1412-
} else {
1413-
if (ins->prefixes[PPS_OSIZE] == P_O64) {
1414-
nasm_warn(WARN_PREFIX_BADMODE_O64,
1415-
"o64 prefix invalid in %d-bit mode", bits);
1416-
ins->prefixes[PPS_OSIZE] = P_none;
1417-
}
1418-
if (ins->prefixes[PPS_ASIZE] == P_A64) {
1419-
nasm_warn(WARN_PREFIX_BADMODE_A64,
1420-
"a64 prefix invalid in %d-bit mode", bits);
1421-
ins->prefixes[PPS_ASIZE] = P_none;
1422-
}
1423-
}
1424-
14251406
nasm_zero(need_pfx);
14261407

14271408
while (*codes) {
@@ -3061,7 +3042,7 @@ static enum match_result matches(const struct itemplate * const itemp,
30613042

30623043
/* "Default" operand size (from mode and prefixes only) */
30633044
op_size = ins->op_size;
3064-
if (itemp_has(itemp, IF_NWSIZE) && op_size == 32) {
3045+
if (bits == 64 && itemp_has(itemp, IF_NWSIZE) && op_size == 32) {
30653046
/* If this is an nw instruction, default to 64 bits in 64-bit mode */
30663047
op_size = bits;
30673048
}
@@ -3101,18 +3082,23 @@ static enum match_result matches(const struct itemplate * const itemp,
31013082

31023083
/* Handle implied SHORT or NEAR */
31033084
if (unlikely(ttype & (NEAR|SHORT))) {
3085+
/* Treat BYTE as an alias for SHORT, ignoring size */
3086+
if (isize[i] == BITS8) {
3087+
itype[i] |= SHORT;
3088+
isize[i] = 0;
3089+
}
3090+
/* An explicit SHORT or BITS8 cancels NEAR; are synonyms */
3091+
if (itype[i] & SHORT) {
3092+
itype[i] &= ~NEAR;
3093+
}
3094+
/* NEAR is implicit unless otherwise specified */
3095+
if (!(itype[i] & (FAR|SHORT))) {
3096+
itype[i] |= ttype & NEAR;
3097+
}
31043098
if ((ttype & (NEAR|SHORT)) == (NEAR|SHORT)) {
3105-
/* Only a short form exists; allow both NEAR and SHORT */
3099+
/* Only a short form exists; this is specially coded */
31063100
if (!(itype[i] & (FAR|ABS)))
31073101
itype[i] |= NEAR|SHORT;
3108-
} else if ((itype[i] & SHORT) || isize[i] == BITS8) {
3109-
/* An explicit SHORT or BITS8 cancel NEAR; are synonyms */
3110-
itype[i] &= ~NEAR;
3111-
if (!isize[i])
3112-
isize[i] = BITS8;
3113-
} else if (!(itype[i] & (FAR|ABS|SHORT))) {
3114-
/* NEAR is implicit unless otherwise specified */
3115-
itype[i] |= ttype & NEAR;
31163102
}
31173103
}
31183104

asm/parser.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,8 +964,10 @@ insn *parse_line(char *buffer, insn *result, const int bits)
964964
while (i == TOKEN_SPECIAL || i == TOKEN_SIZE) {
965965
switch (tokval.t_integer) {
966966
case S_BYTE:
967-
if (!setsize) /* we want to use only the first */
967+
if (!setsize) { /* we want to use only the first */
968+
result->opt |= OPTIM_NO_Jcc_RELAX | OPTIM_NO_JMP_RELAX;
968969
op->type |= BITS8;
970+
}
969971
setsize = 1;
970972
break;
971973
case S_WORD:
@@ -1014,9 +1016,12 @@ insn *parse_line(char *buffer, insn *result, const int bits)
10141016
op->type |= FAR;
10151017
break;
10161018
case S_NEAR:
1019+
/* This is not legacy behavior, even if it perhaps should be */
1020+
/* result->opt |= OPTIM_NO_Jcc_RELAX | OPTIM_NO_JMP_RELAX; */
10171021
op->type |= NEAR;
10181022
break;
10191023
case S_SHORT:
1024+
result->opt |= OPTIM_NO_Jcc_RELAX | OPTIM_NO_JMP_RELAX;
10201025
op->type |= SHORT;
10211026
break;
10221027
case S_ABS:

asm/warnings.dat

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,20 +259,11 @@ pragma-unknown [off] unknown \c{%pragma} facility or directive
259259
Warns about an unknown \c{%pragma} directive.
260260
This is not yet implemented for most cases.
261261

262-
prefix-badmode-a64 [err] a64 prefix invalid in 16/32-bit mode
263-
Warns that an \c{a64} prefix was specified in 16- or 32-bit
264-
mode. If the error is demoted to a warning or suppressed, the
265-
prefix is ignored by the assembler.
266-
267262
prefix-badmode-o64 [err] o64 prefix invalid in 16/32-bit mode
268263
Warns that an \c{a64} prefix was specified in 16- or 32-bit
269264
mode. If the error is demoted to a warning or suppressed, the
270-
prefix is ignored by the assembler.
271-
272-
prefix-badmode-a16 [err] a16 prefix invalid in 64-bit mode
273-
Warns that an \c{a16} prefix was specified in 64-bit mode.
274-
If the error is demoted to a warning or suppressed, the
275-
prefix is ignored by the assembler.
265+
prefix is ignored by the assembler, but is likely to trigger
266+
futher errors.
276267

277268
prefix-bnd [on] invalid \c{BND} prefix
278269
=bnd

doc/changes.src

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,9 @@ It is the production version of NASM since 2025.
5454
\b Hopefully fix building with OpenWatcom.
5555

5656
\b Generate a warning, promoted to error by default, on the use of
57-
\c{a64} or \c{o64} prefixes in 16- or 32-bit mode or \c{a16}
58-
prefixes in 64-bit mode. Those prefixes are not encodable; if
59-
demoted to a warning or suppressed the prefix is ignored, but
60-
likely will generate additional, harder to debug, error messages.
57+
\c{o64} prefixes in 16- or 32-bit mode. If demoted to a warning or
58+
suppressed the prefix is ignored, but likely will trigger
59+
subsequent, harder to debug, error messages.
6160

6261

6362
\S{cl-3.00} Version 3.00

0 commit comments

Comments
 (0)