Add LEM1802, keyboard and clock. Fix indirect argument encoding in assembler.
This commit is contained in:
parent
d13d72ce8b
commit
2148ba60aa
8
Makefile
8
Makefile
|
@ -1,10 +1,16 @@
|
||||||
.PHONY: all clean reformat
|
.PHONY: all clean reformat
|
||||||
|
|
||||||
CFLAGS=-Wall -Werror -pedantic -std=c99 -O2 -mtune=native
|
CFLAGS=-Wall -Werror -pedantic -std=c99 -g3 # -O2 -mtune=native
|
||||||
|
CFLAGS+=-DDEV_DEBUG -DDEV_LEM1802 -DDEV_CLOCK
|
||||||
|
CFLAGS+=$(shell pkg-config --cflags sdl2)
|
||||||
|
LDLIBS+=$(shell pkg-config --libs sdl2)
|
||||||
REFORMAT=astyle --style=linux
|
REFORMAT=astyle --style=linux
|
||||||
|
DEVICES=$(patsubst %.c,%.o,$(wildcard dev_*.c))
|
||||||
|
|
||||||
all: dsim
|
all: dsim
|
||||||
|
|
||||||
|
dsim: dsim.o device.o $(DEVICES)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *~ *% *.o *.orig
|
$(RM) *~ *% *.o *.orig
|
||||||
$(RM) dsim
|
$(RM) dsim
|
||||||
|
|
6
asm.py
6
asm.py
|
@ -53,10 +53,10 @@ class ASM(SimpleNamespace):
|
||||||
if arg.reg == 'SP':
|
if arg.reg == 'SP':
|
||||||
sp = getattr(arg, 'sp', None)
|
sp = getattr(arg, 'sp', None)
|
||||||
if sp is None:
|
if sp is None:
|
||||||
if disp == 0:
|
if arg.disp == 0:
|
||||||
return (0x19, None)
|
return (0x19, None)
|
||||||
else:
|
else:
|
||||||
return (0x1a, disp)
|
return (0x1a, arg.disp)
|
||||||
else:
|
else:
|
||||||
if (sp, is_a) not in (('inc', True), ('dec', False)):
|
if (sp, is_a) not in (('inc', True), ('dec', False)):
|
||||||
raise SyntaxError()
|
raise SyntaxError()
|
||||||
|
@ -83,7 +83,7 @@ class ASM(SimpleNamespace):
|
||||||
else:
|
else:
|
||||||
b_bits, b_extra = self.addr(self.b, False)
|
b_bits, b_extra = self.addr(self.b, False)
|
||||||
r = [o | (a_bits << 10) | (b_bits << 5)]
|
r = [o | (a_bits << 10) | (b_bits << 5)]
|
||||||
for e in b_extra, a_extra:
|
for e in a_extra, b_extra:
|
||||||
if e is not None:
|
if e is not None:
|
||||||
r.append(e)
|
r.append(e)
|
||||||
print("Assembing: %s %r, %r -> %r" % (self.op, self.b, self.a, r))
|
print("Assembing: %s %r, %r -> %r" % (self.op, self.b, self.a, r))
|
||||||
|
|
110
dsim.c
110
dsim.c
|
@ -8,8 +8,9 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define EMU_ID 0xed6f
|
#include <sys/time.h>
|
||||||
#define EMU_VER 0x0000
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
uint16_t ram[0x10000];
|
uint16_t ram[0x10000];
|
||||||
uint16_t ra, rb, rc, rx, ry, rz, ri, rj;
|
uint16_t ra, rb, rc, rx, ry, rz, ri, rj;
|
||||||
|
@ -25,27 +26,8 @@ bool intq_en;
|
||||||
uint16_t intq[MAX_INTQ_SIZE];
|
uint16_t intq[MAX_INTQ_SIZE];
|
||||||
unsigned int intq_size;
|
unsigned int intq_size;
|
||||||
uint8_t intq_head;
|
uint8_t intq_head;
|
||||||
|
uint16_t hwn;
|
||||||
void dumpregs()
|
struct timeval time;
|
||||||
{
|
|
||||||
printf("%4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n",
|
|
||||||
"PC","SP","A","B","C","X","Y","Z","I","J","EX","IA");
|
|
||||||
printf("%04hx %04hx %04hx %04hx %04hx %04hx %04hx %04hx %04hx %04hx %04hx %04hx\n",
|
|
||||||
rpc, rsp, ra, rb, rc, rx, ry, rz, ri, rj, rex, ria);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_ram(uint16_t addr, uint16_t count)
|
|
||||||
{
|
|
||||||
uint16_t i, a;
|
|
||||||
|
|
||||||
for (i=0; i<count; i++) {
|
|
||||||
a = (addr + i) % sizeof(ram);
|
|
||||||
if ((i % 8) == 0)
|
|
||||||
printf("\n%04x: ", a);
|
|
||||||
printf("%04x ", ram[a]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void intq_push(uint16_t v)
|
void intq_push(uint16_t v)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +41,7 @@ void intq_push(uint16_t v)
|
||||||
uint16_t intq_pop()
|
uint16_t intq_pop()
|
||||||
{
|
{
|
||||||
if (intq_size > 0) {
|
if (intq_size > 0) {
|
||||||
return intq[(intq_head-intq_size--) % MAX_INTQ_SIZE];
|
return intq[(intq_head+MAX_INTQ_SIZE-intq_size--) % MAX_INTQ_SIZE];
|
||||||
} else
|
} else
|
||||||
return 0xffff;
|
return 0xffff;
|
||||||
}
|
}
|
||||||
|
@ -78,46 +60,21 @@ void reset()
|
||||||
|
|
||||||
trace = false;
|
trace = false;
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
|
for (hwn = 0; iodevs[hwn] != NULL; hwn++)
|
||||||
|
if (iodevs[hwn]->init)
|
||||||
|
iodevs[hwn]->init();
|
||||||
|
|
||||||
|
printf("Initialized %d devices\n", hwn);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_entry {
|
void shutdown()
|
||||||
uint32_t vendor;
|
|
||||||
uint32_t product;
|
|
||||||
uint16_t version;
|
|
||||||
void (*irqh)();
|
|
||||||
void (*init)();
|
|
||||||
void (*free)();
|
|
||||||
void (*tick)();
|
|
||||||
};
|
|
||||||
|
|
||||||
void debug_irqh()
|
|
||||||
{
|
{
|
||||||
switch (ra) {
|
int i;
|
||||||
case 0x0000:
|
for (i = 0; i < hwn; i++)
|
||||||
running = false;
|
if (iodevs[i]->free)
|
||||||
break;
|
iodevs[i]->free();
|
||||||
case 0x0001:
|
|
||||||
dumpregs();
|
|
||||||
break;
|
|
||||||
case 0x0002:
|
|
||||||
dump_ram(ry, rx);
|
|
||||||
break;
|
|
||||||
case 0x0004:
|
|
||||||
trace = false;
|
|
||||||
break;
|
|
||||||
case 0x0005:
|
|
||||||
trace = true;
|
|
||||||
break;
|
|
||||||
case 0xffff:
|
|
||||||
rx = EMU_ID;
|
|
||||||
ry = EMU_VER;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct dev_entry iodevs[] = {
|
|
||||||
{ 0x6d53647c, 0x62e037d3, 0x00000000, debug_irqh, NULL, NULL, NULL }, /* Debug device */
|
|
||||||
};
|
|
||||||
|
|
||||||
uint16_t *val(int operand, bool is_a)
|
uint16_t *val(int operand, bool is_a)
|
||||||
{
|
{
|
||||||
|
@ -441,19 +398,19 @@ void oIAQ(uint16_t *a, uint16_t *b)
|
||||||
|
|
||||||
void oHWN(uint16_t *a, uint16_t *b)
|
void oHWN(uint16_t *a, uint16_t *b)
|
||||||
{
|
{
|
||||||
*a = sizeof(iodevs) / sizeof(struct dev_entry);
|
*a = hwn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oHWQ(uint16_t *a, uint16_t *b)
|
void oHWQ(uint16_t *a, uint16_t *b)
|
||||||
{
|
{
|
||||||
uint16_t idx = *a;
|
uint16_t idx = *a;
|
||||||
|
|
||||||
if (idx < sizeof(iodevs) / sizeof(struct dev_entry)) {
|
if (idx < hwn) {
|
||||||
ra = iodevs[idx].product & 0xffff;
|
ra = iodevs[idx]->product & 0xffff;
|
||||||
rb = (iodevs[idx].product >> 16) & 0xffff;
|
rb = (iodevs[idx]->product >> 16) & 0xffff;
|
||||||
rc = iodevs[idx].version;
|
rc = iodevs[idx]->version;
|
||||||
rx = iodevs[idx].vendor & 0xffff;
|
rx = iodevs[idx]->vendor & 0xffff;
|
||||||
ry = (iodevs[idx].vendor >> 16) & 0xffff;
|
ry = (iodevs[idx]->vendor >> 16) & 0xffff;
|
||||||
} else {
|
} else {
|
||||||
ra = rb = rc = rx = ry = 0;
|
ra = rb = rc = rx = ry = 0;
|
||||||
}
|
}
|
||||||
|
@ -463,9 +420,9 @@ void oHWI(uint16_t *a, uint16_t *b)
|
||||||
{
|
{
|
||||||
uint16_t idx = *a;
|
uint16_t idx = *a;
|
||||||
|
|
||||||
if (idx < sizeof(iodevs) / sizeof(struct dev_entry)) {
|
if (idx < hwn) {
|
||||||
if (iodevs[idx].irqh)
|
if (iodevs[idx]->irqh)
|
||||||
iodevs[idx].irqh();
|
iodevs[idx]->irqh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,9 +450,12 @@ void next()
|
||||||
op_t f;
|
op_t f;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
|
gettimeofday(&time, NULL);
|
||||||
|
|
||||||
if ((!intq_en) && (intq_size > 0) && (!skip_next)) {
|
if ((!intq_en) && (intq_size > 0) && (!skip_next)) {
|
||||||
i = intq_pop();
|
i = intq_pop();
|
||||||
if (ria != 0) {
|
if (ria != 0) {
|
||||||
|
printf("Firing interrupt with message 0x%04x\n", i);
|
||||||
intq_en = true;
|
intq_en = true;
|
||||||
ram[--rsp] = rpc;
|
ram[--rsp] = rpc;
|
||||||
ram[--rsp] = ra;
|
ram[--rsp] = ra;
|
||||||
|
@ -503,10 +463,10 @@ void next()
|
||||||
ra = i;
|
ra = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (trace)
|
if (trace)
|
||||||
dumpregs();
|
dumpregs();
|
||||||
|
*/
|
||||||
ir = ram[rpc++];
|
ir = ram[rpc++];
|
||||||
|
|
||||||
opcode = ir & 0x001f;
|
opcode = ir & 0x001f;
|
||||||
|
@ -528,6 +488,10 @@ void next()
|
||||||
else
|
else
|
||||||
skip_next = ((opcode & 0x18) == 0x10); /* Skip chained conditionals */
|
skip_next = ((opcode & 0x18) == 0x10); /* Skip chained conditionals */
|
||||||
|
|
||||||
|
for (i = 0; iodevs[i] != NULL; i++)
|
||||||
|
if (iodevs[i]->tick)
|
||||||
|
iodevs[i]->tick();
|
||||||
|
|
||||||
ticks++;
|
ticks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +502,7 @@ int load_image(char *filename)
|
||||||
ssize_t pos;
|
ssize_t pos;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
|
|
||||||
|
printf("Loading %s ...\n", filename);
|
||||||
fd = open(filename, O_RDONLY);
|
fd = open(filename, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -562,6 +527,7 @@ int main(int argc, char *argv[])
|
||||||
load_image(argv[1]);
|
load_image(argv[1]);
|
||||||
reset();
|
reset();
|
||||||
while (running) next();
|
while (running) next();
|
||||||
|
shutdown();
|
||||||
}
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue