# 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); SP = SP; goto ; } :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 ################################################################################################## #compute and display one match,offset pair LookupSwitch_match:match _offset is matchbyte1; matchbyte2; matchbyte3; matchbyte4; offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [match = (matchbyte1 << 24) | (matchbyte2 << 16) | (matchbyte3 << 8) | (matchbyte4); _offset = inst_start + ((offsetbyte1 << 24) | (offsetbyte2 << 16) | (offsetbyte3 << 8) | (offsetbyte4)); ] { } #consume one match,offset pair and decrement the switch number :^LookupSwitch_match, instruction is (in_lookup_switch=1 & in_table_switch=0); LookupSwitch_match; instruction [switch_num = switch_num - 1;] { } #leave the switch statement :""LookupSwitch_match is (in_lookup_switch=1 & switch_num=1 & in_table_switch=0); LookupSwitch_match [in_lookup_switch=0;] { } 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; } #Note: "Default" constructor does not play nice with switchAssist injection... dolookupswitch: _default, npairs is alignmentPad & defaultbyte1; defaultbyte2; defaultbyte3; defaultbyte4; npairsbyte1; npairsbyte2; npairsbyte3; npairsbyte4 [ npairs = (npairsbyte1 << 24) | (npairsbyte2 << 16) | (npairsbyte3 << 8) | npairsbyte4; _default = inst_start + ((defaultbyte1 << 24) | (defaultbyte2 << 16) | (defaultbyte3 << 8) | defaultbyte4); switch_num = npairs; in_lookup_switch = 1;] { local _padding:1 = alignmentPad; local _opcodeAddr:$(SIZE) = inst_start; local _key:$(SIZE) = 0; pop(_key); local _address:$(SIZE) = switchAssist(_key,_opcodeAddr,_padding,_default:$(SIZE),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 ######################################################################################################################## #compute and display one switch offset Switch_offset:_offset is offsetbyte1; offsetbyte2; offsetbyte3; offsetbyte4 [ _offset = inst_start + ((offsetbyte1<<24) | (offsetbyte2<<16) | (offsetbyte3<<8) | offsetbyte4); ] { } # 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_offset, instruction is (in_table_switch=1 & in_lookup_switch=0); Switch_offset; instruction [switch_num = switch_num - 1;] { } #Last switch entry. Get out of switch context. :""Switch_offset is (in_table_switch=1 & in_lookup_switch=0 &switch_num=0); Switch_offset [ in_table_switch=0; ] { } 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; ] { local _offset :$(SIZE) = 0; local idx :$(SIZE) = 0; local 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; } #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); }