Exemple #1
0
bool RARExecuteProgram(RARVirtualMachine *vm, RARProgram *prog)
{
    RAROpcode *opcode = prog->opcodes;
    uint32_t flags = 0;
    uint32_t op1, op2, carry, i;
    uint32_t counter = 0;

    if (!RARIsProgramTerminated(prog))
        return false;

    while ((uint32_t)(opcode - prog->opcodes) < prog->length && counter++ < RARRuntimeMaxInstructions) {
        switch (opcode->instruction) {
        case RARMovInstruction:
            SetOperand1(GetOperand2());
            NextInstruction();

        case RARCmpInstruction:
            op1 = GetOperand1();
            SetFlagsWithCarry(op1 - GetOperand2(), result > op1);
            NextInstruction();

        case RARAddInstruction:
            op1 = GetOperand1();
            if (opcode->bytemode)
                SetOperand1AndByteFlagsWithCarry((op1 + GetOperand2()) & 0xFF, result < op1);
            else
                SetOperand1AndFlagsWithCarry(op1 + GetOperand2(), result < op1);
            NextInstruction();

        case RARSubInstruction:
            op1 = GetOperand1();
#if 0 /* apparently not correctly implemented in the RAR VM */
            if (opcode->bytemode)
                SetOperand1AndByteFlagsWithCarry((op1 - GetOperand2()) & 0xFF, result > op1);
            else
#endif
            SetOperand1AndFlagsWithCarry(op1 - GetOperand2(), result > op1);
            NextInstruction();

        case RARJzInstruction:
            if ((flags & ZeroFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARJnzInstruction:
            if (!(flags & ZeroFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARIncInstruction:
            if (opcode->bytemode)
                SetOperand1AndFlags((GetOperand1() + 1) & 0xFF);
            else
                SetOperand1AndFlags(GetOperand1() + 1);
            NextInstruction();

        case RARDecInstruction:
            if (opcode->bytemode)
                SetOperand1AndFlags((GetOperand1() - 1) & 0xFF);
            else
                SetOperand1AndFlags(GetOperand1() - 1);
            NextInstruction();

        case RARJmpInstruction:
            Jump(GetOperand1());

        case RARXorInstruction:
            SetOperand1AndFlags(GetOperand1() ^ GetOperand2());
            NextInstruction();

        case RARAndInstruction:
            SetOperand1AndFlags(GetOperand1() & GetOperand2());
            NextInstruction();

        case RAROrInstruction:
            SetOperand1AndFlags(GetOperand1() | GetOperand2());
            NextInstruction();

        case RARTestInstruction:
            SetFlags(GetOperand1() & GetOperand2());
            NextInstruction();

        case RARJsInstruction:
            if ((flags & SignFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARJnsInstruction:
            if (!(flags & SignFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARJbInstruction:
            if ((flags & CarryFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARJbeInstruction:
            if ((flags & (CarryFlag | ZeroFlag)))
                Jump(GetOperand1());
            NextInstruction();

        case RARJaInstruction:
            if (!(flags & (CarryFlag | ZeroFlag)))
                Jump(GetOperand1());
            NextInstruction();

        case RARJaeInstruction:
            if (!(flags & CarryFlag))
                Jump(GetOperand1());
            NextInstruction();

        case RARPushInstruction:
            vm->registers[7] -= 4;
            RARVirtualMachineWrite32(vm, vm->registers[7], GetOperand1());
            NextInstruction();

        case RARPopInstruction:
            SetOperand1(RARVirtualMachineRead32(vm, vm->registers[7]));
            vm->registers[7] += 4;
            NextInstruction();

        case RARCallInstruction:
            vm->registers[7] -= 4;
            RARVirtualMachineWrite32(vm, vm->registers[7], (uint32_t)(opcode - prog->opcodes + 1));
            Jump(GetOperand1());

        case RARRetInstruction:
            if (vm->registers[7] >= RARProgramMemorySize)
                return true;
            i = RARVirtualMachineRead32(vm, vm->registers[7]);
            vm->registers[7] += 4;
            Jump(i);

        case RARNotInstruction:
            SetOperand1(~GetOperand1());
            NextInstruction();

        case RARShlInstruction:
            op1 = GetOperand1();
            op2 = GetOperand2();
            SetOperand1AndFlagsWithCarry(op1 << op2, ((op1 << (op2 - 1)) & 0x80000000) != 0);
            NextInstruction();

        case RARShrInstruction:
            op1 = GetOperand1();
            op2 = GetOperand2();
            SetOperand1AndFlagsWithCarry(op1 >> op2, ((op1 >> (op2 - 1)) & 1) != 0);
            NextInstruction();

        case RARSarInstruction:
            op1 = GetOperand1();
            op2 = GetOperand2();
            SetOperand1AndFlagsWithCarry(((int32_t)op1) >> op2, ((op1 >> (op2 - 1)) & 1) != 0);
            NextInstruction();

        case RARNegInstruction:
            SetOperand1AndFlagsWithCarry(-(int32_t)GetOperand1(), result != 0);
            NextInstruction();

        case RARPushaInstruction:
            vm->registers[7] -= 32;
            for (i = 0; i < 8; i++)
                RARVirtualMachineWrite32(vm, vm->registers[7] + (7 - i) * 4, vm->registers[i]);
            NextInstruction();

        case RARPopaInstruction:
            for (i = 0; i < 8; i++)
                vm->registers[i] = RARVirtualMachineRead32(vm, vm->registers[7] + (7 - i) * 4);
            vm->registers[7] += 32;
            NextInstruction();

        case RARPushfInstruction:
            vm->registers[7] -= 4;
            RARVirtualMachineWrite32(vm, vm->registers[7], flags);
            NextInstruction();

        case RARPopfInstruction:
            flags = RARVirtualMachineRead32(vm, vm->registers[7]);
            vm->registers[7] += 4;
            NextInstruction();

        case RARMovzxInstruction:
            SetOperand1(GetOperand2());
            NextInstruction();

        case RARMovsxInstruction:
            SetOperand1(SignExtend(GetOperand2()));
            NextInstruction();

        case RARXchgInstruction:
            op1 = GetOperand1();
            op2 = GetOperand2();
            SetOperand1(op2);
            SetOperand2(op1);
            NextInstruction();

        case RARMulInstruction:
            SetOperand1(GetOperand1() * GetOperand2());
            NextInstruction();

        case RARDivInstruction:
            op2 = GetOperand2();
            if (op2 != 0)
                SetOperand1(GetOperand1() / op2);
            NextInstruction();

        case RARAdcInstruction:
            op1 = GetOperand1();
            carry = (flags & CarryFlag);
            if (opcode->bytemode)
                SetOperand1AndFlagsWithCarry((op1 + GetOperand2() + carry) & 0xFF, result < op1 || (result == op1 && carry)); /* does not correctly set sign bit */
            else
                SetOperand1AndFlagsWithCarry(op1 + GetOperand2() + carry, result < op1 || (result == op1 && carry));
            NextInstruction();

        case RARSbbInstruction:
            op1 = GetOperand1();
            carry = (flags & CarryFlag);
            if (opcode->bytemode)
                SetOperand1AndFlagsWithCarry((op1 - GetOperand2() - carry) & 0xFF, result > op1 || (result == op1 && carry)); /* does not correctly set sign bit */
            else
                SetOperand1AndFlagsWithCarry(op1 - GetOperand2() - carry, result > op1 || (result == op1 && carry));
            NextInstruction();

        case RARPrintInstruction:
            /* TODO: ??? */
            NextInstruction();
        }
    }

    return false;
}
static bool RunVirtualMachineOrGetLabels(RARVirtualMachine *self,
RAROpcode *opcodes,int numopcodes,void ***instructionlabels)
{
	static void *labels[2][RARNumberOfInstructions]=
	{
		[0][RARMovInstruction]=&&MovLabel,[1][RARMovInstruction]=&&MovLabel,
		[0][RARCmpInstruction]=&&CmpLabel,[1][RARCmpInstruction]=&&CmpLabel,
		[0][RARAddInstruction]=&&AddLabel,[1][RARAddInstruction]=&&AddByteLabel,
		[0][RARSubInstruction]=&&SubLabel,[1][RARSubInstruction]=&&SubLabel,
		[0][RARJzInstruction]=&&JzLabel,
		[0][RARJnzInstruction]=&&JnzLabel,
		[0][RARIncInstruction]=&&IncLabel,[1][RARIncInstruction]=&&IncByteLabel,
		[0][RARDecInstruction]=&&DecLabel,[1][RARDecInstruction]=&&DecByteLabel,
		[0][RARJmpInstruction]=&&JmpLabel,
		[0][RARXorInstruction]=&&XorLabel,[1][RARXorInstruction]=&&XorLabel,
		[0][RARAndInstruction]=&&AndLabel,[1][RARAndInstruction]=&&AndLabel,
		[0][RAROrInstruction]=&&OrLabel,[1][RAROrInstruction]=&&OrLabel,
		[0][RARTestInstruction]=&&TestLabel,[1][RARTestInstruction]=&&TestLabel,
		[0][RARJsInstruction]=&&JsLabel,
		[0][RARJnsInstruction]=&&JnsLabel,
		[0][RARJbInstruction]=&&JbLabel,
		[0][RARJbeInstruction]=&&JbeLabel,
		[0][RARJaInstruction]=&&JaLabel,
		[0][RARJaeInstruction]=&&JaeLabel,
		[0][RARPushInstruction]=&&PushLabel,
		[0][RARPopInstruction]=&&PopLabel,
		[0][RARCallInstruction]=&&CallLabel,
		[0][RARRetInstruction]=&&RetLabel,
		[0][RARNotInstruction]=&&NotLabel,[1][RARNotInstruction]=&&NotLabel,
		[0][RARShlInstruction]=&&ShlLabel,[1][RARShlInstruction]=&&ShlLabel,
		[0][RARShrInstruction]=&&ShrLabel,[1][RARShrInstruction]=&&ShrLabel,
		[0][RARSarInstruction]=&&SarLabel,[1][RARSarInstruction]=&&SarLabel,
		[0][RARNegInstruction]=&&NegLabel,[1][RARNegInstruction]=&&NegLabel,
		[0][RARPushaInstruction]=&&PushaLabel,
		[0][RARPopaInstruction]=&&PopaLabel,
		[0][RARPushfInstruction]=&&PushfLabel,
		[0][RARPopfInstruction]=&&PopfLabel,
		[0][RARMovzxInstruction]=&&MovzxLabel,
		[0][RARMovsxInstruction]=&&MovsxLabel,
		[0][RARXchgInstruction]=&&XchgLabel,
		[0][RARMulInstruction]=&&MulLabel,[1][RARMulInstruction]=&&MulLabel,
		[0][RARDivInstruction]=&&DivLabel,[1][RARDivInstruction]=&&DivLabel,
		[0][RARAdcInstruction]=&&AdcLabel,[1][RARAdcInstruction]=&&AdcByteLabel,
		[0][RARSbbInstruction]=&&SbbLabel,[1][RARSbbInstruction]=&&SbbByteLabel,
		[0][RARPrintInstruction]=&&PrintLabel,
	};

	if(instructionlabels)
	{
		*instructionlabels=&labels[0][0];
		return true;
	}

	RAROpcode *opcode;
	uint32_t flags=self->flags;

	Jump(0);

	MovLabel:
		SetOperand1(GetOperand2());
		NextInstruction();

	CmpLabel:
	{
		uint32_t term1=GetOperand1();
		SetFlagsWithCarry(term1-GetOperand2(),result>term1);
		NextInstruction();
	}

	AddLabel:
	{
		uint32_t term1=GetOperand1();
		SetOperand1AndFlagsWithCarry(term1+GetOperand2(),result<term1);
		NextInstruction();
	}
	AddByteLabel:
	{
		uint32_t term1=GetOperand1();
		SetOperand1AndByteFlagsWithCarry(term1+GetOperand2()&0xff,result<term1);
		NextInstruction();
	}

	SubLabel:
	{
		uint32_t term1=GetOperand1();
		SetOperand1AndFlagsWithCarry(term1-GetOperand2(),result>term1);
		NextInstruction();
	}
/*	SubByteLabel: // Not correctly implemented in the RAR VM
	{
		uint32_t term1=GetOperand1();
		SetOperandAndByteFlagsWithCarry(term1-GetOperand2()&0xff,result>term1);
		NextInstruction();
	}*/

	JzLabel:
		if(flags&ZeroFlag) Jump(GetOperand1());
		else NextInstruction();

	JnzLabel:
		if(!(flags&ZeroFlag)) Jump(GetOperand1());
		else NextInstruction();

	IncLabel:
		SetOperand1AndFlags(GetOperand1()+1);
		NextInstruction();
	IncByteLabel:
		SetOperand1AndFlags(GetOperand1()+1&0xff);
		NextInstruction();

	DecLabel:
		SetOperand1AndFlags(GetOperand1()-1);
		NextInstruction();
	DecByteLabel:
		SetOperand1AndFlags(GetOperand1()-1&0xff);
		NextInstruction();

	JmpLabel:
		Jump(GetOperand1());

	XorLabel:
		SetOperand1AndFlags(GetOperand1()^GetOperand2());
		NextInstruction();

	AndLabel:
		SetOperand1AndFlags(GetOperand1()&GetOperand2());
		NextInstruction();

	OrLabel:
		SetOperand1AndFlags(GetOperand1()|GetOperand2());
		NextInstruction();

	TestLabel:
		SetFlags(GetOperand1()&GetOperand2());
		NextInstruction();

	JsLabel:
		if(flags&SignFlag) Jump(GetOperand1());
		else NextInstruction();

	JnsLabel:
		if(!(flags&SignFlag)) Jump(GetOperand1());
		else NextInstruction();

	JbLabel:
		if(flags&CarryFlag) Jump(GetOperand1());
		else NextInstruction();

	JbeLabel:
		if(flags&(CarryFlag|ZeroFlag)) Jump(GetOperand1());
		else NextInstruction();

	JaLabel:
		if(!(flags&(CarryFlag|ZeroFlag))) Jump(GetOperand1());
		else NextInstruction();

	JaeLabel:
		if(!(flags&CarryFlag)) Jump(GetOperand1());
		else NextInstruction();

	PushLabel:
		self->registers[7]-=4;
		RARVirtualMachineWrite32(self,self->registers[7],GetOperand1());
		NextInstruction();

	PopLabel:
		SetOperand1(RARVirtualMachineRead32(self,self->registers[7]));
		self->registers[7]+=4;
		NextInstruction();

	CallLabel:
		self->registers[7]-=4;
		RARVirtualMachineWrite32(self,self->registers[7],opcode-opcodes+1);
		Jump(GetOperand1());

	RetLabel:
	{
		if(self->registers[7]>=RARProgramMemorySize)
		{
			self->flags=flags;
			return true;
		}
		uint32_t retaddr=RARVirtualMachineRead32(self,self->registers[7]);
		self->registers[7]+=4;
		Jump(retaddr);
	}

	NotLabel:
		SetOperand1(~GetOperand1());
		NextInstruction();

	ShlLabel:
	{
		uint32_t op1=GetOperand1();
		uint32_t op2=GetOperand2();
		SetOperand1AndFlagsWithCarry(op1<<op2,((op1<<(op2-1))&0x80000000)!=0);
		NextInstruction();
	}

	ShrLabel:
	{
		uint32_t op1=GetOperand1();
		uint32_t op2=GetOperand2();
		SetOperand1AndFlagsWithCarry(op1>>op2,((op1>>(op2-1))&1)!=0);
		NextInstruction();
	}

	SarLabel:
	{
		uint32_t op1=GetOperand1();
		uint32_t op2=GetOperand2();
		SetOperand1AndFlagsWithCarry(((int32_t)op1)>>op2,((op1>>(op2-1))&1)!=0);
		NextInstruction();
	}

	NegLabel:
		SetOperand1AndFlagsWithCarry(-GetOperand1(),result!=0);
		NextInstruction();

	PushaLabel:
		for(int i=0;i<8;i++) RARVirtualMachineWrite32(self,self->registers[7]-4-i*4,self->registers[i]);
		self->registers[7]-=32;

		NextInstruction();

	PopaLabel:
		for(int i=0;i<8;i++) self->registers[i]=RARVirtualMachineRead32(self,self->registers[7]+28-i*4);
		NextInstruction();

	PushfLabel:
		self->registers[7]-=4;
		RARVirtualMachineWrite32(self,self->registers[7],flags);
		NextInstruction();

	PopfLabel:
		flags=RARVirtualMachineRead32(self,self->registers[7]);
		self->registers[7]+=4;
		NextInstruction();

	MovzxLabel:
		SetOperand1(GetOperand2());
		NextInstruction();

	MovsxLabel:
		SetOperand1(SignExtend(GetOperand2()));
		NextInstruction();

	XchgLabel:
	{
		uint32_t op1=GetOperand1();
		uint32_t op2=GetOperand2();
		SetOperand1(op2);
		SetOperand2(op1);
		NextInstruction();
	}

	MulLabel:
		SetOperand1(GetOperand1()*GetOperand2());
		NextInstruction();

	DivLabel:
	{
		uint32_t denominator=GetOperand2();
		if(denominator!=0) SetOperand1(GetOperand1()/denominator);
		NextInstruction();
	}

	AdcLabel:
	{
		uint32_t term1=GetOperand1();
		uint32_t carry=flags&CarryFlag;
		SetOperand1AndFlagsWithCarry(term1+GetOperand2()+carry,result<term1 || result==term1 && carry);
		NextInstruction();
	}
	AdcByteLabel:
	{
		uint32_t term1=GetOperand1();
		uint32_t carry=flags&CarryFlag;
		SetOperand1AndFlagsWithCarry(term1+GetOperand2()+carry&0xff,result<term1 || result==term1 && carry); // Does not correctly set sign bit.
		NextInstruction();
	}

	SbbLabel:
	{
		uint32_t term1=GetOperand1();
		uint32_t carry=flags&CarryFlag;
		SetOperand1AndFlagsWithCarry(term1-GetOperand2()-carry,result>term1 || result==term1 && carry);
		NextInstruction();
	}
	SbbByteLabel:
	{
		uint32_t term1=GetOperand1();
		uint32_t carry=flags&CarryFlag;
		SetOperand1AndFlagsWithCarry(term1-GetOperand2()-carry&0xff,result>term1 || result==term1 && carry); // Does not correctly set sign bit.
		NextInstruction();
	}

	PrintLabel:
		NextInstruction();

	return false;
}