Hello world with strlen
This commit is contained in:
parent
60cbe91cde
commit
5d2025d7e8
|
@ -27,6 +27,10 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
- `|0010`, move to position in the program
|
- `|0010`, move to position in the program
|
||||||
- `"hello`, push literal bytes for word "hello"
|
- `"hello`, push literal bytes for word "hello"
|
||||||
|
|
||||||
|
### Operator modes
|
||||||
|
|
||||||
|
- `,1234 ,0001 ADD^`, 16-bits operators have the short flag `^`.
|
||||||
|
|
||||||
```
|
```
|
||||||
( hello world )
|
( hello world )
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,19 @@
|
||||||
|
|
||||||
|0100 @RESET
|
|0100 @RESET
|
||||||
|
|
||||||
"hello
|
@word1 "hello_word ( len: 0x0b )
|
||||||
|
|
||||||
@loop
|
@loop
|
||||||
,dev1w STR
|
,dev1w STR ( write to stdout )
|
||||||
,incr JSU ( call incr )
|
,incr JSU ( increment itr )
|
||||||
,05 NEQ ,loop ROT JSC
|
,word1 ,strlen JSU ( get strlen )
|
||||||
|
NEQ ,loop ROT JSC ( loop != strlen )
|
||||||
|
|
||||||
BRK ( RESET )
|
BRK
|
||||||
|
|
||||||
|
@strlen
|
||||||
|
,0001 ADD^ PEK
|
||||||
|
RTS
|
||||||
|
|
||||||
@incr
|
@incr
|
||||||
,iterator LDR
|
,iterator LDR
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
( hello world )
|
||||||
|
|
||||||
|
;iterator
|
||||||
|
:dev1r FFF0
|
||||||
|
:dev1w FFF1
|
||||||
|
|
||||||
|
|0100 @RESET
|
||||||
|
|
||||||
|
@word1 "hello_word ( len: 0x0b )
|
||||||
|
|
||||||
|
@loop
|
||||||
|
,dev1w STR ( write to stdout )
|
||||||
|
,incr JSU ( increment itr )
|
||||||
|
,word1 ,strlen JSU ( get strlen )
|
||||||
|
NEQ ,loop ROT JSC ( loop != strlen )
|
||||||
|
|
||||||
|
BRK
|
||||||
|
|
||||||
|
@strlen
|
||||||
|
,0001 ADD^ PEK
|
||||||
|
RTS
|
||||||
|
|
||||||
|
@incr
|
||||||
|
,iterator LDR
|
||||||
|
,01 ADD
|
||||||
|
,iterator STR
|
||||||
|
,iterator LDR
|
||||||
|
RTS
|
||||||
|
|
||||||
|
|c000 @FRAME BRK
|
||||||
|
|d000 @ERROR BRK
|
||||||
|
|FFFA .RESET .FRAME .ERROR
|
81
uxn.c
81
uxn.c
|
@ -12,7 +12,7 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FLAG_HALT 0x01
|
#define FLAG_HALT 0x01
|
||||||
#define FLAG_ZERO 0x02
|
#define FLAG_SHORT 0x02
|
||||||
#define FLAG_CARRY 0x04
|
#define FLAG_CARRY 0x04
|
||||||
#define FLAG_TRAPS 0x08
|
#define FLAG_TRAPS 0x08
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ Uint8 rampeek8(Uint16 s) { return cpu.ram.dat[s] & 0xff; }
|
||||||
Uint8 mempeek8(Uint16 s) { return cpu.rom.dat[s]; }
|
Uint8 mempeek8(Uint16 s) { return cpu.rom.dat[s]; }
|
||||||
Uint16 mempeek16(Uint16 s) { return (cpu.rom.dat[s] << 8) + (cpu.rom.dat[s+1] & 0xff); }
|
Uint16 mempeek16(Uint16 s) { return (cpu.rom.dat[s] << 8) + (cpu.rom.dat[s+1] & 0xff); }
|
||||||
void wspush8(Uint8 b) { cpu.wst.dat[cpu.wst.ptr++] = b; }
|
void wspush8(Uint8 b) { cpu.wst.dat[cpu.wst.ptr++] = b; }
|
||||||
|
void wspush16(Uint16 s) { wspush8(s >> 8); wspush8(s & 0xff); }
|
||||||
Uint8 wspop8(void) { return cpu.wst.dat[--cpu.wst.ptr]; }
|
Uint8 wspop8(void) { return cpu.wst.dat[--cpu.wst.ptr]; }
|
||||||
Uint16 wspop16(void) { return wspop8() + (wspop8() << 8); }
|
Uint16 wspop16(void) { return wspop8() + (wspop8() << 8); }
|
||||||
Uint8 wspeek8(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; }
|
Uint8 wspeek8(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; }
|
||||||
|
@ -116,24 +117,31 @@ void op_jmc() { if(wspop8()) op_jmu(); }
|
||||||
void op_jsc() { if(wspop8()) op_jsu(); }
|
void op_jsc() { if(wspop8()) op_jsu(); }
|
||||||
void op_equ() { wspush8(wspop8() == wspop8()); }
|
void op_equ() { wspush8(wspop8() == wspop8()); }
|
||||||
void op_neq() { wspush8(wspop8() != wspop8()); }
|
void op_neq() { wspush8(wspop8() != wspop8()); }
|
||||||
void op_gth() { wspush8(wspop8() < wspop8()); }
|
void op_gth() { wspush8(wspop8() < wspop8()); }
|
||||||
void op_lth() { wspush8(wspop8() > wspop8()); }
|
void op_lth() { wspush8(wspop8() > wspop8()); }
|
||||||
void op_and() { wspush8(wspop8() & wspop8()); }
|
void op_and() { wspush8(wspop8() & wspop8()); }
|
||||||
void op_ora() { wspush8(wspop8() | wspop8()); }
|
void op_ora() { wspush8(wspop8() | wspop8()); }
|
||||||
void op_rol() { wspush8(wspop8() << 1); }
|
void op_rol() { wspush8(wspop8() << 1); }
|
||||||
void op_ror() { wspush8(wspop8() >> 1); }
|
void op_ror() { wspush8(wspop8() >> 1); }
|
||||||
void op_add() { wspush8(wspop8() + wspop8()); }
|
void op_add() {
|
||||||
|
if(getflag(FLAG_SHORT))
|
||||||
|
wspush16(wspop16() + wspop16());
|
||||||
|
else
|
||||||
|
wspush8(wspop8() + wspop8());
|
||||||
|
}
|
||||||
void op_sub() { wspush8(wspop8() - wspop8()); }
|
void op_sub() { wspush8(wspop8() - wspop8()); }
|
||||||
void op_mul() { wspush8(wspop8() * wspop8()); }
|
void op_mul() { wspush8(wspop8() * wspop8()); }
|
||||||
void op_div() { wspush8(wspop8() / wspop8()); }
|
void op_div() { wspush8(wspop8() / wspop8()); }
|
||||||
void op_ldr() { wspush8(cpu.ram.dat[wspop16()]); }
|
void op_ldr() { wspush8(cpu.ram.dat[wspop16()]); }
|
||||||
void op_str() { cpu.ram.dat[wspop16()] = wspop8(); }
|
void op_str() { cpu.ram.dat[wspop16()] = wspop8(); }
|
||||||
|
void op_pek() { wspush8(cpu.rom.dat[wspop16()]); }
|
||||||
|
void op_pok() { printf("TODO:\n");}
|
||||||
|
|
||||||
void (*ops[])(void) = {
|
void (*ops[])() = {
|
||||||
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
|
op_ldr, op_str, op_pek, op_pok, op_brk, op_brk, op_brk, op_brk
|
||||||
};
|
};
|
||||||
|
|
||||||
Uint8 opr[][2] = {
|
Uint8 opr[][2] = {
|
||||||
|
@ -162,9 +170,9 @@ reset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
error(char *name)
|
error(char *name, int id)
|
||||||
{
|
{
|
||||||
printf("Error: %s, at 0x%04x\n", name, cpu.counter);
|
printf("Error: %s[%04x], at 0x%04x\n", name, id, cpu.counter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,31 +185,48 @@ device1(Uint8 *read, Uint8 *write)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
opc(Uint8 src, Uint8 *op, Uint8 *mode)
|
||||||
|
{
|
||||||
|
*op = src;
|
||||||
|
*op &= ~(1 << 5);
|
||||||
|
*op &= ~(1 << 6);
|
||||||
|
*op &= ~(1 << 7);
|
||||||
|
*mode = src;
|
||||||
|
*mode &= ~(1 << 0);
|
||||||
|
*mode &= ~(1 << 1);
|
||||||
|
*mode &= ~(1 << 2);
|
||||||
|
*mode &= ~(1 << 3);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
eval(void)
|
eval(void)
|
||||||
{
|
{
|
||||||
Uint8 instr = cpu.rom.dat[cpu.rom.ptr++];
|
Uint8 instr = cpu.rom.dat[cpu.rom.ptr++];
|
||||||
|
Uint8 op, opmode;
|
||||||
|
/* when literal */
|
||||||
if(cpu.literal > 0) {
|
if(cpu.literal > 0) {
|
||||||
wspush8(instr);
|
wspush8(instr);
|
||||||
cpu.literal--;
|
cpu.literal--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(instr < 32) {
|
/* when opcode */
|
||||||
if(cpu.wst.ptr < opr[instr][0])
|
opc(instr, &op, &opmode);
|
||||||
return error("Stack underflow");
|
setflag(FLAG_SHORT, (instr >> 5) & 1);
|
||||||
/* TODO stack overflow */
|
if((instr >> 6) & 1)
|
||||||
(*ops[instr])();
|
printf("Unused flag: %02x\n", instr);
|
||||||
}
|
if((instr >> 7) & 1)
|
||||||
if(instr > 0x10)
|
printf("Unused flag: %02x\n", instr);
|
||||||
setflag(FLAG_ZERO, 0);
|
/* TODO: setflag(FLAG_B, (instr >> 6) & 1); */
|
||||||
if(cpu.counter == 128) {
|
/* TODO: setflag(FLAG_C, (instr >> 7) & 1); */
|
||||||
return error("Reached bounds");
|
if(cpu.wst.ptr < opr[op][0])
|
||||||
}
|
return error("Stack underflow", op);
|
||||||
|
(*ops[op])();
|
||||||
cpu.counter++;
|
cpu.counter++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
start(FILE *f)
|
start(FILE *f)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -216,6 +241,8 @@ start(FILE *f)
|
||||||
/* experimental */
|
/* experimental */
|
||||||
if(cpu.ram.dat[0xfff1])
|
if(cpu.ram.dat[0xfff1])
|
||||||
device1(&cpu.ram.dat[0xfff0], &cpu.ram.dat[0xfff1]);
|
device1(&cpu.ram.dat[0xfff0], &cpu.ram.dat[0xfff1]);
|
||||||
|
if(cpu.counter > 256)
|
||||||
|
return error("Reached bounds", cpu.counter);
|
||||||
}
|
}
|
||||||
/*eval frame */
|
/*eval frame */
|
||||||
printf("\nPhase: frame\n");
|
printf("\nPhase: frame\n");
|
||||||
|
@ -227,10 +254,11 @@ start(FILE *f)
|
||||||
printf("ended @ %d steps | ", 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) != 0,
|
getflag(FLAG_HALT) != 0,
|
||||||
getflag(FLAG_ZERO) != 0,
|
getflag(FLAG_SHORT) != 0,
|
||||||
getflag(FLAG_CARRY) != 0,
|
getflag(FLAG_CARRY) != 0,
|
||||||
getflag(FLAG_TRAPS) != 0);
|
getflag(FLAG_TRAPS) != 0);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -238,10 +266,11 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
if(argc < 2)
|
if(argc < 2)
|
||||||
return error("No input.");
|
return error("No input.", 0);
|
||||||
if(!(f = fopen(argv[1], "rb")))
|
if(!(f = fopen(argv[1], "rb")))
|
||||||
return error("Missing input.");
|
return error("Missing input.", 0);
|
||||||
start(f);
|
if(!start(f))
|
||||||
|
return error("Program error", 0);
|
||||||
/* print result */
|
/* print result */
|
||||||
echos(&cpu.wst, 0x40, "stack");
|
echos(&cpu.wst, 0x40, "stack");
|
||||||
echom(&cpu.ram, 0x40, "ram");
|
echom(&cpu.ram, 0x40, "ram");
|
||||||
|
|
41
uxnasm.c
41
uxnasm.c
|
@ -29,11 +29,11 @@ Label labels[256];
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
char opcodes[][4] = {
|
char ops[][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", "---", "---", "---", "---", "---", "---"
|
"LDR", "STR", "PEK", "POK", "---", "---", "---", "---"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
@ -162,6 +162,27 @@ findlabel(char *s)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint8
|
||||||
|
findop(char *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 32; ++i) {
|
||||||
|
int m = 0;
|
||||||
|
if(ops[i][0] != s[0]) continue;
|
||||||
|
if(ops[i][1] != s[1]) continue;
|
||||||
|
if(ops[i][2] != s[2]) continue;
|
||||||
|
while(s[3 + m]) {
|
||||||
|
char c = s[3 + m];
|
||||||
|
if(c == '^') i |= (1 << 5); /* mode: 16 bits */
|
||||||
|
if(c == '&') i |= (1 << 6); /* mode: unused */
|
||||||
|
if(c == '~') i |= (1 << 7); /* mode: unused */
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Parser
|
#pragma mark - Parser
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -171,16 +192,6 @@ error(char *name, char *id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8
|
|
||||||
findop(char *s)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < 32; ++i)
|
|
||||||
if(scmp(opcodes[i], s))
|
|
||||||
return i;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
makelabel(char *id, Uint16 addr)
|
makelabel(char *id, Uint16 addr)
|
||||||
{
|
{
|
||||||
|
@ -210,7 +221,6 @@ pass1(FILE *f)
|
||||||
char w[64];
|
char w[64];
|
||||||
while(fscanf(f, "%s", w) == 1) {
|
while(fscanf(f, "%s", w) == 1) {
|
||||||
if(iscomment(w, &skip)) continue;
|
if(iscomment(w, &skip)) continue;
|
||||||
suca(w);
|
|
||||||
if(w[0] == '@' && !makelabel(w + 1, addr))
|
if(w[0] == '@' && !makelabel(w + 1, addr))
|
||||||
return error("Pass1 failed", w);
|
return error("Pass1 failed", w);
|
||||||
if(w[0] == ';' && !makelabel(w + 1, vars++))
|
if(w[0] == ';' && !makelabel(w + 1, vars++))
|
||||||
|
@ -253,7 +263,6 @@ pass2(FILE *f)
|
||||||
Label *l;
|
Label *l;
|
||||||
if(w[0] == '@') continue;
|
if(w[0] == '@') continue;
|
||||||
if(w[0] == ';') continue;
|
if(w[0] == ';') continue;
|
||||||
suca(w);
|
|
||||||
if(iscomment(w, &skip)) continue;
|
if(iscomment(w, &skip)) continue;
|
||||||
if(w[0] == '|')
|
if(w[0] == '|')
|
||||||
p.ptr = shex(w + 1);
|
p.ptr = shex(w + 1);
|
||||||
|
@ -261,10 +270,10 @@ pass2(FILE *f)
|
||||||
fscanf(f, "%s", w);
|
fscanf(f, "%s", w);
|
||||||
else if(w[0] == '"')
|
else if(w[0] == '"')
|
||||||
pushword(w + 1);
|
pushword(w + 1);
|
||||||
else if((op = findop(w)) || scmp(w, "BRK"))
|
|
||||||
pushbyte(op, 0);
|
|
||||||
else if((l = findlabel(w + 1)))
|
else if((l = findlabel(w + 1)))
|
||||||
pushshort(l->addr, w[0] == ',');
|
pushshort(l->addr, w[0] == ',');
|
||||||
|
else if((op = findop(w)) || scmp(w, "BRK"))
|
||||||
|
pushbyte(op, 0);
|
||||||
else if(sihx(w + 1) && slen(w + 1) == 2)
|
else if(sihx(w + 1) && slen(w + 1) == 2)
|
||||||
pushbyte(shex(w + 1), w[0] == ',');
|
pushbyte(shex(w + 1), w[0] == ',');
|
||||||
else if(sihx(w + 1) && slen(w + 1) == 4)
|
else if(sihx(w + 1) && slen(w + 1) == 4)
|
||||||
|
|
Loading…
Reference in New Issue