mirror of
https://git.sr.ht/~rabbits/uxn
synced 2024-11-29 09:13:01 +00:00
Started implementing errors
This commit is contained in:
parent
5147884639
commit
2cf40a4293
8 changed files with 124 additions and 118 deletions
29
README.md
29
README.md
|
@ -17,20 +17,20 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
```
|
```
|
||||||
< conditionals >
|
< conditionals >
|
||||||
|
|
||||||
+03 +02 ADD
|
0302 ADD
|
||||||
+05 EQU
|
05 EQU
|
||||||
|
|
||||||
.there JMQ
|
.there JMQ
|
||||||
|
|
||||||
:here
|
:here
|
||||||
< when not equal >
|
< when not equal >
|
||||||
+ee
|
ee
|
||||||
BRK
|
BRK
|
||||||
|
|
||||||
:there
|
:there
|
||||||
< when is equal >
|
< when is equal >
|
||||||
+ff
|
ff
|
||||||
BRK
|
BRK
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mission
|
## Mission
|
||||||
|
@ -44,10 +44,6 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
- Print word to stdout
|
- Print word to stdout
|
||||||
- Draw pixel to screen
|
- Draw pixel to screen
|
||||||
- Detect mouse click
|
- Detect mouse click
|
||||||
- 16 bits addressing
|
|
||||||
- jumping to subroutine should be relative
|
|
||||||
- Implement addressing
|
|
||||||
- Implement 16 bits operations
|
|
||||||
- Jumps should be relative
|
- Jumps should be relative
|
||||||
- Catch overflow/underflow
|
- Catch overflow/underflow
|
||||||
- Audo-detect literals length.
|
- Audo-detect literals length.
|
||||||
|
@ -55,6 +51,13 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
- Build PPU
|
- Build PPU
|
||||||
- Interrupts
|
- Interrupts
|
||||||
|
|
||||||
|
### 16 Bit Missions
|
||||||
|
|
||||||
|
- 16 bits addressing
|
||||||
|
- jumping to subroutine should be relative
|
||||||
|
- Implement addressing
|
||||||
|
- Implement 16 bits operations
|
||||||
|
|
||||||
## Refs
|
## Refs
|
||||||
|
|
||||||
https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c
|
https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
< conditionals >
|
< conditionals >
|
||||||
|
|
||||||
+03 +02 ADD
|
0302 ADD
|
||||||
+05 EQU
|
05 EQU
|
||||||
|
|
||||||
.there JMQ
|
.there JMQ
|
||||||
|
|
||||||
:here
|
:here
|
||||||
< when not equal >
|
< when not equal >
|
||||||
+ee
|
ee
|
||||||
BRK
|
BRK
|
||||||
|
|
||||||
:there
|
:there
|
||||||
< when is equal >
|
< when is equal >
|
||||||
+ff
|
ff
|
||||||
BRK
|
BRK
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
< core >
|
< core >
|
||||||
|
|
||||||
+12 +34 ADD
|
01 ADD
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
< conditionals >
|
< jump >
|
||||||
|
|
||||||
.end JMP
|
.end JMP BRK
|
||||||
|
|
||||||
:end
|
:end
|
||||||
+ff
|
ff
|
||||||
BRK
|
BRK
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
< comment >
|
|
||||||
|
|
||||||
.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
|
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
:begin
|
:begin
|
||||||
.addall JSR ADD ADD
|
.addall JSR ADD ADD
|
||||||
+06 EQU .isequal JSR
|
06 EQU .isequal JSR
|
||||||
BRK
|
BRK
|
||||||
|
|
||||||
:add1
|
:add1
|
||||||
+01 RTS
|
01 RTS
|
||||||
|
|
||||||
:add2
|
:add2
|
||||||
+02 RTS
|
02 RTS
|
||||||
|
|
||||||
:add3
|
:add3
|
||||||
+03 RTS
|
03 RTS
|
||||||
|
|
||||||
:addall
|
:addall
|
||||||
.add1 JSR
|
.add1 JSR
|
||||||
|
@ -21,5 +21,5 @@
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
:isequal
|
:isequal
|
||||||
.addall JSR +ff
|
.addall JSR ff
|
||||||
RTS
|
RTS
|
||||||
|
|
53
uxn.c
53
uxn.c
|
@ -19,15 +19,15 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
#define STACK_DEPTH 256
|
#define STACK_DEPTH 256
|
||||||
|
|
||||||
typedef unsigned char Uint8;
|
typedef unsigned char Uint8;
|
||||||
|
typedef unsigned short Uint16;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Uint8 literal;
|
Uint8 literal, status;
|
||||||
Uint8 status, counter;
|
|
||||||
Uint8 memory[STACK_DEPTH];
|
|
||||||
Uint8 mptr, sptr, rsptr;
|
Uint8 mptr, sptr, rsptr;
|
||||||
|
Uint8 memory[STACK_DEPTH];
|
||||||
Uint8 stack[STACK_DEPTH];
|
Uint8 stack[STACK_DEPTH];
|
||||||
Uint8 rstack[STACK_DEPTH];
|
Uint8 rstack[STACK_DEPTH];
|
||||||
Uint8 address[STACK_DEPTH];
|
Uint16 counter;
|
||||||
} Computer;
|
} Computer;
|
||||||
|
|
||||||
Computer cpu;
|
Computer cpu;
|
||||||
|
@ -92,7 +92,7 @@ rspop(void)
|
||||||
|
|
||||||
void op_brk() { setflag(FLAG_HALT, 1); }
|
void op_brk() { setflag(FLAG_HALT, 1); }
|
||||||
void op_rts() { cpu.mptr = rspop(); }
|
void op_rts() { cpu.mptr = rspop(); }
|
||||||
void op_lit() { cpu.literal += 1; }
|
void op_lit() { cpu.literal += cpu.memory[cpu.mptr++]; }
|
||||||
void op_drp() { spop(); }
|
void op_drp() { spop(); }
|
||||||
void op_dup() { spush(cpu.stack[cpu.sptr - 1]); }
|
void op_dup() { spush(cpu.stack[cpu.sptr - 1]); }
|
||||||
void op_swp() { Uint8 b = spop(), a = spop(); spush(b); spush(a); }
|
void op_swp() { Uint8 b = spop(), a = spop(); spush(b); spush(a); }
|
||||||
|
@ -100,8 +100,8 @@ 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_rot() { Uint8 c = spop(),b = spop(),a = spop(); spush(b); spush(c); spush(a); }
|
||||||
void op_jmp() { cpu.mptr = spop(); }
|
void op_jmp() { cpu.mptr = spop(); }
|
||||||
void op_jsr() { rspush(cpu.mptr); cpu.mptr = spop(); }
|
void op_jsr() { rspush(cpu.mptr); cpu.mptr = spop(); }
|
||||||
void op_jmq() { if(getflag(FLAG_ZERO)){ op_jmp(); } setflag(FLAG_ZERO,0); }
|
void op_jmq() { Uint8 a = spop(); if(getflag(FLAG_ZERO)){ cpu.mptr = a; } setflag(FLAG_ZERO,0); }
|
||||||
void op_jsq() { if(getflag(FLAG_ZERO)){ op_jsr(); } setflag(FLAG_ZERO,0); }
|
void op_jsq() { Uint8 a = spop(); if(getflag(FLAG_ZERO)){ rspush(cpu.mptr); cpu.mptr = a; } setflag(FLAG_ZERO,0); }
|
||||||
void op_equ() { setflag(FLAG_ZERO, spop() == spop()); }
|
void op_equ() { setflag(FLAG_ZERO, spop() == spop()); }
|
||||||
void op_neq() { setflag(FLAG_ZERO, spop() != spop()); }
|
void op_neq() { setflag(FLAG_ZERO, spop() != spop()); }
|
||||||
void op_lth() { setflag(FLAG_ZERO, spop() < spop()); }
|
void op_lth() { setflag(FLAG_ZERO, spop() < spop()); }
|
||||||
|
@ -120,6 +120,13 @@ void (*ops[])(void) = {
|
||||||
op_jmp, op_jsr, op_jmq, op_jsq, op_equ, op_neq, op_gth, op_lth,
|
op_jmp, op_jsr, op_jmq, op_jsq, op_equ, op_neq, op_gth, op_lth,
|
||||||
op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div};
|
op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div};
|
||||||
|
|
||||||
|
Uint8 opr[][2] = {
|
||||||
|
{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
|
||||||
|
{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
|
||||||
|
{0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {0,0}, {0,0}, {0,0},
|
||||||
|
{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
|
||||||
|
};
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -148,38 +155,40 @@ load(FILE *f)
|
||||||
fread(cpu.memory, sizeof(cpu.memory), 1, f);
|
fread(cpu.memory, sizeof(cpu.memory), 1, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
eval()
|
eval()
|
||||||
{
|
{
|
||||||
Uint8 instr = cpu.memory[cpu.mptr++];
|
Uint8 instr = cpu.memory[cpu.mptr++];
|
||||||
if(cpu.literal > 0) {
|
if(cpu.literal > 0) {
|
||||||
spush(instr);
|
spush(instr);
|
||||||
cpu.literal--;
|
cpu.literal--;
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
if(instr < 24)
|
if(instr < 24) {
|
||||||
|
if(cpu.sptr < opr[instr][0])
|
||||||
|
return error("Stack underflow");
|
||||||
|
/* TODO stack overflow */
|
||||||
(*ops[instr])();
|
(*ops[instr])();
|
||||||
|
}
|
||||||
if(instr > 0x10)
|
if(instr > 0x10)
|
||||||
setflag(FLAG_ZERO, 0);
|
setflag(FLAG_ZERO, 0);
|
||||||
|
cpu.counter++;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run(void)
|
run(void)
|
||||||
{
|
{
|
||||||
int i;
|
while(!(cpu.status & FLAG_HALT) && eval(cpu))
|
||||||
while((cpu.status & FLAG_HALT) == 0)
|
;
|
||||||
eval(cpu);
|
|
||||||
/* debug */
|
/* debug */
|
||||||
printf("ended @ %d | ", cpu.counter);
|
printf("ended @ %d steps | ", cpu.counter);
|
||||||
printf("hf: %x zf: %x cf: %x tf: %x\n",
|
printf("hf: %x zf: %x cf: %x tf: %x\n",
|
||||||
getflag(FLAG_HALT),
|
getflag(FLAG_HALT) != 0,
|
||||||
getflag(FLAG_ZERO),
|
getflag(FLAG_ZERO) != 0,
|
||||||
getflag(FLAG_CARRY),
|
getflag(FLAG_CARRY) != 0,
|
||||||
getflag(FLAG_TRAPS));
|
getflag(FLAG_TRAPS) != 0);
|
||||||
printf("\n\n");
|
printf("\n");
|
||||||
for(i = 0; i < 4; i++)
|
|
||||||
printf("%d-", (cpu.status & (1 << i)) != 0);
|
|
||||||
printf("\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
102
uxnasm.c
102
uxnasm.c
|
@ -29,33 +29,14 @@ typedef struct {
|
||||||
int labelslen;
|
int labelslen;
|
||||||
Label labels[256];
|
Label labels[256];
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
char opcodes[][4] = {
|
char opcodes[][4] = {
|
||||||
"BRK",
|
"BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT",
|
||||||
"RTS",
|
"JMP", "JSR", "JMQ", "JSQ", "EQU", "NEQ", "LTH", "GTH",
|
||||||
"LIT",
|
"AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV"};
|
||||||
"POP",
|
|
||||||
"DUP",
|
/* clang-format on */
|
||||||
"SWP",
|
|
||||||
"OVR",
|
|
||||||
"ROT",
|
|
||||||
/* */
|
|
||||||
"JMP",
|
|
||||||
"JSR",
|
|
||||||
"JMQ",
|
|
||||||
"JSQ",
|
|
||||||
"EQU",
|
|
||||||
"NEQ",
|
|
||||||
"LTH",
|
|
||||||
"GTH",
|
|
||||||
"---",
|
|
||||||
"---",
|
|
||||||
"---",
|
|
||||||
"---",
|
|
||||||
"ADD",
|
|
||||||
"SUB",
|
|
||||||
"MUL",
|
|
||||||
"DIV"
|
|
||||||
/* */};
|
|
||||||
|
|
||||||
Program p;
|
Program p;
|
||||||
|
|
||||||
|
@ -81,6 +62,15 @@ scpy(char *src, char *dst, int len) /* string copy */
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
slen(char *s) /* string length */
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while(s[i] && s[++i])
|
||||||
|
;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
suca(char *s) /* string to uppercase */
|
suca(char *s) /* string to uppercase */
|
||||||
{
|
{
|
||||||
|
@ -120,11 +110,41 @@ shex(char *s) /* string to num */
|
||||||
#pragma mark - Parser
|
#pragma mark - Parser
|
||||||
|
|
||||||
void
|
void
|
||||||
addprg(Uint8 hex)
|
pushprg(Uint8 hex)
|
||||||
{
|
{
|
||||||
p.data[p.len++] = hex;
|
p.data[p.len++] = hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushlabel(Label *l)
|
||||||
|
{
|
||||||
|
pushprg(0x02);
|
||||||
|
pushprg(0x01);
|
||||||
|
pushprg(l->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushliteral(char *w)
|
||||||
|
{
|
||||||
|
int len = slen(w) / 2, value = shex(w);
|
||||||
|
pushprg(0x02);
|
||||||
|
pushprg(len);
|
||||||
|
switch(len) {
|
||||||
|
case 1:
|
||||||
|
pushprg(value);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pushprg(value >> 8);
|
||||||
|
pushprg(value);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
pushprg(value >> 16);
|
||||||
|
pushprg(value >> 8);
|
||||||
|
pushprg(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
addlabel(char *id, Uint8 addr)
|
addlabel(char *id, Uint8 addr)
|
||||||
{
|
{
|
||||||
|
@ -164,10 +184,9 @@ int
|
||||||
getlength(char *w)
|
getlength(char *w)
|
||||||
{
|
{
|
||||||
if(findop(w) || scmp(w, "BRK")) return 1;
|
if(findop(w) || scmp(w, "BRK")) return 1;
|
||||||
if(w[0] == '.') return 2;
|
if(w[0] == '.') return 3;
|
||||||
if(w[0] == ':') return 0;
|
if(w[0] == ':') return 0;
|
||||||
if(w[0] == '+') return 2;
|
if(sihx(w)) { return slen(w) / 2 + 2; }
|
||||||
if(w[0] == '-') return 2;
|
|
||||||
printf("Unknown length %s\n", w);
|
printf("Unknown length %s\n", w);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -209,21 +228,14 @@ pass2(FILE *f)
|
||||||
if(word[0] == ':') continue;
|
if(word[0] == ':') continue;
|
||||||
suca(word);
|
suca(word);
|
||||||
if(comment(word, &skip)) continue;
|
if(comment(word, &skip)) continue;
|
||||||
/* literals */
|
if((op = findop(word)) || scmp(word, "BRK"))
|
||||||
if(word[0] == '+' || word[0] == '-')
|
pushprg(op);
|
||||||
addprg(0x02);
|
else if((l = findlabel(word + 1)))
|
||||||
if(word[0] == '+')
|
pushlabel(l);
|
||||||
addprg(shex(word + 1));
|
else if(sihx(word))
|
||||||
else if(word[0] == '-')
|
pushliteral(word);
|
||||||
addprg((Uint8)(-1 * shex(word + 1)));
|
else
|
||||||
/* opcodes */
|
printf("Unknown label: %s\n", word);
|
||||||
else if((op = findop(word)) || scmp(word, "BRK"))
|
|
||||||
addprg(op);
|
|
||||||
else if((l = findlabel(word + 1))) {
|
|
||||||
addprg(0x02);
|
|
||||||
addprg(l->addr);
|
|
||||||
} else
|
|
||||||
printf("unknown: %s\n", word);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue