aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2012-04-25 23:06:58 +0000
committerDimitri Sokolyuk <demon@dim13.org>2012-04-25 23:06:58 +0000
commitbb6cb77863e2b6d0e84c698b5b0530d86b6f985c (patch)
tree8b253af4f628923d28660c1497be858051ec9aad
parentf2d426a0874e04816979fd0e4eb703821867b8d7 (diff)
spec 1.3, work in progress: some new ops are on todo
-rw-r--r--dcpu16.h13
-rw-r--r--emu.c370
-rw-r--r--gramar.y53
-rw-r--r--lexer.l27
-rw-r--r--tui.c4
5 files changed, 327 insertions, 140 deletions
diff --git a/dcpu16.h b/dcpu16.h
index af96a6e..12b36b2 100644
--- a/dcpu16.h
+++ b/dcpu16.h
@@ -18,12 +18,17 @@
#ifndef _DCPU16_H
#define _DCPU16_H
-enum { A, B, C, X, Y, Z, I, J, PC, SP, O, Aux, nReg };
+enum { A, B, C, X, Y, Z, I, J, PC, SP, EX, IA,
+ Aux, nReg };
-enum { EXT, SET, ADD, SUB, MUL, DIV, MOD, SHL,
- SHR, AND, BOR, XOR, IFE, IFN, IFG, IFB, nOpt };
+enum { EXT, SET, ADD, SUB, MUL, MLI, DIV, DVI,
+ MOD, AND, BOR, XOR, SHR, ASR, SHL, MVI,
+ IFB, IFC, IFE, IFN, IFG, IFA, IFL, IFU,
+ ADX = 0x1a, SUX, nOpt };
-enum { NOP, JSR, BRK, nExt };
+enum { NOP, JSR, BRK,
+ INT = 0x08, IAG, IAS,
+ HWN = 0x10, HWQ, HWI, nExt };
#define MEMSZ 0x10000
diff --git a/emu.c b/emu.c
index 1d363ca..8752c8f 100644
--- a/emu.c
+++ b/emu.c
@@ -26,218 +26,358 @@ static unsigned short skip = 0;
static unsigned short run = 1;
static unsigned short cycle = 0;
-void ext(unsigned short *a, unsigned short *b);
-void set(unsigned short *a, unsigned short *b);
-void add(unsigned short *a, unsigned short *b);
-void sub(unsigned short *a, unsigned short *b);
-void mul(unsigned short *a, unsigned short *b);
-void div(unsigned short *a, unsigned short *b);
-void mod(unsigned short *a, unsigned short *b);
-void shl(unsigned short *a, unsigned short *b);
-void shr(unsigned short *a, unsigned short *b);
-void and(unsigned short *a, unsigned short *b);
-void bor(unsigned short *a, unsigned short *b);
-void xor(unsigned short *a, unsigned short *b);
-void ife(unsigned short *a, unsigned short *b);
-void ifn(unsigned short *a, unsigned short *b);
-void ifg(unsigned short *a, unsigned short *b);
-void ifb(unsigned short *a, unsigned short *b);
+void
+nop(unsigned short *a)
+{
+ cycle += 1;
+}
-void (*op[nOpt])(unsigned short *a, unsigned short *b) = {
- [EXT] = ext,
- [SET] = set,
- [ADD] = add,
- [SUB] = sub,
- [MUL] = mul,
- [DIV] = div,
- [MOD] = mod,
- [SHL] = shl,
- [SHR] = shr,
- [AND] = and,
- [BOR] = bor,
- [XOR] = xor,
- [IFE] = ife,
- [IFN] = ifn,
- [IFG] = ifg,
- [IFB] = ifb,
-};
+void
+jsr(unsigned short *a)
+{
+ mem[--reg[SP]] = reg[PC];
+ reg[PC] = *a;
+ cycle += 3;
+}
+
+void
+stop(unsigned short *a)
+{
+ run = 0;
+ cycle += 1;
+}
-void nop(unsigned short *a);
-void jsr(unsigned short *a);
-void stop(unsigned short *a);
+
+void
+intr(unsigned short *a)
+{
+ /* TODO */
+ cycle += 4;
+}
+
+void
+iag(unsigned short *a)
+{
+ /* TODO */
+ cycle += 1;
+}
+
+void
+ias(unsigned short *a)
+{
+ /* TODO */
+ cycle += 1;
+}
+
+void
+hwn(unsigned short *a)
+{
+ /* TODO */
+ cycle += 2;
+}
+
+void
+hwq(unsigned short *a)
+{
+ /* TODO */
+ cycle += 4;
+}
+
+void
+hwi(unsigned short *a)
+{
+ /* TODO */
+ cycle += 4;
+}
void (*extop[nExt])(unsigned short *a) = {
[NOP] = nop,
[JSR] = jsr,
[BRK] = stop,
+ [INT] = intr,
+ [IAG] = iag,
+ [IAS] = ias,
+ [HWN] = hwn,
+ [HWQ] = hwq,
+ [HWI] = hwi,
};
void
-ext(unsigned short *a, unsigned short *b)
+ext(unsigned short *b, unsigned short *a)
{
- if (*a < nExt)
- extop[*a](b);
+ extop[*b](a);
}
void
-set(unsigned short *a, unsigned short *b)
+set(unsigned short *b, unsigned short *a)
{
- *a = *b;
+ *b = *a;
cycle += 1;
}
void
-add(unsigned short *a, unsigned short *b)
+add(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ int tmp = *b;
- tmp += *b;
- reg[O] = tmp > 0xFFFF;
+ tmp += *a;
+ reg[EX] = (tmp > 0xFFFF) ? 0x0001 : 0;
- *a = tmp;
+ *b = tmp;
cycle += 2;
}
void
-sub(unsigned short *a, unsigned short *b)
+sub(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ int tmp = *b;
- tmp -= *b;
- reg[O] = tmp < 0;
+ tmp -= *a;
+ reg[EX] = (tmp < 0) ? 0xFFFF : 0;
- *a = tmp;
+ *b = tmp;
cycle += 2;
}
void
-mul(unsigned short *a, unsigned short *b)
+mul(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ unsigned int tmp = *b;
- tmp *= *b;
- reg[O] = tmp >> 16;
+ tmp *= *a;
+ reg[EX] = tmp >> 16;
- *a = tmp;
+ *b = tmp;
cycle += 2;
}
void
-div(unsigned short *a, unsigned short *b)
+mli(unsigned short *b, unsigned short *a)
+{
+ int tmp = *b;
+
+ tmp *= *a;
+ reg[EX] = tmp >> 16;
+
+ *b = tmp;
+ cycle += 2;
+}
+
+void
+div(unsigned short *b, unsigned short *a)
+{
+ unsigned int tmp = *b;
+
+ if (*a == 0) {
+ reg[EX] = 0;
+ *b = 0;
+ } else {
+ reg[EX] = ((tmp << 16) / *a);
+ *b /= *a;
+ }
+ cycle += 3;
+}
+
+void
+dvi(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ int tmp = *b;
- if (*b == 0) {
- reg[O] = 0;
- *a = 0;
+ if (*a == 0) {
+ reg[EX] = 0;
+ *b = 0;
} else {
- reg[O] = ((tmp << 16) / *b);
- *a /= *b;
+ reg[EX] = ((tmp << 16) / *a);
+ *b /= *a;
}
cycle += 3;
}
void
-mod(unsigned short *a, unsigned short *b)
+mod(unsigned short *b, unsigned short *a)
{
- if (*b == 0)
- *a = 0;
+ if (*a == 0)
+ *b = 0;
else
- *a %= *b;
+ *b %= *a;
cycle += 3;
}
void
-shl(unsigned short *a, unsigned short *b)
+and(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ *b &= *a;
+ cycle += 1;
+}
- reg[O] = ((tmp << *b) >> 16);
- *a <<= *b;
+void
+bor(unsigned short *b, unsigned short *a)
+{
+ *b |= *a;
+ cycle += 1;
+}
+
+void
+xor(unsigned short *b, unsigned short *a)
+{
+ *b ^= *a;
+ cycle += 1;
+}
+
+void
+shr(unsigned short *b, unsigned short *a)
+{
+ int tmp = *b;
+
+ /* TODO */
+
+ reg[EX] = ((tmp << 16) >> *a);
+ *b >>= *a;
cycle += 2;
}
void
-shr(unsigned short *a, unsigned short *b)
+asr(unsigned short *b, unsigned short *a)
{
- int tmp = *a;
+ int tmp = *b;
- reg[O] = ((tmp << 16) >> *b);
- *a >>= *b;
+ /* TODO */
+
+ reg[EX] = ((tmp << 16) >> *a);
+ *b >>= *a;
cycle += 2;
}
void
-and(unsigned short *a, unsigned short *b)
+shl(unsigned short *b, unsigned short *a)
{
- *a &= *b;
- cycle += 1;
+ int tmp = *b;
+
+ /* TODO */
+
+ reg[EX] = ((tmp << *a) >> 16);
+ *b <<= *a;
+ cycle += 2;
}
void
-bor(unsigned short *a, unsigned short *b)
+mvi(unsigned short *b, unsigned short *a)
{
- *a |= *b;
- cycle += 1;
+ *b = *a;
+ ++reg[I];
+ ++reg[J];
+ cycle += 2;
}
void
-xor(unsigned short *a, unsigned short *b)
+ifb(unsigned short *b, unsigned short *a)
{
- *a ^= *b;
- cycle += 1;
+ skip = !(*b & *a);
+ cycle += 2 + skip;
}
void
-ife(unsigned short *a, unsigned short *b)
+ifc(unsigned short *b, unsigned short *a)
{
- skip = !(*a == *b);
+ skip = (*b & *a);
cycle += 2 + skip;
}
void
-ifn(unsigned short *a, unsigned short *b)
+ife(unsigned short *b, unsigned short *a)
{
- skip = !(*a != *b);
+ skip = !(*b == *a);
cycle += 2 + skip;
}
void
-ifg(unsigned short *a, unsigned short *b)
+ifn(unsigned short *b, unsigned short *a)
{
- skip = !(*a > *b);
+ skip = (*b == *a);
cycle += 2 + skip;
}
void
-ifb(unsigned short *a, unsigned short *b)
+ifg(unsigned short *b, unsigned short *a)
{
- skip = !(*a & *b);
+ skip = !(*b > *a);
cycle += 2 + skip;
}
void
-nop(unsigned short *a)
+ifa(unsigned short *b, unsigned short *a)
{
- cycle += 1;
+ skip = !((signed short)*b > (signed short)*a);
+ cycle += 2 + skip;
}
void
-jsr(unsigned short *a)
+ifl(unsigned short *b, unsigned short *a)
{
- mem[--reg[SP]] = reg[PC];
- reg[PC] = *a;
- cycle += 2;
+ skip = !(*b < *a);
+ cycle += 2 + skip;
}
void
-stop(unsigned short *a)
+ifu(unsigned short *b, unsigned short *a)
{
- run = 0;
+ skip = !((signed short)*b < (signed short)*a);
+ cycle += 2 + skip;
+}
+
+void
+adx(unsigned short *b, unsigned short *a)
+{
+ int tmp = *b;
+
+ /* TODO */
+ tmp += *a + reg[EX];
+ reg[EX] = tmp > 0xFFFF ? 0x0001 : 0;
+ cycle += 3;
}
+void
+sux(unsigned short *b, unsigned short *a)
+{
+ int tmp = *b;
+
+ /* TODO */
+ tmp -= *a + reg[EX];
+ reg[EX] = tmp < 0 ? 0x0001 : 0;
+ cycle += 3;
+}
+
+void (*op[nOpt])(unsigned short *a, unsigned short *b) = {
+ [EXT] = ext,
+ [SET] = set,
+ [ADD] = add,
+ [SUB] = sub,
+ [MUL] = mul,
+ [MLI] = mli,
+ [DIV] = div,
+ [DVI] = dvi,
+ [MOD] = mod,
+ [AND] = and,
+ [BOR] = bor,
+ [XOR] = xor,
+ [SHR] = shr,
+ [ASR] = asr,
+ [SHL] = shl,
+ [MVI] = mvi,
+ [IFB] = ifb,
+ [IFC] = ifc,
+ [IFE] = ife,
+ [IFN] = ifn,
+ [IFG] = ifg,
+ [IFA] = ifa,
+ [IFU] = ifu,
+ [IFL] = ifl,
+ [ADX] = adx,
+ [SUX] = sux,
+};
+
unsigned short *
-fetcharg(int a)
+fetcharg(int a, int first)
{
switch (a) {
case 0x00:
@@ -272,14 +412,17 @@ fetcharg(int a)
cycle += 1;
return &mem[mem[reg[PC]++] + reg[a - 0x10]];
case 0x18:
- /* pop */
- return &mem[reg[SP]++];
+ /* TODO push or pop */
+ if (first)
+ return &mem[reg[SP]++]; /* push */
+ else
+ return &mem[--reg[SP]]; /* pop */
case 0x19:
/* peek */
return &mem[reg[SP]];
case 0x1a:
- /* push */
- return &mem[--reg[SP]];
+ /* pick */
+ return &mem[reg[SP] + reg[PC]++];
case 0x1b:
/* SP */
return &reg[SP];
@@ -287,8 +430,8 @@ fetcharg(int a)
/* PC */
return &reg[PC];
case 0x1d:
- /* O */
- return &reg[O];
+ /* EX */
+ return &reg[EX];
case 0x1e:
/* [next word] */
cycle += 1;
@@ -319,17 +462,18 @@ step(unsigned short *m, unsigned short *r)
c = mem[reg[PC]++];
s = reg[SP]; /* store SP */
- o = c & 0x0f;
- reg[Aux] = (c >> 4) & 0x3f;
+ o = c & 0x1f;
+
/* don't fetch first arg for extended opcodes */
- a = o ? fetcharg(reg[Aux]) : &reg[Aux];
- b = fetcharg((c >> 10) & 0x3f);
+ reg[Aux] = (c >> 5) & 0x1f;
+ b = o ? fetcharg(reg[Aux], 0) : &reg[Aux];
+ a = fetcharg((c >> 10) & 0x3f, 1);
if (skip) {
skip = 0;
reg[SP] = s; /* restore SP on skipped opcode */
} else
- op[o](a, b);
+ op[o](b, a);
usleep(10 * cycle); /* 100kHz */
diff --git a/gramar.y b/gramar.y
index f2fa79e..08c4467 100644
--- a/gramar.y
+++ b/gramar.y
@@ -61,9 +61,13 @@ struct label {
};
%token A B C X Y Z I J
-%token POP PEEK PUSH SP PC O
-%token SET ADD SUB MUL DIV MOD SHL SHR AND BOR XOR IFE IFN IFG IFB
-%token NOP JSR BRK DAT ORG
+
+%token PUSH POP PEEK PICK SP PC EX
+
+%token SET ADD SUB MUL MLI DIV DVI MOD AND BOR XOR SHR ASR SHL MVI
+%token IFB IFC IFE IFN IFG IFA IFL IFU ADX SUX
+%token NOP BRK DAT ORG
+%token JSR INT IAG IAS HWN HWQ HWI
%token LBR RBR LBRACE RBRACE LPAR RPAR
%token COMMA DP PLUS MINUS MULT
%token DOT HASH MACRO INCLUDE
@@ -85,15 +89,15 @@ prog
statement
: opcode operand COMMA operand
{
- popop(($4 << 10) | ($2 << 4) | $1);
+ popop(($4 << 10) | ($2 << 5) | $1);
popall();
}
| extended operand
{
- popop(($2 << 10) | ($1 << 4));
+ popop(($2 << 10) | ($1 << 5));
popall();
}
- | noop { popop($1 << 4); }
+ | noop { popop($1 << 5); }
| DP STRING { addref($2); }
| DAT data { popall(); }
| ORG expr { pc = $2; }
@@ -133,12 +137,13 @@ expr
operand
: register { $$ = $1; }
| LBR register RBR { $$ = 0x08 + $2; }
+ | PUSH { $$ = 0x18; }
| POP { $$ = 0x18; }
| PEEK { $$ = 0x19; }
- | PUSH { $$ = 0x1a; }
+ | PICK { $$ = 0x1a; }
| SP { $$ = 0x1b; }
| PC { $$ = 0x1c; }
- | O { $$ = 0x1d; }
+ | EX { $$ = 0x1d; }
| LBR expr RBR
{
$$ = 0x1e;
@@ -201,21 +206,37 @@ opcode
| ADD { $$ = 0x02; }
| SUB { $$ = 0x03; }
| MUL { $$ = 0x04; }
- | DIV { $$ = 0x05; }
- | MOD { $$ = 0x06; }
- | SHL { $$ = 0x07; }
- | SHR { $$ = 0x08; }
+ | MLI { $$ = 0x05; }
+ | DIV { $$ = 0x06; }
+ | DVI { $$ = 0x07; }
+ | MOD { $$ = 0x08; }
| AND { $$ = 0x09; }
| BOR { $$ = 0x0a; }
| XOR { $$ = 0x0b; }
- | IFE { $$ = 0x0c; }
- | IFN { $$ = 0x0d; }
- | IFG { $$ = 0x0e; }
- | IFB { $$ = 0x0f; }
+ | SHR { $$ = 0x0c; }
+ | ASR { $$ = 0x0d; }
+ | SHL { $$ = 0x0e; }
+ | MVI { $$ = 0x0f; }
+ | IFB { $$ = 0x10; }
+ | IFC { $$ = 0x11; }
+ | IFE { $$ = 0x12; }
+ | IFN { $$ = 0x13; }
+ | IFG { $$ = 0x14; }
+ | IFA { $$ = 0x15; }
+ | IFL { $$ = 0x16; }
+ | IFU { $$ = 0x17; }
+ | ADX { $$ = 0x1a; }
+ | SUX { $$ = 0x1b; }
;
extended
: JSR { $$ = 0x01; }
+ | INT { $$ = 0x08; }
+ | IAG { $$ = 0x09; }
+ | IAS { $$ = 0x0a; }
+ | HWN { $$ = 0x10; }
+ | HWQ { $$ = 0x11; }
+ | HWI { $$ = 0x12; }
;
noop
diff --git a/lexer.l b/lexer.l
index 9d0697f..b48f8ab 100644
--- a/lexer.l
+++ b/lexer.l
@@ -39,31 +39,48 @@ DEC [0-9]+
[Aa][Dd][Dd] return ADD;
[Ss][Uu][Bb] return SUB;
[Mm][Uu][Ll] return MUL;
+[Mm][Ll][Ii] return MLI;
[Dd][Ii][Vv] return DIV;
+[Dd][Vv][Ii] return DVI;
[Mm][Oo][Dd] return MOD;
-[Ss][Hh][Ll] return SHL;
-[Ss][Hh][Rr] return SHR;
[Aa][Nn][Dd] return AND;
[Bb][Oo][Rr] return BOR;
[Xx][Oo][Rr] return XOR;
+[Ss][Hh][Rr] return SHR;
+[Aa][Ss][Rr] return ASR;
+[Ss][Hh][Ll] return SHL;
+[Mm][Vv][Ii] return MVI;
+[Ii][Ff][Bb] return IFB;
+[Ii][Ff][Cc] return IFC;
[Ii][Ff][Ee] return IFE;
[Ii][Ff][Nn] return IFN;
[Ii][Ff][Gg] return IFG;
-[Ii][Ff][Bb] return IFB;
+[Ii][Ff][Aa] return IFA;
+[Ii][Ff][Ll] return IFL;
+[Ii][Ff][Uu] return IFU;
+[Aa][Dd][Xx] return ADX;
+[Ss][Uu][Xx] return SUX;
[Nn][Oo][Pp] return NOP;
[Jj][Ss][Rr] return JSR;
[Bb][Rr][Kk] return BRK;
+[Ii][Nn][Tt] return INT;
+[Ii][Aa][Gg] return IAG;
+[Ii][Aa][Ss] return IAS;
+[Hh][Ww][Nn] return HWN;
+[Hh][Ww][Qq] return HWQ;
+[Hh][Ww][Ii] return HWI;
[Dd][Aa][Tt] return DAT;
[Oo][Rr][Gg] return ORG;
+[Pp][Uu][Ss][Hh] return PUSH;
[Pp][Oo][Pp] return POP;
[Pp][Ee][Ee][Kk] return PEEK;
-[Pp][Uu][Ss][Hh] return PUSH;
+[Pp][Ii][Cc][Kk] return PICK;
[Ss][Pp] return SP;
[Pp][Cc] return PC;
-[Oo] return O;
+[Ee][Xx] return EX;
[Aa] return A;
[Bb] return B;
diff --git a/tui.c b/tui.c
index 6fddaa9..3185d1b 100644
--- a/tui.c
+++ b/tui.c
@@ -104,7 +104,7 @@ dumpreg(unsigned short *mem, unsigned short *reg)
mvwprintw(regs, 0, 16, "PC: %4.4x [%4.4x]", reg[PC], mem[reg[PC]]);
mvwprintw(regs, 1, 16, "SP: %4.4x [%4.4x]", reg[SP], mem[reg[SP]]);
- mvwprintw(regs, 2, 16, " O: %4.4x [%4.4x]", reg[O], mem[reg[O]]);
+ mvwprintw(regs, 2, 16, "EX: %4.4x [%4.4x]", reg[EX], mem[reg[EX]]);
wnoutrefresh(regs);
}
@@ -132,7 +132,7 @@ tuiemu(unsigned short *m, unsigned short *r)
initscr();
noecho();
- nodelay(stdscr, TRUE);
+// nodelay(stdscr, TRUE);
start_color();
init_colors();