0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-11-08 23:27:15 -05:00

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: https://github.com/netwide-assembler/nasm/issues/144
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel)
2025-10-10 13:03:33 -07:00
parent 2c71e67762
commit a7457e66cf
22 changed files with 6875 additions and 100 deletions

View File

@@ -1400,28 +1400,9 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
ins->itemp = temp; /* Instruction template */
eat = EA_SCALAR; /* Expect a scalar EA */
/* Default operand size */
/* Default operand size (prefixes are handled in the byte code) */
ins->op_size = bits != 16 ? 32 : 16;
if (bits == 64) {
if (ins->prefixes[PPS_ASIZE] == P_A16) {
nasm_warn(WARN_PREFIX_BADMODE_A16,
"a64 prefix invalid in 64-bit mode");
ins->prefixes[PPS_ASIZE] = 0;
}
} else {
if (ins->prefixes[PPS_OSIZE] == P_O64) {
nasm_warn(WARN_PREFIX_BADMODE_O64,
"o64 prefix invalid in %d-bit mode", bits);
ins->prefixes[PPS_OSIZE] = P_none;
}
if (ins->prefixes[PPS_ASIZE] == P_A64) {
nasm_warn(WARN_PREFIX_BADMODE_A64,
"a64 prefix invalid in %d-bit mode", bits);
ins->prefixes[PPS_ASIZE] = P_none;
}
}
nasm_zero(need_pfx);
while (*codes) {
@@ -3061,7 +3042,7 @@ static enum match_result matches(const struct itemplate * const itemp,
/* "Default" operand size (from mode and prefixes only) */
op_size = ins->op_size;
if (itemp_has(itemp, IF_NWSIZE) && op_size == 32) {
if (bits == 64 && itemp_has(itemp, IF_NWSIZE) && op_size == 32) {
/* If this is an nw instruction, default to 64 bits in 64-bit mode */
op_size = bits;
}
@@ -3101,18 +3082,23 @@ static enum match_result matches(const struct itemplate * const itemp,
/* Handle implied SHORT or NEAR */
if (unlikely(ttype & (NEAR|SHORT))) {
/* Treat BYTE as an alias for SHORT, ignoring size */
if (isize[i] == BITS8) {
itype[i] |= SHORT;
isize[i] = 0;
}
/* An explicit SHORT or BITS8 cancels NEAR; are synonyms */
if (itype[i] & SHORT) {
itype[i] &= ~NEAR;
}
/* NEAR is implicit unless otherwise specified */
if (!(itype[i] & (FAR|SHORT))) {
itype[i] |= ttype & NEAR;
}
if ((ttype & (NEAR|SHORT)) == (NEAR|SHORT)) {
/* Only a short form exists; allow both NEAR and SHORT */
/* Only a short form exists; this is specially coded */
if (!(itype[i] & (FAR|ABS)))
itype[i] |= NEAR|SHORT;
} else if ((itype[i] & SHORT) || isize[i] == BITS8) {
/* An explicit SHORT or BITS8 cancel NEAR; are synonyms */
itype[i] &= ~NEAR;
if (!isize[i])
isize[i] = BITS8;
} else if (!(itype[i] & (FAR|ABS|SHORT))) {
/* NEAR is implicit unless otherwise specified */
itype[i] |= ttype & NEAR;
}
}