Added special multiplication routines
git-svn-id: svn://svn.cc65.org/cc65/trunk@1012 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
560ac0ac43
commit
0fdf581d06
6 changed files with 188 additions and 36 deletions
|
@ -130,6 +130,9 @@ OBJS = add.o \
|
||||||
makebool.o \
|
makebool.o \
|
||||||
mod.o \
|
mod.o \
|
||||||
mul.o \
|
mul.o \
|
||||||
|
mulax3.o \
|
||||||
|
mulax5.o \
|
||||||
|
mulax10.o \
|
||||||
ne.o \
|
ne.o \
|
||||||
neg.o \
|
neg.o \
|
||||||
or.o \
|
or.o \
|
||||||
|
|
32
libsrc/runtime/mulax10.s
Normal file
32
libsrc/runtime/mulax10.s
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
;
|
||||||
|
; Ullrich von Bassewitz, 04.10.2001
|
||||||
|
;
|
||||||
|
; CC65 runtime: Multiply the primary register
|
||||||
|
;
|
||||||
|
|
||||||
|
.export mulax10
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
.proc mulax10
|
||||||
|
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
clc
|
||||||
|
adc ptr1
|
||||||
|
pha
|
||||||
|
txa
|
||||||
|
adc ptr1+1
|
||||||
|
sta ptr1+1
|
||||||
|
pla
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
ldx ptr1+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
27
libsrc/runtime/mulax3.s
Normal file
27
libsrc/runtime/mulax3.s
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
;
|
||||||
|
; Ullrich von Bassewitz, 04.10.2001
|
||||||
|
;
|
||||||
|
; CC65 runtime: Multiply the primary register
|
||||||
|
;
|
||||||
|
|
||||||
|
.export mulax3
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
.proc mulax3
|
||||||
|
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
clc
|
||||||
|
adc ptr1
|
||||||
|
pha
|
||||||
|
txa
|
||||||
|
adc ptr1+1
|
||||||
|
tax
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
29
libsrc/runtime/mulax5.s
Normal file
29
libsrc/runtime/mulax5.s
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
;
|
||||||
|
; Ullrich von Bassewitz, 04.10.2001
|
||||||
|
;
|
||||||
|
; CC65 runtime: Multiply the primary register
|
||||||
|
;
|
||||||
|
|
||||||
|
.export mulax5
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
.proc mulax5
|
||||||
|
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
asl a
|
||||||
|
rol ptr1+1
|
||||||
|
clc
|
||||||
|
adc ptr1
|
||||||
|
pha
|
||||||
|
txa
|
||||||
|
adc ptr1+1
|
||||||
|
tax
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
||||||
|
|
||||||
|
|
|
@ -2526,7 +2526,7 @@ void g_mul (unsigned flags, unsigned long val)
|
||||||
if (flags & CF_CONST && (p2 = powerof2 (val)) >= 0) {
|
if (flags & CF_CONST && (p2 = powerof2 (val)) >= 0) {
|
||||||
/* Generate a shift instead */
|
/* Generate a shift instead */
|
||||||
g_asl (flags, p2);
|
g_asl (flags, p2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the right hand side is const, the lhs is not on stack but still
|
/* If the right hand side is const, the lhs is not on stack but still
|
||||||
|
@ -2538,50 +2538,61 @@ void g_mul (unsigned flags, unsigned long val)
|
||||||
|
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
if (flags & CF_FORCECHAR) {
|
if (flags & CF_FORCECHAR) {
|
||||||
/* Handle some special cases */
|
/* Handle some special cases */
|
||||||
switch (val) {
|
switch (val) {
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
AddCodeLine ("sta tmp1");
|
AddCodeLine ("sta tmp1");
|
||||||
AddCodeLine ("asl a");
|
AddCodeLine ("asl a");
|
||||||
AddCodeLine ("clc");
|
AddCodeLine ("clc");
|
||||||
AddCodeLine ("adc tmp1");
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
AddCodeLine ("sta tmp1");
|
|
||||||
AddCodeLine ("asl a");
|
|
||||||
AddCodeLine ("asl a");
|
|
||||||
AddCodeLine ("clc");
|
|
||||||
AddCodeLine ("adc tmp1");
|
AddCodeLine ("adc tmp1");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 10:
|
case 5:
|
||||||
AddCodeLine ("sta tmp1");
|
AddCodeLine ("sta tmp1");
|
||||||
AddCodeLine ("asl a");
|
AddCodeLine ("asl a");
|
||||||
AddCodeLine ("asl a");
|
AddCodeLine ("asl a");
|
||||||
AddCodeLine ("clc");
|
AddCodeLine ("clc");
|
||||||
AddCodeLine ("adc tmp1");
|
AddCodeLine ("adc tmp1");
|
||||||
AddCodeLine ("asl a");
|
return;
|
||||||
return;
|
|
||||||
}
|
case 10:
|
||||||
|
AddCodeLine ("sta tmp1");
|
||||||
|
AddCodeLine ("asl a");
|
||||||
|
AddCodeLine ("asl a");
|
||||||
|
AddCodeLine ("clc");
|
||||||
|
AddCodeLine ("adc tmp1");
|
||||||
|
AddCodeLine ("asl a");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case CF_INT:
|
case CF_INT:
|
||||||
break;
|
switch (val) {
|
||||||
|
case 3:
|
||||||
|
AddCodeLine ("jsr mulax3");
|
||||||
|
return;
|
||||||
|
case 5:
|
||||||
|
AddCodeLine ("jsr mulax5");
|
||||||
|
return;
|
||||||
|
case 10:
|
||||||
|
AddCodeLine ("jsr mulax10");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case CF_LONG:
|
case CF_LONG:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
typeerror (flags);
|
typeerror (flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we go here, we didn't emit code. Push the lhs on stack and fall
|
/* If we go here, we didn't emit code. Push the lhs on stack and fall
|
||||||
* into the normal, non-optimized stuff.
|
* into the normal, non-optimized stuff.
|
||||||
*/
|
*/
|
||||||
flags &= ~CF_FORCECHAR; /* Handle chars as ints */
|
flags &= ~CF_FORCECHAR; /* Handle chars as ints */
|
||||||
g_push (flags & ~CF_CONST, 0);
|
g_push (flags & ~CF_CONST, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,53 @@ static unsigned OptShift1 (CodeSeg* S)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned OptShift2 (CodeSeg* S)
|
||||||
|
/* A call to the shraxN routine may get replaced by one or more lsr insns
|
||||||
|
* if the value of X is not used later.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned Changes = 0;
|
||||||
|
|
||||||
|
/* Walk over the entries */
|
||||||
|
unsigned I = 0;
|
||||||
|
while (I < CS_GetEntryCount (S)) {
|
||||||
|
|
||||||
|
/* Get next entry */
|
||||||
|
CodeEntry* E = CS_GetEntry (S, I);
|
||||||
|
|
||||||
|
/* Check for the sequence */
|
||||||
|
if (E->OPC == OP65_JSR &&
|
||||||
|
strncmp (E->Arg, "shrax", 5) == 0 &&
|
||||||
|
strlen (E->Arg) == 6 &&
|
||||||
|
IsDigit (E->Arg[5]) &&
|
||||||
|
!RegXUsed (S, I+1)) {
|
||||||
|
|
||||||
|
/* Insert shift insns */
|
||||||
|
unsigned Count = E->Arg[5] - '0';
|
||||||
|
while (Count--) {
|
||||||
|
CodeEntry* X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI);
|
||||||
|
CS_InsertEntry (S, X, I+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the call to shlax */
|
||||||
|
CS_DelEntry (S, I);
|
||||||
|
|
||||||
|
/* Remember, we had changes */
|
||||||
|
++Changes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++I;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of changes made */
|
||||||
|
return Changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Optimize stores through pointers */
|
/* Optimize stores through pointers */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -1299,6 +1346,7 @@ static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 0, 0, 0, 0
|
||||||
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptShift1 = { OptShift1, "OptShift1", 0, 0, 0, 0, 0 };
|
static OptFunc DOptShift1 = { OptShift1, "OptShift1", 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptShift2 = { OptShift2, "OptShift2", 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptSize1 = { OptSize1, "OptSize1", 0, 0, 0, 0, 0 };
|
static OptFunc DOptSize1 = { OptSize1, "OptSize1", 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptSize2 = { OptSize2, "OptSize2", 0, 0, 0, 0, 0 };
|
static OptFunc DOptSize2 = { OptSize2, "OptSize2", 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptStackOps = { OptStackOps, "OptStackOps", 0, 0, 0, 0, 0 };
|
static OptFunc DOptStackOps = { OptStackOps, "OptStackOps", 0, 0, 0, 0, 0 };
|
||||||
|
@ -1349,6 +1397,7 @@ static OptFunc* OptFuncs[] = {
|
||||||
&DOptRTS,
|
&DOptRTS,
|
||||||
&DOptRTSJumps,
|
&DOptRTSJumps,
|
||||||
&DOptShift1,
|
&DOptShift1,
|
||||||
|
&DOptShift2,
|
||||||
&DOptSize1,
|
&DOptSize1,
|
||||||
&DOptSize2,
|
&DOptSize2,
|
||||||
&DOptStackOps,
|
&DOptStackOps,
|
||||||
|
@ -1596,6 +1645,7 @@ static void RunOptGroup1 (CodeSeg* S)
|
||||||
RunOptFunc (S, &DOptAdd1, 1);
|
RunOptFunc (S, &DOptAdd1, 1);
|
||||||
RunOptFunc (S, &DOptAdd2, 1);
|
RunOptFunc (S, &DOptAdd2, 1);
|
||||||
RunOptFunc (S, &DOptShift1, 1);
|
RunOptFunc (S, &DOptShift1, 1);
|
||||||
|
RunOptFunc (S, &DOptShift2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue