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 AlignAfterOpenBracket: DontAlign
AlignEscapedNewlines: DontAlign AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign AlignOperands: DontAlign
AllowShortBlocksOnASingleLine: Empty AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true AllowShortEnumsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: TopLevel AlwaysBreakAfterDefinitionReturnType: TopLevel
BinPackArguments: false BinPackArguments: false
BinPackParameters: 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 ## Assembly Syntax
``` ```
: starting a definition < comment >
& obtaining pointers
( stack comments
` inlining bytecodes
' strings
# numbers
$ characters
~ vector
[ 12 34 ] real values
< 12 34 > relative values
( 12 34 ) deadzone
```
``` +01 < literal >
;add-two JSR
BRK [ 01 02 03 04 ] < block of literals >
:add-two $01 < pointer8 >
[ 2 ] ADD RTS
{ 01 02 03 04 } < block of pointer8 >
~ff0f < pointer16 >
( ff00 ff01 ff02 ff03 ) < block of pointer16 >
=const +ff
:label ADD RTS
``` ```
## Design ## Design
@ -57,3 +54,12 @@ BRK
### Emulator ### Emulator
- SDL Layer - 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]; Uint8 address[STACK_DEPTH];
} Computer; } Computer;
Computer cpu;
#pragma mark - Helpers
void void
setflag(Computer *cpu, char flag, int b) setflag(char flag, int b)
{ {
if(b) if(b)
cpu->status |= flag; cpu.status |= flag;
else else
cpu->status &= (~flag); cpu.status &= (~flag);
} }
int int
getflag(Computer *cpu, char flag) getflag(char flag)
{ {
return cpu->status & flag; return cpu.status & flag;
} }
void void
@ -57,30 +61,31 @@ echo(Uint8 *s, Uint8 len, char *name)
printf("\n\n"); printf("\n\n");
} }
#pragma mark - Operations
void void
op_push(Uint8 *s, Uint8 *ptr, Uint8 v) op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
{ {
s[*ptr] = v; s[(*ptr)++] = v;
(*ptr) += 1;
} }
void Uint8
op_pop(Uint8 *s, Uint8 *ptr) op_pop(Uint8 *s, Uint8 *ptr)
{ {
s[*ptr--] = 0x00; return s[--*ptr];
} }
void void
reset(Computer *cpu) reset(void)
{ {
int i; int i;
cpu->status = 0x00; cpu.status = 0x00;
cpu->counter = 0x00; cpu.counter = 0x00;
cpu->mptr = 0x00; cpu.mptr = 0x00;
cpu->sptr = 0x00; cpu.sptr = 0x00;
cpu->literal = 0x00; cpu.literal = 0x00;
for(i = 0; i < 256; i++) for(i = 0; i < 256; i++)
cpu->stack[i] = 0x00; cpu.stack[i] = 0x00;
} }
int int
@ -91,39 +96,63 @@ error(char *name)
} }
void 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 void
eval(Computer *cpu) eval()
{ {
Uint8 instr = cpu->memory[cpu->mptr++]; Uint8 instr = cpu.memory[cpu.mptr++];
Uint8 a, b, c;
if(cpu->literal > 0) { if(cpu.literal > 0) {
printf("push: %02x[%d](%d)\n", instr, cpu->literal, cpu->sptr); printf("push: %02x[%d](%d)\n", instr, cpu.literal, cpu.sptr);
op_push(cpu->stack, &cpu->sptr, instr); op_push(cpu.stack, &cpu.sptr, instr);
cpu->literal--; cpu.literal--;
return; return;
} }
switch(instr) { switch(instr) {
case 0x0: setflag(cpu, FLAG_HALT, 1); break; case 0x0: setflag(FLAG_HALT, 1); break;
case 0x1: cpu->literal += 4; 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); default: printf("Unknown instruction: #%02x\n", instr);
} }
} }
void void
run(Computer *cpu) run(void)
{ {
int i; int i;
while((cpu->status & FLAG_HALT) == 0) while((cpu.status & FLAG_HALT) == 0)
eval(cpu); eval(cpu);
/* debug */ /* debug */
printf("ended @ %d | ", cpu->counter); printf("ended @ %d | ", cpu.counter);
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
printf("%d-", (cpu->status & (1 << i)) != 0); printf("%d-", (cpu.status & (1 << i)) != 0);
printf("\n\n"); printf("\n\n");
} }
@ -131,14 +160,13 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
FILE *f; FILE *f;
Computer cpu;
if(argc < 2) if(argc < 2)
return error("No input."); return error("No input.");
if(!(f = fopen(argv[1], "rb"))) if(!(f = fopen(argv[1], "rb")))
return error("Missing input."); return error("Missing input.");
reset(&cpu); reset();
load(&cpu, f); load(f);
run(&cpu); run();
/* print result */ /* print result */
echo(cpu.stack, 0x40, "stack"); echo(cpu.stack, 0x40, "stack");
echo(cpu.memory, 0x40, "memory"); echo(cpu.memory, 0x40, "memory");

128
uxnasm.c
View File

@ -16,43 +16,31 @@ WITH REGARD TO THIS SOFTWARE.
typedef unsigned char Uint8; typedef unsigned char Uint8;
typedef struct { typedef struct {
int ptr; int len;
Uint8 data[PRGLEN]; Uint8 data[PRGLEN];
} Program; } Program;
char labels[256][16];
char opcodes[][4] = { char opcodes[][4] = {
"BRK", "BRK",
"LIT", "LIT",
"---",
"POP",
"DUP", "DUP",
"DRP",
"SWP", "SWP",
"SLP", "OVR",
"PSH", "ROT",
"POP", /* --- */ /* */
"JMP", "JMP",
"JSR", "JSR",
"RST", "JEQ",
"BEQ", "RTS",
"EQU", "EQU",
"NEQ", "NEQ",
"LTH", "LTH",
"GTH", /* --- */ "GTH",
"---", /* */};
"---",
"---",
"---",
"---",
"---",
"---",
"---", /* --- */
"---",
"---",
"---",
"---",
"---",
"---",
"---",
"---"};
Program p; Program p;
@ -78,6 +66,17 @@ suca(char *s) /* string to uppercase */
return s; 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 int
shex(char *s) /* string to num */ shex(char *s) /* string to num */
{ {
@ -86,36 +85,90 @@ shex(char *s) /* string to num */
while((c = s[i++])) while((c = s[i++]))
if(c >= '0' && c <= '9') if(c >= '0' && c <= '9')
n = n * 16 + (c - '0'); n = n * 16 + (c - '0');
else if(c >= 'a' && c <= 'f') else if(c >= 'A' && c <= 'F')
n = n * 16 + 10 + (c - 'a'); n = n * 16 + 10 + (c - 'A');
return n; 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 Uint8
getopcode(char *s) findop(char *s)
{ {
int i; int i;
if(s[0] == '{') /* TODO catch closing */
return 0x01;
for(i = 0; i < 16; ++i) for(i = 0; i < 16; ++i)
if(scmp(opcodes[i], suca(s))) if(scmp(opcodes[i], s))
return i; 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 void
pass1(FILE *f) pass1(FILE *f)
{ {
int skip = 0;
char word[64]; char word[64];
while(fscanf(f, "%s", word) == 1) { while(fscanf(f, "%s", word) == 1) {
int op = getopcode(word); if(comment(word, &skip))
if(word[0] == '}')
continue; continue;
if(op == 0xff) }
op = shex(word); rewind(f);
p.data[p.ptr++] = op; }
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"))) if(!(f = fopen(argv[1], "r")))
return error("Missing input."); return error("Missing input.");
pass1(f); pass1(f);
pass2(f);
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;