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