Emulator/src/execute.c

97 lines
1.8 KiB
C

#include "../header/execute.h"
int execute(uint32_t *memory)
{
uint32_t instr_ptr = 0;
uint32_t instr_curr;
uint32_t cpu_register = 0;
while((instr_curr = memory[instr_ptr]) >> 28 != INSTR_EOJ)
{
uint8_t op_code = memory[instr_ptr] >> 28; // Get only the first 4 bits
uint32_t adress = memory[instr_ptr] & ADRESS_BITS; // Discard the first 4 bits
// This check should be unnecessary when using the official EIPA Assembler, but
// some people might want to hand-craft their EIPA Images
if(adress > MAX_MEMORY)
{
printf("ERROR: Adress on instruction %u is too big\n", instr_ptr);
return 1;
}
// Run the instruction
switch(op_code)
{
case INSTR_INP:
{
printf("Input: ");
int check = scanf("%u", memory + adress);
fflush(stdin);
if(!check)
{
printf("ERROR: Received invalid input on a INP instruction\n");
return 1;
}
instr_ptr++;
break;
}
case INSTR_OUT:
printf("%u\n", memory[adress]);
instr_ptr++;
break;
case INSTR_LDA:
cpu_register = memory[adress];
instr_ptr++;
break;
case INSTR_STA:
memory[adress] = cpu_register;
instr_ptr++;
break;
case INSTR_INC:
cpu_register++;
instr_ptr++;
break;
case INSTR_DEC:
cpu_register--;
instr_ptr++;
break;
case INSTR_JPP:
if(cpu_register > 0)
{
instr_ptr = adress;
}
else
{
instr_ptr++;
}
break;
case INSTR_JPZ:
if(cpu_register == 0)
{
instr_ptr = adress;
}
else
{
instr_ptr++;
}
break;
case INSTR_JPN:
if(cpu_register < 0)
{
instr_ptr = adress;
}
else
{
instr_ptr++;
}
break;
case INSTR_JPU:
instr_ptr = adress;
break;
default:
printf("ERROR: Unknown opcode %u\n", op_code);
}
}
return 0;
}