Add stubbed EMC (emulator call) instruction

This commit is contained in:
Horseshoe Crab 2021-05-03 09:35:00 -04:00
parent 736bc261c1
commit 081b72c6ea
10 changed files with 60 additions and 8 deletions

View File

@ -32,17 +32,19 @@ disass: bin/disass.o bin/vm.o
bin/%.o: src/%.c
$(CC) $(CFLAGS) -o $@ -c $^
bin/emcalls.o:
bin/vm.o:
bin/main.o:
bin/disass.o:
# needs to be run separately
rom: rom.bin
xxd -i src/$^ > src/$@.h
rom.bin: src/rom.asm src/zeropage.incbin
./ass.sh src/rom.asm src/zeropage.incbin
$(TARGET): bin/main.o bin/vm.o
$(TARGET): bin/main.o bin/vm.o bin/emcalls.o
$(CC) $(CFLAGS) -o bin/$@$(TRACE_SUFFIX) $^
clean:

1
ass.sh
View File

@ -37,6 +37,7 @@ bad_assemble() {
sed -i 's/JMP[[:blank:]]/0d/gi' "$1"
sed -i 's/BEQ[[:blank:]]/0e/gi' "$1"
sed -i 's/BNQ[[:blank:]]/0f/gi' "$1"
sed -i 's/EMC[[:blank:]]/10/gi' "$1"
sed -i 's/NOP[[:blank:]]*/ff 00 00/gi' "$1"
sed -i 's/H//gi' "$1" # remove hex suffix 'h' after only hex digits remain

View File

@ -1,3 +1,5 @@
/* x1phosura 2021 */
#include <assert.h>
#include <getopt.h>
#include <stdbool.h>

34
src/emcalls.c Normal file
View File

@ -0,0 +1,34 @@
/* emcalls.c: This file implements emulator calls ("emcalls"). Emcalls are
analogous to system calls, except since there's no real OS, they're handled
directly by the emulator. The basic usage should revolve around adding cases
to the emcall switch-case, where each case is a special emcall that calls a
function to handle it. This is perhaps the easiest way to plug fancy features
into the emulator itself; basically treat the EMC instruction is like the ioctl
syscall (_now_ I see why ioctl is such a tempting serpent of a syscall to have)
x1phosura 2021
*/
#include <stdint.h>
#include <stdio.h>
void do_emcall(uint8_t emc_args[2])
{
// emc_args[1] may be used in the future
switch(emc_args[0]) {
case 0x00:
printf("I'm a zero emcall!\n"); // replace with emcall handler
break;
case 0x01:
printf("I'm a one emcall!\n"); // replace with emcall handler
break;
case 0x02:
printf("I'm a two emcall!\n"); // replace with emcall handler
break;
default:
printf("EMC: 1st arg: 0x%02x, 2nd arg: 0x%02x\n", emc_args[0], emc_args[1]);
}
printf("[DEBUG] TODO: finish (stubbed)\n");
}

6
src/emcalls.h Normal file
View File

@ -0,0 +1,6 @@
/* x1phosura 2021 */
#pragma once // WAAAAAY better than a dumb header guard ;)
void do_emcall(uint8_t emc_args[2]);

View File

@ -1,3 +1,5 @@
/* x1phosura 2021 */
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>

View File

@ -419,7 +419,7 @@ push 0x400b # check fourth block
pushi 0x1d00
push 0x410b
pushi 0x1600
0xee 0x07 0x30 # junk NOP
emc 0x0122
0x30 0x30 0x30 # junk NOP
push 0x420b
pushi 0x4400
@ -431,7 +431,7 @@ bnq 0xd102 # Fail if any two bytes ever not equal
pop 0xffff
pop 0xffff
0xee 0x07 0x30 # junk NOP
0xee 0x07 0x30 # junk NOP
emc 0x3344
bnq 0xd102 # Fail if any two bytes ever not equal
pop 0xffff
0xee 0x07 0x30 # junk NOP

View File

@ -85,10 +85,10 @@ unsigned char src_rom_bin[] = {
0x30, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0x0f, 0xd1, 0x02, 0x02, 0xff,
0xff, 0xee, 0x07, 0x30, 0x02, 0xff, 0xff, 0x0f, 0xd1, 0x02, 0x02, 0xff,
0xff, 0x02, 0xff, 0xff, 0x01, 0x40, 0x0b, 0x03, 0x1d, 0x00, 0x01, 0x41,
0x0b, 0x03, 0x16, 0x00, 0xee, 0x07, 0x30, 0x30, 0x30, 0x30, 0x01, 0x42,
0x0b, 0x03, 0x16, 0x00, 0x10, 0x01, 0x22, 0x30, 0x30, 0x30, 0x01, 0x42,
0x0b, 0x03, 0x44, 0x00, 0x01, 0x43, 0x0b, 0x03, 0x75, 0x00, 0x0f, 0xd1,
0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xee, 0x07, 0x30, 0xee, 0x07,
0x30, 0x0f, 0xd1, 0x02, 0x02, 0xff, 0xff, 0xee, 0x07, 0x30, 0x02, 0xff,
0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xee, 0x07, 0x30, 0x10, 0x33,
0x44, 0x0f, 0xd1, 0x02, 0x02, 0xff, 0xff, 0xee, 0x07, 0x30, 0x02, 0xff,
0xff, 0x0f, 0xd1, 0x02, 0x02, 0xff, 0xff, 0x02, 0xff, 0xff, 0xee, 0x07,
0x30, 0x0f, 0xd1, 0x02, 0x02, 0xff, 0xff, 0x30, 0x30, 0x30, 0x02, 0xff,
0xff, 0x0d, 0xcb, 0x02, 0x01, 0xcb, 0x02, 0x40, 0x77, 0x12, 0x00, 0x00,

View File

@ -23,6 +23,7 @@ use assert()s to make sure pc, sp, etc... are valid
#endif
#include "vm.h"
#include "emcalls.h"
#ifdef TRACE // TRACE_VARS
@ -50,7 +51,6 @@ static inline void push(struct CPU *cpu, uint8_t val)
++cpu->sp;
}
static inline uint8_t pop(struct CPU *cpu)
{
uint8_t val;
@ -62,7 +62,6 @@ static inline uint8_t pop(struct CPU *cpu)
return val;
}
/* vm_do_instruction:
*/
uint16_t vm_do_instruction(struct CPU *cpu, uint8_t *mem, uint8_t instr[3])
@ -163,6 +162,10 @@ uint16_t vm_do_instruction(struct CPU *cpu, uint8_t *mem, uint8_t instr[3])
return operand;
pc += 3;
break;
case EMC:
do_emcall(operands);
pc += 3;
break;
case NOP:
pc += 3;
break;
@ -208,6 +211,7 @@ void print_op_decoded(uint8_t i[3], bool pargs)
case JMP: printf("JMP"); if (pargs) printf(fmt, i[1], i[2]); break;
case BEQ: printf("BEQ"); if (pargs) printf(fmt, i[1], i[2]); break;
case BNQ: printf("BNQ"); if (pargs) printf(fmt, i[1], i[2]); break;
case EMC: printf("EMC"); if (pargs) printf(fmt, i[1], i[2]); break;
case NOP: printf("NOP"); break;
default: printf("0x%02x 0x%02x 0x%02x", i[0], i[1], i[2]);
}

View File

@ -23,6 +23,7 @@ enum instructions {
JMP = 13,
BEQ = 14,
BNQ = 15,
EMC = 16,
// every opcode 0x10-0xfe is basically just a NOP just to be annoying
NOP = 0xff
};