+#include "asmlabel.h"
+#include "codeent.h"
#include "codegen.h"
+#include "codeseg.h"
+#include "cpu.h"
#include "error.h"
+#include "exprdesc.h"
+#include "expr.h"
+#include "loadexpr.h"
#include "scanner.h"
+#include "standard.h"
#include "symtab.h"
#include "goto.h"
NextToken ();
/* Label name must follow */
- if (CurTok.Tok != TOK_IDENT) {
-
- Error ("Label name expected");
-
- } else {
+ if (CurTok.Tok == TOK_IDENT) {
/* Add a new label symbol if we don't have one until now */
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO);
/* Jump to the label */
g_jump (Entry->V.L.Label);
- }
- /* Eat the label name */
- NextToken ();
+ /* Eat the label name */
+ NextToken ();
+
+ } else if (CurTok.Tok == TOK_STAR && IS_Get (&Standard) >= STD_CC65) {
+ SymEntry *arr, *idx, *cur;
+ SymTable *tab;
+ ExprDesc desc;
+ CodeEntry *E;
+ unsigned char val;
+ unsigned I;
+
+ NextToken ();
+
+ /* arr[foo], we only support simple foo for now */
+ if (CurTok.Tok == TOK_IDENT &&
+ (arr = FindSym (CurTok.Ident))) {
+ NextToken ();
+ ConsumeLBrack ();
+
+ /* Find array size */
+ if (!IsTypeArray(arr->Type) || SizeOf(arr->Type) == 0 ||
+ SizeOf(GetElementType(arr->Type)) != 2)
+ Error ("Expected array");
+ if (GetElementCount(arr->Type) > 127)
+ Error ("Only arrays with <= 127 labels are supported, got %lu",
+ GetElementCount(arr->Type));
+
+ if (CurTok.Tok == TOK_ICONST) {
+ val = CurTok.IVal;
+ NextToken ();
+
+ if (CPUIsets[CPU] & CPU_ISET_65SC02) {
+ AddCodeLine ("ldx #$%02X", val * 2);
+ AddCodeLine ("jmp (%s,x)", arr->AsmName);
+ } else {
+ AddCodeLine ("ldy #$%02X", val * 2);
+ AddCodeLine ("lda %s,y", arr->AsmName);
+ AddCodeLine ("ldx %s+1,y", arr->AsmName);
+ AddCodeLine ("jmp callax");
+ }
+ } else if (CurTok.Tok == TOK_IDENT &&
+ (idx = FindSym (CurTok.Ident))) {
+ hie10 (&desc);
+ LoadExpr (CF_NONE, &desc);
+ AddCodeLine ("asl a");
+
+ if (CPUIsets[CPU] & CPU_ISET_65SC02) {
+ AddCodeLine ("tax");
+ AddCodeLine ("jmp (%s,x)", arr->AsmName);
+ } else {
+ AddCodeLine ("tay");
+ AddCodeLine ("lda %s,y", arr->AsmName);
+ AddCodeLine ("ldx %s+1,y", arr->AsmName);
+ AddCodeLine ("jmp callax");
+ }
+ } else {
+ Error ("Only simple expressions are supported for computed goto");
+ }
+
+ ConsumeRBrack ();
+
+ /* Loop over all target labels, specifying this as a jump point.
+ ** It's not exact - if there's multiple gotos, the last will be used,
+ ** but it's only needed so the optimizer does not remove the labels.
+ */
+ I = CS_GetEntryCount (CS->Code) - 1;
+ E = CS_GetEntry (CS->Code, I);
+
+ tab = GetLabelSymTab ();
+ if (tab) {
+ cur = tab->SymHead;
+ while (cur) {
+ if ((cur->Flags & (SC_LABEL|SC_GOTO_IND)) == (SC_LABEL|SC_GOTO_IND)) {
+ cur->V.L.IndJumpFrom = E;
+ }
+ cur = cur->NextSym;
+ }
+ }
+ }
+ } else {
+
+ Error ("Label name expected");
+ }
}
SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF);
/* Emit the jump label */
- g_defcodelabel (Entry->V.L.Label);
+ CodeLabel* L = CS_AddLabel (CS->Code, LocalLabelName (Entry->V.L.Label));
+ if (Entry->V.L.IndJumpFrom) {
+ CollAppend (&L->JumpFrom, Entry->V.L.IndJumpFrom);
+ }
/* Eat the ident and colon */
NextToken ();
for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) {
DOR = CollAt (Entry->V.L.DefsOrRefs, i);
- if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & SC_GOTO)) {
+ if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & (SC_GOTO|SC_GOTO_IND))) {
/* We're processing a goto and here is its destination label.
** This means the difference between SP values is already known,
** so we simply emit the SP adjustment code.
}
- if ((DOR->Flags & SC_REF) && (DOR->Flags & SC_GOTO) && (Flags & SC_DEF)) {
+ if ((DOR->Flags & SC_REF) && (DOR->Flags & (SC_GOTO|SC_GOTO_IND)) && (Flags & SC_DEF)) {
/* We're processing a label, let's update all gotos encountered
** so far
*/
- SymEntry *E;
- g_userodata();
- g_defdatalabel (DOR->LateSP_Label);
- g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
-
- /* Optimizer will need the information about the value of SP adjustment
- ** later, so let's preserve it.
- */
- E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT);
- E->V.SPAdjustment = StackPtr - DOR->StackPtr;
- AddSymEntry (SPAdjustTab, E);
+ if (DOR->Flags & SC_GOTO) {
+ SymEntry *E;
+ g_userodata();
+ g_defdatalabel (DOR->LateSP_Label);
+ g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
+
+ /* Optimizer will need the information about the value of SP adjustment
+ ** later, so let's preserve it.
+ */
+ E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT);
+ E->V.SPAdjustment = StackPtr - DOR->StackPtr;
+ AddSymEntry (SPAdjustTab, E);
+ }
/* Are we jumping into a block with initalization of an object that
** has automatic storage duration? Let's emit a warning.