summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2014-05-21 08:19:16 -0700
committerH. Peter Anvin <hpa@zytor.com>2014-05-21 08:24:21 -0700
commit0a9250c2ab32028dfdca6578655882b4be6a5c04 (patch)
treea1a48e04b96a2060c8ef4eb464c0fedd080ee510
parent13558c1e7cb2a1a2ea1b1c13ff554063de8afaf0 (diff)
downloadnasm-0a9250c2ab32028dfdca6578655882b4be6a5c04.tar.gz
nasm-0a9250c2ab32028dfdca6578655882b4be6a5c04.tar.bz2
nasm-0a9250c2ab32028dfdca6578655882b4be6a5c04.zip
BR 3392279: Fix duplicated REX prefixes
The fix for BR 3392278: aa29b1d93f5a assemble.c: Don't drop rex prefix from instruction itself ... would cause multiple REX prefixes to be emitted for some instructions. Create a new flag to indicate that REX has already been emitted, which can be cleared for each instance of an instruction. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--assemble.c9
-rw-r--r--nasm.h3
-rw-r--r--test/times.asm8
3 files changed, 17 insertions, 3 deletions
diff --git a/assemble.c b/assemble.c
index e9cd70f..ff3cea7 100644
--- a/assemble.c
+++ b/assemble.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2013 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2014 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -1365,9 +1365,12 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
static inline unsigned int emit_rex(insn *ins, int32_t segment, int64_t offset, int bits)
{
if (bits == 64) {
- if ((ins->rex & REX_REAL) && !(ins->rex & (REX_V | REX_EV))) {
+ if ((ins->rex & REX_REAL) &&
+ !(ins->rex & (REX_V | REX_EV)) &&
+ !ins->rex_done) {
int rex = (ins->rex & REX_REAL) | REX_P;
out(offset, segment, &rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
+ ins->rex_done = true;
return 1;
}
}
@@ -1389,6 +1392,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
uint8_t opex = 0;
enum ea_type eat = EA_SCALAR;
+ ins->rex_done = false;
+
while (*codes) {
c = *codes++;
op1 = (c & 3) + ((opex & 1) << 2);
diff --git a/nasm.h b/nasm.h
index 18de37c..666d749 100644
--- a/nasm.h
+++ b/nasm.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2013 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2014 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -702,6 +702,7 @@ typedef struct insn { /* an instruction itself */
int eops_float; /* true if DD and floating */
int32_t times; /* repeat count (TIMES prefix) */
bool forw_ref; /* is there a forward reference? */
+ bool rex_done; /* REX prefix emitted? */
int rex; /* Special REX Prefix */
int vexreg; /* Register encoded in VEX prefix */
int vex_cm; /* Class and M field for VEX prefix */
diff --git a/test/times.asm b/test/times.asm
new file mode 100644
index 0000000..a8e3d58
--- /dev/null
+++ b/test/times.asm
@@ -0,0 +1,8 @@
+ bits 64
+
+; Broken per BR 3392278
+ times 4 paddd xmm8, xmm11
+
+; Broken per BR 3392279
+ bswap r12d
+ times 4 bswap r12d