1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 05:28:06 +11:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Virgil Dupras
57c1a10434 avra: first steps 2019-12-13 17:38:40 -05:00
Virgil Dupras
e691dab070 zasm: little drive-by optimization
Use IX directly for argspec rows instead of going through DE. It saves a bit
of processing. The code was this way because I initially didn't use IX at all,
so as code evolved, that DE translation stayed as an artifact.
2019-12-13 10:54:01 -05:00
16 changed files with 591 additions and 60 deletions

View File

@ -165,4 +165,17 @@ using `IX` and `IY` as 8-bit registers. We used to support them, but because
this makes our code incompatible with Z80-compatible CPUs such as the Z180, we this makes our code incompatible with Z80-compatible CPUs such as the Z180, we
prefer to avoid these in our code. prefer to avoid these in our code.
## AVR assembler
`zasm` can be configured, at compile time, to be a AVR assembler instead of a
z80 assembler. Directives, literals, symbols, they're all the same, it's just
instructions and their arguments that change.
Instructions and their arguments have a ayntax that is similar to other AVR
assemblers: registers are referred to as `rXX`, mnemonics are the same,
arguments are separated by commas.
To assemble an AVR assembler, use the `gluea.asm` file instead of the regular
one.
[libz80]: https://github.com/ggambetta/libz80 [libz80]: https://github.com/ggambetta/libz80

263
apps/zasm/avr.asm Normal file
View File

@ -0,0 +1,263 @@
; Same thing as instr.asm, but for AVR instructions
; *** Instructions table ***
; List of mnemonic names separated by a null terminator. Their index in the
; list is their ID. Unlike in zasm, not all mnemonics have constant associated
; to it because it's generally not needed. This list is grouped by argument
; categories, and then alphabetically. Categories are ordered so that the 8bit
; opcodes come first, then the 16bit ones. 0xff ends the chain
instrNames:
; Rd(5) + Rr(5)
.equ I_ADC 0
.db "ADC", 0
.db "ADD", 0
.db "AND", 0
.db "CLR", 0
.db "CP", 0
.db "CPC", 0
.db "CPSE", 0
.db "EOR", 0
.db "MOV", 0
.db "MUL", 0
.db "OR", 0
.db "SBC", 0
.db "SUB", 0
; no arg
.equ I_BREAK 13
.db "BREAK", 0
.db "CLC", 0
.db "CLH", 0
.db "CLI", 0
.db "CLN", 0
.db "CLS", 0
.db "CLT", 0
.db "CLV", 0
.db "CLZ", 0
.db "EICALL", 0
.db "EIJMP", 0
.db "ICALL", 0
.db "IJMP", 0
.db "NOP", 0
.db "RET", 0
.db "RETI", 0
.db "SEC", 0
.db "SEH", 0
.db "SEI", 0
.db "SEN", 0
.db "SES", 0
.db "SET", 0
.db "SEV", 0
.db "SEZ", 0
.db "SLEEP", 0
.db "WDR", 0
; Rd(5)
.equ I_ASR 39
.db "ASR", 0
.db "COM", 0
.db "DEC", 0
.db "INC", 0
.db "LAC", 0
.db "LAS", 0
.db "LAT", 0
.db "LSR", 0
.db "NEG", 0
.db "POP", 0
.db "PUSH", 0
.db "ROR", 0
.db "SWAP", 0
.db "XCH", 0
.db 0xff
; 8-bit constant masks associated with each instruction. In the same order as
; in instrNames
instrUpMasks1:
; Rd(5) + Rd(5): XXXXXXrd ddddrrrr
.db 0b00011100 ; ADC
.db 0b00001100 ; ADD
.db 0b00100000 ; AND
.db 0b00100100 ; CLR
.db 0b00010100 ; CP
.db 0b00000100 ; CPC
.db 0b00010000 ; CPSE
.db 0b00100100 ; EOR
.db 0b00101100 ; MOV
.db 0b10011100 ; MUL
.db 0b00101000 ; OR
.db 0b00001000 ; SBC
.db 0b00011000 ; SUB
; 16-bit constant masks associated with each instruction. In the same order as
; in instrNames
instrUpMasks2:
; no arg
.db 0b10010101, 0b10011000 ; BREAK
.db 0b10010100, 0b10001000 ; CLC
.db 0b10010100, 0b11011000 ; CLH
.db 0b10010100, 0b11111000 ; CLI
.db 0b10010100, 0b10101000 ; CLN
.db 0b10010100, 0b11001000 ; CLS
.db 0b10010100, 0b11101000 ; CLT
.db 0b10010100, 0b10111000 ; CLV
.db 0b10010100, 0b10011000 ; CLZ
.db 0b10010101, 0b00011001 ; EICALL
.db 0b10010100, 0b00011001 ; EIJMP
.db 0b10010101, 0b00001001 ; ICALL
.db 0b10010100, 0b00001001 ; IJMP
.db 0b00000000, 0b00000000 ; NOP
.db 0b10010101, 0b00001000 ; RET
.db 0b10010101, 0b00011000 ; RETI
.db 0b10010100, 0b00001000 ; SEC
.db 0b10010100, 0b01011000 ; SEH
.db 0b10010100, 0b01111000 ; SEI
.db 0b10010100, 0b00101000 ; SEN
.db 0b10010100, 0b01001000 ; SES
.db 0b10010100, 0b01101000 ; SET
.db 0b10010100, 0b00111000 ; SEV
.db 0b10010100, 0b00011000 ; SEZ
.db 0b10010101, 0b10001000 ; SLEEP
.db 0b10010101, 0b10101000 ; WDR
; Rd(5): XXXXXXXd ddddXXXX
.db 0b10010100, 0b00000101 ; ASR
.db 0b10010100, 0b00000000 ; COM
.db 0b10010100, 0b00001010 ; DEC
.db 0b10010100, 0b00000011 ; INC
.db 0b10010010, 0b00000110 ; LAC
.db 0b10010010, 0b00000101 ; LAS
.db 0b10010010, 0b00000111 ; LAT
.db 0b10010100, 0b00000110 ; LSR
.db 0b10010100, 0b00000001 ; NEG
.db 0b10010000, 0b00001111 ; POP
.db 0b10010010, 0b00001111 ; PUSH
.db 0b10010100, 0b00000111 ; ROR
.db 0b10010100, 0b00000010 ; SWAP
.db 0b10010010, 0b00000100 ; XCH
; Same signature as getInstID in instr.asm
; Reads string in (HL) and returns the corresponding ID (I_*) in A. Sets Z if
; there's a match.
getInstID:
push bc
push hl
push de
ex de, hl ; DE makes a better needle
; haystack. -1 because we inc HL at the beginning of the loop
ld hl, instrNames-1
ld b, 0xff ; index counter
.loop:
inc b
inc hl
ld a, (hl)
inc a ; check if 0xff
jr z, .notFound
call strcmpIN
jr nz, .loop
; found!
ld a, b ; index
cp a ; ensure Z
.end:
pop de
pop hl
pop bc
ret
.notFound:
dec a ; unset Z
jr .end
; Same signature as parseInstruction in instr.asm
; Parse instruction specified in A (I_* const) with args in I/O and write
; resulting opcode(s) in I/O.
; Sets Z on success. On error, A contains an error code (ERR_*)
parseInstruction:
; BC, during .spit, is ORred to the spitted opcode.
ld bc, 0
cp I_BREAK
jr c, .spitRd5Rr5
cp I_ASR
jr c, .spitNoArg
; spitRd5
ld d, a ; save A for later
call .readR5
ret nz
call .placeRd
ld a, d ; restore A
; continue to .spitNoArg
.spitNoArg:
call .getUp2
jr .spit
.spitRd5Rr5:
ld d, a ; save A for later
call .readR5
ret nz
call .placeRd
call readComma
call .readR5
ret nz
push af ; --> lvl 1
; let's start with the 4 lower bits
and 0xf
or c
; We now have our LSB in A. Let's spit it now.
call ioPutB
pop af ; <-- lvl 1
; and now that last high bit, currently bit 4, which must become bit 1
and 0b00010000
rra \ rra \ rra
or b
ld b, a
ld a, d ; restore A
ld hl, instrUpMasks1
call addHL
; now that's our MSB
jr .spitMSB
.spit:
; LSB is spit *before* MSB
inc hl
ld a, (hl)
or c
call ioPutB
dec hl
.spitMSB:
ld a, (hl)
or b
call ioPutB
xor a ; ensure Z, set success
ret
; local routines
; place number in A in BC at position .......d dddd....
; BC is assumed to be 0
.placeRd:
sla a \ rla \ rla \ rla ; last RLA might set carry
rl b
ld c, a
ret
; Fetch a 16-bit upcode specified by instr index in A and set that upcode in HL
.getUp2:
sub I_BREAK
sla a ; A * 2
ld hl, instrUpMasks2
jp addHL
; read a rXX argument and return register number in A.
; Set Z for success.
.readR5:
call readWord
ld a, (hl)
call upcase
cp 'R'
ret nz ; not a register
inc hl
call parseDecimal
ret nz
push ix \ pop hl
ld a, h
or a
ret nz ; should be zero
ld a, l
cp 32
jp nc, unsetZ ; must be < 32
; we're good!
cp a ; ensure Z
ret

134
apps/zasm/avr.txt Normal file
View File

@ -0,0 +1,134 @@
The AVR instruction set is a bit more regular than z80's, which allows us for
simpler upcode spitting logic (simplicity which is lost when we need to take
into account all AVR models and instruction constraints on each models). This
file categorizes all available ops with their opcode signature. X means upcode
bit.
Categories are in descending order of "popularity"
Mnemonics with "*" are a bit special.
### 16-bit
## Plain
XXXX XXXX XXXX XXXX
BREAK, CLC, CLH, CLI, CLN, CLS, CLT, CLV, CLZ, EICALL, EIJMP, ELPM*, ICALL,
IJMP, NOP, RET, RETI, SEC, SEH, SEI, SEN, SES, SET, SEV, SEZ, SLEEP, SPM*, WDR
## Rd(5)
XXXX XXXd dddd XXXX
ASR, COM, DEC, ELPM*, INC, LAC, LAS, LAT, LD*, LPM*, LSR, NEG, POP, PUSH, ROR,
ST*, SWAP, XCH
## Rd(5) + Rr(5)
XXXX XXrd dddd rrrr
ADC, ADD, AND, CLR, CP, CPC, CPSE, EOR, MOV, MUL, OR, ROL*, SBC, SUB,
TST*
## k(7)
XXXX XXkk kkkk kXXX
BRCC, BRCS, BREQ, BRGE, BRHC, BRHS, BRID, BRIE, BRLO, BRLT, BRMI, BRNE, BRPL,
BRSH, BRTC, BRTS, BRVC, BRVS
## Rd(4) + K(8)
XXXX KKKK dddd KKKK
ANDI, CBR*, CPI, LDI, ORI, SBCI, SBR, SUBI
## Rd(5) + bit
XXXX XXXd dddd Xbbb
BLD, BST, SBRC, SBRS
## A(5) + bit
XXXX XXXX AAAA Abbb
CBI, SBI, SBIC, SBIS
## Rd(3) + Rr(3)
XXXX XXXX Xddd Xrrr
FMUL, FMULS, FMULSU, MULSU
## Rd(4) + Rr(4)
XXXX XXXX dddd rrrr
MOVW, MULS
## Rd(5) + A(6)
XXXX XAAd dddd AAAA
IN, OUT
## Rd(4) + k(7)
XXXX Xkkk dddd kkkk
LDS*, STS*
## Rd(2) + K
XXXX XXXX KKdd KKKK
ADIW, SBIW
## Rd(4)
XXXX XXXX dddd XXXX
SER
## K(4)
XXXX XXXX KKKK XXXX
DES
## k(12)
XXXX kkkk kkkk kkkk
RCALL, RJMP
## SREG
XXXX XXXX Xsss XXXX
BCLR, BSET
## SREG + k(7)
XXXX XXkk kkkk ksss
BRBC, BRBS
### 32-bit
## k(22)
XXXX XXXk kkkk XXXk
kkkk kkkk kkkk kkkk
CALL, JMP
## Rd(5) + k(16)
XXXX XXXd dddd XXXX
kkkk kkkk kkkk kkkk
LDS*, STS*

45
apps/zasm/gluea.asm Normal file
View File

@ -0,0 +1,45 @@
; avra
;
; This glue code assembles as assembler for AVR microcontrollers. It looks a
; lot like zasm, but it spits AVR binary. Comments have been stripped, refer
; to glue.asm for details.
.inc "user.h"
; *** Overridable consts ***
.equ ZASM_REG_MAXCNT 0xff
.equ ZASM_LREG_MAXCNT 0x20
.equ ZASM_REG_BUFSZ 0x700
.equ ZASM_LREG_BUFSZ 0x100
; ******
.inc "err.h"
.inc "ascii.h"
.inc "blkdev.h"
.inc "fs.h"
jp zasmMain
.inc "core.asm"
.inc "zasm/const.asm"
.inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm"
.inc "lib/args.asm"
.inc "zasm/util.asm"
.equ IO_RAMSTART USER_RAMSTART
.inc "zasm/io.asm"
.equ TOK_RAMSTART IO_RAMEND
.inc "zasm/tok.asm"
.inc "zasm/avr.asm"
.equ DIREC_RAMSTART TOK_RAMEND
.inc "zasm/directive.asm"
.inc "zasm/parse.asm"
.equ EXPR_PARSE parseNumberOrSymbol
.inc "lib/expr.asm"
.equ SYM_RAMSTART DIREC_RAMEND
.inc "zasm/symbol.asm"
.equ ZASM_RAMSTART SYM_RAMEND
.inc "zasm/main.asm"
USER_RAMSTART:

View File

@ -417,26 +417,6 @@ matchArg:
dec hl dec hl
ret ret
; Compare primary row at (DE) with ID in A. Sets Z flag if there's a match.
matchPrimaryRow:
push hl
push ix
push de \ pop ix
cp (ix)
jr nz, .end
; name matches, let's see the rest
ld hl, INS_CURARG1
ld a, (ix+1)
call matchArg
jr nz, .end
ld hl, INS_CURARG2
ld a, (ix+2)
call matchArg
.end:
pop ix
pop hl
ret
; *** Special opcodes *** ; *** Special opcodes ***
; The special upcode handling routines below all have the same signature. ; The special upcode handling routines below all have the same signature.
; Instruction row is at IX and we're expected to perform the same task as ; Instruction row is at IX and we're expected to perform the same task as
@ -574,16 +554,13 @@ handleRST:
ld c, 0 ld c, 0
ret ret
; Compute the upcode for argspec row at (DE) and arguments in curArg{1,2} and ; Compute the upcode for argspec row at (IX) and arguments in curArg{1,2} and
; writes the resulting upcode to IO. ; writes the resulting upcode to IO.
; A is zero, with Z set, on success. A is non-zero, with Z unset, on error. ; A is zero, with Z set, on success. A is non-zero, with Z unset, on error.
spitUpcode: spitUpcode:
push ix
push de push de
push hl push hl
push bc push bc
; First, let's go in IX mode. It's easier to deal with offsets here.
push de \ pop ix
; before we begin, are we in a 'l' argspec? Is it flagged for IX/IY ; before we begin, are we in a 'l' argspec? Is it flagged for IX/IY
; acceptance? If yes, a 'x' or 'y' instruction? Check this on both ; acceptance? If yes, a 'x' or 'y' instruction? Check this on both
@ -823,7 +800,6 @@ spitUpcode:
pop bc pop bc
pop hl pop hl
pop de pop de
pop ix
ret ret
.checkCB: .checkCB:
ld a, (INS_UPCODE) ld a, (INS_UPCODE)
@ -876,7 +852,7 @@ parseInstruction:
push bc push bc
push hl push hl
push de push de
; A is reused in matchPrimaryRow but that register is way too changing. ; A is reused in .matchPrimaryRow but that register is way too changing.
; Let's keep a copy in a more cosy register. ; Let's keep a copy in a more cosy register.
ld c, a ld c, a
xor a xor a
@ -899,24 +875,24 @@ parseInstruction:
; To speed up things a little, we use a poor man's indexing. Full ; To speed up things a little, we use a poor man's indexing. Full
; bisecting would involve too much complexity. ; bisecting would involve too much complexity.
ld a, c ; recall A param ld a, c ; recall A param
ld de, instrTBl ld ix, instrTBl
cp I_EX cp I_EX
jr c, .loop jr c, .loop
ld de, instrTBlEX ld ix, instrTBlEX
cp I_LD cp I_LD
jr c, .loop jr c, .loop
ld de, instrTBlLD ld ix, instrTBlLD
cp I_RET cp I_RET
jr c, .loop jr c, .loop
ld de, instrTBlRET ld ix, instrTBlRET
.loop: .loop:
ld a, c ; recall A param ld a, c ; recall A param
call matchPrimaryRow call .matchPrimaryRow
jr z, .match jr z, .match
ld a, INSTR_TBL_ROWSIZE ld de, INSTR_TBL_ROWSIZE
call addDE add ix, de
ld a, (de) ld a, 0xff
cp 0xff cp (ix)
jr nz, .loop jr nz, .loop
; No signature match ; No signature match
ld a, ERR_BAD_ARG ld a, ERR_BAD_ARG
@ -936,6 +912,19 @@ parseInstruction:
pop bc pop bc
ret ret
; Compare primary row at (IX) with ID in A. Sets Z flag if there's a match.
.matchPrimaryRow:
cp (ix)
ret nz
; name matches, let's see the rest
ld hl, INS_CURARG1
ld a, (ix+1)
call matchArg
ret nz
ld hl, INS_CURARG2
ld a, (ix+2)
jp matchArg
; In instruction metadata below, argument types arge indicated with a single ; In instruction metadata below, argument types arge indicated with a single
; char mnemonic that is called "argspec". This is the table of correspondence. ; char mnemonic that is called "argspec". This is the table of correspondence.

View File

@ -76,6 +76,35 @@ strncmpI:
; early, set otherwise) ; early, set otherwise)
ret ret
; strcmp, then next. Same thing as strcmp, but case insensitive and if strings
; are not equal, make HL point to the character right after the null
; termination. We assume that the haystack (HL), has uppercase chars.
strcmpIN:
push de ; --> lvl 1
push hl ; --> lvl 2
.loop:
ld a, (de)
call upcase
cp (hl)
jr nz, .notFound ; not equal? break early.
or a ; If our chars are null, stop the cmp
jr z, .found
inc hl
inc de
jr .loop
.found:
pop hl ; <-- lvl 2
pop de ; <-- lvl 1
; Z already set
ret
.notFound:
; Not found, we skip the string
call strskip
pop de ; <-- lvl 2, junk
pop de ; <-- lvl 1
ret
; If string at (HL) starts with ( and ends with ), "enter" into the parens ; If string at (HL) starts with ( and ends with ), "enter" into the parens
; (advance HL and put a null char at the end of the string) and set Z. ; (advance HL and put a null char at the end of the string) and set Z.
; Otherwise, do nothing and reset Z. ; Otherwise, do nothing and reset Z.

View File

@ -1,6 +1,7 @@
/shell/shell /shell/shell
/bshell/shell /bshell/shell
/zasm/zasm /zasm/zasm
/zasm/avra
/runbin/runbin /runbin/runbin
/*/*-bin.h /*/*-bin.h
/*/*.bin /*/*.bin

View File

@ -3,6 +3,7 @@ TARGETS = shell/shell zasm/zasm runbin/runbin
KERNEL = ../../kernel KERNEL = ../../kernel
APPS = ../../apps APPS = ../../apps
ZASMBIN = zasm/zasm ZASMBIN = zasm/zasm
AVRABIN = zasm/avra
ZASMSH = ../zasm.sh ZASMSH = ../zasm.sh
SHELLAPPS = zasm ed SHELLAPPS = zasm ed
SHELLTGTS = ${SHELLAPPS:%=cfsin/%} SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
@ -10,7 +11,7 @@ CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
OBJS = emul.o libz80/libz80.o OBJS = emul.o libz80/libz80.o
.PHONY: all .PHONY: all
all: $(TARGETS) $(CFSIN_CONTENTS) all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS)
# -o in sync with SHELL_CODE in shell/glue.asm # -o in sync with SHELL_CODE in shell/glue.asm
shell/shell.bin: shell/glue.asm $(ZASMBIN) shell/shell.bin: shell/glue.asm $(ZASMBIN)
@ -19,18 +20,27 @@ shell/shell.bin: shell/glue.asm $(ZASMBIN)
shell/shell-bin.h: shell/shell.bin shell/shell-bin.h: shell/shell.bin
./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null ./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null
shell/shell: shell/shell.c $(OBJS) shell/shell-bin.h
$(CC) shell/shell.c $(OBJS) -o $@
zasm/kernel-bin.h: zasm/kernel.bin zasm/kernel-bin.h: zasm/kernel.bin
./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null ./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null
zasm/zasm-bin.h: zasm/zasm.bin zasm/zasm-bin.h: zasm/zasm.bin
./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null ./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null
shell/shell: shell/shell.c $(OBJS) shell/shell-bin.h
$(CC) shell/shell.c $(OBJS) -o $@
$(ZASMBIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK) $(ZASMBIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK)
$(CC) zasm/zasm.c $(OBJS) -o $@ $(CC) zasm/zasm.c $(OBJS) -o $@
zasm/avra.bin: $(ZASMBIN)
$(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/gluea.asm > $@
zasm/avra-bin.h: zasm/avra.bin
./bin2c.sh USERSPACE < zasm/avra.bin | tee $@ > /dev/null
$(AVRABIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/avra-bin.h
$(CC) -D AVRA zasm/zasm.c $(OBJS) -o $@
runbin/runbin: runbin/runbin.c $(OBJS) runbin/runbin: runbin/runbin.c $(OBJS)
$(CC) runbin/runbin.c $(OBJS) -o $@ $(CC) runbin/runbin.c $(OBJS) -o $@
@ -52,7 +62,7 @@ cfsin/user.h: shell/user.h
cp shell/user.h $@ cp shell/user.h $@
.PHONY: updatebootstrap .PHONY: updatebootstrap
updatebootstrap: $(ZASMBIN) $(INCCFS) updatebootstrap: $(ZASMBIN)
$(ZASMSH) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin $(ZASMSH) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
$(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin $(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin

View File

@ -60,6 +60,12 @@ Those binaries can be updated with the `make updatebootstrap` command. If they
are up-to date and that zasm isn't broken, this command should output the same are up-to date and that zasm isn't broken, this command should output the same
binary as before. binary as before.
## avra
In the `zasm` folder, there's also `avra` which is a zasm compiled as an AVR
assembler. It works the same way as zasm except it expects AVR mnemonics and
spits AVR binaries.
## runbin ## runbin
This is a very simple tool that reads binary z80 code from stdin, loads it in This is a very simple tool that reads binary z80 code from stdin, loads it in

View File

@ -3,7 +3,11 @@
#include <string.h> #include <string.h>
#include "../emul.h" #include "../emul.h"
#include "kernel-bin.h" #include "kernel-bin.h"
#ifdef AVRA
#include "avra-bin.h"
#else
#include "zasm-bin.h" #include "zasm-bin.h"
#endif
/* zasm reads from a specified blkdev, assemble the file and writes the result /* zasm reads from a specified blkdev, assemble the file and writes the result
* in another specified blkdev. In our emulator layer, we use stdin and stdout * in another specified blkdev. In our emulator layer, we use stdin and stdout

View File

@ -3,9 +3,10 @@ CFSPACK = ../cfspack/cfspack
.PHONY: run .PHONY: run
run: run:
$(MAKE) -C $(EMULDIR) zasm/zasm runbin/runbin shell/shell $(MAKE) -C $(EMULDIR) zasm/zasm zasm/avra runbin/runbin shell/shell
cd unit && ./runtests.sh cd unit && ./runtests.sh
cd zasm && ./runtests.sh cd zasm && ./runtests.sh
cd avra && ./runtests.sh
cd shell && ./runtests.sh cd shell && ./runtests.sh
$(CFSPACK): $(CFSPACK):

28
tools/tests/avra/runtests.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh -e
AVRA=../../emul/zasm/avra
cmpas() {
FN=$1
EXPECTED=$(xxd ${FN%.*}.expected)
ACTUAL=$(cat ${FN} | $AVRA | xxd)
if [ "$ACTUAL" = "$EXPECTED" ]; then
echo ok
else
echo actual
echo "$ACTUAL"
echo expected
echo "$EXPECTED"
exit 1
fi
}
if [ ! -z $1 ]; then
cmpas $1
exit 0
fi
for fn in *.asm; do
echo "Comparing ${fn}"
cmpas $fn
done

View File

@ -0,0 +1,5 @@
add r1, r31
ret
sleep
break
asr r20

View File

@ -0,0 +1 @@
ˆ˜•E•

View File

@ -1,4 +1,6 @@
#!/bin/sh -e #!/usr/bin/env bash
set -e
# TODO: find POSIX substitute to that PIPESTATUS thing
BASE=../../.. BASE=../../..
TOOLS=../.. TOOLS=../..

View File

@ -46,15 +46,15 @@ runTests:
halt halt
testSpitUpcode: testSpitUpcode:
ld ix, .t1 ld iy, .t1
call .test call .test
ld ix, .t2 ld iy, .t2
call .test call .test
ld ix, .t3 ld iy, .t3
call .test call .test
ld ix, .t4 ld iy, .t4
call .test call .test
ld ix, .t5 ld iy, .t5
call .test call .test
ret ret
@ -66,36 +66,36 @@ testSpitUpcode:
ld (SPITBOWL+1), a ld (SPITBOWL+1), a
ld (SPITBOWL+2), a ld (SPITBOWL+2), a
ld (SPITBOWL+3), a ld (SPITBOWL+3), a
push ix \ pop de push iy \ pop ix
call intoDE call intoIX
ld a, (ix+2) ld a, (iy+2)
ld (INS_CURARG1), a ld (INS_CURARG1), a
ld a, (ix+3) ld a, (iy+3)
ld (INS_CURARG1+1), a ld (INS_CURARG1+1), a
ld a, (ix+4) ld a, (iy+4)
ld (INS_CURARG1+2), a ld (INS_CURARG1+2), a
ld a, (ix+5) ld a, (iy+5)
ld (INS_CURARG2), a ld (INS_CURARG2), a
ld a, (ix+6) ld a, (iy+6)
ld (INS_CURARG2+1), a ld (INS_CURARG2+1), a
ld a, (ix+7) ld a, (iy+7)
ld (INS_CURARG2+2), a ld (INS_CURARG2+2), a
call spitUpcode call spitUpcode
jp nz, fail jp nz, fail
ld a, (SPITCNT) ld a, (SPITCNT)
cp (ix+8) cp (iy+8)
jp nz, fail jp nz, fail
ld a, (SPITBOWL) ld a, (SPITBOWL)
cp (ix+9) cp (iy+9)
jp nz, fail jp nz, fail
ld a, (SPITBOWL+1) ld a, (SPITBOWL+1)
cp (ix+10) cp (iy+10)
jp nz, fail jp nz, fail
ld a, (SPITBOWL+2) ld a, (SPITBOWL+2)
cp (ix+11) cp (iy+11)
jp nz, fail jp nz, fail
ld a, (SPITBOWL+3) ld a, (SPITBOWL+3)
cp (ix+12) cp (iy+12)
jp nz, fail jp nz, fail
jp nexttest jp nexttest