|
|
1.1 ! root 1: /* ! 2: * This file contains a fairly general writer for Intel iAPX-86 OMF. ! 3: * The 'out...' routines write to a temporary file during code assembly. ! 4: * At the end of assembly, 'copycode' uses the 'put...' routines ! 5: * to write the object file. ! 6: * This is necessary: SEGDEF records must be written before ! 7: * LEDATA and FIXUPP records, but each SEGDEF includes the size ! 8: * of the segment in bytes. ! 9: */ ! 10: ! 11: /* ! 12: * References: "8086 Relocatable Object Formats," ! 13: * Intel 121748-001 (C) Intel 1981. ! 14: * "Type Definition Records for High Level Languages," ! 15: * Version 2.0, 6/25/84, Intel 114834 (Intel proprietary). ! 16: */ ! 17: ! 18: #ifdef vax ! 19: #include "INC$LIB:cc2.h" ! 20: #else ! 21: #include "cc2.h" ! 22: #endif ! 23: ! 24: /* ! 25: * As of 4/29/85, PSCOPE does not support unnamed blocks correctly. ! 26: * The output writer therefore suppresses unnamed blocks #ifdef NOABLOCKS. ! 27: */ ! 28: #if INTEL ! 29: #define NOABLOCKS 1 ! 30: int blkcount; ! 31: #endif ! 32: ! 33: #define NTXT 256 /* Text buffer size */ ! 34: #define NREL 256 /* Relocation buffer size */ ! 35: ! 36: #ifndef __LINE__ ! 37: #define __LINE__ 0 ! 38: #endif ! 39: ! 40: /* ! 41: * Scratch file opcodes. ! 42: * Flags are or'ed in to TBYTE and TWORD opcodes only. ! 43: */ ! 44: #define TTYPE 07 /* Type */ ! 45: #define TPCR 010 /* PC relative flag */ ! 46: #define TSYM 020 /* Symbol based flag */ ! 47: ! 48: #define TEND 00 /* End marker */ ! 49: #define TENTER 01 /* Enter new area */ ! 50: #define TBYTE 02 /* Byte data */ ! 51: #define TWORD 03 /* Word data */ ! 52: #define TCODE 04 /* Code segment base */ ! 53: #define TDATA 05 /* Data segment base */ ! 54: #define TBASE 06 /* External segment base */ ! 55: #define TDLAB 07 /* Debug label */ ! 56: #define TDLOC 010 /* Debug location */ ! 57: ! 58: #if EMUFIXUPS ! 59: /* ! 60: * If EMUFIXUPS is defined at compile time, the generated output writer ! 61: * targets 8087 instructions with magic "M:..." fixups. ! 62: * The linker can then create objects which use either 8087 hardware ! 63: * or software floating point emulation; in the latter case, the ! 64: * linker changes the 8087 instructions into traps to the emulator. ! 65: */ ! 66: #define T8087 0340 /* 8087 flags */ ! 67: #define TWT 0040 /* M:_WT */ ! 68: #define TWST 0100 /* M:_WST */ ! 69: #define TWES 0140 /* M:_WES */ ! 70: #define TWCS 0200 /* M:_WCS */ ! 71: #define TWSS 0240 /* M:_WSS */ ! 72: #define TWDS 0300 /* M:_WDS */ ! 73: #endif ! 74: ! 75: /* ! 76: * OMF types. ! 77: */ ! 78: #define BLKDEF 0x7A /* Block definition */ ! 79: #define BLKEND 0x7C /* Block end */ ! 80: #define DEBSYM 0x7E /* Debug symbol */ ! 81: #define THEADR 0x80 /* Translator module header */ ! 82: #define COMENT 0x88 /* Comment */ ! 83: #define MODEND 0x8A /* Module end */ ! 84: #define EXTDEF 0x8C /* External definition (reference) */ ! 85: #define TYPDEF 0x8E /* Type definition */ ! 86: #define PUBDEF 0x90 /* Public definition (definition) */ ! 87: #define LINNUM 0x94 /* Line # */ ! 88: #define LNAMES 0x96 /* List of names */ ! 89: #define SEGDEF 0x98 /* Segment definition */ ! 90: #define GRPDEF 0x9A /* Group definition */ ! 91: #define FIXUPP 0x9C /* Fixups */ ! 92: #define LEDATA 0xA0 /* Enumerated data */ ! 93: #define LIDATA 0xA2 /* Iterated data */ ! 94: ! 95: /* ! 96: * Some OMF fields and flags. ! 97: */ ! 98: #define PARA (0x03<<5) /* Paragraph alignment */ ! 99: #define BIG 0x02 /* 64k */ ! 100: #define CCON (0x02<<2) /* C field, concatenate */ ! 101: #define CMEM (0x01<<2) /* C field, memory */ ! 102: #define CSTACK (0x05<<2) /* C field, stack */ ! 103: ! 104: #define LOCAT 0x80 /* Locat flag bit */ ! 105: #define M 0x40 /* M bit; 0=self rel, 1=seg rel */ ! 106: #define LOBYTE (0x00<<2) /* Locat */ ! 107: #define OFFSET (0x01<<2) /* Locat */ ! 108: #define BASE (0x02<<2) /* Locat */ ! 109: #define POINTER (0x03<<2) /* Locat */ ! 110: #define HIBYTE (0x04<<2) /* Locat */ ! 111: ! 112: #define SECWAY 0x04 /* Secondary way */ ! 113: #define FD8087 0x36 /* FIXDAT for 8087 fixup */ ! 114: #define FSI (0<<4) /* Frame segment index */ ! 115: #define FGI (1<<4) /* Frame group index */ ! 116: #define FEI (2<<4) /* Frame external index */ ! 117: #define FFN (3<<4) /* Frame frame number */ ! 118: #define FLSEG (4<<4) /* Frame of LSEG */ ! 119: #define FTARGET (5<<4) /* Frame of TARGET object */ ! 120: #define FNONE (6<<4) /* No frame */ ! 121: #define TSI 0 /* Target: segment index */ ! 122: #define TGI 1 /* Target: group index */ ! 123: #define TEI 2 /* Target: external index */ ! 124: #define TFN 3 /* Target: frame */ ! 125: #define F 0x80 /* Frame thread used */ ! 126: #define T 0x08 /* Target thread used */ ! 127: #define FT0 0x00 /* 0 */ ! 128: #define FT1 0x10 /* 1 */ ! 129: ! 130: /* ! 131: * Type representations for TYPDEF records. ! 132: */ ! 133: #if INTEL ! 134: /* Intel proprietary. */ ! 135: #define OTSFUNC 0x5E /* SHORT$NOPOP */ ! 136: #define OTLFUNC 0x5F /* LONG$NOPOP */ ! 137: #define OTUPACK 0x66 /* Unpacked */ ! 138: #define OTLABEL 0x71 /* LABEL */ ! 139: #define OTLONG 0x72 /* LONG */ ! 140: #define OTSHORT 0x73 /* SHORT */ ! 141: #define OTPROC 0x74 /* PROCEDURE */ ! 142: #define OTPARA 0x75 /* PARAMETER */ ! 143: #define OTARRAY 0x77 /* ARRAY */ ! 144: #define OTSTRUC 0x79 /* STRUCTURE */ ! 145: #define OTPOINT 0x7A /* POINTER */ ! 146: #define OTSCAL 0x7B /* SCALAR */ ! 147: #define OTUINT 0x7C /* UNSINT */ ! 148: #define OTSINT 0x7D /* SGNINT */ ! 149: #define OTREAL 0x7E /* REAL */ ! 150: #define OTLIST 0x7F /* LIST */ ! 151: #endif ! 152: ! 153: #define OTNIL 0x80 /* NIL */ ! 154: #define OTUNUM2 0x81 /* Unsigned numeric (2 byte) leaf */ ! 155: #define OTNAME 0x82 /* Name leaf */ ! 156: #define OTINDEX 0x83 /* Index leaf */ ! 157: #define OTUNUM3 0x84 /* Unsigned numeric (3 byte) leaf */ ! 158: ! 159: /* ! 160: * A linked list of TINFO records containing OMF type definitions ! 161: * is generated while reading DLABEL records. ! 162: * The type index corresponds to the position in the TINFO list. ! 163: * The tflag keeps track of whether a forward reference ! 164: * tagname type ever gets resolved. ! 165: * The length must directly precede the info for puttypdef() to work right. ! 166: */ ! 167: typedef struct typeinfo { ! 168: struct typeinfo *t_tp; /* link */ ! 169: char t_tflag; /* tag name flag */ ! 170: int t_length; /* length */ ! 171: char t_info[]; /* info */ ! 172: } TINFO; ! 173: ! 174: /* ! 175: * To generate correct references to tagged types, ! 176: * the tag name is entered first as a type and ! 177: * all references to the type are made by tag name. ! 178: * When types are dumped, a list of these patch ! 179: * records is consulted to substitute the tag definition ! 180: * for the tag name. ! 181: */ ! 182: typedef struct typefix { ! 183: struct typefix *t_tp; /* link */ ! 184: int t_ttype; /* dummy definition */ ! 185: int t_type; /* fixed definition */ ! 186: } TYFIX; ! 187: ! 188: static TINFO *typelistp; /* Typdef list */ ! 189: static TYFIX *typefixp; /* Type fix list */ ! 190: static TINFO *gettype(); ! 191: static int checksum; /* For putrecord and putbyte */ ! 192: static char txt[NTXT]; /* Text buffer */ ! 193: static char rel[NREL]; /* Relocation buffer */ ! 194: static ADDRESS code_size; /* Size of CODE */ ! 195: static ADDRESS data_size; /* Size of DATA */ ! 196: static ADDRESS const_size; /* Size of CONST */ ! 197: static ADDRESS bss_size; /* Size of BSS */ ! 198: static char *txtp = txt; /* Text pointer */ ! 199: static char *relp = rel; /* Relocation pointer */ ! 200: ! 201: #if EMUFIXUPS ! 202: static int has8087; /* Has 8087 code flag */ ! 203: static SYM *wsp[6]; /* Links to emulator symbols */ ! 204: #endif ! 205: ! 206: #if VAXFMT ! 207: /* ! 208: * The Intel cross software packs the OMF ! 209: * data into 512 byte blocks as 510 byte variable length ! 210: * records, with the last record short. ! 211: */ ! 212: #define NVDATA 510 /* Blocksize - 2 */ ! 213: static char vaxbuf[NVDATA]; /* Buffer */ ! 214: static char *vaxptr = vaxbuf; /* Pointer */ ! 215: #endif ! 216: ! 217: extern char *setsymid(); ! 218: extern char *setindex(); ! 219: extern char *setsize(); ! 220: extern char *setnumb(); ! 221: extern long lastsize; ! 222: ! 223: /* ! 224: * These tables are indexed by a compiler segment name (SCODE et al) ! 225: * to get the OMF segment index. ! 226: * These tables understand the way the SSTRN segment moves ! 227: * around when the ROM option is given, and ! 228: * are dependent on the order of the calls to putsegdef() in copycode(). ! 229: */ ! 230: static char lnonseg[] = { ! 231: 1, /* SCODE => module_CODE */ ! 232: 1, /* SLINK => module_CODE */ ! 233: 1, /* SPURE => module_CODE */ ! 234: 2, /* SSTRN => module_DATA */ ! 235: 2, /* SDATA => module_DATA */ ! 236: 2 /* SBSS => module_DATA */ ! 237: }; ! 238: ! 239: static char lromseg[] = { ! 240: 1, /* SCODE => module_CODE */ ! 241: 1, /* SLINK => module_CODE */ ! 242: 1, /* SPURE => module_CODE */ ! 243: 1, /* SSTRN => module_CODE */ ! 244: 2, /* SDATA => module_DATA */ ! 245: 2 /* SBSS => module_DATA */ ! 246: }; ! 247: ! 248: static char lramseg[] = { ! 249: 1, /* SCODE => module_CODE */ ! 250: 1, /* SLINK => module_CODE */ ! 251: 2, /* SPURE => module_DATA */ ! 252: 2, /* SSTRN => module_DATA */ ! 253: 2, /* SDATA => module_DATA */ ! 254: 2 /* SBSS => module_DATA */ ! 255: }; ! 256: ! 257: static char snonseg[] = { ! 258: 1, /* SCODE => CODE */ ! 259: 1, /* SLINK => CODE */ ! 260: 2, /* SPURE => CONST */ ! 261: 3, /* SSTRN => DATA */ ! 262: 3, /* SDATA => DATA */ ! 263: 3 /* SBSS => DATA */ ! 264: }; ! 265: ! 266: static char sromseg[] = { ! 267: 1, /* SCODE => CODE */ ! 268: 1, /* SLINK => CODE */ ! 269: 2, /* SPURE => CONST */ ! 270: 2, /* SSTRN => CONST */ ! 271: 3, /* SDATA => DATA */ ! 272: 3 /* SDATA => DATA */ ! 273: }; ! 274: ! 275: static char sramseg[] = { ! 276: 1, /* SCODE => CODE */ ! 277: 1, /* SLINK => CODE */ ! 278: 3, /* SPURE => DATA */ ! 279: 3, /* SSTRN => DATA */ ! 280: 3, /* SDATA => DATA */ ! 281: 3 /* SDATA => DATA */ ! 282: }; ! 283: ! 284: /* ! 285: * Same game, but for group index codes. ! 286: * This is used only in SMALL model. ! 287: */ ! 288: static char grpindex[] = { ! 289: 1, /* SCODE => CGROUP */ ! 290: 1, /* SLINK => CGROUP */ ! 291: 2, /* SPURE => DGROUP */ ! 292: 2, /* SSTRN => DGROUP */ ! 293: 2, /* SDATA => DGROUP */ ! 294: 2 /* SBSS => DGROUP */ ! 295: }; ! 296: ! 297: /* ! 298: * Some prefabricated OMF items. ! 299: * These are just blasted out via a call to putrecord(). ! 300: */ ! 301: static char lthred[] = { 0x40, 0x01, /* module_CODE */ ! 302: 0x41, 0x02 }; /* module_DATA */ ! 303: static char lnames[] = { 0, ! 304: 4, 'C', 'O', 'D', 'E', ! 305: 4, 'D', 'A', 'T', 'A', ! 306: 5, 'C', 'O', 'N', 'S', 'T', ! 307: 5, 'S', 'T', 'A', 'C', 'K', ! 308: 6, 'M', 'E', 'M', 'O', 'R', 'Y', ! 309: 6, 'C', 'G', 'R', 'O', 'U', 'P', ! 310: 6, 'D', 'G', 'R', 'O', 'U', 'P' ! 311: }; ! 312: static char gdef1[] = { 7, 0xFF, 1 }; ! 313: static char gdef2[] = { 8, 0xFF, 2, 0xFF, 3, 0xFF, 4, 0xFF, 5 }; ! 314: static char sthred[] = { 0x00, 0x01, /* Code */ ! 315: 0x01, 0x02, /* Const */ ! 316: 0x02, 0x03, /* Data */ ! 317: 0x44, 0x01, /* Frame -> cgroup */ ! 318: 0x45, 0x02 /* Frame -> dgroup */ ! 319: }; ! 320: static char modend[] = { 0x00 }; ! 321: static int blkindex; /* current block index */ ! 322: ! 323: /* ! 324: ** First pass routines. ! 325: ** Output items to the temporary file. ! 326: */ ! 327: /* ! 328: * Initialize the code writer. ! 329: */ ! 330: outinit() ! 331: { ! 332: register TINFO *tp; ! 333: #if MONOLITHIC ! 334: register int i; ! 335: ! 336: txtp = &txt[0]; ! 337: relp = &rel[0]; ! 338: #if EMUFIXUPS ! 339: has8087 = 0; ! 340: for (i=0; i<6; ++i) ! 341: wsp[i] = NULL; ! 342: #endif ! 343: #if VAXFMT ! 344: vaxptr = &vaxbuf[0]; ! 345: #endif ! 346: #endif ! 347: typelistp = tp = (TINFO *)malloc(sizeof(TINFO)+1); ! 348: tp->t_tp = NULL; ! 349: tp->t_tflag = 0; ! 350: tp->t_length = 1; ! 351: tp->t_info[0] = OTNIL; ! 352: typefixp = NULL; ! 353: } ! 354: ! 355: /* ! 356: * Output a segment switch. ! 357: */ ! 358: outseg(s) ! 359: { ! 360: bput(TENTER); ! 361: bput(s); ! 362: } ! 363: ! 364: /* ! 365: * Output an absolute byte. ! 366: */ ! 367: outab(b) ! 368: { ! 369: bput(TBYTE); ! 370: bput(b); ! 371: ++dot; ! 372: } ! 373: ! 374: /* ! 375: * Output an absolute word. ! 376: */ ! 377: outaw(w) ! 378: { ! 379: bput(TWORD); ! 380: iput(w); ! 381: dot += 2; ! 382: } ! 383: ! 384: /* ! 385: * Output a full byte. ! 386: */ ! 387: outxb(sp, b, pcrf) ! 388: register SYM *sp; ! 389: { ! 390: register opcode; ! 391: ! 392: opcode = TBYTE; ! 393: if (sp != NULL) ! 394: opcode |= TSYM; ! 395: if (pcrf) ! 396: opcode |= TPCR; ! 397: bput(opcode); ! 398: bput(b); ! 399: if (sp != NULL) ! 400: pput(sp); ! 401: ++dot; ! 402: } ! 403: ! 404: /* ! 405: * Output a full word. ! 406: */ ! 407: outxw(sp, w, pcrf) ! 408: register SYM *sp; ! 409: { ! 410: register opcode; ! 411: ! 412: opcode = TWORD; ! 413: if (sp != NULL) ! 414: opcode |= TSYM; ! 415: if (pcrf) ! 416: opcode |= TPCR; ! 417: bput(opcode); ! 418: iput(w); ! 419: if (sp != NULL) ! 420: pput(sp); ! 421: dot += 2; ! 422: } ! 423: ! 424: #if EMUFIXUPS ! 425: /* ! 426: * Output a one byte opcode for the 8087. ! 427: */ ! 428: outfb(b) ! 429: { ! 430: has8087 = 1; ! 431: bput(TBYTE|TWT); ! 432: bput(b); ! 433: ++dot; ! 434: } ! 435: ! 436: /* ! 437: * Output a two byte opcode for the 8087. ! 438: */ ! 439: outfw(w, prefix) ! 440: { ! 441: has8087 = 1; ! 442: bput(TWORD|((prefix>>3)+TWST)); ! 443: iput(w); ! 444: dot += 2; ! 445: } ! 446: #endif ! 447: ! 448: #if 0 ! 449: /* ! 450: * Because the compiler now generates LARGE model code with links, ! 451: * the following routines are currently unused. ! 452: * They are retained for future reference. ! 453: */ ! 454: /* ! 455: * Output a 1 word object containing ! 456: * the base address of the current code segment. ! 457: */ ! 458: outcb() ! 459: { ! 460: bput(TCODE); ! 461: dot += 2; ! 462: } ! 463: ! 464: /* ! 465: * Output a 1 word object containing ! 466: * the base address of the current data segment. ! 467: */ ! 468: outdb() ! 469: { ! 470: bput(TDATA); ! 471: dot += 2; ! 472: } ! 473: #endif ! 474: ! 475: /* ! 476: * Output a 1 word object containing ! 477: * the base address of the external symbol pointed to by 'sp'. ! 478: */ ! 479: outsb(sp) ! 480: SYM *sp; ! 481: { ! 482: bput(TBASE); ! 483: pput(sp); ! 484: dot += 2; ! 485: } ! 486: ! 487: /* ! 488: * Read a dlabel record from ifp. ! 489: * If l(evel) == 0, then only the DLABEL and class bytes have been read; ! 490: * For GDEF's and SEX's in SCODE, we save the symbol pointer, accumulate the ! 491: * argument list types, and back patch the type appropriately. ! 492: * For everything else at level zero, we translate the type to Oomf ! 493: * and write a truncated record to the scratch file. ! 494: */ ! 495: SYM *curfsp; /* function sp */ ! 496: int curfna; /* nargs */ ! 497: int curfar[NARGS]; /* arg types */ ! 498: ! 499: outdlab(l, class) ! 500: { ! 501: register int value; ! 502: register int nline; ! 503: register SYM *sp; ! 504: register int type; ! 505: register int seg; ! 506: register int ttype; ! 507: ! 508: /* Get line number */ ! 509: nline = iget(); ! 510: ! 511: if (l != 0) ! 512: dbfatal(__LINE__); ! 513: value = 0; ! 514: seg = dotseg; ! 515: /* Get value */ ! 516: if (class < DC_AUTO) ! 517: ; ! 518: else if (class < DC_MOS) ! 519: value = iget(); ! 520: else ! 521: dbfatal(__LINE__); ! 522: ! 523: /* Get name */ ! 524: sget(id, NCSYMB); ! 525: ! 526: /* Check for symbol table entry */ ! 527: sp = NULL; ! 528: if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) { ! 529: sp = glookup(id, 0); ! 530: } else { ! 531: /* Make all c names the same, hopefully */ ! 532: strcat(id, "_"); ! 533: } ! 534: if (sp != NULL) { ! 535: seg = sp->s_seg; ! 536: value = sp->s_value; ! 537: } ! 538: /* Check for tag definition */ ! 539: if (class==DC_ETAG ! 540: || class==DC_STAG ! 541: || class==DC_UTAG) ! 542: ttype = tlookup(id, strlen(id)+1); ! 543: else ! 544: ttype = 0; ! 545: ! 546: /* Write part of truncated record */ ! 547: bput(TDLAB); ! 548: bput(class); ! 549: iput(nline); ! 550: iput(value); ! 551: bput(seg); ! 552: sput(id); ! 553: ! 554: /* Get type and enter into table */ ! 555: /* This will possibly overwrite id[], so it must come after glookup */ ! 556: type = dbtmap(ttype); ! 557: ! 558: /* Write out truncated record. */ ! 559: iput(type); ! 560: ! 561: /* Store the type for PUBDEF and EXTDEF records. */ ! 562: if (sp != NULL) { ! 563: sp->s_type = type; ! 564: /* Begin collecting parameter types */ ! 565: if ((class == DC_GDEF || class == DC_SEX) ! 566: && sp->s_seg == SCODE) { ! 567: curfsp = sp; ! 568: curfna = 0; ! 569: } ! 570: } ! 571: /* Collect parameter types */ ! 572: if (class == DC_PAUTO || class == DC_PREG) ! 573: curfar[curfna++] = type; ! 574: /* Dump the parameter list, tricky stuff. */ ! 575: if (class == DC_LINE && id[0] == '{' && curfna >= 0) { ! 576: arglisttype(); ! 577: curfna = -1; ! 578: } ! 579: /* Back patch tag definition */ ! 580: if (ttype != 0) ! 581: tpatch(ttype, type); ! 582: } ! 583: ! 584: /* ! 585: * Enter a patch into the typefix list. ! 586: */ ! 587: tpatch(ttype, type) ! 588: { ! 589: register TYFIX *tp; ! 590: ! 591: tp = (TYFIX *) malloc(sizeof(*tp)); ! 592: if (tp == NULL) dbmemory(__LINE__); ! 593: tp->t_ttype = ttype; ! 594: tp->t_type = type; ! 595: tp->t_tp = typefixp; ! 596: typefixp = tp; ! 597: } ! 598: ! 599: /* ! 600: * Return type index associated with type definition ! 601: * at infop of length len. ! 602: * Define a new TINFO item if necessary. ! 603: */ ! 604: tlookup(infop, len) ! 605: register char *infop; ! 606: int len; ! 607: { ! 608: #if INTEL ! 609: register TINFO *tp, *lasttp; ! 610: register int i, index; ! 611: register char *cp1, *cp2; ! 612: tp = typelistp; ! 613: index = 1; ! 614: /* Search the TINFO list for the type. */ ! 615: while (tp != NULL) { ! 616: if (tp->t_length == len) { ! 617: cp1 = infop; ! 618: cp2 = tp->t_info; ! 619: i = len; ! 620: while ((*cp1++ == *cp2++) && (--i > 0)) ! 621: ; ! 622: if (i == 0) return (index); ! 623: } ! 624: index++; ! 625: lasttp = tp; ! 626: tp = tp->t_tp; ! 627: } ! 628: /* Not found, add new type to TINFO list. */ ! 629: if ((tp=(TINFO *)malloc(sizeof(TINFO)+len)) == NULL) ! 630: cnomem("tlookup"); ! 631: tp->t_tp = NULL; ! 632: tp->t_tflag = 0; ! 633: tp->t_length = len; ! 634: cp1 = tp->t_info; ! 635: while (len--) ! 636: *cp1++ = *infop++; ! 637: /* Outinit puts the nil type on the list so never empty */ ! 638: lasttp->t_tp = tp; ! 639: return (index); ! 640: #else ! 641: return (1); ! 642: #endif ! 643: } ! 644: ! 645: /* ! 646: * Length and OMF type of scalar C types. ! 647: * The order corresponds to the order of DT_ types in ops.h. ! 648: */ ! 649: #if INTEL ! 650: static char ntypes [DT_DOUBLE+1][2] = { ! 651: { 0x00, OTNIL }, /* DT_NONE */ ! 652: { 0x08, OTSINT }, /* DT_CHAR */ ! 653: { 0x08, OTUINT }, /* DT_UCHAR */ ! 654: { 0x10, OTSINT }, /* DT_SHORT */ ! 655: { 0x10, OTUINT }, /* DT_USHORT */ ! 656: { 0x10, OTSINT }, /* DT_INT */ ! 657: { 0x10, OTUINT }, /* DT_UINT */ ! 658: { 0x20, OTSINT }, /* DT_LONG */ ! 659: { 0x20, OTUINT }, /* DT_ULONG */ ! 660: { 0x20, OTREAL }, /* DT_FLOAT */ ! 661: { 0x40, OTREAL } /* DT_DOUBLE */ ! 662: }; ! 663: #endif ! 664: ! 665: /* ! 666: * Read the dimension/type/info list from input ! 667: * and return the Ooomf type index. ! 668: * Store the size back through the pointer supplied. ! 669: * This routine is reentrant so that ! 670: * types of structure members are mappable while ! 671: * the structure definition is mapped. ! 672: */ ! 673: ! 674: dbtmap(ttype) ! 675: { ! 676: int type; ! 677: unsigned size; ! 678: register char *bp; ! 679: char bb[10]; ! 680: ! 681: bp = bb; ! 682: type = bget(); ! 683: size = iget(); ! 684: switch (type) { ! 685: case DT_NONE: ! 686: #if INTEL ! 687: *bp++ = OTNIL; ! 688: #endif ! 689: break; ! 690: case DT_CHAR: ! 691: case DT_UCHAR: ! 692: case DT_SHORT: ! 693: case DT_USHORT: ! 694: case DT_INT: ! 695: case DT_UINT: ! 696: case DT_LONG: ! 697: case DT_ULONG: ! 698: case DT_FLOAT: ! 699: case DT_DOUBLE: ! 700: #if INTEL ! 701: *bp++ = OTSCAL; /* SCALAR */ ! 702: bp = setsize(bp, (long)(ntypes[type][0])); /* length */ ! 703: *bp++ = ntypes[type][1]; /* OMF type */ ! 704: #endif ! 705: break; ! 706: case DT_VOID: ! 707: #if INTEL ! 708: *bp++ = OTNIL; ! 709: #endif ! 710: break; ! 711: case DT_STRUCT: ! 712: case DT_UNION: ! 713: case DT_ENUM: ! 714: if (bget() == DX_NAME) { ! 715: lastsize = ((long)size) * NBPBYTE; ! 716: return (dbxname(ttype)); ! 717: } ! 718: else if (type == DT_STRUCT) ! 719: return (dbxstruct(size, ttype)); ! 720: else if (type == DT_UNION) ! 721: return (dbxunion(size, ttype)); ! 722: else ! 723: return (dbxenum(size, ttype)); ! 724: case DD_PTR: ! 725: #if INTEL ! 726: *bp++ = OTPOINT; ! 727: *bp++ = OTINDEX; ! 728: #endif ! 729: type = dbtmap(ttype); ! 730: #if INTEL ! 731: bp = setindex(bp, type); ! 732: type = tlookup(bb, bp-bb); ! 733: bp = bb; ! 734: *bp++ = OTSCAL; ! 735: bp = setsize(bp, isvariant(VLARGE) ? 0x20L : 0x10L); ! 736: *bp++ = OTINDEX; ! 737: bp = setindex(bp, type); ! 738: #endif ! 739: break; ! 740: case DD_FUNC: ! 741: #if INTEL ! 742: *bp++ = OTPROC; ! 743: *bp++ = OTNIL; ! 744: *bp++ = OTINDEX; ! 745: #endif ! 746: type = dbtmap(ttype); ! 747: #if INTEL ! 748: bp = setindex(bp, type); ! 749: if (isvariant(VLARGE)) *bp++ = OTLFUNC; ! 750: else *bp++ = OTSFUNC; ! 751: *bp++ = 0; /* Zero args, possibly corrected later */ ! 752: #endif ! 753: break; ! 754: case DD_ARRAY: ! 755: type = dbtmap(ttype); ! 756: #if INTEL ! 757: *bp++ = OTARRAY; ! 758: bp = setsize(bp, ((long)size)*NBPBYTE); ! 759: *bp++ = OTINDEX; ! 760: bp = setindex(bp, type); ! 761: #endif ! 762: break; ! 763: default: ! 764: dbfatal(__LINE__); ! 765: } ! 766: return (tlookup(bb, bp-bb)); ! 767: } ! 768: ! 769: dbfatal(lineno) ! 770: { ! 771: cbotch("debug label format in %d", lineno); ! 772: } ! 773: ! 774: dbmemory(lineno) ! 775: { ! 776: cnomem("dbmemory %d", lineno); ! 777: } ! 778: ! 779: /* ! 780: * Construct typdef for enum, struct, or union. ! 781: */ ! 782: dbxname(ttype) ! 783: { ! 784: register char *bp; ! 785: register TINFO *tp; ! 786: register int i; ! 787: ! 788: /* DX_NAME records supply tag name of type which ! 789: * will be defined later. ! 790: * Tag references point to type consisting of ! 791: * the tag name; type will be backpatched into ! 792: * a struct/union/enum typdef */ ! 793: iget(); /* Dummy size */ ! 794: bp = &id[0]; ! 795: while (*bp = bget()) ! 796: ++bp; ! 797: *bp = '_'; ! 798: *++bp = 0; ! 799: i = tlookup(id, ++bp-id); ! 800: tp = gettype(i); ! 801: tp->t_tflag = 1; ! 802: return(i); ! 803: } ! 804: ! 805: dbxstruct(s, ttype) ! 806: unsigned s; /* Size of structure in bytes */ ! 807: { ! 808: int nmemb; /* The number of members */ ! 809: int i; /* Member counter */ ! 810: unsigned bwid; /* Bit width of current field */ ! 811: unsigned boff; /* Bit offset of current field */ ! 812: unsigned valu; /* Byte offset of current member */ ! 813: int type; /* type index of current member */ ! 814: #if INTEL ! 815: int size; /* Size of name field */ ! 816: long offs; /* Bit offset computed from valu and boff */ ! 817: long loffs; /* Bit offset computed from previous member */ ! 818: int nname; /* Number of bytes required for name list */ ! 819: int tlist; /* Type list index */ ! 820: int nlist; /* Name list index */ ! 821: struct slist { ! 822: struct slist *sl_sp; ! 823: int sl_type; ! 824: char sl_id[]; ! 825: }; ! 826: struct slist *sp1; ! 827: register struct slist *sp2; ! 828: char *lp; ! 829: register char *bp; ! 830: char bb[64]; ! 831: #endif ! 832: ! 833: /* Struct member list */ ! 834: #if INTEL ! 835: sp1 = NULL; ! 836: offs = loffs = 0; ! 837: nname = 0; ! 838: #endif ! 839: nmemb = iget(); /* Number of members */ ! 840: /* Does not include filler fields */ ! 841: /* Read in member descriptions */ ! 842: for (i = nmemb; i > 0; i -= 1) { ! 843: if (bget() != DC_MOS) ! 844: dbfatal(__LINE__); ! 845: iget(); /* forget line */ ! 846: bwid = bget(); /* bit width */ ! 847: boff = bget(); /* bit offset */ ! 848: valu = iget(); /* byte offset */ ! 849: sget(id, NCSYMB); ! 850: #if INTEL ! 851: strcat(id, "_"); ! 852: /* Enter into list, possibly prefixing nil filler field */ ! 853: offs = (long)valu * (long)NBPBYTE + boff; ! 854: if (offs != loffs) { ! 855: /* Nil named filler field so pscope doesn't lose */ ! 856: /* its place in the structure */ ! 857: nmemb += 1; ! 858: nname += 2; /* Bytes required for nlist */ ! 859: sp2 = (struct slist *)malloc(sizeof(*sp2)+1); ! 860: if (sp2 == NULL) ! 861: dbmemory(__LINE__); ! 862: sp2->sl_type = dbfmap((int)(offs-loffs), DT_UINT); ! 863: sp2->sl_id[0] = 0; ! 864: sp2->sl_sp = sp1; ! 865: sp1 = sp2; ! 866: } ! 867: size = strlen(id)+2; /* OTNAME, count/nul */ ! 868: nname += size; ! 869: sp2 = (struct slist *)malloc(sizeof(*sp2)+size); ! 870: if (sp2 == NULL) dbmemory(__LINE__); ! 871: strcpy(sp2->sl_id, id); ! 872: #endif ! 873: /* Now get the type with its possible id field */ ! 874: if (bwid != 0) { ! 875: /* Only fields have non-zero widths and offsets */ ! 876: type = dbfmap(bwid, bget()); ! 877: iget(); /* Subtype size */ ! 878: lastsize = bwid; ! 879: } else { ! 880: /* Non field member, must lookup its width */ ! 881: type = dbtmap(0); ! 882: } ! 883: #if INTEL ! 884: sp2->sl_type = type; ! 885: sp2->sl_sp = sp1; ! 886: sp1 = sp2; ! 887: loffs = offs + lastsize; ! 888: #endif ! 889: } ! 890: #if INTEL ! 891: /* Reverse member list */ ! 892: sp2 = sp1; ! 893: sp1 = NULL; ! 894: while (sp2 != NULL) { ! 895: struct slist *tsp; ! 896: ! 897: tsp = sp2->sl_sp; ! 898: sp2->sl_sp = sp1; ! 899: sp1 = sp2; ! 900: sp2 = tsp; ! 901: } ! 902: /* Construct type list */ ! 903: lp = bp = malloc(nmemb*3+nmemb/8+8); ! 904: if (bp == NULL) dbmemory(__LINE__); ! 905: *bp++ = OTLIST; ! 906: sp2 = sp1; ! 907: for (i = 0; i < nmemb; i += 1) { ! 908: if ((i%8) == 7) *bp++ = 0; /* EN byte */ ! 909: *bp++ = OTINDEX; ! 910: bp = setindex(bp, sp2->sl_type); ! 911: sp2 = sp2->sl_sp; ! 912: } ! 913: tlist = tlookup(lp, bp-lp); ! 914: free(lp); ! 915: /* Construct name list */ ! 916: lp = bp = malloc(nname+nmemb/8+8); ! 917: if (bp == NULL) dbmemory(__LINE__); ! 918: *bp++ = OTLIST; ! 919: sp2 = sp1; ! 920: for (i = 0; i < nmemb; i += 1) { ! 921: if (sp2==NULL) dbfatal(__LINE__); ! 922: if ((i%8) == 7) *bp++ = 0; /* EN byte */ ! 923: *bp++ = OTNAME; ! 924: bp = setsymid(bp, sp2->sl_id); ! 925: sp2 = sp2->sl_sp; ! 926: free(sp1); ! 927: sp1 = sp2; ! 928: } ! 929: nlist = tlookup(lp, bp-lp); ! 930: free(lp); ! 931: /* Construct the true type record */ ! 932: bp = &bb[0]; ! 933: *bp++ = OTSTRUC; ! 934: /* Set length of structure */ ! 935: bp = setsize(bp, ((long)s)*NBPBYTE); ! 936: /* Set number of members */ ! 937: bp = setnumb(bp, (long)nmemb); ! 938: *bp++ = OTINDEX; ! 939: bp = setindex(bp, tlist); ! 940: *bp++ = OTINDEX; ! 941: bp = setindex(bp, nlist); ! 942: *bp++ = OTNAME; ! 943: if (ttype == 0) ! 944: *bp++ = 0; ! 945: else ! 946: bp = setsymid(bp, gettype(ttype)->t_info); ! 947: return (tlookup(bb, bp-bb)); ! 948: #else ! 949: return (1); ! 950: #endif ! 951: } ! 952: ! 953: /* ! 954: * Map a bitfield type. ! 955: * Should only have CHAR, UCHAR, sort of type. ! 956: */ ! 957: dbfmap(bw, bt) ! 958: int bw; /* Bit width */ ! 959: int bt; /* Base type */ ! 960: { ! 961: #if INTEL ! 962: char bb[4]; ! 963: ! 964: bb[0] = OTSCAL; ! 965: bb[1] = bw; ! 966: switch (bt) { ! 967: case DT_CHAR: case DT_SHORT: case DT_INT: case DT_LONG: ! 968: bb[2] = OTSINT; ! 969: break; ! 970: case DT_UCHAR: case DT_USHORT: case DT_UINT: case DT_ULONG: ! 971: bb[2] = OTUINT; ! 972: break; ! 973: default: ! 974: dbfatal(__LINE__); ! 975: } ! 976: return (tlookup(bb, 3)); ! 977: #else ! 978: return (1); ! 979: #endif ! 980: } ! 981: ! 982: dbxunion(s, ttype) ! 983: unsigned s; /* Size of union in bytes */ ! 984: { ! 985: int nmemb; ! 986: int i; ! 987: #if INTEL ! 988: char *lp; ! 989: register char *bp; ! 990: int size; ! 991: #endif ! 992: ! 993: /* Union member list */ ! 994: nmemb = iget(); /* Number of members in union */ ! 995: #if INTEL ! 996: size = (ttype) ? strlen(gettype(ttype)->t_info) : 0; ! 997: lp = bp = malloc(18+7*nmemb+(10+3*nmemb)/8+1+size); ! 998: if (bp == NULL) dbmemory(__LINE__); ! 999: *bp++ = OTSTRUC; ! 1000: bp = setsize(bp, ((long)s)*NBPBYTE); ! 1001: *bp++ = 0; /* Invariant records */ ! 1002: *bp++ = OTNIL; /* Invariant type list */ ! 1003: *bp++ = OTNIL; /* Invariant name list */ ! 1004: *bp++ = OTNAME; ! 1005: if (ttype == 0) ! 1006: *bp++ = 0; ! 1007: else ! 1008: bp = setsymid(bp, gettype(ttype)->t_info); ! 1009: *bp++ = OTUPACK; /* Unpacked or something */ ! 1010: bp = setnumb(bp, (long)nmemb); ! 1011: *bp++ = 0; /* EN byte, for more leaves */ ! 1012: *bp++ = OTNIL; /* Selector field type */ ! 1013: *bp++ = OTNIL; /* Selector field name */ ! 1014: #endif ! 1015: i = 1; ! 1016: while (--nmemb >= 0) { ! 1017: int type; ! 1018: #if INTEL ! 1019: int tlist; ! 1020: int nlist; ! 1021: char bb[50]; ! 1022: register char *tbp; ! 1023: #endif ! 1024: ! 1025: if (bget() != DC_MOU) dbfatal(__LINE__); ! 1026: iget(); /* forget line */ ! 1027: bget(); /* forget bit width */ ! 1028: bget(); /* forget bit offset */ ! 1029: iget(); /* forget byte offset */ ! 1030: sget(id, NCSYMB); ! 1031: #if INTEL ! 1032: /* Make name list item */ ! 1033: strcat(id, "_"); ! 1034: tbp = bb; ! 1035: *tbp++ = OTLIST; ! 1036: *tbp++ = OTNAME; ! 1037: tbp = setsymid(tbp, id); ! 1038: nlist = tlookup(bb, tbp-bb); ! 1039: #endif ! 1040: type = dbtmap(0); ! 1041: #if INTEL ! 1042: /* Make type list item */ ! 1043: tbp = bb; ! 1044: *tbp++ = OTLIST; ! 1045: *tbp++ = OTINDEX; ! 1046: tbp = setindex(tbp, type); ! 1047: tlist = tlookup(bb, tbp-bb); ! 1048: /* Append member items to typdef */ ! 1049: if ((++i%8) == 0) *bp++ = 0; /* EN extend list */ ! 1050: *bp++ = 1; ! 1051: if ((++i%8) == 0) *bp++ = 0; ! 1052: *bp++ = OTINDEX; ! 1053: bp = setindex(bp, tlist); ! 1054: if ((++i%8) == 0) *bp++ = 0; ! 1055: *bp++ = OTINDEX; ! 1056: bp = setindex(bp, nlist); ! 1057: #endif ! 1058: } ! 1059: #if INTEL ! 1060: lastsize = ((long)s) * NBPBYTE; ! 1061: i = tlookup(lp, bp-lp); ! 1062: free(lp); ! 1063: return (i); ! 1064: #else ! 1065: return (1); ! 1066: #endif ! 1067: } ! 1068: ! 1069: dbxenum(s, ttype) ! 1070: unsigned s; /* Size of enum type in bytes */ ! 1071: { ! 1072: int nmemb; ! 1073: int i; ! 1074: int valu; ! 1075: int nname; ! 1076: #if INTEL ! 1077: int minvalu; ! 1078: int maxvalu; ! 1079: int range; ! 1080: int nlist; ! 1081: struct el { ! 1082: struct el *el_ep; ! 1083: int el_valu; ! 1084: char el_id[]; ! 1085: }; ! 1086: struct el **epp; ! 1087: register char *bp; ! 1088: char *lp; ! 1089: char bb[16]; ! 1090: #endif ! 1091: ! 1092: /* Enum member list */ ! 1093: nname = 0; ! 1094: nmemb = iget(); /* Number of members in enum */ ! 1095: #if INTEL ! 1096: epp = (struct el **)malloc(nmemb * sizeof(*epp)); ! 1097: if (epp == NULL) dbmemory(__LINE__); ! 1098: maxvalu = -MAXIV-1; ! 1099: minvalu = MAXIV; ! 1100: #endif ! 1101: for (i = 0; i < nmemb; i += 1) { ! 1102: #if INTEL ! 1103: int size; ! 1104: register struct el *ep; ! 1105: #endif ! 1106: ! 1107: ! 1108: if (bget() != DC_MOE) dbfatal(__LINE__); ! 1109: iget(); /* forget line */ ! 1110: valu = iget(); /* value */ ! 1111: sget(id, NCSYMB); ! 1112: #if INTEL ! 1113: strcat(id, "_"); ! 1114: size = strlen(id)+2; ! 1115: nname += size; ! 1116: #endif ! 1117: dbtmap(0); ! 1118: #if INTEL ! 1119: ep = malloc(sizeof(*ep)+size); ! 1120: if (ep == NULL) dbmemory(__LINE__); ! 1121: ep->el_valu = valu; ! 1122: strcpy(ep->el_id, id); ! 1123: if (valu < minvalu) ! 1124: minvalu = valu; ! 1125: else if (valu > maxvalu) ! 1126: maxvalu = valu; ! 1127: epp[i] = ep; ! 1128: #endif ! 1129: } ! 1130: #if INTEL ! 1131: /* Construct name list */ ! 1132: range = maxvalu - minvalu + 1; ! 1133: if (range > nmemb) ! 1134: nname += (range-nmemb)*2; ! 1135: nname += range/8 + 3; ! 1136: lp = bp = malloc(nname); ! 1137: if (bp == NULL) dbmemory(__LINE__); ! 1138: *bp++ = OTLIST; ! 1139: for (valu = minvalu; valu <= maxvalu; valu += 1) { ! 1140: if (((valu-minvalu)%8) == 7) *bp++ = 0; /* EN byte */ ! 1141: *bp++ = OTNAME; ! 1142: for (i = 0; i < nmemb; i += 1) ! 1143: if (epp[i]->el_valu == valu) ! 1144: break; ! 1145: if (i < nmemb) { ! 1146: bp = setsymid(bp, epp[i]->el_id); ! 1147: free(epp[i]); ! 1148: } else ! 1149: *bp++ = 0; ! 1150: if (bp > lp + nname) cbotch("enum overrun"); ! 1151: } ! 1152: free(epp); ! 1153: nlist = tlookup(lp, bp-lp); ! 1154: free(lp); ! 1155: /* Construct type record */ ! 1156: bp = &bb[0]; ! 1157: *bp++ = OTSCAL; ! 1158: bp = setsize(bp, ((long)s)*NBPBYTE); ! 1159: *bp++ = OTSINT; ! 1160: *bp++ = OTNAME; ! 1161: if (ttype == 0) ! 1162: *bp++ = 0; ! 1163: else ! 1164: bp = setsymid(bp, gettype(ttype)->t_info); ! 1165: *bp++ = OTINDEX; ! 1166: bp = setindex(bp, nlist); ! 1167: bp = setnumb(bp, (long)minvalu); ! 1168: bp = setnumb(bp, (long)maxvalu); ! 1169: return (tlookup(bb, bp-bb)); ! 1170: #else ! 1171: return (1); ! 1172: #endif ! 1173: } ! 1174: ! 1175: /* ! 1176: * Construct list of arg types and return its type. ! 1177: * The list may contain more than 8 leaves, requiring extra EN bytes. ! 1178: * The function's type with zero args has already been computed. ! 1179: * We must expand the type and append nargs, arglist type, and ! 1180: * reenter. ! 1181: */ ! 1182: arglisttype() ! 1183: { ! 1184: #if INTEL ! 1185: int type; ! 1186: int oldtypesize; ! 1187: char *oldtype; ! 1188: ! 1189: if (curfna == 0) ! 1190: return; ! 1191: { /* Compute argument list type */ ! 1192: register char *bp; ! 1193: register int i; ! 1194: register char *sbp; ! 1195: char b[3*NARGS+3]; ! 1196: ! 1197: bp = &b[0]; ! 1198: *bp++ = OTLIST; ! 1199: for (i=0; i<curfna; ++i) { ! 1200: if (i%8 == 7) ! 1201: *bp++ = 0; /* EN byte */ ! 1202: *bp++ = OTINDEX; ! 1203: sbp = bp; ! 1204: *bp++ = OTPARA; ! 1205: *bp++ = OTINDEX; ! 1206: bp = setindex(bp, curfar[i]); ! 1207: bp = setindex(sbp, tlookup(sbp, bp-sbp)); ! 1208: } ! 1209: type = tlookup(b, bp-b); ! 1210: } ! 1211: { /* Find old type */ ! 1212: register TINFO *tp; ! 1213: ! 1214: tp = gettype(curfsp->s_type); ! 1215: oldtype = tp->t_info; ! 1216: oldtypesize = tp->t_length; ! 1217: } ! 1218: { /* Expand and compute new type */ ! 1219: register char *bp; ! 1220: char b[16]; ! 1221: ! 1222: bp = b; ! 1223: while (--oldtypesize > 0) /* Last byte should be zero */ ! 1224: *bp++ = *oldtype++; ! 1225: bp = setnumb(bp, (long)curfna); /* Number of args */ ! 1226: *bp++ = OTINDEX; ! 1227: bp = setindex(bp, type); /* Arg types */ ! 1228: curfsp->s_type = tlookup(b, bp-b); ! 1229: } ! 1230: #else ! 1231: return; ! 1232: #endif ! 1233: } ! 1234: ! 1235: /* ! 1236: * Output a debug line record. ! 1237: */ ! 1238: outdlin(op) ! 1239: { ! 1240: bput(TDLAB); ! 1241: bput(DC_LINE); ! 1242: iput(line); ! 1243: bput(op); ! 1244: bput(0); ! 1245: bput(1); /* Nil type */ ! 1246: } ! 1247: ! 1248: /* ! 1249: * Output a debug relocation record. ! 1250: * This 'n' is an index into the list of debug records written. ! 1251: */ ! 1252: outdloc(n) ! 1253: { ! 1254: bput(TDLOC); ! 1255: iput(n); ! 1256: } ! 1257: ! 1258: /* ! 1259: * Finish up the code. ! 1260: */ ! 1261: outdone() ! 1262: { ! 1263: if (notvariant(VASM)) ! 1264: bput(TEND); ! 1265: #if EMUFIXUPS ! 1266: /* ! 1267: * Put magic names into the symbol table ! 1268: * if any 8087 code was generated. ! 1269: */ ! 1270: if (has8087) { ! 1271: wsp[0] = glookup("M:_WT", 0); ! 1272: wsp[1] = glookup("M:_WST", 0); ! 1273: wsp[2] = glookup("M:_WES", 0); ! 1274: wsp[3] = glookup("M:_WCS", 0); ! 1275: wsp[4] = glookup("M:_WSS", 0); ! 1276: wsp[5] = glookup("M:_WDS", 0); ! 1277: } ! 1278: #endif ! 1279: } ! 1280: ! 1281: /* ! 1282: ** Second pass routines. ! 1283: ** Read the temporary file and write the output. ! 1284: */ ! 1285: /* ! 1286: * Finish up. ! 1287: * Figure out the sizes and final values ! 1288: * of everything. Copy the code from the scratch ! 1289: * file back to the output file. ! 1290: */ ! 1291: copycode() ! 1292: { ! 1293: register int op; ! 1294: register SYM *sp; ! 1295: register int i; ! 1296: register ADDRESS v; ! 1297: int fixup; ! 1298: int nd; ! 1299: int data; ! 1300: char coment[30]; ! 1301: ! 1302: /* ! 1303: * Assign the base addresses to the ! 1304: * compiler's logical segments, based on the ! 1305: * compilation model and the setting of the VROM ! 1306: * variant flag. The VROM option only changes ! 1307: * where the strings are placed. ! 1308: */ ! 1309: seg[SCODE].s_mseek = 0; ! 1310: v = rup(seg[SCODE].s_dot); ! 1311: seg[SLINK].s_mseek = v; ! 1312: v += rup(seg[SLINK].s_dot); ! 1313: if ((isvariant(VSMALL)) || (isvariant(VRAM))) { ! 1314: code_size = v; ! 1315: v = 0; ! 1316: } ! 1317: seg[SPURE].s_mseek = v; ! 1318: v += rup(seg[SPURE].s_dot); ! 1319: if (notvariant(VROM) && notvariant(VRAM)) { ! 1320: if (isvariant(VSMALL)) ! 1321: const_size = v; ! 1322: else ! 1323: code_size = v; ! 1324: v = 0; ! 1325: } ! 1326: seg[SSTRN].s_mseek = v; ! 1327: v += rup(seg[SSTRN].s_dot); ! 1328: if (isvariant(VROM)) { ! 1329: if (isvariant(VSMALL)) ! 1330: const_size = v; ! 1331: else ! 1332: code_size = v; ! 1333: v = 0; ! 1334: } ! 1335: seg[SDATA].s_mseek = v; ! 1336: v += rup(seg[SDATA].s_dot); ! 1337: seg[SBSS].s_mseek = v; ! 1338: bss_size = rup(seg[SBSS].s_dot); ! 1339: data_size = v + bss_size; ! 1340: /* ! 1341: * Put out the preamble. ! 1342: */ ! 1343: puttheadr(); ! 1344: coment[0] = coment[1] = '\0'; ! 1345: sprintf(&coment[2], "%s %s %s %s", ! 1346: #ifdef vax ! 1347: "VAX", ! 1348: #else ! 1349: #ifdef UDI ! 1350: "UDI", ! 1351: #else ! 1352: #ifdef MSDOS ! 1353: "MS-DOS", ! 1354: #else ! 1355: "COHERENT", ! 1356: #endif ! 1357: #endif ! 1358: #endif ! 1359: #if INTEL ! 1360: "iC86", VERSINT, ! 1361: #else ! 1362: "MWC86", VERSMWC, ! 1363: #endif ! 1364: (isvariant(VSMALL)) ? "SMALL" : "LARGE"); ! 1365: putrecord(COMENT, coment, strlen(&coment[2])+2); ! 1366: if (isvariant(VLARGE)) { ! 1367: putlnames(); ! 1368: putsegdef(PARA|CCON, code_size, 2, 4); ! 1369: putsegdef(PARA|CCON, data_size, 3, 5); ! 1370: } else { ! 1371: putrecord(LNAMES, lnames, sizeof(lnames)); ! 1372: putsegdef(PARA|CCON, code_size, 2, 2); ! 1373: putsegdef(PARA|CCON, const_size, 4, 4); ! 1374: putsegdef(PARA|CCON, data_size, 3, 3); ! 1375: putsegdef(PARA|CSTACK, 0, 5, 5); ! 1376: putsegdef(PARA|CMEM, 0, 6, 6); ! 1377: putrecord(GRPDEF, gdef1, sizeof(gdef1)); ! 1378: putrecord(GRPDEF, gdef2, sizeof(gdef2)); ! 1379: } ! 1380: /* ! 1381: * Write out type and symbol definitions. ! 1382: */ ! 1383: puttypdef(); ! 1384: putsymdef(); ! 1385: ! 1386: /* ! 1387: * Copy out code. ! 1388: */ ! 1389: if (isvariant(VLARGE)) ! 1390: putrecord(FIXUPP, lthred, sizeof(lthred)); ! 1391: else ! 1392: putrecord(FIXUPP, sthred, sizeof(sthred)); ! 1393: for (i=0; i<NSEG; ++i) ! 1394: seg[i].s_dot = seg[i].s_mseek; ! 1395: dotseg = SCODE; ! 1396: dot = seg[SCODE].s_dot; ! 1397: while ((op = bget()) != TEND) { ! 1398: switch (op) { ! 1399: ! 1400: case TENTER: ! 1401: notenuf(); ! 1402: seg[dotseg].s_dot = dot; ! 1403: dotseg = bget(); ! 1404: dot = seg[dotseg].s_dot; ! 1405: continue; ! 1406: case TDLAB: ! 1407: getdlab(); ! 1408: continue; ! 1409: case TDLOC: ! 1410: getdloc(); ! 1411: continue; ! 1412: #if 0 ! 1413: /* See comment on outcb()/outdb() above. */ ! 1414: case TCODE: ! 1415: case TDATA: ! 1416: if (isvariant(VSMALL)) ! 1417: cbotch("code:data"); ! 1418: enuf(2, 4); ! 1419: fixup = txtp - (txt+3); ! 1420: *txtp++ = 0; ! 1421: *txtp++ = 0; ! 1422: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 1423: *relp++ = fixup; ! 1424: *relp++ = FTARGET|SECWAY|TSI; ! 1425: *relp++ = (op==TCODE) ? 1 : 2; ! 1426: dot += 2; ! 1427: continue; ! 1428: #endif ! 1429: case TBASE: ! 1430: if (isvariant(VSMALL)) ! 1431: cbotch("base"); ! 1432: sp = pget(); ! 1433: if ((sp->s_flag&S_DEF) != 0) { ! 1434: enuf(2, 4); ! 1435: fixup = txtp - (txt+3); ! 1436: *txtp++ = 0; ! 1437: *txtp++ = 0; ! 1438: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 1439: *relp++ = fixup; ! 1440: *relp++ = FTARGET|SECWAY|TSI; ! 1441: *relp++ = getsegindex(sp->s_seg); ! 1442: dot += 2; ! 1443: continue; ! 1444: } ! 1445: enuf(2, 5); ! 1446: fixup = txtp - (txt+3); ! 1447: *txtp++ = 0; ! 1448: *txtp++ = 0; ! 1449: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 1450: *relp++ = fixup; ! 1451: *relp++ = FTARGET|SECWAY|TEI; ! 1452: relp = setindex(relp, sp->s_ref); ! 1453: dot += 2; ! 1454: continue; ! 1455: } ! 1456: if ((op&TTYPE) == TBYTE) { ! 1457: nd = 1; ! 1458: data = bget(); ! 1459: } else { ! 1460: nd = 2; ! 1461: data = iget(); ! 1462: } ! 1463: #if EMUFIXUPS ! 1464: /* ! 1465: * 8087 opcodes. ! 1466: * Apply magic relocation for the emulator. ! 1467: */ ! 1468: if ((op&T8087) != 0) { ! 1469: sp = wsp[((op&T8087)-TWT)>>5]; ! 1470: enuf(nd, 7); ! 1471: fixup = txtp - (txt+3); ! 1472: *txtp++ = data; ! 1473: if (nd != 1) { ! 1474: *txtp++ = data >> 8; ! 1475: fixup |= OFFSET << 8; /* Locat */ ! 1476: } ! 1477: fixup |= M << 8; /* Seg rel */ ! 1478: *relp++ = (fixup>>8) | LOCAT; /* Not thread */ ! 1479: *relp++ = fixup; ! 1480: *relp++ = FD8087; /* Symbol based */ ! 1481: *relp++ = 0; /* Frame # */ ! 1482: *relp++ = 0; ! 1483: relp = setindex(relp, sp->s_ref); ! 1484: dot += nd; ! 1485: continue; ! 1486: } ! 1487: #endif ! 1488: /* ! 1489: * Absolute. ! 1490: */ ! 1491: if ((op&(TSYM|TPCR)) == 0) { ! 1492: enuf(nd, 0); ! 1493: *txtp++ = data; ! 1494: if (nd != 1) ! 1495: *txtp++ = data >> 8; ! 1496: dot += nd; ! 1497: continue; ! 1498: } ! 1499: /* ! 1500: * Absolute PC rel. ! 1501: */ ! 1502: if ((op&TSYM) == 0) { ! 1503: enuf(nd, 6); ! 1504: fixup = txtp - (txt+3); ! 1505: *txtp++ = 0; ! 1506: if (nd != 1) { ! 1507: *txtp++ = 0; ! 1508: fixup |= OFFSET << 8; ! 1509: } ! 1510: *relp++ = (fixup>>8) | LOCAT; /* Not thread */ ! 1511: *relp++ = fixup; ! 1512: *relp++ = FTARGET|TFN; /* Absolute frame */ ! 1513: *relp++ = 0; /* Frame number */ ! 1514: *relp++ = data; /* Disp */ ! 1515: *relp++ = data >> 8; ! 1516: dot += nd; ! 1517: continue; ! 1518: } ! 1519: /* ! 1520: * Symbol based. ! 1521: * I would like to always do this ! 1522: * in the primary way. However, LINK-86 ! 1523: * doesn't do 3 byte offsets, so I cannot ! 1524: * do a negative one. ! 1525: */ ! 1526: sp = pget(); ! 1527: if ((sp->s_flag&S_DEF) != 0) { ! 1528: data += sp->s_value; ! 1529: /* Absolute */ ! 1530: if ((op&TPCR)!=0 && sp->s_seg==dotseg) { ! 1531: enuf(nd, 0); ! 1532: data -= dot+nd; ! 1533: *txtp++ = data; ! 1534: if (nd != 1) ! 1535: *txtp++ = data >> 8; ! 1536: dot += nd; ! 1537: continue; ! 1538: } ! 1539: /* Segment relative */ ! 1540: enuf(nd, 6); ! 1541: fixup = txtp - (txt+3); ! 1542: *txtp++ = 0; ! 1543: if (nd != 1) { ! 1544: *txtp++ = 0; ! 1545: fixup |= OFFSET << 8; /* Loc */ ! 1546: } ! 1547: if ((op&TPCR) == 0) ! 1548: fixup |= M << 8; /* Seg rel */ ! 1549: *relp++ = (fixup>>8) | LOCAT; /* Not thread */ ! 1550: *relp++ = fixup; ! 1551: fixup = F|FT0|TSI; /* F code, seg ind */ ! 1552: if (getsegindex(sp->s_seg) != 1) ! 1553: fixup |= FT1; /* F data */ ! 1554: *relp++ = fixup; ! 1555: *relp++ = getsegindex(sp->s_seg); ! 1556: *relp++ = data; /* Disp */ ! 1557: *relp++ = data >> 8; ! 1558: dot += nd; ! 1559: continue; ! 1560: } ! 1561: /* ! 1562: * Symbol relative. ! 1563: */ ! 1564: enuf(nd, 5); ! 1565: fixup = txtp - (txt+3); ! 1566: *txtp++ = data; ! 1567: if (nd != 1) { ! 1568: *txtp++ = data >> 8; ! 1569: fixup |= OFFSET << 8; /* Loc */ ! 1570: } ! 1571: if ((op&TPCR) == 0) ! 1572: fixup |= M << 8; /* Seg rel */ ! 1573: *relp++ = LOCAT|(fixup>>8); /* Not THREAD */ ! 1574: *relp++ = fixup; ! 1575: *relp++ = FTARGET|SECWAY|TEI; /* Fix dat */ ! 1576: relp = setindex(relp, sp->s_ref); ! 1577: dot += nd; ! 1578: } ! 1579: notenuf(); /* Flush */ ! 1580: /* ! 1581: * If the size of the SBSS segment ! 1582: * is non zero, use an LIDATA item to get it ! 1583: * zeroed when the program is run. ! 1584: */ ! 1585: if (bss_size != 0) { ! 1586: txtp = &txt[0]; ! 1587: if (isvariant(VSMALL)) ! 1588: *txtp++ = 3; /* DATA */ ! 1589: else ! 1590: *txtp++ = 2; /* module_DATA */ ! 1591: *txtp++ = seg[SBSS].s_mseek; /* Offset */ ! 1592: *txtp++ = seg[SBSS].s_mseek >> 8; ! 1593: *txtp++ = bss_size; /* Length of loop */ ! 1594: *txtp++ = bss_size >> 8; ! 1595: *txtp++ = 0; ! 1596: *txtp++ = 0; ! 1597: *txtp++ = 1; ! 1598: *txtp++ = 0; ! 1599: putrecord(LIDATA, txt, 9); /* Emit OMF */ ! 1600: } ! 1601: dbdump(); /* Clean up db tables */ ! 1602: putrecord(MODEND, modend, sizeof(modend)); ! 1603: #if VAXFMT ! 1604: vaxflush(); ! 1605: #endif ! 1606: } ! 1607: ! 1608: /* ! 1609: ** Header writing routines. ! 1610: */ ! 1611: /* ! 1612: * Put out a THEADR item. ! 1613: * The name is just the module name that ! 1614: * the compiler has been keeping. It must be ! 1615: * mapped into upper case before writing ! 1616: * it to the file. ! 1617: */ ! 1618: puttheadr() ! 1619: { ! 1620: register char *p1, *p2; ! 1621: register c; ! 1622: char b[40]; ! 1623: ! 1624: p1 = module; ! 1625: p2 = &b[0]; ! 1626: *p2++ = strlen(p1); ! 1627: while ((c = *p1++) != '\0') { ! 1628: if (c>='a' && c<='z') ! 1629: c -= 'a'-'A'; ! 1630: *p2++ = c; ! 1631: } ! 1632: putrecord(THEADR, b, p2-b); ! 1633: } ! 1634: ! 1635: /* ! 1636: * Make up the list of names ! 1637: * record for the LARGE model of segmentation. ! 1638: * The names are set up like this: 1 => "", ! 1639: * 2 => "module_CODE", 3 => "module_DATA", 4 => "CODE" ! 1640: * 5 => "DATA". ! 1641: */ ! 1642: putlnames() ! 1643: { ! 1644: register char *p1, *p2; ! 1645: register c; ! 1646: char *movelname(); ! 1647: char b[40+40+11]; ! 1648: ! 1649: p1 = &b[0]; ! 1650: *p1++ = 0; /* EMPTY */ ! 1651: p1 = movelname(p1, "CODE"); ! 1652: p1 = movelname(p1, "DATA"); ! 1653: p2 = "\004CODE\004DATA"; ! 1654: while ((c = *p2++) != '\0') ! 1655: *p1++ = c; ! 1656: putrecord(LNAMES, b, p1-b); ! 1657: } ! 1658: ! 1659: /* ! 1660: * Move the module name with the supplied suffix to the supplied buffer. ! 1661: * Used by putlnames(). ! 1662: */ ! 1663: char * ! 1664: movelname(p1, p2) ! 1665: register char *p1; ! 1666: char *p2; ! 1667: { ! 1668: register char *p3; ! 1669: register c; ! 1670: ! 1671: p3 = module; ! 1672: *p1++ = strlen(p3) + 5; /* "_CODE" or "_DATA" */ ! 1673: while ((c = *p3++) != '\0') { ! 1674: if (c>='a' && c<='z') ! 1675: c -= 'a'-'A'; ! 1676: *p1++ = c; ! 1677: } ! 1678: *p1++ = '_'; ! 1679: p3 = p2; ! 1680: while ((c = *p3++) != '\0') ! 1681: *p1++ = c; ! 1682: return (p1); ! 1683: } ! 1684: ! 1685: /* ! 1686: * This routine formats and outputs a SEGDEF ! 1687: * item. There is no checking for BIG segments (these ! 1688: * are segments that are 64k in size). ! 1689: * The overlay index is set to point to a null name. ! 1690: */ ! 1691: putsegdef(flag, size, segi, classi) ! 1692: { ! 1693: register char *bp; ! 1694: char b[6]; ! 1695: ! 1696: bp = &b[0]; ! 1697: *bp++ = flag; ! 1698: *bp++ = size; ! 1699: *bp++ = size >> 8; ! 1700: *bp++ = segi; ! 1701: *bp++ = classi; ! 1702: *bp++ = 1; ! 1703: putrecord(SEGDEF, b, 6); ! 1704: } ! 1705: ! 1706: /* ! 1707: * Write TYPDEF records. ! 1708: * This assumes that the length member directly precedes the info array. ! 1709: */ ! 1710: puttypdef() ! 1711: { ! 1712: register TINFO *tp; ! 1713: register int length; ! 1714: register TINFO *ttp; ! 1715: ! 1716: fixpatch(); ! 1717: tp = typelistp; ! 1718: while (tp != NULL) { ! 1719: length = tp->t_length + 2; ! 1720: tp->t_length = 0; ! 1721: if (tp->t_tflag) { ! 1722: length = 3; ! 1723: tp->t_info[0] = OTNIL; ! 1724: } ! 1725: putrecord(TYPDEF, tp->t_info - 2, length); ! 1726: ttp = tp; ! 1727: tp = tp->t_tp; ! 1728: free(ttp); ! 1729: } ! 1730: } ! 1731: ! 1732: fixpatch() ! 1733: { ! 1734: register TYFIX *fp; ! 1735: #if INTEL ! 1736: register TINFO *ttp, *pttp, *tp, *ptp; ! 1737: #endif ! 1738: ! 1739: while ((fp = typefixp) != NULL) { ! 1740: #if INTEL ! 1741: if (fp->t_ttype >= fp->t_type) dbfatal(__LINE__); ! 1742: /* ! 1743: * This depends on NIL being at type index 1. ! 1744: * Excise the dummy type def. ! 1745: */ ! 1746: pttp = gettype(fp->t_ttype-1); ! 1747: ttp = pttp->t_tp; ! 1748: pttp->t_tp = ttp->t_tp; ! 1749: /* ! 1750: * Excise the real type def. ! 1751: */ ! 1752: ptp = gettype(fp->t_type-2); ! 1753: tp = ptp->t_tp; ! 1754: ptp->t_tp = tp->t_tp; ! 1755: /* ! 1756: * Insert the dummy and blank it. ! 1757: */ ! 1758: ttp->t_tp = ptp->t_tp; ! 1759: ptp->t_tp = ttp; ! 1760: ttp->t_length = 1; ! 1761: ttp->t_tflag = 0; ! 1762: ttp->t_info[0] = OTNIL; ! 1763: /* ! 1764: * Insert the real definition. ! 1765: */ ! 1766: tp->t_tp = pttp->t_tp; ! 1767: pttp->t_tp = tp; ! 1768: #endif ! 1769: /* ! 1770: * Release the memory. ! 1771: */ ! 1772: typefixp = fp->t_tp; ! 1773: free(fp); ! 1774: } ! 1775: } ! 1776: ! 1777: static TINFO * ! 1778: gettype(index) ! 1779: { ! 1780: register TINFO *tp; ! 1781: ! 1782: tp = typelistp; ! 1783: while (--index != 0) ! 1784: if ((tp = tp->t_tp) == NULL) ! 1785: dbfatal(__LINE__); ! 1786: return (tp); ! 1787: } ! 1788: ! 1789: /* ! 1790: * Sweep through the symbol table: ! 1791: * 1) Make symbols LSEG relative. ! 1792: * 2) Assign reference numbers. ! 1793: * 3) Output EXTDEF or PUBDEF. ! 1794: * 4) Output DEBSYM. ! 1795: */ ! 1796: putsymdef() ! 1797: { ! 1798: register SYM *sp; ! 1799: register int refnum; ! 1800: register int i; ! 1801: ! 1802: refnum = 1; ! 1803: for (i=0; i<NSHASH; ++i) { ! 1804: sp = hash2[i]; ! 1805: while (sp != NULL) { ! 1806: if ((sp->s_flag&S_DEF) != 0) ! 1807: sp->s_value += seg[sp->s_seg].s_mseek; ! 1808: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) { ! 1809: sp->s_ref = 0; ! 1810: if ((sp->s_flag&S_DEF) != 0) { ! 1811: putpubdef(sp); ! 1812: } else { ! 1813: sp->s_ref = refnum++; ! 1814: putextdef(sp); ! 1815: } ! 1816: } ! 1817: sp = sp->s_fp; ! 1818: } ! 1819: } ! 1820: } ! 1821: ! 1822: /* ! 1823: * Put out a PUBDEF item for symbol 'sp'. ! 1824: * All defs are tagged with the group ! 1825: * so that a FTARGET,EI fixup can determine the correct frame. ! 1826: */ ! 1827: putpubdef(sp) ! 1828: register SYM *sp; ! 1829: { ! 1830: register char *bp; ! 1831: char b[1+1+40+2+1]; ! 1832: ! 1833: bp = &b[0]; ! 1834: *bp++ = getgrpindex(sp->s_seg); ! 1835: *bp++ = getsegindex(sp->s_seg); ! 1836: bp = setsymid(bp, sp->s_id); ! 1837: *bp++ = sp->s_value; ! 1838: *bp++ = sp->s_value >> 8; ! 1839: if (sp->s_type == 0) ! 1840: *bp++ = 1; ! 1841: else ! 1842: bp = setindex(bp, sp->s_type); ! 1843: putrecord(PUBDEF, b, bp-b); ! 1844: } ! 1845: ! 1846: /* ! 1847: * Put out an EXTDEF item for symbol 'sp'. ! 1848: */ ! 1849: putextdef(sp) ! 1850: register SYM *sp; ! 1851: { ! 1852: register char *bp; ! 1853: char b[40+2]; ! 1854: ! 1855: bp = setsymid(b, sp->s_id); ! 1856: if (sp->s_type == 0) ! 1857: *bp++ = 1; ! 1858: else ! 1859: bp = setindex(bp, sp->s_type); ! 1860: putrecord(EXTDEF, b, bp-b); ! 1861: } ! 1862: ! 1863: /* ! 1864: * Translate compiler segment codes ! 1865: * to OMF segment index value, using tables. ! 1866: * The table is selected by the model and the ! 1867: * setting of the VROM variant. ! 1868: */ ! 1869: getsegindex(s) ! 1870: register int s; ! 1871: { ! 1872: if (isvariant(VSMALL)) { ! 1873: if (isvariant(VRAM)) ! 1874: return (sramseg[s]); ! 1875: if (notvariant(VROM)) ! 1876: return (snonseg[s]); ! 1877: return (sromseg[s]); ! 1878: } ! 1879: if (isvariant(VRAM)) ! 1880: return (lramseg[s]); ! 1881: if (notvariant(VROM)) ! 1882: return (lnonseg[s]); ! 1883: return (lromseg[s]); ! 1884: } ! 1885: ! 1886: /* ! 1887: * Translate compiler segment codes ! 1888: * to OMF group index value, using table and model. ! 1889: */ ! 1890: getgrpindex(s) ! 1891: register int s; ! 1892: { ! 1893: if (isvariant(VSMALL)) return (grpindex[s]); ! 1894: else return (0); ! 1895: } ! 1896: ! 1897: /* ! 1898: ** Debug information processors. ! 1899: */ ! 1900: /* ! 1901: * Structure to contain debug items on this pass. ! 1902: */ ! 1903: struct dbgt { ! 1904: struct dbgt *d_dp; /* Link */ ! 1905: int d_ref; /* Index number */ ! 1906: unsigned char d_class; /* Storage class */ ! 1907: unsigned char d_flag; /* Flags */ ! 1908: unsigned char d_level; /* Bracket level */ ! 1909: unsigned char d_seg; /* Segment */ ! 1910: ADDRESS d_value; /* Offset in segment */ ! 1911: int d_type; /* Type index */ ! 1912: int d_line; /* Line number */ ! 1913: char d_id[]; /* Name */ ! 1914: }; ! 1915: ! 1916: struct dbgt *getdbgt(); ! 1917: struct dbgt *dbase; ! 1918: struct dbgt *dnext; ! 1919: #if !TINY ! 1920: #define dbrpt(x,y) _dbrpt(x,y) ! 1921: #else ! 1922: #define dbrpt(x,y) /* _dbrpt(x,y) */ ! 1923: #endif ! 1924: ! 1925: /* ! 1926: * Read debug table item(s) into memory. ! 1927: * These are buffered until appropriate moments. ! 1928: */ ! 1929: getdlab() ! 1930: { ! 1931: register struct dbgt *dp; ! 1932: static int refnum = 0; ! 1933: ! 1934: dp = getdbgt(); ! 1935: if (dp->d_class == DC_LINE || dp->d_class == DC_LAB) ! 1936: dp->d_ref = refnum; ! 1937: refnum += 1; ! 1938: if (dbase == NULL) ! 1939: dbase = dp; ! 1940: if (dnext != NULL) ! 1941: dnext->d_dp = dp; ! 1942: dbrpt("enter", dp); ! 1943: while (dp->d_dp != NULL) { ! 1944: dp = dp->d_dp; ! 1945: dbrpt("enter", dp); ! 1946: } ! 1947: dnext = dp; ! 1948: } ! 1949: ! 1950: /* ! 1951: * Read in debug item in form abbreviated by outdlab(). ! 1952: */ ! 1953: struct dbgt * ! 1954: getdbgt() ! 1955: { ! 1956: register char *cp; ! 1957: register struct dbgt *dp; ! 1958: static int level = 0; ! 1959: struct dbgt d; ! 1960: SYM *sp; ! 1961: ! 1962: d.d_level = level; ! 1963: ! 1964: /* ! 1965: * Read the values in. ! 1966: */ ! 1967: d.d_class = bget(); ! 1968: d.d_line = iget(); ! 1969: d.d_value = iget(); ! 1970: d.d_seg = bget(); ! 1971: ! 1972: /* ! 1973: * Read name. ! 1974: */ ! 1975: for (cp = id; *cp = bget(); cp += 1); ! 1976: ! 1977: /* ! 1978: * Read type. ! 1979: */ ! 1980: d.d_type = iget(); ! 1981: ! 1982: /* ! 1983: * Check level change. ! 1984: */ ! 1985: if (d.d_class == DC_LINE) { ! 1986: switch (id[0]) { ! 1987: case '{': level += 1; break; ! 1988: case '}': level -= 1; break; ! 1989: } ! 1990: } ! 1991: ! 1992: /* ! 1993: * Find location of static internal items. ! 1994: */ ! 1995: if (d.d_class == DC_SIN) { ! 1996: sp = llookup(d.d_value, 0); ! 1997: d.d_value = sp->s_value; ! 1998: d.d_seg = sp->s_seg; ! 1999: } ! 2000: ! 2001: /* ! 2002: * Copy into dynamic storage. ! 2003: */ ! 2004: dp = (struct dbgt *)malloc(sizeof(struct dbgt) + cp - id + 1); ! 2005: if (dp == NULL) ! 2006: cnomem("getdbgt"); ! 2007: dp->d_level = d.d_level; ! 2008: dp->d_class = d.d_class; ! 2009: dp->d_line = d.d_line; ! 2010: dp->d_seg = d.d_seg; ! 2011: if (d.d_seg < SANY) ! 2012: d.d_value += seg[d.d_seg].s_mseek; ! 2013: dp->d_value = d.d_value; ! 2014: dp->d_type = d.d_type; ! 2015: dp->d_dp = NULL; ! 2016: dp->d_ref = -1; ! 2017: while (cp >= id) { ! 2018: dp->d_id[cp-id] = *cp; ! 2019: cp -= 1; ! 2020: } ! 2021: return (dp); ! 2022: } ! 2023: ! 2024: /* ! 2025: * Read a debug relocation item and patch current 'dot' ! 2026: * into the appropriate debug/symbol table item. ! 2027: * If the debug item is '}' and level 1, then dump everything in the list. ! 2028: */ ! 2029: getdloc() ! 2030: { ! 2031: register struct dbgt *dp; ! 2032: register int ref; ! 2033: ! 2034: ref = iget(); ! 2035: for (dp = dbase; ; dp = dp->d_dp) { ! 2036: if (dp == NULL) ! 2037: cbotch("getdloc: %d", ref); ! 2038: if (dp->d_ref == ref) ! 2039: break; ! 2040: } ! 2041: dp->d_seg = dotseg; ! 2042: dp->d_value = dot; ! 2043: ! 2044: dbrpt("reloc", dp); ! 2045: if (dp->d_id[0] == '}' && dp->d_level == 1) ! 2046: dbdump(); ! 2047: } ! 2048: ! 2049: /* ! 2050: * Dump all the debug symbols. ! 2051: */ ! 2052: dbdump() ! 2053: { ! 2054: register struct dbgt *dp, **dpp; ! 2055: extern char *regnames[]; ! 2056: ! 2057: dpp = &dbase; ! 2058: dnext = NULL; ! 2059: while ((dp = *dpp) != NULL) { ! 2060: switch (dp->d_class) { ! 2061: case DC_GDEF: /* Global def. */ ! 2062: case DC_SEX: /* Static external */ ! 2063: /* Function definitions replace initial { */ ! 2064: if (dp->d_seg == SCODE) { ! 2065: /* The initial BLKDEF occurs before PROLOG ! 2066: * at the function entry point. Could be ! 2067: * moved after PROLOG if desired. ! 2068: * The last BLKEND occurs just ! 2069: * before the EPILOG, and can also be moved. ! 2070: */ ! 2071: SYM *sp; ! 2072: ! 2073: sp = glookup(dp->d_id, 0); ! 2074: dp->d_type = sp->s_type; ! 2075: putlno(dp); ! 2076: putblkdef(dp); ! 2077: } else ! 2078: putdebsym(dp); ! 2079: break; ! 2080: case DC_GREF: /* Global ref. */ ! 2081: break; ! 2082: case DC_TYPE: /* Typedef name */ ! 2083: case DC_STAG: /* Structure tag */ ! 2084: case DC_UTAG: /* Union tag */ ! 2085: case DC_ETAG: /* Enumeration tag */ ! 2086: case DC_FILE: /* Source file name */ ! 2087: break; ! 2088: case DC_AUTO: /* Auto */ ! 2089: case DC_PAUTO: /* Parametric auto */ ! 2090: putlocsym(dp); ! 2091: break; ! 2092: case DC_SIN: /* Static internal */ ! 2093: case DC_LAB: /* Label */ ! 2094: putdebsym(dp); ! 2095: break; ! 2096: case DC_REG: /* Register */ ! 2097: case DC_PREG: /* Parametric register */ ! 2098: #if INTEL ! 2099: line = dp->d_line; ! 2100: cwarn("variable \"%s\" is in register %s", ! 2101: dp->d_id, regnames[dp->d_value]); ! 2102: #endif ! 2103: break; ! 2104: case DC_MOE: /* Member of enumeration */ ! 2105: break; ! 2106: case DC_LINE: /* Line number */ ! 2107: switch (dp->d_id[0]) { ! 2108: case '{': /* Block begins */ ! 2109: /* GDEF or SEX takes first blkdef */ ! 2110: if (dp->d_level != 0) { ! 2111: putlno(dp); ! 2112: putblkdef(dp); ! 2113: } ! 2114: break; ! 2115: case ';': /* Line number */ ! 2116: putlno(dp); ! 2117: break; ! 2118: case '}': /* Block ends */ ! 2119: #ifdef NOABLOCKS ! 2120: if (blkcount > 0) { ! 2121: blkcount--; ! 2122: break; ! 2123: } ! 2124: #endif ! 2125: putrecord(BLKEND, NULL, 0); ! 2126: break; ! 2127: default: ! 2128: cbotch("bad line record (dbdump)"); ! 2129: } ! 2130: break; ! 2131: case DC_MOS: /* Member of structure */ ! 2132: case DC_MOU: /* Member of union */ ! 2133: case DC_CALL: /* Function call */ ! 2134: break; ! 2135: default: ! 2136: cbotch("bad class (dbdump)"); ! 2137: } ! 2138: *dpp = dp->d_dp; ! 2139: free(dp); ! 2140: } ! 2141: } ! 2142: ! 2143: /* ! 2144: * Put out a DEBSYM item. ! 2145: * The symbol pointed to by 'dp' is a public ! 2146: * definition in this module. ! 2147: * This only gets executed under the VDEBUG option. ! 2148: */ ! 2149: putdebsym(dp) ! 2150: register struct dbgt *dp; ! 2151: { ! 2152: register char *bp; ! 2153: char b[1+1+1+40+2+1]; ! 2154: ! 2155: bp = &b[0]; ! 2156: *bp++ = 0; /* B=0, L=0, FM=0 */ ! 2157: *bp++ = getgrpindex(dp->d_seg); ! 2158: *bp++ = getsegindex(dp->d_seg); ! 2159: bp = setsymid(bp, dp->d_id); ! 2160: *bp++ = dp->d_value; ! 2161: *bp++ = dp->d_value >> 8; ! 2162: bp = setindex(bp, dp->d_type); ! 2163: putrecord(DEBSYM, b, bp-b); ! 2164: } ! 2165: ! 2166: /* ! 2167: * Process a local symbol definition. ! 2168: * Put out a DEBSYM record for symbol sp. ! 2169: */ ! 2170: putlocsym(dp) ! 2171: register struct dbgt *dp; ! 2172: { ! 2173: register char *bp; ! 2174: char b[1+2+40+2+1]; ! 2175: ! 2176: bp = &b[0]; ! 2177: *bp++ = 2; /* B=0, L=0, FM=2 */ ! 2178: bp = setindex(bp, blkindex); ! 2179: bp = setsymid(bp, dp->d_id); ! 2180: *bp++ = dp->d_value; ! 2181: *bp++ = dp->d_value >> 8; ! 2182: bp = setindex(bp, dp->d_type); ! 2183: putrecord(DEBSYM, b, bp-b); ! 2184: } ! 2185: ! 2186: /* ! 2187: * Process a block definition item. ! 2188: */ ! 2189: putblkdef(dp) ! 2190: register struct dbgt *dp; ! 2191: { ! 2192: char b[1+1+40+2+2+1+2+1]; ! 2193: register char *bp; ! 2194: char info = 0; ! 2195: int isproc; ! 2196: int episize; ! 2197: ! 2198: isproc = dp->d_id[0] != '{'; ! 2199: #ifdef NOABLOCKS ! 2200: if (!isproc) { ! 2201: blkcount++; ! 2202: return; ! 2203: } ! 2204: #endif ! 2205: ++blkindex; /* update block index */ ! 2206: bp = &b[0]; ! 2207: *bp++ = getgrpindex(dp->d_seg); ! 2208: *bp++ = getsegindex(dp->d_seg); ! 2209: if (isproc) ! 2210: bp = setsymid(bp, dp->d_id); /* name */ ! 2211: else ! 2212: *bp++ = 0; /* no name */ ! 2213: *bp++ = dp->d_value; ! 2214: *bp++ = dp->d_value >> 8; /* offset */ ! 2215: dp->d_value = blklength(dp, &episize); ! 2216: if (isproc) ! 2217: dp->d_value += episize; ! 2218: *bp++ = dp->d_value; ! 2219: *bp++ = dp->d_value >> 8; /* length */ ! 2220: if (isproc) { ! 2221: info |= 0x80; /* procedure bit */ ! 2222: if (isvariant(VLARGE)) { ! 2223: info |= 0x40; ! 2224: } ! 2225: *bp++ = info; ! 2226: *bp++ = 6; ! 2227: *bp++ = 0; /* return address offset */ ! 2228: bp = setindex(bp, dp->d_type); /* type index */ ! 2229: } else ! 2230: *bp++ = info; ! 2231: putrecord(BLKDEF, b, bp-b); ! 2232: } ! 2233: ! 2234: blklength(dp, epp) ! 2235: register struct dbgt *dp; ! 2236: int *epp; ! 2237: { ! 2238: register int level; ! 2239: register ADDRESS length; ! 2240: int autoseen; ! 2241: ! 2242: autoseen = 0; ! 2243: level = dp->d_level + 1; ! 2244: length = dp->d_value; ! 2245: while ((dp = dp->d_dp) != NULL) { ! 2246: if (dp->d_class == DC_AUTO) ! 2247: ++autoseen; ! 2248: else if (dp->d_class == DC_LINE ! 2249: && dp->d_id[0] == '}' ! 2250: && dp->d_level == level) { ! 2251: *epp = (isvariant(V80186)) ? 4 : (autoseen) ? 6 : 4; ! 2252: return ((int) (dp->d_value - length)); ! 2253: } ! 2254: } ! 2255: cbotch("missing blkend"); ! 2256: } ! 2257: ! 2258: /* ! 2259: * Put out a line number item. ! 2260: */ ! 2261: putlno(dp) ! 2262: register struct dbgt *dp; ! 2263: { ! 2264: register char *p1; ! 2265: char b[10]; ! 2266: static last = 0; ! 2267: ! 2268: if ((dp->d_line) == last) ! 2269: return; ! 2270: last = dp->d_line; ! 2271: p1 = &b[0]; ! 2272: *p1++ = getgrpindex(dp->d_seg); ! 2273: *p1++ = getsegindex(dp->d_seg); ! 2274: *p1++ = dp->d_line; ! 2275: *p1++ = dp->d_line>>8; ! 2276: *p1++ = dp->d_value; ! 2277: *p1++ = dp->d_value>>8; ! 2278: putrecord(LINNUM, b, p1-b); ! 2279: } ! 2280: ! 2281: #if !TINY ! 2282: _dbrpt(p, dp) ! 2283: char *p; ! 2284: register struct dbgt *dp; ! 2285: { ! 2286: if (xflag > 5) ! 2287: printf("%s: %d %s %d %d %o %d\n", ! 2288: p, ! 2289: dp->d_class, ! 2290: dp->d_id, ! 2291: dp->d_ref, ! 2292: dp->d_level, ! 2293: dp->d_flag, ! 2294: dp->d_type, ! 2295: 0); ! 2296: } ! 2297: ! 2298: #endif ! 2299: ! 2300: /* ! 2301: ** Low level record formatting. ! 2302: */ ! 2303: /* ! 2304: * Splat a bit size for the people. ! 2305: */ ! 2306: long lastsize; ! 2307: char * ! 2308: setsize(bp, size) ! 2309: char *bp; ! 2310: long size; ! 2311: { ! 2312: lastsize = size; ! 2313: return (setnumb(bp, size)); ! 2314: } ! 2315: ! 2316: /* ! 2317: * Splat an unsigned numeric leaf. ! 2318: * This assumes that the leaf will fit in at most 3 bytes, ! 2319: * since the biggest objects the compiler knows about are ! 2320: * 64K bytes or NBPBYTE*64K = 512K bits. ! 2321: */ ! 2322: char * ! 2323: setnumb(bp, numb) ! 2324: char *bp; ! 2325: unsigned long numb; ! 2326: { ! 2327: if (numb < 128) ! 2328: *bp++ = numb; ! 2329: else if (numb < 0x10000L) { ! 2330: *bp++ = OTUNUM2; ! 2331: *bp++ = numb; ! 2332: *bp++ = numb >> 8; ! 2333: } ! 2334: else { ! 2335: *bp++ = OTUNUM3; ! 2336: *bp++ = numb; ! 2337: *bp++ = numb >> 8; ! 2338: *bp++ = numb >> 16; ! 2339: } ! 2340: return (bp); ! 2341: } ! 2342: ! 2343: /* ! 2344: * Put OMF index i at cp and return updated cp. ! 2345: */ ! 2346: char * ! 2347: setindex(cp, i) ! 2348: register char *cp; ! 2349: register unsigned i; ! 2350: { ! 2351: if (i >= 128) ! 2352: *cp++ = (i >> 8) | 0x80; ! 2353: *cp++ = i; ! 2354: return (cp); ! 2355: } ! 2356: ! 2357: /* ! 2358: * This routine takes the name pointed to by 'cp' and ! 2359: * moves it into an OMF record. The 'bp' argument ! 2360: * is the OMF buffer pointer. The updated value ! 2361: * of 'bp' is returned. ! 2362: */ ! 2363: char * ! 2364: setsymid(bp, cp) ! 2365: register char *bp; ! 2366: register char *cp; ! 2367: { ! 2368: register c, n; ! 2369: ! 2370: if ((n=strlen(cp)) > 39) { ! 2371: cwarn("symbol \"%s\" truncated to 39 characters", cp); ! 2372: n = 39; ! 2373: } ! 2374: *bp++ = n; ! 2375: while (n--) { ! 2376: if ((c = *cp++)>='a' && c<='z') ! 2377: c -= 'a'-'A'; ! 2378: *bp++ = c; ! 2379: } ! 2380: return (bp); ! 2381: } ! 2382: ! 2383: /* ! 2384: * Put a record. ! 2385: * The 'type' argument is the record type. ! 2386: * The body of the record starts at 'p' and is ! 2387: * 'n' bytes long. The checksum is added. ! 2388: */ ! 2389: putrecord(type, p, n) ! 2390: register unsigned char *p; ! 2391: register n; ! 2392: { ! 2393: checksum = 0; ! 2394: putbyte(type); ! 2395: putbyte(n+1); /* +1 for the checksum */ ! 2396: putbyte((n+1)>>8); ! 2397: while(n--) ! 2398: putbyte(*p++); ! 2399: putbyte(-checksum); ! 2400: } ! 2401: ! 2402: putbyte(b) ! 2403: register b; ! 2404: { ! 2405: #if VAXFMT ! 2406: if (vaxptr >= &vaxbuf[NVDATA]) { ! 2407: vaxflush(); ! 2408: vaxptr = vaxbuf; ! 2409: } ! 2410: *vaxptr++ = b; ! 2411: #else ! 2412: bput(b); ! 2413: #endif ! 2414: checksum += b; ! 2415: } ! 2416: ! 2417: /* ! 2418: ** Output buffering. ! 2419: */ ! 2420: /* ! 2421: * Check if there is enough room in the text and relocation ! 2422: * buffers to hold 'nt' bytes of text and 'nr' bytes of relocation. ! 2423: */ ! 2424: enuf(nt, nr) ! 2425: { ! 2426: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL]) ! 2427: notenuf(); ! 2428: if (txtp == txt) { ! 2429: *txtp++ = getsegindex(dotseg); ! 2430: *txtp++ = dot; ! 2431: *txtp++ = dot >> 8; ! 2432: } ! 2433: } ! 2434: ! 2435: /* ! 2436: * Flush the buffer. ! 2437: */ ! 2438: notenuf() ! 2439: { ! 2440: register n; ! 2441: ! 2442: if ((n = txtp-txt) > 3) { ! 2443: putrecord(LEDATA, txt, n); ! 2444: if ((n = relp-rel) != 0) { ! 2445: putrecord(FIXUPP, rel, n); ! 2446: relp = rel; ! 2447: } ! 2448: } ! 2449: txtp = txt; ! 2450: } ! 2451: ! 2452: /* ! 2453: * Round up to the next word. ! 2454: */ ! 2455: rup(a) ! 2456: ADDRESS a; ! 2457: { ! 2458: return ((a+01)&~01); ! 2459: } ! 2460: ! 2461: #if VAXFMT ! 2462: /* ! 2463: * Flush out a record on the VAX. The record is a standard, ! 2464: * RMS variable length record. This routine checks for no bytes ! 2465: * in the buffer, so it can be unconditionally called at the ! 2466: * end to flush the buffer out. ! 2467: * The record is padded out to NVDATA bytes with zeros. This ! 2468: * only happens on the last block; the data beyond the end ! 2469: * is zeroed. ! 2470: */ ! 2471: vaxflush() ! 2472: { ! 2473: register int n; ! 2474: ! 2475: if ((n = vaxptr-vaxbuf) != 0) { ! 2476: if (fwrite(vaxbuf, n, 1, ofp) != 1 ! 2477: || fflush(ofp) == EOF) ! 2478: cfatal("output write error"); ! 2479: } ! 2480: } ! 2481: #endif ! 2482:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.