mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 16: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 ***
|
; *** Code ***
|
||||||
.org USER_CODE
|
|
||||||
|
|
||||||
; Parse asm file in (HL) and outputs its upcodes in (DE). Returns the number
|
; Parse asm file in (HL) and outputs its upcodes in (DE). Returns the number
|
||||||
; of bytes written in C.
|
; of bytes written in C.
|
||||||
main:
|
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)
|
TMPFILE=$(mktemp)
|
||||||
SCAS=scas
|
SCAS=scas
|
||||||
ZASM=../emul/zasm
|
ZASM=../../../tools/emul/zasm
|
||||||
ASMFILE=../instr.asm
|
ASMFILE=../instr.asm
|
||||||
|
|
||||||
cmpas() {
|
cmpas() {
|
||||||
|
4
tools/emul/.gitignore
vendored
4
tools/emul/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
/shell
|
/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
|
.PHONY: all
|
||||||
all: shell
|
all: $(TARGETS)
|
||||||
|
|
||||||
shell-kernel.h: shell_.asm
|
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
|
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 $@
|
cc $< libz80/libz80.o -o $@
|
||||||
|
|
||||||
libz80/libz80.o: libz80/z80.c
|
libz80/libz80.o: libz80/z80.c
|
||||||
@ -13,4 +23,4 @@ libz80/libz80.o: libz80/z80.c
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm shell shell-kernel.h
|
rm -f $(TARGETS) $(KERNEL_HEADERS)
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// in sync with shell.asm
|
// in sync with shell.asm
|
||||||
#define RAMSTART 0x4000
|
|
||||||
#define STDIO_PORT 0x00
|
#define STDIO_PORT 0x00
|
||||||
#define STDIN_ST_PORT 0x01
|
#define STDIN_ST_PORT 0x01
|
||||||
|
|
||||||
@ -79,8 +78,8 @@ int main()
|
|||||||
|
|
||||||
|
|
||||||
// initialize memory
|
// initialize memory
|
||||||
for (int i=0; i<sizeof(SHELL_KERNEL); i++) {
|
for (int i=0; i<sizeof(KERNEL); i++) {
|
||||||
mem[i] = SHELL_KERNEL[i];
|
mem[i] = KERNEL[i];
|
||||||
}
|
}
|
||||||
// Run!
|
// Run!
|
||||||
running = 1;
|
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 TABLE ***
|
||||||
JUMP_STRNCMP .equ 0x02
|
JUMP_STRNCMP .equ 0x02
|
||||||
JUMP_ADDDE .equ 0x05
|
JUMP_ADDDE .equ 0x05
|
||||||
JUMP_UPCASE .equ 0x08
|
JUMP_UPCASE .equ 0x08
|
||||||
JUMP_UNSETZ .equ 0x0b
|
JUMP_UNSETZ .equ 0x0b
|
||||||
JUMP_INTODE .equ 0x0e
|
JUMP_INTODE .equ 0x0e
|
||||||
|
|
||||||
|
.org 0x4000
|
||||||
|
#include "main.asm"
|
Loading…
Reference in New Issue
Block a user