| # Copyright (C) 2011-2018 Apple Inc. All rights reserved. | 
 | # | 
 | # Redistribution and use in source and binary forms, with or without | 
 | # modification, are permitted provided that the following conditions | 
 | # are met: | 
 | # 1. Redistributions of source code must retain the above copyright | 
 | #    notice, this list of conditions and the following disclaimer. | 
 | # 2. Redistributions in binary form must reproduce the above copyright | 
 | #    notice, this list of conditions and the following disclaimer in the | 
 | #    documentation and/or other materials provided with the distribution. | 
 | # | 
 | # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 
 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 
 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 
 | # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 
 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 
 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 
 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 
 | # THE POSSIBILITY OF SUCH DAMAGE. | 
 |  | 
 | require "config" | 
 | require "set" | 
 |  | 
 | # Interesting invariant, which we take advantage of: branching instructions | 
 | # always begin with "b", and no non-branching instructions begin with "b". | 
 | # Terminal instructions are "jmp" and "ret". | 
 |  | 
 | MACRO_INSTRUCTIONS = | 
 |     [ | 
 |      "emit", | 
 |      "addi", | 
 |      "andi", | 
 |      "andf", | 
 |      "andd", | 
 |      "lshifti", | 
 |      "lshiftp", | 
 |      "lshiftq", | 
 |      "muli", | 
 |      "negi", | 
 |      "negp", | 
 |      "negq", | 
 |      "noti", | 
 |      "ori", | 
 |      "orf", | 
 |      "ord", | 
 |      "orh", | 
 |      "rshifti", | 
 |      "urshifti", | 
 |      "rshiftp", | 
 |      "urshiftp", | 
 |      "rshiftq", | 
 |      "urshiftq", | 
 |      "lrotatei", | 
 |      "lrotateq", | 
 |      "rrotatei", | 
 |      "rrotateq", | 
 |      "subi", | 
 |      "xori", | 
 |      "loadi", | 
 |      "loadis", | 
 |      "loadb", | 
 |      "loadbsi", | 
 |      "loadbsq", | 
 |      "loadh", | 
 |      "loadhsi", | 
 |      "loadhsq", | 
 |      "storei", | 
 |      "storeh", | 
 |      "storeb", | 
 |      "loadf", | 
 |      "loadd", | 
 |      "moved", | 
 |      "storef", | 
 |      "stored", | 
 |      "addf", | 
 |      "addd", | 
 |      "divf", | 
 |      "divd", | 
 |      "subf", | 
 |      "subd", | 
 |      "mulf", | 
 |      "muld", | 
 |      "sqrtf", | 
 |      "sqrtd", | 
 |      "floorf", | 
 |      "floord", | 
 |      "roundf", | 
 |      "roundd", | 
 |      "truncatef", | 
 |      "truncated", | 
 |      "truncatef2i", | 
 |      "truncatef2q", | 
 |      "truncated2q", | 
 |      "truncated2i", | 
 |      "truncatef2is", | 
 |      "truncated2is", | 
 |      "truncatef2qs", | 
 |      "truncated2qs", | 
 |      "ci2d", | 
 |      "ci2ds", | 
 |      "ci2f", | 
 |      "ci2fs", | 
 |      "cq2f", | 
 |      "cq2fs", | 
 |      "cq2d", | 
 |      "cq2ds", | 
 |      "cd2f", | 
 |      "cf2d", | 
 |      "fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr> | 
 |      "fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits> | 
 |      "fq2d", | 
 |      "fd2q", | 
 |      "bdeq", | 
 |      "bdneq", | 
 |      "bdgt", | 
 |      "bdgteq", | 
 |      "bdlt", | 
 |      "bdlteq", | 
 |      "bdequn", | 
 |      "bdnequn", | 
 |      "bdgtun", | 
 |      "bdgtequn", | 
 |      "bdltun", | 
 |      "bdltequn", | 
 |      "bfeq", | 
 |      "bfgt", | 
 |      "bflt", | 
 |      "bfgtun", | 
 |      "bfgtequn", | 
 |      "bfltun", | 
 |      "bfltequn", | 
 |      "btd2i", | 
 |      "td2i", | 
 |      "bcd2i", | 
 |      "movdz", | 
 |      "pop", | 
 |      "push", | 
 |      "move", | 
 |      "sxi2q", | 
 |      "zxi2q", | 
 |      "nop", | 
 |      "bieq", | 
 |      "bineq", | 
 |      "bia", | 
 |      "biaeq", | 
 |      "bib", | 
 |      "bibeq", | 
 |      "bigt", | 
 |      "bigteq", | 
 |      "bilt", | 
 |      "bilteq", | 
 |      "bbeq", | 
 |      "bbneq", | 
 |      "bba", | 
 |      "bbaeq", | 
 |      "bbb", | 
 |      "bbbeq", | 
 |      "bbgt", | 
 |      "bbgteq", | 
 |      "bblt", | 
 |      "bblteq", | 
 |      "btis", | 
 |      "btiz", | 
 |      "btinz", | 
 |      "btbs", | 
 |      "btbz", | 
 |      "btbnz", | 
 |      "jmp", | 
 |      "baddio", | 
 |      "baddis", | 
 |      "baddiz", | 
 |      "baddinz", | 
 |      "bsubio", | 
 |      "bsubis", | 
 |      "bsubiz", | 
 |      "bsubinz", | 
 |      "bmulio", | 
 |      "bmulis", | 
 |      "bmuliz", | 
 |      "bmulinz", | 
 |      "borio", | 
 |      "boris", | 
 |      "boriz", | 
 |      "borinz", | 
 |      "break", | 
 |      "call", | 
 |      "ret", | 
 |      "cbeq", | 
 |      "cbneq", | 
 |      "cba", | 
 |      "cbaeq", | 
 |      "cbb", | 
 |      "cbbeq", | 
 |      "cbgt", | 
 |      "cbgteq", | 
 |      "cblt", | 
 |      "cblteq", | 
 |      "cieq", | 
 |      "cineq", | 
 |      "cia", | 
 |      "ciaeq", | 
 |      "cib", | 
 |      "cibeq", | 
 |      "cigt", | 
 |      "cigteq", | 
 |      "cilt", | 
 |      "cilteq", | 
 |      "tis", | 
 |      "tiz", | 
 |      "tinz", | 
 |      "tbs", | 
 |      "tbz", | 
 |      "tbnz", | 
 |      "tps", | 
 |      "tpz", | 
 |      "tpnz", | 
 |      "peek", | 
 |      "poke", | 
 |      "bpeq", | 
 |      "bpneq", | 
 |      "bpa", | 
 |      "bpaeq", | 
 |      "bpb", | 
 |      "bpbeq", | 
 |      "bpgt", | 
 |      "bpgteq", | 
 |      "bplt", | 
 |      "bplteq", | 
 |      "addp", | 
 |      "mulp", | 
 |      "andp", | 
 |      "orp", | 
 |      "subp", | 
 |      "xorp", | 
 |      "loadp", | 
 |      "cpeq", | 
 |      "cpneq", | 
 |      "cpa", | 
 |      "cpaeq", | 
 |      "cpb", | 
 |      "cpbeq", | 
 |      "cpgt", | 
 |      "cpgteq", | 
 |      "cplt", | 
 |      "cplteq", | 
 |      "storep", | 
 |      "btps", | 
 |      "btpz", | 
 |      "btpnz", | 
 |      "baddpo", | 
 |      "baddps", | 
 |      "baddpz", | 
 |      "baddpnz", | 
 |      "tqs", | 
 |      "tqz", | 
 |      "tqnz", | 
 |      "bqeq", | 
 |      "bqneq", | 
 |      "bqa", | 
 |      "bqaeq", | 
 |      "bqb", | 
 |      "bqbeq", | 
 |      "bqgt", | 
 |      "bqgteq", | 
 |      "bqlt", | 
 |      "bqlteq", | 
 |      "addq", | 
 |      "mulq", | 
 |      "andq", | 
 |      "orq", | 
 |      "subq", | 
 |      "xorq", | 
 |      "loadq", | 
 |      "cqeq", | 
 |      "cqneq", | 
 |      "cqa", | 
 |      "cqaeq", | 
 |      "cqb", | 
 |      "cqbeq", | 
 |      "cqgt", | 
 |      "cqgteq", | 
 |      "cqlt", | 
 |      "cqlteq", | 
 |      "storeq", | 
 |      "btqs", | 
 |      "btqz", | 
 |      "btqnz", | 
 |      "baddqo", | 
 |      "baddqs", | 
 |      "baddqz", | 
 |      "baddqnz", | 
 |      "bo", | 
 |      "bs", | 
 |      "bz", | 
 |      "bnz", | 
 |      "leai", | 
 |      "leap", | 
 |      "memfence", | 
 |      "tagReturnAddress", | 
 |      "untagReturnAddress", | 
 |      "removeCodePtrTag", | 
 |      "untagArrayPtr",     | 
 |      "tzcnti", | 
 |      "tzcntq", | 
 |      "lzcnti", | 
 |      "lzcntq", | 
 |      "absf", | 
 |      "absd", | 
 |      "negf", | 
 |      "negd", | 
 |      "ceilf", | 
 |      "ceild", | 
 |      "cfeq", | 
 |      "cdeq", | 
 |      "cfneq", | 
 |      "cfnequn", | 
 |      "cdneq", | 
 |      "cdnequn", | 
 |      "cflt", | 
 |      "cdlt", | 
 |      "cflteq", | 
 |      "cdlteq", | 
 |      "cfgt", | 
 |      "cdgt", | 
 |      "cfgteq", | 
 |      "cdgteq", | 
 |      "fi2f", | 
 |      "ff2i", | 
 |      "tls_loadp", | 
 |      "tls_storep", | 
 |     ] | 
 |  | 
 | X86_INSTRUCTIONS = | 
 |     [ | 
 |      "cdqi", | 
 |      "idivi", | 
 |      "udivi", | 
 |      "cqoq", | 
 |      "idivq", | 
 |      "udivq", | 
 |     ] | 
 |  | 
 | ARM_INSTRUCTIONS = | 
 |     [ | 
 |      "clrbp", | 
 |      "mvlbl", | 
 |      "globaladdr" | 
 |     ] | 
 |  | 
 | ARM64_INSTRUCTIONS = | 
 |     [ | 
 |      "bfiq", # Bit field insert <source reg> <last bit written> <width immediate> <dest reg> | 
 |      "pcrtoaddr",   # Address from PC relative offset - adr instruction | 
 |      "nopFixCortexA53Err835769", # nop on Cortex-A53 (nothing otherwise) | 
 |      "globaladdr", | 
 |      "divi", | 
 |      "divis", | 
 |      "divq", | 
 |      "divqs", | 
 |     ] | 
 |  | 
 | RISC_INSTRUCTIONS = | 
 |     [ | 
 |      "smulli",  # Multiply two 32-bit words and produce a 64-bit word | 
 |      "addis",   # Add integers and set a flag. | 
 |      "subis",   # Same, but for subtraction. | 
 |      "oris",    # Same, but for bitwise or. | 
 |      "addps"    # addis but for pointers. | 
 |     ] | 
 |  | 
 | MIPS_INSTRUCTIONS = | 
 |     [ | 
 |     "la", | 
 |     "movz", | 
 |     "movn", | 
 |     "setcallreg", | 
 |     "slt", | 
 |     "sltu", | 
 |     "pichdr" | 
 |     ] | 
 |  | 
 | CXX_INSTRUCTIONS = | 
 |     [ | 
 |      "cloopCrash",              # no operands | 
 |      "cloopCallJSFunction",     # operands: callee | 
 |      "cloopCallNative",         # operands: callee | 
 |      "cloopCallSlowPath",       # operands: callTarget, currentFrame, currentPC | 
 |      "cloopCallSlowPathVoid",   # operands: callTarget, currentFrame, currentPC | 
 |  | 
 |      # For debugging only: | 
 |      # Takes no operands but simply emits whatever follows in // comments as | 
 |      # a line of C++ code in the generated LLIntAssembly.h file. This can be | 
 |      # used to insert instrumentation into the interpreter loop to inspect | 
 |      # variables of interest. Do not leave these instructions in production | 
 |      # code. | 
 |      "cloopDo",              # no operands | 
 |     ] | 
 |  | 
 | INSTRUCTIONS = MACRO_INSTRUCTIONS + X86_INSTRUCTIONS + ARM_INSTRUCTIONS + ARM64_INSTRUCTIONS + RISC_INSTRUCTIONS + MIPS_INSTRUCTIONS + CXX_INSTRUCTIONS | 
 |  | 
 | INSTRUCTION_SET = INSTRUCTIONS.to_set | 
 |  | 
 | def isBranch(instruction) | 
 |     instruction =~ /^b/ | 
 | end | 
 |  | 
 | def hasFallThrough(instruction) | 
 |     instruction != "ret" and instruction != "jmp" | 
 | end | 
 |  | 
 | def isPowerOfTwo(value) | 
 |     return false if value <= 0 | 
 |     (value & (value - 1)).zero? | 
 | end |