1/*****************************************************************************/
2/* */
3/* goto.c */
4/* */
5/* Goto and label handling for the cc65 C compiler */
6/* */
7/* */
8/* */
9/* (C) 2000 Ullrich von Bassewitz */
10/* Wacholderweg 14 */
11/* D-70597 Stuttgart */
12/* EMail: uz@musoftware.de */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36#include "asmlabel.h"
37#include "codeent.h"
38#include "codegen.h"
39#include "codeseg.h"
40#include "cpu.h"
41#include "error.h"
42#include "exprdesc.h"
43#include "expr.h"
44#include "loadexpr.h"
45#include "scanner.h"
46#include "standard.h"
47#include "symtab.h"
48#include "goto.h"
49
50
51
52/*****************************************************************************/
53/* Code */
54/*****************************************************************************/
55
56
57
58void GotoStatement (void)
59/* Process a goto statement. */
60{
61 /* Eat the "goto" */
62 NextToken ();
63
64 /* Label name must follow */
65 if (CurTok.Tok == TOK_IDENT) {
66
67 /* Add a new label symbol if we don't have one until now */
68 SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO);
69
70 /* Jump to the label */
71 g_jump (Entry->V.L.Label);
72
73 /* Eat the label name */
74 NextToken ();
75
76 } else if (CurTok.Tok == TOK_STAR && IS_Get (&Standard) >= STD_CC65) {
77 SymEntry *arr, *idx, *cur;
78 SymTable *tab;
79 ExprDesc desc;
80 CodeEntry *E;
81 unsigned char val;
82
83 NextToken ();
84
85 /* arr[foo], we only support simple foo for now */
86 if (CurTok.Tok == TOK_IDENT &&
87 (arr = FindSym (CurTok.Ident))) {
88 NextToken ();
89
90 /* Find array size */
91 if (!IsTypeArray (arr->Type) || SizeOf (arr->Type) == 0 ||
92 !(arr->Flags & SC_STATIC) ||
93 SizeOf (GetElementType(arr->Type)) != 2) {
94 Error ("Expected a static array");
95 } else if (GetElementCount (arr->Type) > 127) {
96 Error ("Only arrays with <= 127 labels are supported, got %lu",
97 GetElementCount (arr->Type));
98 }
99
100 ConsumeLBrack ();
101
102 if (CurTok.Tok == TOK_ICONST) {
103 val = (unsigned char)CurTok.IVal;
104 NextToken ();
105
106 if (CPUIsets[CPU] & CPU_ISET_65SC02) {
107 AddCodeLine ("ldx #$%02X", val * 2);
108 AddCodeLine ("jmp (.loword(%s),x)", arr->AsmName);
109 } else {
110 AddCodeLine ("ldy #$%02X", val * 2);
111 AddCodeLine ("lda %s,y", arr->AsmName);
112 AddCodeLine ("ldx %s+1,y", arr->AsmName);
113 AddCodeLine ("jmp callax");
114 }
115 } else if (CurTok.Tok == TOK_IDENT &&
116 (idx = FindSym (CurTok.Ident))) {
117 hie10 (&desc);
118 LoadExpr (CF_NONE, &desc);
119 AddCodeLine ("asl a");
120
121 if (CPUIsets[CPU] & CPU_ISET_65SC02) {
122 AddCodeLine ("tax");
123 AddCodeLine ("jmp (.loword(%s),x)", arr->AsmName);
124 } else {
125 AddCodeLine ("tay");
126 AddCodeLine ("lda %s,y", arr->AsmName);
127 AddCodeLine ("ldx %s+1,y", arr->AsmName);
128 AddCodeLine ("jmp callax");
129 }
130 } else {
131 Error ("Only simple expressions are supported for computed goto");
132 }
133
134 ConsumeRBrack ();
135
136 /* Loop over all target labels, specifying this as a jump point.
137 ** It's not exact -- if there's multiple gotos, the last will be used;
138 ** but, it's needed only so the optimizer does not remove the labels.
139 */
140 E = CS_GetEntry (CS->Code, CS_GetEntryCount (CS->Code) - 1);
141 tab = GetLabelSymTab ();
142 if (tab) {
143 cur = tab->SymHead;
144 while (cur) {
145 if ((cur->Flags & SC_GOTO_IND) != 0) {
146 cur->V.L.IndJumpFrom = E;
147 }
148 cur = cur->NextSym;
149 }
150 }
151 } else {
152 /* It was not TOK_IDENT, or we couldn't find the symbol */
153 Error ("Array name expected");
154 }
155 } else {
156 Error ("Label name expected");
157 }
158}
159
160
161
162void DoLabel (void)
163/* Define a label. */
164{
165 /* Add a label symbol */
166 SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF);
167
168 /* Emit the jump label */
169 CodeLabel* L = CS_AddLabel (CS->Code, LocalLabelName (Entry->V.L.Label));
170
171 if (Entry->V.L.IndJumpFrom) {
172 CollAppend (&L->JumpFrom, Entry->V.L.IndJumpFrom);
173 }
174
175 /* Eat the ident and colon */
176 NextToken ();
177 NextToken ();
178}
179