/*****************************************************************************/
/* */
-/* stdfunc.c */
+/* stdfunc.c */
/* */
-/* Handle inlining of known functions for the cc65 compiler */
+/* Handle inlining of known functions for the cc65 compiler */
/* */
/* */
/* */
/*****************************************************************************/
-/* Function forwards */
+/* Function forwards */
/*****************************************************************************/
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Table with all known functions and their handlers. Must be sorted
- * alphabetically!
- */
+** alphabetically!
+*/
static struct StdFuncDesc {
- const char* Name;
- void (*Handler) (FuncDesc*, ExprDesc*);
+ const char* Name;
+ void (*Handler) (FuncDesc*, ExprDesc*);
} StdFuncs[] = {
- { "memcpy", StdFunc_memcpy },
- { "memset", StdFunc_memset },
- { "strcmp", StdFunc_strcmp },
- { "strcpy", StdFunc_strcpy },
- { "strlen", StdFunc_strlen },
+ { "memcpy", StdFunc_memcpy },
+ { "memset", StdFunc_memset },
+ { "strcmp", StdFunc_strcmp },
+ { "strcpy", StdFunc_strcpy },
+ { "strlen", StdFunc_strlen },
};
-#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
+#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
typedef struct ArgDesc ArgDesc;
struct ArgDesc {
/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
static long ArrayElementCount (const ArgDesc* Arg)
/* Check if the type of the given argument is an array. If so, and if the
- * element count is known, return it. In all other cases, return UNSPECIFIED.
- */
+** element count is known, return it. In all other cases, return UNSPECIFIED.
+*/
{
long Count;
static void ParseArg (ArgDesc* Arg, Type* Type)
/* Parse one argument but do not push it onto the stack. Make all fields in
- * Arg valid.
- */
+** Arg valid.
+*/
{
/* We have a prototype, so chars may be pushed as chars */
Arg->Flags = CF_FORCECHAR;
GetCodePos (&Arg->Load);
/* If the value is a constant, set the flag, otherwise load it into the
- * primary register.
- */
+ ** primary register.
+ */
if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) {
/* Remember that we have a constant value */
Arg->Flags |= CF_CONST;
+void AddCmpCodeIfSizeNot256 (const char* Code, long Size)
+/* Add a line of Assembly code that compares an index register
+** only if it isn't comparing to #<256. (If the next line
+** is "bne", then this will avoid a redundant line.)
+*/
+{
+ if (Size != 256) {
+ AddCodeLine (Code, (unsigned int)Size);
+ }
+}
+
+
+
/*****************************************************************************/
/* memcpy */
/*****************************************************************************/
ArgDesc Arg1, Arg2, Arg3;
unsigned ParamSize = 0;
unsigned Label;
+ int Offs;
/* Argument #1 */
ParseArg (&Arg1, Arg1Type);
ConsumeComma ();
/* Argument #3. Since memcpy is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg3, Arg3Type);
if (Arg3.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg3.Expr);
Warning ("Call to memcpy has no effect");
/* Remove all of the generated code but the load of the first
- * argument, which is what memcpy returns.
- */
+ ** argument, which is what memcpy returns.
+ */
RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
goto ExitPoint;
}
- /* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- */
- if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
+ if (IS_Get (&InlineStdFuncs)) {
- int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
- int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
+ int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127) {
+ /* We need a label */
+ Label = GetLocalLabel ();
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg2) {
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
- } else {
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
- }
- if (Reg1) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 129) {
- } else {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ g_defcodelabel (Label);
+ if (Reg2) {
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
+ } else {
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
+ }
+ if (Reg1) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
- AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg2) {
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
- } else {
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
- }
- if (Reg1) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
} else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
- }
+ AddCodeLine ("ldy #$00");
+ g_defcodelabel (Label);
+ if (Reg2) {
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
+ } else {
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
+ }
+ if (Reg1) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
- /* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
- *Expr = Arg1.Expr;
+ }
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
- !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
+ !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Calculate the real stack offset */
+ Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 129 && !AllowOneIndex) {
+
+ if (Offs == 0) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("dex");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ }
- if (Offs == 0) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
} else {
- AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("dey");
- AddCodeLine ("dex");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- }
- } else {
+ if (Offs == 0 || AllowOneIndex) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- if (Offs == 0 || AllowOneIndex) {
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
- AddCodeLine ("bne %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldx #$00");
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
}
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
- /* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
- *Expr = Arg1.Expr;
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+
+ /* Calculate the real stack offset */
+ Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 129 && !AllowOneIndex) {
+
+ if (Offs == 0) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("dey");
+ AddCodeLine ("dex");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ }
+
+ } else {
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+ if (Offs == 0 || AllowOneIndex) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- /* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
- !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+ }
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* We need a label */
- Label = GetLocalLabel ();
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
+
+ /* Drop the generated code but leave the load of the first argument*/
+ RemoveCode (&Arg1.Push);
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+ /* We need a label */
+ Label = GetLocalLabel ();
- if (Offs == 0) {
+ /* Generate memcpy code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 129) {
AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
g_defcodelabel (Label);
AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("sta (ptr1),y");
AddCodeLine ("dey");
- AddCodeLine ("dex");
AddCodeLine ("bpl %s", LocalLabelName (Label));
- }
-
- } else {
-
- if (Offs == 0 || AllowOneIndex) {
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
- AddCodeLine ("bne %s", LocalLabelName (Label));
} else {
- AddCodeLine ("ldx #$00");
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ AddCodeLine ("ldy #$00");
g_defcodelabel (Label);
AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
- }
-
- /* memcpy returns the address, so the result is actually identical
- * to the first argument.
- */
- *Expr = Arg1.Expr;
-
- } else {
+ /* Reload result - X hasn't changed by the code above */
+ AddCodeLine ("lda ptr1");
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
ConsumeComma ();
/* Argument #2. This argument is special in that we will call another
- * function if it is a constant zero.
- */
+ ** function if it is a constant zero.
+ */
ParseArg (&Arg2, Arg2Type);
if ((Arg2.Flags & CF_CONST) != 0 && Arg2.Expr.IVal == 0) {
/* Don't call memset, call bzero instead */
ConsumeComma ();
/* Argument #3. Since memset is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg3, Arg3Type);
if (Arg3.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg3.Expr);
Warning ("Call to memset has no effect");
/* Remove all of the generated code but the load of the first
- * argument, which is what memset returns.
- */
+ ** argument, which is what memset returns.
+ */
RemoveCode (&Arg1.Push);
/* Set the function result to the first argument */
goto ExitPoint;
}
- /* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- * Note: Lots of improvements would be possible here, but I will
- * concentrate on the most common case: memset with arguments 2 and 3
- * being constant numerical values. Some checks have shown that this
- * covers nearly 90% of all memset calls.
- */
- if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
+ if (IS_Get (&InlineStdFuncs)) {
- int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ ** Note: Lots of improvements would be possible here, but I will
+ ** concentrate on the most common case: memset with arguments 2 and 3
+ ** being constant numerical values. Some checks have shown that this
+ ** covers nearly 90% of all memset calls.
+ */
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate memset code */
- if (Arg3.Expr.IVal <= 127) {
+ /* We need a label */
+ Label = GetLocalLabel ();
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
+ /* Generate memset code */
+ if (Arg3.Expr.IVal <= 129) {
- } else {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
- AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
} else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
-
- }
-
- /* memset returns the address, so the result is actually identical
- * to the first argument.
- */
- *Expr = Arg1.Expr;
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
-
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ }
- /* We need a label */
- Label = GetLocalLabel ();
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* Generate memset code */
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
- AddCodeLine ("bne %s", LocalLabelName (Label));
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* memset returns the address, so the result is actually identical
- * to the first argument.
- */
- *Expr = Arg1.Expr;
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* Remove all of the generated code but the load of the first
- * argument.
- */
- RemoveCode (&Arg1.Push);
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* We need a label */
+ Label = GetLocalLabel ();
- /* Generate code */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- if (Arg3.Expr.IVal <= 127) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ /* Generate memset code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
+
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
- /* Load the function result pointer into a/x (x is still valid). This
- * code will get removed by the optimizer if it is not used later.
- */
- AddCodeLine ("lda ptr1");
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* Remove all of the generated code but the load of the first
+ ** argument.
+ */
+ RemoveCode (&Arg1.Push);
- } else {
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 129) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* Load the function result pointer into a/x (x is still valid). This
+ ** code will get removed by the optimizer if it is not used later.
+ */
+ AddCodeLine ("lda ptr1");
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
ParseArg (&Arg2, Arg2Type);
/* Since strcmp is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
if (Arg2.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg2.Expr);
}
g_call (CF_FIXARGC, Func_strcmp, ParamSize);
/* Get the element counts of the arguments. Then get the larger of the
- * two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
- */
+ ** two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically
+ */
ECount1 = ArrayElementCount (&Arg1);
ECount2 = ArrayElementCount (&Arg2);
if (ECount2 > ECount1) {
ECount1 = ECount2;
}
- /* If the second argument is the empty string literal, we can generate
- * more efficient code.
- */
- if (ED_IsLocLiteral (&Arg2.Expr) &&
- IS_Get (&WritableStrings) == 0 &&
- GetLiteralSize (Arg2.Expr.LVal) == 1 &&
- GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
-
- /* Drop the generated code so we have the first argument in the
- * primary
- */
- RemoveCode (&Arg1.Push);
+ if (IS_Get (&InlineStdFuncs)) {
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg2.Expr.LVal);
+ /* If the second argument is the empty string literal, we can generate
+ ** more efficient code.
+ */
+ if (ED_IsLocLiteral (&Arg2.Expr) &&
+ IS_Get (&WritableStrings) == 0 &&
+ GetLiteralSize (Arg2.Expr.LVal) == 1 &&
+ GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
- /* We do now have Arg1 in the primary. Load the first character from
- * this string and cast to int. This is the function result.
- */
- IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
- if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
- (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Load);
+ /* Drop the generated code so we have the first argument in the
+ ** primary
+ */
+ RemoveCode (&Arg1.Push);
- /* Generate code */
- AddCodeLine ("ldy #$%02X", Offs);
- AddCodeLine ("ldx #$00");
- AddCodeLine ("lda (sp),y");
- } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Load);
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg2.Expr.LVal);
- /* Generate code */
- AddCodeLine ("ldx #$00");
- AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- /* Drop part of the generated code so we have the first argument
- * in the primary
- */
- RemoveCode (&Arg1.Push);
+ /* We do now have Arg1 in the primary. Load the first character from
+ ** this string and cast to int. This is the function result.
+ */
+ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
+ if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
- /* Fetch the first char */
- g_getind (CF_CHAR | CF_UNSIGNED, 0);
- }
+ /* Generate code */
+ AddCodeLine ("ldy #$%02X", Offs);
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda (sp),y");
+ } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
- } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
- (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+ /* Generate code */
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ /* Drop part of the generated code so we have the first argument
+ ** in the primary
+ */
+ RemoveCode (&Arg1.Push);
+ /* Fetch the first char */
+ g_getind (CF_CHAR | CF_UNSIGNED, 0);
+ }
- unsigned Entry, Loop, Fin; /* Labels */
- const char* Load;
- const char* Compare;
+ } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
- if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
- Load = "lda (%s),y";
- } else {
- Load = "lda %s,y";
- }
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Compare = "cmp (%s),y";
- } else {
- Compare = "cmp %s,y";
- }
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Load;
+ const char* Compare;
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
-
- /* We need labels */
- Entry = GetLocalLabel ();
- Loop = GetLocalLabel ();
- Fin = GetLocalLabel ();
-
- /* Generate strcmp code */
- AddCodeLine ("ldy #$00");
- AddCodeLine ("beq %s", LocalLabelName (Entry));
- g_defcodelabel (Loop);
- AddCodeLine ("tax");
- AddCodeLine ("beq %s", LocalLabelName (Fin));
- AddCodeLine ("iny");
- g_defcodelabel (Entry);
- AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("beq %s", LocalLabelName (Loop));
- AddCodeLine ("ldx #$01");
- AddCodeLine ("bcs %s", LocalLabelName (Fin));
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (Fin);
-
- } else if ((IS_Get (&CodeSizeFactor) > 190) &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
-
-
- unsigned Entry, Loop, Fin; /* Labels */
- const char* Compare;
-
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Compare = "cmp (%s),y";
- } else {
- Compare = "cmp %s,y";
- }
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Push);
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+
+ } else if ((IS_Get (&CodeSizeFactor) > 190) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Compare;
+
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
- /* We need labels */
- Entry = GetLocalLabel ();
- Loop = GetLocalLabel ();
- Fin = GetLocalLabel ();
-
- /* Store Arg1 into ptr1 */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
-
- /* Generate strcmp code */
- AddCodeLine ("ldy #$00");
- AddCodeLine ("beq %s", LocalLabelName (Entry));
- g_defcodelabel (Loop);
- AddCodeLine ("tax");
- AddCodeLine ("beq %s", LocalLabelName (Fin));
- AddCodeLine ("iny");
- g_defcodelabel (Entry);
- AddCodeLine ("lda (ptr1),y");
- AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("beq %s", LocalLabelName (Loop));
- AddCodeLine ("ldx #$01");
- AddCodeLine ("bcs %s", LocalLabelName (Fin));
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (Fin);
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Push);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+ /* Store Arg1 into ptr1 */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+ }
}
/* The function result is an rvalue in the primary register */
ConsumeComma ();
/* Argument #2. Since strcpy is a fastcall function, we must load the
- * arg into the primary if it is not already there. This parameter is
- * also ignored for the calculation of the parameter size, since it is
- * not passed via the stack.
- */
+ ** arg into the primary if it is not already there. This parameter is
+ ** also ignored for the calculation of the parameter size, since it is
+ ** not passed via the stack.
+ */
ParseArg (&Arg2, Arg2Type);
if (Arg2.Flags & CF_CONST) {
LoadExpr (CF_NONE, &Arg2.Expr);
/* Get the element count of argument 1 if it is an array */
ECount = ArrayElementCount (&Arg1);
- /* We've generated the complete code for the function now and know the
- * types of all parameters. Check for situations where better code can
- * be generated. If such a situation is detected, throw away the
- * generated, and emit better code.
- */
- if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
- (IS_Get (&InlineStdFuncs) ||
- (ECount != UNSPECIFIED && ECount < 256))) {
-
- const char* Load;
- const char* Store;
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Load = "lda (%s),y";
- } else {
- Load = "lda %s,y";
- }
- if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
- Store = "sta (%s),y";
- } else {
- Store = "sta %s,y";
- }
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
+ if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) ||
+ (ECount != UNSPECIFIED && ECount < 256))) {
+
+ const char* Load;
+ const char* Store;
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Store = "sta (%s),y";
+ } else {
+ Store = "sta %s,y";
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* We need labels */
+ L1 = GetLocalLabel ();
- /* Generate strcpy code */
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- StackPtr >= -255 &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
- !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ StackPtr >= -255 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate strcpy code */
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
- if (Offs == 0 || AllowOneIndex) {
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
- } else {
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* We need labels */
+ L1 = GetLocalLabel ();
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- StackPtr >= -255) {
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
- /* It is possible to just use one index register even if the stack
- * offset is not zero, by adjusting the offset to the constant
- * address accordingly. But we cannot do this if the data in
- * question is in the register space or at an absolute address less
- * than 256. Register space is zero page, which means that the
- * address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
- !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ StackPtr >= -255) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
+ !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* Generate strcpy code */
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
- if (Offs == 0 || AllowOneIndex) {
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- } else {
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- }
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* We need labels */
+ L1 = GetLocalLabel ();
- } else {
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
}
long ECount;
unsigned L;
-
-
/* Setup the argument type string */
ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
hie1 (&Arg);
/* Check if the argument is an array. If so, remember the element count.
- * Otherwise set the element count to undefined.
- */
+ ** Otherwise set the element count to undefined.
+ */
IsArray = IsTypeArray (Arg.Type);
if (IsArray) {
ECount = GetElementCount (Arg.Type);
}
/* Check if the elements of an array can be addressed by a byte sized
- * index. This is true if the size of the array is known and less than
- * 256.
- */
+ ** index. This is true if the size of the array is known and less than
+ ** 256.
+ */
IsByteIndex = (ECount != UNSPECIFIED && ECount < 256);
/* Do type conversion */
TypeConversion (&Arg, ArgType);
- /* If the expression is a literal, and if string literals are read
- * only, we can calculate the length of the string and remove it
- * from the literal pool. Otherwise we have to calculate the length
- * at runtime.
- */
- if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
-
- /* Constant string literal */
- ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
-
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg.LVal);
-
- /* We will inline strlen for arrays with constant addresses, if either the
- * inlining was forced on the command line, or the array is smaller than
- * 256, so the inlining is considered safe.
- */
- } else if (ED_IsLocConst (&Arg) && IsArray &&
- (IS_Get (&InlineStdFuncs) || IsByteIndex)) {
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg, 0));
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* We will inline strlen for arrays on the stack, if the array is
- * completely within the reach of a byte sized index register.
- */
- } else if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
- (Arg.IVal - StackPtr) + ECount < 256) {
-
- /* Calculate the true stack offset */
- int Offs = ED_GetStackOffs (&Arg, 0);
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldx #$FF");
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1));
- g_defcodelabel (L);
- AddCodeLine ("inx");
- AddCodeLine ("iny");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("txa");
- AddCodeLine ("ldx #$00");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* strlen for a string that is pointed to by a register variable will only
- * get inlined if requested on the command line, since we cannot know how
- * big the buffer actually is, so inlining is not always safe.
- */
- } else if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr &&
- IS_Get (&InlineStdFuncs)) {
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0));
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* Last check: We will inline a generic strlen routine if inlining was
- * requested on the command line, and the code size factor is more than
- * 400 (code is 13 bytes vs. 3 for a jsr call).
- */
- } else if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&InlineStdFuncs)) {
-
- /* Load the expression into the primary */
- LoadExpr (CF_NONE, &Arg);
-
- /* Inline the function */
- L = GetLocalLabel ();
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda (ptr1),y");
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
+ if (IS_Get (&Optimize)) {
- } else {
+ /* If the expression is a literal, and if string literals are read
+ ** only, we can calculate the length of the string and remove it
+ ** from the literal pool. Otherwise we have to calculate the length
+ ** at runtime.
+ */
+ if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
- /* Load the expression into the primary */
- LoadExpr (CF_NONE, &Arg);
+ /* Constant string literal */
+ ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
- /* Call the strlen function */
- AddCodeLine ("jsr _%s", Func_strlen);
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg.LVal);
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
+ /* Bail out, no need for further improvements */
+ goto ExitPoint;
+ }
+ }
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* We will inline strlen for arrays with constant addresses, if either
+ ** requested on the command line, or the array is smaller than 256,
+ ** so the inlining is considered safe.
+ */
+ if (ED_IsLocConst (&Arg) && IsArray &&
+ (IS_Get (&EagerlyInlineFuncs) || IsByteIndex)) {
+
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("ldx %s,y", ED_GetLabelName (&Arg, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ /* We will inline strlen for arrays on the stack, if the array is
+ ** completely within the reach of a byte sized index register.
+ */
+ if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
+ (Arg.IVal - StackPtr) + ECount < 256) {
+
+ /* Calculate the true stack offset */
+ int Offs = ED_GetStackOffs (&Arg, 0);
+
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldx #$FF");
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1));
+ g_defcodelabel (L);
+ AddCodeLine ("inx");
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("txa");
+ AddCodeLine ("ldx #$00");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ /* strlen for a string that is pointed to by a register variable will only
+ ** get inlined if requested on the command line, since we cannot know how
+ ** big the buffer actually is, so inlining is not always safe.
+ */
+ if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr &&
+ IS_Get (&EagerlyInlineFuncs)) {
+
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tax");
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ /* Last check: We will inline a generic strlen routine if inlining was
+ ** requested on the command line, and the code size factor is more than
+ ** 400 (code is 13 bytes vs. 3 for a jsr call).
+ */
+ if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&EagerlyInlineFuncs)) {
+
+ /* Load the expression into the primary */
+ LoadExpr (CF_NONE, &Arg);
+
+ /* Inline the function */
+ L = GetLocalLabel ();
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tax");
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* Load the expression into the primary */
+ LoadExpr (CF_NONE, &Arg);
+
+ /* Call the strlen function */
+ AddCodeLine ("jsr _%s", Func_strlen);
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
int FindStdFunc (const char* Name)
/* Determine if the given function is a known standard function that may be
- * called in a special way. If so, return the index, otherwise return -1.
- */
+** called in a special way. If so, return the index, otherwise return -1.
+*/
{
/* Look into the table for known names */
struct StdFuncDesc* D =
/* Call the handler function */
D->Handler (F, lval);
}
-
-
-