+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 */
/*****************************************************************************/
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) {
-
- /* 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);
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* Calculate the real stack offset */
- Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ 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) {
+
+ /* 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);
- } 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)) {
-
- /* 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);
- /* 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));
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ } else {
- /* We need a label */
- Label = GetLocalLabel ();
+ 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));
+ }
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+ }
+
+ /* 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;
+ }
- if (Offs == 0) {
+ 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);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* 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;
+ /* Reload result - X hasn't changed by the code above */
+ AddCodeLine ("lda ptr1");
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
- /* Drop the generated code but leave the load of the first argument*/
- RemoveCode (&Arg1.Push);
-
- /* We need a label */
- Label = GetLocalLabel ();
-
- /* Generate memcpy code */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- if (Arg3.Expr.IVal <= 127) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldy #$00");
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
-
- /* 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);
-
- } else {
-
- /* 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);
+
ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
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 ();
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* 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));
+ }
+
+ /* 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 ();
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') {
+ if (IS_Get (&InlineStdFuncs)) {
- /* Drop the generated code so we have the first argument in the
- ** primary
+ /* If the second argument is the empty string literal, we can generate
+ ** more efficient code.
*/
- RemoveCode (&Arg1.Push);
-
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg2.Expr.LVal);
+ 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
+ /* We do now have Arg1 in the primary. Load the first character from
+ ** this string and cast to int. This is the function result.
*/
- RemoveCode (&Arg1.Push);
+ 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);
+
+ /* 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);
- /* Fetch the first char */
- g_getind (CF_CHAR | CF_UNSIGNED, 0);
- }
+ /* 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);
- } 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))) {
+ /* Fetch the first char */
+ g_getind (CF_CHAR | CF_UNSIGNED, 0);
+ }
+ } 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))) {
- unsigned Entry, Loop, Fin; /* Labels */
- const char* Load;
- const char* Compare;
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Load;
+ const char* Compare;
- 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";
- }
+ 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.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";
- }
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Drop the generated code */
- RemoveCode (&Arg1.Push);
+ /* 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);
- /* 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);
+ } 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";
+ }
+
+ /* 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 */
/* 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)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* 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";
+ }
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* 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));
+ /* We need labels */
+ L1 = GetLocalLabel ();
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* 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));
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- StackPtr >= -255 &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+ /* 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 (&Arg1.Expr) &&
- !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ StackPtr >= -255 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
- /* 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 (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
- /* 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));
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* We need labels */
+ L1 = GetLocalLabel ();
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- StackPtr >= -255) {
+ /* 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));
- /* 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);
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ StackPtr >= -255) {
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* 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);
- /* 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));
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- } else {
+ /* We need labels */
+ L1 = GetLocalLabel ();
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* 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));
+ /* 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;
/* 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) {
+ if (IS_Get (&Optimize)) {
- /* Constant string literal */
- ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
+ /* 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) {
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg.LVal);
+ /* Constant string literal */
+ ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
- /* 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;
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg.LVal);
- } else {
+ /* 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");
- /* Load the expression into the primary */
- LoadExpr (CF_NONE, &Arg);
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
- /* Call the strlen function */
- AddCodeLine ("jsr _%s", Func_strlen);
+ /* 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) {
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
+ /* 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 ();
}