use struct nlist; change field names; vgrind format fixes
[unix-history] / usr / src / old / as.vax / asjxxx.c
CommitLineData
d0d638ee 1/* Copyright (c) 1980 Regents of the University of California */
451260e7 2static char sccsid[] = "@(#)asjxxx.c 4.2 %G%";
d0d638ee 3#include <stdio.h>
d0d638ee
BJ
4#include "as.h"
5#include "assyms.h"
6
7#define JBR 0x11
8#define BRW 0x31
9
10/*
11 * The number of bytes to add if the jxxx must be "exploded"
12 * into the long form
13 */
14#define JBRFSIZE 1 /*goes to brw*/
15#define JXXXFSIZE 3 /*goes to brb, brw <byte> <byte> */
16
17/*
18 * These variables are filled by asscan.c with the
19 * last name encountered (a pointer buried in the intermediate file),
20 * and the last jxxx symbol table entry encountered.
21 */
22struct symtab *lastnam;
23struct symtab *lastjxxx;
24
25/*
26 * Handle jxxx instructions
27 */
28ijxout(op,ap,nact)
29 struct arg *ap;
30{
31 if (passno == 1){
32 /*
33 * READ THIS BEFORE LOOKING AT jxxxfix()
34 *
35 * Record the jxxx in a special symbol table entry
36 */
37 register struct symtab *jumpfrom;
38
39 /*
40 * We assume the MINIMAL length
41 */
42 putins(op,ap,nact);
43 jumpfrom = lastjxxx;
451260e7
RH
44 jumpfrom->s_tag = JXACTIVE;
45 jumpfrom->s_jxbump = 0;
d0d638ee 46 if (op == JBR)
451260e7 47 jumpfrom->s_jxfear = JBRFSIZE;
d0d638ee 48 else
451260e7 49 jumpfrom->s_jxfear = JXXXFSIZE;
d0d638ee
BJ
50 if (lastnam == 0)
51 yyerror("jxxx destination not a label");
451260e7
RH
52 jumpfrom->s_dest = lastnam;
53 jumpfrom->s_type = dotp->e_xtype; /*only TEXT or DATA*/
54 jumpfrom->s_index = dotp-usedot;
d0d638ee
BJ
55 /*
56 * value ALWAYS (ALWAYS!!!) indexes the next instruction
57 * after the jump, even in the jump must be exploded
58 * (bumped)
59 */
451260e7 60 jumpfrom->s_value = dotp->e_xvalue;
d0d638ee
BJ
61 njxxx++;
62 } else {/* pass2, resolve */
63 /*
64 * READ THIS AFTER LOOKING AT jxxxfix()
65 */
66 register long oxvalue;
67 register struct exp *xp;
68 register struct symtab *tunnel;
69 register struct arg *aplast;
70
71 aplast = ap + nact - 1;
451260e7
RH
72 xp = aplast->a_xp;
73 if (lastjxxx->s_tag == JXTUNNEL){
74 lastjxxx->s_tag = JXINACTIVE;
75 tunnel = lastjxxx->s_dest;
76 xp->e_xvalue = tunnel->s_value /*index of instruction following*/
d0d638ee 77 - 3 /* size of brw + word*/
451260e7
RH
78 + ( ( (tunnel->s_jxfear == JBRFSIZE) &&
79 (tunnel->s_jxbump == 0))?1:0);
d0d638ee
BJ
80 /*non bumped branch byteis only 2 back*/
81 }
451260e7 82 if (lastjxxx->s_jxbump == 0){ /*wasn't bumped, so is short form*/
d0d638ee
BJ
83 putins(op, ap, nact);
84 } else {
85 if (op != JBR){ /*branch reverse conditional byte over
86 branch unconditional word*/
451260e7
RH
87 oxvalue = xp->e_xvalue;
88 xp->e_xvalue = lastjxxx->s_value;
d0d638ee 89 putins(op^1, ap, nact);
451260e7 90 xp->e_xvalue = oxvalue;
d0d638ee
BJ
91 }
92 putins(BRW, aplast, 1);
93 }
94 }
95} /*end of ijxout*/
96
97jalign(xp, sp)
98 register struct exp *xp;
99 register struct symtab *sp;
100{
101 register int mask;
451260e7 102 if (xp->e_xtype != XABS || xp->e_xvalue < 0 || xp->e_xvalue > 16) {
d0d638ee
BJ
103 yyerror("Illegal `align' argument");
104 return;
105 }
106 flushfield(NBPW/4);
107 if (passno == 1) {
451260e7
RH
108 sp->s_tag = JXALIGN;
109 sp->s_jxfear = (1 << xp->e_xvalue) - 1;
110 sp->s_type = dotp->e_xtype;
111 sp->s_index = dotp-usedot;
d0d638ee
BJ
112 /*
113 * We guess that the align will take up at least one
114 * byte in the code output. We will correct for this
115 * initial high guess when we explode (bump) aligns
116 * when we fix the jxxxes. We must do this guess
117 * so that the symbol table is sorted correctly
118 * and labels declared to fall before the align
119 * really get their, instead of guessing zero size
120 * and have the label (incorrectly) fall after the jxxx.
121 * This is a quirk of our requirement that indices into
122 * the code stream point to the next byte following
123 * the logical entry in the symbol table
124 */
451260e7
RH
125 dotp->e_xvalue += 1;
126 sp->s_value = dotp->e_xvalue;
d0d638ee
BJ
127 njxxx++;
128 } else {
451260e7
RH
129 mask = (1 << xp->e_xvalue) - 1;
130 while (dotp->e_xvalue & mask){
d0d638ee
BJ
131#ifdef UNIX
132 outb(0);
133#endif UNIX
134#ifdef VMS
135 *vms_obj_ptr++ = -1;
136 *vms_obj_ptr++ = 0;
451260e7 137 dotp->e_xvalue += 1;
d0d638ee
BJ
138#endif VMS
139 }
140 }
141}
142
143/*
144 * Pass 1.5, resolve jxxx instructions and .align in .text
145 */
146jxxxfix()
147{
148 register struct symtab *jumpfrom;
149 struct symtab **cojumpfrom, *ubjumpfrom;
150 register struct symtab *dest;
151 register struct symtab *intdest; /*intermediate dest*/
152 register struct symtab **cointdest, *ubintdest;
153
154 register struct symtab *tunnel;
155 int displ,nchange;
156 int badjxalign; /*if jump across an align*/
157 int stillactives; /*if still active jxxxes*/
158 int segno; /*current segment number*/
159 int topono; /*which iteration in the topo sort*/
160 register unsigned char tag;
161 /*
162 * consider each segment in turn...
163 */
164 for (segno = 0; segno < NLOC + NLOC; segno++){
165 badjxalign = 0; /*done on a per segment basis*/
166 /*
167 * Do a lazy topological sort.
168 */
169 for (topono = 1, nchange = 1; nchange != 0; topono++){
170#ifdef DEBUG
171 if (debug)
172 printf("\nSegment %d, topo iteration %d\n",
173 segno, topono);
174#endif
175 nchange = 0;
176 stillactives = 0;
177 /*
178 * We keep track of one possible tunnel location.
179 * A tunnel will eventually be an unconditional
180 * branch to the same place that another jxxx
181 * will want to branch to. We will turn a
182 * branch conditional/unconditional (word) that would
183 * have to get bumped because its destination is too
184 * far away, into a branch conditional/unconditional
185 * byte to the tunnel branch conditional/unconditional.
186 * Of course, the tunnel must branch to the same place
187 * as we want to go.
188 */
189 tunnel = 0; /*initially, no tunnel*/
190 SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom, ubjumpfrom, ++){
451260e7 191 tag = jumpfrom->s_tag;
d0d638ee
BJ
192 if (tag <= IGNOREBOUND)
193 continue; /*just an ordinary symbol*/
194 if (tag == JXALIGN){
195 tunnel = 0; /*avoid tunneling across a flex alocation*/
196 continue; /*we take care of these later*/
197 }
451260e7 198 if ( jumpfrom->s_jxfear == JBRFSIZE /*unconditional*/
d0d638ee 199 || ( tag == JXINACTIVE /*inactive bumped*/
451260e7 200 && (jumpfrom->s_jxbump != 0)
d0d638ee
BJ
201 )
202 ) tunnel = jumpfrom;
203 if (tag != JXACTIVE)
204 continue;
451260e7
RH
205 dest = jumpfrom->s_dest;
206 if (jumpfrom->s_index != dest->s_index){
d0d638ee
BJ
207 yyerror("Intersegment jxxx");
208 continue;
209 }
451260e7 210 displ = dest->s_value - jumpfrom->s_value;
d0d638ee
BJ
211 if (displ < MINBYTE || displ > MAXBYTE) {
212 /*
213 * This is an immediate lose!
214 *
215 * We first attempt to tunnel
216 * by finding an intervening jump that
217 * has the same destination.
218 * The tunnel is always the first preceeding
219 * jxxx instruction, so the displacement
220 * to the tunnel is less than zero, and
221 * its relative position will be unaffected
222 * by future jxxx expansions.
223 */
451260e7 224 if ( (jumpfrom->s_jxfear > JBRFSIZE)
d0d638ee 225 && (tunnel)
451260e7
RH
226 && (tunnel->s_dest == jumpfrom->s_dest)
227 && (tunnel->s_index == jumpfrom->s_index)
228 && (tunnel->s_value - jumpfrom->s_value >=
d0d638ee
BJ
229 MINBYTE + JXXXFSIZE)
230 ) {
231 /*
232 * tunnelling is OK
233 */
451260e7 234 jumpfrom->s_dest = tunnel;
d0d638ee
BJ
235 /*
236 * no bumping needed, this
237 * is now effectively inactive
238 * but must be remembered
239 */
451260e7 240 jumpfrom->s_tag = JXTUNNEL;
d0d638ee
BJ
241#ifdef DEBUG
242 if(debug)
243 printf("Tunnel from %s from line %d\n",
451260e7 244 jumpfrom->s_name, lineno);
d0d638ee
BJ
245#endif
246 continue;
247 } else { /*tunneling not possible*/
248 /*
249 * since this will be turned
250 * into a bumped jump, we can
251 * use the unconditional jump
252 * as a tunnel
253 */
254 tunnel = jumpfrom;
451260e7 255 jumpfrom->s_tag = JXNOTYET;
d0d638ee
BJ
256 ++nchange;
257 continue;
258 }
259 } /*end of immediate lose*/
260 /*
261 * Do a forward search for an intervening jxxx
262 */
263 if (displ >= 0) {
264 SEGITERATE(segno, cojumpfrom + 1,0,cointdest,
265 intdest, ubintdest, ++){
451260e7 266 if (intdest->s_value > dest->s_value)
d0d638ee 267 break; /* beyond destination */
451260e7 268 if (intdest->s_tag <= JXQUESTIONABLE)
d0d638ee 269 continue; /*frozen solid*/
451260e7
RH
270 if (intdest->s_tag == JXALIGN){
271 jumpfrom->s_jxoveralign = 1;
d0d638ee
BJ
272 badjxalign++;
273 }
274 /*
275 * we assume the worst case
276 * for unfrozen jxxxxes
277 */
451260e7 278 displ += intdest->s_jxfear;
d0d638ee
BJ
279 }
280 if (displ <= MAXBYTE){
281 /*
282 * the worst possible conditions
283 * can't hurt us, so forget about
284 * this jump
285 */
451260e7 286 jumpfrom->s_tag = JXINACTIVE;
d0d638ee
BJ
287 } else {
288 stillactives++;
289 }
290 } else {
291 /*
292 * backward search for intervening jxxx
293 */
294 SEGITERATE(segno, cojumpfrom - 1,1,cointdest,
295 intdest, ubintdest, --){
451260e7 296 if (intdest->s_value <= dest->s_value)
d0d638ee 297 break; /* beyond destination */
451260e7 298 if (intdest->s_tag <= JXQUESTIONABLE)
d0d638ee 299 continue; /*frozen solid*/
451260e7
RH
300 if (intdest->s_tag == JXALIGN){
301 jumpfrom->s_jxoveralign = 1;
d0d638ee
BJ
302 badjxalign++;
303 }
451260e7 304 displ -= intdest->s_jxfear;
d0d638ee
BJ
305 }
306 if (displ >= MINBYTE) {
451260e7 307 jumpfrom->s_tag = JXINACTIVE;
d0d638ee
BJ
308 } else {
309 stillactives++;
310 }
311 } /*end of backwards search*/
312 } /*end of iterating through all symbols in this seg*/
313
314 if (nchange == 0) {
315 /*
316 * Now, if there are still active jxxx entries,
317 * we are partially deadlocked. We can leave
318 * these jxxx entries in their assumed short jump
319 * form, as all initial displacement calcualtions
320 * are hanging on unresolved jxxx instructions
321 * that might explode into a long form, causing
322 * other jxxxes jumping across the first set of
323 * jxxxes to explode, etc.
324 * However, if a jxxx jumps across a .align,
325 * we assume the worst for the deadlock cycle,
326 * and resolve all of them towards the long
327 * jump.
328 * Currently, the C compiler does not produce
329 * jumps across aligns, as aligns are only used
330 * in data segments, or in text segments to align
331 * functions.
332 */
333 if (stillactives){
334 SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
335 ubjumpfrom, ++){
451260e7
RH
336 if (jumpfrom->s_tag == JXACTIVE){
337 jumpfrom->s_tag =
d0d638ee
BJ
338 badjxalign?JXNOTYET:JXINACTIVE;
339 }
340 }
341 if (badjxalign){
342 jxxxbump(segno, (struct symtab **)0);
343 }
344 }
345 /*
346 * Handle all of the .align s
347 */
348 SEGITERATE(segno, 0, 0, cojumpfrom, jumpfrom,
349 ubjumpfrom, ++){
451260e7 350 if (jumpfrom->s_tag == JXALIGN){
d0d638ee
BJ
351 /*
352 * Predict the true displacement
353 * needed, irregardless of the
354 * fact that we guessed 1
355 */
451260e7 356 displ = (jumpfrom->s_value - 1) & (unsigned)jumpfrom->s_jxfear;
d0d638ee 357 if (displ == 0){ /*no virtual displacement*/
451260e7 358 jumpfrom->s_jxfear = -1;
d0d638ee 359 } else {
451260e7 360 jumpfrom->s_jxfear = (jumpfrom->s_jxfear + 1) - displ;
d0d638ee 361 /*
451260e7 362 * assert jumpfrom->s_jxfear > 0
d0d638ee 363 */
451260e7 364 if (jumpfrom->s_jxfear == 1){
d0d638ee
BJ
365 /*our prediction was correct*/
366 continue;
367 }
368 /*
451260e7 369 * assert jumpfrom->s_jxfear > 1
d0d638ee 370 */
451260e7 371 jumpfrom->s_jxfear -= 1; /*correct guess*/
d0d638ee
BJ
372 }
373 /*
451260e7 374 * assert jumpfrom->s_jxfear = -1, +1...2**n-1
d0d638ee 375 */
451260e7 376 jumpfrom->s_tag = JXNOTYET; /*signal*/
d0d638ee 377 jxxxbump(segno, cojumpfrom);
451260e7 378 jumpfrom->s_tag = JXINACTIVE;
d0d638ee
BJ
379 /*
380 * Assert jxfrom->jxvalue indexes the first
381 * code byte after the added bytes, and
382 * has n low order zeroes.
383 */
384 }
385 } /*end of walking through each segment*/
386 } /*end of no changes */
387 else { /*changes, and still have to try another pass*/
388 jxxxbump(segno, (struct symtab **)0);
389 }
390 } /*end of doing the topologic sort*/
391 } /*end of iterating through all segments*/
392} /*end of jxxxfix*/
393
394/*
395 * Go through the symbols in a given segment number,
396 * and see which entries are jxxx entries that have
397 * been logically "exploded" (expanded), but for which
398 * the value of textually following symbols has not been
399 * increased
400 */
401
402jxxxbump(segno, starthint)
403 int segno;
404 struct symtab **starthint;
405{
406 register struct symtab **cosp, *sp;
407 register struct symtab *ub;
408 register int cum_bump;
409 register unsigned char tag;
410
411 cum_bump = 0;
412 SEGITERATE(segno, starthint, 0, cosp, sp, ub, ++){
451260e7 413 tag = sp->s_tag;
d0d638ee
BJ
414 if (tag == JXNOTYET){
415#ifdef DEBUG
416 if (debug){
451260e7 417 if (sp->s_dest != 0)
d0d638ee 418 printf("Explode jump to %s on line %d\n",
451260e7 419 sp->s_dest->s_name, lineno);
d0d638ee
BJ
420 else
421 printf("Explode an align!\n");
422 }
423#endif
451260e7
RH
424 sp->s_tag = JXINACTIVE;
425 sp->s_jxbump = 1;
426 cum_bump += sp->s_jxfear;
d0d638ee
BJ
427 }
428 /*
429 * Only bump labels and jxxxes. Ignored entries can
430 * be incremented, as they are thrown away later on.
431 * Stabds are given their final value in the second
432 * pass.
433 */
434 if (tag >= OKTOBUMP) /*only bump labels and jxxxes and floating stabs*/
451260e7 435 sp->s_value += cum_bump;
d0d638ee 436 }
451260e7 437 usedot[segno].e_xvalue += cum_bump;
d0d638ee 438}