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