/* File: pass.c * * Contains: link * * * This is the main loop for one pass. * */ #include "link.h" #define MAX ((unsigned) 0xffff) extern unsigned int topaddr; extern unsigned int lastaddr; extern unsigned int transaddr; extern unsigned int adrsav; extern unsigned int adrefc[]; extern unsigned int relo[]; extern unsigned int ofset1; extern unsigned int noload; extern unsigned int hex_value; extern unsigned int lflag; extern unsigned int had_data; extern unsigned int slenth; extern unsigned char passno; extern unsigned char mode; extern unsigned char gblname[]; extern FILE *gblfile; extern FILE *infile; static unsigned char header; static unsigned char length; static unsigned char flag; static unsigned char libflag; static unsigned char done; static unsigned char name1[20]; static unsigned char name2[20]; static unsigned int address; unsigned char *search(); unsigned char hexasc(); unsigned char getbyte(); SYM *locate(); int head_error(); int pure_code(); /* 01 header */ int transfer(); /* 02-03 header */ int ext_ent(); /* 04 header */ int set_psect(); /* 05-06 header */ int defs(); /* 07 header */ int global_output(); /* 08 header */ int link_include(); /* 09 header */ int lnkset(); /* 0A header */ int set_mode(); /* 0B header */ int (*head_function[])() = { head_error, pure_code, transfer, transfer, ext_ent, set_psect, set_psect, defs, global_output, link_include, lnkset, set_mode }; xlink() { int save; save = mode; done = 0; while(!done) onehead(); mode = save; } onehead() { header = getbyte(); length = getbyte(); if((header < 1) || (header > 11)) head_error(); (*head_function[(int) header])(); } int head_error() { printl("link: unknown header: %X at byte offset %X\n", header, ftell(infile)); xdone(1); } /* example of 01 header |<----object------>| :010C03007AB33E1BC8EBED52D8CD 01 = header 0C = length (including address) 0003 = address offset */ int pure_code() { unsigned char i; unsigned char len; if(length == 0) len = 254; else if(length == 1) len = 255; else if(length == 2) len = 256; else len = length - 2; getaddr(); for(i = 0; i < len; i++) objout(getbyte()); } /* example of 02 header :02030000 02 = header 03 = flag 0000 = transfer address offset */ int transfer() { register SYM *sp; done = 1; if(passno == 1) return; switch(header) { case 2: if(length == 2) getaddr(); else if(length == 3) { getaddr(); transaddr = adjust(address); traout(transaddr, 1); } break; case 3: if(length == 2) { transaddr = 0; traout(transaddr, 1); } else { getfl(); readsym(name1); if((sp = locate(name1)) && (sp->flag & LNKENT)) { transaddr = sp->value; traout(transaddr, 1); } else { undefined(name1); transaddr = 0; traout(transaddr, 1); } } } } /* example of 04 header |<---entry name---->|<--external name->| :0419CF03001000676F6F6420202020202068656C6C6F2020202020 04 = header 19 = length (hex) CF = flag (entry and external name, relocatable object, use lsb AND msb) 0003 = entry offset 0010 = object */ int ext_ent() { register SYM *sp; register unsigned int eaddress, oaddr; getfl(); oaddr = address; eaddress = 0; if(flag & O4ENT) { eaddress = address; getaddr(); oaddr = address; readsym(name1); } if(flag & O4EXT) readsym(name2); if(!(flag & O4ABS)) eaddress = adjust(eaddress); if((flag & O4OBJ) && (flag & O4OBJR)) oaddr = adjust(oaddr); if(passno == 1) { if(flag & O4ENT) setent(name1, eaddress); if(flag & O4EXT) { if(sp = locate(name2)) sp->flag |= LNKEXT; else insert(name2, 0, LNKEXT); } } else { if(flag & O4ENT) symchk(name1, eaddress); if(flag & O4EXT) { if(sp = locate(name2)) { if((sp->flag & LNKENT) == 0) { if((sp->flag & LNKDSP) == 0) { undefined(name2); sp->flag |= LNKDSP; } oaddr = 0; } else { outref(sp); oaddr = sp->value + address; } } else { undefined(name2); oaddr = 0; } } } if(flag & O4OBJ) { switch(flag & O4FULL) { case O4LSB: objout(oaddr & 0xff); break; case O4MSB: objout((oaddr >> 8) & 0xff); break; case O4FULL: objout(oaddr & 0xff); objout((oaddr >> 8) & 0xff); break; } } } /* example of 05 & 06 header |<--psect->| | name | :060AD00E000046414C4C4F43 06 = header 0A = length D0 = header flags (obj is relo, has externals, has entrys) 0E = symbol length 0000 = psect offset */ int set_psect() { register unsigned int i; unsigned char x; if(header == O6HC) { printl("Can't handle absolute module\n"); xdone(1); } if(length == 9) getfl(); else { flag = getbyte(); slenth = getbyte(); getaddr(); } ofset1 = (adrefc[mode] - relo[mode]) + address; if(address) clsrec(); /* did we wrap over the top of micro's addressing? */ if(ofset1 > MAX) { went_over(0); ofset1 &= MAX; } for(i = 0; i < 6;) { x = getbyte(); name1[i++] = (x == ' ' ? 0 : x); name1[i] = 0; } if(passno == 1) insertp(name1, adrefc[mode], libflag); } /* example of 07 header |<---entry name--->| :070F930300220068656C6C6F2020202020 07 = header 0F = length 93 = flag (entry name, relocatable object, use MSB and LSB) 0003 = entry offset 0022 = defs size */ int defs() { register unsigned int storage, eaddress; flag = 0; getfl(); storage = address; if(flag & O4ENT) { getaddr(); eaddress = adjust(storage); storage = address; readsym(name1); if(passno == 1) setent(name1, eaddress); else symchk(name1, eaddress); } if((adrefc[mode] + storage) > MAX) went_over(1, storage); if(noload) { while(storage--) objout(hex_value); } else { adrefc[mode] += storage; adrefc[mode] &= MAX; lflag |= LADIS; } } /* example of 08 header |<--global name--->| :080A676F6F64202020202020 08 = header 0A = length */ int global_output() { register GBL *fp; register SYM *sp; unsigned char tx3[100]; readsym(name1); if((passno == 1) || ((sp = locate(name1)) == 0)) return; if(!gblfile) { if((gblfile = fopen(gblname, "w+")) == 0) { printl("Can't create global file\n"); xdone(1); } fp = (GBL *) tx3; fp->g_name[0] = 0x06; fp->g_name[1] = 0x01; fp->g_flag1 = O6H; fp->g_flag2 = O6GBL; fwrite(fp, GSIZE, 1, gblfile); } fp = ( GBL * ) tx3; strcpy(fp->g_name, sp->name); fp->g_flag1 = 0x10; fp->g_flag2 = 0; fp->g_isect = 0; fp->g_psect = 0; fp->g_value = sp->value; fp->leftptr = 0; fp->rightptr = 0; fp->ref_beg = 0; fp->ref_end = 0; fwrite(fp, GSIZE, 1, gblfile); } /* example of 09 header |<-----name------->| :090A20746573746572CB572020 09 = header 0A = length 20 = flag (link request) */ int link_include() { flag = getbyte(); libflag = 0; if(flag & O9LNK) linkx(); else if(flag & O9GBL) glinkx(); /* else if(flag & O9LIB) { libflag = 1; libx(); } */ else { printl("%x: unknown link directive\n", flag); xdone(1); } libflag = 0; } /* example of 0A header :0A020001 0A = header 02 = length 0100 = modulo boundary */ int lnkset() { register unsigned int value; getaddr(); if(address > 256) { printl("lnkset address in excess of 256\n"); address = 256; } if(adrefc[mode] % address) { value = adrefc[mode]; value += address; address = ~(address - 1); address |= 0xff00; value &= address; adrefc[mode] = value; ofset1 = adrefc[mode] - relo[mode]; /* printl("%X\n", value); adrefc[mode] = (adrefc[mode] + address) & ((~(address - 1)) | 0xff00); */ } lflag |= LADIS; } set_mode() { mode = --length; lflag |= LADIS; if(mode == DSEG) had_data = 1; } linkset(val) register unsigned int val; { if(val > 256) { printl("lnkset address in excess of 256\n"); val = 256; } if(adrefc[mode] % val) adrefc[mode] = (adrefc[mode] + val) & ((~(val - 1)) | 0xff00); lflag |= LADIS; } getfl() { flag = getbyte(); getaddr(); } getaddr() { address = getbyte(); address |= (getbyte() << 8); }