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