ghidra/Ghidra/Processors/JVM/data/languages/JVM.slaspec

2164 lines
52 KiB
Plaintext

# Stack Convention:
# 1) Stack grows to smaller addresses (Subtract to push)
# 2) Stack pointer points to a valid item on the stack
# A Java "word" can hold a boolean, byte, short, float, int, reference, or returnAddress.
# Two "words" hold a long or a double
@define SIZE "4" # Number of bytes in the Java Word
@define DOUBLE_SIZE "8"
@define INT_SUPPORT "1"
###############################################################################
# Basic Definitions
###############################################################################
define endian=big;
define alignment=1;
define space ram type=ram_space size=$(SIZE) default;
define space register type=register_space size=$(SIZE);
define space constantPool type=ram_space size=$(SIZE);
define space localVariableArray type=ram_space size=$(SIZE);
define space parameterSpace type=ram_space size=$(SIZE);
define register offset = 0x0 size=$(DOUBLE_SIZE) [cat2_return_value];
define register offset = 0x0 size=$(SIZE) [_ return_value SP PC switch_target return_address call_target LVA];
#define register offset = 0x0 size=$(DOUBLE_SIZE) [cat2_return_value];
#define register offset = 0x8 size=$(SIZE) [return_value SP PC switch_target return_address call_target LVA];
define register offset=0x100 size=16 [ switch_ctrl ];
@define CPOOL_ANEWARRAY "0:4"
@define CPOOL_CHECKCAST "1:4"
@define CPOOL_GETFIELD "2:4"
@define CPOOL_GETSTATIC "3:4"
#also used for ldc_w
@define CPOOL_LDC "4:4"
@define CPOOL_LDC2_W "5:4"
@define CPOOL_INSTANCEOF "6:4"
@define CPOOL_INVOKEDYNAMIC "7:4"
@define CPOOL_INVOKEINTERFACE "8:4"
@define CPOOL_INVOKESPECIAL "9:4"
@define CPOOL_INVOKESTATIC "10:4"
@define CPOOL_INVOKEVIRTUAL "11:4"
@define CPOOL_MULTIANEWARRAY "12:4"
@define CPOOL_NEW "13:4"
@define CPOOL_NEWARRAY "14:4"
@define CPOOL_PUTSTATIC "15:4"
@define CPOOL_PUTFIELD "16:4"
@define CPOOL_ARRAYLENGTH "17:4"
#
#defined ops ending in "CallOther" are used for pcode injection
#
define pcodeop getFieldCallOther;
define pcodeop getStaticCallOther;
define pcodeop ldcCallOther;
define pcodeop ldc_wCallOther;
define pcodeop ldc2_wCallOther;
define pcodeop invokedynamicCallOther;
define pcodeop invokeinterfaceCallOther;
define pcodeop invokespecialCallOther;
define pcodeop invokestaticCallOther;
define pcodeop invokevirtualCallOther;
define pcodeop multianewarrayCallOther;
define pcodeop putStaticCallOther;
define pcodeop putFieldCallOther;
#
# defined ops ending in "Op" are black-box instructions
#
define pcodeop athrowOp;
define pcodeop checkcastOp;
define pcodeop dremOp;
define pcodeop fremOp;
define pcodeop monitorenterOp;
define pcodeop monitorexitOp;
define pcodeop multianewarrayOp;
define pcodeop multianewarrayProcessAdditionalDimensionsOp;
define pcodeop throwExceptionOp;
###############################################################################
# Context
###############################################################################
define context switch_ctrl
switch_low = (0,31) noflow
switch_high = (32,63) noflow
switch_num = (64,95) noflow
in_table_switch = (96,97) noflow
in_lookup_switch = (98,99) noflow
alignmentPad = (100,101) noflow
padVal = (100,101) noflow
;
###############################################################################
# TOKENS
###############################################################################
define token opcode (8)
op = (0,7)
;
define token w_opcode (16)
w_op = (0,15)
;
define token data8 (8)
n = (0,3)
m = (4,7)
atype = (0,7)
byte = (0,7)
byte1 = (0,7)
byte2 = (0,7)
byte3 = (0,7)
byte4 = (0,7)
sbyte = (0,7) signed
branch = (0,7) signed
branchbyte1 = (0,7) signed
branchbyte2 = (0,7)
branchbyte3 = (0,7)
branchbyte4 = (0,7)
index = (0,7)
indexbyte1 = (0,7)
indexbyte2 = (0,7)
constant = (0,7)
constantbyte1= (0,7)
constantbyte2= (0,7)
nargs = (0,7)
method = (0,7)
defaultbyte1 = (0,7)
defaultbyte2 = (0,7)
defaultbyte3 = (0,7)
defaultbyte4 = (0,7)
highbyte1 = (0,7)
highbyte2 = (0,7)
highbyte3 = (0,7)
highbyte4 = (0,7)
lowbyte1 = (0,7)
lowbyte2 = (0,7)
lowbyte3 = (0,7)
lowbyte4 = (0,7)
npairsbyte1 = (0,7)
npairsbyte2 = (0,7)
npairsbyte3 = (0,7)
npairsbyte4 = (0,7)
dimensions = (0,7)
blank1 = (0,7)
blank2 = (0,7)
count = (0,7)
pad = (0,7)
pad1 = (0,7)
pad2 = (0,7)
pad3 = (0,7)
wide_op = (0,7)
;
define token switch (8)
matchbyte1 = (0,7)
matchbyte2 = (0,7)
matchbyte3 = (0,7)
matchbyte4 = (0,7)
offsetbyte1 = (0,7)
offsetbyte2 = (0,7)
offsetbyte3 = (0,7)
offsetbyte4 = (0,7)
;
###############################################################################
# Macros
###############################################################################
macro push(x)
{
SP = SP - $(SIZE);
*:$(SIZE) SP = x;
}
macro pop(x)
{
x = *:$(SIZE) SP;
SP = SP + $(SIZE);
}
macro push2(x)
{
SP = SP - $(DOUBLE_SIZE);
*:$(DOUBLE_SIZE) SP = x:$(DOUBLE_SIZE);
}
macro pop2(x)
{
x = *:$(DOUBLE_SIZE) SP;
SP = SP + $(DOUBLE_SIZE);
}
###############################################################################
# Pseudo Instructions
###############################################################################
Branch:addr is branchbyte1; branchbyte2 [ addr = inst_start + (branchbyte1<<8 | branchbyte2); ]
{
export *:$(SIZE) addr;
}
Branch_w:addr is branchbyte1; branchbyte2; branchbyte3; branchbyte4 [ addr = inst_start + ((branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4); ]
{
export *:$(SIZE) addr;
}
Default:"default" addr is defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4 [ addr = inst_start + ((defaultbyte1<<24) | (defaultbyte2<<16) | (defaultbyte3 << 8) | defaultbyte4); ]
{
export *:$(SIZE) addr;
}
###############################################################################
# Constructors
###############################################################################
:aaload is (in_table_switch=0 & in_lookup_switch=0 & op=0x32)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
pop(_index);
pop(_arrayref);
_offset:$(SIZE) = _arrayref + $(SIZE) * _index;
_value:$(SIZE) = *[ram] _offset;
push(_value);
}
:aastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x53)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value :$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
_offset:$(SIZE) = _arrayref + $(SIZE) * _index;
*[ram]:$(SIZE) _offset = _value;
}
:aconst_null is (in_table_switch=0 & in_lookup_switch=0 & op=0x01)
{
push(0:4);
}
:aload index is (in_table_switch=0 & in_lookup_switch=0 & op=0x19); index
{
LVA = $(SIZE) * index;
_objectref :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_objectref);
}
:aload_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x2a)
{
LVA = 0;
_objectref :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_objectref);
}
:aload_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x2b)
{
LVA = 1 * $(SIZE);
_objectref :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_objectref);
}
:aload_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x2c)
{
LVA = 2 * $(SIZE);
_objectref :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_objectref);
}
:aload_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x2d)
{
LVA = 3 * $(SIZE);
_objectref :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_objectref);
}
:anewarray index is (in_table_switch=0 & in_lookup_switch=0 & op=0xbd); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
_count :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
pop(_count);
_ref: $(SIZE) = cpool(0:4,index,$(CPOOL_ANEWARRAY));
_arrayref = newobject(_ref,_count);
push(_arrayref);
}
:areturn is (in_table_switch=0 & in_lookup_switch=0 & op=0xb0)
{
pop(return_value);
return [return_address];
}
:arraylength is (in_table_switch=0 & in_lookup_switch=0 & op=0xbe)
{
_arrayref :$(SIZE) = 0;
_length :$(SIZE) = 0;
pop(_arrayref);
_length = cpool(_arrayref, 0:4, $(CPOOL_ARRAYLENGTH));
push(_length);
}
:astore index is (in_table_switch=0 & in_lookup_switch=0 & op=0x3a); index
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index*$(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:astore_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x4b)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 0;
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:astore_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x4c)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 1 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:astore_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x4d)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 2 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:astore_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x4e)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 3 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:athrow is (in_table_switch=0 & in_lookup_switch=0 & op=0xbf)
{
_objectref :$(SIZE) = 0;
pop(_objectref);
athrowOp(_objectref);
<loop>
SP = SP;
goto <loop>;
}
:baload is (in_table_switch=0 & in_lookup_switch=0 & op=0x33)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value:1 = 0;
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + _index;
_value = *[ram]:1 _offset;
_valueSignExtended:$(SIZE) = sext(_value);
push(_valueSignExtended);
}
:bastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x54)
{
_value :$(SIZE) = 0;
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + _index;
*[ram]:1 _offset = _value:1;
}
:bipush sbyte is (in_table_switch=0 & in_lookup_switch=0 & op=0x10); sbyte
{
_value:$(SIZE) = sext(sbyte:1);
push(_value);
}
:caload is (in_table_switch=0 & in_lookup_switch=0 & op=0x34)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value:2 = 0;
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + 2 * _index;
_value = *[ram]:2 _offset;
_valueZeroExtended:$(SIZE) = zext(_value);
push(_valueZeroExtended);
}
:castore is (in_table_switch=0 & in_lookup_switch=0 & op = 0x55)
{
_value :$(SIZE) = 0;
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + 2 * _index;
*[ram]:2 _offset = _value:2;
}
:checkcast index is (in_table_switch=0 & in_lookup_switch=0 & op=0xc0); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
#_object: $(SIZE) = *:$(SIZE) SP;
#throwExceptionOp(_object);
#_res:1 = cpool(_object,index,$(CPOOL_CHECKCAST));
#throwExceptionOp(_res);
#_ref: $(SIZE) = cpool(0:4,index,$(CPOOL_CHECKCAST));
#checkcastOp(_object,_ref);
_object:$(SIZE) = 0;
pop(_object);
_object = cpool(_object,index,$(CPOOL_CHECKCAST));
push(_object);
#_res:1 = cpool(_object,index,$(CPOOL_CHECKCAST));
#_result:$(SIZE) = zext(_res);
#push(_result);
}
:d2f is (in_table_switch=0 & in_lookup_switch=0 & op=0x90)
{
_double :$(DOUBLE_SIZE) = 0;
_float :$(SIZE) = 0;
pop2(_double);
_float = float2float(_double);
push(_float);
}
#this is not exactly the algorithm that the JVM uses to convert doubles to ints
#should be good enough
:d2i is (in_table_switch=0 & in_lookup_switch=0 & op=0x8e)
{
_double :$(DOUBLE_SIZE) = 0;
_int :$(DOUBLE_SIZE) = 0;
pop2(_double);
_int = round(_double);
push(_int:$(SIZE));
}
#this is not exactly the algorithm that the JVM uses to convert doubles to longs
:d2l is (in_table_switch=0 & in_lookup_switch=0 & op=0x8f)
{
_double :$(DOUBLE_SIZE) = 0;
_long :$(DOUBLE_SIZE) = 0;
pop2(_double);
_long = round(_double);
push2(_long);
}
:dadd is (in_table_switch=0 & in_lookup_switch=0 & op=0x63)
{
_value1 :$(DOUBLE_SIZE) = 0;
_value2 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 f+ _value2;
push2(_result);
}
:daload is (in_table_switch=0 & in_lookup_switch=0 & op=0x31)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value :$(DOUBLE_SIZE) = 0;
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + $(DOUBLE_SIZE) * _index;
_value = *[ram]:$(DOUBLE_SIZE) _offset;
push2(_value);
}
:dastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x52)
{
_value :$(DOUBLE_SIZE) = 0;
_index:$(SIZE) = 0;
_arrayref:$(SIZE) = 0;
pop2(_value);
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + $(DOUBLE_SIZE) * _index;
*[ram]:$(DOUBLE_SIZE) _offset = _value;
}
:dcmpg is (in_table_switch=0 & in_lookup_switch=0 & op=0x98)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = zext(_value1 f> _value2) + zext(_value1 f>= _value2) - 1;
push(_result);
}
:dcmpl is (in_table_switch=0 & in_lookup_switch=0 & op=0x97)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = zext(_value1 f> _value2) + zext(_value1 f>= _value2) - 1;
push(_result);
}
:dconst_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0e)
{
_int :$(DOUBLE_SIZE) = 0;
_double :$(DOUBLE_SIZE) = int2float(_int);
push2(_double);
}
:dconst_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0f)
{
_int :$(DOUBLE_SIZE) = 1;
_double :$(DOUBLE_SIZE) = int2float(_int);
push2(_double);
}
:ddiv is (in_table_switch=0 & in_lookup_switch=0 & op=0x6f)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 f/ _value2;
push2(_result);
}
:dload index is (in_table_switch=0 & in_lookup_switch=0 & op=0x18); index
{
LVA = index*$(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:dload_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x26)
{
LVA = 0;
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:dload_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x27)
{
LVA = 1 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:dload_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x28)
{
LVA = 2 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:dload_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x29)
{
LVA = 3 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:dmul is (in_table_switch=0 & in_lookup_switch=0 & op=0x6b)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 f* _value2;
push2(_result);
}
:dneg is (in_table_switch=0 & in_lookup_switch=0 & op=0x77)
{
_value :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value);
_result = f- _value;
push2(_result);
}
:drem is (in_table_switch=0 & in_lookup_switch=0 & op=0x73)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = dremOp(_value1, _value2);
push2(_result);
}
:dreturn is (in_table_switch=0 & in_lookup_switch=0 & op=0xaf)
{
pop2(cat2_return_value);
return [return_address];
}
:dstore index is (in_table_switch=0 & in_lookup_switch=0 & op=0x39); index
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = index*$(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:dstore_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x47)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 0;
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:dstore_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x48)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 1 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:dstore_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x49)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 2 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:dstore_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x4a)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 3 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:dsub is (in_table_switch=0 & in_lookup_switch=0 & op=0x67)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 f- _value2;
push2(_result);
}
:dup is (in_table_switch=0 & in_lookup_switch=0 & op=0x59)
{
local word = *:$(SIZE) SP;
push(word);
}
:dup_x1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x5a)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
push(_value1);
push(_value2);
push(_value1);
}
:dup_x2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x5b)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
_value3 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
pop(_value3);
push(_value1);
push(_value3);
push(_value2);
push(_value1);
}
:dup2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x5c)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
push(_value2);
push(_value1);
push(_value2);
push(_value1);
}
:dup2_x1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x5d)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
_value3 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
pop(_value3);
push(_value2);
push(_value1);
push(_value3);
push(_value2);
push(_value1);
}
:dup2_x2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x5e)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
_value3 :$(SIZE) = 0;
_value4 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
pop(_value3);
pop(_value4);
push(_value2);
push(_value1);
push(_value4);
push(_value3);
push(_value2);
push(_value1);
}
:f2d is (in_table_switch=0 & in_lookup_switch=0 & op=0x8d)
{
_value :$(SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value);
_result = float2float(_value);
push2(_result);
}
#not exactly how the JVM converts floats to ints but close enough
:f2i is (in_table_switch=0 & in_lookup_switch=0 & op=0x8b)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
_result = round(_value);
push(_result);
}
#not exactly how the JVM converts floats to longs
:f2l is (in_table_switch=0 & in_lookup_switch=0 & op=0x8c)
{
_value :$(SIZE) = 0;
_value2 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value);
_value2 = float2float(_value);
_result = round(_value2);
push2(_result);
}
:fadd is (in_table_switch=0 & in_lookup_switch=0 & op=0x62)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 f+ _value2;
push(_result);
}
:faload is (in_table_switch=0 & in_lookup_switch=0 & op=0x30)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value :$(SIZE) = 0;
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(SIZE) * _index);
_value = *[ram] (_offset);
push(_value);
}
:fastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x51)
{
_value :$(SIZE) = 0;
_index:$(SIZE) = 0;
_arrayref:$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(SIZE) * _index);
*[ram] _offset = _value;
}
:fcmpg is (in_table_switch=0 & in_lookup_switch=0 & op=0x96)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = zext(_value1 f> _value2) + zext(_value1 f>= _value2) - 1;
push(_result);
}
:fcmpl is (in_table_switch=0 & in_lookup_switch=0 & op=0x95)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = zext(_value1 f> _value2) + zext(_value1 f>= _value2) - 1;
push(_result);
}
:fconst_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0b)
{
f :$(SIZE) = 0;
fAsFloat:$(SIZE) = int2float(f);
push(fAsFloat);
}
:fconst_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0c)
{
f :$(SIZE) = 1;
fAsFloat:$(SIZE) = int2float(f);
push(fAsFloat);
}
:fconst_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0d)
{
f :$(SIZE) = 2;
fAsFloat:$(SIZE) = int2float(f);
push(fAsFloat);
}
:fdiv is (in_table_switch=0 & in_lookup_switch=0 & op=0x6e)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 f/ _value2;
push(_result);
}
:fload index is (in_table_switch=0 & in_lookup_switch=0 & op=0x17); index
{
LVA = $(SIZE) * index;
_value :$(SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push(_value);
}
:fload_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x22)
{
LVA = 0;
_value :$(SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push(_value);
}
:fload_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x23)
{
LVA = 1 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push(_value);
}
:fload_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x24)
{
LVA = 2 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push(_value);
}
:fload_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x25)
{
LVA = 3 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push(_value);
}
:fmul is (in_table_switch=0 & in_lookup_switch=0 & op=0x6a)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 f* _value2;
push(_result);
}
:fneg is (in_table_switch=0 & in_lookup_switch=0 & op=0x76)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
_result = f- _value;
push(_result);
}
:frem is (in_table_switch=0 & in_lookup_switch=0 & op=0x72)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = fremOp(_value1, _value2);
push(_result);
}
:freturn is (in_table_switch=0 & in_lookup_switch=0 & op=0xae)
{
pop(return_value);
return [return_address];
}
:fstore index is (in_table_switch=0 & in_lookup_switch=0 & op=0x38); index
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index*$(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:fstore_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x43)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 0;
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:fstore_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x44)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 1 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:fstore_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x45)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 2 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:fstore_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x46)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 3 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:fsub is (in_table_switch=0 & in_lookup_switch=0 & op=0x66)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 f- _value2;
push(_result);
}
:getfield index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb4 ); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
getFieldCallOther(index:2);
}
:getstatic index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb2); indexbyte1; indexbyte2 [index = indexbyte1 << 8 | indexbyte2;]
{
getStaticCallOther(index:2);
}
:goto Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa7); Branch
{
goto Branch;
}
:goto_w Branch_w is (in_table_switch=0 & in_lookup_switch=0 & op=0xc8); Branch_w
{
goto Branch_w;
}
:i2b is (in_table_switch=0 & in_lookup_switch=0 & op=0x91)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
local _byte = _value:1;
_result = sext(_byte);
push(_result);
}
:i2c is (in_table_switch=0 & in_lookup_switch=0 & op=0x92)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
local _char = _value:2;
_result = zext(_char);
push(_result);
}
:i2d is (in_table_switch=0 & in_lookup_switch=0 & op=0x87)
{
_value :$(SIZE) = 0;
_resultAsLong :$(DOUBLE_SIZE) = 0;
_resultAsDouble :$(DOUBLE_SIZE) = 0;
pop(_value);
_resultAsLong = sext(_value);
_resultAsDouble = int2float(_resultAsLong);
push2(_resultAsDouble);
}
:i2f is (in_table_switch=0 & in_lookup_switch=0 & op=0x86)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
_result = int2float(_value);
push(_result);
}
:i2l is (in_table_switch=0 & in_lookup_switch=0 & op=0x85)
{
_value :$(SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value);
_result = sext(_value);
push2(_result);
}
:i2s is (in_table_switch=0 & in_lookup_switch=0 & op=0x93)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
local _short = _value:2;
_result = sext(_short);
push(_result);
}
:iadd is (in_table_switch=0 & in_lookup_switch=0 & op=0x60)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 + _value2;
push(_result);
}
:iaload is (in_table_switch=0 & in_lookup_switch=0 & op=0x2e)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value :$(SIZE) = 0;
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(SIZE) * _index);
_value = *[ram] (_offset);
push(_value);
}
:iand is (in_table_switch=0 & in_lookup_switch=0 & op=0x7e)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 & _value2;
push(_result);
}
:iastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x4f)
{
_value :$(SIZE) = 0;
_index:$(SIZE) = 0;
_arrayref:$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(SIZE) * _index);
*[ram] _offset = _value;
}
:iconst_m1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x02)
{
_i :$(SIZE) = -1;
push(_i);
}
:iconst_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x03)
{
_i :$(SIZE) = 0;
push(_i);
}
:iconst_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x04)
{
_i :$(SIZE) = 1;
push(_i);
}
:iconst_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x05)
{
_i :$(SIZE) = 2;
push(_i);
}
:iconst_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x06)
{
_i :$(SIZE) = 3;
push(_i);
}
:iconst_4 is (in_table_switch=0 & in_lookup_switch=0 & op=0x07)
{
_i :$(SIZE) = 4;
push(_i);
}
:iconst_5 is (in_table_switch=0 & in_lookup_switch=0 & op=0x08)
{
_i :$(SIZE) = 5;
push(_i);
}
:idiv is (in_table_switch=0 & in_lookup_switch=0 & op=0x6c)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 s/ _value2;
push(_result);
}
:if_acmpeq Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa5); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 == _value2 ) goto Branch;
}
:if_acmpne Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa6); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 != _value2 ) goto Branch;
}
:if_icmpeq Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9f); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 == _value2 ) goto Branch;
}
:if_icmpne Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa0); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 != _value2 ) goto Branch;
}
:if_icmplt Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa1); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 s< _value2 ) goto Branch;
}
:if_icmpge Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa2); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 s>= _value2 ) goto Branch;
}
:if_icmpgt Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa3); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 s> _value2 ) goto Branch;
}
:if_icmple Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa4); Branch
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
pop(_value2);
pop(_value1);
if( _value1 s<= _value2 ) goto Branch;
}
:ifeq Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x99); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value == 0 ) goto Branch;
}
:ifne Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9a); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value != 0 ) goto Branch;
}
:iflt Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9b); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value s< 0 ) goto Branch;
}
:ifge Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9c); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value s>= 0 ) goto Branch;
}
:ifgt Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9d); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value s> 0 ) goto Branch;
}
:ifle Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0x9e); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if( _value s<= 0 ) goto Branch;
}
:ifnonnull Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xc7); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if ( _value != 0) goto Branch;
}
:ifnull Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xc6); Branch
{
_value :$(SIZE) = 0;
pop(_value);
if ( _value == 0) goto Branch;
}
:iinc index, constant is (in_table_switch=0 & in_lookup_switch=0 & op=0x84); index; constant
{
_const :$(SIZE) = 0;
LVA = index*$(SIZE);
_const = sext(constant:1);
*[localVariableArray]:$(SIZE) (LVA) = (*[localVariableArray]:$(SIZE) (LVA)) + _const;
}
:iload index is (in_table_switch=0 & in_lookup_switch=0 & op=0x15); index
{
LVA = index*$(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:iload_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1a)
{
LVA = 0;
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:iload_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1b)
{
LVA = 1 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:iload_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1c)
{ LVA = 2 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:iload_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1d)
{
LVA = 3 * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:imul is (in_table_switch=0 & in_lookup_switch=0 & op=0x68)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 * _value2;
push(_result);
}
:ineg is (in_table_switch=0 & in_lookup_switch=0 & op=0x74)
{
_value :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value);
_result = -_value;
push(_result);
}
:instanceof index is (in_table_switch=0 & in_lookup_switch=0 & op=0xc1); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
_object:$(SIZE) = 0;
pop(_object);
_res:1 = cpool(_object,index,$(CPOOL_INSTANCEOF));
_result:$(SIZE) = zext(_res);
push(_result);
}
:invokedynamic index, blank1, blank2 is (in_table_switch=0 & in_lookup_switch=0 & op=0xba); indexbyte1; indexbyte2; blank1; blank2 [ index = indexbyte1<<8 | indexbyte2; ]
{
invokedynamicCallOther(index:2);
}
:invokeinterface index, count, blank1 is (in_table_switch=0 & in_lookup_switch=0 & op=0xb9); indexbyte1; indexbyte2; count; blank1 [ index = indexbyte1<<8 | indexbyte2; ]
{
invokeinterfaceCallOther(index:2);
}
:invokespecial index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb7); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
invokespecialCallOther(index:2);
}
:invokestatic index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb8); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
invokestaticCallOther(index:2);
}
:invokevirtual index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb6); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
invokevirtualCallOther(index:2);
}
:ior is (in_table_switch=0 & in_lookup_switch=0 & op=0x80)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 | _value2;
push(_result);
}
:irem is (in_table_switch=0 & in_lookup_switch=0 & op=0x70)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 s% _value2;
push(_result);
}
:ireturn is (in_table_switch=0 & in_lookup_switch=0 & op=0xac)
{
pop(return_value);
return [return_address];
}
:ishl is (in_table_switch=0 & in_lookup_switch=0 & op=0x78)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 << (_value2 & 0x1f);
push(_result);
}
:ishr is (in_table_switch=0 & in_lookup_switch=0 & op=0x7a)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 s>> (_value2 & 0x1f);
push(_result);
}
:istore index is (in_table_switch=0 & in_lookup_switch=0 & op=0x36); index
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index*$(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:istore_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x3b)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 0;
*[localVariableArray]:$(SIZE) (LVA) =_value;
}
:istore_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x3c)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 1 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) =_value;
}
:istore_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x3d)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 2 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) =_value;
}
:istore_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x3e)
{
_value :$(SIZE) = 0;
pop(_value);
LVA = 3 * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) =_value;
}
:isub is (in_table_switch=0 & in_lookup_switch=0 & op=0x64)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 - _value2;
push(_result);
}
:iushr is (in_table_switch=0 & in_lookup_switch=0 & op=0x7c)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 >> (_value2 & 0x1f);
push(_result);
}
:ixor is (in_table_switch=0 & in_lookup_switch=0 & op=0x82)
{
_value2 :$(SIZE) = 0;
_value1 :$(SIZE) = 0;
_result :$(SIZE) = 0;
pop(_value2);
pop(_value1);
_result = _value1 ^ _value2;
push(_result);
}
:jsr Branch is (in_table_switch=0 & in_lookup_switch=0 & op=0xa8); Branch
{
retAddr :$(SIZE) = inst_next;
push(retAddr);
goto Branch;
}
:jsr_w Branch_w is (in_table_switch=0 & in_lookup_switch=0 & op=0xc9); Branch_w
{
retAddr :$(SIZE) = inst_next;
push(retAddr);
goto Branch_w;
}
:l2d is (in_table_switch=0 & in_lookup_switch=0 & op=0x8a)
{
_value :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value);
_result = int2float(_value);
push2(_result);
}
:l2f is (in_table_switch=0 & in_lookup_switch=0 & op=0x89)
{
_value :$(DOUBLE_SIZE) = 0;
_result :$(SIZE) = 0;
pop2(_value);
_result = int2float(_value);
push(_result);
}
:l2i is (in_table_switch=0 & in_lookup_switch=0 & op=0x88)
{
_value :$(DOUBLE_SIZE) = 0;
_result :$(SIZE) = 0;
pop2(_value);
_result = _value:$(SIZE);
push(_result);
}
:ladd is (in_table_switch=0 & in_lookup_switch=0 & op=0x61)
{
_value1 :$(DOUBLE_SIZE) = 0;
_value2 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 + _value2;
push2(_result);
}
:laload is (in_table_switch=0 & in_lookup_switch=0 & op=0x2f)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value :$(DOUBLE_SIZE) = 0;
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(DOUBLE_SIZE) * _index);
_value = *[ram]:$(DOUBLE_SIZE) (_offset);
push2(_value);
}
:land is (in_table_switch=0 & in_lookup_switch=0 & op=0x7f)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 & _value2;
push2(_result);
}
:lastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x50)
{
_value :$(DOUBLE_SIZE) = 0;
_index:$(SIZE) = 0;
_arrayref:$(SIZE) = 0;
pop2(_value);
pop(_index);
pop(_arrayref);
local _offset = _arrayref + ($(DOUBLE_SIZE) * _index);
*[ram]:$(DOUBLE_SIZE) _offset = _value;
}
:lcmp is (in_table_switch=0 & in_lookup_switch=0 & op=0x94)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = zext(_value1 s> _value2) + zext(_value1 s>= _value2) - 1;
push(_result);
}
:lconst_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x09)
{
_l :$(DOUBLE_SIZE) = 0;
push2(_l);
}
:lconst_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x0a)
{
_l :$(DOUBLE_SIZE) = 1;
push2(_l);
}
:ldc index is (in_table_switch=0 & in_lookup_switch=0 & op=0x12); index
{
ldcCallOther(index:1);
}
:ldc_w index is (in_table_switch=0 & in_lookup_switch=0 & op=0x13); indexbyte1; indexbyte2 [ index = indexbyte1 << 8 | indexbyte2; ]
{
ldc_wCallOther(index:2);
}
:ldc2_w index is (in_table_switch=0 & in_lookup_switch=0 & op=0x14); indexbyte1; indexbyte2 [ index = indexbyte1 << 8 | indexbyte2; ]
{
ldc2_wCallOther(index:2);
}
:ldiv is (in_table_switch=0 & in_lookup_switch=0 & op=0x6d)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 s/ _value2;
push2(_result);
}
:lload index is (in_table_switch=0 & in_lookup_switch=0 & op=0x16); index
{
LVA = index * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:lload_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1e)
{
LVA = 0;
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:lload_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x1f)
{
LVA = 1 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:lload_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x20)
{
LVA = 2 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:lload_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x21)
{
LVA = 3 * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:lmul is (in_table_switch=0 & in_lookup_switch=0 & op=0x69)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 * _value2;
push2(_result);
}
:lneg is (in_table_switch=0 & in_lookup_switch=0 & op=0x75)
{
_value :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value);
_result= -_value;
push2(_result);
}
##################################################################################################
# lookupswitch
##################################################################################################
LookupSwitch_match:match _offset is matchbyte1; matchbyte2; matchbyte3; matchbyte4; offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [match = (matchbyte1 << 24) | (matchbyte2 << 16) | (matchbyte3 << 8) | (matchbyte4); _offset = (offsetbyte1 << 24) | (offsetbyte2 << 16) | (offsetbyte3 << 8) | (offsetbyte4); ]
{
}
LookupSwitch_case:"lscase" lscase is (in_lookup_switch=1 & in_table_switch=0) [ lscase = switch_num; switch_num = switch_num - 1;]
{
}
:^LookupSwitch_case LookupSwitch_match, instruction is (in_lookup_switch=1 & in_table_switch=0); LookupSwitch_case; LookupSwitch_match; instruction
{
}
:"lscase" lscase LookupSwitch_match is (in_lookup_switch=1 & switch_num=1 & in_table_switch=0); LookupSwitch_match [in_lookup_switch=0; lscase=switch_num; ]
{
}
define pcodeop switchAssist;
padSwitch: "" is alignmentPad = 3 & padVal & op ; pad1; pad2; pad3 { export *[const]:1 padVal; }
padSwitch: "" is alignmentPad = 2 & padVal & op ; pad1; pad2 { export *[const]:1 padVal; }
padSwitch: "" is alignmentPad = 1 & padVal & op ; pad1 { export *[const]:1 padVal; }
padSwitch: "" is alignmentPad = 0 & padVal & op { export *[const]:1 padVal; }
dolookupswitch: _default, npairs is alignmentPad & defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4; npairsbyte1; npairsbyte2; npairsbyte3; npairsbyte4 [ npairs = (npairsbyte1 << 24) | (npairsbyte2 << 16) | (npairsbyte3 << 8) | npairsbyte4; _default = (defaultbyte1 << 24) | (defaultbyte2 << 16) | (defaultbyte3 << 8) | (defaultbyte4); switch_num = npairs; in_lookup_switch = 1;]
{
_padding:1 = alignmentPad;
_opcodeAddr:$(SIZE) = inst_start;
_defaultAddr:$(SIZE) = inst_start + _default;
_key:$(SIZE) = 0;
pop(_key);
_address:$(SIZE) = switchAssist(_key,_opcodeAddr,_padding,_defaultAddr,npairs:$(SIZE));
goto [ _address ];
}
:lookupswitch dolookupswitch, instruction is in_lookup_switch=0 & in_table_switch=0 & op=0xab & alignmentPad = 0 ; dolookupswitch; instruction
{
build dolookupswitch;
}
:lookupswitch dolookupswitch, instruction is in_lookup_switch=0 & in_table_switch=0 & op=0xab & alignmentPad = 1 ; pad1; dolookupswitch; instruction
{
build dolookupswitch;
}
:lookupswitch dolookupswitch, instruction is in_lookup_switch=0 & in_table_switch=0 & op=0xab & alignmentPad = 2 ; pad1; pad2; dolookupswitch; instruction
{
build dolookupswitch;
}
:lookupswitch dolookupswitch, instruction is in_lookup_switch=0 & in_table_switch=0 & op=0xab & alignmentPad = 3 ; pad1; pad2; pad3; dolookupswitch; instruction
{
build dolookupswitch;
}
:lor is (in_table_switch=0 & in_lookup_switch=0 & op=0x81)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 | _value2;
push2(_result);
}
:lrem is (in_table_switch=0 & in_lookup_switch=0 & op=0x71)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 s% _value2;
push2(_result);
}
:lreturn is (in_table_switch=0 & in_lookup_switch=0 & op=0xad)
{
pop2(cat2_return_value);
return [return_address];
}
:lshl is (in_table_switch=0 & in_lookup_switch=0 & op=0x79)
{
_value2 :$(SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value2);
pop2(_value1);
_result = _value1 << (_value2 & 0x3f);
push2(_result);
}
:lshr is (in_table_switch=0 & in_lookup_switch=0 & op=0x7b)
{
_value2 :$(SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value2);
pop2(_value1);
_result = _value1 s>> (_value2 & 0x3f);
push2(_result);
}
:lstore index is (in_table_switch=0 & in_lookup_switch=0 & op=0x37); index
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:lstore_0 is (in_table_switch=0 & in_lookup_switch=0 & op=0x3f)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 0;
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) =_value;
}
:lstore_1 is (in_table_switch=0 & in_lookup_switch=0 & op=0x40)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 1 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) =_value;
}
:lstore_2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x41)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 2 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) =_value;
}
:lstore_3 is (in_table_switch=0 & in_lookup_switch=0 & op=0x42)
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = 3 * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) =_value;
}
:lsub is (in_table_switch=0 & in_lookup_switch=0 & op=0x65)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 - _value2;
push2(_result);
}
:lushr is (in_table_switch=0 & in_lookup_switch=0 & op=0x7d)
{
_value2 :$(SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop(_value2);
pop2(_value1);
_result = _value1 >> (_value2 & 0x3f);
push2(_result);
}
:lxor is (in_table_switch=0 & in_lookup_switch=0 & op=0x83)
{
_value2 :$(DOUBLE_SIZE) = 0;
_value1 :$(DOUBLE_SIZE) = 0;
_result :$(DOUBLE_SIZE) = 0;
pop2(_value2);
pop2(_value1);
_result = _value1 ^ _value2;
push2(_result);
}
:monitorenter is (in_table_switch=0 & in_lookup_switch=0 & op=0xc2)
{
_objectref :$(SIZE) = 0;
pop(_objectref);
monitorenterOp(_objectref);
}
:monitorexit is (in_table_switch=0 & in_lookup_switch=0 & op=0xc3)
{
_objectref :$(SIZE) = 0;
pop(_objectref);
monitorexitOp(_objectref);
}
:multianewarray index is (in_table_switch=0 & in_lookup_switch=0 & op=0xc5); indexbyte1; indexbyte2; dimensions [index = indexbyte1<<8 | indexbyte2;]
{
multianewarrayCallOther(index:2,dimensions:1);
}
:new index is (in_table_switch=0 & in_lookup_switch=0 & op=0xbb); indexbyte1; indexbyte2 [ index = indexbyte1<<8 | indexbyte2; ]
{
local _className = cpool(0:4,index,$(CPOOL_NEW));
_ref: $(SIZE) = newobject(_className);
push(_ref);
}
:newarray atype is (in_table_switch=0 & in_lookup_switch=0 & op=0xbc); atype
{
_count:$(SIZE)=0;
_arrayref:$(SIZE)=0;
pop(_count);
_ref:$(SIZE) = cpool(0:4,atype:1,$(CPOOL_NEWARRAY));
_arrayref = newobject(_ref, _count);
push(_arrayref);
}
:nop is (in_table_switch=0 & in_lookup_switch=0 & in_lookup_switch=0 & op=0x00)
{
}
:pop is (in_table_switch=0 & in_lookup_switch=0 & op=0x57)
{
SP = SP + $(SIZE);
}
:pop2 is (in_table_switch=0 & in_lookup_switch=0 & op=0x58)
{
SP = SP + $(DOUBLE_SIZE);
}
:putfield index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb5); indexbyte1; indexbyte2 [ index = indexbyte1 << 8 | indexbyte2; ]
{
putFieldCallOther(index:2);
}
:putstatic index is (in_table_switch=0 & in_lookup_switch=0 & op=0xb3); indexbyte1; indexbyte2 [index = indexbyte1 << 8 | indexbyte2; ]
{
putStaticCallOther(index:2);
}
:ret index is (in_table_switch=0 & in_lookup_switch=0 & op=0xa9); index
{
LVA = index * $(SIZE);
_value:$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
goto [_value];
}
:return is (in_table_switch=0 & in_lookup_switch=0 & op=0xb1)
{
return [return_address];
}
:saload is (in_table_switch=0 & in_lookup_switch=0 & op=0x35)
{
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
_value:2 = 0;
pop(_index);
pop(_arrayref);
_offset: $(SIZE) = _arrayref + _index * 2;
_value = *[ram]:2 _offset;
_valueSignExtended:$(SIZE) = sext(_value);
push(_valueSignExtended);
}
:sastore is (in_table_switch=0 & in_lookup_switch=0 & op=0x56)
{
_value :$(SIZE) = 0;
_index :$(SIZE) = 0;
_arrayref :$(SIZE) = 0;
pop(_value);
pop(_index);
pop(_arrayref);
local _offset = _arrayref + _index * 2;
*[ram]:$(SIZE) _offset = _value:2;
}
:sipush short is (in_table_switch=0 & in_lookup_switch=0 & op=0x11); byte1; byte2 [ short = byte1<<8 | byte2; ]
{
_result:$(SIZE) = sext(short:2);
push(_result);
}
:swap is (in_table_switch=0 & in_lookup_switch=0 & op=0x5f)
{
_value1 :$(SIZE) = 0;
_value2 :$(SIZE) = 0;
pop(_value1);
pop(_value2);
push(_value1);
push(_value2);
}
########################################################################################################################
# tableswitch
########################################################################################################################
Switch_offset:_offset is offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [ _offset = inst_start + ((offsetbyte1<<24) | (offsetbyte2<<16) | (offsetbyte3<<8) | offsetbyte4); ]
{
}
Switch_case:"case" case is (in_table_switch=1) [ case = switch_high-switch_num; switch_num=switch_num-1; ]
{
}
dotableswitch: Default, low, high is alignmentPad & Default;lowbyte1; lowbyte2; lowbyte3; lowbyte4; highbyte1; highbyte2; highbyte3; highbyte4 [ low = (lowbyte1 << 24) | (lowbyte2 << 16) | (lowbyte3 << 8) | lowbyte4; high = (highbyte1 << 24) | (highbyte2 << 16) | (highbyte3 << 8) | highbyte4; switch_low = low; switch_num = high - low; switch_high = high; in_table_switch = 1; ]
{
_offset :$(SIZE) = 0;
idx :$(SIZE) = 0;
padding:$(SIZE) = alignmentPad;
pop(idx);
if (idx s< low) goto Default;
if (idx s> high) goto Default;
#opcode_address + byte_for_opcode + padding + default + low + high = start of table
_offset = inst_start + 1 + padding + 4 + 4 + 4 + 4*(idx-low);
switch_target = inst_start + *:$(SIZE)(_offset);
goto [switch_target];
}
:tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=0; dotableswitch; instruction
{
build dotableswitch;
}
:tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=1; pad1; dotableswitch; instruction
{
build dotableswitch;
}
:tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=2; pad1; pad2; dotableswitch; instruction
{
build dotableswitch;
}
:tableswitch dotableswitch, instruction is in_table_switch=0 & in_lookup_switch=0 & op=0xaa & alignmentPad=3; pad1; pad2; pad3; dotableswitch; instruction
{
build dotableswitch;
}
# Switch entry that's not the last one.
# no pcode def - this construction is just for consuming all of the bytes of a tableswitch instructions
# decrements the switch number
:^Switch_case Switch_offset, instruction is (in_table_switch=1 & in_lookup_switch=0); Switch_case; Switch_offset; instruction
{
}
#Last switch entry. Get out of switch context.
:"case" case Switch_offset is (in_table_switch=1 & in_lookup_switch=0 &switch_num=0); Switch_offset [ in_table_switch=0; case=switch_high-switch_num; ]
{
}
#wide loads
:wide_iload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc415); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{
LVA = index * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:wide_fload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc417); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{
LVA = index * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:wide_aload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc419); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{
LVA = index * $(SIZE);
_value :$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
push(_value);
}
:wide_lload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc416); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{
LVA = index * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
:wide_dload index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc418); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2; ]
{
LVA = index * $(SIZE);
_value :$(DOUBLE_SIZE) = *[localVariableArray]:$(DOUBLE_SIZE) (LVA);
push2(_value);
}
#wide stores
:wide_istore index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc436); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:wide_fstore index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc438); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:wide_astore index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc43a); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
_value :$(SIZE) = 0;
pop(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(SIZE) (LVA) = _value;
}
:wide_lstore index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc437); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
:wide_dstore index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc439); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
_value :$(DOUBLE_SIZE) = 0;
pop2(_value);
LVA = index * $(SIZE);
*[localVariableArray]:$(DOUBLE_SIZE) (LVA) = _value;
}
#wide ret
:wide_ret index is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc4a9); indexbyte1; indexbyte2 [index = (indexbyte1 << 8) | indexbyte2;]
{
LVA = index * $(SIZE);
_value:$(SIZE) = *[localVariableArray]:$(SIZE) (LVA);
goto [_value];
}
#wide inc - instruction is called wide format 2 by JVM specification but iinc_w by javap
:iinc_w index, constant is (in_table_switch=0 & in_lookup_switch=0 & w_op=0xc484); indexbyte1; indexbyte2; constantbyte1; constantbyte2 [ index = (indexbyte1 << 8) | indexbyte2; constant = (constantbyte1 << 8) | constantbyte2;]
{
fullIndex: $(SIZE) = 4*zext(index:2);
fullConstant: $(SIZE) = sext(constant:2);
intVal:$(SIZE) = *[localVariableArray]:$(SIZE) (fullIndex);
*[localVariableArray]:$(SIZE) (fullIndex) = (intVal + fullConstant);
}