void WordcodeEmitter::emitPushuint(const uint8_t *pc)
	{
		// FIXME: wrong for 64-bit, we want 32 bits of payload
		pc++;
		uint32_t value = pool->cpool_uint[AvmCore::readU30(pc)];
		if ((value & 0xF0000000U) == 0) {
			CHECK(2);
			*dest++ = NEW_OPCODE(WOP_pushbits);
			*dest++ = (value << 3) | kIntegerType;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
			peep(WOP_pushbits, dest-2);
#endif
		}
		else {
			union {
				double d;
				uint32_t bits[2];
			} v;
			v.d = (double)value;
			CHECK(3);
			*dest++ = NEW_OPCODE(WOP_push_doublebits);
			*dest++ = v.bits[0];
			*dest++ = v.bits[1];
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
			peep(WOP_push_doublebits, dest-3);
#endif
		}
	}
void ST_avmplus_peephole::test0() {

#ifdef AVMPLUS_DIRECT_THREADED
    WordcodeEmitter* t = new WordcodeEmitter(core, NULL, opcode_labels);
#else
    WordcodeEmitter* t = new WordcodeEmitter(core, NULL);
#endif

     t->emitOp1(WOP_getlocal, 5);
     t->emitOp1(WOP_getlocal, 4);
     t->emitOp1(WOP_getlocal, 65536);
     t->emitOp1(WOP_getlocal, 7);
     t->emitOp1(WOP_getlocal, 6);
     uint32_t* code;
     uint32_t len = t->epilogue(&code);

verifyPass(len == 6, "len == 6", __FILE__, __LINE__);
verifyPass(code[0] == NEW_OPCODE(WOP_get2locals), "code[0] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
verifyPass(code[1] == ((4 << 16) | 5), "code[1] == ((4 << 16) | 5)", __FILE__, __LINE__);
verifyPass(code[2] == NEW_OPCODE(WOP_getlocal), "code[2] == NEW_OPCODE(WOP_getlocal)", __FILE__, __LINE__);
verifyPass(code[3] == 65536, "code[3] == 65536", __FILE__, __LINE__);
verifyPass(code[4] == NEW_OPCODE(WOP_get2locals), "code[4] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
verifyPass(code[5] == ((6 << 16) | 7), "code[5] == ((6 << 16) | 7)", __FILE__, __LINE__);

    delete t;


}
예제 #3
0
void ST_avmplus_peephole::test0() {

    WordcodeEmitter* t = new WordcodeEmitter(core, NULL);

     t->emitOp1(WOP_getlocal, 5);
     t->emitOp1(WOP_getlocal, 4);
     t->emitOp1(WOP_getlocal, 65536);
     t->emitOp1(WOP_getlocal, 7);
     t->emitOp1(WOP_getlocal, 6);
     uintptr_t* code;
uint32_t len = (uint32_t)t->epilogue(&code);

#line 76 "ST_avmplus_peephole.st"
verifyPass(len == 6, "len == 6", __FILE__, __LINE__);
#line 77 "ST_avmplus_peephole.st"
verifyPass(code[0] == NEW_OPCODE(WOP_get2locals), "code[0] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
#line 78 "ST_avmplus_peephole.st"
verifyPass(code[1] == ((4 << 16) | 5), "code[1] == ((4 << 16) | 5)", __FILE__, __LINE__);
#line 79 "ST_avmplus_peephole.st"
verifyPass(code[2] == NEW_OPCODE(WOP_getlocal), "code[2] == NEW_OPCODE(WOP_getlocal)", __FILE__, __LINE__);
#line 80 "ST_avmplus_peephole.st"
verifyPass(code[3] == 65536, "code[3] == 65536", __FILE__, __LINE__);
#line 81 "ST_avmplus_peephole.st"
verifyPass(code[4] == NEW_OPCODE(WOP_get2locals), "code[4] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
#line 82 "ST_avmplus_peephole.st"
verifyPass(code[5] == ((6 << 16) | 7), "code[5] == ((6 << 16) | 7)", __FILE__, __LINE__);

    delete t;


}
	void WordcodeEmitter::emitLookupswitch(const uint8_t *pc)
	{
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		// Avoid a lot of hair by flushing before LOOKUPSWITCH and not peepholing after.
		peepFlush();
#endif
		const uint8_t* base_pc = pc;
		pc++;
		uint32_t base_offset = uint32_t(buffer_offset + (dest - buffers->data));
		intptr_t default_offset = AvmCore::readS24(pc);
		pc += 3;
		uint32_t case_count = AvmCore::readU30(pc);
		CHECK(3);
		*dest++ = NEW_OPCODE(OP_lookupswitch);
		emitRelativeOffset(base_offset, base_pc, default_offset);
		*dest++ = case_count;
		
		for ( uint32_t i=0 ; i <= case_count ; i++ ) {
			intptr_t offset = AvmCore::readS24(pc);
			pc += 3;
			CHECK(1);
			emitRelativeOffset(base_offset, base_pc, offset);
		}
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		// need a forward declaration for toplevel.
//		AvmAssert(toplevel[OP_lookupswitch] == 0);
#endif
	}
	void WordcodeEmitter::emitGetscopeobject(const uint8_t *pc) 
	{
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(OP_getscopeobject);
		*dest++ = *pc++;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(OP_getscopeobject, dest-2);
#endif
	}
	void WordcodeEmitter::emitPushshort(const uint8_t *pc) 
	{
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(WOP_pushbits);
		*dest++ = (intptr_t)((int16_t)AvmCore::readU30(pc) << 3) | kIntegerType;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(WOP_pushbits, dest-2);
#endif
	}
	// These take no arguments
	void WordcodeEmitter::emitOp0(const uint8_t *pc, WordOpcode opcode) {
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 1);
#endif // _DEBUG
		(void)pc;
		CHECK(1);
		*dest++ = NEW_OPCODE(opcode);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-1);
#endif
	}
	// These take one U30 argument, and the argument is explicitly passed here (result of optimization)
	void WordcodeEmitter::emitOp1(WordOpcode opcode, uint32_t operand)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 2);
#endif // _DEBUG
		CHECK(2);
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)operand;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
#endif
	}
	void WordcodeEmitter::emitOp2(WordOpcode opcode, uint32_t op1, uint32_t op2)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 3);
#endif
		CHECK(3);
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)op1;
		*dest++ = (intptr_t)(int32_t)op2;
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-3);
#endif
	}
	// These take one U30 argument
	void WordcodeEmitter::emitOp1(const uint8_t *pc, WordOpcode opcode)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].width == 2);
#endif // _DEBUG
		CHECK(2);
		pc++;
		*dest++ = NEW_OPCODE(opcode);
		*dest++ = (intptr_t)(int32_t)AvmCore::readU30(pc);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
#endif
	}
	void WordcodeEmitter::emitDebug(const uint8_t *pc) 
	{
		CHECK(5);
		pc++;
		uint8_t debug_type = *pc++;
		uint32_t index = AvmCore::readU30(pc);
		uint8_t reg = *pc++;
		uint32_t extra = AvmCore::readU30(pc);
		// 4 separate operands to match the value in the operand count table,
		// though obviously we could pack debug_type and reg into one word and
		// we could also omit extra.
		*dest++ = NEW_OPCODE(OP_debug);
		*dest++ = debug_type;
		*dest++ = (intptr_t)(int32_t)index;
		*dest++ = (intptr_t)(int32_t)reg;
		*dest++ = (intptr_t)(int32_t)extra;
	}
	// These take one S24 argument that is PC-relative.  If the offset is negative
	// then the target must be a LABEL instruction, and we can just look it up.
	// Otherwise, we enter the target offset into an ordered list with the current
	// transformed PC and the location to backpatch.
	void WordcodeEmitter::emitRelativeJump(const uint8_t *pc, WordOpcode opcode)
	{
#ifdef _DEBUG
		AvmAssert(wopAttrs[opcode].jumps);
#endif
		CHECK(2);
		pc++;
		intptr_t offset = (intptr_t)AvmCore::readS24(pc);
		pc += 3;
		*dest++ = NEW_OPCODE(opcode);
		uintptr_t base_offset = uintptr_t(buffer_offset + (dest - buffers->data) + 1);
		emitRelativeOffset(base_offset, pc, offset);
#ifdef AVMPLUS_PEEPHOLE_OPTIMIZER
		peep(opcode, dest-2);
		AvmAssert(state == 0);		// Never allow a jump instruction to be in the middle of a match
#endif
	}
예제 #13
0
파일: peephole.cpp 프로젝트: bsdf/trx
bool WordcodeEmitter::commit(uint32_t action)
{
    switch (action) {
    case 1:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] < 4) {
            S[0] = WOP_getlocal0 + I[0][1];
            R[0] = NEW_OPCODE(WOP_getlocal0 + I[0][1]);
            return replace(1,1);
        }
        return false;
    case 2:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_get2locals;
            R[0] = NEW_OPCODE(WOP_get2locals);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(2,2);
        }
        return false;
    case 3:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] < 1024 && I[1][1] < 1024 && I[2][1] < 1024) {
            S[0] = WOP_get3locals;
            R[0] = NEW_OPCODE(WOP_get3locals);
            R[1] = (I[2][1] << 20) | (I[1][1] << 10) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 4:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_getlocal) && I[3][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] < 256 && I[1][1] < 256 && I[2][1] < 256 && I[3][1] < 256) {
            S[0] = WOP_get4locals;
            R[0] = NEW_OPCODE(WOP_get4locals);
            R[1] = (I[3][1] << 24) | (I[2][1] << 16) | (I[1][1] << 8) | I[0][1];
            return replace(4,2);
        }
        return false;
    case 5:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_getlocal) && I[3][0] == NEW_OPCODE(WOP_getlocal) && I[4][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] < 64 && I[1][1] < 64 && I[2][1] < 64 && I[3][1] < 64 && I[4][1] < 64) {
            S[0] = WOP_get5locals;
            R[0] = NEW_OPCODE(WOP_get5locals);
            R[1] = (I[4][1] << 24) | (I[3][1] << 18) | (I[2][1] << 12) | (I[1][1] << 6) | I[0][1];
            return replace(5,2);
        }
        return false;
    case 6:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_add));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_add_ll;
            R[0] = NEW_OPCODE(WOP_add_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 7:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_add) && I[3][0] == NEW_OPCODE(WOP_setlocal));
        if (I[0][1] < 1024 && I[1][1] < 1024 && I[3][1] < 1024) {
            S[0] = WOP_add_set_lll;
            R[0] = NEW_OPCODE(WOP_add_set_lll);
            R[1] = (I[3][1] << 20) | (I[1][1] << 10) | I[0][1];
            return replace(4,2);
        }
        return false;
    case 8:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_subtract));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_subtract_ll;
            R[0] = NEW_OPCODE(WOP_subtract_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 9:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_multiply));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_multiply_ll;
            R[0] = NEW_OPCODE(WOP_multiply_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 10:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_divide));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_divide_ll;
            R[0] = NEW_OPCODE(WOP_divide_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 11:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_modulo));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_modulo_ll;
            R[0] = NEW_OPCODE(WOP_modulo_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 12:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_bitand));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_bitand_ll;
            R[0] = NEW_OPCODE(WOP_bitand_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 13:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_bitor));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_bitor_ll;
            R[0] = NEW_OPCODE(WOP_bitor_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 14:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_bitxor));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            S[0] = WOP_bitxor_ll;
            R[0] = NEW_OPCODE(WOP_bitxor_ll);
            R[1] = (I[1][1] << 16) | I[0][1];
            return replace(3,2);
        }
        return false;
    case 15:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_iflt));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_iflt_ll;
            R[0] = NEW_OPCODE(WOP_iflt_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 16:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifnlt));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnlt_ll;
            R[0] = NEW_OPCODE(WOP_ifnlt_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 17:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifle));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifle_ll;
            R[0] = NEW_OPCODE(WOP_ifle_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 18:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifnle));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnle_ll;
            R[0] = NEW_OPCODE(WOP_ifnle_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 19:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifgt));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifgt_ll;
            R[0] = NEW_OPCODE(WOP_ifgt_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 20:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifngt));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifngt_ll;
            R[0] = NEW_OPCODE(WOP_ifngt_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 21:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifge));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifge_ll;
            R[0] = NEW_OPCODE(WOP_ifge_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 22:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifnge));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnge_ll;
            R[0] = NEW_OPCODE(WOP_ifnge_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 23:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifeq));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifeq_ll;
            R[0] = NEW_OPCODE(WOP_ifeq_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 24:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifne));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifne_ll;
            R[0] = NEW_OPCODE(WOP_ifne_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 25:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifstricteq));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifstricteq_ll;
            R[0] = NEW_OPCODE(WOP_ifstricteq_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 26:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal) && I[2][0] == NEW_OPCODE(WOP_ifstrictne));
        if (I[0][1] < 65536 && I[1][1] < 65536) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifstrictne_ll;
            R[0] = NEW_OPCODE(WOP_ifstrictne_ll);
            R[1] = I[2][1];
            R[2] = (I[1][1] << 16) | I[0][1];
            return replace(3,3,true);
        }
        return false;
    case 27:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_add));
        if (true) {
            S[0] = WOP_add_lb;
            R[0] = NEW_OPCODE(WOP_add_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 28:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_subtract));
        if (true) {
            S[0] = WOP_subtract_lb;
            R[0] = NEW_OPCODE(WOP_subtract_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 29:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_multiply));
        if (true) {
            S[0] = WOP_multiply_lb;
            R[0] = NEW_OPCODE(WOP_multiply_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 30:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_divide));
        if (true) {
            S[0] = WOP_divide_lb;
            R[0] = NEW_OPCODE(WOP_divide_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 31:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_bitand));
        if (true) {
            S[0] = WOP_bitand_lb;
            R[0] = NEW_OPCODE(WOP_bitand_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 32:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_bitor));
        if (true) {
            S[0] = WOP_bitor_lb;
            R[0] = NEW_OPCODE(WOP_bitor_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 33:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_bitxor));
        if (true) {
            S[0] = WOP_bitxor_lb;
            R[0] = NEW_OPCODE(WOP_bitxor_lb);
            R[1] = I[0][1];
            R[2] = I[1][1];
            return replace(3,3);
        }
        return false;
    case 34:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_iflt));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_iflt_lb;
            R[0] = NEW_OPCODE(WOP_iflt_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 35:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifnlt));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnlt_lb;
            R[0] = NEW_OPCODE(WOP_ifnlt_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 36:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifle));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifle_lb;
            R[0] = NEW_OPCODE(WOP_ifle_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 37:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifnle));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnle_lb;
            R[0] = NEW_OPCODE(WOP_ifnle_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 38:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifgt));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifgt_lb;
            R[0] = NEW_OPCODE(WOP_ifgt_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 39:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifngt));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifngt_lb;
            R[0] = NEW_OPCODE(WOP_ifngt_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 40:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifge));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifge_lb;
            R[0] = NEW_OPCODE(WOP_ifge_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 41:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifnge));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifnge_lb;
            R[0] = NEW_OPCODE(WOP_ifnge_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 42:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifeq));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifeq_lb;
            R[0] = NEW_OPCODE(WOP_ifeq_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 43:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifne));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifne_lb;
            R[0] = NEW_OPCODE(WOP_ifne_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 44:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifstricteq));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifstricteq_lb;
            R[0] = NEW_OPCODE(WOP_ifstricteq_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 45:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_getlocal) && I[1][0] == NEW_OPCODE(WOP_pushbits) && I[2][0] == NEW_OPCODE(WOP_ifstrictne));
        if (true) {
            undoRelativeOffsetInJump();
            S[0] = WOP_ifstrictne_lb;
            R[0] = NEW_OPCODE(WOP_ifstrictne_lb);
            R[1] = I[2][1];
            R[2] = I[0][1];
            R[3] = I[1][1];
            return replace(3,4,true);
        }
        return false;
    case 46:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_setlocal));
        if (I[0][1] < 4) {
            S[0] = WOP_setlocal0 + I[0][1];
            R[0] = NEW_OPCODE(WOP_setlocal0 + I[0][1]);
            return replace(1,1);
        }
        return false;
    case 47:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_setlocal) && I[1][0] == NEW_OPCODE(WOP_getlocal));
        if (I[0][1] == I[1][1]) {
            S[0] = WOP_storelocal;
            R[0] = NEW_OPCODE(WOP_storelocal);
            R[1] = I[0][1];
            return replace(2,2);
        }
        return false;
    case 48:
        AvmAssert(I[0][0] == NEW_OPCODE(WOP_swap) && I[1][0] == NEW_OPCODE(WOP_pop));
        if (true) {
            S[0] = WOP_swap_pop;
            R[0] = NEW_OPCODE(WOP_swap_pop);
            return replace(2,1);
        }
        return false;
    default:
        AvmAssert(!"Should not happen");
        return false;
    }
}