LIRopcode.tbl
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=0 ft=c:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey nanojit.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* This file is best viewed with 128 columns:
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
*
* Definitions of LIR opcodes. If you need to allocate an opcode, look
* for one defined using OP_UN() and claim it.
*
* Includers must define an OPxyz macro of the following form:
*
* #define OPxyz(op, number, repKind, retType) ...
*
* Selected arguments can then be used within the macro expansions.
* - op Opcode name, token-pasted after "LIR_" to form an LOpcode.
* - number Opcode number, used as the LOpcode enum value.
* - repKind Indicates how the instruction is represented in memory; XYZ
* corresponds to LInsXYZ and LRK_XYZ.
* - retType Type (LTy) of the value returned by the instruction.
* - isCse 0 if the opcode can never be CSE'd safely, 1 if it always
* can, -1 if things are more complicated -- in which case
* isCseOpcode() shouldn't be called on this opcode.
*
* Opcodes use type-indicators suffixes that are loosly based on C type names:
* - 'c': "char", ie. 8-bit integer
* - 's': "short", ie. 16-bit integer
* - 'i': "int", ie. 32-bit integer
* - 'q': "quad", ie. 64-bit integer
* - 'u': "unsigned", is used as a prefix on integer type-indicators when necessary
* - 'f': "float", ie. 32-bit floating point value
* - 'd': "double", ie. 64-bit floating point value
* - 'p': "pointer", ie. a int on 32-bit machines, a quad on 64-bit machines
*
* 'p' opcodes are all aliases of int and quad opcodes, they're given in LIR.h
* and chosen according to the platform pointer size.
*
* Certain opcodes aren't supported on all platforms, so OPxyz must be one of
* the following:
*
* OP___: for opcodes supported on all platforms.
* OP_UN: for opcodes not yet used on any platform.
* OP_32: for opcodes supported only on 32-bit platforms.
* OP_64: for opcodes supported only on 64-bit platforms.
* OP_SF: for opcodes supported only on SoftFloat platforms.
* OP_86: for opcodes supported only on i386/X64.
*/
#define OP_UN(n) OP___(__##n, n, None, V, -1)
#ifdef NANOJIT_64BIT
# define OP_32(a, b, c, d, e) OP_UN(b)
# define OP_64 OP___
#else
# define OP_32 OP___
# define OP_64(a, b, c, d, e) OP_UN(b)
#endif
#if NJ_SOFTFLOAT_SUPPORTED
# define OP_SF OP___
#else
# define OP_SF(a, b, c, d, e) OP_UN(b)
#endif
#if defined NANOJIT_IA32 || defined NANOJIT_X64
# define OP_86 OP___
#else
# define OP_86(a, b, c, d, e) OP_UN(b)
#endif
//---------------------------------------------------------------------------
// Miscellaneous operations
//---------------------------------------------------------------------------
OP___(start, 0, Op0, V, 0) // start of a fragment
// A register fence causes no code to be generated, but it affects register
// allocation so that no registers are live when it is reached.
OP___(regfence, 1, Op0, V, 0)
OP___(skip, 2, Sk, V, 0) // links code chunks
OP_32(parami, 3, P, I, 0) // load an int parameter (register or stack location)
OP_64(paramq, 4, P, Q, 0) // load a quad parameter (register or stack location)
OP___(allocp, 5, I, P, 0) // allocate stack space (result is an address)
OP___(reti, 6, Op1, V, 0) // return an int
OP_64(retq, 7, Op1, V, 0) // return a quad
OP___(retd, 8, Op1, V, 0) // return a double
OP___(livei, 9, Op1, V, 0) // extend live range of an int
OP_64(liveq, 10, Op1, V, 0) // extend live range of a quad
OP___(lived, 11, Op1, V, 0) // extend live range of a double
OP___(file, 12, Op1, V, 0) // source filename for debug symbols
OP___(line, 13, Op1, V, 0) // source line number for debug symbols
OP___(comment, 14, Op1, V, 0) // a comment shown, on its own line, in LIR dumps
OP_UN(15)
OP_UN(16)
//---------------------------------------------------------------------------
// Loads and stores
//---------------------------------------------------------------------------
OP___(ldc2i, 17, Ld, I, -1) // load char and sign-extend to an int
OP___(lds2i, 18, Ld, I, -1) // load short and sign-extend to an int
OP___(lduc2ui, 19, Ld, I, -1) // load unsigned char and zero-extend to an unsigned int
OP___(ldus2ui, 20, Ld, I, -1) // load unsigned short and zero-extend to an unsigned int
OP___(ldi, 21, Ld, I, -1) // load int
OP_64(ldq, 22, Ld, Q, -1) // load quad
OP___(ldd, 23, Ld, D, -1) // load double
OP___(ldf2d, 24, Ld, D, -1) // load float and extend to a double
OP___(sti2c, 25, St, V, 0) // store int truncated to char
OP___(sti2s, 26, St, V, 0) // store int truncated to short
OP___(sti, 27, St, V, 0) // store int
OP_64(stq, 28, St, V, 0) // store quad
OP___(std, 29, St, V, 0) // store double
OP___(std2f, 30, St, V, 0) // store double as a float (losing precision)
OP_UN(31)
OP_UN(32)
//---------------------------------------------------------------------------
// Calls
//---------------------------------------------------------------------------
OP___(callv, 33, C, V, -1) // call subroutine that returns void
OP___(calli, 34, C, I, -1) // call subroutine that returns an int
OP_64(callq, 35, C, Q, -1) // call subroutine that returns a quad
OP___(calld, 36, C, D, -1) // call subroutine that returns a double
//---------------------------------------------------------------------------
// Branches and labels
//---------------------------------------------------------------------------
// 'jt' and 'jf' must be adjacent so that (op ^ 1) gives the opposite one.
// Static assertions in LIR.h check this requirement.
OP___(j, 37, Op2, V, 0) // jump always
OP___(jt, 38, Op2, V, 0) // jump if true
OP___(jf, 39, Op2, V, 0) // jump if false
OP___(jtbl, 40, Jtbl, V, 0) // jump to address in table
OP___(label, 41, Op0, V, 0) // a jump target (no machine code is emitted for this)
OP_UN(42)
//---------------------------------------------------------------------------
// Guards
//---------------------------------------------------------------------------
// 'xt' and 'xf' must be adjacent so that (op ^ 1) gives the opposite one.
// Static assertions in LIR.h check this requirement.
OP___(x, 43, Op2, V, 0) // exit always
OP___(xt, 44, Op2, V, 1) // exit if true
OP___(xf, 45, Op2, V, 1) // exit if false
// A LIR_xbarrier cause no code to be generated, but it acts like a never-taken
// guard in that it inhibits certain optimisations, such as dead stack store
// elimination.
OP___(xbarrier, 46, Op2, V, 0)
OP_UN(47)
OP_UN(48)
//---------------------------------------------------------------------------
// Immediates
//---------------------------------------------------------------------------
OP___(immi, 49, I, I, 1) // int immediate
OP_64(immq, 50, QorD, Q, 1) // quad immediate
OP___(immd, 51, QorD, D, 1) // double immediate
OP_UN(52)
//---------------------------------------------------------------------------
// Comparisons
//---------------------------------------------------------------------------
// All comparisons return an int: 0 on failure and 1 on success.
//
// Within each type group, order must be preserved so that, except for eq*, (op
// ^ 1) gives the opposite one (eg. lt ^ 1 == gt). eq* must have odd numbers
// for this to work. They must also remain contiguous so that opcode range
// checking works correctly. Static assertions in LIR.h check these
// requirements.
OP___(eqi, 53, Op2, I, 1) // int equality
OP___(lti, 54, Op2, I, 1) // signed int less-than
OP___(gti, 55, Op2, I, 1) // signed int greater-than
OP___(lei, 56, Op2, I, 1) // signed int less-than-or-equal
OP___(gei, 57, Op2, I, 1) // signed int greater-than-or-equal
OP___(ltui, 58, Op2, I, 1) // unsigned int less-than
OP___(gtui, 59, Op2, I, 1) // unsigned int greater-than
OP___(leui, 60, Op2, I, 1) // unsigned int less-than-or-equal
OP___(geui, 61, Op2, I, 1) // unsigned int greater-than-or-equal
OP_UN(62)
OP_64(eqq, 63, Op2, I, 1) // quad equality
OP_64(ltq, 64, Op2, I, 1) // signed quad less-than
OP_64(gtq, 65, Op2, I, 1) // signed quad greater-than
OP_64(leq, 66, Op2, I, 1) // signed quad less-than-or-equal
OP_64(geq, 67, Op2, I, 1) // signed quad greater-than-or-equal
OP_64(ltuq, 68, Op2, I, 1) // unsigned quad less-than
OP_64(gtuq, 69, Op2, I, 1) // unsigned quad greater-than
OP_64(leuq, 70, Op2, I, 1) // unsigned quad less-than-or-equal
OP_64(geuq, 71, Op2, I, 1) // unsigned quad greater-than-or-equal
OP_UN(72)
OP___(eqd, 73, Op2, I, 1) // double equality
OP___(ltd, 74, Op2, I, 1) // double less-than
OP___(gtd, 75, Op2, I, 1) // double greater-than
OP___(led, 76, Op2, I, 1) // double less-than-or-equal
OP___(ged, 77, Op2, I, 1) // double greater-than-or-equal
//---------------------------------------------------------------------------
// Arithmetic
//---------------------------------------------------------------------------
OP___(negi, 78, Op1, I, 1) // negate int
OP___(addi, 79, Op2, I, 1) // add int
OP___(subi, 80, Op2, I, 1) // subtract int
OP___(muli, 81, Op2, I, 1) // multiply int
OP_86(divi, 82, Op2, I, 1) // divide int
// LIR_modi is a hack. It's only used on i386/X64. The operand is the result
// of a LIR_divi because on i386/X64 div and mod results are computed by the
// same instruction.
OP_86(modi, 83, Op1, I, 1) // modulo int
OP___(noti, 84, Op1, I, 1) // bitwise-NOT int
OP___(andi, 85, Op2, I, 1) // bitwise-AND int
OP___(ori, 86, Op2, I, 1) // bitwise-OR int
OP___(xori, 87, Op2, I, 1) // bitwise-XOR int
// For all three integer shift operations, only the bottom five bits of the
// second operand are used, and they are treated as unsigned. This matches
// x86 semantics.
OP___(lshi, 88, Op2, I, 1) // left shift int
OP___(rshi, 89, Op2, I, 1) // right shift int (>>)
OP___(rshui, 90, Op2, I, 1) // right shift unsigned int (>>>)
OP_64(addq, 91, Op2, Q, 1) // add quad
OP_64(subq, 92, Op2, Q, 1) // subtract quad
OP_64(andq, 93, Op2, Q, 1) // bitwise-AND quad
OP_64(orq, 94, Op2, Q, 1) // bitwise-OR quad
OP_64(xorq, 95, Op2, Q, 1) // bitwise-XOR quad
// For all three quad shift operations, only the bottom six bits of the
// second operand are used, and they are treated as unsigned. This matches
// x86-64 semantics.
OP_64(lshq, 96, Op2, Q, 1) // left shift quad; 2nd operand is an int
OP_64(rshq, 97, Op2, Q, 1) // right shift quad; 2nd operand is an int
OP_64(rshuq, 98, Op2, Q, 1) // right shift unsigned quad; 2nd operand is an int
OP___(negd, 99, Op1, D, 1) // negate double
OP___(addd, 100, Op2, D, 1) // add double
OP___(subd, 101, Op2, D, 1) // subtract double
OP___(muld, 102, Op2, D, 1) // multiply double
OP___(divd, 103, Op2, D, 1) // divide double
// LIR_modd is just a place-holder opcode, ie. the back-ends cannot generate
// code for it. It's used in TraceMonkey briefly but is always demoted to a
// LIR_modl or converted to a function call before Nanojit has to do anything
// serious with it.
OP___(modd, 104, Op2, D, 1) // modulo double
OP___(cmovi, 105, Op3, I, 1) // conditional move int
OP_64(cmovq, 106, Op3, Q, 1) // conditional move quad
OP___(cmovd, 107, Op3, D, 1) // conditional move double
//---------------------------------------------------------------------------
// Conversions
//---------------------------------------------------------------------------
OP_64(i2q, 108, Op1, Q, 1) // sign-extend int to quad
OP_64(ui2uq, 109, Op1, Q, 1) // zero-extend unsigned int to unsigned quad
OP_64(q2i, 110, Op1, I, 1) // truncate quad to int (removes the high 32 bits)
OP___(i2d, 111, Op1, D, 1) // convert int to double
OP___(ui2d, 112, Op1, D, 1) // convert unsigned int to double
// The rounding behavior of LIR_d2i is platform specific.
//
// Platform Asm code Behavior
// -------- -------- --------
// x86 w/ x87 fist uses current FP control word (default is rounding)
// x86 w/ SSE cvttsd2si performs round to zero (truncate)
// x64 (SSE) cvttsd2si performs round to zero (truncate)
// PowerPC unsupported
// ARM ftosid round to nearest
// MIPS trunc.w.d performs round to zero (truncate)
// SH4 frtc performs round to zero (truncate)
// SPARC fdtoi performs round to zero (truncate)
//
// round to zero examples: 1.9 -> 1, 1.1 -> 1, -1.1 -> -1, -1.9 -> -1
// round to nearest examples: 1.9 -> 2, 1.1 -> 1, -1.1 -> -1, -1.9 -> -2
OP___(d2i, 113, Op1, I, 1) // convert double to int (no exceptions raised)
OP_64(dasq, 114, Op1, Q, 1) // interpret the bits of a double as a quad
OP_64(qasd, 115, Op1, D, 1) // interpret the bits of a quad as a double
//---------------------------------------------------------------------------
// Overflow arithmetic
//---------------------------------------------------------------------------
// These all exit if overflow occurred. The result is valid on either path.
OP___(addxovi, 116, Op3, I, 1) // add int and exit on overflow
OP___(subxovi, 117, Op3, I, 1) // subtract int and exit on overflow
OP___(mulxovi, 118, Op3, I, 1) // multiply int and exit on overflow
// These all branch if overflow occurred. The result is valid on either path.
OP___(addjovi, 119, Op3, I, 1) // add int and branch on overflow
OP___(subjovi, 120, Op3, I, 1) // subtract int and branch on overflow
OP___(muljovi, 121, Op3, I, 1) // multiply int and branch on overflow
OP_64(addjovq, 122, Op3, Q, 1) // add quad and branch on overflow
OP_64(subjovq, 123, Op3, Q, 1) // subtract quad and branch on overflow
//---------------------------------------------------------------------------
// SoftFloat
//---------------------------------------------------------------------------
OP_SF(dlo2i, 124, Op1, I, 1) // get the low 32 bits of a double as an int
OP_SF(dhi2i, 125, Op1, I, 1) // get the high 32 bits of a double as an int
OP_SF(ii2d, 126, Op2, D, 1) // join two ints (1st arg is low bits, 2nd is high)
// LIR_hcalli is a hack that's only used on 32-bit platforms that use
// SoftFloat. Its operand is always a LIR_calli, but one that specifies a
// function that returns a double. It indicates that the double result is
// returned via two 32-bit integer registers. The result is always used as the
// second operand of a LIR_ii2d.
OP_SF(hcalli, 127, Op1, I, 1)
#undef OP_UN
#undef OP_32
#undef OP_64
#undef OP_SF
#undef OP_86