Added return stack

This commit is contained in:
neauoire 2021-01-30 21:31:49 -08:00
parent ba2e7aefa1
commit 1482e5662d
4 changed files with 153 additions and 72 deletions

View File

@ -10,6 +10,10 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
## Assembly Syntax
- `:label`, a named offset
- `+literal`, a numeric value
- `.pointer`, pointer to a label
```
< comment >
@ -30,31 +34,16 @@ $01 < pointer8 >
:label ADD RTS
```
## Design
### CPU
- Build stack with pointer
- Print stack
- Build memory
### PPU
### Assembly
#### Addressing
- `label`, a named offset[TODO]
- `literal`, a numeric value
- `pointer`, pointer to an address[TODO]
### Assembler
### Emulator
- SDL Layer
## TODOs
- Implement addressing
- Implement 16 bits operations
- Jumps should be relative
- Catch overflow/underflow
- Implement literals like `[2]`, and `[ 2 3 ]`.
- Audo-detect literals length.
- SDL Layer Emulator
- Build PPU
## Refs

View File

@ -1,5 +1,18 @@
< comment >
[3 1 2 3 ] pop dup swp ovr rot
.deep JSR [4 6 7 8 9 ] BRK
brk
:deep
[2 1 2 ]
.deeper JSR
RTS
:deeper
[3 3 4 5 ]
.deeperyet JSR
RTS
:deeperyet
[2 aa bb ]
RTS

96
uxn.c
View File

@ -24,8 +24,9 @@ typedef struct {
Uint8 literal;
Uint8 status, counter;
Uint8 memory[STACK_DEPTH];
Uint8 mptr, sptr;
Uint8 mptr, sptr, rsptr;
Uint8 stack[STACK_DEPTH];
Uint8 rstack[STACK_DEPTH];
Uint8 address[STACK_DEPTH];
} Computer;
@ -61,20 +62,66 @@ echo(Uint8 *s, Uint8 len, char *name)
printf("\n\n");
}
#pragma mark - Operations
void
op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
spush(Uint8 v)
{
s[(*ptr)++] = v;
cpu.stack[cpu.sptr++] = v;
}
Uint8
op_pop(Uint8 *s, Uint8 *ptr)
spop(void)
{
return s[--*ptr];
return cpu.stack[--cpu.sptr];
}
void
rspush(Uint8 v)
{
cpu.rstack[cpu.rsptr++] = v;
}
Uint8
rspop(void)
{
return cpu.rstack[--cpu.rsptr];
}
#pragma mark - Operations
/* clang-format off */
void op_brk() { setflag(FLAG_HALT, 1); }
void op_lit() { cpu.literal += cpu.memory[cpu.mptr++]; }
void op_nop() { }
void op_drp() { spop(); }
void op_dup() { spush(cpu.stack[cpu.sptr - 1]); }
void op_swp() { Uint8 b = spop(), a = spop(); spush(b); spush(a); }
void op_ovr() { spush(cpu.stack[cpu.sptr - 2]); }
void op_rot() { Uint8 c = spop(),b = spop(),a = spop(); spush(b); spush(c); spush(a); }
void op_jmp() { cpu.mptr = spop(); }
void op_jsr() { rspush(cpu.mptr); cpu.mptr = spop(); }
void op_jeq() { if(getflag(FLAG_ZERO)) cpu.mptr = spop(); }
void op_rts() { cpu.mptr = rspop(); }
void op_equ() { setflag(FLAG_ZERO, spop() == spop()); }
void op_neq() { setflag(FLAG_ZERO, spop() != spop()); }
void op_lth() { setflag(FLAG_ZERO, spop() < spop()); }
void op_gth() { setflag(FLAG_ZERO, spop() > spop()); }
void op_and() { spush(spop() & spop()); }
void op_ora() { spush(spop() | spop()); }
void op_rol() { spush(spop() << 1); }
void op_ror() { spush(spop() >> 1); }
void op_add() { spush(spop() + spop()); }
void op_sub() { spush(spop() - spop()); }
void op_mul() { spush(spop() * spop()); }
void op_div() { spush(spop() / spop()); }
void (*ops[])(void) = {
op_brk, op_lit, op_nop, op_drp, op_dup, op_swp, op_ovr, op_rot,
op_jmp, op_jsr, op_jeq, op_rts, op_equ, op_neq, op_gth, op_lth,
op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div};
/* clang-format on */
void
reset(void)
{
@ -105,42 +152,13 @@ void
eval()
{
Uint8 instr = cpu.memory[cpu.mptr++];
Uint8 a, b, c;
if(cpu.literal > 0) {
printf("push: %02x[%d](%d)\n", instr, cpu.literal, cpu.sptr);
op_push(cpu.stack, &cpu.sptr, instr);
spush(instr);
cpu.literal--;
return;
}
switch(instr) {
case 0x0: setflag(FLAG_HALT, 1); break;
case 0x1: cpu.literal += cpu.memory[cpu.mptr++]; break;
case 0x2: printf("??\n"); break;
case 0x3: /* pop */
op_pop(cpu.stack, &cpu.sptr);
break;
case 0x4: /* dup */
op_push(cpu.stack, &cpu.sptr, cpu.stack[cpu.sptr - 1]);
break;
case 0x5: /* swp */
b = op_pop(cpu.stack, &cpu.sptr);
a = op_pop(cpu.stack, &cpu.sptr);
op_push(cpu.stack, &cpu.sptr, b);
op_push(cpu.stack, &cpu.sptr, a);
break;
case 0x6: /* ovr */
op_push(cpu.stack, &cpu.sptr, cpu.stack[cpu.sptr - 2]);
break;
case 0x7: /* rot */
c = op_pop(cpu.stack, &cpu.sptr);
b = op_pop(cpu.stack, &cpu.sptr);
a = op_pop(cpu.stack, &cpu.sptr);
op_push(cpu.stack, &cpu.sptr, b);
op_push(cpu.stack, &cpu.sptr, c);
op_push(cpu.stack, &cpu.sptr, a);
break;
default: printf("Unknown instruction: #%02x\n", instr);
}
if(instr < 24)
(*ops[instr])();
}
void

View File

@ -12,6 +12,7 @@ WITH REGARD TO THIS SOFTWARE.
*/
#define PRGLEN 256
#define LABELIDLEN 32
typedef unsigned char Uint8;
@ -20,7 +21,13 @@ typedef struct {
Uint8 data[PRGLEN];
} Program;
char labels[256][16];
typedef struct {
Uint8 addr;
char name[LABELIDLEN];
} Label;
int labelslen;
Label labels[256];
char opcodes[][4] = {
"BRK",
@ -40,6 +47,14 @@ char opcodes[][4] = {
"NEQ",
"LTH",
"GTH",
"---",
"---",
"---",
"---",
"ADD",
"SUB",
"MUL",
"DIV"
/* */};
Program p;
@ -56,6 +71,16 @@ scmp(char *a, char *b) /* string compare */
return 0;
}
char *
scpy(char *src, char *dst, int len) /* string copy */
{
int i = 0;
while((dst[i] = src[i]) && i < len - 2)
i++;
dst[i + 1] = '\0';
return dst;
}
char *
suca(char *s) /* string to uppercase */
{
@ -72,7 +97,7 @@ sihx(char *s)
int i = 0;
char c;
while((c = s[i++]))
if(!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F'))
if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
return 0;
return 1;
}
@ -87,6 +112,8 @@ shex(char *s) /* string to num */
n = n * 16 + (c - '0');
else if(c >= 'A' && c <= 'F')
n = n * 16 + 10 + (c - 'A');
else if(c >= 'a' && c <= 'f')
n = n * 16 + 10 + (c - 'f');
return n;
}
@ -101,7 +128,10 @@ addprg(Uint8 hex)
void
addlabel(char *id, Uint8 addr)
{
printf("new label: %s=%02x\n", id, addr);
Label *l = &labels[labelslen++];
scpy(suca(id), l->name, LABELIDLEN);
l->addr = addr;
printf("new label: %s=%02x\n", l->name, l->addr);
}
void
@ -110,16 +140,39 @@ addconst(char *id, Uint8 value)
printf("new const: %s=%02x\n", id, value);
}
Label *
findlabel(char *s)
{
int i;
for(i = 0; i < labelslen; ++i)
if(scmp(labels[i].name, s))
return &labels[i];
return NULL;
}
Uint8
findop(char *s)
{
int i;
for(i = 0; i < 16; ++i)
for(i = 0; i < 24; ++i)
if(scmp(opcodes[i], s))
return i;
return 0;
}
int
getlength(char *w)
{
if(findop(w) || scmp(w, "BRK")) return 1;
if(w[0] == '.') return 3;
if(w[0] == ':') return 0;
if(w[0] == '[') return 2;
if(sihx(w)) return 1;
if(w[0] == ']') return 0;
printf("Unknown length %s\n", w);
return 0;
}
int
comment(char *w, int *skip)
{
@ -136,10 +189,12 @@ void
pass1(FILE *f)
{
int skip = 0;
int addr = 0;
char word[64];
while(fscanf(f, "%s", word) == 1) {
if(comment(word, &skip))
continue;
if(comment(word, &skip)) continue;
if(word[0] == ':') addlabel(word + 1, addr);
addr += getlength(word);
}
rewind(f);
}
@ -151,6 +206,8 @@ pass2(FILE *f)
char word[64];
while(fscanf(f, "%s", word) == 1) {
Uint8 op;
Label *l;
if(word[0] == ':') continue;
suca(word);
if(comment(word, &skip)) continue;
if(word[0] == ']') continue;
@ -167,7 +224,11 @@ pass2(FILE *f)
addprg(shex(word));
else if(scmp(word, "BRK"))
addprg(0x00);
else
else if((l = findlabel(word + 1))) {
addprg(0x01);
addprg(1);
addprg(l->addr);
} else
printf("unknown: %s\n", word);
}
}