File indexing completed on 2025-02-02 04:26:02
0001 /* Copyright 2015 the unarr project authors (see AUTHORS file). 0002 License: LGPLv3 */ 0003 0004 /* adapted from https://code.google.com/p/theunarchiver/source/browse/XADMaster/RARVirtualMachine.c */ 0005 0006 #include "rarvm.h" 0007 #include "../common/allocator.h" 0008 0009 #include <stdlib.h> 0010 #include <string.h> 0011 0012 typedef struct RAROpcode_s RAROpcode; 0013 0014 struct RAROpcode_s { 0015 uint8_t instruction; 0016 uint8_t bytemode; 0017 uint8_t addressingmode1; 0018 uint8_t addressingmode2; 0019 uint32_t value1; 0020 uint32_t value2; 0021 }; 0022 0023 struct RARProgram_s { 0024 RAROpcode *opcodes; 0025 uint32_t length; 0026 uint32_t capacity; 0027 }; 0028 0029 /* Program building */ 0030 0031 RARProgram *RARCreateProgram() 0032 { 0033 return calloc(1, sizeof(RARProgram)); 0034 } 0035 0036 void RARDeleteProgram(RARProgram *prog) 0037 { 0038 if (prog) 0039 free(prog->opcodes); 0040 free(prog); 0041 } 0042 0043 bool RARProgramAddInstr(RARProgram *prog, uint8_t instruction, bool bytemode) 0044 { 0045 if (instruction >= RARNumberOfInstructions) 0046 return false; 0047 if (bytemode && !RARInstructionHasByteMode(instruction)) 0048 return false; 0049 if (prog->length + 1 >= prog->capacity) { 0050 /* in my small file sample, 16 is the value needed most often */ 0051 uint32_t newCapacity = prog->capacity ? prog->capacity * 4 : 32; 0052 RAROpcode *newCodes = calloc(newCapacity, sizeof(*prog->opcodes)); 0053 if (!newCodes) 0054 return false; 0055 memcpy(newCodes, prog->opcodes, prog->capacity * sizeof(*prog->opcodes)); 0056 free(prog->opcodes); 0057 prog->opcodes = newCodes; 0058 prog->capacity = newCapacity; 0059 } 0060 memset(&prog->opcodes[prog->length], 0, sizeof(prog->opcodes[prog->length])); 0061 prog->opcodes[prog->length].instruction = instruction; 0062 if (instruction == RARMovzxInstruction || instruction == RARMovsxInstruction) 0063 prog->opcodes[prog->length].bytemode = 2; /* second argument only */ 0064 else if (bytemode) 0065 prog->opcodes[prog->length].bytemode = (1 | 2); 0066 else 0067 prog->opcodes[prog->length].bytemode = 0; 0068 prog->length++; 0069 return true; 0070 } 0071 0072 bool RARSetLastInstrOperands(RARProgram *prog, uint8_t addressingmode1, uint32_t value1, uint8_t addressingmode2, uint32_t value2) 0073 { 0074 RAROpcode *opcode = &prog->opcodes[prog->length - 1]; 0075 int numoperands; 0076 0077 if (addressingmode1 >= RARNumberOfAddressingModes || addressingmode2 >= RARNumberOfAddressingModes) 0078 return false; 0079 if (!prog->length || opcode->addressingmode1 || opcode->value1 || opcode->addressingmode2 || opcode->value2) 0080 return false; 0081 0082 numoperands = NumberOfRARInstructionOperands(opcode->instruction); 0083 if (numoperands == 0) 0084 return true; 0085 0086 if (addressingmode1 == RARImmediateAddressingMode && RARInstructionWritesFirstOperand(opcode->instruction)) 0087 return false; 0088 opcode->addressingmode1 = addressingmode1; 0089 opcode->value1 = value1; 0090 0091 if (numoperands == 2) { 0092 if (addressingmode2 == RARImmediateAddressingMode && RARInstructionWritesSecondOperand(opcode->instruction)) 0093 return false; 0094 opcode->addressingmode2 = addressingmode2; 0095 opcode->value2 = value2; 0096 } 0097 0098 return true; 0099 } 0100 0101 bool RARIsProgramTerminated(RARProgram *prog) 0102 { 0103 return prog->length > 0 && RARInstructionIsUnconditionalJump(prog->opcodes[prog->length - 1].instruction); 0104 } 0105 0106 /* Execution */ 0107 0108 #define EXTMACRO_BEGIN do { 0109 #ifdef _MSC_VER 0110 #define EXTMACRO_END } __pragma(warning(push)) __pragma(warning(disable:4127)) while (0) __pragma(warning(pop)) 0111 #else 0112 #define EXTMACRO_END } while (0) 0113 #endif 0114 0115 #define CarryFlag 1 0116 #define ZeroFlag 2 0117 #define SignFlag 0x80000000 0118 0119 #define SignExtend(a) ((uint32_t)((int8_t)(a))) 0120 0121 static uint32_t _RARGetOperand(RARVirtualMachine *vm, uint8_t addressingmode, uint32_t value, bool bytemode); 0122 static void _RARSetOperand(RARVirtualMachine *vm, uint8_t addressingmode, uint32_t value, bool bytemode, uint32_t data); 0123 0124 #define GetOperand1() _RARGetOperand(vm, opcode->addressingmode1, opcode->value1, opcode->bytemode & 1) 0125 #define GetOperand2() _RARGetOperand(vm, opcode->addressingmode2, opcode->value2, opcode->bytemode & 2) 0126 #define SetOperand1(data) _RARSetOperand(vm, opcode->addressingmode1, opcode->value1, opcode->bytemode & 1, data) 0127 #define SetOperand2(data) _RARSetOperand(vm, opcode->addressingmode2, opcode->value2, opcode->bytemode & 2, data) 0128 0129 #define SetFlagsWithCarry(res, carry) EXTMACRO_BEGIN uint32_t result = (res); flags = (result == 0 ? ZeroFlag : (result & SignFlag)) | ((carry) ? CarryFlag : 0); EXTMACRO_END 0130 #define SetByteFlagsWithCarry(res, carry) EXTMACRO_BEGIN uint8_t result = (res); flags = (result == 0 ? ZeroFlag : (SignExtend(result) & SignFlag)) | ((carry) ? CarryFlag : 0); EXTMACRO_END 0131 #define SetFlags(res) SetFlagsWithCarry(res, 0) 0132 0133 #define SetOperand1AndFlagsWithCarry(res, carry) EXTMACRO_BEGIN uint32_t r = (res); SetFlagsWithCarry(r, carry); SetOperand1(r); EXTMACRO_END 0134 #define SetOperand1AndByteFlagsWithCarry(res, carry) EXTMACRO_BEGIN uint8_t r = (res); SetByteFlagsWithCarry(r, carry); SetOperand1(r); EXTMACRO_END 0135 #define SetOperand1AndFlags(res) EXTMACRO_BEGIN uint32_t r = (res); SetFlags(r); SetOperand1(r); EXTMACRO_END 0136 0137 #define NextInstruction() { opcode++; continue; } 0138 #define Jump(offs) { uint32_t o = (offs); if (o >= prog->length) return false; opcode = &prog->opcodes[o]; continue; } 0139 0140 bool RARExecuteProgram(RARVirtualMachine *vm, RARProgram *prog) 0141 { 0142 RAROpcode *opcode = prog->opcodes; 0143 uint32_t flags = 0; 0144 uint32_t op1, op2, carry, i; 0145 uint32_t counter = 0; 0146 0147 if (!RARIsProgramTerminated(prog)) 0148 return false; 0149 0150 while ((uint32_t)(opcode - prog->opcodes) < prog->length && counter++ < RARRuntimeMaxInstructions) { 0151 switch (opcode->instruction) { 0152 case RARMovInstruction: 0153 SetOperand1(GetOperand2()); 0154 NextInstruction(); 0155 0156 case RARCmpInstruction: 0157 op1 = GetOperand1(); 0158 SetFlagsWithCarry(op1 - GetOperand2(), result > op1); 0159 NextInstruction(); 0160 0161 case RARAddInstruction: 0162 op1 = GetOperand1(); 0163 if (opcode->bytemode) 0164 SetOperand1AndByteFlagsWithCarry((op1 + GetOperand2()) & 0xFF, result < op1); 0165 else 0166 SetOperand1AndFlagsWithCarry(op1 + GetOperand2(), result < op1); 0167 NextInstruction(); 0168 0169 case RARSubInstruction: 0170 op1 = GetOperand1(); 0171 #if 0 /* apparently not correctly implemented in the RAR VM */ 0172 if (opcode->bytemode) 0173 SetOperand1AndByteFlagsWithCarry((op1 - GetOperand2()) & 0xFF, result > op1); 0174 else 0175 #endif 0176 SetOperand1AndFlagsWithCarry(op1 - GetOperand2(), result > op1); 0177 NextInstruction(); 0178 0179 case RARJzInstruction: 0180 if ((flags & ZeroFlag)) 0181 Jump(GetOperand1()); 0182 NextInstruction(); 0183 0184 case RARJnzInstruction: 0185 if (!(flags & ZeroFlag)) 0186 Jump(GetOperand1()); 0187 NextInstruction(); 0188 0189 case RARIncInstruction: 0190 if (opcode->bytemode) 0191 SetOperand1AndFlags((GetOperand1() + 1) & 0xFF); 0192 else 0193 SetOperand1AndFlags(GetOperand1() + 1); 0194 NextInstruction(); 0195 0196 case RARDecInstruction: 0197 if (opcode->bytemode) 0198 SetOperand1AndFlags((GetOperand1() - 1) & 0xFF); 0199 else 0200 SetOperand1AndFlags(GetOperand1() - 1); 0201 NextInstruction(); 0202 0203 case RARJmpInstruction: 0204 Jump(GetOperand1()); 0205 0206 case RARXorInstruction: 0207 SetOperand1AndFlags(GetOperand1() ^ GetOperand2()); 0208 NextInstruction(); 0209 0210 case RARAndInstruction: 0211 SetOperand1AndFlags(GetOperand1() & GetOperand2()); 0212 NextInstruction(); 0213 0214 case RAROrInstruction: 0215 SetOperand1AndFlags(GetOperand1() | GetOperand2()); 0216 NextInstruction(); 0217 0218 case RARTestInstruction: 0219 SetFlags(GetOperand1() & GetOperand2()); 0220 NextInstruction(); 0221 0222 case RARJsInstruction: 0223 if ((flags & SignFlag)) 0224 Jump(GetOperand1()); 0225 NextInstruction(); 0226 0227 case RARJnsInstruction: 0228 if (!(flags & SignFlag)) 0229 Jump(GetOperand1()); 0230 NextInstruction(); 0231 0232 case RARJbInstruction: 0233 if ((flags & CarryFlag)) 0234 Jump(GetOperand1()); 0235 NextInstruction(); 0236 0237 case RARJbeInstruction: 0238 if ((flags & (CarryFlag | ZeroFlag))) 0239 Jump(GetOperand1()); 0240 NextInstruction(); 0241 0242 case RARJaInstruction: 0243 if (!(flags & (CarryFlag | ZeroFlag))) 0244 Jump(GetOperand1()); 0245 NextInstruction(); 0246 0247 case RARJaeInstruction: 0248 if (!(flags & CarryFlag)) 0249 Jump(GetOperand1()); 0250 NextInstruction(); 0251 0252 case RARPushInstruction: 0253 vm->registers[7] -= 4; 0254 RARVirtualMachineWrite32(vm, vm->registers[7], GetOperand1()); 0255 NextInstruction(); 0256 0257 case RARPopInstruction: 0258 SetOperand1(RARVirtualMachineRead32(vm, vm->registers[7])); 0259 vm->registers[7] += 4; 0260 NextInstruction(); 0261 0262 case RARCallInstruction: 0263 vm->registers[7] -= 4; 0264 RARVirtualMachineWrite32(vm, vm->registers[7], (uint32_t)(opcode - prog->opcodes + 1)); 0265 Jump(GetOperand1()); 0266 0267 case RARRetInstruction: 0268 if (vm->registers[7] >= RARProgramMemorySize) 0269 return true; 0270 i = RARVirtualMachineRead32(vm, vm->registers[7]); 0271 vm->registers[7] += 4; 0272 Jump(i); 0273 0274 case RARNotInstruction: 0275 SetOperand1(~GetOperand1()); 0276 NextInstruction(); 0277 0278 case RARShlInstruction: 0279 op1 = GetOperand1(); 0280 op2 = GetOperand2(); 0281 SetOperand1AndFlagsWithCarry(op1 << op2, ((op1 << (op2 - 1)) & 0x80000000) != 0); 0282 NextInstruction(); 0283 0284 case RARShrInstruction: 0285 op1 = GetOperand1(); 0286 op2 = GetOperand2(); 0287 SetOperand1AndFlagsWithCarry(op1 >> op2, ((op1 >> (op2 - 1)) & 1) != 0); 0288 NextInstruction(); 0289 0290 case RARSarInstruction: 0291 op1 = GetOperand1(); 0292 op2 = GetOperand2(); 0293 SetOperand1AndFlagsWithCarry(((int32_t)op1) >> op2, ((op1 >> (op2 - 1)) & 1) != 0); 0294 NextInstruction(); 0295 0296 case RARNegInstruction: 0297 SetOperand1AndFlagsWithCarry(-(int32_t)GetOperand1(), result != 0); 0298 NextInstruction(); 0299 0300 case RARPushaInstruction: 0301 vm->registers[7] -= 32; 0302 for (i = 0; i < 8; i++) 0303 RARVirtualMachineWrite32(vm, vm->registers[7] + (7 - i) * 4, vm->registers[i]); 0304 NextInstruction(); 0305 0306 case RARPopaInstruction: 0307 for (i = 0; i < 8; i++) 0308 vm->registers[i] = RARVirtualMachineRead32(vm, vm->registers[7] + (7 - i) * 4); 0309 vm->registers[7] += 32; 0310 NextInstruction(); 0311 0312 case RARPushfInstruction: 0313 vm->registers[7] -= 4; 0314 RARVirtualMachineWrite32(vm, vm->registers[7], flags); 0315 NextInstruction(); 0316 0317 case RARPopfInstruction: 0318 flags = RARVirtualMachineRead32(vm, vm->registers[7]); 0319 vm->registers[7] += 4; 0320 NextInstruction(); 0321 0322 case RARMovzxInstruction: 0323 SetOperand1(GetOperand2()); 0324 NextInstruction(); 0325 0326 case RARMovsxInstruction: 0327 SetOperand1(SignExtend(GetOperand2())); 0328 NextInstruction(); 0329 0330 case RARXchgInstruction: 0331 op1 = GetOperand1(); 0332 op2 = GetOperand2(); 0333 SetOperand1(op2); 0334 SetOperand2(op1); 0335 NextInstruction(); 0336 0337 case RARMulInstruction: 0338 SetOperand1(GetOperand1() * GetOperand2()); 0339 NextInstruction(); 0340 0341 case RARDivInstruction: 0342 op2 = GetOperand2(); 0343 if (op2 != 0) 0344 SetOperand1(GetOperand1() / op2); 0345 NextInstruction(); 0346 0347 case RARAdcInstruction: 0348 op1 = GetOperand1(); 0349 carry = (flags & CarryFlag); 0350 if (opcode->bytemode) 0351 SetOperand1AndFlagsWithCarry((op1 + GetOperand2() + carry) & 0xFF, result < op1 || (result == op1 && carry)); /* does not correctly set sign bit */ 0352 else 0353 SetOperand1AndFlagsWithCarry(op1 + GetOperand2() + carry, result < op1 || (result == op1 && carry)); 0354 NextInstruction(); 0355 0356 case RARSbbInstruction: 0357 op1 = GetOperand1(); 0358 carry = (flags & CarryFlag); 0359 if (opcode->bytemode) 0360 SetOperand1AndFlagsWithCarry((op1 - GetOperand2() - carry) & 0xFF, result > op1 || (result == op1 && carry)); /* does not correctly set sign bit */ 0361 else 0362 SetOperand1AndFlagsWithCarry(op1 - GetOperand2() - carry, result > op1 || (result == op1 && carry)); 0363 NextInstruction(); 0364 0365 case RARPrintInstruction: 0366 /* TODO: ??? */ 0367 NextInstruction(); 0368 } 0369 } 0370 0371 return false; 0372 } 0373 0374 /* Memory and register access */ 0375 0376 static uint32_t _RARRead32(const uint8_t *b) 0377 { 0378 return ((uint32_t)b[3] << 24) | ((uint32_t)b[2] << 16) | ((uint32_t)b[1] << 8) | (uint32_t)b[0]; 0379 } 0380 0381 static void _RARWrite32(uint8_t *b, uint32_t n) 0382 { 0383 b[3] = (n >> 24) & 0xFF; 0384 b[2] = (n >> 16) & 0xFF; 0385 b[1] = (n >> 8) & 0xFF; 0386 b[0] = n & 0xFF; 0387 } 0388 0389 void RARSetVirtualMachineRegisters(RARVirtualMachine *vm, uint32_t registers[8]) 0390 { 0391 if (registers) 0392 memcpy(vm->registers, registers, sizeof(vm->registers)); 0393 else 0394 memset(vm->registers, 0, sizeof(vm->registers)); 0395 } 0396 0397 uint32_t RARVirtualMachineRead32(RARVirtualMachine *vm, uint32_t address) 0398 { 0399 return _RARRead32(&vm->memory[address & RARProgramMemoryMask]); 0400 } 0401 0402 void RARVirtualMachineWrite32(RARVirtualMachine *vm, uint32_t address, uint32_t val) 0403 { 0404 _RARWrite32(&vm->memory[address & RARProgramMemoryMask], val); 0405 } 0406 0407 uint8_t RARVirtualMachineRead8(RARVirtualMachine *vm, uint32_t address) 0408 { 0409 return vm->memory[address & RARProgramMemoryMask]; 0410 } 0411 0412 void RARVirtualMachineWrite8(RARVirtualMachine *vm, uint32_t address, uint8_t val) 0413 { 0414 vm->memory[address & RARProgramMemoryMask] = val; 0415 } 0416 0417 static uint32_t _RARGetOperand(RARVirtualMachine *vm, uint8_t addressingmode, uint32_t value, bool bytemode) 0418 { 0419 if (RARRegisterAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterAddressingMode(7)) { 0420 uint32_t result = vm->registers[addressingmode % 8]; 0421 if (bytemode) 0422 result = result & 0xFF; 0423 return result; 0424 } 0425 if (RARRegisterIndirectAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterIndirectAddressingMode(7)) { 0426 if (bytemode) 0427 return RARVirtualMachineRead8(vm, vm->registers[addressingmode % 8]); 0428 return RARVirtualMachineRead32(vm, vm->registers[addressingmode % 8]); 0429 } 0430 if (RARIndexedAbsoluteAddressingMode(0) <= addressingmode && addressingmode <= RARIndexedAbsoluteAddressingMode(7)) { 0431 if (bytemode) 0432 return RARVirtualMachineRead8(vm, value + vm->registers[addressingmode % 8]); 0433 return RARVirtualMachineRead32(vm, value + vm->registers[addressingmode % 8]); 0434 } 0435 if (addressingmode == RARAbsoluteAddressingMode) { 0436 if (bytemode) 0437 return RARVirtualMachineRead8(vm, value); 0438 return RARVirtualMachineRead32(vm, value); 0439 } 0440 /* if (addressingmode == RARImmediateAddressingMode) */ 0441 return value; 0442 } 0443 0444 static void _RARSetOperand(RARVirtualMachine *vm, uint8_t addressingmode, uint32_t value, bool bytemode, uint32_t data) 0445 { 0446 if (RARRegisterAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterAddressingMode(7)) { 0447 if (bytemode) 0448 data = data & 0xFF; 0449 vm->registers[addressingmode % 8] = data; 0450 } 0451 else if (RARRegisterIndirectAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterIndirectAddressingMode(7)) { 0452 if (bytemode) 0453 RARVirtualMachineWrite8(vm, vm->registers[addressingmode % 8], (uint8_t)data); 0454 else 0455 RARVirtualMachineWrite32(vm, vm->registers[addressingmode % 8], data); 0456 } 0457 else if (RARIndexedAbsoluteAddressingMode(0) <= addressingmode && addressingmode <= RARIndexedAbsoluteAddressingMode(7)) { 0458 if (bytemode) 0459 RARVirtualMachineWrite8(vm, value + vm->registers[addressingmode % 8], (uint8_t)data); 0460 else 0461 RARVirtualMachineWrite32(vm, value + vm->registers[addressingmode % 8], data); 0462 } 0463 else if (addressingmode == RARAbsoluteAddressingMode) { 0464 if (bytemode) 0465 RARVirtualMachineWrite8(vm, value, (uint8_t)data); 0466 else 0467 RARVirtualMachineWrite32(vm, value, data); 0468 } 0469 } 0470 0471 /* Instruction properties */ 0472 0473 #define RAR0OperandsFlag 0 0474 #define RAR1OperandFlag 1 0475 #define RAR2OperandsFlag 2 0476 #define RAROperandsFlag 3 0477 #define RARHasByteModeFlag 4 0478 #define RARIsUnconditionalJumpFlag 8 0479 #define RARIsRelativeJumpFlag 16 0480 #define RARWritesFirstOperandFlag 32 0481 #define RARWritesSecondOperandFlag 64 0482 #define RARReadsStatusFlag 128 0483 #define RARWritesStatusFlag 256 0484 0485 static const int InstructionFlags[RARNumberOfInstructions] = { 0486 /*RARMovInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag, 0487 /*RARCmpInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesStatusFlag, 0488 /*RARAddInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0489 /*RARSubInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0490 /*RARJzInstruction*/ RAR1OperandFlag | RARIsUnconditionalJumpFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0491 /*RARJnzInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0492 /*RARIncInstruction*/ RAR1OperandFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0493 /*RARDecInstruction*/ RAR1OperandFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0494 /*RARJmpInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag, 0495 /*RARXorInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0496 /*RARAndInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0497 /*RAROrInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0498 /*RARTestInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesStatusFlag, 0499 /*RARJsInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0500 /*RARJnsInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0501 /*RARJbInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0502 /*RARJbeInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0503 /*RARJaInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0504 /*RARJaeInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag | RARReadsStatusFlag, 0505 /*RARPushInstruction*/ RAR1OperandFlag, 0506 /*RARPopInstruction*/ RAR1OperandFlag, 0507 /*RARCallInstruction*/ RAR1OperandFlag | RARIsRelativeJumpFlag, 0508 /*RARRetInstruction*/ RAR0OperandsFlag | RARIsUnconditionalJumpFlag, 0509 /*RARNotInstruction*/ RAR1OperandFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag, 0510 /*RARShlInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0511 /*RARShrInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0512 /*RARSarInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0513 /*RARNegInstruction*/ RAR1OperandFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARWritesStatusFlag, 0514 /*RARPushaInstruction*/ RAR0OperandsFlag, 0515 /*RARPopaInstruction*/ RAR0OperandsFlag, 0516 /*RARPushfInstruction*/ RAR0OperandsFlag | RARReadsStatusFlag, 0517 /*RARPopfInstruction*/ RAR0OperandsFlag | RARWritesStatusFlag, 0518 /*RARMovzxInstruction*/ RAR2OperandsFlag | RARWritesFirstOperandFlag, 0519 /*RARMovsxInstruction*/ RAR2OperandsFlag | RARWritesFirstOperandFlag, 0520 /*RARXchgInstruction*/ RAR2OperandsFlag | RARWritesFirstOperandFlag | RARWritesSecondOperandFlag | RARHasByteModeFlag, 0521 /*RARMulInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag, 0522 /*RARDivInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag, 0523 /*RARAdcInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARReadsStatusFlag | RARWritesStatusFlag, 0524 /*RARSbbInstruction*/ RAR2OperandsFlag | RARHasByteModeFlag | RARWritesFirstOperandFlag | RARReadsStatusFlag | RARWritesStatusFlag, 0525 /*RARPrintInstruction*/ RAR0OperandsFlag 0526 }; 0527 0528 int NumberOfRARInstructionOperands(uint8_t instruction) 0529 { 0530 if (instruction >= RARNumberOfInstructions) 0531 return 0; 0532 return InstructionFlags[instruction] & RAROperandsFlag; 0533 } 0534 0535 bool RARInstructionHasByteMode(uint8_t instruction) 0536 { 0537 if (instruction >= RARNumberOfInstructions) 0538 return false; 0539 return (InstructionFlags[instruction] & RARHasByteModeFlag)!=0; 0540 } 0541 0542 bool RARInstructionIsUnconditionalJump(uint8_t instruction) 0543 { 0544 if (instruction >= RARNumberOfInstructions) 0545 return false; 0546 return (InstructionFlags[instruction] & RARIsUnconditionalJumpFlag) != 0; 0547 } 0548 0549 bool RARInstructionIsRelativeJump(uint8_t instruction) 0550 { 0551 if (instruction >= RARNumberOfInstructions) 0552 return false; 0553 return (InstructionFlags[instruction] & RARIsRelativeJumpFlag) != 0; 0554 } 0555 0556 bool RARInstructionWritesFirstOperand(uint8_t instruction) 0557 { 0558 if (instruction >= RARNumberOfInstructions) 0559 return false; 0560 return (InstructionFlags[instruction] & RARWritesFirstOperandFlag) != 0; 0561 } 0562 0563 bool RARInstructionWritesSecondOperand(uint8_t instruction) 0564 { 0565 if (instruction >= RARNumberOfInstructions) 0566 return false; 0567 return (InstructionFlags[instruction] & RARWritesSecondOperandFlag) != 0; 0568 } 0569 0570 /* Program debugging */ 0571 0572 #ifndef NDEBUG 0573 #include <stdio.h> 0574 0575 static void RARPrintOperand(uint8_t addressingmode, uint32_t value) 0576 { 0577 if (RARRegisterAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterAddressingMode(7)) 0578 printf("r%d", addressingmode % 8); 0579 else if (RARRegisterIndirectAddressingMode(0) <= addressingmode && addressingmode <= RARRegisterIndirectAddressingMode(7)) 0580 printf("@(r%d)", addressingmode % 8); 0581 else if (RARIndexedAbsoluteAddressingMode(0) <= addressingmode && addressingmode <= RARIndexedAbsoluteAddressingMode(7)) 0582 printf("@(r%d+$%02x)", addressingmode % 8, value); 0583 else if (addressingmode == RARAbsoluteAddressingMode) 0584 printf("@($%02x)", value); 0585 else if (addressingmode == RARImmediateAddressingMode) 0586 printf("$%02x", value); 0587 } 0588 0589 void RARPrintProgram(RARProgram *prog) 0590 { 0591 static const char *instructionNames[RARNumberOfInstructions] = { 0592 "Mov", "Cmp", "Add", "Sub", "Jz", "Jnz", "Inc", "Dec", "Jmp", "Xor", 0593 "And", "Or", "Test", "Js", "Jns", "Jb", "Jbe", "Ja", "Jae", "Push", 0594 "Pop", "Call", "Ret", "Not", "Shl", "Shr", "Sar", "Neg", "Pusha", "Popa", 0595 "Pushf", "Popf", "Movzx", "Movsx", "Xchg", "Mul", "Div", "Adc", "Sbb", "Print", 0596 }; 0597 0598 uint32_t i; 0599 for (i = 0; i < prog->length; i++) { 0600 RAROpcode *opcode = &prog->opcodes[i]; 0601 int numoperands = NumberOfRARInstructionOperands(opcode->instruction); 0602 printf(" %02x: %s", i, instructionNames[opcode->instruction]); 0603 if (opcode->bytemode) 0604 printf("B"); 0605 if (numoperands >= 1) { 0606 printf(" "); 0607 RARPrintOperand(opcode->addressingmode1, opcode->value1); 0608 } 0609 if (numoperands == 2) { 0610 printf(", "); 0611 RARPrintOperand(opcode->addressingmode2, opcode->value2); 0612 } 0613 printf("\n"); 0614 } 0615 } 0616 #endif