From 404dbf4e0b144d60a2e106ef2b32cab556436f62 Mon Sep 17 00:00:00 2001 From: michaelh Date: Sun, 6 Feb 2000 19:07:10 +0000 Subject: [PATCH] * Improved the pop params code * dhry.c now compiles and links for the z80 * Added simple z80 lib files and a stub strings.c git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@69 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- device/lib/z80/Makefile | 25 +++ device/lib/z80/crt0.s | 32 ++++ device/lib/z80/div.s | 318 +++++++++++++++++++++++++++++++ device/lib/z80/mul.s | 78 ++++++++ device/lib/z80/putchar.s | 13 ++ src/z80/gen.c | 18 +- src/z80/main.c | 1 + support/tests/dhrystone/Makefile | 22 ++- support/tests/dhrystone/dhry.c | 2 +- support/tests/dhrystone/dhry.h | 32 ++-- 10 files changed, 515 insertions(+), 26 deletions(-) create mode 100644 device/lib/z80/Makefile create mode 100644 device/lib/z80/crt0.s create mode 100644 device/lib/z80/div.s create mode 100644 device/lib/z80/mul.s create mode 100644 device/lib/z80/putchar.s diff --git a/device/lib/z80/Makefile b/device/lib/z80/Makefile new file mode 100644 index 00000000..41151374 --- /dev/null +++ b/device/lib/z80/Makefile @@ -0,0 +1,25 @@ +# libc/z80 Makefile + +TOPDIR = ../../.. + +SCC = $(TOPDIR)/bin/sdcc -mz80 +SAS = as-z80 + +OBJ = div.o mul.o putchar.o string.o +LIB = z80.lib +CC = $(SCC) +AS = $(SAS) +CFLAGS = -I../include -I. + +all: $(LIB) crt0.o + +$(LIB): $(OBJ) Makefile _dummy + rm -f $(LIB) + for i in $(OBJ); do echo $$i >> $(LIB); done + +_dummy: + +clean: + rm -f $(OBJ) *~ $(CLEANSPEC) + + diff --git a/device/lib/z80/crt0.s b/device/lib/z80/crt0.s new file mode 100644 index 00000000..dee48ca5 --- /dev/null +++ b/device/lib/z80/crt0.s @@ -0,0 +1,32 @@ + ;; Generic crt0.s for a Z80 + .globl __main + + .area _HEADER (ABS) + ;; Reset vector + .org 0 + jp init + + .org 0x38 + reti + + .org 0x150 +init: + ;; Stack at the top of memory. + ld sp,#0xffff + + ;; Use _main instead of main to bypass sdcc's intelligence + call __main + jp _exit + + ;; Ordering of segments for the linker. + .area _CODE + .area _DATA + + .area _CODE +_exit:: + ;; Exit - special code to the emulator + ld a,#0 + out (1),a +1$: + halt + jr 1$ diff --git a/device/lib/z80/div.s b/device/lib/z80/div.s new file mode 100644 index 00000000..5917c24a --- /dev/null +++ b/device/lib/z80/div.s @@ -0,0 +1,318 @@ + ;; Originally from GBDK by Pascal Felber. + .area _CODE + +__divschar:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld e,9(ix) + call .div8 + + ld l,c + + pop ix + pop bc + pop de + ret + +__modschar:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld e,9(ix) + call .div8 + + ld l,e + + pop ix + pop bc + pop de + ret + +__divsint:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld b,9(ix) + ld e,10(ix) + ld d,11(ix) + call .div16 + + ld l,c + ld h,b + + pop ix + pop bc + pop de + ret + +__modsint:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld b,9(ix) + ld e,10(ix) + ld d,11(ix) + call .div16 + + ld l,e + ld h,d + + pop ix + pop bc + pop de + ret + + ;; Unsigned +__divuchar:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld e,9(ix) + call .divu8 + + ld l,c + + pop ix + pop bc + pop de + ret + +__moduchar:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld e,9(ix) + call .divu8 + + ld l,e + + pop ix + pop bc + pop de + ret + +__divuint:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld b,9(ix) + ld e,10(ix) + ld d,11(ix) + call .divu16 + + ld l,c + ld h,b + + pop ix + pop bc + pop de + ret + +__moduint:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld b,9(ix) + ld e,10(ix) + ld d,11(ix) + call .divu16 + + ld l,e + ld h,d + + pop ix + pop bc + pop de + ret + +.div8:: +.mod8:: + LD A,C ; Sign extend + RLCA + SBC A + LD B,A + LD A,E ; Sign extend + RLCA + SBC A + LD D,A + + ; Fall through to .div16 + + ;; 16-bit division + ;; + ;; Entry conditions + ;; BC = dividend + ;; DE = divisor + ;; + ;; Exit conditions + ;; BC = quotient + ;; DE = remainder + ;; If divisor is non-zero, carry=0 + ;; If divisor is 0, carry=1 and both quotient and remainder are 0 + ;; + ;; Register used: AF,BC,DE,HL +.div16:: +.mod16:: + ;; Determine sign of quotient by xor-ing high bytes of dividend + ;; and divisor. Quotient is positive if signs are the same, negative + ;; if signs are different + ;; Remainder has same sign as dividend + LD A,B ; Get high byte of dividend + LD (.srem),A ; Save as sign of remainder + XOR D ; Xor with high byte of divisor + LD (.squot),A ; Save sign of quotient + ;; Take absolute value of divisor + BIT 7,D + JR Z,.chkde ; Jump if divisor is positive + SUB A ; Substract divisor from 0 + SUB E + LD E,A + SBC A ; Propagate borrow (A=0xFF if borrow) + SUB D + LD D,A + ;; Take absolute value of dividend +.chkde: + BIT 7,B + JR Z,.dodiv ; Jump if dividend is positive + SUB A ; Substract dividend from 0 + SUB C + LD C,A + SBC A ; Propagate borrow (A=0xFF if borrow) + SUB B + LD B,A + ;; Divide absolute values +.dodiv: + CALL .divu16 + RET C ; Exit if divide by zero + ;; Negate quotient if it is negative + LD A,(.squot) + AND #0x80 + JR Z,.dorem ; Jump if quotient is positive + SUB A ; Substract quotient from 0 + SUB C + LD C,A + SBC A ; Propagate borrow (A=0xFF if borrow) + SUB B + LD B,A +.dorem: + ;; Negate remainder if it is negative + LD A,(.srem) + AND #0x80 + RET Z ; Return if remainder is positive + SUB A ; Substract remainder from 0 + SUB E + LD E,A + SBC A ; Propagate remainder (A=0xFF if borrow) + SUB D + LD D,A + RET + +.divu8:: +.modu8:: + LD B,#0x00 + LD D,B + ; Fall through to divu16 + +.divu16:: +.modu16:: + ;; Check for division by zero + LD A,E + OR D + JR NZ,.divide ; Branch if divisor is non-zero + LD BC,#0x00 ; Divide by zero error + LD D,B + LD E,C + SCF ; Set carry, invalid result + RET +.divide: + LD L,C ; L = low byte of dividend/quotient + LD H,B ; H = high byte of dividend/quotient + LD BC,#0x00 ; BC = remainder + OR A ; Clear carry to start + LD A,#16 ; 16 bits in dividend +.dvloop: + ;; Shift next bit of quotient into bit 0 of dividend + ;; Shift next MSB of dividend into LSB of remainder + ;; BC holds both dividend and quotient. While we shift a bit from + ;; MSB of dividend, we shift next bit of quotient in from carry + ;; HL holds remainder + ;; Do a 32-bit left shift, shifting carry to L, L to H, + ;; H to C, C to B + LD (.dcnt),A + RL L ; Carry (next bit of quotient) to bit 0 + RL H ; Shift remaining bytes + RL C + RL B ; Clears carry since BC was 0 + ;; If remainder is >= divisor, next bit of quotient is 1. This + ;; bit goes to carry + PUSH BC ; Save current remainder + LD A,C ; Substract divisor from remainder + SBC E + LD C,A + LD A,B + SBC D + LD B,A + CCF ; Complement borrow so 1 indicates a + ; successful substraction (this is the + ; next bit of quotient) + JR C,.drop ; Jump if remainder is >= dividend + POP BC ; Otherwise, restore remainder + JR .nodrop +.drop: + INC SP + INC SP +.nodrop: + LD A,(.dcnt) + DEC A ; DEC does not affect carry flag + JR NZ,.dvloop + ;; Shift last carry bit into quotient + LD D,B ; DE = remainder + LD E,C + RL L ; Carry to L + LD C,L ; C = low byte of quotient + RL H + LD B,H ; B = high byte of quotient + OR A ; Clear carry, valid result + RET + + .area _BSS + +.srem: + .ds 0x01 ; Sign of quotient +.squot: + .ds 0x01 ; Sign of remainder +.dcnt: + .ds 0x01 ; Counter for division diff --git a/device/lib/z80/mul.s b/device/lib/z80/mul.s new file mode 100644 index 00000000..57c06a91 --- /dev/null +++ b/device/lib/z80/mul.s @@ -0,0 +1,78 @@ + ;; Originally from GBDK by Pascal Felber. + + .area _CODE +__mulschar:: +__muluchar:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld e,9(ix) + call .mulu8 + + pop ix + pop bc + pop de + ret + +__mulsint:: +__muluint:: + push de + push bc + push ix + ld ix,#0 + add ix,sp + + ld c,8(ix) + ld b,9(ix) + ld e,10(ix) + ld d,11(ix) + call .mulu16 + + pop ix + pop bc + pop de + ret + +.mul8: +.mulu8: + LD B,#0x00 ; Sign extend is not necessary with mul + LD D,B + ; Fall through + + ;; 16-bit multiplication + ;; + ;; Entry conditions + ;; BC = multiplicand + ;; DE = multiplier + ;; + ;; Exit conditions + ;; DE = less significant word of product + ;; + ;; Register used: AF,BC,DE,HL +.mul16: +.mulu16: + LD HL,#0x00 ; Product = 0 + LD A,#15 ; Count = bit length - 1 + ;; Shift-and-add algorithm + ;; If MSB of multiplier is 1, add multiplicand to partial product + ;; Shift partial product, multiplier left 1 bit +.mlp: + SLA E ; Shift multiplier left 1 bit + RL D + JR NC,.mlp1 ; Jump if MSB of multiplier = 0 + ADD HL,BC ; Add multiplicand to partial product +.mlp1: + ADD HL,HL ; Shift partial product left + DEC A + JR NZ,.mlp ; Continue until count = 0 + ;; Add multiplicand one last time if MSB of multiplier is 1 + BIT 7,D ; Get MSB of multiplier + JR Z,.mend ; Exit if MSB of multiplier is 0 + ADD HL,BC ; Add multiplicand to product +.mend: + RET ; HL = result + diff --git a/device/lib/z80/putchar.s b/device/lib/z80/putchar.s new file mode 100644 index 00000000..2b8fa688 --- /dev/null +++ b/device/lib/z80/putchar.s @@ -0,0 +1,13 @@ + .area _CODE +_putchar:: + push ix + ld ix,#0 + add ix,sp + + ld a,4(ix) + out (0xff),a + + pop ix + ret + + diff --git a/src/z80/gen.c b/src/z80/gen.c index 625ea103..fef18979 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -1097,13 +1097,19 @@ static void emitCall (iCode *ic, bool ispcall) /* adjust the stack for parameters if required */ if (IC_LEFT(ic)->parmBytes) { int i = IC_LEFT(ic)->parmBytes; - /* PENDING: do better */ - while (i>1) { - emitcode("pop", "hl"); - i-=2; + if (i>6) { + emitcode("ld", "hl,#%d", i); + emitcode("add", "hl,sp"); + emitcode("ld", "sp,hl"); + } + else { + while (i>1) { + emitcode("pop", "hl"); + i-=2; + } + if (i) + emitcode("inc", "sp"); } - if (i) - emitcode("inc", "sp"); } } diff --git a/src/z80/main.c b/src/z80/main.c index cc416fa2..5378f7be 100644 --- a/src/z80/main.c +++ b/src/z80/main.c @@ -37,6 +37,7 @@ static const char *_z80_getRegName(struct regs *reg) { if (reg) return reg->name; + assert(0); return "err"; } diff --git a/support/tests/dhrystone/Makefile b/support/tests/dhrystone/Makefile index f97747e5..d55569e6 100644 --- a/support/tests/dhrystone/Makefile +++ b/support/tests/dhrystone/Makefile @@ -1,10 +1,26 @@ # Simple Makefile for dhrystone and sdcc -CC = /home/michaelh/projects/sdcc/bin/sdcc -mz80 -v -CFLAGS = -DREG= -DNOSTRUCTASSIGN -DNOENUM +CC = /home/michaelh/projects/sdcc/bin/sdcc +# -DNOENUM is here to make the results more predictable +CFLAGS = -mz80 -v +CFLAGS += -DREG= -DNOSTRUCTASSIGN -DNOENUM +LIBDIR = /home/michaelh/projects/sdcc/device/lib/z80/ +LD = link-z80 + +OBJ = dhry.o all: dhry +dhry: $(OBJ) + $(LD) -n -- -i -j -k$(LIBDIR) -lz80.lib \ + -b_CODE=0x200 dhry.ihx $(LIBDIR)crt0.o $(OBJ) + cat dhry.ihx | ../../makebin/makebin > dhry.rom + +.c.o: + $(CC) $(CFLAGS) $< + +dhry.c: $(CC) + clean: rm -r *~ dhry - + diff --git a/support/tests/dhrystone/dhry.c b/support/tests/dhrystone/dhry.c index b6c78613..79de20ff 100644 --- a/support/tests/dhrystone/dhry.c +++ b/support/tests/dhrystone/dhry.c @@ -59,7 +59,7 @@ Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val); Boolean Func_2 (char *Str_1_Par_Ref, char *Str_2_Par_Ref); Boolean Func_3 (Enumeration Enum_Par_Val); -int main(void) +int _main(void) { One_Fifty Int_1_Loc; REG One_Fifty Int_2_Loc; diff --git a/support/tests/dhrystone/dhry.h b/support/tests/dhrystone/dhry.h index 8a880aae..81477aa1 100644 --- a/support/tests/dhrystone/dhry.h +++ b/support/tests/dhrystone/dhry.h @@ -413,24 +413,24 @@ typedef int Arr_1_Dim [50]; typedef int Arr_2_Dim [50] [50]; typedef struct record - { +{ struct record *Ptr_Comp; Enumeration Discr; union { - struct { - Enumeration Enum_Comp; - int Int_Comp; - char Str_Comp [31]; - } var_1; - struct { - Enumeration E_Comp_2; - char Str_2_Comp [31]; - } var_2; - struct { - char Ch_1_Comp; - char Ch_2_Comp; - } var_3; - } variant; - } Rec_Type, *Rec_Pointer; + struct { + Enumeration Enum_Comp; + int Int_Comp; + char Str_Comp [31]; + } var_1; + struct { + Enumeration E_Comp_2; + char Str_2_Comp [31]; + } var_2; + struct { + char Ch_1_Comp; + char Ch_2_Comp; + } var_3; + } variant; +} Rec_Type, *Rec_Pointer; -- 2.30.2