From 0694926e60ec83b31f87590e601f7e0d8f86c512 Mon Sep 17 00:00:00 2001 From: epetrich Date: Mon, 1 Dec 2003 07:37:58 +0000 Subject: [PATCH] * sim/ucsim/hc08.src/inst.cc, * sim/ucsim/hc08.src/hc08mac.h: fixed some problems with CC flag bits and carries from x to h * src/hc08/gen.c (aopAdrStr): fixed problem with 16 bit immediate * src/hc08/gen.c (XAccRsh): fixed problem with right shift * device/include/stdarg.h: fixed varargs for hc08 * device/lib/Makefile.in, * device/lib/hc08/Makefile, * device/lib/hc08/_mulint.c, * device/lib/hc08/_mullong.c: fixed some endian problems git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3037 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 13 +++ device/include/stdarg.h | 2 +- device/lib/Makefile.in | 2 +- device/lib/hc08/Makefile | 2 +- device/lib/hc08/_mulint.c | 65 ++++++++++++ device/lib/hc08/_mullong.c | 97 ++++++++++++++++++ sim/ucsim/hc08.src/hc08mac.h | 2 +- sim/ucsim/hc08.src/inst.cc | 194 ++++++++++++----------------------- src/hc08/gen.c | 10 +- 9 files changed, 249 insertions(+), 138 deletions(-) create mode 100644 device/lib/hc08/_mulint.c create mode 100644 device/lib/hc08/_mullong.c diff --git a/ChangeLog b/ChangeLog index 12edff89..c620a1a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-12-01 Erik Petrich + + * sim/ucsim/hc08.src/inst.cc, + * sim/ucsim/hc08.src/hc08mac.h: fixed some problems with CC flag bits and + carries from x to h + * src/hc08/gen.c (aopAdrStr): fixed problem with 16 bit immediate + * src/hc08/gen.c (XAccRsh): fixed problem with right shift + * device/include/stdarg.h: fixed varargs for hc08 + * device/lib/Makefile.in, + * device/lib/hc08/Makefile, + * device/lib/hc08/_mulint.c, + * device/lib/hc08/_mullong.c: fixed some endian problems + 2003-11-28 Frieder Ferlemann * sdcc/src/mcs51/gen.c (genMultOneByte): help peephole 105 diff --git a/device/include/stdarg.h b/device/include/stdarg.h index 7f18a1e0..7f77256c 100644 --- a/device/include/stdarg.h +++ b/device/include/stdarg.h @@ -5,7 +5,7 @@ #ifndef __SDC51_STDARG_H #define __SDC51_STDARG_H 1 -#if defined(__z80) || defined(__gbz80) +#if defined(__z80) || defined(__gbz80) || defined(__hc08) typedef unsigned char * va_list; #define va_start(list, last) list = (unsigned char *)&last + sizeof(last) diff --git a/device/lib/Makefile.in b/device/lib/Makefile.in index d6a81b09..ee98a9e4 100644 --- a/device/lib/Makefile.in +++ b/device/lib/Makefile.in @@ -130,7 +130,7 @@ HC08SOURCES = _atof.c _atoi.c _atol.c _schar2fs.c \ _isupper.c _isxdigit.c _itoa.c _ltoa.c \ _slong2fs.c _memcmp.c \ _memcpy.c _memmove.c _memset.c _modsint.c _modslong.c \ - _moduint.c _modulong.c _mulint.c _mullong.c \ + _moduint.c _modulong.c \ _spx.c _startup.c _strchr.c _strcmp.c _strcpy.c \ _strcspn.c _strlen.c _strncat.c _strncmp.c \ _strncpy.c _strpbrk.c _strrchr.c _strspn.c \ diff --git a/device/lib/hc08/Makefile b/device/lib/hc08/Makefile index c690a372..baded10f 100644 --- a/device/lib/hc08/Makefile +++ b/device/lib/hc08/Makefile @@ -5,7 +5,7 @@ TOPDIR = ../../.. SCC = $(TOPDIR)/bin/sdcc -mhc08 SAS = $(TOPDIR)/bin/as6808 -OBJ = _ret.rel _divuint.rel _divulong.rel +OBJ = _ret.rel _divuint.rel _divulong.rel _mulint.rel _mullong.rel LIB = hc08.lib CC = $(SCC) diff --git a/device/lib/hc08/_mulint.c b/device/lib/hc08/_mulint.c new file mode 100644 index 00000000..9ac3a720 --- /dev/null +++ b/device/lib/hc08/_mulint.c @@ -0,0 +1,65 @@ +/*------------------------------------------------------------------------- + _mulint.c :- routine for (unsigned) int (16 bit) multiplication + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +/* Signed and unsigned multiplication are the same - as long as the output + has the same precision as the input. + + Assembler-functions are provided for: + ds390 + mcs51 small + mcs51 small stack-auto + mcs51 large +*/ + + +union uu { + struct { unsigned char hi,lo ;} s; + unsigned int t; +} ; + +int +_mulint (int a, int b) +{ +#if !defined(SDCC_STACK_AUTO) && (defined(SDCC_MODEL_LARGE) || defined(SDCC_ds390)) // still needed for large + union uu xdata *x; + union uu xdata *y; + union uu t; + x = (union uu xdata *)&a; + y = (union uu xdata *)&b; +#else + register union uu *x; + register union uu *y; + union uu t; + x = (union uu *)&a; + y = (union uu *)&b; +#endif + + t.t = x->s.lo * y->s.lo; + t.s.hi += (x->s.lo * y->s.hi) + (x->s.hi * y->s.lo); + + return t.t; +} + + +#undef _MULINT_ASM diff --git a/device/lib/hc08/_mullong.c b/device/lib/hc08/_mullong.c new file mode 100644 index 00000000..f84a9e50 --- /dev/null +++ b/device/lib/hc08/_mullong.c @@ -0,0 +1,97 @@ +/*------------------------------------------------------------------------- + _mullong.c - routine for multiplication of 32 bit (unsigned) long + + Written By - Jean Louis VERN jlvern@writeme.com (1999) + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +/* Signed and unsigned multiplication are the same - as long as the output + has the same precision as the input. + + Assembler-functions are provided for: + mcs51 small + mcs51 small stack-auto +*/ + + +struct some_struct { + short a ; + char b; + long c ;}; +union bil { + struct {unsigned char b3,b2,b1,b0 ;} b; + struct {unsigned short hi,lo ;} i; + unsigned long l; + struct { unsigned char b3; unsigned short i12; unsigned char b0;} bi; +} ; + +# define bcast(x) ((union bil *)&(x)) + +/* + 3 2 1 0 + X 3 2 1 0 + ---------------------------- + 0.3 0.2 0.1 0.0 + 1.3 1.2 1.1 1.0 + 2.3 2.2 2.1 2.0 + 3.3 3.2 3.1 3.0 + ---------------------------- + |3.3|1.3|0.2|0.0| A + |2.3|0.3|0.1| B + |3.2|1.2|1.0| C + |2.2|1.1| D + |3.1|2.0| E + |2.1| F + |3.0| G + |-------> only this side 32 x 32 -> 32 +*/ +long +_mullong (long a, long b) +{ + union bil t; + + t.i.hi = bcast(a)->b.b0 * bcast(b)->b.b2; // A + t.i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; // A + t.b.b3 += bcast(a)->b.b3 * + bcast(b)->b.b0; // G + t.b.b3 += bcast(a)->b.b2 * + bcast(b)->b.b1; // F + t.i.hi += bcast(a)->b.b2 * bcast(b)->b.b0; // E <- b lost in .lst + // bcast(a)->i.hi is free ! + t.i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; // D <- b lost in .lst + + bcast(a)->bi.b3 = bcast(a)->b.b1 * + bcast(b)->b.b2; + bcast(a)->bi.i12 = bcast(a)->b.b1 * + bcast(b)->b.b0; // C + + bcast(b)->bi.b3 = bcast(a)->b.b0 * + bcast(b)->b.b3; + bcast(b)->bi.i12 = bcast(a)->b.b0 * + bcast(b)->b.b1; // B + bcast(b)->bi.b0 = 0; // B + bcast(a)->bi.b0 = 0; // C + t.l += a; + + return t.l + b; +} + +#endif // _MULLONG_ASM diff --git a/sim/ucsim/hc08.src/hc08mac.h b/sim/ucsim/hc08.src/hc08mac.h index 0b1df1c7..9eec83d6 100644 --- a/sim/ucsim/hc08.src/hc08mac.h +++ b/sim/ucsim/hc08.src/hc08mac.h @@ -36,7 +36,7 @@ #define FLAG_ASSIGN(f,c) {regs.P = (c) ? regs.P | (f) : regs.P & ~(f);} #define FLAG_NZ(f) { \ regs.P = (regs.P & ~(BIT_N|BIT_Z)) \ - | ((f) ? 0 : BIT_Z) \ + | (((f) & 0xff) ? 0 : BIT_Z) \ | (((f) & 0x80) ? BIT_N : 0) \ ; } #define EA_IMM(c) ((((c) >> 4) & 0xf)==0xa) diff --git a/sim/ucsim/hc08.src/inst.cc b/sim/ucsim/hc08.src/inst.cc index 80e1439a..bdd8312d 100644 --- a/sim/ucsim/hc08.src/inst.cc +++ b/sim/ucsim/hc08.src/inst.cc @@ -204,70 +204,34 @@ cl_hc08::inst_stx(t_mem code, bool prefix) int cl_hc08::inst_add(t_mem code, bool prefix) { - int result; - uchar operand; + int result, operand1, operand2; - operand = OPERAND(code, prefix); - result = (regs.A + operand) & 0xff; + operand1 = regs.A; + operand2 = OPERAND(code, prefix); + result = operand1 + operand2; FLAG_NZ (result); - FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & operand & ~result) - | (~regs.A & ~operand & result))); - FLAG_ASSIGN (BIT_H, 0x08 & ((regs.A & operand) - | (operand & ~result) - | (~result & regs.A))); - FLAG_ASSIGN (BIT_C, 0x80 & ((regs.A & operand) - | (operand & ~result) - | (~result & regs.A))); - -#if 0 - fprintf (stdout, "add 0x%02x + 0x%02x = 0x%02x ",regs.A, operand, result & 0xff); - fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ", - (regs.P & BIT_V)!=0, - (regs.P & BIT_H)!=0, - (regs.P & BIT_C)!=0, - (regs.P & BIT_N)!=0, - (regs.P & BIT_Z)!=0); -#endif + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result)); - regs.A = result; + regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_adc(t_mem code, bool prefix) { - int result; - uchar operand; - int sresult; - uchar carryin = (regs.P & BIT_C)!=0; - - operand = OPERAND(code, prefix); - result = regs.A + operand + carryin; - sresult = (signed char)regs.A + (signed char)operand + ((regs.P & BIT_C)!=0); - FLAG_NZ (result & 0xff); - FLAG_ASSIGN (BIT_V, (sresult<-128) || (sresult>127)); - /* 0x80 & ((regs.A & operand & ~result) - | (~regs.A & ~operand & result))); */ - FLAG_ASSIGN (BIT_H, (result & 0xf) < (regs.A & 0xf)); - /* 0x10 & ((regs.A & operand) - | (operand & ~result) - | (~result & regs.A))); */ - FLAG_ASSIGN (BIT_C, result & 0x100); - /* 0x80 & ((regs.A & operand) - | (operand & ~result) - | (~result & regs.A))); */ - -#if 0 - fprintf (stdout, "adc 0x%02x + 0x%02x + %d = 0x%02x ", - regs.A, operand, carryin, result & 0xff); - fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ", - (regs.P & BIT_V)!=0, - (regs.P & BIT_H)!=0, - (regs.P & BIT_C)!=0, - (regs.P & BIT_N)!=0, - (regs.P & BIT_Z)!=0); -#endif - + int result, operand1, operand2; + int carryin = (regs.P & BIT_C)!=0; + + operand1 = regs.A; + operand2 = OPERAND(code, prefix); + result = operand1 + operand2 + carryin; + FLAG_NZ (result); + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result)); + regs.A = result & 0xff; return(resGO); } @@ -275,90 +239,63 @@ cl_hc08::inst_adc(t_mem code, bool prefix) int cl_hc08::inst_sub(t_mem code, bool prefix) { - int result; - uchar operand; + int result, operand1, operand2; - operand = OPERAND(code, prefix); - result = (regs.A - operand) & 0xff; + operand1 = regs.A; + operand2 = OPERAND(code, prefix); + result = operand1 - operand2; FLAG_NZ (result); - FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result) - | (~regs.A & operand & result))); - FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand) - | (operand & result) - | (result & ~regs.A))); -#if 0 - fprintf (stdout, "sub 0x%02x - 0x%02x = 0x%02x ",regs.A, operand, result & 0xff); - fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ", - (regs.P & BIT_V)!=0, - (regs.P & BIT_H)!=0, - (regs.P & BIT_C)!=0, - (regs.P & BIT_N)!=0, - (regs.P & BIT_Z)!=0); -#endif - regs.A = result; + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + + regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_sbc(t_mem code, bool prefix) { - int result; - uchar operand; - uchar carryin = (regs.P & BIT_C)!=0; + int result, operand1, operand2; + int carryin = (regs.P & BIT_C)!=0; - operand = OPERAND(code, prefix); - result = (regs.A - operand - carryin) & 0xff; + operand1 = regs.A; + operand2 = OPERAND(code, prefix); + result = operand1 - operand2 - carryin; FLAG_NZ (result); - FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result) - | (~regs.A & operand & result))); - FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand) - | (operand & result) - | (result & ~regs.A))); -#if 0 - fprintf (stdout, "sbc 0x%02x - 0x%02x - %d = 0x%02x ", - regs.A, operand, carryin, result & 0xff); - fprintf (stdout, "(V=%d, H=%d, C=%d, N=%d, Z=%d), ", - (regs.P & BIT_V)!=0, - (regs.P & BIT_H)!=0, - (regs.P & BIT_C)!=0, - (regs.P & BIT_N)!=0, - (regs.P & BIT_Z)!=0); -#endif - regs.A = result; + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + + regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_cmp(t_mem code, bool prefix) { - int result; - uchar operand; + int result, operand1, operand2; - operand = OPERAND(code, prefix); - result = (regs.A - operand) & 0xff; + operand1 = regs.A; + operand2 = OPERAND(code, prefix); + result = operand1 - operand2; FLAG_NZ (result); - FLAG_ASSIGN (BIT_V, 0x80 & ((regs.A & ~operand & ~result) - | (~regs.A & operand & result))); - FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.A & operand) - | (operand & result) - | (result & ~regs.A))); + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + return(resGO); } int cl_hc08::inst_cpx(t_mem code, bool prefix) { - int result; - uchar operand; + int result, operand1, operand2; - operand = OPERAND(code, prefix); - result = (regs.X - operand) & 0xff; + operand1 = regs.X; + operand2 = OPERAND(code, prefix); + result = operand1 - operand2; FLAG_NZ (result); - FLAG_ASSIGN (BIT_V, 0x80 & ((regs.X & ~operand & ~result) - | (~regs.X & operand & result))); - FLAG_ASSIGN (BIT_C, 0x80 & ((~regs.X & operand) - | (operand & result) - | (result & ~regs.X))); + FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); + FLAG_ASSIGN (BIT_C, 0x100 & result); + return(resGO); } @@ -402,7 +339,10 @@ cl_hc08::inst_ais(t_mem code, bool prefix) int cl_hc08::inst_aix(t_mem code, bool prefix) { - regs.X = regs.X + (signed char)fetch(); + int hx = (regs.H << 8) | (regs.X); + hx += (signed char)fetch(); + regs.H = (hx >> 8) & 0xff; + regs.X = hx & 0xff; return(resGO); } @@ -901,11 +841,11 @@ cl_hc08::inst_mul(t_mem code, bool prefix) int cl_hc08::inst_div(t_mem code, bool prefix) { - int dividend = (regs.H << 8) | regs.A; - int quotient; + unsigned int dividend = (regs.H << 8) | regs.A; + unsigned int quotient; if (regs.X) { - quotient = dividend / regs.X; + quotient = dividend / (unsigned int)regs.X; if (quotient<=0xff) { regs.A = quotient; regs.H = dividend % regs.X; @@ -1124,8 +1064,8 @@ cl_hc08::inst_sthx(t_mem code, bool prefix) store1((ea+1) & 0xffff, regs.X); FLAG_CLEAR(BIT_V); - FLAG_ASSIGN(BIT_N, regs.X & 0x80); - FLAG_ASSIGN(BIT_Z, !regs.X && !regs.A); + FLAG_ASSIGN(BIT_N, regs.H & 0x80); + FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H); return(resGO); } @@ -1147,8 +1087,8 @@ cl_hc08::inst_ldhx(t_mem code, bool prefix) return(resHALT); FLAG_CLEAR(BIT_V); - FLAG_ASSIGN(BIT_N, regs.X & 0x80); - FLAG_ASSIGN(BIT_Z, !regs.X && !regs.A); + FLAG_ASSIGN(BIT_N, regs.H & 0x80); + FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H); return(resGO); } @@ -1172,16 +1112,12 @@ cl_hc08::inst_cphx(t_mem code, bool prefix) return(resHALT); hx = (regs.H << 8) | regs.X; + result = hx-operand; - result = (hx-operand) & 0xffff; - - FLAG_ASSIGN (BIT_V, 0x8000 & ((hx & ~operand & ~result) - | (~hx & operand & result))); - FLAG_ASSIGN (BIT_C, 0x8000 & ((~hx & operand) - | (operand & result) - | (result & ~hx))); + FLAG_ASSIGN (BIT_V, 0x8000 & (hx ^ operand ^ result ^ (result>>1))); + FLAG_ASSIGN (BIT_C, 0x10000 & result); FLAG_ASSIGN(BIT_N, result & 0x8000); - FLAG_ASSIGN(BIT_Z, !result); + FLAG_ASSIGN(BIT_Z, !(result & 0xffff)); return(resGO); } diff --git a/src/hc08/gen.c b/src/hc08/gen.c index fde9e310..9c94f355 100644 --- a/src/hc08/gen.c +++ b/src/hc08/gen.c @@ -1920,7 +1920,7 @@ aopAdrStr (asmop * aop, int loffset, bool bit16) case AOP_LIT: if (bit16) - return aopLiteralLong (aop->aopu.aop_lit, loffset, 2); + return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2); else return aopLiteral (aop->aopu.aop_lit, loffset); @@ -5374,7 +5374,7 @@ XAccRsh (int shCount, bool sign) ** rola 1 1 bcde fgh0 0000 000a 0 ** lslx 1 1 cdef gh00 0000 000a b ** rola 1 1 cdef gh00 0000 00ab 0 - ** clrx 1 1 0000 0000 0000 000a 0 + ** clrx 1 1 0000 0000 0000 00ab 0 ** total: 6 cycles, 6 bytes */ loadRegFromConst (hc08_reg_x, zero); @@ -5430,12 +5430,12 @@ XAccRsh (int shCount, bool sign) ; } - /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */ + /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */ /* the fastest and shortest. */ for (i=0;i