Added return stack
This commit is contained in:
parent
ba2e7aefa1
commit
1482e5662d
37
README.md
37
README.md
|
@ -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
|
||||
|
||||
|
|
17
example.usm
17
example.usm
|
@ -1,5 +1,18 @@
|
|||
< comment >
|
||||
|
||||
[3 1 2 3 ] pop dup swp ovr rot
|
||||
.deep JSR [4 6 7 8 9 ] BRK
|
||||
|
||||
:deep
|
||||
[2 1 2 ]
|
||||
.deeper JSR
|
||||
RTS
|
||||
|
||||
:deeper
|
||||
[3 3 4 5 ]
|
||||
.deeperyet JSR
|
||||
RTS
|
||||
|
||||
:deeperyet
|
||||
[2 aa bb ]
|
||||
RTS
|
||||
|
||||
brk
|
||||
|
|
96
uxn.c
96
uxn.c
|
@ -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
|
||||
|
|
75
uxnasm.c
75
uxnasm.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue