blob: a41e06f7d6a1a22233d937266c44c270e339d393 [file] [log] [blame]
# 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