1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 06:29:38 +00:00

fix g_div patch, hopefully checks works again

This commit is contained in:
mrdudz 2022-11-13 17:50:40 +01:00
parent c427fb36b2
commit e77bf71ab9
4 changed files with 96 additions and 81 deletions

View File

@ -62,7 +62,7 @@ g_defdata_float
(see below) g_add, g_sub, g_mul, g_div, g_neg, g_bneg
(see below) g_eq, g_ne, g_lt, g_gt, g_le, g_ge
(invalid) g_mod, g_or, g_xor, g_and, g_asr
(invalid) g_mod, g_or, g_xor, g_and, g_asr, g_asl
```
#### datatype.c

View File

@ -1681,7 +1681,8 @@ unsigned g_typecast (unsigned to, unsigned from)
/* If we are converting from float, first convert float to int,
then fall through to char conversion */
if ((from & CF_TYPEMASK) == CF_FLOAT) {
AddCodeLine ("jsr feaxint");
// AddCodeLine ("jsr feaxint");
g_regint (from);
}
/* We must truncate the primary register to char and then
@ -2564,7 +2565,7 @@ void g_push (unsigned flags, unsigned long val)
/* Value is not 16 bit or not constant */
if (flags & CF_CONST) {
/* Constant 32 bit value, load into eax */
ASMLOG(("nop ; g_push")); // FIXME: remove
ASMLOG(("nop ; g_push load val into eax")); // FIXME: remove
g_getimmed (flags, val, 0);
}
@ -2921,6 +2922,7 @@ void g_mul (unsigned flags, unsigned long val)
/* Check if we can use shift instead of multiplication */
if (p2 == 0 || (p2 > 0 && IS_Get (&CodeSizeFactor) >= (Negation ? 100 : 0))) {
LOG(("g_mul doing strength reduction\n"));
/* Generate a shift instead */
g_asl (flags, p2);
@ -3040,95 +3042,100 @@ void g_div (unsigned flags, unsigned long val)
};
LOG(("g_div flags:%04x val:%d\n", flags, val));
ASMLOG(("nop ; g_div(flags:%2x,val:%lx)", flags, val)); // FIXME: remove
/* Do strength reduction if the value is constant and a power of two */
if ((flags & CF_CONST) && ((flags & CF_TYPEMASK) != CF_FLOAT)) {
if (flags & CF_CONST) {
/* Deal with negative values as well as different sizes */
int Negation = (flags & CF_UNSIGNED) == 0 && (long)val < 0;
unsigned long NegatedVal = 0UL - val;
int p2 = PowerOf2 (Negation ? NegatedVal : val);
if ((flags & CF_TYPEMASK) != CF_FLOAT) {
/* Deal with negative values as well as different sizes */
int Negation = (flags & CF_UNSIGNED) == 0 && (long)val < 0;
unsigned long NegatedVal = 0UL - val;
int p2 = PowerOf2 (Negation ? NegatedVal : val);
/* Generate a shift instead */
if ((flags & CF_UNSIGNED) != 0 && p2 > 0) {
g_asr (flags, p2);
return;
}
LOG(("g_div doing strength reduction\n"));
/* Check if we can afford using shift instead of multiplication at the
** cost of code size */
if (p2 == 0 || (p2 > 0 && IS_Get (&CodeSizeFactor) >= (Negation ? 200 : 170))) {
/* Generate a conditional shift instead */
if (p2 > 0) {
unsigned int DoShiftLabel = GetLocalLabel ();
unsigned int EndLabel = GetLocalLabel ();
unsigned long MaskedVal = Negation ? val : NegatedVal;
/* Generate a shift instead */
if ((flags & CF_UNSIGNED) != 0 && p2 > 0) {
g_asr (flags, p2);
return;
}
/* GitHub #169 - if abs(expr) < abs(val), the result is always 0.
** First, check whether expr >= 0 and skip to the shift if true.
*/
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if (flags & CF_FORCECHAR) {
MaskedVal &= 0xFF;
AddCodeLine ("cmp #$00");
/* Check if we can afford using shift instead of multiplication at the
** cost of code size */
if (p2 == 0 || (p2 > 0 && IS_Get (&CodeSizeFactor) >= (Negation ? 200 : 170))) {
/* Generate a conditional shift instead */
if (p2 > 0) {
unsigned int DoShiftLabel = GetLocalLabel ();
unsigned int EndLabel = GetLocalLabel ();
unsigned long MaskedVal = Negation ? val : NegatedVal;
/* GitHub #169 - if abs(expr) < abs(val), the result is always 0.
** First, check whether expr >= 0 and skip to the shift if true.
*/
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if (flags & CF_FORCECHAR) {
MaskedVal &= 0xFF;
AddCodeLine ("cmp #$00");
AddCodeLine ("bpl %s", LocalLabelName (DoShiftLabel));
break;
}
/* FALLTHROUGH */
case CF_INT:
MaskedVal &= 0xFFFF;
AddCodeLine ("cpx #$00");
AddCodeLine ("bpl %s", LocalLabelName (DoShiftLabel));
break;
case CF_LONG:
MaskedVal &= 0xFFFFFFFF;
AddCodeLine ("ldy sreg+1");
AddCodeLine ("bpl %s", LocalLabelName (DoShiftLabel));
break;
default:
typeerror (flags);
break;
}
/* FALLTHROUGH */
/* Second, check whether expr <= -asb(val) and skip to the
** shift if true. The original content of expr has to be saved
** before the checking comparison and restored after that, as
** the content in Primary register will be destroyed.
** The result of the comparison is a boolean. We can store
** it in the Carry flag with a LSR and branch on it later.
*/
g_save (flags);
g_le (flags | CF_UNSIGNED, MaskedVal);
AddCodeLine ("lsr a");
g_restore (flags);
AddCodeLine ("bcs %s", LocalLabelName (DoShiftLabel));
case CF_INT:
MaskedVal &= 0xFFFF;
AddCodeLine ("cpx #$00");
AddCodeLine ("bpl %s", LocalLabelName (DoShiftLabel));
break;
/* The result is 0. We can just load 0 and skip the shifting. */
g_getimmed (flags | CF_ABSOLUTE, 0, 0);
case CF_LONG:
MaskedVal &= 0xFFFFFFFF;
AddCodeLine ("ldy sreg+1");
AddCodeLine ("bpl %s", LocalLabelName (DoShiftLabel));
break;
/* TODO: replace with BEQ? Would it be optimized? */
g_jump (EndLabel);
default:
typeerror (flags);
break;
/* Do the shift. The sign of the result may need to be corrected
** later.
*/
g_defcodelabel (DoShiftLabel);
g_asr (flags, p2);
g_defcodelabel (EndLabel);
}
/* Second, check whether expr <= -asb(val) and skip to the
** shift if true. The original content of expr has to be saved
** before the checking comparison and restored after that, as
** the content in Primary register will be destroyed.
** The result of the comparison is a boolean. We can store
** it in the Carry flag with a LSR and branch on it later.
/* Negate the result as long as val < 0, even if val == -1 and no
** shift was generated.
*/
g_save (flags);
g_le (flags | CF_UNSIGNED, MaskedVal);
AddCodeLine ("lsr a");
g_restore (flags);
AddCodeLine ("bcs %s", LocalLabelName (DoShiftLabel));
if (Negation) {
g_neg (flags);
}
/* The result is 0. We can just load 0 and skip the shifting. */
g_getimmed (flags | CF_ABSOLUTE, 0, 0);
/* TODO: replace with BEQ? Would it be optimized? */
g_jump (EndLabel);
/* Do the shift. The sign of the result may need to be corrected
** later.
*/
g_defcodelabel (DoShiftLabel);
g_asr (flags, p2);
g_defcodelabel (EndLabel);
/* Done */
return;
}
/* Negate the result as long as val < 0, even if val == -1 and no
** shift was generated.
*/
if (Negation) {
g_neg (flags);
}
/* Done */
return;
}
/* If we go here, we didn't emit code. Push the lhs on stack and fall
@ -3137,7 +3144,6 @@ void g_div (unsigned flags, unsigned long val)
flags &= ~CF_FORCECHAR; /* Handle chars as ints */
g_push (flags & ~CF_CONST, 0);
}
ASMLOG(("nop ; g_div(flags:%2x,val:%lx)", flags, val)); // FIXME: remove
/* Generate a division */
oper (flags, val, ops);

View File

@ -2201,12 +2201,19 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */
** it's a constant, since we will exchange both operands.
*/
if ((Gen->Flags & GEN_COMM) == 0) {
g_push (ltype | CF_CONST, Expr->IVal);
if (ltype == CF_FLOAT) {
LOG(("hie_internal push left side const (float)\n"));
g_push (ltype | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal));
} else {
LOG(("hie_internal push left side const (int)\n"));
g_push (ltype | CF_CONST, Expr->IVal);
}
}
} else {
/* Value not constant */
LoadExpr (CF_NONE, Expr);
GetCodePos (&Mark2);
LOG(("hie_internal push left side var\n"));
g_push (ltype, 0);
}
@ -2392,7 +2399,7 @@ LOG(("hie_internal Expr->Type:%s Expr2->Type:%s\n",
Expr->Type = ArithmeticConvert (Expr->Type, Expr2.Type);
/* Generate code */
if (TypeOf (Expr2.Type) == CF_FLOAT) {
if (TypeOf (Expr->Type) == CF_FLOAT) {
Gen->Func (type, FP_D_As32bitRaw(Expr->V.FVal));
} else {
Gen->Func (type, Expr->IVal);
@ -2419,7 +2426,7 @@ LOG(("hie_internal Expr->Type:%s Expr2->Type:%s\n",
LOG(("rtype float is %x\n", CF_FLOAT));
if (rtype == CF_FLOAT) {
// FIXME add respective checks for float
FIXME(("add div checks for float\n"));
FIXME(("FIXME: add div checks for float\n"));
} else {
if (Tok == TOK_DIV && Expr2.IVal == 0) {
Error ("Division by zero");
@ -2430,6 +2437,7 @@ LOG(("hie_internal Expr->Type:%s Expr2->Type:%s\n",
type |= CF_CONST;
rtype |= CF_CONST;
if ((Gen->Flags & GEN_NOPUSH) != 0) {
FIXME(("hie_internal ?2 removing code\n"));
RemoveCode (&Mark2);
ltype |= CF_PRIMARY; /* Value is in register */
}
@ -2877,7 +2885,7 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */
/* FIXME: float --- startcode end */
if (Expr2.Type == type_float) {
LOG(("FIXME: special cases for comparison with float constant"));
LOG(("FIXME: special cases for comparison with float constant\n"));
} else {
/* FIXME: float --- newcode end */

View File

@ -41,6 +41,7 @@ int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]",temp,str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}