0
0
Fork 0
mirror of https://git.sr.ht/~rabbits/uxn synced 2024-11-21 21:35:11 +00:00
This commit is contained in:
neauoire 2021-01-30 14:25:48 -08:00
parent 099d1f0845
commit ba2e7aefa1
5 changed files with 185 additions and 93 deletions

View file

@ -1,11 +1,11 @@
AlignAfterOpenBracket: DontAlign
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AllowShortBlocksOnASingleLine: Empty
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: TopLevel
BinPackArguments: false
BinPackParameters: false

View file

@ -11,26 +11,23 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
## Assembly Syntax
```
: starting a definition
& obtaining pointers
( stack comments
` inlining bytecodes
' strings
# numbers
$ characters
~ vector
[ 12 34 ] real values
< 12 34 > relative values
( 12 34 ) deadzone
```
< comment >
```
;add-two JSR
+01 < literal >
BRK
[ 01 02 03 04 ] < block of literals >
:add-two
[ 2 ] ADD RTS
$01 < pointer8 >
{ 01 02 03 04 } < block of pointer8 >
~ff0f < pointer16 >
( ff00 ff01 ff02 ff03 ) < block of pointer16 >
=const +ff
:label ADD RTS
```
## Design
@ -57,3 +54,12 @@ BRK
### Emulator
- SDL Layer
## Refs
https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c
http://www.w3group.de/stable_glossar.html
http://www.emulator101.com/6502-addressing-modes.html
http://forth.works/8f0c04f616b6c34496eb2141785b4454
https://justinmeiners.github.io/lc3-vm/

View file

@ -1 +1,5 @@
{ 25 26 27 28 } SWP POP DUP BRK
< comment >
[3 1 2 3 ] pop dup swp ovr rot
brk

98
uxn.c
View file

@ -29,19 +29,23 @@ typedef struct {
Uint8 address[STACK_DEPTH];
} Computer;
Computer cpu;
#pragma mark - Helpers
void
setflag(Computer *cpu, char flag, int b)
setflag(char flag, int b)
{
if(b)
cpu->status |= flag;
cpu.status |= flag;
else
cpu->status &= (~flag);
cpu.status &= (~flag);
}
int
getflag(Computer *cpu, char flag)
getflag(char flag)
{
return cpu->status & flag;
return cpu.status & flag;
}
void
@ -57,30 +61,31 @@ echo(Uint8 *s, Uint8 len, char *name)
printf("\n\n");
}
#pragma mark - Operations
void
op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
{
s[*ptr] = v;
(*ptr) += 1;
s[(*ptr)++] = v;
}
void
Uint8
op_pop(Uint8 *s, Uint8 *ptr)
{
s[*ptr--] = 0x00;
return s[--*ptr];
}
void
reset(Computer *cpu)
reset(void)
{
int i;
cpu->status = 0x00;
cpu->counter = 0x00;
cpu->mptr = 0x00;
cpu->sptr = 0x00;
cpu->literal = 0x00;
cpu.status = 0x00;
cpu.counter = 0x00;
cpu.mptr = 0x00;
cpu.sptr = 0x00;
cpu.literal = 0x00;
for(i = 0; i < 256; i++)
cpu->stack[i] = 0x00;
cpu.stack[i] = 0x00;
}
int
@ -91,39 +96,63 @@ error(char *name)
}
void
load(Computer *cpu, FILE *f)
load(FILE *f)
{
fread(cpu->memory, sizeof(cpu->memory), 1, f);
fread(cpu.memory, sizeof(cpu.memory), 1, f);
}
void
eval(Computer *cpu)
eval()
{
Uint8 instr = cpu->memory[cpu->mptr++];
if(cpu->literal > 0) {
printf("push: %02x[%d](%d)\n", instr, cpu->literal, cpu->sptr);
op_push(cpu->stack, &cpu->sptr, instr);
cpu->literal--;
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);
cpu.literal--;
return;
}
switch(instr) {
case 0x0: setflag(cpu, FLAG_HALT, 1); break;
case 0x1: cpu->literal += 4; break;
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);
}
}
void
run(Computer *cpu)
run(void)
{
int i;
while((cpu->status & FLAG_HALT) == 0)
while((cpu.status & FLAG_HALT) == 0)
eval(cpu);
/* debug */
printf("ended @ %d | ", cpu->counter);
printf("ended @ %d | ", cpu.counter);
for(i = 0; i < 4; i++)
printf("%d-", (cpu->status & (1 << i)) != 0);
printf("%d-", (cpu.status & (1 << i)) != 0);
printf("\n\n");
}
@ -131,14 +160,13 @@ int
main(int argc, char *argv[])
{
FILE *f;
Computer cpu;
if(argc < 2)
return error("No input.");
if(!(f = fopen(argv[1], "rb")))
return error("Missing input.");
reset(&cpu);
load(&cpu, f);
run(&cpu);
reset();
load(f);
run();
/* print result */
echo(cpu.stack, 0x40, "stack");
echo(cpu.memory, 0x40, "memory");

128
uxnasm.c
View file

@ -16,43 +16,31 @@ WITH REGARD TO THIS SOFTWARE.
typedef unsigned char Uint8;
typedef struct {
int ptr;
int len;
Uint8 data[PRGLEN];
} Program;
char labels[256][16];
char opcodes[][4] = {
"BRK",
"LIT",
"---",
"POP",
"DUP",
"DRP",
"SWP",
"SLP",
"PSH",
"POP", /* --- */
"OVR",
"ROT",
/* */
"JMP",
"JSR",
"RST",
"BEQ",
"JEQ",
"RTS",
"EQU",
"NEQ",
"LTH",
"GTH", /* --- */
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---", /* --- */
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---"};
"GTH",
/* */};
Program p;
@ -78,6 +66,17 @@ suca(char *s) /* string to uppercase */
return s;
}
int
sihx(char *s)
{
int i = 0;
char c;
while((c = s[i++]))
if(!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F'))
return 0;
return 1;
}
int
shex(char *s) /* string to num */
{
@ -86,36 +85,90 @@ shex(char *s) /* string to num */
while((c = s[i++]))
if(c >= '0' && c <= '9')
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 - 'A');
return n;
}
#pragma mark - Helpers
#pragma mark - Parser
void
addprg(Uint8 hex)
{
p.data[p.len++] = hex;
}
void
addlabel(char *id, Uint8 addr)
{
printf("new label: %s=%02x\n", id, addr);
}
void
addconst(char *id, Uint8 value)
{
printf("new const: %s=%02x\n", id, value);
}
Uint8
getopcode(char *s)
findop(char *s)
{
int i;
if(s[0] == '{') /* TODO catch closing */
return 0x01;
for(i = 0; i < 16; ++i)
if(scmp(opcodes[i], suca(s)))
if(scmp(opcodes[i], s))
return i;
return 0xff;
return 0;
}
int
comment(char *w, int *skip)
{
if(w[0] == '>') {
*skip = 0;
return 1;
}
if(w[0] == '<') *skip = 1;
if(*skip) return 1;
return 0;
}
void
pass1(FILE *f)
{
int skip = 0;
char word[64];
while(fscanf(f, "%s", word) == 1) {
int op = getopcode(word);
if(word[0] == '}')
if(comment(word, &skip))
continue;
if(op == 0xff)
op = shex(word);
p.data[p.ptr++] = op;
}
rewind(f);
}
void
pass2(FILE *f)
{
int skip = 0;
char word[64];
while(fscanf(f, "%s", word) == 1) {
Uint8 op;
suca(word);
if(comment(word, &skip)) continue;
if(word[0] == ']') continue;
if(word[0] == '+') {
addprg(0x01);
addprg(1);
addprg(shex(word + 1));
} else if(word[0] == '[') {
addprg(0x01);
addprg(shex(word + 1));
} else if((op = findop(word)))
addprg(op);
else if(sihx(word))
addprg(shex(word));
else if(scmp(word, "BRK"))
addprg(0x00);
else
printf("unknown: %s\n", word);
}
}
@ -135,6 +188,7 @@ main(int argc, char *argv[])
if(!(f = fopen(argv[1], "r")))
return error("Missing input.");
pass1(f);
pass2(f);
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb"));
fclose(f);
return 0;