Annotation of 41BSD/cmd/as/asjxxx.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.