HLE: Implement the basic mechanism for XACQUIRE/XRELEASE
authorH. Peter Anvin <hpa@zytor.com>
Sat, 25 Feb 2012 05:51:46 +0000 (21:51 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Sat, 25 Feb 2012 05:57:17 +0000 (21:57 -0800)
This implements the mechanism for XACQUIRE/XRELEASE.  It does not
include the necessary annotations in insns.dat.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
assemble.c
disasm.c
insns.pl
nasm.h
nasmlib.c
parser.c
tokens.dat

index 691e792..06fba53 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2011 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2012 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -97,6 +97,9 @@
  *
  * t = 0 for VEX (C4/C5), t = 1 for XOP (8F).
  *
+ * \271                 - instruction takes XRELEASE (F3) with or without lock
+ * \272                 - instruction takes XACQUIRE/XRELEASE with or without lock
+ * \273                 - instruction takes XACQUIRE/XRELEASE with lock only
  * \274..\277    - a signed byte immediate operand, from operand 0..3,
  *                 which is to be extended to the operand size.
  * \310          - indicates fixed 16-bit address size, i.e. optional 0x67.
@@ -507,11 +510,13 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
                         break;
                     case P_REPNE:
                     case P_REPNZ:
+                    case P_XACQUIRE:
                         c = 0xF2;
                         break;
                     case P_REPE:
                     case P_REPZ:
                     case P_REP:
+                    case P_XRELEASE:
                         c = 0xF3;
                         break;
                     case R_CS:
@@ -787,6 +792,41 @@ static bool is_sbyte32(operand *o)
     return v >= -128 && v <= 127;
 }
 
+static void bad_hle_warn(const insn * ins, uint8_t hleok)
+{
+    enum prefixes rep_pfx = ins->prefixes[PPS_REP];
+    enum whatwarn { w_none, w_lock, w_inval };
+    static const enum whatwarn warn[2][4] =
+    {
+        { w_inval, w_inval, w_none, w_lock }, /* XACQUIRE */
+        { w_inval, w_none,  w_none, w_lock }, /* XRELEASE */
+    };
+    unsigned int n;
+
+    n = (unsigned int)rep_pfx - P_XACQUIRE;
+    if (n > 1)
+        return;                 /* Not XACQUIRE/XRELEASE */
+
+    switch (warn[n][hleok]) {
+    case w_none:
+        break;
+
+    case w_lock:
+        if (ins->prefixes[PPS_LOCK] != P_LOCK) {
+            errfunc(ERR_WARNING | ERR_PASS2,
+                    "%s with this instruction requires lock",
+                    prefix_name(rep_pfx));
+        }
+        break;
+
+    case w_inval:
+        errfunc(ERR_WARNING | ERR_PASS2,
+                "%s invalid with this instruction",
+                prefix_name(rep_pfx));
+        break;
+    }
+}
+
 /* Common construct */
 #define case4(x) case (x): case (x)+1: case (x)+2: case (x)+3
 
@@ -800,6 +840,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
     struct operand *opx;
     uint8_t opex = 0;
     enum ea_type eat;
+    uint8_t hleok = 0;
 
     ins->rex = 0;               /* Ensure REX is reset */
     eat = EA_SCALAR;            /* Expect a scalar EA */
@@ -939,6 +980,12 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             ins->vex_wlp = *codes++;
             break;
 
+        case 0271:
+        case 0272:
+        case 0273:
+            hleok = c & 3;
+            break;
+
         case4(0274):
             length++;
             break;
@@ -1190,6 +1237,8 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             return -1;
         }
     }
+    
+    bad_hle_warn(ins, hleok);
 
     return length;
 }
index 9bedcc7..c2a21fd 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -703,6 +703,27 @@ static int matches(const struct itemplate *t, uint8_t *data,
            break;
        }
 
+        case 0271:
+            if (prefix->rep == 0xF3)
+                drep = P_XRELEASE;
+            break;
+
+        case 0272:
+            if (prefix->rep == 0xF2)
+                drep = P_XACQUIRE;
+            else if (prefix->rep == 0xF3)
+                drep = P_XRELEASE;
+            break;
+
+        case 0273:
+            if (prefix->lock == 0xF0) {
+                if (prefix->rep == 0xF2)
+                    drep = P_XACQUIRE;
+                else if (prefix->rep == 0xF3)
+                    drep = P_XRELEASE;
+            }
+            break;
+
        case 0310:
             if (asize != 16)
                 return false;
index d9a968b..d5645e0 100755 (executable)
--- a/insns.pl
+++ b/insns.pl
@@ -744,6 +744,12 @@ sub byte_code_compile($$) {
             push(@codes, 0325);
        } elsif ($op eq 'wait') { # Needs a wait prefix
            push(@codes, 0341);
+       } elsif ($op eq 'hlexr') {
+           push(@codes, 0271);
+       } elsif ($op eq 'hlenl') {
+           push(@codes, 0272);
+       } elsif ($op eq 'hle') {
+           push(@codes, 0273);
         } elsif ($op eq 'vsibx' || $op eq 'vm32x' || $op eq 'vm64x') {
             # This instruction takes XMM VSIB
             push(@codes, 0374);
diff --git a/nasm.h b/nasm.h
index 23def29..46e4c05 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *   
- *   Copyright 1996-2011 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2012 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -473,7 +473,7 @@ enum prefixes { /* instruction prefixes */
     P_A16 = PREFIX_ENUM_START, P_A32, P_A64, P_ASP,
     P_LOCK, P_O16, P_O32, P_O64, P_OSP,
     P_REP, P_REPE, P_REPNE, P_REPNZ, P_REPZ, P_TIMES,
-    P_WAIT,
+    P_WAIT, P_XACQUIRE, P_XRELEASE,
     PREFIX_ENUM_LIMIT
 };
 
index e35d99e..254c84c 100644 (file)
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *   
- *   Copyright 1996-2010 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2012 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -563,7 +563,8 @@ void standard_extension(char *inname, char *outname, char *extension)
  */
 static const char *prefix_names[] = {
     "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
-    "rep", "repe", "repne", "repnz", "repz", "times", "wait"
+    "rep", "repe", "repne", "repnz", "repz", "times", "wait",
+    "xacquire", "xrelease"
 };
 
 const char *prefix_name(int token)
index 3a592fe..aa2df24 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -87,6 +87,8 @@ static int prefix_slot(int prefix)
     case P_REPZ:
     case P_REPNE:
     case P_REPNZ:
+    case P_XACQUIRE:
+    case P_XRELEASE:
         return PPS_REP;
     case P_O16:
     case P_O32:
index c7d3b97..25179fa 100644 (file)
@@ -1,6 +1,6 @@
 ## --------------------------------------------------------------------------
 ##   
-##   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+##   Copyright 1996-2012 The NASM Authors - All Rights Reserved
 ##   See the file AUTHORS included with the NASM distribution for
 ##   the specific copyright holders.
 ##
@@ -52,6 +52,8 @@ repnz
 repz
 times
 wait
+xacquire
+xrelease
 
 % TOKEN_SPECIAL, 0, S_*
 abs