Mercurial > hg > index.cgi
diff lwlink/output.c @ 148:08fb11004df9
Initial pass at OS9 module support for lwlink
author | lost@l-w.ca |
---|---|
date | Fri, 26 Aug 2011 23:26:00 -0600 |
parents | 2c24602be78f |
children | 3b58d76ea032 |
line wrap: on
line diff
--- a/lwlink/output.c Thu Aug 25 22:29:58 2011 -0600 +++ b/lwlink/output.c Fri Aug 26 23:26:00 2011 -0600 @@ -32,6 +32,7 @@ // better in the future #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); } while (0) +void do_output_os9(FILE *of); void do_output_decb(FILE *of); void do_output_raw(FILE *of); void do_output_lwex0(FILE *of); @@ -62,6 +63,10 @@ do_output_lwex0(of); break; + case OUTPUT_OS9: + do_output_os9(of); + break; + default: fprintf(stderr, "Unknown output format doing output!\n"); exit(111); @@ -213,3 +218,118 @@ writebytes(sectlist[sn].ptr -> code, 1, sectlist[sn].ptr -> codesize, of); } } + +void os9crc(unsigned char crc[3], unsigned char b) +{ + b ^= crc[0]; + crc[0] = crc[1]; + crc[1] = crc[2]; + crc[1] ^= b >> 7; + crc[2] = b << 1; + crc[1] ^= b >> 2; + crc[2] ^= b << 6; + b ^= b << 1; + b ^= b << 2; + b ^= b << 4; + if (b & 0x80) + { + crc[0] ^= 0x80; + crc[2] ^= 0x21; + } +} + + +void do_output_os9(FILE *of) +{ + int sn; + int codedatasize = 0; + int bsssize = 0; + int i; + + unsigned char buf[16]; + unsigned char crc[3]; + + // calculate items for the file header + for (sn = 0; sn < nsects; sn++) + { + if (sectlist[sn].ptr -> flags & SECTION_BSS) + { + // no output for a BSS section + bsssize += sectlist[sn].ptr -> codesize; + continue; + } + codedatasize += sectlist[sn].ptr -> codesize; + } + + // now bss size is the data size for the module + // and codesize is the length of the module minus the module header + // and CRC + + codedatasize += 16; // add in headers + codedatasize += strlen(linkscript.name); // add in name length + + // output the file header + buf[0] = 0x87; + buf[1] = 0xCD; + buf[2] = (codedatasize >> 8) & 0xff; + buf[3] = codedatasize & 0xff; + buf[4] = 0; + buf[5] = 13; + buf[6] = (linkscript.modtype << 4) | (linkscript.modlang); + buf[7] = (linkscript.modattr << 4) | (linkscript.modrev); + buf[8] = (~(buf[0] ^ buf[1] ^ buf[2] ^ buf[3] ^ buf[4] ^ buf[5] ^ buf[6] ^ buf[7])) & 0xff; + buf[9] = (linkscript.execaddr >> 8) & 0xff; + buf[10] = linkscript.execaddr & 0xff; + buf[11] = (bsssize >> 8) & 0xff; + buf[12] = bsssize & 0xff; + + crc[0] = 0xff; + crc[1] = 0xff; + crc[2] = 0xff; + + os9crc(crc, buf[0]); + os9crc(crc, buf[1]); + os9crc(crc, buf[2]); + os9crc(crc, buf[3]); + os9crc(crc, buf[4]); + os9crc(crc, buf[5]); + os9crc(crc, buf[6]); + os9crc(crc, buf[7]); + os9crc(crc, buf[8]); + os9crc(crc, buf[9]); + os9crc(crc, buf[10]); + os9crc(crc, buf[11]); + os9crc(crc, buf[12]); + + + writebytes(buf, 1, 13, of); + + // output the name + for (i = 0; linkscript.name[i + 1]; i++) + { + writebytes(linkscript.name + i, 1, 1, of); + os9crc(crc, linkscript.name[i]); + } + buf[0] = linkscript.name[i] | 0x80; + writebytes(buf, 1, 1, of); + os9crc(crc, buf[0]); + + // output the data + // NOTE: disjoint load addresses will not work correctly!!!!! + for (sn = 0; sn < nsects; sn++) + { + if (sectlist[sn].ptr -> flags & SECTION_BSS) + { + // no output for a BSS section + continue; + } + writebytes(sectlist[sn].ptr -> code, 1, sectlist[sn].ptr -> codesize, of); + for (i = 0; i < sectlist[sn].ptr -> codesize; i++) + os9crc(crc, sectlist[sn].ptr -> code[i]); + } + + crc[0] ^= 0xff; + crc[1] ^= 0xff; + crc[2] ^= 0xff; + writebytes(crc, 1, 3, of); +}