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

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

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

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

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

void teq(short dst, short a, short 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(short dst, short a, short 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(short dst)
{
    if(dst > MAX_INT)
    {
        pc = regs[dst % (MAX_INT+1)];
    }
    else
    {
        pc = dst;
    }
}

void jnz(short cond, short dst)
{
    if(cond)
    {
        jmp(dst);
    }
}

void jz(short cond, short dst)
{
    if(!cond)
    {
        jmp(dst);
    }
}

void add(short dst, short a, short 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(short dst, short a, short 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(short dst, short a, short 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(short dst, short a, short 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(short dst, short a, short 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(short dst, short src)
{
    if(src > MAX_INT)
    {
        src = regs[src % (MAX_INT+1)];
    }
    regs[dst % (MAX_INT+1)] = ~src & 0x7FFF;
}

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

void stor(short dst, short 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(short dst)
{
    stack_push(pc);
    jmp(dst);
}

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

void out(unsigned char a)
{
    putchar(a);
}

void in(short dst)
{
    int c = getchar();
    regs[dst] = (short)c;
}

void nop()
{
    return;
}

void start_execution()
{
    for(;;)
    {
        short opcode = mem[pc++];
        switch(opcode)
        {
            case HALT:
                return;
            case MOV:
                mov(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case PUSH:
                push(mem[pc++]);
                break;
            case POP:
                pop(mem[pc++]);
                break;
            case TEQ:
                teq(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case TGT:
                tgt(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case JMP:
                jmp(mem[pc++]);
                break;
            case JNZ:
                jnz(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case JZ:
                jz(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case ADD:
                add(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case MULT:
                mult(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case MOD:
                mod(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case AND:
                and(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case OR:
                or(mem[pc],mem[pc+1],mem[pc+2]);
                pc += 3;
                break;
            case NOT:
                not(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case LOAD:
                load(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case STOR:
                stor(mem[pc],mem[pc+1]);
                pc += 2;
                break;
            case CALL:
                call(mem[pc++]);
                break;
            case RET:
                if(ret())
                {
                    return;
                }
                break;
            case OUT:
                out((unsigned char)mem[pc++]);
                break;
            case IN:
                in(mem[pc++]);
                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);
}