mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-24 14:28:06 +11:00
Move apps/zasm/emul to tools/emul
This commit is contained in:
parent
193e6e066c
commit
7f27d63c19
4
apps/zasm/emul/.gitignore
vendored
4
apps/zasm/emul/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
libz80
|
||||
kernel.h
|
||||
zasm.h
|
||||
zasm
|
@ -1,12 +0,0 @@
|
||||
zasm: zasm.c libz80/libz80.o kernel.h zasm.h
|
||||
cc $< libz80/libz80.o -o $@
|
||||
|
||||
libz80/libz80.o: libz80/z80.c
|
||||
make -C libz80/codegen opcodes
|
||||
gcc -Wall -ansi -g -c -o libz80/libz80.o libz80/z80.c
|
||||
|
||||
kernel.h: glue.asm
|
||||
scas -o - -I ../../../parts/z80 $< | ./bin2c.sh KERNEL | tee $@ > /dev/null
|
||||
|
||||
zasm.h: $(addprefix ../, main.asm instr.asm directive.asm tok.asm parse.asm literal.asm util.asm)
|
||||
scas -o - -I.. $< | ./bin2c.sh ZASM | tee $@ > /dev/null
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "unsigned char $1[] = { "
|
||||
xxd -i -
|
||||
echo " };"
|
@ -1,28 +0,0 @@
|
||||
#include "user.inc"
|
||||
; Glue code for the emulated environment
|
||||
ZASM_INPUT .equ 0xa000
|
||||
ZASM_OUTPUT .equ 0xd000
|
||||
|
||||
jr init ; 2 bytes
|
||||
; *** JUMP TABLE ***
|
||||
jp strncmp
|
||||
jp addDE
|
||||
jp upcase
|
||||
jp unsetZ
|
||||
jp intoDE
|
||||
|
||||
init:
|
||||
di
|
||||
ld hl, RAMEND
|
||||
ld sp, hl
|
||||
ld hl, ZASM_INPUT
|
||||
ld de, ZASM_OUTPUT
|
||||
call USER_CODE
|
||||
; signal the emulator we're done
|
||||
; BC contains the number of written bytes
|
||||
ld a, c
|
||||
ld c, b
|
||||
out (c), a
|
||||
halt
|
||||
|
||||
#include "core.asm"
|
@ -1,81 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "libz80/z80.h"
|
||||
#include "kernel.h"
|
||||
#include "zasm.h"
|
||||
|
||||
/* zasm is a "pure memory" application. It starts up being told memory location
|
||||
* to read and memory location to write.
|
||||
*
|
||||
* This program works be writing stdin in a specific location in memory, run
|
||||
* zasm in a special wrapper, wait until we receive the stop signal, then
|
||||
* spit the contents of the dest memory to stdout.
|
||||
*/
|
||||
|
||||
// in sync with glue.asm
|
||||
#define READFROM 0xa000
|
||||
#define WRITETO 0xd000
|
||||
#define ZASM_CODE_OFFSET 0x8000
|
||||
|
||||
static Z80Context cpu;
|
||||
static uint8_t mem[0xffff];
|
||||
static int running;
|
||||
// Number of bytes written to WRITETO
|
||||
// We receive that result from an OUT (C), A call. C contains LSB, A is MSB.
|
||||
static uint16_t written;
|
||||
|
||||
|
||||
static uint8_t io_read(int unused, uint16_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void io_write(int unused, uint16_t addr, uint8_t val)
|
||||
{
|
||||
written = ((addr & 0xff) << 8) + (val & 0xff);
|
||||
running = 0;
|
||||
}
|
||||
|
||||
static uint8_t mem_read(int unused, uint16_t addr)
|
||||
{
|
||||
return mem[addr];
|
||||
}
|
||||
|
||||
static void mem_write(int unused, uint16_t addr, uint8_t val)
|
||||
{
|
||||
mem[addr] = val;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// initialize memory
|
||||
for (int i=0; i<sizeof(KERNEL); i++) {
|
||||
mem[i] = KERNEL[i];
|
||||
}
|
||||
for (int i=0; i<sizeof(ZASM); i++) {
|
||||
mem[i+ZASM_CODE_OFFSET] = ZASM[i];
|
||||
}
|
||||
int ptr = READFROM;
|
||||
int c = getchar();
|
||||
while (c != EOF) {
|
||||
mem[ptr] = c;
|
||||
ptr++;
|
||||
c = getchar();
|
||||
}
|
||||
// Run!
|
||||
running = 1;
|
||||
Z80RESET(&cpu);
|
||||
cpu.ioRead = io_read;
|
||||
cpu.ioWrite = io_write;
|
||||
cpu.memRead = mem_read;
|
||||
cpu.memWrite = mem_write;
|
||||
|
||||
while (running) {
|
||||
Z80Execute(&cpu);
|
||||
}
|
||||
|
||||
for (int i=0; i<written; i++) {
|
||||
putchar(mem[WRITETO+i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
#include "user.inc"
|
||||
; *** Requirements ***
|
||||
; JUMP_STRNCMP
|
||||
; JUMP_ADDDE
|
||||
; JUMP_UPCASE
|
||||
; JUMP_UNSETZ
|
||||
; JUMP_INTODE
|
||||
|
||||
; *** Code ***
|
||||
.org USER_CODE
|
||||
|
||||
; Parse asm file in (HL) and outputs its upcodes in (DE). Returns the number
|
||||
; of bytes written in C.
|
||||
main:
|
||||
|
6
apps/zasm/tests/Makefile
Normal file
6
apps/zasm/tests/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
EMULDIR = ../../../tools/emul
|
||||
|
||||
.PHONY: run
|
||||
run:
|
||||
make -C $(EMULDIR) zasm
|
||||
./runtests.sh
|
@ -4,7 +4,7 @@ set -e
|
||||
|
||||
TMPFILE=$(mktemp)
|
||||
SCAS=scas
|
||||
ZASM=../emul/zasm
|
||||
ZASM=../../../tools/emul/zasm
|
||||
ASMFILE=../instr.asm
|
||||
|
||||
cmpas() {
|
||||
|
4
tools/emul/.gitignore
vendored
4
tools/emul/.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
/shell
|
||||
/shell-kernel.h
|
||||
/zasm
|
||||
/*-kernel.h
|
||||
/*-user.h
|
||||
|
@ -1,10 +1,20 @@
|
||||
TARGETS = shell zasm
|
||||
KERNEL_HEADERS = shell-kernel.h zasm-kernel.h
|
||||
|
||||
.PHONY: all
|
||||
all: shell
|
||||
all: $(TARGETS)
|
||||
|
||||
shell-kernel.h: shell_.asm
|
||||
scas -o - -I ../../parts/z80 $< | ./bin2c.sh SHELL_KERNEL | tee $@ > /dev/null
|
||||
zasm-kernel.h: zasm_glue.asm
|
||||
$(KERNEL_HEADERS):
|
||||
scas -o - -I ../../parts/z80 $< | ./bin2c.sh KERNEL | tee $@ > /dev/null
|
||||
|
||||
zasm-user.h: zasm_user.asm
|
||||
scas -o - -I ../../apps/zasm $< | ./bin2c.sh USERSPACE | tee $@ > /dev/null
|
||||
|
||||
shell: shell.c libz80/libz80.o shell-kernel.h
|
||||
zasm: zasm.c libz80/libz80.o zasm-kernel.h zasm-user.h
|
||||
$(TARGETS):
|
||||
cc $< libz80/libz80.o -o $@
|
||||
|
||||
libz80/libz80.o: libz80/z80.c
|
||||
@ -13,4 +23,4 @@ libz80/libz80.o: libz80/z80.c
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm shell shell-kernel.h
|
||||
rm -f $(TARGETS) $(KERNEL_HEADERS)
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
// in sync with shell.asm
|
||||
#define RAMSTART 0x4000
|
||||
#define STDIO_PORT 0x00
|
||||
#define STDIN_ST_PORT 0x01
|
||||
|
||||
@ -79,8 +78,8 @@ int main()
|
||||
|
||||
|
||||
// initialize memory
|
||||
for (int i=0; i<sizeof(SHELL_KERNEL); i++) {
|
||||
mem[i] = SHELL_KERNEL[i];
|
||||
for (int i=0; i<sizeof(KERNEL); i++) {
|
||||
mem[i] = KERNEL[i];
|
||||
}
|
||||
// Run!
|
||||
running = 1;
|
||||
|
84
tools/emul/zasm.c
Normal file
84
tools/emul/zasm.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "libz80/z80.h"
|
||||
#include "zasm-kernel.h"
|
||||
#include "zasm-user.h"
|
||||
|
||||
/* zasm is a "pure memory" application. It starts up being told memory location
|
||||
* to read and memory location to write.
|
||||
*
|
||||
*
|
||||
* Memory layout:
|
||||
*
|
||||
* 0x0000 - 0x3fff: ROM code from zasm_glue.asm
|
||||
* 0x4000 - 0xffff: Userspace
|
||||
*
|
||||
* I/O Ports:
|
||||
*
|
||||
* 0 - stdin / stdout
|
||||
*/
|
||||
|
||||
// in sync with zasm_glue.asm
|
||||
#define USER_CODE 0x4000
|
||||
#define STDIO_PORT 0x00
|
||||
|
||||
static Z80Context cpu;
|
||||
static uint8_t mem[0xffff];
|
||||
|
||||
static uint8_t io_read(int unused, uint16_t addr)
|
||||
{
|
||||
addr &= 0xff;
|
||||
if (addr == STDIO_PORT) {
|
||||
int c = getchar();
|
||||
if (c == EOF) {
|
||||
return 0;
|
||||
}
|
||||
return c;
|
||||
} else {
|
||||
fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void io_write(int unused, uint16_t addr, uint8_t val)
|
||||
{
|
||||
addr &= 0xff;
|
||||
if (addr == STDIO_PORT) {
|
||||
putchar(val);
|
||||
} else {
|
||||
fprintf(stderr, "Out of bounds I/O write: %d / %d\n", addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t mem_read(int unused, uint16_t addr)
|
||||
{
|
||||
return mem[addr];
|
||||
}
|
||||
|
||||
static void mem_write(int unused, uint16_t addr, uint8_t val)
|
||||
{
|
||||
mem[addr] = val;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// initialize memory
|
||||
for (int i=0; i<sizeof(KERNEL); i++) {
|
||||
mem[i] = KERNEL[i];
|
||||
}
|
||||
for (int i=0; i<sizeof(USERSPACE); i++) {
|
||||
mem[i+USER_CODE] = USERSPACE[i];
|
||||
}
|
||||
Z80RESET(&cpu);
|
||||
cpu.ioRead = io_read;
|
||||
cpu.ioWrite = io_write;
|
||||
cpu.memRead = mem_read;
|
||||
cpu.memWrite = mem_write;
|
||||
|
||||
while (!cpu.halted) {
|
||||
Z80Execute(&cpu);
|
||||
}
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
51
tools/emul/zasm_glue.asm
Normal file
51
tools/emul/zasm_glue.asm
Normal file
@ -0,0 +1,51 @@
|
||||
; Glue code for the emulated environment
|
||||
.equ USER_CODE 0x4000
|
||||
.equ RAMEND 0xffff
|
||||
.equ ZASM_INPUT 0xa000
|
||||
.equ ZASM_OUTPUT 0xd000
|
||||
.equ STDIO_PORT 0x00
|
||||
|
||||
jr init ; 2 bytes
|
||||
; *** JUMP TABLE ***
|
||||
jp strncmp
|
||||
jp addDE
|
||||
jp upcase
|
||||
jp unsetZ
|
||||
jp intoDE
|
||||
|
||||
init:
|
||||
di
|
||||
ld hl, RAMEND
|
||||
ld sp, hl
|
||||
ld hl, ZASM_INPUT
|
||||
; yes, this means that input can't have null bytes
|
||||
.inloop:
|
||||
in a, (STDIO_PORT)
|
||||
ld (hl), a ; before cond jr so we write a final \0
|
||||
or a
|
||||
jr z, .inloopend
|
||||
inc hl
|
||||
jr .inloop
|
||||
.inloopend:
|
||||
ld hl, ZASM_INPUT
|
||||
ld de, ZASM_OUTPUT
|
||||
call USER_CODE
|
||||
; BC contains the number of written bytes
|
||||
xor a
|
||||
cp b
|
||||
jr nz, .spit
|
||||
cp c
|
||||
jr z, .end ; no output
|
||||
.spit:
|
||||
ld hl, ZASM_OUTPUT
|
||||
.outloop:
|
||||
ld a, (hl)
|
||||
out (STDIO_PORT), a
|
||||
cpi ; a trick to inc HL and dec BC at the same time.
|
||||
; P/V indicates whether BC reached 0
|
||||
jp pe, .outloop ; BC is not zero, loop
|
||||
.end:
|
||||
; signal the emulator we're done
|
||||
halt
|
||||
|
||||
#include "core.asm"
|
@ -1,10 +1,9 @@
|
||||
RAMSTART .equ 0x8000
|
||||
RAMEND .equ 0xffff
|
||||
USER_CODE .equ RAMSTART
|
||||
|
||||
; *** JUMP TABLE ***
|
||||
JUMP_STRNCMP .equ 0x02
|
||||
JUMP_ADDDE .equ 0x05
|
||||
JUMP_UPCASE .equ 0x08
|
||||
JUMP_UNSETZ .equ 0x0b
|
||||
JUMP_INTODE .equ 0x0e
|
||||
|
||||
.org 0x4000
|
||||
#include "main.asm"
|
Loading…
Reference in New Issue
Block a user