mcim/cpu.c

272 lines
3.8 KiB
C

/*
* Copyright (c) 2021, 2022 ipc
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include "mcim.h"
uint
lget(uchar *p)
{
uint n;
n = *p;
n |= *(p+1) << 8;
n |= *(p+2) << 16;
n |= *(p+3) << 24;
return n;
}
#define MEM(p) p->mem
static uint
lcget(struct mcimp *p)
{
uint n;
n = lget(&p->MEM(p)[p->pc]);
p->pc += 4;
return n;
}
static uint
rget(struct mcimp *p)
{
uint n;
n = p->MEM(p)[p->pc];
p->pc += 1;
return n;
}
#define R() rget(p)
#define L() lcget(p)
#define J(n) p->pc = n + p->epc
static void
lw(struct mcimp *p)
{
uint r;
uint l;
r = R();
if ((l = L() + 4) >= p->p->nmem)
return;
p->r[r] = lget(&p->MEM(p)[l+p->r[8]]);
}
static void
lb(struct mcimp *p)
{
uint r;
uint l;
r = R();
if ((l = L()) >= p->p->nmem)
return;
p->r[r] = p->MEM(p)[l+p->r[8]];
}
static void
li(struct mcimp *p)
{
uint r;
r = R();
p->r[r] = L();
}
static void
sw(struct mcimp *p)
{
uint r;
uint l;
uint c;
r = R();
l = L();
l += p->r[8];
if (l > p->p->nmem) {
c = (l - p->p->nmem) + 4;
allocmem(p->p, c);
p->p->nmem += c;
}
p->MEM(p)[l] = p->r[r];
p->MEM(p)[l+1] = p->r[r] >> 8;
p->MEM(p)[l+2] = p->r[r] >> 16;
p->MEM(p)[l+3] = p->r[r] >> 24;
}
static void
sb(struct mcimp *p)
{
uint r;
uint l;
uint c;
r = R();
l = L();
l += p->r[8];
if (l >= p->p->nmem) {
c = l - p->p->nmem;
allocmem(p->p, c+128);
p->p->nmem += c+128;
}
p->MEM(p)[l] = p->r[r];
}
static void
add(struct mcimp *p)
{
uint r[3];
r[0] = R();
r[1] = R();
r[2] = R();
p->r[r[2]] = p->r[r[0]] + p->r[r[1]];
}
static void
addi(struct mcimp *p)
{
uint r[2];
uint l;
r[0] = R();
l = L();
r[1] = R();
p->r[r[1]] = p->r[r[0]] + l;
}
static void
ble(struct mcimp *p)
{
uint r[2];
uint l;
r[0] = R();
r[1] = R();
l = L();
if (p->r[r[0]] < p->r[r[1]])
J(l);
}
static void
bgt(struct mcimp *p)
{
uint r[2];
uint l;
r[0] = R();
r[1] = R();
l = L();
if (p->r[r[0]] > p->r[r[1]])
J(l);
}
static void
beq(struct mcimp *p)
{
uint r[2];
uint l;
r[0] = R();
r[1] = R();
l = L();
if (p->r[r[0]] == p->r[r[1]])
J(l);
}
static void
bne(struct mcimp *p)
{
uint r[2];
uint l;
r[0] = R();
r[1] = R();
l = L();
if (p->r[r[0]] != p->r[r[1]])
J(l);
}
static void
j(struct mcimp *p)
{
J(L());
}
static void
jr(struct mcimp *p)
{
p->pc = p->r[R()];
}
static void
jal(struct mcimp *p)
{
uint pc;
pc = L();
p->r[3] = p->pc;
J(pc);
}
static void
sys(struct mcimp *p)
{
uint r;
r = p->r[R()];
switch (r) {
case SYSE:
p->stat |= STATEXIT;
break;
case SYSW:
if (p->p->ntty >= sizeof p->p->tty)
p->p->ntty = 0;
p->p->tty[p->p->ntty++] = p->r[1];
break;
default:
err(1, "fatal: illegal syscall (%08x)\n", r);
break;
}
}
static void (*op[]) (struct mcimp *) = {
&lw, NULL, &lb, &li, &sw, NULL, &sb, NULL,
&add, &addi, NULL, NULL, NULL, &ble, &bgt, &beq,
&bne, &j, &jr, &jal, &sys
};
#define brk(p) (p->stat & STATEXIT || p->stat & STATBRK)
void
step(struct mcim *p)
{
int n;
uint i;
struct mcimp *c;
for (i = 0; i < p->nproc; i++) {
n = SCHCNT;
c = &p->proc[i];
while (n-- && !brk(c))
op[p->mem[c->pc++]](c);
}
}