1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-24 11:31:31 +00:00

g_asr, g_asl: Use ROL/ROR for char shifts by >= 6

Instead of `val` right (left) shifts, we can also do `9 - val` left (right)
rotates and a mask.  This saves 3 bytes and 8 cycles for `val == 7` and
1 byte and 4 cycles for `val == 6`.
This commit is contained in:
Jesse Rosenstock 2020-11-15 23:03:01 +01:00 committed by greg-king5
parent ef258bdc19
commit e0c12c90cd

View File

@ -3114,9 +3114,26 @@ void g_asr (unsigned flags, unsigned long val)
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if (flags & CF_FORCECHAR) {
if ((flags & CF_UNSIGNED) != 0 && val < 8) {
while (val--) {
AddCodeLine ("lsr a");
val &= 7;
if ((flags & CF_UNSIGNED) != 0) {
/* Instead of `val` right shifts, we can also do `9 - val` left rotates
** and a mask. This saves 3 bytes and 8 cycles for `val == 7` and
** 1 byte and 4 cycles for `val == 6`.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("lsr a"); /* 1 byte, 2 cycles */
}
} else {
unsigned i;
/* The first ROL shifts in garbage and sets carry to the high bit.
** The garbage is cleaned up by the mask.
*/
for (i = val; i < 9; ++i) {
AddCodeLine ("rol a"); /* 1 byte, 2 cycles */
}
/* 2 bytes, 2 cycles */
AddCodeLine ("and #$%02X", 0xFF >> val);
}
return;
} else if (val <= 2) {
@ -3270,9 +3287,21 @@ void g_asl (unsigned flags, unsigned long val)
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if ((flags & CF_FORCECHAR) != 0 && val <= 6) {
while (val--) {
AddCodeLine ("asl a");
if ((flags & CF_FORCECHAR) != 0) {
val &= 7;
/* Large shifts are faster and smaller with ROR. See g_asr for detailed
** byte and cycle counts.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("asl a");
}
} else {
unsigned i;
for (i = val; i < 9; ++i) {
AddCodeLine ("ror a");
}
AddCodeLine ("and #$%02X", (~0U << val) & 0xFF);
}
return;
}