In Nanojit, **LIR** is the source language for compilation to machine code. LIR stands for *low-level intermediate representation*.

## The LIR instruction set

**Types in LIR.** Values in LIR have a type: either 32-bit or 64-bit. A 32-bit value, additionally, may be a condition or not. Each instruction requires operands of a specific type and produces a result of a specific type.

LIR makes no distinction at all between pointers and integers of the same size, between signed and unsigned integer values, or between 64-bit floating-point and 64-bit integer values. It is acceptable to load a 64-bit value from memory using `ldq`

and then use the result with a floating-point arithmetic operation such as `fadd`

.

The names of the operands and results below indicate the types required by LIR. Names starting with *i* indicate 32-bit values. Results starting with *b* are 32-bit integers and additionally are conditions. Operand names starting with *b* must be conditions. Names starting with *q* or *f* indicate 64-bit values. (*f* and *q* indicate the same type as far as LIR is concerned, but *f* is used here for floating-point operations.) Operand names starting with *p* must be pointer-sized integers. That is, they must be 64 bits on a 64-bit platform and 32 bits otherwise.

### Constants

The result of each of these instructions is a constant value.

On 32-bit platforms, `int`

is used to load constant addresses; on 64-bit platforms, `quad`

is used. The convenience function `LirWriter::insImmPtr()`

emits the appropriate instruction depending on the platform.

Note: These instructions are currently rendered in `VerboseWriter`

output as lines containing only the symbolic name of the immediate value being loaded. The instruction name and numeric value are not displayed for `short`

and `int`

instructions. This is arguably a bug.

#### short

An immediate 32-bit integer that fits in a signed 16-bit integer.

i= short<number>

must be an integer that fits in the range of a signed 16-bit integer (-32768 to 32767). The result of a `<number>``short`

instruction is a 32-bit integer with the same value (sign-extended).

The result is a 32-bit integer. This is exactly like `int`

but saves a few bytes in the `LirBuffer`

.

#### int

An immediate 32-bit value.

i= int<number>

must be an integer that fits in `<number>``int32_t`

or `uint32_t`

.

#### quad

An immediate 64-bit value.

q= quad<number>

must be either an integer that fits in a signed or unsigned 64-bit integer; or a floating-point number (containing a decimal point).`<number>`

### Integer arithmetic

#### neg

32-bit integer negation.

i= negi1

#### add

32-bit integer addition.

i= addi1,i2

#### qiadd

64-bit integer addition.

q= qiaddq1,q2

#### sub

32-bit integer subtraction.

i= subi1,i2

#### mul

32-bit integer multiplication.

i= muli1,i2

#### and

32-bit bitwise AND.

i= andi1,i2

#### qiand

64-bit bitwise AND.

q= qiandq1,q2

#### or

32-bit bitwise OR.

i= ori1,i2

#### qior

64-bit bitwise OR.

q= qiorq1,q2

#### xor

32-bit bitwise XOR.

i= ori1,i2

#### not

32-bit bitwise NOT.

i= noti1

### Bit shifting

The bit shifting operations behave as in Java and ECMAScript. When the first operand is 32-bit, all but the five least-significant bits of the second operand are discarded. (See {{ es3_spec("11.7.1") }}.) When the first operand is 64-bit, all but the six least-significant bits are discarded.

#### lsh

32-bit left shift.

i= lshi1,i2

The result is

left-shifted by `i1`

bits.`i2` & 0x1f

#### qilsh

64-bit left shift.

q= qilshq1,i2

The result is

left-shifted by `q1`

bits.`i2` & 0x3f

#### rsh

32-bit right shift with sign extend.

i= rshi1,i2

The result is

right-shifted by `q1`

bits. New bits shifted into the result match the sign bit of `i2` & 0x1f

.`i1`

#### ush

32-bit unsigned right shift.

i= ushi1,i2

The result is

right-shifted by `q1`

bits. New bits shifted into the result are zero.`i2` & 0x1f

### Floating-point arithmetic

Any 64-bit value may be treated as a floating-point number. These operations behave according to the rules of IEEE 754 double-precision arithmetic. Some details may be found in the ECMAScript language standard, {{ Es3_spec("11.5.1") }} and subsequent sections.

#### fneg

Floating-point negation.

f= fnegf1

#### fadd

Floating-point addition.

f= faddf1,f2

#### fsub

Floating-point subtraction.

f= fsubf1,f2

#### fmul

Floating-point multiplication.

f= mulf1,f2

#### fdiv

Floating-point division.

f= divf1,f2

### Numeric conversions

#### qlo

Get the low 32 bits of a 64-bit value.

i= qloq

#### qhi

Get the high 32 bits of a 64-bit value.

i= qhiq

#### qjoin

Join two 32-bit values to form a 64-bit value.

q= qjoini1,i2

#### i2f

Convert signed 32-bit integer to floating-point number.

f= i2fi1

#### u2f

Convert unsigned 32-bit integer to floating-point number.

f= u2fi1

### Loads and stores

LIR provides a single addressing mode. Each load or store instruction takes a pointer provided by a previous instruction and a constant offset (in bytes). The

must fit in the range of a signed 32-bit integer, even on 64-bit platforms.`offset`

Although the `ld`

instruction takes 2 operands, a pointer and offset, the second operand must be the result of an `int`

instruction. This is enforced with assertions.

The convenience functions `LirWriter::insLoad(LOpcode op, LIns *base, int32_t offset)`

and `LirWriter::insStorei(LIns *value, LIns *base, int32_t offset)`

should be used to emit loads and stores.

#### ld

32-bit load. This instruction is never removed by common subexpression elimination.

i= ldp1[offset]

#### ldq

64-bit load. This instruction is never removed by common subexpression elimination.

q= ldqp1[offset]

#### ldcb

8-bit load. This instruction may be removed by common subexpression elimination.

i= ldcbp1[offset]

#### ldcs

16-bit load. This instruction may be removed by common subexpression elimination.

i= ldcsp1[offset]

#### ldc

32-bit load. This instruction may be removed by common subexpression elimination.

i= ldcp1[offset]

#### ldqc

64-bit load. This instruction may be removed by common subexpression elimination.

q= ldqcp1[offset]

#### st

32-bit store.

stp1[offset] =i2

#### stq

64-bit store.

stqp1[offset] =q2

must fit in the range of a 32-bit integer, even on 64-bit platforms.`offset`

#### sti

32-bit store.

stip1[offset] =i2

must be in the range [-128, 127]. `offset``sti`

is identical to the corresponding `st`

instruction but takes a few bytes less to represent in a `LirBuffer`

.

#### stqi

64-bit store.

stqip1[offset] =q2

must be in the range [-128, 127]. `offset``sti`

is identical to the corresponding `st`

instruction but takes a few bytes less to represent in a `LirBuffer`

.

### Subroutine calls

#### calli

Indirect subroutine call returning a 32-bit integer value.

#### call

Subroutine call returning a 32-bit integer value.

#### callh

#### fcalli

Indirect subroutine call returning a 64-bit value.

#### fcall

Subroutine call returning a 64-bit value.

#### ret

#### fret

### Conditions

The result of these instructions is a 32-bit value, either 1 (true) or 0 (false). Conditions are used as operands to conditional branch, guard, and conditional move instructions.

#### eq

32-bit integer equality test.

b= eqi1,i2

There is no not-equal instruction. Instead, flip the instruction that uses the result, or add a `not`

instruction.

#### lt

Signed 32-bit integer less-than test.

b= lti1,i2

#### gt

Signed 32-bit integer greater-than test.

b= gti1,i2

#### le

Signed 32-bit integer less-than-or-equals test.

b= lei1,i2

#### ge

Signed 32-bit integer greater-than-or-equals test.

b= gei1,i2

#### ult

Unsigned 32-bit integer less-than test.

b= ulti1,i2

#### ugt

Unsigned 32-bit integer greater-than test.

b= ugti1,i2

#### ule

Unsigned 32-bit integer less-than-or-equals test.

b= ulei1,i2

#### uge

Unsigned 32-bit integer greater-than-or-equals test.

b= ugei1,i2

#### feq

Floating-point equality test.

b= feqf1,f2

#### flt

Floating-point less-than test.

b= fltf1,f2

#### fgt

Floating-point greater-than test.

b= fgtf1,f2

#### fle

Floating-point less-than-or-equals test.

b= flef1,f2

#### fge

Floating-point greater-than-or-equals test.

b= fgef1,f2

#### ov

Test for overflow.

b= ovi1

The result is `1`

if

is the result of an `i1``add`

, `sub`

, or `neg`

that overflowed the range of a signed 32-bit integer, for example.

Note: nanojit may produce incorrect code if this instruction does not immediately follow the instruction that produced

. On Intel, this reads the overflow condition flag. Other platforms have to emulate this behavior.`i1`

#### cs

Test for carry.

b= csi1

The result is `1`

if

is the result of an `i1``add`

that overflowed the range of an unsigned 32-bit integer, for example.

Note: nanojit may produce incorrect code if this instruction does not immediately follow the instruction that produced

. On Intel, this reads the carry condition flag. Other platforms have to emulate this behavior.`i1`

### Guards

Note: `VerboseWriter::formatGuard`

is left undefined in nanojit, so applications can display more information about the side exit alongside these instructions.

#### loop

Loop fragment.

loop

#### x

Exit unconditionally.

x

#### xt

Exit if true.

xtcondition

#### xf

Exit if false.

#### xbarrier

Do not exit but emit writes to flush all values to the stack.

### Forward branches

To emit forward branches in LIR, first emit a jump instruction. Later, emit a `label`

instruction and use `LIns::target`

to set the target of the jump instruction to the `LIns *`

of the `label`

.

#### j

Jump unconditionally.

jlabel

#### jt

Jump if true.

jtcondition,label

#### jf

Jump if false.

jfcondition,label

#### label

A jump target. This LIR instruction is used to hook up jumps to their targets. No machine code is emitted.

label:

#### ji

Indirect jump.

### Conditional moves

Note: These two instructions can be written using the idiom `lirwriter->ins2(LIR_cmov, b1, lirwriter->ins2(LIR_2, i2, i3))`

. The `LIR_2`

instruction serves only to group the second and third operands, since `LirWriter`

has no `ins3`

method.

The `LirWriter::ins_choose()`

convenience method can be used instead. It uses the above idiom.

#### cmov

Choice of two 32-bit values.

i= cmovb1,i2,i3

#### qcmov

Choice of two 64-bit values.

Note: This instruction currently does not work on 32-bit Intel platforms.

q= qcmovb1,q2,q3

### Special operations

#### start

Indicates the start of a fragment.

start

#### nearskip

Used to skip across blobs of binary data in the LIR, such as guard records. Also used internally to allow `LirBuffer`

s to continue across multiple pages.

#### skip

Used to skip across blobs of binary data in the LIR, such as guard records. Also used internally to allow `LirBuffer`

s to continue across multiple pages.

### Operations that are weird but don't count as special

#### addp

#### param

#### file

#### line

#### alloc

Allocate stack space, as though with the C standard library function `alloca`

.

p= allocsize

must be a multiple of 4 that does not exceed 262140 (`size``0xffff << 2`

).

#### live

Extend live range of reference.

livex

Here

may be the result of any previous instruction that produces a value.`x`