bool WordcodeEmitter::replace(uint32_t old_instr, uint32_t new_words, bool jump_has_been_translated) 
	{
		// Undo any relative offsets in the last instruction, if that wasn't done by
		// the commit code.

		if (isJumpInstruction(O[nextI - 1]) && !jump_has_been_translated)
			undoRelativeOffsetInJump();
		
		// Catenate unconsumed instructions onto R (it's easier than struggling with
		// moving instructions across buffer boundaries)

		uint32_t k = new_words;
		for ( uint32_t n=old_instr ; n < nextI ; n++ ) {
			uint32_t len = calculateInstructionWidth(O[n]);
			S[k] = O[n];
			for ( uint32_t j=0 ; j < len ; j++ )
				R[k++] = I[n][j];
		}
		
		// Unlink the last buffer segment if we took everything from it, push it onto
		// a reserve (there can only ever be one free).  We know I[nextI-1] points into the
		// current buffer, so check if I[0] is between the start of the buffer and
		// the last instruction.
		
		if (!(buffers->data <= I[0] && I[0] <= I[nextI-1])) {
			spare_buffer = buffers;
			buffers = buffers->next;
			spare_buffer->next = NULL;
			dest_limit = buffers->data + sizeof(buffers->data)/sizeof(buffers->data[0]);
			buffer_offset -= buffers->entries_used;
		}
		dest = I[0];
		
		// Emit the various instructions from new_data, handling branches specially.
		//
		// At this point the instance variables state, I, O, nextI, backtrack_stack,
		// and backtrack_idx are dead, and all the data we need for emitting the
		// instructions are in S and R.  In addition, dest has been rolled back and
		// points to the address of the first instruction in the peephole window, and
		// nothing is live in the code buffer beyond that point.  It's as if we are
		// in a context where we're just emitting instructions.
		//
		// Consequently, we set state to 0 and start emitting instructions from S/R
		// normally, calling peep() after each instruction that was not replaced by
		// the current action.  This works without having local copies of S and R
		// because peephole optimization cannot insert a replacement sequence that is 
		// longer than the matched sequence; so the segments of S and R used by any
		// recursive match will not affect what we're doing here.  Furthermore, 'dest'
		// is shared between this match and recursive matches, so if a recursive match
		// shortens the instruction sequence the correct value of dest will be used
		// when we get back to the present invocation of replace().

		// Reset the machine.
		
		state = 0;
		
		uint32_t i=0;
		while (i < k) {
			uintptr_t op = S[i];
			uintptr_t width = calculateInstructionWidth(op);
			CHECK(width);
			if (isJumpInstruction(op)) {
				*dest++ = R[i++];
				int32_t offset = int32_t(R[i++]);
				if (offset >= 0) {
					// Forward jump
					// Install a new backpatch structure
					makeAndInsertBackpatch(code_start + offset, uint32_t(buffer_offset + (dest + (width - 1) - buffers->data)));
				}
				else {
					// Backward jump
					// Compute new jump offset
					*dest = -int32_t(buffer_offset + (dest + (width - 1) - buffers->data) + offset);
					dest++;
				}
				if (width >= 3)
					*dest++ = R[i++];
				if (width >= 4)
					*dest++ = R[i++];
				AvmAssert(width <= 4);
			}
			else {
				switch (width) {
					default:
						AvmAssert(!"Can't happen");
					case 1:
						*dest++ = R[i++];
						break;
					case 2:
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
					case 3:
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
					case 5:  // OP_debug
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						*dest++ = R[i++];
						break;
				}
			}
			if (i-width >= new_words)
				peep((uint32_t)op, dest-width);
		}
		
		return true;  // always
	}
Example #2
0
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;
    }
}