<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[194045] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/194045">194045</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-12-14 11:54:15 -0800 (Mon, 14 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Air: Support Architecture-specific forms and Opcodes
https://bugs.webkit.org/show_bug.cgi?id=151736

Reviewed by Benjamin Poulain.

This adds really awesome architecture selection to the AirOpcode.opcodes file. If an opcode or
opcode form is unavailable on some architecture, you can still mention its name in C++ code (it'll
still be a member of the enum) but isValidForm() and all other reflective queries will tell you
that it doesn't exist. This will make the instruction selector steer clear of it, and it will
also ensure that the spiller doesn't try to use any unavailable architecture-specific address
forms.

The new capability is documented extensively in a comment in AirOpcode.opcodes.

* b3/air/AirOpcode.opcodes:
* b3/air/opcode_generator.rb:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirOpcodeopcodes">trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airopcode_generatorrb">trunk/Source/JavaScriptCore/b3/air/opcode_generator.rb</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194044 => 194045)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-14 19:53:04 UTC (rev 194044)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-14 19:54:15 UTC (rev 194045)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2015-12-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air: Support Architecture-specific forms and Opcodes
+        https://bugs.webkit.org/show_bug.cgi?id=151736
+
+        Reviewed by Benjamin Poulain.
+
+        This adds really awesome architecture selection to the AirOpcode.opcodes file. If an opcode or
+        opcode form is unavailable on some architecture, you can still mention its name in C++ code (it'll
+        still be a member of the enum) but isValidForm() and all other reflective queries will tell you
+        that it doesn't exist. This will make the instruction selector steer clear of it, and it will
+        also ensure that the spiller doesn't try to use any unavailable architecture-specific address
+        forms.
+
+        The new capability is documented extensively in a comment in AirOpcode.opcodes.
+
+        * b3/air/AirOpcode.opcodes:
+        * b3/air/opcode_generator.rb:
+
</ins><span class="cx"> 2015-12-14  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Misc. small fixes in snippet related code.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirOpcodeopcodes"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes (194044 => 194045)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-14 19:53:04 UTC (rev 194044)
+++ trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes        2015-12-14 19:54:15 UTC (rev 194045)
</span><span class="lines">@@ -53,6 +53,50 @@
</span><span class="cx"> #     Addr, Tmp
</span><span class="cx"> #
</span><span class="cx"> # I.e. a two-form instruction that uses a GPR or an int immediate and uses+defs a float register.
</span><ins>+#
+# Any opcode or opcode form can be preceded with an architecture list, which restricts the opcode to the
+# union of those architectures. For example, if this is the only overload of the opcode, then it makes the
+# opcode only available on x86_64:
+#
+# x86_64: Fuzz UD:G, D:G
+#     Tmp, Tmp
+#     Tmp, Addr
+#
+# But this only restricts the two-operand form, the other form is allowed on all architectures:
+#
+# x86_64: Fuzz UD:G, D:G
+#     Tmp, Tmp
+#     Tmp, Addr
+# Fuzz UD:G, D:G, U:F
+#     Tmp, Tmp, Tmp
+#     Tmp, Addr, Tmp
+#
+# And you can also restrict individual forms:
+#
+# Thingy UD:G, D:G
+#     Tmp, Tmp
+#     arm64: Tmp, Addr
+#
+# Additionally, you can have an intersection between the architectures of the opcode overload and the
+# form. In this example, the version that takes an address is only available on armv7 while the other
+# versions are available on armv7 or x86_64:
+#
+# x86_64 armv7: Buzz U:G, UD:F
+#     Tmp, Tmp
+#     Imm, Tmp
+#     armv7: Addr, Tmp
+#
+# Finally, you can specify architectures using helpful architecture groups. Here are all of the
+# architecture keywords that we support:
+#
+# x86: means x86-32 or x86-64.
+# x86_32: means just x86-32.
+# x86_64: means just x86-64.
+# arm: means armv7 or arm64.
+# armv7: means just armv7.
+# arm64: means just arm64.
+# 32: means x86-32 or armv7.
+# 64: means x86-64 or arm64.
</ins><span class="cx"> 
</span><span class="cx"> # Note that the opcodes here have a leading capital (Add32) but must correspond to MacroAssembler
</span><span class="cx"> # API that has a leading lower-case (add32).
</span><span class="lines">@@ -61,99 +105,99 @@
</span><span class="cx"> 
</span><span class="cx"> Add32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><del>-    Imm, Addr
</del><ins>+    x86: Imm, Addr
</ins><span class="cx">     Imm, Tmp
</span><del>-    Addr, Tmp
-    Tmp, Addr
</del><ins>+    x86: Addr, Tmp
+    x86: Tmp, Addr
</ins><span class="cx"> 
</span><span class="cx"> Add32 U:G, U:G, D:G
</span><span class="cx">     Imm, Tmp, Tmp
</span><span class="cx">     Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><del>-Add64 U:G, UD:G
</del><ins>+64: Add64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><del>-    Imm, Addr
</del><ins>+    x86: Imm, Addr
</ins><span class="cx">     Imm, Tmp
</span><del>-    Addr, Tmp
-    Tmp, Addr
</del><ins>+    x86: Addr, Tmp
+    x86: Tmp, Addr
</ins><span class="cx"> 
</span><del>-Add64 U:G, U:G, D:G
</del><ins>+64: Add64 U:G, U:G, D:G
</ins><span class="cx">     Imm, Tmp, Tmp
</span><span class="cx">     Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> AddDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> AddFloat U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> Sub32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><del>-    Imm, Addr
</del><ins>+    x86: Imm, Addr
</ins><span class="cx">     Imm, Tmp
</span><del>-    Addr, Tmp
-    Tmp, Addr
</del><ins>+    x86: Addr, Tmp
+    x86: Tmp, Addr
</ins><span class="cx"> 
</span><del>-Sub64 U:G, UD:G
</del><ins>+64: Sub64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><del>-    Imm, Addr
</del><ins>+    x86: Imm, Addr
</ins><span class="cx">     Imm, Tmp
</span><del>-    Addr, Tmp
-    Tmp, Addr
</del><ins>+    x86: Addr, Tmp
+    x86: Tmp, Addr
</ins><span class="cx"> 
</span><span class="cx"> SubDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> SubFloat U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> Neg32 UD:G
</span><span class="cx">     Tmp
</span><span class="cx">     Addr
</span><span class="cx"> 
</span><del>-Neg64 UD:G
</del><ins>+64: Neg64 UD:G
</ins><span class="cx">     Tmp
</span><span class="cx"> 
</span><span class="cx"> Mul32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> Mul32 U:G, U:G, D:G
</span><span class="cx">     Imm, Tmp, Tmp
</span><span class="cx"> 
</span><del>-Mul64 U:G, UD:G
</del><ins>+64: Mul64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> MulDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> MulFloat U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> DivDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> DivFloat U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><del>-X86ConvertToDoubleWord32 U:G, D:G
</del><ins>+x86: X86ConvertToDoubleWord32 U:G, D:G
</ins><span class="cx">     Tmp*, Tmp*
</span><span class="cx"> 
</span><del>-X86ConvertToQuadWord64 U:G, D:G
</del><ins>+x86_64: X86ConvertToQuadWord64 U:G, D:G
</ins><span class="cx">     Tmp*, Tmp*
</span><span class="cx"> 
</span><del>-X86Div32 UD:G, UD:G, U:G
</del><ins>+x86: X86Div32 UD:G, UD:G, U:G
</ins><span class="cx">     Tmp*, Tmp*, Tmp
</span><span class="cx"> 
</span><del>-X86Div64 UD:G, UD:G, U:G
</del><ins>+x86_64: X86Div64 UD:G, UD:G, U:G
</ins><span class="cx">     Tmp*, Tmp*, Tmp
</span><span class="cx"> 
</span><span class="cx"> Lea UA:G, D:G
</span><span class="lines">@@ -162,11 +206,11 @@
</span><span class="cx"> And32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><del>-    Tmp, Addr
-    Addr, Tmp
-    Imm, Addr
</del><ins>+    x86: Tmp, Addr
+    x86: Addr, Tmp
+    x86: Imm, Addr
</ins><span class="cx"> 
</span><del>-And64 U:G, UD:G
</del><ins>+64: And64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -180,7 +224,7 @@
</span><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><del>-Lshift64 U:G, UD:G
</del><ins>+64: Lshift64 U:G, UD:G
</ins><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -188,7 +232,7 @@
</span><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><del>-Rshift64 U:G, UD:G
</del><ins>+64: Rshift64 U:G, UD:G
</ins><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -196,71 +240,71 @@
</span><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><del>-Urshift64 U:G, UD:G
</del><ins>+64: Urshift64 U:G, UD:G
</ins><span class="cx">     Tmp*, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="cx"> Or32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><del>-    Tmp, Addr
-    Addr, Tmp
-    Imm, Addr
</del><ins>+    x86: Tmp, Addr
+    x86: Addr, Tmp
+    x86: Imm, Addr
</ins><span class="cx"> 
</span><del>-Or64 U:G, UD:G
</del><ins>+64: Or64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="cx"> Xor32 U:G, UD:G
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Imm, Tmp
</span><del>-    Tmp, Addr
-    Addr, Tmp
-    Imm, Addr
</del><ins>+    x86: Tmp, Addr
+    x86: Addr, Tmp
+    x86: Imm, Addr
</ins><span class="cx"> 
</span><del>-Xor64 U:G, UD:G
</del><ins>+64: Xor64 U:G, UD:G
</ins><span class="cx">     Tmp, Tmp
</span><del>-    Tmp, Addr
</del><ins>+    x86: Tmp, Addr
</ins><span class="cx">     Imm, Tmp
</span><span class="cx"> 
</span><span class="cx"> Not32 UD:G
</span><span class="cx">     Tmp
</span><del>-    Addr
</del><ins>+    x86: Addr
</ins><span class="cx"> 
</span><del>-Not64 UD:G
</del><ins>+64: Not64 UD:G
</ins><span class="cx">     Tmp
</span><del>-    Addr
</del><ins>+    x86: Addr
</ins><span class="cx"> 
</span><span class="cx"> SqrtDouble U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> SqrtFloat U:F, UD:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> ConvertInt32ToDouble U:G, D:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><del>-ConvertInt64ToDouble U:G, D:F
</del><ins>+64: ConvertInt64ToDouble U:G, D:F
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> CountLeadingZeros32 U:G, D:G
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><del>-CountLeadingZeros64 U:G, D:G
</del><ins>+64: CountLeadingZeros64 U:G, D:G
</ins><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> ConvertDoubleToFloat U:F, D:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> ConvertFloatToDouble U:F, D:F
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp
</del><ins>+    x86: Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> # Note that Move operates over the full register size, which is either 32-bit or 64-bit depending on
</span><span class="cx"> # the platform. I'm not entirely sure that this is a good thing; it might be better to just have a
</span><span class="lines">@@ -295,7 +339,7 @@
</span><span class="cx"> 
</span><span class="cx"> SignExtend8To32 U:G, D:G
</span><span class="cx">     Tmp, Tmp
</span><del>-    Addr, Tmp as load8SignedExtendTo32
</del><ins>+    x86: Addr, Tmp as load8SignedExtendTo32
</ins><span class="cx">     Index, Tmp as load8SignedExtendTo32
</span><span class="cx"> 
</span><span class="cx"> ZeroExtend16To32 U:G, D:G
</span><span class="lines">@@ -325,7 +369,7 @@
</span><span class="cx"> MoveZeroToDouble D:F
</span><span class="cx">     Tmp
</span><span class="cx"> 
</span><del>-Move64ToDouble U:G, D:F
</del><ins>+64: Move64ToDouble U:G, D:F
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as loadDouble
</span><span class="cx"> 
</span><span class="lines">@@ -333,7 +377,7 @@
</span><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as loadFloat
</span><span class="cx"> 
</span><del>-MoveDoubleTo64 U:F, D:G
</del><ins>+64: MoveDoubleTo64 U:F, D:G
</ins><span class="cx">     Tmp, Tmp
</span><span class="cx">     Addr, Tmp as load64
</span><span class="cx"> 
</span><span class="lines">@@ -367,15 +411,15 @@
</span><span class="cx">     RelCond, Tmp, Tmp, Tmp
</span><span class="cx">     RelCond, Tmp, Imm, Tmp
</span><span class="cx"> 
</span><del>-Compare64 U:G, U:G, U:G, D:G
</del><ins>+64: Compare64 U:G, U:G, U:G, D:G
</ins><span class="cx">     RelCond, Tmp, Imm, Tmp
</span><span class="cx">     RelCond, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> Test32 U:G, U:G, U:G, D:G
</span><del>-    ResCond, Addr, Imm, Tmp
</del><ins>+    x86: ResCond, Addr, Imm, Tmp
</ins><span class="cx">     ResCond, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><del>-Test64 U:G, U:G, U:G, D:G
</del><ins>+64: Test64 U:G, U:G, U:G, D:G
</ins><span class="cx">     ResCond, Tmp, Imm, Tmp
</span><span class="cx">     ResCond, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -383,41 +427,41 @@
</span><span class="cx"> # you opt them into the block order optimizations.
</span><span class="cx"> 
</span><span class="cx"> Branch8 U:G, U:G, U:G /branch
</span><del>-    RelCond, Addr, Imm
-    RelCond, Index, Imm
</del><ins>+    x86: RelCond, Addr, Imm
+    x86: RelCond, Index, Imm
</ins><span class="cx"> 
</span><span class="cx"> Branch32 U:G, U:G, U:G /branch
</span><del>-    RelCond, Addr, Imm
</del><ins>+    x86: RelCond, Addr, Imm
</ins><span class="cx">     RelCond, Tmp, Tmp
</span><span class="cx">     RelCond, Tmp, Imm
</span><del>-    RelCond, Tmp, Addr
-    RelCond, Addr, Tmp
-    RelCond, Index, Imm
</del><ins>+    x86: RelCond, Tmp, Addr
+    x86: RelCond, Addr, Tmp
+    x86: RelCond, Index, Imm
</ins><span class="cx"> 
</span><del>-Branch64 U:G, U:G, U:G /branch
</del><ins>+64: Branch64 U:G, U:G, U:G /branch
</ins><span class="cx">     RelCond, Tmp, Tmp
</span><del>-    RelCond, Tmp, Addr
-    RelCond, Addr, Tmp
-    RelCond, Index, Tmp
</del><ins>+    x86: RelCond, Tmp, Addr
+    x86: RelCond, Addr, Tmp
+    x86: RelCond, Index, Tmp
</ins><span class="cx"> 
</span><span class="cx"> BranchTest8 U:G, U:G, U:G /branch
</span><del>-    ResCond, Addr, Imm
-    ResCond, Index, Imm
</del><ins>+    x86: ResCond, Addr, Imm
+    x86: ResCond, Index, Imm
</ins><span class="cx"> 
</span><span class="cx"> BranchTest32 U:G, U:G, U:G /branch
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm
</span><del>-    ResCond, Addr, Imm
-    ResCond, Index, Imm
</del><ins>+    x86: ResCond, Addr, Imm
+    x86: ResCond, Index, Imm
</ins><span class="cx"> 
</span><span class="cx"> # Warning: forms that take an immediate will sign-extend their immediate. You probably want
</span><span class="cx"> # BranchTest32 in most cases where you use an immediate.
</span><del>-BranchTest64 U:G, U:G, U:G /branch
</del><ins>+64: BranchTest64 U:G, U:G, U:G /branch
</ins><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm
</span><del>-    ResCond, Addr, Imm
-    ResCond, Addr, Tmp
-    ResCond, Index, Imm
</del><ins>+    x86: ResCond, Addr, Imm
+    x86: ResCond, Addr, Tmp
+    x86: ResCond, Index, Imm
</ins><span class="cx"> 
</span><span class="cx"> BranchDouble U:G, U:F, U:F /branch
</span><span class="cx">     DoubleCond, Tmp, Tmp
</span><span class="lines">@@ -428,52 +472,52 @@
</span><span class="cx"> BranchAdd32 U:G, U:G, UD:G /branch
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx">     ResCond, Imm, Tmp
</span><del>-    ResCond, Imm, Addr
-    ResCond, Tmp, Addr
-    ResCond, Addr, Tmp
</del><ins>+    x86: ResCond, Imm, Addr
+    x86: ResCond, Tmp, Addr
+    x86: ResCond, Addr, Tmp
</ins><span class="cx"> 
</span><del>-BranchAdd64 U:G, U:G, UD:G /branch
</del><ins>+64: BranchAdd64 U:G, U:G, UD:G /branch
</ins><span class="cx">     ResCond, Imm, Tmp
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> BranchMul32 U:G, U:G, UD:G /branch
</span><span class="cx">     ResCond, Tmp, Tmp
</span><del>-    ResCond, Addr, Tmp
</del><ins>+    x86: ResCond, Addr, Tmp
</ins><span class="cx"> 
</span><span class="cx"> BranchMul32 U:G, U:G, U:G, D:G /branch
</span><span class="cx">     ResCond, Tmp, Imm, Tmp
</span><span class="cx"> 
</span><del>-BranchMul64 U:G, U:G, UD:G /branch
</del><ins>+64: BranchMul64 U:G, U:G, UD:G /branch
</ins><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> BranchSub32 U:G, U:G, UD:G /branch
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx">     ResCond, Imm, Tmp
</span><del>-    ResCond, Imm, Addr
-    ResCond, Tmp, Addr
-    ResCond, Addr, Tmp
</del><ins>+    x86: ResCond, Imm, Addr
+    x86: ResCond, Tmp, Addr
+    x86: ResCond, Addr, Tmp
</ins><span class="cx"> 
</span><del>-BranchSub64 U:G, U:G, UD:G /branch
</del><ins>+64: BranchSub64 U:G, U:G, UD:G /branch
</ins><span class="cx">     ResCond, Imm, Tmp
</span><span class="cx">     ResCond, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> BranchNeg32 U:G, UD:G /branch
</span><span class="cx">     ResCond, Tmp
</span><span class="cx"> 
</span><del>-BranchNeg64 U:G, UD:G /branch
</del><ins>+64: BranchNeg64 U:G, UD:G /branch
</ins><span class="cx">     ResCond, Tmp
</span><span class="cx"> 
</span><span class="cx"> MoveConditionally32 U:G, U:G, U:G, U:G, UD:G
</span><span class="cx">     RelCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><del>-MoveConditionally64 U:G, U:G, U:G, U:G, UD:G
</del><ins>+64: MoveConditionally64 U:G, U:G, U:G, U:G, UD:G
</ins><span class="cx">     RelCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> MoveConditionallyTest32 U:G, U:G, U:G, U:G, UD:G
</span><span class="cx">     ResCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm, Tmp, Tmp
</span><span class="cx"> 
</span><del>-MoveConditionallyTest64 U:G, U:G, U:G, U:G, UD:G
</del><ins>+64: MoveConditionallyTest64 U:G, U:G, U:G, U:G, UD:G
</ins><span class="cx">     ResCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm, Tmp, Tmp
</span><span class="cx"> 
</span><span class="lines">@@ -486,14 +530,14 @@
</span><span class="cx"> MoveDoubleConditionally32 U:G, U:G, U:G, U:F, UD:F
</span><span class="cx">     RelCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><del>-MoveDoubleConditionally64 U:G, U:G, U:G, U:F, UD:F
</del><ins>+64: MoveDoubleConditionally64 U:G, U:G, U:G, U:F, UD:F
</ins><span class="cx">     RelCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx"> 
</span><span class="cx"> MoveDoubleConditionallyTest32 U:G, U:G, U:G, U:F, UD:F
</span><span class="cx">     ResCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm, Tmp, Tmp
</span><span class="cx"> 
</span><del>-MoveDoubleConditionallyTest64 U:G, U:G, U:G, U:F, UD:F
</del><ins>+64: MoveDoubleConditionallyTest64 U:G, U:G, U:G, U:F, UD:F
</ins><span class="cx">     ResCond, Tmp, Tmp, Tmp, Tmp
</span><span class="cx">     ResCond, Tmp, Imm, Tmp, Tmp
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airopcode_generatorrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/opcode_generator.rb (194044 => 194045)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/opcode_generator.rb        2015-12-14 19:53:04 UTC (rev 194044)
+++ trunk/Source/JavaScriptCore/b3/air/opcode_generator.rb        2015-12-14 19:54:15 UTC (rev 194045)
</span><span class="lines">@@ -92,11 +92,12 @@
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> class Form
</span><del>-    attr_reader :kinds, :altName
</del><ins>+    attr_reader :kinds, :altName, :archs
</ins><span class="cx"> 
</span><del>-    def initialize(kinds, altName)
</del><ins>+    def initialize(kinds, altName, archs)
</ins><span class="cx">         @kinds = kinds
</span><span class="cx">         @altName = altName
</span><ins>+        @archs = archs
</ins><span class="cx">     end
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -183,8 +184,12 @@
</span><span class="cx">     token =~ /\A((Tmp)|(Imm)|(Imm64)|(Addr)|(Index)|(RelCond)|(ResCond)|(DoubleCond))\Z/
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def isArch(token)
+    token =~ /\A((x86)|(x86_32)|(x86_64)|(arm)|(armv7)|(arm64)|(32)|(64))\Z/
+end
+
</ins><span class="cx"> def isKeyword(token)
</span><del>-    isUD(token) or isGF(token) or isKind(token) or
</del><ins>+    isUD(token) or isGF(token) or isKind(token) or isArch(token) or
</ins><span class="cx">         token == &quot;special&quot; or token == &quot;as&quot;
</span><span class="cx"> end
</span><span class="cx"> 
</span><span class="lines">@@ -251,6 +256,66 @@
</span><span class="cx">         result
</span><span class="cx">     end
</span><span class="cx"> 
</span><ins>+    def parseArchs
+        return nil unless isArch(token)
+
+        result = []
+        while isArch(token)
+            case token.string
+            when &quot;x86&quot;
+                result &lt;&lt; &quot;X86&quot;
+                result &lt;&lt; &quot;X86_64&quot;
+            when &quot;x86_32&quot;
+                result &lt;&lt; &quot;X86&quot;
+            when &quot;x86_64&quot;
+                result &lt;&lt; &quot;X86_64&quot;
+            when &quot;arm&quot;
+                result &lt;&lt; &quot;ARMv7&quot;
+                result &lt;&lt; &quot;ARM64&quot;
+            when &quot;armv7&quot;
+                result &lt;&lt; &quot;ARMv7&quot;
+            when &quot;arm64&quot;
+                result &lt;&lt; &quot;ARM64&quot;
+            when &quot;32&quot;
+                result &lt;&lt; &quot;X86&quot;
+                result &lt;&lt; &quot;ARMv7&quot;
+            when &quot;64&quot;
+                result &lt;&lt; &quot;X86_64&quot;
+                result &lt;&lt; &quot;ARM64&quot;
+            else
+                raise token.string
+            end
+            advance
+        end
+
+        consume(&quot;:&quot;)
+        @lastArchs = result
+    end
+
+    def consumeArchs
+        result = @lastArchs
+        @lastArchs = nil
+        result
+    end
+
+    def parseAndConsumeArchs
+        parseArchs
+        consumeArchs
+    end
+
+    def intersectArchs(left, right)
+        return left unless right
+        return right unless left
+
+        left.select {
+            | value |
+            right.find {
+                | otherValue |
+                value == otherValue
+            }
+        }
+    end
+
</ins><span class="cx">     def parse
</span><span class="cx">         result = {}
</span><span class="cx">         
</span><span class="lines">@@ -265,6 +330,8 @@
</span><span class="cx"> 
</span><span class="cx">                 result[opcodeName] = Opcode.new(opcodeName, true)
</span><span class="cx">             else
</span><ins>+                opcodeArchs = parseAndConsumeArchs
+
</ins><span class="cx">                 opcodeName = consumeIdentifier
</span><span class="cx"> 
</span><span class="cx">                 if result[opcodeName]
</span><span class="lines">@@ -306,10 +373,12 @@
</span><span class="cx">                     advance
</span><span class="cx">                 end
</span><span class="cx"> 
</span><ins>+                parseArchs
</ins><span class="cx">                 if isKind(token)
</span><span class="cx">                     loop {
</span><span class="cx">                         kinds = []
</span><span class="cx">                         altName = nil
</span><ins>+                        formArchs = consumeArchs
</ins><span class="cx">                         loop {
</span><span class="cx">                             kinds &lt;&lt; Kind.new(consumeKind)
</span><span class="cx"> 
</span><span class="lines">@@ -340,14 +409,16 @@
</span><span class="cx">                                 end
</span><span class="cx">                             end
</span><span class="cx">                         }
</span><del>-                        forms &lt;&lt; Form.new(kinds, altName)
</del><ins>+                        forms &lt;&lt; Form.new(kinds, altName, intersectArchs(opcodeArchs, formArchs))
+
+                        parseArchs
</ins><span class="cx">                         break unless isKind(token)
</span><span class="cx">                     }
</span><span class="cx">                 end
</span><span class="cx"> 
</span><span class="cx">                 if signature.length == 0
</span><span class="cx">                     raise unless forms.length == 0
</span><del>-                    forms &lt;&lt; Form.new([], nil)
</del><ins>+                    forms &lt;&lt; Form.new([], nil, opcodeArchs)
</ins><span class="cx">                 end
</span><span class="cx"> 
</span><span class="cx">                 opcode.overloads &lt;&lt; Overload.new(signature, forms)
</span><span class="lines">@@ -412,6 +483,7 @@
</span><span class="cx">     if columnIndex &gt;= forms[0].kinds.length
</span><span class="cx">         raise &quot;Did not reduce to one form: #{forms.inspect}&quot; unless forms.length == 1
</span><span class="cx">         callback[forms[0]]
</span><ins>+        outp.puts &quot;break;&quot;
</ins><span class="cx">         return
</span><span class="cx">     end
</span><span class="cx">     
</span><span class="lines">@@ -497,6 +569,23 @@
</span><span class="cx">     }
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def beginArchs(outp, archs)
+    return unless archs
+    if archs.empty?
+        outp.puts &quot;#if 0&quot;
+        return
+    end
+    outp.puts(&quot;#if &quot; + archs.map {
+                  | arch |
+                  &quot;CPU(#{arch})&quot;
+              }.join(&quot; || &quot;))
+end
+
+def endArchs(outp, archs)
+    return unless archs
+    outp.puts &quot;#endif&quot;
+end
+
</ins><span class="cx"> writeH(&quot;OpcodeUtils&quot;) {
</span><span class="cx">     | outp |
</span><span class="cx">     outp.puts &quot;#include \&quot;AirInst.h\&quot;&quot;
</span><span class="lines">@@ -559,8 +648,10 @@
</span><span class="cx">                 filter = proc { false }
</span><span class="cx">                 callback = proc {
</span><span class="cx">                     | form |
</span><del>-                    special = (not form.kinds.detect { | kind | kind.special })
-                    outp.puts &quot;OPGEN_RETURN(#{special});&quot;
</del><ins>+                    notSpecial = (not form.kinds.detect { | kind | kind.special })
+                    beginArchs(outp, form.archs)
+                    outp.puts &quot;OPGEN_RETURN(#{notSpecial});&quot;
+                    endArchs(outp, form.archs)
</ins><span class="cx">                 }
</span><span class="cx">                 matchForms(outp, :safe, overload.forms, 0, columnGetter, filter, callback)
</span><span class="cx">                 outp.puts &quot;break;&quot;
</span><span class="lines">@@ -626,6 +717,7 @@
</span><span class="cx">             outp.puts &quot;return false;&quot;
</span><span class="cx">             outp.puts &quot;OPGEN_RETURN(args[0].special()-&gt;isValid(*this));&quot;
</span><span class="cx">         else
</span><ins>+            beginArchs(outp, form.archs)
</ins><span class="cx">             needsMoreValidation = false
</span><span class="cx">             overload.signature.length.times {
</span><span class="cx">                 | index |
</span><span class="lines">@@ -647,6 +739,7 @@
</span><span class="cx">                 outp.puts &quot;OPGEN_RETURN(false);&quot;
</span><span class="cx">             end
</span><span class="cx">             outp.puts &quot;OPGEN_RETURN(true);&quot;
</span><ins>+            endArchs(outp, form.archs)
</ins><span class="cx">         end
</span><span class="cx">     }
</span><span class="cx">     outp.puts &quot;return false;&quot;
</span><span class="lines">@@ -720,7 +813,7 @@
</span><span class="cx">                         }
</span><span class="cx"> 
</span><span class="cx">                         if numYes == 0
</span><del>-                        # Don't emit anything, just drop to default.
</del><ins>+                            # Don't emit anything, just drop to default.
</ins><span class="cx">                         elsif numNo == 0
</span><span class="cx">                             outp.puts &quot;case #{overload.signature.length}:&quot; if needOverloadSwitch
</span><span class="cx">                             outp.puts &quot;OPGEN_RETURN(true);&quot;
</span><span class="lines">@@ -758,7 +851,10 @@
</span><span class="cx">                                 end
</span><span class="cx">                             }
</span><span class="cx">                             callback = proc {
</span><ins>+                                | form |
+                                beginArchs(outp, form.archs)
</ins><span class="cx">                                 outp.puts &quot;OPGEN_RETURN(true);&quot;
</span><ins>+                                endArchs(outp, form.archs)
</ins><span class="cx">                             }
</span><span class="cx">                             matchForms(outp, :safe, overload.forms, 0, columnGetter, filter, callback)
</span><span class="cx"> 
</span><span class="lines">@@ -858,6 +954,7 @@
</span><span class="cx">         if opcode.special
</span><span class="cx">             outp.puts &quot;OPGEN_RETURN(args[0].special()-&gt;generate(*this, jit, context));&quot;
</span><span class="cx">         else
</span><ins>+            beginArchs(outp, form.archs)
</ins><span class="cx">             if form.altName
</span><span class="cx">                 methodName = form.altName
</span><span class="cx">             else
</span><span class="lines">@@ -899,6 +996,7 @@
</span><span class="cx"> 
</span><span class="cx">             outp.puts &quot;);&quot;
</span><span class="cx">             outp.puts &quot;OPGEN_RETURN(result);&quot;
</span><ins>+            endArchs(outp, form.archs)
</ins><span class="cx">         end
</span><span class="cx">     }
</span><span class="cx">     outp.puts &quot;RELEASE_ASSERT_NOT_REACHED();&quot;
</span></span></pre>
</div>
</div>

</body>
</html>