mirror of
https://git.sr.ht/~rabbits/uxn
synced 2024-11-22 05:45:10 +00:00
*
This commit is contained in:
parent
72d9c98f35
commit
099d1f0845
6 changed files with 125 additions and 57 deletions
|
@ -1,7 +1,9 @@
|
||||||
AlignAfterOpenBracket: DontAlign
|
AlignAfterOpenBracket: DontAlign
|
||||||
AlignEscapedNewlines: DontAlign
|
AlignEscapedNewlines: DontAlign
|
||||||
|
AlignOperands: DontAlign
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: true
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: false
|
||||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||||
|
|
7
build.sh
7
build.sh
|
@ -7,10 +7,11 @@ clang-format -i uxn.c
|
||||||
# remove old
|
# remove old
|
||||||
rm -f ./uxnasm
|
rm -f ./uxnasm
|
||||||
rm -f ./uxn
|
rm -f ./uxn
|
||||||
|
rm -f ./boot.rom
|
||||||
|
|
||||||
# debug(slow)
|
# debug(slow)
|
||||||
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxnasm.c -o uxnasm
|
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxnasm.c -o uxnasm
|
||||||
# cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn
|
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c -o uxn
|
||||||
|
|
||||||
# build(fast)
|
# build(fast)
|
||||||
# cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
# cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn
|
||||||
|
@ -19,5 +20,5 @@ cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werr
|
||||||
# echo "Size: $(du -sk ./uxn)"
|
# echo "Size: $(du -sk ./uxn)"
|
||||||
|
|
||||||
# run
|
# run
|
||||||
./uxnasm program.usm program.rom
|
./uxnasm example.usm boot.rom
|
||||||
# ./uxn program.rom
|
./uxn boot.rom
|
||||||
|
|
1
example.usm
Normal file
1
example.usm
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{ 25 26 27 28 } SWP POP DUP BRK
|
|
@ -1 +0,0 @@
|
||||||
LIT 25 26 LIT DUP ADD BRK
|
|
116
uxn.c
116
uxn.c
|
@ -11,20 +11,38 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define FLAG_HALT 0x01
|
||||||
|
#define FLAG_ZERO 0x02
|
||||||
|
#define FLAG_CARRY 0x04
|
||||||
|
#define FLAG_TRAPS 0x08
|
||||||
|
|
||||||
#define STACK_DEPTH 256
|
#define STACK_DEPTH 256
|
||||||
#define ECHO 1
|
|
||||||
|
|
||||||
typedef unsigned char Uint8;
|
typedef unsigned char Uint8;
|
||||||
typedef unsigned char Uint16;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Uint8 literal;
|
||||||
|
Uint8 status, counter;
|
||||||
|
Uint8 memory[STACK_DEPTH];
|
||||||
|
Uint8 mptr, sptr;
|
||||||
|
Uint8 stack[STACK_DEPTH];
|
||||||
|
Uint8 address[STACK_DEPTH];
|
||||||
} Computer;
|
} Computer;
|
||||||
|
|
||||||
Uint8 sptr;
|
void
|
||||||
Uint8 stack[STACK_DEPTH];
|
setflag(Computer *cpu, char flag, int b)
|
||||||
Uint8 address[STACK_DEPTH];
|
{
|
||||||
Uint16 memory[STACK_DEPTH];
|
if(b)
|
||||||
|
cpu->status |= flag;
|
||||||
|
else
|
||||||
|
cpu->status &= (~flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getflag(Computer *cpu, char flag)
|
||||||
|
{
|
||||||
|
return cpu->status & flag;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
echo(Uint8 *s, Uint8 len, char *name)
|
echo(Uint8 *s, Uint8 len, char *name)
|
||||||
|
@ -34,51 +52,79 @@ echo(Uint8 *s, Uint8 len, char *name)
|
||||||
for(i = 0; i < len; ++i) {
|
for(i = 0; i < len; ++i) {
|
||||||
if(i % 16 == 0)
|
if(i % 16 == 0)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if(sptr == i)
|
printf("%02x ", s[i]);
|
||||||
printf("[%02x]", s[i]);
|
|
||||||
else
|
|
||||||
printf(" %02x ", s[i]);
|
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
op_push(Uint8 *s, Uint8 v)
|
op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
|
||||||
{
|
{
|
||||||
s[sptr++] = v;
|
s[*ptr] = v;
|
||||||
|
(*ptr) += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
op_pop(Uint8 *s)
|
op_pop(Uint8 *s, Uint8 *ptr)
|
||||||
{
|
{
|
||||||
s[sptr--] = 0x00;
|
s[*ptr--] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reset(Computer *cpu)
|
reset(Computer *cpu)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
disk(Computer *cpu, FILE *f)
|
error(char *name)
|
||||||
{
|
{
|
||||||
int i;
|
printf("Error: %s\n", name);
|
||||||
unsigned short buffer[256];
|
return 0;
|
||||||
reset(cpu);
|
|
||||||
if(!fread(buffer, sizeof(buffer), 1, f))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(i = 0; i < 128; i++) {
|
|
||||||
cpu->memory[i * 2] |= (buffer[i] >> 8) & 0xFF;
|
|
||||||
cpu->memory[i * 2 + 1] |= buffer[i] & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run(Computer *cpu, int debug)
|
load(Computer *cpu, FILE *f)
|
||||||
{
|
{
|
||||||
|
fread(cpu->memory, sizeof(cpu->memory), 1, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eval(Computer *cpu)
|
||||||
|
{
|
||||||
|
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--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(instr) {
|
||||||
|
case 0x0: setflag(cpu, FLAG_HALT, 1); break;
|
||||||
|
case 0x1: cpu->literal += 4; break;
|
||||||
|
default: printf("Unknown instruction: #%02x\n", instr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run(Computer *cpu)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
while((cpu->status & FLAG_HALT) == 0)
|
||||||
|
eval(cpu);
|
||||||
|
/* debug */
|
||||||
|
printf("ended @ %d | ", cpu->counter);
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
printf("%d-", (cpu->status & (1 << i)) != 0);
|
||||||
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -90,11 +136,11 @@ main(int argc, char *argv[])
|
||||||
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.");
|
||||||
if(!disk(&cpu, f))
|
reset(&cpu);
|
||||||
return error("Unreadable input.");
|
load(&cpu, f);
|
||||||
run(&cpu, ECHO);
|
run(&cpu);
|
||||||
/* print result */
|
/* print result */
|
||||||
echo(stack, 0x40, "stack");
|
echo(cpu.stack, 0x40, "stack");
|
||||||
echo(memory, 0x40, "memory");
|
echo(cpu.memory, 0x40, "memory");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
55
uxnasm.c
55
uxnasm.c
|
@ -20,7 +20,39 @@ typedef struct {
|
||||||
Uint8 data[PRGLEN];
|
Uint8 data[PRGLEN];
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
char opcodes[][4] = {"BRK", "LIT", "DUP", "DRP", "SWP", "SLP", "PSH", "POP", "JMP", "JSR", "RST", "BEQ", "EQU", "NEQ", "LTH", "GTH"};
|
char opcodes[][4] = {
|
||||||
|
"BRK",
|
||||||
|
"LIT",
|
||||||
|
"DUP",
|
||||||
|
"DRP",
|
||||||
|
"SWP",
|
||||||
|
"SLP",
|
||||||
|
"PSH",
|
||||||
|
"POP", /* --- */
|
||||||
|
"JMP",
|
||||||
|
"JSR",
|
||||||
|
"RST",
|
||||||
|
"BEQ",
|
||||||
|
"EQU",
|
||||||
|
"NEQ",
|
||||||
|
"LTH",
|
||||||
|
"GTH", /* --- */
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---", /* --- */
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---",
|
||||||
|
"---"};
|
||||||
|
|
||||||
Program p;
|
Program p;
|
||||||
|
|
||||||
|
@ -65,34 +97,22 @@ Uint8
|
||||||
getopcode(char *s)
|
getopcode(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], suca(s)))
|
||||||
return i;
|
return i;
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
echo(Uint8 *s, Uint8 len, Uint8 ptr, char *name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
printf("%s\n", name);
|
|
||||||
for(i = 0; i < len; ++i) {
|
|
||||||
if(i % 16 == 0)
|
|
||||||
printf("\n");
|
|
||||||
if(ptr == i)
|
|
||||||
printf("[%02x]", s[i]);
|
|
||||||
else
|
|
||||||
printf(" %02x ", s[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pass1(FILE *f)
|
pass1(FILE *f)
|
||||||
{
|
{
|
||||||
char word[64];
|
char word[64];
|
||||||
while(fscanf(f, "%s", word) == 1) {
|
while(fscanf(f, "%s", word) == 1) {
|
||||||
int op = getopcode(word);
|
int op = getopcode(word);
|
||||||
|
if(word[0] == '}')
|
||||||
|
continue;
|
||||||
if(op == 0xff)
|
if(op == 0xff)
|
||||||
op = shex(word);
|
op = shex(word);
|
||||||
p.data[p.ptr++] = op;
|
p.data[p.ptr++] = op;
|
||||||
|
@ -117,6 +137,5 @@ main(int argc, char *argv[])
|
||||||
pass1(f);
|
pass1(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);
|
||||||
echo(p.data, 0x40, 0, "program");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue