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; }