r16/emu/cpu/instruction.c
2024-04-19 12:11:28 +00:00

122 lines
4.1 KiB
C

#include "./instruction.h"
#include <stdio.h>
#include <stdlib.h>
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");
exit(0);
case ADD:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s + actArg2.s });
break;
case SUB:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s - actArg2.s });
break;
case MUL:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s * actArg2.s });
break;
case DIV:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s / actArg2.s });
break;
case LBS:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s << actArg2.s });
break;
case RBS:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.s >> actArg2.s });
break;
case BAN:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u & actArg2.u });
break;
case BOR:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u | actArg2.u });
break;
case BXO:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
SetRegister(ACU, (r16_int){ actArg1.u ^ actArg2.u });
break;
case BNO:
SetRegister(ACU, (r16_int){ ~ GetArgVal(arg1Info, arg1).u });
break;
case PUS:
StackPush(GetArgVal(arg1Info, arg1));
break;
case POP:
SetRegister(ACU, StackPop());
break;
case JMP:
SetRegister(PC, GetArgVal(arg1Info, arg1));
break;
case JEQ:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
if (actArg2.u == GetRegister(ACU).u)
SetRegister(PC, actArg1);
break;
case JNZ:
GetAllArgVal(arg1Info, arg2Info, arg1, arg2, &actArg1, &actArg2);
if (actArg2.s != 0)
SetRegister(PC, actArg1);
break;
case CAL:
StackPush(GetRegister(PC));
SetRegister(PC, GetArgVal(arg1Info, arg1));
break;
case RET:
SetRegister(PC, StackPop());
break;
case REG: // TODO
case INT: // TODO
fprintf(stderr, "INTS NOT IMPLEMENTED YET\n");
exit(-1);
case INP:
SetRegister(ACU, (r16_int){ getchar() });
break;
case OUT:
putchar((char)(GetArgVal(arg1Info, arg1).u));
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);
break;
}
}