mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-10-10 00:25:06 -04:00
Add support for the {pt} and {pn} branch hint prefixes
Add support for the {pt} and {pn} branch hint prefixes, now when they are no longer orphanned... Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
@@ -220,7 +220,7 @@ static void warn_overflow(int size, const char *prefix, const char *suffix)
|
|||||||
if (!suffix)
|
if (!suffix)
|
||||||
suffix = ++sufsp;
|
suffix = ++sufsp;
|
||||||
|
|
||||||
nasm_warn(ERR_PASS2 | WARN_NUMBER_OVERFLOW,
|
nasm_warn(WARN_NUMBER_OVERFLOW|ERR_PASS2,
|
||||||
"%s%s%s%s%s exceeds bounds",
|
"%s%s%s%s%s exceeds bounds",
|
||||||
prefix, pfxsp, size_name(size), sufsp, suffix);
|
prefix, pfxsp, size_name(size), sufsp, suffix);
|
||||||
}
|
}
|
||||||
@@ -1451,14 +1451,14 @@ static void bad_hle_warn(const insn * ins, uint8_t hleok)
|
|||||||
|
|
||||||
case w_lock:
|
case w_lock:
|
||||||
if (ins->prefixes[PPS_LOCK] != P_LOCK) {
|
if (ins->prefixes[PPS_LOCK] != P_LOCK) {
|
||||||
nasm_warn(WARN_PREFIX_HLE|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_HLE,
|
||||||
"%s with this instruction requires lock",
|
"%s with this instruction requires lock",
|
||||||
prefix_name(rep_pfx));
|
prefix_name(rep_pfx));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case w_inval:
|
case w_inval:
|
||||||
nasm_warn(WARN_PREFIX_HLE|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_HLE,
|
||||||
"%s invalid with this instruction",
|
"%s invalid with this instruction",
|
||||||
prefix_name(rep_pfx));
|
prefix_name(rep_pfx));
|
||||||
break;
|
break;
|
||||||
@@ -1784,7 +1784,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
if (bits != 16 && pfx == P_OSP) {
|
if (bits != 16 && pfx == P_OSP) {
|
||||||
/* Allow osp prefix as is */
|
/* Allow osp prefix as is */
|
||||||
} else if (pfx != P_none && pfx != P_O16) {
|
} else if (pfx != P_none && pfx != P_O16) {
|
||||||
nasm_warn(WARN_PREFIX_OPSIZE|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_OPSIZE,
|
||||||
"invalid operand size prefix %s, must be o16",
|
"invalid operand size prefix %s, must be o16",
|
||||||
prefix_name(pfx));
|
prefix_name(pfx));
|
||||||
} else if (!(opt_opsize & 16)) {
|
} else if (!(opt_opsize & 16)) {
|
||||||
@@ -1805,7 +1805,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
} else if (bits == 16 && pfx == P_OSP) {
|
} else if (bits == 16 && pfx == P_OSP) {
|
||||||
/* Allow osp prefix as is */
|
/* Allow osp prefix as is */
|
||||||
} else if (pfx != P_none && pfx != P_O32) {
|
} else if (pfx != P_none && pfx != P_O32) {
|
||||||
nasm_warn(WARN_PREFIX_OPSIZE|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_OPSIZE,
|
||||||
"invalid operand size prefix %s, must be o32",
|
"invalid operand size prefix %s, must be o32",
|
||||||
prefix_name(pfx));
|
prefix_name(pfx));
|
||||||
} else if (!(opt_opsize & 32)) {
|
} else if (!(opt_opsize & 32)) {
|
||||||
@@ -1839,7 +1839,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
if (!(ins->rex & REX_NW))
|
if (!(ins->rex & REX_NW))
|
||||||
ins->rex |= REX_W;
|
ins->rex |= REX_W;
|
||||||
} else if (pfx != P_none && pfx != P_O64) {
|
} else if (pfx != P_none && pfx != P_O64) {
|
||||||
nasm_warn(WARN_PREFIX_OPSIZE|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_OPSIZE,
|
||||||
"invalid operand size prefix %s, must be o64",
|
"invalid operand size prefix %s, must be o64",
|
||||||
prefix_name(pfx));
|
prefix_name(pfx));
|
||||||
} else if (!(opt_opsize & 64)) {
|
} else if (!(opt_opsize & 64)) {
|
||||||
@@ -2013,7 +2013,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
*! \c{bnd jmp dword}.
|
*! \c{bnd jmp dword}.
|
||||||
*/
|
*/
|
||||||
if (!ins->dummy)
|
if (!ins->dummy)
|
||||||
nasm_warn(WARN_PREFIX_BND|ERR_PASS2 ,
|
nasm_warn(WARN_PREFIX_BND,
|
||||||
"jmp short does not init bnd regs - bnd prefix dropped");
|
"jmp short does not init bnd regs - bnd prefix dropped");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2246,7 +2246,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
*!=lock
|
*!=lock
|
||||||
*! warns about \c{LOCK} prefixes on unlockable instructions.
|
*! warns about \c{LOCK} prefixes on unlockable instructions.
|
||||||
*/
|
*/
|
||||||
nasm_warn(WARN_PREFIX_LOCK_ERROR|ERR_PASS2 , "instruction is not lockable");
|
nasm_warn(WARN_PREFIX_LOCK_ERROR, "instruction is not lockable");
|
||||||
} else if (temp->opcode == I_XCHG) {
|
} else if (temp->opcode == I_XCHG) {
|
||||||
/*!
|
/*!
|
||||||
*!prefix-lock-xchg [on] superfluous \c{LOCK} prefix on \c{XCHG} instruction
|
*!prefix-lock-xchg [on] superfluous \c{LOCK} prefix on \c{XCHG} instruction
|
||||||
@@ -2256,7 +2256,7 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
*! explicitly provided by the user, so this warning indicates that
|
*! explicitly provided by the user, so this warning indicates that
|
||||||
*! suboptimal code is being generated.
|
*! suboptimal code is being generated.
|
||||||
*/
|
*/
|
||||||
nasm_warn(WARN_PREFIX_LOCK_XCHG|ERR_PASS2,
|
nasm_warn(WARN_PREFIX_LOCK_XCHG,
|
||||||
"superfluous LOCK prefix on XCHG instruction");
|
"superfluous LOCK prefix on XCHG instruction");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2272,6 +2272,27 @@ static int64_t calcsize(insn *ins, const struct itemplate * const temp)
|
|||||||
(itemp_has(temp, IF_BND) && !has_prefix(ins, PPS_REP, P_NOBND)))
|
(itemp_has(temp, IF_BND) && !has_prefix(ins, PPS_REP, P_NOBND)))
|
||||||
ins->prefixes[PPS_REP] = P_BND;
|
ins->prefixes[PPS_REP] = P_BND;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Warn on {pt} or {pn} on a nonhintable instruction
|
||||||
|
*/
|
||||||
|
if (ins->prefixes[PPS_SEG] == P_PT || ins->prefixes[PPS_SEG] == P_PN) {
|
||||||
|
if (!itemp_has(temp, IF_JCC_HINT)) {
|
||||||
|
/*!
|
||||||
|
*!prefix-hint-dropped [on] invalid branch hint prefix dropped
|
||||||
|
*! warns that the \c{{PT}} (predict taken) or \c{{PN}}
|
||||||
|
*! (predict not taken) branch prediction hint prefixes
|
||||||
|
*! are specified on an instruction that does not take
|
||||||
|
*! these prefixes. As these prefixes alias the segment
|
||||||
|
*! override prefixes, this may be a very serious error,
|
||||||
|
*! and therefore NASM will not generate these prefixes.
|
||||||
|
*! To force these prefixes to be emitted, use \c{DS} or
|
||||||
|
*! \c{CS}, instead, respectively.
|
||||||
|
*/
|
||||||
|
nasm_warn(WARN_PREFIX_HINT_DROPPED,
|
||||||
|
"invalid branch hint prefix dropped");
|
||||||
|
ins->prefixes[PPS_SEG] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add length of legacy prefixes
|
* Add length of legacy prefixes
|
||||||
@@ -2347,9 +2368,11 @@ static int prefix_byte(enum prefixes pfx, const int bits)
|
|||||||
return 0xF3;
|
return 0xF3;
|
||||||
|
|
||||||
case R_CS:
|
case R_CS:
|
||||||
|
case P_PN:
|
||||||
return 0x2E;
|
return 0x2E;
|
||||||
|
|
||||||
case R_DS:
|
case R_DS:
|
||||||
|
case P_PT:
|
||||||
return 0x3E;
|
return 0x3E;
|
||||||
|
|
||||||
case R_ES:
|
case R_ES:
|
||||||
@@ -2673,7 +2696,7 @@ static void gencode(struct out_data *data, insn *ins)
|
|||||||
nasm_nonfatal("non-absolute expression not permitted "
|
nasm_nonfatal("non-absolute expression not permitted "
|
||||||
"as argument %d", op2);
|
"as argument %d", op2);
|
||||||
else if (opy->offset & ~mask)
|
else if (opy->offset & ~mask)
|
||||||
nasm_warn(ERR_PASS2|WARN_NUMBER_OVERFLOW,
|
nasm_warn(WARN_NUMBER_OVERFLOW,
|
||||||
"is4 argument exceeds bounds");
|
"is4 argument exceeds bounds");
|
||||||
c = opy->offset & mask;
|
c = opy->offset & mask;
|
||||||
goto emit_is4;
|
goto emit_is4;
|
||||||
@@ -2776,7 +2799,7 @@ static void gencode(struct out_data *data, insn *ins)
|
|||||||
* If this wasn't explicitly byte-sized, warn as though we
|
* If this wasn't explicitly byte-sized, warn as though we
|
||||||
* had fallen through to the imm16/32/64 case.
|
* had fallen through to the imm16/32/64 case.
|
||||||
*/
|
*/
|
||||||
nasm_warn(ERR_PASS2|WARN_NUMBER_OVERFLOW,
|
nasm_warn(WARN_NUMBER_OVERFLOW|ERR_PASS2,
|
||||||
"%s exceeds bounds",
|
"%s exceeds bounds",
|
||||||
(opx->type & BITS8) ? "signed byte" :
|
(opx->type & BITS8) ? "signed byte" :
|
||||||
s == 16 ? "word" :
|
s == 16 ? "word" :
|
||||||
@@ -2797,7 +2820,7 @@ static void gencode(struct out_data *data, insn *ins)
|
|||||||
emit_rex(data, ins);
|
emit_rex(data, ins);
|
||||||
if (absolute_op(opx)) {
|
if (absolute_op(opx)) {
|
||||||
if (!is_hint_nop(opx->offset)) {
|
if (!is_hint_nop(opx->offset)) {
|
||||||
nasm_warn(ERR_PASS2, "not a valid hint-NOP opcode (0D, 18-1F)");
|
nasm_warn(0, "not a valid hint-NOP opcode (0D, 18-1F)");
|
||||||
}
|
}
|
||||||
out_rawbyte(data, opx->offset);
|
out_rawbyte(data, opx->offset);
|
||||||
} else {
|
} else {
|
||||||
@@ -3629,7 +3652,7 @@ static int process_ea(operand *input, int rfield, opflags_t rflags,
|
|||||||
*/
|
*/
|
||||||
if (input->segment == NO_SEG ||
|
if (input->segment == NO_SEG ||
|
||||||
(input->opflags & OPFLAG_RELATIVE)) {
|
(input->opflags & OPFLAG_RELATIVE)) {
|
||||||
nasm_warn(WARN_EA_ABSOLUTE|ERR_PASS2,
|
nasm_warn(WARN_EA_ABSOLUTE,
|
||||||
"absolute address can not be RIP-relative");
|
"absolute address can not be RIP-relative");
|
||||||
input->type &= ~IP_REL;
|
input->type &= ~IP_REL;
|
||||||
input->type |= MEMORY;
|
input->type |= MEMORY;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
## --------------------------------------------------------------------------
|
## --------------------------------------------------------------------------
|
||||||
##
|
##
|
||||||
## Copyright 1996-2021 The NASM Authors - All Rights Reserved
|
## Copyright 1996-2025 The NASM Authors - All Rights Reserved
|
||||||
## See the file AUTHORS included with the NASM distribution for
|
## See the file AUTHORS included with the NASM distribution for
|
||||||
## the specific copyright holders.
|
## the specific copyright holders.
|
||||||
##
|
##
|
||||||
@@ -89,6 +89,10 @@ nf
|
|||||||
% TOKEN_PREFIX, PPS_ZU, TFLAG_BRC, P_*
|
% TOKEN_PREFIX, PPS_ZU, TFLAG_BRC, P_*
|
||||||
zu
|
zu
|
||||||
|
|
||||||
|
% TOKEN_PREFIX, PPS_SEG, TFLAG_BRC, P_*
|
||||||
|
pt
|
||||||
|
pn
|
||||||
|
|
||||||
% TOKEN_SIZE, SIZE_*, 0, S_*
|
% TOKEN_SIZE, SIZE_*, 0, S_*
|
||||||
byte
|
byte
|
||||||
word
|
word
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* ----------------------------------------------------------------------- *
|
/* ----------------------------------------------------------------------- *
|
||||||
*
|
*
|
||||||
* Copyright 1996-2024 The NASM Authors - All Rights Reserved
|
* Copyright 1996-2025 The NASM Authors - All Rights Reserved
|
||||||
* See the file AUTHORS included with the NASM distribution for
|
* See the file AUTHORS included with the NASM distribution for
|
||||||
* the specific copyright holders.
|
* the specific copyright holders.
|
||||||
*
|
*
|
||||||
@@ -67,7 +67,8 @@ const char *prefix_name(int token)
|
|||||||
"a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
|
"a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
|
||||||
"rep", "repe", "repne", "repnz", "repz", "wait",
|
"rep", "repe", "repne", "repnz", "repz", "wait",
|
||||||
"xacquire", "xrelease", "bnd", "nobnd", "{rex}", "{rex2}",
|
"xacquire", "xrelease", "bnd", "nobnd", "{rex}", "{rex2}",
|
||||||
"{evex}", "{vex}", "{vex3}", "{vex2}", "{nf}", "{zu}"
|
"{evex}", "{vex}", "{vex3}", "{vex2}", "{nf}", "{zu}",
|
||||||
|
"{pt}", "{pn}"
|
||||||
};
|
};
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
@@ -1226,9 +1226,16 @@ static int matches(const uint8_t *data, const struct prefix_info *prefix,
|
|||||||
return 0;
|
return 0;
|
||||||
ins->prefixes[PPS_OSIZE] = pfx;
|
ins->prefixes[PPS_OSIZE] = pfx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (itemp_has(t, IF_JCC_HINT)) {
|
||||||
|
if ((prefix->seg & ~0x10) == 0x2e)
|
||||||
|
ins->prefixes[PPS_SEG] = prefix->seg & 0x10 ? P_PT : P_PN;
|
||||||
|
}
|
||||||
|
|
||||||
if (!a_used) {
|
if (!a_used) {
|
||||||
/* Emit segment override prefix explicitly */
|
/* Emit any possible segment override prefix explicitly */
|
||||||
ins->prefixes[PPS_SEG] = prefix->segover;
|
if (!ins->prefixes[PPS_SEG])
|
||||||
|
ins->prefixes[PPS_SEG] = prefix->segover;
|
||||||
|
|
||||||
if (prefix->asp) {
|
if (prefix->asp) {
|
||||||
if (ins->prefixes[PPS_ASIZE])
|
if (ins->prefixes[PPS_ASIZE])
|
||||||
|
@@ -684,6 +684,8 @@ enum prefixes { /* instruction prefixes */
|
|||||||
P_VEX2,
|
P_VEX2,
|
||||||
P_NF,
|
P_NF,
|
||||||
P_ZU,
|
P_ZU,
|
||||||
|
P_PT,
|
||||||
|
P_PN,
|
||||||
PREFIX_ENUM_LIMIT
|
PREFIX_ENUM_LIMIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
12
test/jcchint.asm
Normal file
12
test/jcchint.asm
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
bits 64
|
||||||
|
here:
|
||||||
|
cs jz there
|
||||||
|
ds jz there
|
||||||
|
{pt} jz there
|
||||||
|
{pn} jz there
|
||||||
|
es jz there
|
||||||
|
ss jz there
|
||||||
|
|
||||||
|
there:
|
||||||
|
{pt} jmp there
|
||||||
|
{pn} jmp there
|
Reference in New Issue
Block a user