1 /* label.c - label handling routines for bcc */
2 
3 /* Copyright (C) 1992 Bruce Evans */
4 
5 #include "bcc.h"
6 #include "condcode.h"
7 #include "gencode.h"
8 #include "label.h"
9 #include "output.h"
10 #include "sc.h"
11 #include "scan.h"
12 #include "sizes.h"
13 #include "type.h"
14 
15 #ifdef I8088
16 # define outlbranch() outop3str( "b")
17 # define outsbranch() outop2str( "j")
18 #endif
19 #ifdef MC6809
20 # define outlbranch() outop3str( "LB")
21 # define outsbranch() outop2str( "B")
22 #endif
23 
24 #define MAXVISLAB 32
25 
26 struct labdatstruct
27 {
28     label_no labnum;		/* 0 if not active */
29     offset_T lablc;		/* location counter for branch or label */
30     char *labpatch;		/* buffer ptr for branch, NULL for label */
31     ccode_t labcond;		/* condition code for branch */
32 };
33 
34 #ifdef I8088
35 PRIVATE char lcondnames[][2] =	/* names of long condition codes */
36 {
37     { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', },
38     { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', },
39     { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' },
40 };
41 PRIVATE char scondnames[][2] =	/* names of short condition codes */
42 {
43     { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, },
44     { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', },
45     { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', },
46 };
47 #endif
48 
49 #ifdef MC6809
50 PRIVATE char condnames[][2] =	/* names of condition codes */
51 {
52     { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', },
53     { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', },
54     { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', },
55 };
56 #endif
57 
58 PRIVATE label_no lasthighlab = 0xFFFF+1;	/* temp & temp init so labels fixed */
59 				/* lint */
60 PRIVATE label_no lastlab;	/* bss init to 0 */
61 PRIVATE offset_T lc;		/* bss init to 0 */
62 
63 PRIVATE struct labdatstruct vislab[MAXVISLAB];	/* bss, all labnum's init 0 */
64 PRIVATE smalin_t nextvislab;	/* bss init to NULL */
65 PRIVATE struct symstruct *namedfirst;	/* bss init to NULL */
66 PRIVATE struct symstruct *namedlast;	/* bss init to NULL */
67 
68 FORWARD void addlabel P((ccode_pt cond, label_no label, char *patch));
69 FORWARD struct labdatstruct *findlabel P((label_no label));
70 
71 /* add label to circular list */
72 
addlabel(cond,label,patch)73 PRIVATE void addlabel(cond, label, patch)
74 ccode_pt cond;
75 label_no label;
76 char *patch;
77 {
78     register struct labdatstruct *labptr;
79 
80     labptr = &vislab[(int)nextvislab];
81     labptr->labcond = cond;
82     labptr->labnum = label;
83     labptr->lablc = lc;
84     labptr->labpatch = patch;
85     if (++nextvislab == MAXVISLAB)
86 	nextvislab = 0;
87 }
88 
89 /* bump location counter */
90 
bumplc()91 PUBLIC void bumplc()
92 {
93     ++lc;
94 }
95 
96 /* bump location counter by 2 */
97 
bumplc2()98 PUBLIC void bumplc2()
99 {
100     lc += 2;
101 }
102 
103 /* bump location counter by 3 */
104 
bumplc3()105 PUBLIC void bumplc3()
106 {
107     lc += 3;
108 }
109 
110 /* clear out labels in function */
111 
clearfunclabels()112 PUBLIC void clearfunclabels()
113 {
114     register struct symstruct *symptr;
115     register struct symstruct *tmp;
116 
117     for (symptr = namedfirst; symptr != NULL;)
118     {
119 	if (symptr->indcount == 2)
120 	    error("undefined label");
121 	symptr->indcount = 0;
122 	tmp = symptr;
123 	symptr = (struct symstruct *) symptr->type;
124 	tmp->type = NULL;
125     }
126     namedlast = namedfirst = NULL;
127 }
128 
129 /* clear out labels no longer in buffer */
130 
clearlabels(patchbuf,patchtop)131 PUBLIC void clearlabels(patchbuf, patchtop)
132 char *patchbuf;
133 char *patchtop;
134 {
135     register struct labdatstruct *labptr;
136     struct labdatstruct *labtop;
137     register char *labpatch;
138 
139     for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
140 	 labptr < labtop; ++labptr)
141 	if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop)
142 	    labptr->labnum = 0;
143 }
144 
145 /* clear out labels in switch statement */
146 
clearswitchlabels()147 PUBLIC void clearswitchlabels()
148 {
149     register struct symstruct *symptr;
150 
151     for (symptr = namedfirst; symptr != NULL;
152 	 symptr = (struct symstruct *) symptr->type)
153 	if (symptr->indcount == 3)
154 	{
155 	    equlab(symptr->offset.offlabel, lowsp);
156 	    symptr->indcount = 4;
157 	}
158 }
159 
160 /* return location counter */
161 
getlc()162 PUBLIC uoffset_T getlc()
163 {
164     return (uoffset_T) lc;
165 }
166 
167 /* define location of label and backpatch references to it */
168 
deflabel(label)169 PUBLIC void deflabel(label)
170 label_no label;
171 {
172     char *cnameptr;
173     struct labdatstruct *labmin;
174     struct labdatstruct *labmax;
175     struct labdatstruct *labmid;
176     struct labdatstruct *labptrsave;
177     offset_T nlonger;
178 
179     outnlabel(label);
180     {
181 	register struct labdatstruct *labptr;
182 	register char *labpatch;
183 
184 	labmin = &vislab[0];
185 	labmax = &vislab[MAXVISLAB];
186 	labptr = labmid = &vislab[(int)nextvislab];
187 	if (!watchlc)
188 	    do
189 	    {
190 		if (labptr == labmin)
191 		    labptr = &vislab[MAXVISLAB];
192 		--labptr;
193 		if (labptr->labnum == label)
194 		{
195 		    if ((labpatch = labptr->labpatch) != NULL &&
196 			isshortbranch(lc - labptr->lablc))
197 		    {
198 #ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */
199 			*labpatch = 'j';
200 			*(labpatch + 1) =
201 			    *(cnameptr = scondnames[(int)labptr->labcond]);
202 #endif
203 #ifdef MC6809
204 # ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
205 			*labpatch = 'B';
206 			*(labpatch + 4) = '\t';	/* redundant unless JMP */
207 			*(labpatch + 1) =
208 			    *(cnameptr = condnames[labptr->labcond]);
209 # else
210 			if (labptr->labcond == RA)
211 			    strncpy(labpatch, "BRA\t\t", 5);
212 			else
213 			    *labpatch = '\t';
214 			goto over;
215 # endif
216 #endif
217 			*(labpatch + 2) = *(cnameptr + 1);
218 			*(labpatch + 3) = ' ';
219 #ifdef MC6809
220 # ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
221 		over: ;		/* temp regression test kludge */
222 # endif
223 #endif
224 			nlonger = jcclonger;
225 			if (labptr->labcond == RA)
226 			    nlonger = jmplonger;
227 			lc -= nlonger;
228 			labptrsave = labptr;
229 			while (++labptr != labmid)
230 			    if (labptr == labmax)
231 				labptr = &vislab[-1];
232 			    else
233 				labptr->lablc -= nlonger;
234 			labptr = labptrsave;
235 		    }
236 		}
237 	    }
238 	    while (labptr != labmid);
239     }
240     addlabel((ccode_pt) 0, label, (char *) NULL);
241 }
242 
findlabel(label)243 PRIVATE struct labdatstruct *findlabel(label)
244 label_no label;
245 {
246     register struct labdatstruct *labptr;
247     struct labdatstruct *labtop;
248 
249     for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
250 	 labptr < labtop; ++labptr)
251 	if (labptr->labnum == label)
252 	{
253 	    if (labptr->labpatch != 0)
254 		break;
255 	    return labptr;
256 	}
257     return (struct labdatstruct *) NULL;
258 }
259 
260 /* reserve a new label, from top down to temp avoid renumbering low labels */
261 
gethighlabel()262 PUBLIC label_no gethighlabel()
263 {
264     return --lasthighlab;
265 }
266 
267 /* reserve a new label */
268 
getlabel()269 PUBLIC label_no getlabel()
270 {
271     return ++lastlab;
272 }
273 
274 /* jump to label */
275 
jump(label)276 PUBLIC void jump(label)
277 label_no label;
278 {
279     lbranch(RA, label);
280 }
281 
282 /* long branch on condition to label */
283 
lbranch(cond,label)284 PUBLIC void lbranch(cond, label)
285 ccode_pt cond;
286 label_no label;
287 {
288 #ifdef I8088
289     char *cnameptr;
290 
291 #endif
292     struct labdatstruct *labptr;
293     char *oldoutptr;
294 
295     if ((ccode_t) cond == RN)
296 	return;
297     if ((labptr = findlabel(label)) != NULL &&
298 	isshortbranch(lc - labptr->lablc + 2))
299     {
300 	sbranch(cond, label);
301 	return;
302     }
303     oldoutptr = outbufptr;
304     if (cond == RA)
305 	outjumpstring();
306     else
307     {
308 	outlbranch();
309 #ifdef I8088
310 	outbyte(*(cnameptr = lcondnames[(int) cond]));
311 	outbyte(*(cnameptr + 1));
312 	if ((ccode_t) cond == LS || (ccode_t) cond == HS)
313 	    outbyte('s');	/* "blos" or "bhis" */
314 	else
315 	    outbyte(' ');
316 	outtab();
317 	bumplc2();
318 #ifdef I80386
319 	if (i386_32)
320 	    bumplc();
321 #endif
322 #endif
323 #ifdef MC6809
324 	outcond(cond);
325 	bumplc();
326 #endif
327     }
328     outlabel(label);
329     outnl();
330     if (labptr == NULL && oldoutptr < outbufptr)	/* no wrap-around */
331 	addlabel(cond, label, oldoutptr);
332 }
333 
334 /* look up the name gsname in label space, install it if new */
335 
namedlabel()336 PUBLIC struct symstruct *namedlabel()
337 {
338     struct symstruct *symptr;
339 
340     gs2name[1] = 0xFF;
341     if ((symptr = findlorg(gs2name + 1)) == NULL)
342     {
343 	symptr = addglb(gs2name + 1, vtype);
344 	symptr->flags = LABELLED;
345     }
346     if (symptr->indcount < 2)
347     {
348 	symptr->indcount = 2;
349 	symptr->offset.offlabel = gethighlabel();
350 	if (namedfirst == NULL)
351 	    namedfirst = symptr;
352 	else
353 	    namedlast->type = (struct typestruct *) symptr;
354 	namedlast = symptr;
355 	symptr->type = NULL;
356     }
357     return symptr;
358 }
359 
360 #ifdef MC6809
361 
362 /* print condition code name */
363 
outcond(cond)364 PUBLIC void outcond(cond)
365 ccode_pt cond;
366 {
367     char *cnameptr;
368 
369     outbyte(*(cnameptr = condnames[(ccode_t) cond]));
370     outbyte(*(cnameptr + 1));
371     outtab();
372 }
373 
374 #endif
375 
376 /* print label */
377 
outlabel(label)378 PUBLIC void outlabel(label)
379 label_no label;
380 {
381     outbyte(LABELSTARTCHAR);
382     outhexdigs((uoffset_T) label);
383 }
384 
385 /* print label and newline */
386 
outnlabel(label)387 PUBLIC void outnlabel(label)
388 label_no label;
389 {
390     outlabel(label);
391 #ifdef LABELENDCHAR
392     outnbyte(LABELENDCHAR);
393 #else
394     outnl();
395 #endif
396 }
397 
398 /* short branch on condition to label */
399 
sbranch(cond,label)400 PUBLIC void sbranch(cond, label)
401 ccode_pt cond;
402 label_no label;
403 {
404 #ifdef I8088
405     char *cnameptr;
406 
407     if ((ccode_t) cond != RN)
408     {
409 	outsbranch();
410 	outbyte(*(cnameptr = scondnames[(int) cond]));
411 	outbyte(*(cnameptr + 1));
412 	outtab();
413 	outlabel(label);
414 	outnl();
415     }
416 #endif
417 #ifdef MC6809
418     outsbranch();
419     outcond(cond);
420     outlabel(label);
421     outnl();
422 #endif
423 }
424 
425 /* reverse bump location counter */
426 
unbumplc()427 PUBLIC void unbumplc()
428 {
429     --lc;
430 }
431