/* */
/* */
/* */
-/* (C) 2004 Ullrich von Bassewitz */
+/* (C) 2004-2006 Ullrich von Bassewitz */
/* Römerstraße 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
ExprDesc Expr2;
CodeMark Mark1;
CodeMark Mark2;
- token_t Tok; /* The operator token */
+ token_t Tok; /* The operator token */
+ Type* EffType; /* Effective lhs type */
+ Type* ResultType; /* Type of the result */
unsigned ExprBits; /* Bits of the lhs operand */
- unsigned ltype, rtype, flags;
- int rconst; /* Operand is a constant */
+ unsigned GenFlags; /* Generator flags */
+ unsigned ltype;
+ int rconst; /* Operand is a constant */
/* Evaluate the lhs */
while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
- /* All operators that call this function expect an int on the lhs */
- if (!IsClassInt (Expr->Type)) {
- Error ("Integer expression expected");
+ /* All operators that call this function expect an int on the lhs */
+ if (!IsClassInt (Expr->Type)) {
+ Error ("Integer expression expected");
ED_MakeConstAbsInt (Expr, 1);
- }
+ }
+
+ /* Remember the operator token, then skip it */
+ Tok = CurTok.Tok;
+ NextToken ();
- /* Remember the operator token, then skip it */
- Tok = CurTok.Tok;
- NextToken ();
+ /* Get the type of the result */
+ ResultType = EffType = IntPromotion (Expr->Type);
+
+ /* Prepare the code generator flags */
+ GenFlags = TypeOf (ResultType);
/* Calculate the number of bits the lhs operand has */
- ExprBits = SizeOf (Expr->Type) * 8;
-
- /* Get the lhs on stack */
- Mark1 = GetCodePos ();
- ltype = TypeOf (Expr->Type);
- if (ED_IsConstAbs (Expr)) {
- /* Constant value */
- Mark2 = GetCodePos ();
- g_push (ltype | CF_CONST, Expr->IVal);
- } else {
- /* Value not constant */
- LoadExpr (CF_NONE, Expr);
- Mark2 = GetCodePos ();
- g_push (ltype, 0);
- }
-
- /* Get the right hand side */
+ ExprBits = SizeOf (ResultType) * 8;
+
+ /* Get the lhs on stack */
+ GetCodePos (&Mark1);
+ ltype = TypeOf (Expr->Type);
+ if (ED_IsConstAbs (Expr)) {
+ /* Constant value */
+ GetCodePos (&Mark2);
+ g_push (ltype | CF_CONST, Expr->IVal);
+ } else {
+ /* Value not constant */
+ LoadExpr (CF_NONE, Expr);
+ GetCodePos (&Mark2);
+ g_push (ltype, 0);
+ }
+
+ /* Get the right hand side */
ExprWithCheck (hie8, &Expr2);
- /* Check the type of the rhs */
- if (!IsClassInt (Expr2.Type)) {
- Error ("Integer expression expected");
+ /* Check the type of the rhs */
+ if (!IsClassInt (Expr2.Type)) {
+ Error ("Integer expression expected");
ED_MakeConstAbsInt (&Expr2, 1);
- }
+ }
/* Check for a constant right side expression */
rconst = ED_IsConstAbs (&Expr2);
} else {
- /* The rhs is a constant numeric value */
+ /* The rhs is a constant numeric value. */
+ GenFlags |= CF_CONST;
+
+ /* Remove the code that pushes the rhs onto the stack. */
+ RemoveCode (&Mark2);
/* If the shift count is greater or equal than the bit count of
* the operand, the behaviour is undefined according to the
if (Expr2.IVal == 0) {
/* Result is already in Expr, remove the generated code */
- RemoveCode (Mark1);
- pop (ltype);
+ RemoveCode (&Mark1);
/* Done */
goto Next;
}
/* Both operands are constant, remove the generated code */
- RemoveCode (Mark1);
- pop (ltype);
+ RemoveCode (&Mark1);
/* Done */
goto Next;
}
- /* If we're shifting an integer or unsigned to the left, the
+ /* If we're shifting an integer or unsigned to the right, the
* lhs has a const address, and the shift count is larger than 8,
* we can load just the high byte as a char with the correct
* signedness, and reduce the shift count by 8. If the remaining
* shift count is zero, we're done.
*/
- if (Tok == TOK_SHL &&
+ if (Tok == TOK_SHR &&
IsTypeInt (Expr->Type) &&
ED_IsLVal (Expr) &&
(ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) &&
Expr2.IVal >= 8) {
- type* OldType;
+ Type* OldType;
/* Increase the address by one and decrease the shift count */
++Expr->IVal;
}
/* Remove the generated load code */
- RemoveCode (Mark1);
- pop (ltype);
+ RemoveCode (&Mark1);
- /* Generate again code for the load */
+ /* Generate again code for the load, this time with the new type */
LoadExpr (CF_NONE, Expr);
/* Reset the type */
/* If the shift count is now zero, we're done */
if (Expr2.IVal == 0) {
/* Be sure to mark the value as in the primary */
- goto Loaded;
+ goto MakeRVal;
}
-
- /* Otherwise generate code to push the value */
- Mark2 = GetCodePos ();
- g_push (ltype, 0);
}
}
- /* If the right hand side is a constant, remove the push of the
- * primary register.
- */
- rtype = TypeOf (Expr2.Type);
- flags = 0;
- if (rconst) {
- flags |= CF_CONST;
- rtype |= CF_CONST;
- RemoveCode (Mark2);
- pop (ltype);
- ltype |= CF_REG; /* Value is in register */
- }
-
- /* Determine the type of the operation result. */
- flags |= g_typeadjust (ltype, rtype);
-
/* Generate code */
switch (Tok) {
- case TOK_SHL: g_asl (flags, Expr2.IVal); break;
- case TOK_SHR: g_asr (flags, Expr2.IVal); break;
- default: break;
+ case TOK_SHL: g_asl (GenFlags, Expr2.IVal); break;
+ case TOK_SHR: g_asr (GenFlags, Expr2.IVal); break;
+ default: break;
}
-Loaded:
+MakeRVal:
/* We have a rvalue in the primary now */
ED_MakeRValExpr (Expr);
Next:
- /* Get the type of the result */
- Expr->Type = IntPromotion (Expr->Type);
+ /* Set the type of the result */
+ Expr->Type = ResultType;
}
}
-
-
-