cpu.c 7.46 KB
//
// Created by imanol on 12/25/16.
//

#include <stdlib.h>
#include "cpu.h"

uint64_t cycle_count = 0;

void mov(uint16_t dst, uint16_t src)
{
    if(src > MAX_INT)
    {
        regs[dst % (MAX_INT+1)] = regs[src % (MAX_INT+1)];
    }
    else
    {
        regs[dst % (MAX_INT+1)] = src;
    }
}

void push(uint16_t src)
{
    if(src > MAX_INT)
    {
        stack_push(regs[src % (MAX_INT+1)]);
    }
    else
    {
        stack_push(src);
    }
}

void pop(uint16_t dst)
{
    uint16_t value = stack_pop();
    if(STACK_FAULT)
    {
        fprintf(stderr,"CRITICAL: STACK VIOLATION\n");
        core_dump();
    }
    regs[dst % (MAX_INT+1)] = value;
}

void teq(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a == b);
}

void tgt(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a > b);
}

void jmp(uint16_t dst)
{
    if(dst > MAX_INT)
    {
        pc = regs[dst % (MAX_INT+1)];
    }
    else
    {
        pc = dst;
    }
}

void jnz(uint16_t cond, uint16_t dst)
{
    if(cond > MAX_INT)
    {
        cond = regs[cond % (MAX_INT+1)];
    }
    if(cond)
    {
        jmp(dst);
    }
}

void jz(uint16_t cond, uint16_t dst)
{
    if(cond > MAX_INT)
    {
        cond = regs[cond % (MAX_INT+1)];
    }
    if(!cond)
    {
        jmp(dst);
    }
}

void add(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a + b) % (MAX_INT+1);
}

void mult(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a * b) % (MAX_INT+1);
}

void mod(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a % b);
}

void and(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a & b);
}

void or(uint16_t dst, uint16_t a, uint16_t b)
{
    if(a > MAX_INT)
    {
        a = regs[a % (MAX_INT+1)];
    }
    if(b > MAX_INT)
    {
        b = regs[b % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = (a | b);
}

void not(uint16_t dst, uint16_t src)
{
    if(src > MAX_INT)
    {
        src = regs[src % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = ~src & 0x7FFF;
}

void load(uint16_t dst, uint16_t src)
{
    if(src > MAX_INT)
    {
        src = regs[src % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = mem[src];
}

void stor(uint16_t dst, uint16_t src)
{
    if(src > MAX_INT)
    {
        src = regs[src % (MAX_INT+1)];
    }
    if(dst > MAX_INT)
    {
        mem[regs[dst % (MAX_INT+1)]] = src;
    }
    else
    {
        mem[dst] = src;
    }
}

void call(uint16_t dst)
{
    stack_push(pc);
    jmp(dst);
}

uint8_t ret()
{
    pc = stack_pop();
    return STACK_FAULT;
}

void out(uint16_t src)
{
    if(src > MAX_INT)
    {
        src = regs[src % (MAX_INT+1)];
    }
    putchar(src);
}

void in(uint16_t dst)
{
    int c = getchar();
    regs[dst % (MAX_INT + 1)] = (uint16_t)c;
}

void nop()
{
    return;
}

uint16_t fetch()
{
    /*if(pc == 0x5bf-1)
    {
	//break
    }*/
    uint16_t value = mem[pc++];
    //printf("0x%2x (0x%2x)",pc,pc*sizeof(uint16_t));
    //printf(" cycle: %d\n",cycle_count++);
    return value;
}

void start_execution()
{
    uint16_t arg1;
    uint16_t arg2;
    uint16_t arg3;
    for(;;)
    {
        uint16_t opcode = fetch();
        switch(opcode)
        {
            case HALT:
                return;
            case MOV:
                arg1 = fetch();
                arg2 = fetch();
                mov(arg1,arg2);
                break;
            case PUSH:
                arg1 = fetch();
                push(arg1);
                break;
            case POP:
                arg1 = fetch();
                pop(arg1);
                break;
            case TEQ:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                teq(arg1,arg2,arg3);
                break;
            case TGT:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                tgt(arg1,arg2,arg3);
                break;
            case JMP:
                arg1 = fetch();
                jmp(arg1);
                break;
            case JNZ:
                arg1 = fetch();
                arg2 = fetch();
                jnz(arg1,arg2);
                break;
            case JZ:
                arg1 = fetch();
                arg2 = fetch();
                jz(arg1,arg2);
                break;
            case ADD:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                add(arg1,arg2,arg3);
                break;
            case MULT:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                mult(arg1,arg2,arg3);
                break;
            case MOD:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                mod(arg1,arg2,arg3);
                break;
            case AND:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                and(arg1,arg2,arg3);
                break;
            case OR:
                arg1 = fetch();
                arg2 = fetch();
                arg3 = fetch();
                or(arg1,arg2,arg3);
                break;
            case NOT:
                arg1 = fetch();
                arg2 = fetch();
                not(arg1,arg2);
                break;
            case LOAD:
                arg1 = fetch();
                arg2 = fetch();
                load(arg1,arg2);
                break;
            case STOR:
                arg1 = fetch();
                arg2 = fetch();
                stor(arg1,arg2);
                break;
            case CALL:
                arg1 = fetch();
                call(arg1);
                break;
            case RET:
                if(ret())
                {
                    return;
                }
                break;
            case OUT:
                arg1 = fetch();
                out(arg1);
                break;
            case IN:
                arg1 = fetch();
                in(arg1);
                break;
            case NOP:
                nop();
                break;
            default:
                fprintf(stderr,"CRITICAL: UNKNOWN OPCODE %2x FOUND IN %2x\n",opcode,pc);
                core_dump();
                break;
        }
    }
}

void core_dump()
{
    fprintf(stderr,"r0: %2x\n",regs[0]);
    fprintf(stderr,"r1: %2x\n",regs[1]);
    fprintf(stderr,"r2: %2x\n",regs[2]);
    fprintf(stderr,"r3: %2x\n",regs[3]);
    fprintf(stderr,"r4: %2x\n",regs[4]);
    fprintf(stderr,"r5: %2x\n",regs[5]);
    fprintf(stderr,"r6: %2x\n",regs[6]);
    fprintf(stderr,"r7: %2x\n",regs[7]);
    fprintf(stderr,"pc: %2x\n",pc);
    //dump memory to file
    //dump stack to file
    exit(1);
}