@@ -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 |
@@ -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 |
@@ -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* | |||||
@@ -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: | |||||
@@ -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. | ||||
@@ -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 | ||||
@@ -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 | ||||
@@ -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 | ||||
@@ -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 | ||||
@@ -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): | ||||
@@ -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 |
@@ -0,0 +1,5 @@ | |||||
add r1, r31 | |||||
ret | |||||
sleep | |||||
break | |||||
asr r20 |
@@ -0,0 +1 @@ | |||||
•ˆ•˜•E• |