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:
parent
c427fb36b2
commit
e77bf71ab9
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user