97 lines
1.8 KiB
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;
|
|
}
|