+2008-09-16 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ * device/lib/z80/mul.s (__mulsuchar_rrx_s, __muluschar_rrx_s),
+ * device/lib/z80/div.s (__divsuchar_rrx_s, __modsuchar_rrx_s,
+ __divuschar_rrx_s, __moduschar_rrx_s): added mixed signedness versions
+ * device/lib/z80/stubs.s: added stubs for above functions
+ * src/SDCCopt.c (convilong),
+ * src/SDCCsymt.c (initCSupport): fixed bug 1900961
+ * src/SDCCsymt.h (__muldiv): enlarged for mixed signedness
+ * src/z80/main.c (_hasNativeMulFor): fixed bug, I think
+ * support/regression/tests/onebyte.c: enabled all tests for z80
+
2008-09-15 Borut Razem <borut.razem AT siol.net>
* device/include/pic16/stdio.h, device/lib/pic16/libc/stdio/streams.c,
ret
+__divsuchar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld e,(hl)
+ dec hl
+ ld c,(hl)
+ ld b, #0
+
+ call signexte
+
+ ld l,c
+ ld h,b
+
+ ret
+
+__modsuchar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld e,(hl)
+ dec hl
+ ld c,(hl)
+ ld b, #0
+
+ call signexte
+
+ ld l,e
+ ld h,d
+
+ ret
+
+__divuschar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld e,(hl)
+ ld d, #0
+ dec hl
+ ld c,(hl)
+
+ ld a,c ; Sign extend
+ rlca
+ sbc a
+ ld b,a
+
+ call .div16
+
+ ld l,c
+ ld h,b
+
+ ret
+
+__moduschar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld e,(hl)
+ ld d, #0
+ dec hl
+ ld c,(hl)
+
+ ld a,c ; Sign extend
+ rlca
+ sbc a
+ ld b,a
+
+ call .div16
+
+ ld l,e
+ ld h,d
+
+ ret
+
.div8::
.mod8::
ld a,c ; Sign extend
rlca
sbc a
ld b,a
+signexte:
ld a,e ; Sign extend
rlca
sbc a
; from Rodnay Zaks, "Programming the Z80".
__muluchar_rrx_s::
- ld hl, #2
+ ld hl, #2+1
add hl, sp
ld e, (hl)
- inc hl
+ dec hl
ld h, (hl)
ld l, #0
ld d, l
djnz muluchar_rrx_s_loop
ret
+; operands have different sign
+
+__mulsuchar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld e,(hl)
+ dec hl
+ ld c,(hl)
+ ld b, #0
+ jr signexte
+
+__muluschar_rrx_s::
+ ld hl,#2+1
+ add hl,sp
+
+ ld c,(hl)
+ ld b, #0
+ dec hl
+ ld e,(hl)
+ jr signexte
+
;; Originally from GBDK by Pascal Felber.
__mulschar_rrx_s::
- ld hl,#2
+ ld hl,#2+1
add hl,sp
ld e,(hl)
- inc hl
+ dec hl
ld l,(hl)
;; Fall through
rla
sbc a,a
ld b,a
-
+signexte:
ld a,e
rla
sbc a,a
ld d,a
- jp .mul16
+ jr .mul16
__mulint_rrx_s::
ld hl,#2
__muluchar_rrx_hds::
__mulint_rrx_hds::
;; Parameters:
- ;; HL, DE (left, right irrelivent)
+ ;; HL, DE (left, right irrelevant)
ld b,h
ld c,l
;; Optimise for the case when this side has 8 bits of data or
;; less. This is often the case with support address calls.
or a
- jp NZ,1$
+ jr NZ,1$
ld b,#8
ld a,c
.globl __divslong
.globl __divulong
.globl __divschar_rrx_s
- .globl __divsint_rrx_s
.globl __divuchar_rrx_s
+ .globl __divsuchar_rrx_s
+ .globl __divuschar_rrx_s
+ .globl __divsint_rrx_s
.globl __divuint_rrx_s
.globl __mulschar_rrx_s
.globl __muluchar_rrx_s
+ .globl __mulsuchar_rrx_s
+ .globl __muluschar_rrx_s
.globl __mulint_rrx_s
- .globl __moduchar_rrx_s
.globl __modschar_rrx_s
+ .globl __moduchar_rrx_s
+ .globl __modsuchar_rrx_s
+ .globl __moduschar_rrx_s
.globl __moduint_rrx_s
.globl __modsint_rrx_s
.globl __rrulong_rrx_s
rst 0x08
jp __divschar_rrx_s
+__modschar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __modschar_rrx_s
+
__muluchar_rrf_s::
ld a,#5
rst 0x08
rst 0x08
jp __divuchar_rrx_s
-__modschar_rrf_s::
+__moduchar_rrf_s::
ld a,#5
rst 0x08
- jp __modschar_rrx_s
+ jp __moduchar_rrx_s
-__moduchar_rrf_s::
+__mulsuchar_rrf_s::
ld a,#5
rst 0x08
- jp __moduchar_rrx_s
+ jp __mulsuchar_rrx_s
+
+__divsuchar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __divsuchar_rrx_s
+
+__modsuchar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __modsuchar_rrx_s
+
+__muluschar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __muluschar_rrx_s
+
+__divuschar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __divuschar_rrx_s
+
+__moduschar_rrf_s::
+ ld a,#5
+ rst 0x08
+ jp __moduschar_rrx_s
__modsint_rrf_s::
ld a,#5
/* convilong - converts int or long mults or divs to fcalls */
/*-----------------------------------------------------------------*/
static void
-convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op)
+convilong (iCode * ic, eBBlock * ebp)
{
+ int op = ic->op;
symbol *func = NULL;
iCode *ip = ic->next;
iCode *newic;
int bwd;
int su;
int bytesPushed=0;
+ sym_link *leftType = operandType (IC_LEFT (ic));
+ sym_link *rightType = operandType (IC_RIGHT (ic));
remiCodeFromeBBlock (ebp, ic);
+ if (getSize (leftType) == 1 && getSize (rightType) == 1)
+ {
+ int muldivmod;
+
+ if (op == '*')
+ muldivmod = 0;
+ else if (op == '/')
+ muldivmod = 1;
+ else if (op == '%')
+ muldivmod = 2;
+ else
+ muldivmod = -1;
+
+ for (su = 0; su < 4 && muldivmod >= 0; su++)
+ {
+ if ((compareType (leftType, __multypes[0][su%2]) == 1) &&
+ (compareType (rightType, __multypes[0][su/2]) == 1))
+ {
+ func = __muldiv[muldivmod][0][su];
+ goto found;
+ }
+ }
+ }
+
/* depending on the type */
for (bwd = 0; bwd < 3; bwd++)
{
for (su = 0; su < 2; su++)
{
- if (compareType (type, __multypes[bwd][su]) == 1)
+ if (compareType (leftType, __multypes[bwd][su]) == 1)
{
+ if ((op=='*' || op=='/' || op=='%') &&
+ compareType (rightType, __multypes[bwd][su]) != 1)
+ {
+ assert(0);
+ }
+
if (op == '*')
func = __muldiv[0][bwd][su];
else if (op == '/')
}
else
{
- convilong (ic, ebbs[i], leftType, ic->op);
+ convilong (ic, ebbs[i]);
}
}
}
if (IS_INTEGRAL (type) && getSize (type) > port->support.shift && port->support.shift >= 0)
{
- convilong (ic, ebbs[i], type, ic->op);
+ convilong (ic, ebbs[i]);
}
}
}
if (!bp) /* did not find it */
return;
+
/* if this is the first one in the chain */
if (!bp->prev)
{
bp->prev->next = bp->next;
}
-
}
/*-----------------------------------------------------------------*/
// short AND long
werror (E_LONG_AND_SHORT_INVALID, noun, name);
}
-
}
/*------------------------------------------------------------------*/
{
/* if not formal parameter and not in file scope
then show symbol redefined error
- else check if symbols have conpatible types */
+ else check if symbols have compatible types */
if (!sym->_isparm && sym->level > 0)
error = 1;
else
symbol *__fps16x16_gt;
symbol *__fps16x16_gteq;
-/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
-symbol *__muldiv[3][3][2];
+/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED/BOTH */
+symbol *__muldiv[3][3][4];
/* Dims: BYTE/WORD/DWORD SIGNED/UNSIGNED */
sym_link *__multypes[3][2];
/* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
};
const char *ssu[] =
{
- "s", "u"
+ "s", "su", "us", "u"
};
const char *srlrr[] =
{
{
if (tofrom)
{
- SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su], sbwd[bwd]);
+ SNPRINTF (buffer, sizeof(buffer), "__fs2%s%s", ssu[su*3], sbwd[bwd]);
__conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent);
}
else
{
- SNPRINTF (buffer, sizeof(buffer), "__%s%s2fs", ssu[su], sbwd[bwd]);
+ SNPRINTF (buffer, sizeof(buffer), "__%s%s2fs", ssu[su*3], sbwd[bwd]);
__conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent);
}
}
{
if (tofrom)
{
- SNPRINTF (buffer, sizeof(buffer), "__fps16x162%s%s", ssu[su], fp16x16sbwd[bwd]);
+ SNPRINTF (buffer, sizeof(buffer), "__fps16x162%s%s", ssu[su*3], fp16x16sbwd[bwd]);
if(bwd == 3) {
__fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, floatType, fixed16x16Type, 1, options.float_rent);
} else
}
else
{
- SNPRINTF (buffer, sizeof(buffer), "__%s%s2fps16x16", ssu[su], fp16x16sbwd[bwd]);
+ SNPRINTF (buffer, sizeof(buffer), "__%s%s2fps16x16", ssu[su*3], fp16x16sbwd[bwd]);
if(bwd == 3) {
__fp16x16conv[tofrom][bwd][su] = funcOfType (buffer, fixed16x16Type, floatType, 1, options.float_rent);
} else
SNPRINTF (buffer, sizeof(buffer),
"_%s%s%s",
smuldivmod[muldivmod],
- ssu[su],
+ ssu[su*3],
sbwd[bwd]);
__muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
Therefore they've been merged into mulint() and mullong().
*/
- for (bwd = 0; bwd < 3; bwd++)
+ /* byte */
+ bwd = 0;
+ for (su = 0; su < 4; su++)
+ {
+ for (muldivmod = 0; muldivmod < 3; muldivmod++)
+ {
+ /* muluchar, mulschar, mulsuchar and muluschar are separate functions, because e.g. the z80
+ port is sign/zero-extending to int before calling mulint() */
+ /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */
+ if (!TARGET_IS_PIC16 || muldivmod != 1 || su != 0)
+ {
+ SNPRINTF (buffer, sizeof(buffer),
+ "_%s%s%s",
+ smuldivmod[muldivmod],
+ ssu[su],
+ sbwd[bwd]);
+ __muldiv[muldivmod][bwd][su] = funcOfType (
+ _mangleFunctionName(buffer),
+ __multypes[bwd][su%2],
+ __multypes[bwd][su/2],
+ 2,
+ options.intlong_rent);
+ FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+ }
+ }
+ }
+
+ for (bwd = 1; bwd < 3; bwd++)
{
for (su = 0; su < 2; su++)
{
SNPRINTF (buffer, sizeof(buffer),
"_%s%s%s",
smuldivmod[muldivmod],
- ssu[su],
+ ssu[su*3],
sbwd[bwd]);
__muldiv[muldivmod][bwd][su] = funcOfType (
_mangleFunctionName(buffer),
/* mul only */
muldivmod = 0;
- /* byte */
- bwd = 0;
- for (su = 0; su < 2; su++)
- {
- /* muluchar and mulschar are still separate functions, because e.g. the z80
- port is sign/zero-extending to int before calling mulint() */
- SNPRINTF (buffer, sizeof(buffer),
- "_%s%s%s",
- smuldivmod[muldivmod],
- ssu[su],
- sbwd[bwd]);
- __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
- FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
- }
/* signed only */
su = 0;
/* word and doubleword */
SNPRINTF (buffer, sizeof(buffer),
"_%s%s%s",
srlrr[rlrr],
- ssu[su],
+ ssu[su*3],
sbwd[bwd]);
__rlrr[rlrr][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[0][0], 2, options.intlong_rent);
FUNC_NONBANKED (__rlrr[rlrr][bwd][su]->type) = 1;
extern symbol *__fps16x16_gt;
extern symbol *__fps16x16_gteq;
-/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
-extern symbol *__muldiv[3][3][2];
+/* Dims: mul/div/mod, BYTE/WORD/DWORD, SIGNED/UNSIGNED/BOTH */
+extern symbol *__muldiv[3][3][4];
/* Dims: BYTE/WORD/DWORD SIGNED/UNSIGNED */
extern sym_link *__multypes[3][2];
/* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
optimize.loopInduction = 1;
}
-/* Mangaling format:
+/* Mangling format:
_fun_policy_params
where:
policy is the function policy
where:
r is 'r' for reentrant, 's' for static functions
s is 'c' for callee saves, 'r' for caller saves
- p is 'p' for profiling on, 'x' for profiling off
+ f is 'f' for profiling on, 'x' for profiling off
examples:
rr - reentrant, caller saves
params format:
sprintf(buffer, "%s_rr%s_%s", original,
options.profile ? "f" : "x",
- options.noRegParams ? "s" : "bds"
+ options.noRegParams ? "s" : "bds" /* MB: but the library only has hds variants ??? */
);
return Safe_strdup(buffer);
}
else if ( IS_LITERAL (right))
{
- test = left;
+ test = right;
val = OP_VALUE (IC_RIGHT (ic));
}
else
cL = -128; cR = 1; r8 = cL * cR; r8b = cR * cL; ASSERT ( r8 == -128); ASSERT ( r8b == -128);
cL = 128; cR = 1; ur8 = cL * cR; ur8b = cR * cL; ASSERT (ur8 == 128); ASSERT (ur8b == 128);
-#ifndef SDCC_z80
ucL = 128; cR = -5; r16 = ucL * cR; r16b = cR * ucL; ASSERT (r16 == -640); ASSERT (r16b == -640);
ucL = 128; cR = 5; r16 = ucL * cR; r16b = cR * ucL; ASSERT (r16 == 640); ASSERT (r16b == 640);
-#endif
ucL = 127; cR = -1; r8 = ucL * cR; r8b = cR * ucL; ASSERT ( r8 == -127); ASSERT ( r8b == -127);
ucL = 128; cR = 1; ur8 = ucL * cR; ur8b = cR * ucL; ASSERT (ur8 == 128); ASSERT (ur8b == 128);
ucL = 127; cR = 3; r8 = ucL / cR; ASSERT (r8 == 42);
ucL = 255; cR = 3; r8 = ucL / cR; ASSERT (r8 == 85);
-#ifndef SDCC_z80
ucL = 127; cR = -3; r8 = ucL / cR; ASSERT (r8 == -42);
ucL = 255; cR = -3; r8 = ucL / cR; ASSERT (r8 == -85);
-#endif
cL = 127; ucR = 3; r8 = cL / ucR; ASSERT (r8 == 42);
cL = -127; ucR = 3; r8 = cL / ucR; ASSERT (r8 == -42);
ucL = 251; cR = 1; ur8 = ucL / cR; ASSERT (ur8 == 251);
ucL = 251; cR = 1; r16 = ucL / cR; ASSERT (r16 == 251);
-#ifndef SDCC_z80
ucL = 253; cR = -3; r8 = ucL / cR; ASSERT (r8 == -84);
ucL = 253; cR = -3; r16 = ucL / cR; ASSERT (r16 == -84);
ucL = 254; cR = -1; r16 = ucL / cR; ASSERT (r16 == -254);
-#endif
cL = -128; cR = -1; r16 = cL / cR; ASSERT (r16 == 128);
}
volatile short r16;
ucL = 128; cR = 5; r16 = ucL % cR; ASSERT (r16 == 3);
-#ifndef SDCC_z80
ucL = 128; cR = -5; r16 = ucL % cR; ASSERT (r16 == 3);
-#endif
ucL = 128; ucR = 5; r16 = ucL % ucR; ASSERT (r16 == 3);
ucL = 128; ucR = 255; ur8 = ucL % ucR; ASSERT (ur8 == 128);