mirror of
https://git.sr.ht/~rabbits/uxn
synced 2024-11-21 21:35:11 +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
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: DontAlign
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||
|
|
7
build.sh
7
build.sh
|
@ -7,10 +7,11 @@ clang-format -i uxn.c
|
|||
# remove old
|
||||
rm -f ./uxnasm
|
||||
rm -f ./uxn
|
||||
rm -f ./boot.rom
|
||||
|
||||
# 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 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)
|
||||
# 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)"
|
||||
|
||||
# run
|
||||
./uxnasm program.usm program.rom
|
||||
# ./uxn program.rom
|
||||
./uxnasm example.usm boot.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.
|
||||
*/
|
||||
|
||||
#define FLAG_HALT 0x01
|
||||
#define FLAG_ZERO 0x02
|
||||
#define FLAG_CARRY 0x04
|
||||
#define FLAG_TRAPS 0x08
|
||||
|
||||
#define STACK_DEPTH 256
|
||||
#define ECHO 1
|
||||
|
||||
typedef unsigned char Uint8;
|
||||
typedef unsigned char Uint16;
|
||||
|
||||
typedef struct {
|
||||
|
||||
Uint8 literal;
|
||||
Uint8 status, counter;
|
||||
Uint8 memory[STACK_DEPTH];
|
||||
Uint8 mptr, sptr;
|
||||
Uint8 stack[STACK_DEPTH];
|
||||
Uint8 address[STACK_DEPTH];
|
||||
} Computer;
|
||||
|
||||
Uint8 sptr;
|
||||
Uint8 stack[STACK_DEPTH];
|
||||
Uint8 address[STACK_DEPTH];
|
||||
Uint16 memory[STACK_DEPTH];
|
||||
void
|
||||
setflag(Computer *cpu, char flag, int b)
|
||||
{
|
||||
if(b)
|
||||
cpu->status |= flag;
|
||||
else
|
||||
cpu->status &= (~flag);
|
||||
}
|
||||
|
||||
int
|
||||
getflag(Computer *cpu, char flag)
|
||||
{
|
||||
return cpu->status & flag;
|
||||
}
|
||||
|
||||
void
|
||||
echo(Uint8 *s, Uint8 len, char *name)
|
||||
|
@ -34,51 +52,79 @@ echo(Uint8 *s, Uint8 len, char *name)
|
|||
for(i = 0; i < len; ++i) {
|
||||
if(i % 16 == 0)
|
||||
printf("\n");
|
||||
if(sptr == i)
|
||||
printf("[%02x]", s[i]);
|
||||
else
|
||||
printf(" %02x ", s[i]);
|
||||
printf("%02x ", s[i]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
void
|
||||
op_push(Uint8 *s, Uint8 v)
|
||||
op_push(Uint8 *s, Uint8 *ptr, Uint8 v)
|
||||
{
|
||||
s[sptr++] = v;
|
||||
s[*ptr] = v;
|
||||
(*ptr) += 1;
|
||||
}
|
||||
|
||||
void
|
||||
op_pop(Uint8 *s)
|
||||
op_pop(Uint8 *s, Uint8 *ptr)
|
||||
{
|
||||
s[sptr--] = 0x00;
|
||||
s[*ptr--] = 0x00;
|
||||
}
|
||||
|
||||
void
|
||||
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
|
||||
disk(Computer *cpu, FILE *f)
|
||||
error(char *name)
|
||||
{
|
||||
int i;
|
||||
unsigned short buffer[256];
|
||||
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;
|
||||
printf("Error: %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -90,11 +136,11 @@ main(int argc, char *argv[])
|
|||
return error("No input.");
|
||||
if(!(f = fopen(argv[1], "rb")))
|
||||
return error("Missing input.");
|
||||
if(!disk(&cpu, f))
|
||||
return error("Unreadable input.");
|
||||
run(&cpu, ECHO);
|
||||
reset(&cpu);
|
||||
load(&cpu, f);
|
||||
run(&cpu);
|
||||
/* print result */
|
||||
echo(stack, 0x40, "stack");
|
||||
echo(memory, 0x40, "memory");
|
||||
echo(cpu.stack, 0x40, "stack");
|
||||
echo(cpu.memory, 0x40, "memory");
|
||||
return 0;
|
||||
}
|
||||
|
|
55
uxnasm.c
55
uxnasm.c
|
@ -20,7 +20,39 @@ typedef struct {
|
|||
Uint8 data[PRGLEN];
|
||||
} 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;
|
||||
|
||||
|
@ -65,34 +97,22 @@ Uint8
|
|||
getopcode(char *s)
|
||||
{
|
||||
int i;
|
||||
if(s[0] == '{') /* TODO catch closing */
|
||||
return 0x01;
|
||||
for(i = 0; i < 16; ++i)
|
||||
if(scmp(opcodes[i], suca(s)))
|
||||
return i;
|
||||
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
|
||||
pass1(FILE *f)
|
||||
{
|
||||
char word[64];
|
||||
while(fscanf(f, "%s", word) == 1) {
|
||||
int op = getopcode(word);
|
||||
if(word[0] == '}')
|
||||
continue;
|
||||
if(op == 0xff)
|
||||
op = shex(word);
|
||||
p.data[p.ptr++] = op;
|
||||
|
@ -117,6 +137,5 @@ main(int argc, char *argv[])
|
|||
pass1(f);
|
||||
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb"));
|
||||
fclose(f);
|
||||
echo(p.data, 0x40, 0, "program");
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue