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

Defined functions

ijxout defined in line 53; used 1 times
initijxxx defined in line 39; used 1 times
jalign defined in line 136; used 1 times
jxxxbump defined in line 478; used 3 times
jxxxfix defined in line 215; used 1 times

Defined variables

jbrfsize defined in line 28; used 5 times
jxxxfsize defined in line 29; used 3 times
lastjxxx defined in line 37; used 13 times
lastnam defined in line 36; used 7 times
sccsid defined in line 8; never used

Defined macros

BRW defined in line 16; used 1 times
JBR defined in line 15; used 2 times
JBRDELTA defined in line 23; used 2 times
JBRJDELTA defined in line 25; used 1 times
  • in line 41
JMP defined in line 17; used 1 times
JXXXDELTA defined in line 24; used 2 times
JXXXJDELTA defined in line 26; used 1 times
  • in line 42
Last modified: 1985-06-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1659
Valid CSS Valid XHTML 1.0 Strict