Starting 16bits mode
This commit is contained in:
parent
521be808a0
commit
6ac543f312
24
README.md
24
README.md
|
@ -10,13 +10,27 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
|
|
||||||
## Assembly Syntax
|
## Assembly Syntax
|
||||||
|
|
||||||
- `;variable`, a named address(zero-page)
|
### Write
|
||||||
- `:label`, a named address
|
|
||||||
- `.pointer`, a pointer to a label
|
- `;variable`, set a name to address on the zero-page
|
||||||
- `@0010`, a position in the program
|
- `:label`, set a name to an address
|
||||||
|
|
||||||
|
### Read
|
||||||
|
|
||||||
|
- `,literal`, get a literal pointer
|
||||||
|
- `.pointer`, get a raw pointer
|
||||||
|
|
||||||
|
### Special
|
||||||
|
|
||||||
|
- `@0010`, move to position in the program
|
||||||
|
- `( comment )`
|
||||||
|
|
||||||
```
|
```
|
||||||
< conditionals >
|
( comment )
|
||||||
|
|
||||||
|
;variable1
|
||||||
|
;variable2
|
||||||
|
;variable3
|
||||||
|
|
||||||
.there ( 0a 05 GTH ) JMC
|
.there ( 0a 05 GTH ) JMC
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
< conditionals >
|
( comment )
|
||||||
|
|
||||||
.there ( 0a 05 GTH ) JMC
|
,abcd ,ef STR
|
||||||
|
|
||||||
:here
|
|
||||||
< when not equal >
|
|
||||||
ee
|
|
||||||
BRK
|
|
||||||
|
|
||||||
:there
|
|
||||||
< when is equal >
|
|
||||||
ff
|
|
||||||
BRK
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
< vectors >
|
||||||
|
|
||||||
|
:RESET BRK
|
||||||
|
:FRAME BRK
|
||||||
|
:ERROR BRK
|
||||||
|
|
||||||
|
@FFFA < vectors >
|
||||||
|
|
||||||
|
.RESET
|
||||||
|
.FRAME
|
||||||
|
.ERROR
|
23
uxn.c
23
uxn.c
|
@ -74,6 +74,13 @@ echo(Stack *s, Uint8 len, char *name)
|
||||||
|
|
||||||
void wspush(Uint8 v) { cpu.wst.dat[cpu.wst.ptr++] = v; }
|
void wspush(Uint8 v) { cpu.wst.dat[cpu.wst.ptr++] = v; }
|
||||||
Uint8 wspop(void) { return cpu.wst.dat[--cpu.wst.ptr]; }
|
Uint8 wspop(void) { return cpu.wst.dat[--cpu.wst.ptr]; }
|
||||||
|
Uint16 wspop16(void) {
|
||||||
|
|
||||||
|
Uint8 a = cpu.wst.dat[--cpu.wst.ptr];
|
||||||
|
Uint8 b = cpu.wst.dat[--cpu.wst.ptr];
|
||||||
|
return a + (b << 8);
|
||||||
|
|
||||||
|
}
|
||||||
Uint8 wspeek(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; }
|
Uint8 wspeek(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; }
|
||||||
void rspush(Uint8 v) { cpu.rst.dat[cpu.rst.ptr++] = v; }
|
void rspush(Uint8 v) { cpu.rst.dat[cpu.rst.ptr++] = v; }
|
||||||
Uint8 rspop(void) { return cpu.rst.dat[--cpu.rst.ptr]; }
|
Uint8 rspop(void) { return cpu.rst.dat[--cpu.rst.ptr]; }
|
||||||
|
@ -102,17 +109,27 @@ void op_add() { wspush(wspop() + wspop()); }
|
||||||
void op_sub() { wspush(wspop() - wspop()); }
|
void op_sub() { wspush(wspop() - wspop()); }
|
||||||
void op_mul() { wspush(wspop() * wspop()); }
|
void op_mul() { wspush(wspop() * wspop()); }
|
||||||
void op_div() { wspush(wspop() / wspop()); }
|
void op_div() { wspush(wspop() / wspop()); }
|
||||||
|
void op_ldr() { }
|
||||||
|
void op_str() {
|
||||||
|
|
||||||
|
Uint8 b = wspop();
|
||||||
|
Uint16 addr = wspop16();
|
||||||
|
printf("store: %02x @ %04x\n", b, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void (*ops[])(void) = {
|
void (*ops[])(void) = {
|
||||||
op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot,
|
op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot,
|
||||||
op_jmu, op_jsu, op_jmc, op_jsc, op_equ, op_neq, op_gth, op_lth,
|
op_jmu, op_jsu, op_jmc, op_jsc, 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,
|
||||||
|
op_ldr, op_str, op_brk, op_brk, op_brk, op_brk, op_brk, op_brk
|
||||||
|
};
|
||||||
|
|
||||||
Uint8 opr[][2] = {
|
Uint8 opr[][2] = {
|
||||||
{0,0}, {0,0}, {0,0}, {1,0}, {0,1}, {1,1}, {0,1}, {3,3},
|
{0,0}, {0,0}, {0,0}, {1,0}, {0,1}, {1,1}, {0,1}, {3,3},
|
||||||
{2,0}, {2,0}, {2,0}, {2,0}, {2,1}, {2,1}, {2,1}, {2,1},
|
{2,0}, {2,0}, {2,0}, {2,0}, {2,1}, {2,1}, {2,1}, {2,1},
|
||||||
{1,0}, {1,0}, {1,0}, {1,0}, {2,1}, {0,0}, {0,0}, {0,0},
|
{1,0}, {1,0}, {1,0}, {1,0}, {2,1}, {0,0}, {0,0}, {0,0},
|
||||||
{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}
|
{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1},
|
||||||
|
{3,1}, {3,1}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
@ -155,7 +172,7 @@ eval()
|
||||||
cpu.literal--;
|
cpu.literal--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(instr < 24) {
|
if(instr < 32) {
|
||||||
if(cpu.wst.ptr < opr[instr][0])
|
if(cpu.wst.ptr < opr[instr][0])
|
||||||
return error("Stack underflow");
|
return error("Stack underflow");
|
||||||
/* TODO stack overflow */
|
/* TODO stack overflow */
|
||||||
|
|
233
uxnasm.c
233
uxnasm.c
|
@ -11,19 +11,17 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PRGLEN 256
|
|
||||||
#define LABELIDLEN 32
|
|
||||||
|
|
||||||
typedef unsigned char Uint8;
|
typedef unsigned char Uint8;
|
||||||
|
typedef unsigned short Uint16;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int ptr;
|
int ptr;
|
||||||
Uint8 data[PRGLEN];
|
Uint8 data[65536];
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Uint8 addr;
|
Uint16 addr;
|
||||||
char name[LABELIDLEN];
|
char name[64];
|
||||||
} Label;
|
} Label;
|
||||||
|
|
||||||
int labelslen;
|
int labelslen;
|
||||||
|
@ -34,7 +32,9 @@ Label labels[256];
|
||||||
char opcodes[][4] = {
|
char opcodes[][4] = {
|
||||||
"BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT",
|
"BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT",
|
||||||
"JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH",
|
"JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH",
|
||||||
"AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV"};
|
"AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV",
|
||||||
|
"LDR", "STR", "---", "---", "---", "---", "---", "---"
|
||||||
|
};
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ suca(char *s) /* string to uppercase */
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sihx(char *s)
|
sihx(char *s) /* string is hexadecimal */
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char c;
|
char c;
|
||||||
|
@ -107,59 +107,68 @@ shex(char *s) /* string to num */
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ismarker(char *w)
|
||||||
|
{
|
||||||
|
return w[0] == '[' || w[0] == ']' || w[0] == '{' || w[0] == '}';
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iscomment(char *w, int *skip)
|
||||||
|
{
|
||||||
|
if(w[0] == ')') {
|
||||||
|
*skip = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(w[0] == '(') *skip = 1;
|
||||||
|
if(*skip) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - I/O
|
||||||
|
|
||||||
|
void
|
||||||
|
pushbyte(Uint8 b, int lit)
|
||||||
|
{
|
||||||
|
if(lit) {
|
||||||
|
pushbyte(0x02, 0);
|
||||||
|
pushbyte(0x01, 0);
|
||||||
|
}
|
||||||
|
p.data[p.ptr++] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pushshort(Uint16 s, int lit)
|
||||||
|
{
|
||||||
|
if(lit) {
|
||||||
|
pushbyte(0x02, 0);
|
||||||
|
pushbyte(0x02, 0);
|
||||||
|
}
|
||||||
|
pushbyte((s >> 8) & 0xff, 0);
|
||||||
|
pushbyte(s & 0xff, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Parser
|
#pragma mark - Parser
|
||||||
|
|
||||||
void
|
Uint8
|
||||||
pushprg(Uint8 hex)
|
findop(char *s)
|
||||||
{
|
{
|
||||||
p.data[p.ptr++] = hex;
|
int i;
|
||||||
|
for(i = 0; i < 32; ++i)
|
||||||
|
if(scmp(opcodes[i], s))
|
||||||
|
return i;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pushlabel(Label *l)
|
makelabel(char *id, Uint8 addr)
|
||||||
{
|
|
||||||
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
|
|
||||||
addlabel(char *id, Uint8 addr)
|
|
||||||
{
|
{
|
||||||
Label *l = &labels[labelslen++];
|
Label *l = &labels[labelslen++];
|
||||||
scpy(suca(id), l->name, LABELIDLEN);
|
scpy(suca(id), l->name, 64);
|
||||||
l->addr = addr;
|
l->addr = addr;
|
||||||
printf("New label: %s[0x%02x]\n", l->name, l->addr);
|
printf("New label: %s[0x%02x]\n", l->name, l->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
addconst(char *id, Uint8 value)
|
|
||||||
{
|
|
||||||
printf("New const: %s[%02x]\n", id, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Label *
|
Label *
|
||||||
findlabel(char *s)
|
findlabel(char *s)
|
||||||
{
|
{
|
||||||
|
@ -170,94 +179,72 @@ findlabel(char *s)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8
|
#pragma mark - Parser
|
||||||
findop(char *s)
|
|
||||||
|
int
|
||||||
|
error(char *name, char *id)
|
||||||
{
|
{
|
||||||
int i;
|
printf("Error: %s - %s\n", name, id);
|
||||||
for(i = 0; i < 24; ++i)
|
|
||||||
if(scmp(opcodes[i], s))
|
|
||||||
return i;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ismarker(char *w)
|
|
||||||
{
|
|
||||||
return w[0] == '(' || w[0] == ')' || w[0] == '{' || w[0] == '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
iscomment(char *w, int *skip)
|
|
||||||
{
|
|
||||||
if(w[0] == '>') {
|
|
||||||
*skip = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(w[0] == '<') *skip = 1;
|
|
||||||
if(*skip) return 1;
|
|
||||||
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 0;
|
|
||||||
if(w[0] == '@') return 0;
|
|
||||||
if(sihx(w)) { return slen(w) / 2 + 2; }
|
|
||||||
if(ismarker(w)) return 0;
|
|
||||||
printf("Unknown length %s\n", w);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pass1(FILE *f)
|
pass1(FILE *f)
|
||||||
{
|
{
|
||||||
int skip = 0;
|
int skip = 0, addr = 0, vars = 0;
|
||||||
int addr = 0;
|
char w[64];
|
||||||
int vars = 0;
|
while(fscanf(f, "%s", w) == 1) {
|
||||||
char word[64];
|
if(iscomment(w, &skip)) continue;
|
||||||
while(fscanf(f, "%s", word) == 1) {
|
if(w[0] == ':') makelabel(w + 1, addr);
|
||||||
if(iscomment(word, &skip)) continue;
|
if(w[0] == ';') makelabel(w + 1, vars++);
|
||||||
if(word[0] == ':') addlabel(word + 1, addr);
|
/* move addr ptr */
|
||||||
if(word[0] == ';') addlabel(word + 1, vars++);
|
if(findop(w) || scmp(w, "BRK"))
|
||||||
addr += getlength(word);
|
addr += 1;
|
||||||
|
else if(w[0] == '@')
|
||||||
|
addr += 0;
|
||||||
|
else if(w[0] == ':')
|
||||||
|
addr += 0;
|
||||||
|
else if(w[0] == ';')
|
||||||
|
addr += 0;
|
||||||
|
else if(w[0] == '.')
|
||||||
|
addr += 2;
|
||||||
|
else if(w[0] == ',')
|
||||||
|
addr += 4;
|
||||||
|
else if(ismarker(w))
|
||||||
|
addr += 0;
|
||||||
|
else
|
||||||
|
return error("Unknown label(pass1)", w);
|
||||||
}
|
}
|
||||||
rewind(f);
|
rewind(f);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
pass2(FILE *f)
|
pass2(FILE *f)
|
||||||
{
|
{
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
char word[64];
|
char w[64];
|
||||||
while(fscanf(f, "%s", word) == 1) {
|
while(fscanf(f, "%s", w) == 1) {
|
||||||
Uint8 op = 0;
|
Uint8 op = 0;
|
||||||
Label *l;
|
Label *l;
|
||||||
if(word[0] == ':') continue;
|
if(w[0] == ':') continue;
|
||||||
if(word[0] == ';') continue;
|
if(w[0] == ';') continue;
|
||||||
suca(word);
|
suca(w);
|
||||||
if(iscomment(word, &skip) || ismarker(word)) continue;
|
if(iscomment(w, &skip) || ismarker(w)) continue;
|
||||||
if(word[0] == '@')
|
if(w[0] == '@')
|
||||||
p.ptr = shex(word + 1);
|
p.ptr = shex(w + 1);
|
||||||
else if((op = findop(word)) || scmp(word, "BRK"))
|
else if((op = findop(w)) || scmp(w, "BRK"))
|
||||||
pushprg(op);
|
pushbyte(op, 0);
|
||||||
else if((l = findlabel(word + 1)))
|
else if((l = findlabel(w + 1)))
|
||||||
pushlabel(l);
|
pushshort(l->addr, w[0] == ',');
|
||||||
else if(sihx(word))
|
else if(sihx(w + 1) && slen(w + 1) == 2)
|
||||||
pushliteral(word);
|
pushbyte(shex(w + 1), w[0] == ',');
|
||||||
|
else if(sihx(w + 1) && slen(w + 1) == 4)
|
||||||
|
pushshort(shex(w + 1), w[0] == ',');
|
||||||
else
|
else
|
||||||
printf("Unknown label: %s\n", word);
|
return error("Unknown label(pass2)", w);
|
||||||
}
|
}
|
||||||
}
|
return 1;
|
||||||
|
|
||||||
int
|
|
||||||
error(char *name)
|
|
||||||
{
|
|
||||||
printf("Error: %s\n", name);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -265,11 +252,11 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
if(argc < 3)
|
if(argc < 3)
|
||||||
return error("No input.");
|
return error("Input", "Missing");
|
||||||
if(!(f = fopen(argv[1], "r")))
|
if(!(f = fopen(argv[1], "r")))
|
||||||
return error("Missing input.");
|
return error("Open", "Failed");
|
||||||
pass1(f);
|
if(!pass1(f) || !pass2(f))
|
||||||
pass2(f);
|
return error("Assembly", "Failed");
|
||||||
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb"));
|
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb"));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue