r16/emu/cpu/instruction.c

213 lines
8.3 KiB
C
Raw Normal View History

2024-04-19 10:08:32 +00:00
#include "./instruction.h"
2024-04-22 11:08:57 +00:00
#include "../cpu_human.h"
2024-04-19 12:11:28 +00:00
#include <stdio.h>
#include <stdlib.h>
2024-04-22 11:08:57 +00:00
#include <inttypes.h>
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);
2024-04-24 12:11:00 +00:00
sprintf(actArg1, "0x%X", arg1Val.u);
2024-04-22 11:08:57 +00:00
sprintf(actArg2, "0x%X", arg2Val.u);
switch (arg1Info)
{
case value:
2024-04-24 12:11:00 +00:00
free(hReadA1);
2024-04-22 11:08:57 +00:00
hReadA1 = "~";
break;
case valueInRam:
sprintf(hReadA1, "0x%X", arg1.u);
break;
case valueInRegister:
2024-04-24 12:11:00 +00:00
free(hReadA1);
2024-04-22 11:08:57 +00:00
hReadA1 = CpuRegistersHumanReadable[arg1.u];
break;
case pointerInRegister:
sprintf(hReadA1, "%s ~ 0x%X", CpuRegistersHumanReadable[arg1.u], GetRegister(arg1.u).u);
break;
}
switch (arg2Info)
{
case value:
2024-04-24 12:11:00 +00:00
free(hReadA2);
2024-04-22 11:08:57 +00:00
hReadA2 = "~";
break;
case valueInRam:
sprintf(hReadA2, "0x%X", arg2.u);
break;
case valueInRegister:
2024-04-24 12:11:00 +00:00
free(hReadA2);
2024-04-22 11:08:57 +00:00
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);
}
2024-04-19 10:08:32 +00:00
r16_int GetArgVal(ArgumentInfo argInfo, r16_int arg)
{
2024-04-19 12:11:28 +00:00
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);
2024-04-19 10:08:32 +00:00
}
void ExecuteInstruction(CpuInstructions instruction, ArgumentInfo arg1Info,
ArgumentInfo arg2Info, r16_int arg1, r16_int arg2)
{
2024-04-19 12:11:28 +00:00
r16_int actArg1, actArg2;
2024-04-19 10:08:32 +00:00
switch (instruction)
{
case HLT:
2024-04-19 12:11:28 +00:00
printf("\nprogram HALTED!\n");
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 });
2024-04-19 10:08:32 +00:00
exit(0);
case ADD:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s + actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case SUB:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s - actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case MUL:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s * actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case DIV:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
2024-04-24 12:11:00 +00:00
if (actArg2.s == 0)
{
fprintf(stderr, "DIV by 0\n");
exit(-1);
}
2024-04-19 12:11:28 +00:00
SetRegister(ACU, (r16_int){ actArg1.s / actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case LBS:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s << actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case RBS:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s >> actArg2.s });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case BAN:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u & actArg2.u });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case BOR:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u | actArg2.u });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case BXO:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u ^ actArg2.u });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case BNO:
2024-04-22 11:08:57 +00:00
actArg1 = GetArgVal(arg1Info, arg1);
SetRegister(ACU, (r16_int){ ~ actArg1.u });
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case PUS:
2024-04-22 11:08:57 +00:00
actArg1 = GetArgVal(arg1Info, arg1);
StackPush(actArg1);
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case POP:
2024-04-19 12:11:28 +00:00
SetRegister(ACU, StackPop());
break;
2024-04-19 10:08:32 +00:00
case JMP:
2024-04-19 12:11:28 +00:00
SetRegister(PC, GetArgVal(arg1Info, arg1));
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case JEQ:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
if (actArg2.u == GetRegister(ACU).u)
SetRegister(PC, actArg1);
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case JNZ:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
if (actArg2.s != 0)
SetRegister(PC, actArg1);
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case CAL:
2024-04-22 11:08:57 +00:00
actArg1 = GetArgVal(arg1Info, arg1);
2024-04-19 12:11:28 +00:00
StackPush(GetRegister(PC));
2024-04-22 11:08:57 +00:00
SetRegister(PC, actArg1);
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case RET:
2024-04-19 12:11:28 +00:00
SetRegister(PC, StackPop());
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
case REG: // TODO
case INT: // TODO
fprintf(stderr, "INTS NOT IMPLEMENTED YET\n");
exit(-1);
2024-04-19 10:08:32 +00:00
case INP:
2024-04-19 12:11:28 +00:00
SetRegister(ACU, (r16_int){ getchar() });
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, (r16_int){ 0 }, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
case OUT:
2024-04-22 11:08:57 +00:00
actArg1 = GetArgVal(arg1Info, arg1);
2024-04-19 12:11:28 +00:00
putchar((char)(GetArgVal(arg1Info, arg1).u));
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, (r16_int){ 0 });
2024-04-19 12:11:28 +00:00
break;
case DIN: // TODO
case DOT: // TODO
fprintf(stderr, "DISK NOT IMPLEMENTED YET\n");
exit(-1);
2024-04-19 10:08:32 +00:00
case MOV:
2024-04-19 12:11:28 +00:00
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetValue(actArg1, actArg2);
2024-04-22 11:08:57 +00:00
LogInstructionData(instruction, arg1Info, arg2Info, arg1, arg2, actArg1, actArg2);
2024-04-19 12:11:28 +00:00
break;
2024-04-19 10:08:32 +00:00
}
}