#include "./instruction.h" #include "../cpu_human.h" #include #include #include void LogInstructionData(CpuInstructions instruction, ArgumentInfo arg1Info, ArgumentInfo arg2Info, r16_int arg1, r16_int arg2, r16_int arg1Val, r16_int arg2Val) { char *hReadIns = CpuInstructionsHumanReadable[instruction], *hReadA1I = ArgumentInfoHumanReadable[arg1Info], *hReadA2I = ArgumentInfoHumanReadable[arg1Info], *actArg1 = malloc(sizeof(char) * 32), *actArg2 = malloc(sizeof(char) * 32), *hReadA1 = malloc(sizeof(char) * 32), *hReadA2 = malloc(sizeof(char) * 32); sprintf(actArg1, "0x%X", arg2Val.u); sprintf(actArg2, "0x%X", arg2Val.u); switch (arg1Info) { case value: hReadA1 = "~"; break; case valueInRam: sprintf(hReadA1, "0x%X", arg1.u); break; case valueInRegister: hReadA1 = CpuRegistersHumanReadable[arg1.u]; break; case pointerInRegister: sprintf(hReadA1, "%s ~ 0x%X", CpuRegistersHumanReadable[arg1.u], GetRegister(arg1.u).u); break; } switch (arg2Info) { case value: hReadA2 = "~"; break; case valueInRam: sprintf(hReadA2, "0x%X", arg2.u); break; case valueInRegister: hReadA2 = CpuRegistersHumanReadable[arg2.u]; break; case pointerInRegister: sprintf(hReadA2, "%s ~ 0x%X", CpuRegistersHumanReadable[arg2.u], GetRegister(arg2.u).u); break; } printf("%s :: (%s) %s -> %s, (%s) %s -> %s\n", hReadIns, hReadA1I, hReadA1, actArg1, hReadA2I, hReadA2, actArg2); free(actArg1); free(actArg2); free(hReadA1); free(hReadA2); } r16_int GetArgVal(ArgumentInfo argInfo, r16_int arg) { switch (argInfo) { case value: return arg; case valueInRegister: return GetRegister((CpuRegisters)arg.u); case valueInRam: return GetValue(arg); case pointerInRegister: return GetValue(GetRegister((CpuRegisters)arg.u)); } } void GetAllArgVal(ArgumentInfo arg1Info, ArgumentInfo arg2Info, r16_int arg1, r16_int arg2, r16_int *arg1Out, r16_int *arg2Out) { *arg1Out = GetArgVal(arg1Info, arg1); *arg2Out = GetArgVal(arg2Info, arg2); } void ExecuteInstruction(CpuInstructions instruction, ArgumentInfo arg1Info, ArgumentInfo arg2Info, r16_int arg1, r16_int arg2) { r16_int actArg1, actArg2; switch (instruction) { case HLT: printf("\nprogram HALTED!\n"); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 }); exit(0); case ADD: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s + actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case SUB: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s - actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case MUL: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s * actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case DIV: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s / actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case LBS: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s << actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case RBS: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.s >> actArg2.s }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case BAN: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.u & actArg2.u }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case BOR: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.u | actArg2.u }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case BXO: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetRegister(ACU, (r16_int){ actArg1.u ^ actArg2.u }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case BNO: actArg1 = GetArgVal(arg1Info, arg1); SetRegister(ACU, (r16_int){ ~ actArg1.u }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 }); break; case PUS: actArg1 = GetArgVal(arg1Info, arg1); StackPush(actArg1); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 }); break; case POP: SetRegister(ACU, StackPop()); break; case JMP: SetRegister(PC, GetArgVal(arg1Info, arg1)); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 }); break; case JEQ: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); if (actArg2.u == GetRegister(ACU).u) SetRegister(PC, actArg1); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case JNZ: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); if (actArg2.s != 0) SetRegister(PC, actArg1); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; case CAL: actArg1 = GetArgVal(arg1Info, arg1); StackPush(GetRegister(PC)); SetRegister(PC, actArg1); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 }); break; case RET: SetRegister(PC, StackPop()); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 }); break; case REG: // TODO case INT: // TODO fprintf(stderr, "INTS NOT IMPLEMENTED YET\n"); exit(-1); case INP: SetRegister(ACU, (r16_int){ getchar() }); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 }); break; case OUT: actArg1 = GetArgVal(arg1Info, arg1); putchar((char)(GetArgVal(arg1Info, arg1).u)); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 }); break; case DIN: // TODO case DOT: // TODO fprintf(stderr, "DISK NOT IMPLEMENTED YET\n"); exit(-1); case MOV: GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2); SetValue(actArg1, actArg2); LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2); break; } }