![cinap_lenrek](/assets/img/avatar_default.png)
The plan 9 assemblers support the DUPOK flag on text symbols. They parse and ignore it on GLOBL symbols. This patch makes it work in the linkers. The reason I ran into this is because my programming language (Myrddin) uses data symbols to generate type information, and it's useful to avoid duplicating all of the type info in every file that gets generated.
846 lines
18 KiB
C
846 lines
18 KiB
C
#include "l.h"
|
|
|
|
#define KMASK 0xF0000000
|
|
#define JMPSZ sizeof(u32int) /* size of bootstrap jump section */
|
|
|
|
#define LPUT(c)\
|
|
{\
|
|
cbp[0] = (c)>>24;\
|
|
cbp[1] = (c)>>16;\
|
|
cbp[2] = (c)>>8;\
|
|
cbp[3] = (c);\
|
|
cbp += 4;\
|
|
cbc -= 4;\
|
|
if(cbc <= 0)\
|
|
cflush();\
|
|
}
|
|
|
|
#define CPUT(c)\
|
|
{\
|
|
cbp[0] = (c);\
|
|
cbp++;\
|
|
cbc--;\
|
|
if(cbc <= 0)\
|
|
cflush();\
|
|
}
|
|
|
|
void strnput(char*, int);
|
|
|
|
long
|
|
entryvalue(void)
|
|
{
|
|
char *a;
|
|
Sym *s;
|
|
|
|
a = INITENTRY;
|
|
if(*a >= '0' && *a <= '9')
|
|
return atolwhex(a);
|
|
s = lookup(a, 0);
|
|
if(s->type == 0)
|
|
return INITTEXT;
|
|
if(dlm && s->type == SDATA)
|
|
return s->value+INITDAT;
|
|
if(s->type != STEXT && s->type != SLEAF)
|
|
diag("entry not text: %s", s->name);
|
|
return s->value;
|
|
}
|
|
|
|
void
|
|
asmb(void)
|
|
{
|
|
Prog *p;
|
|
long t;
|
|
Optab *o;
|
|
long prevpc;
|
|
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f asm\n", cputime());
|
|
Bflush(&bso);
|
|
|
|
/* emit text segment */
|
|
seek(cout, HEADR, 0);
|
|
prevpc = pc = INITTEXT;
|
|
for(p = firstp; p != P; p = p->link) {
|
|
if(p->as == ATEXT) {
|
|
curtext = p;
|
|
autosize = p->to.offset + 4;
|
|
if(p->from3.type == D_CONST) {
|
|
for(; pc < p->pc; pc++)
|
|
CPUT(0);
|
|
}
|
|
}
|
|
if(p->pc != pc) {
|
|
diag("phase error %lux sb %lux",
|
|
p->pc, pc);
|
|
if(!debug['a'])
|
|
prasm(curp);
|
|
pc = p->pc;
|
|
}
|
|
curp = p;
|
|
o = oplook(p); /* could probably avoid this call */
|
|
if(asmout(p, o, 0)) {
|
|
p = p->link;
|
|
pc += 4;
|
|
}
|
|
pc += o->size;
|
|
if (prevpc & (1<<31) && (pc & (1<<31)) == 0) {
|
|
char *tn;
|
|
|
|
tn = "??none??";
|
|
if(curtext != P && curtext->from.sym != S)
|
|
tn = curtext->from.sym->name;
|
|
Bprint(&bso, "%s: warning: text segment wrapped past 0\n", tn);
|
|
}
|
|
prevpc = pc;
|
|
}
|
|
/* for virtex 4, inject a jmp instruction after other text */
|
|
if(HEADTYPE == 6)
|
|
/* branch to absolute entry address (0xfffe2100) */
|
|
lput((18 << 26) | (0x03FFFFFC & entryvalue()) | 2);
|
|
|
|
if(debug['a'])
|
|
Bprint(&bso, "\n");
|
|
Bflush(&bso);
|
|
cflush();
|
|
|
|
/* emit data segment */
|
|
curtext = P;
|
|
switch(HEADTYPE) {
|
|
case 6:
|
|
textsize += JMPSZ;
|
|
/* fall through */
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 5:
|
|
seek(cout, HEADR+textsize, 0);
|
|
break;
|
|
case 3:
|
|
seek(cout, rnd(HEADR+textsize, 4), 0);
|
|
break;
|
|
case 4:
|
|
seek(cout, rnd(HEADR+textsize, 4096), 0);
|
|
break;
|
|
}
|
|
|
|
if(dlm){
|
|
char buf[8];
|
|
|
|
write(cout, buf, INITDAT-textsize);
|
|
textsize = INITDAT;
|
|
}
|
|
|
|
for(t = 0; t < datsize; t += sizeof(buf)-100) {
|
|
if(datsize-t > sizeof(buf)-100)
|
|
datblk(t, sizeof(buf)-100);
|
|
else
|
|
datblk(t, datsize-t);
|
|
}
|
|
|
|
symsize = 0;
|
|
lcsize = 0;
|
|
if(!debug['s']) {
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f sym\n", cputime());
|
|
Bflush(&bso);
|
|
switch(HEADTYPE) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 5:
|
|
case 6:
|
|
seek(cout, HEADR+textsize+datsize, 0);
|
|
break;
|
|
case 3:
|
|
seek(cout, rnd(HEADR+textsize, 4)+datsize, 0);
|
|
break;
|
|
case 4:
|
|
seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0);
|
|
break;
|
|
}
|
|
if(!debug['s'])
|
|
asmsym();
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f sp\n", cputime());
|
|
Bflush(&bso);
|
|
if(!debug['s'])
|
|
asmlc();
|
|
if(dlm)
|
|
asmdyn();
|
|
if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */
|
|
if((symsize+lcsize) & 1)
|
|
CPUT(0);
|
|
cflush();
|
|
}
|
|
else if(dlm){
|
|
asmdyn();
|
|
cflush();
|
|
}
|
|
|
|
/* back up and write the header */
|
|
seek(cout, 0L, 0);
|
|
switch(HEADTYPE) {
|
|
case 0:
|
|
lput(0x1030107); /* magic and sections */
|
|
lput(textsize); /* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(symsize); /* nsyms */
|
|
lput(entryvalue()); /* va of entry */
|
|
lput(0L);
|
|
lput(lcsize);
|
|
break;
|
|
case 1:
|
|
lput(0x4a6f7921); /* Joy! */
|
|
lput(0x70656666); /* peff */
|
|
lput(0x70777063); /* pwpc */
|
|
lput(1);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0x30002); /*YY*/
|
|
lput(0);
|
|
lput(~0);
|
|
lput(0);
|
|
lput(textsize+datsize);
|
|
lput(textsize+datsize);
|
|
lput(textsize+datsize);
|
|
lput(0xd0); /* header size */
|
|
lput(0x10400);
|
|
lput(~0);
|
|
lput(0);
|
|
lput(0xc);
|
|
lput(0xc);
|
|
lput(0xc);
|
|
lput(0xc0);
|
|
lput(0x01010400);
|
|
lput(~0);
|
|
lput(0);
|
|
lput(0x38);
|
|
lput(0x38);
|
|
lput(0x38);
|
|
lput(0x80);
|
|
lput(0x04040400);
|
|
lput(0);
|
|
lput(1);
|
|
lput(0);
|
|
lput(~0);
|
|
lput(0);
|
|
lput(~0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0);
|
|
lput(0x3100); /* load address */
|
|
lput(0);
|
|
lput(0);
|
|
lput(0); /* whew! */
|
|
break;
|
|
case 2:
|
|
if(dlm)
|
|
lput(0x80000000 | (4*21*21+7)); /* magic */
|
|
else
|
|
lput(4*21*21+7); /* magic */
|
|
lput(textsize); /* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(symsize); /* nsyms */
|
|
lput(entryvalue()); /* va of entry */
|
|
lput(0L);
|
|
lput(lcsize);
|
|
break;
|
|
case 3:
|
|
break;
|
|
case 4:
|
|
lput((0x1DFL<<16)|3L); /* magic and sections */
|
|
lput(time(0)); /* time and date */
|
|
lput(rnd(HEADR+textsize, 4096)+datsize);
|
|
lput(symsize); /* nsyms */
|
|
lput((0x48L<<16)|15L); /* size of optional hdr and flags */
|
|
|
|
lput((0413<<16)|01L); /* magic and version */
|
|
lput(textsize); /* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(entryvalue()); /* va of entry */
|
|
lput(INITTEXT); /* va of base of text */
|
|
lput(INITDAT); /* va of base of data */
|
|
lput(INITDAT); /* address of TOC */
|
|
lput((1L<<16)|1); /* sn(entry) | sn(text) */
|
|
lput((2L<<16)|1); /* sn(data) | sn(toc) */
|
|
lput((0L<<16)|3); /* sn(loader) | sn(bss) */
|
|
lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */
|
|
lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */
|
|
lput(0); /* max stack allowed */
|
|
lput(0); /* max data allowed */
|
|
lput(0); lput(0); lput(0); /* reserved */
|
|
|
|
strnput(".text", 8); /* text segment */
|
|
lput(INITTEXT); /* address */
|
|
lput(INITTEXT);
|
|
lput(textsize);
|
|
lput(HEADR);
|
|
lput(0L);
|
|
lput(HEADR+textsize+datsize+symsize);
|
|
lput(lcsize); /* line number size */
|
|
lput(0x20L); /* flags */
|
|
|
|
strnput(".data", 8); /* data segment */
|
|
lput(INITDAT); /* address */
|
|
lput(INITDAT);
|
|
lput(datsize);
|
|
lput(rnd(HEADR+textsize, 4096));/* sizes */
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0x40L); /* flags */
|
|
|
|
strnput(".bss", 8); /* bss segment */
|
|
lput(INITDAT+datsize); /* address */
|
|
lput(INITDAT+datsize);
|
|
lput(bsssize);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0x80L); /* flags */
|
|
break;
|
|
case 5:
|
|
/*
|
|
* customised for blue/gene,
|
|
* notably the alignment and KMASK masking.
|
|
*/
|
|
strnput("\177ELF", 4); /* e_ident */
|
|
CPUT(1); /* class = 32 bit */
|
|
CPUT(2); /* data = MSB */
|
|
CPUT(1); /* version = CURRENT */
|
|
strnput("", 9);
|
|
lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */
|
|
lput(1L); /* version = CURRENT */
|
|
lput(entryvalue() & ~KMASK); /* entry vaddr */
|
|
lput(52L); /* offset to first phdr */
|
|
|
|
if(debug['S']){
|
|
lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */
|
|
lput(0L); /* flags = PPC */
|
|
lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
|
|
lput((3L<<16)|40L); /* # Phdrs & Shdr size */
|
|
lput((3L<<16)|2L); /* # Shdrs & shdr string size */
|
|
}
|
|
else{
|
|
lput(0L);
|
|
lput(0L); /* flags = PPC */
|
|
lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
|
|
lput((3L<<16)|0L); /* # Phdrs & Shdr size */
|
|
lput((3L<<16)|0L); /* # Shdrs & shdr string size */
|
|
}
|
|
|
|
lput(1L); /* text - type = PT_LOAD */
|
|
lput(HEADR); /* file offset */
|
|
lput(INITTEXT & ~KMASK); /* vaddr */
|
|
lput(INITTEXT); /* paddr */
|
|
lput(textsize); /* file size */
|
|
lput(textsize); /* memory size */
|
|
lput(0x05L); /* protections = RX */
|
|
lput(0x10000L); /* alignment */
|
|
|
|
lput(1L); /* data - type = PT_LOAD */
|
|
lput(HEADR+textsize); /* file offset */
|
|
lput(INITDAT & ~KMASK); /* vaddr */
|
|
lput(INITDAT); /* paddr */
|
|
lput(datsize); /* file size */
|
|
lput(datsize); /* memory size */
|
|
lput(0x07L); /* protections = RWX */
|
|
lput(0x10000L); /* alignment */
|
|
|
|
lput(0L); /* data - type = PT_NULL */
|
|
lput(HEADR+textsize+datsize); /* file offset */
|
|
lput(0L); /* vaddr */
|
|
lput(0L); /* paddr */
|
|
lput(symsize); /* symbol table size */
|
|
lput(lcsize); /* line number size */
|
|
lput(0x04L); /* protections = R */
|
|
lput(0x04L); /* alignment code?? */
|
|
cflush();
|
|
|
|
if(!debug['S'])
|
|
break;
|
|
|
|
seek(cout, HEADR+textsize+datsize+symsize, 0);
|
|
lput(1); /* Section name (string tbl index) */
|
|
lput(1); /* Section type */
|
|
lput(2|4); /* Section flags */
|
|
lput(INITTEXT & ~KMASK); /* Section virtual addr at execution */
|
|
lput(HEADR); /* Section file offset */
|
|
lput(textsize); /* Section size in bytes */
|
|
lput(0); /* Link to another section */
|
|
lput(0); /* Additional section information */
|
|
lput(0x10000L); /* Section alignment */
|
|
lput(0); /* Entry size if section holds table */
|
|
|
|
lput(7); /* Section name (string tbl index) */
|
|
lput(1); /* Section type */
|
|
lput(2|1); /* Section flags */
|
|
lput(INITDAT & ~KMASK); /* Section virtual addr at execution */
|
|
lput(HEADR+textsize); /* Section file offset */
|
|
lput(datsize); /* Section size in bytes */
|
|
lput(0); /* Link to another section */
|
|
lput(0); /* Additional section information */
|
|
lput(0x10000L); /* Section alignment */
|
|
lput(0); /* Entry size if section holds table */
|
|
|
|
/* string section header */
|
|
lput(12); /* Section name (string tbl index) */
|
|
lput(3); /* Section type */
|
|
lput(1 << 5); /* Section flags */
|
|
lput(0); /* Section virtual addr at execution */
|
|
lput(HEADR+textsize+datsize+symsize+3*40); /* Section file offset */
|
|
lput(14); /* Section size in bytes */
|
|
lput(0); /* Link to another section */
|
|
lput(0); /* Additional section information */
|
|
lput(1); /* Section alignment */
|
|
lput(0); /* Entry size if section holds table */
|
|
|
|
/* string table */
|
|
cput(0);
|
|
strnput(".text", 5);
|
|
cput(0);
|
|
strnput(".data", 5);
|
|
cput(0);
|
|
strnput(".strtab", 7);
|
|
cput(0);
|
|
cput(0);
|
|
|
|
break;
|
|
case 6:
|
|
/*
|
|
* customised for virtex 4 boot,
|
|
* notably the alignment and KMASK masking.
|
|
*/
|
|
strnput("\177ELF", 4); /* e_ident */
|
|
CPUT(1); /* class = 32 bit */
|
|
CPUT(2); /* data = MSB */
|
|
CPUT(1); /* version = CURRENT */
|
|
strnput("", 9);
|
|
lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */
|
|
lput(1L); /* version = CURRENT */
|
|
lput(entryvalue()); /* entry vaddr */
|
|
lput(52L); /* offset to first phdr */
|
|
|
|
debug['S'] = 1; /* no symbol table */
|
|
if(debug['S']){
|
|
lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */
|
|
lput(0L); /* flags = PPC */
|
|
lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
|
|
lput((4L<<16)|40L); /* # Phdrs & Shdr size */
|
|
lput((4L<<16)|2L); /* # Shdrs & shdr string size */
|
|
}
|
|
else{
|
|
lput(0L);
|
|
lput(0L); /* flags = PPC */
|
|
lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
|
|
lput((4L<<16)|0L); /* # Phdrs & Shdr size */
|
|
lput((4L<<16)|0L); /* # Shdrs & shdr string size */
|
|
}
|
|
|
|
lput(1L); /* text - type = PT_LOAD */
|
|
lput(HEADR); /* file offset */
|
|
lput(INITTEXT); /* vaddr */
|
|
lput(INITTEXT); /* paddr */
|
|
lput(textsize-JMPSZ); /* file size */
|
|
lput(textsize-JMPSZ); /* memory size */
|
|
lput(0x05L); /* protections = RX */
|
|
lput(0); /* alignment */
|
|
|
|
lput(1L); /* data - type = PT_LOAD */
|
|
lput(HEADR+textsize); /* file offset */
|
|
lput(INITDAT); /* vaddr */
|
|
lput(INITDAT); /* paddr */
|
|
lput(datsize); /* file size */
|
|
lput(datsize+bsssize); /* memory size */
|
|
lput(0x07L); /* protections = RWX */
|
|
lput(0); /* alignment */
|
|
|
|
lput(0L); /* data - type = PT_NULL */
|
|
lput(HEADR+textsize+datsize); /* file offset */
|
|
lput(0L); /* vaddr */
|
|
lput(0L); /* paddr */
|
|
lput(symsize); /* symbol table size */
|
|
lput(lcsize); /* line number size */
|
|
lput(0x04L); /* protections = R */
|
|
lput(0x04L); /* alignment code?? */
|
|
|
|
/* add tiny text section at end with jmp to start */
|
|
lput(1L); /* text - type = PT_LOAD */
|
|
lput(HEADR+textsize-JMPSZ); /* file offset */
|
|
lput(0xFFFFFFFC); /* vaddr */
|
|
lput(0xFFFFFFFC); /* paddr */
|
|
lput(JMPSZ); /* file size */
|
|
lput(JMPSZ); /* memory size */
|
|
lput(0x05L); /* protections = RX */
|
|
lput(0); /* disable alignment */
|
|
|
|
cflush();
|
|
break;
|
|
}
|
|
cflush();
|
|
}
|
|
|
|
void
|
|
strnput(char *s, int n)
|
|
{
|
|
for(; *s; s++){
|
|
CPUT(*s);
|
|
n--;
|
|
}
|
|
for(; n > 0; n--)
|
|
CPUT(0);
|
|
}
|
|
|
|
void
|
|
cput(long l)
|
|
{
|
|
CPUT(l);
|
|
}
|
|
|
|
void
|
|
wput(long l)
|
|
{
|
|
cbp[0] = l>>8;
|
|
cbp[1] = l;
|
|
cbp += 2;
|
|
cbc -= 2;
|
|
if(cbc <= 0)
|
|
cflush();
|
|
}
|
|
|
|
void
|
|
lput(long l)
|
|
{
|
|
|
|
LPUT(l);
|
|
}
|
|
|
|
void
|
|
cflush(void)
|
|
{
|
|
int n;
|
|
|
|
n = sizeof(buf.cbuf) - cbc;
|
|
if(n)
|
|
write(cout, buf.cbuf, n);
|
|
cbp = buf.cbuf;
|
|
cbc = sizeof(buf.cbuf);
|
|
}
|
|
|
|
void
|
|
asmsym(void)
|
|
{
|
|
Prog *p;
|
|
Auto *a;
|
|
Sym *s;
|
|
int h;
|
|
|
|
s = lookup("etext", 0);
|
|
if(s->type == STEXT)
|
|
putsymb(s->name, 'T', s->value, s->version);
|
|
|
|
for(h=0; h<NHASH; h++)
|
|
for(s=hash[h]; s!=S; s=s->link)
|
|
switch(s->type) {
|
|
case SCONST:
|
|
putsymb(s->name, 'D', s->value, s->version);
|
|
continue;
|
|
|
|
case SDATA:
|
|
putsymb(s->name, 'D', s->value+INITDAT, s->version);
|
|
continue;
|
|
|
|
case SBSS:
|
|
putsymb(s->name, 'B', s->value+INITDAT, s->version);
|
|
continue;
|
|
|
|
case SFILE:
|
|
putsymb(s->name, 'f', s->value, s->version);
|
|
continue;
|
|
}
|
|
|
|
for(p=textp; p!=P; p=p->cond) {
|
|
s = p->from.sym;
|
|
if(s->type != STEXT && s->type != SLEAF)
|
|
continue;
|
|
|
|
/* filenames first */
|
|
for(a=p->to.autom; a; a=a->link)
|
|
if(a->type == D_FILE)
|
|
putsymb(a->sym->name, 'z', a->aoffset, 0);
|
|
else
|
|
if(a->type == D_FILE1)
|
|
putsymb(a->sym->name, 'Z', a->aoffset, 0);
|
|
|
|
if(s->type == STEXT)
|
|
putsymb(s->name, 'T', s->value, s->version);
|
|
else
|
|
putsymb(s->name, 'L', s->value, s->version);
|
|
|
|
/* frame, auto and param after */
|
|
putsymb(".frame", 'm', p->to.offset+4, 0);
|
|
for(a=p->to.autom; a; a=a->link)
|
|
if(a->type == D_AUTO)
|
|
putsymb(a->sym->name, 'a', -a->aoffset, 0);
|
|
else
|
|
if(a->type == D_PARAM)
|
|
putsymb(a->sym->name, 'p', a->aoffset, 0);
|
|
}
|
|
if(debug['v'] || debug['n'])
|
|
Bprint(&bso, "symsize = %lud\n", symsize);
|
|
Bflush(&bso);
|
|
}
|
|
|
|
void
|
|
putsymb(char *s, int t, long v, int ver)
|
|
{
|
|
int i, f;
|
|
|
|
if(t == 'f')
|
|
s++;
|
|
LPUT(v);
|
|
if(ver)
|
|
t += 'a' - 'A';
|
|
CPUT(t+0x80); /* 0x80 is variable length */
|
|
|
|
if(t == 'Z' || t == 'z') {
|
|
CPUT(s[0]);
|
|
for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
|
|
CPUT(s[i]);
|
|
CPUT(s[i+1]);
|
|
}
|
|
CPUT(0);
|
|
CPUT(0);
|
|
i++;
|
|
}
|
|
else {
|
|
for(i=0; s[i]; i++)
|
|
CPUT(s[i]);
|
|
CPUT(0);
|
|
}
|
|
symsize += 4 + 1 + i + 1;
|
|
|
|
if(debug['n']) {
|
|
if(t == 'z' || t == 'Z') {
|
|
Bprint(&bso, "%c %.8lux ", t, v);
|
|
for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
|
|
f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
|
|
Bprint(&bso, "/%x", f);
|
|
}
|
|
Bprint(&bso, "\n");
|
|
return;
|
|
}
|
|
if(ver)
|
|
Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
|
|
else
|
|
Bprint(&bso, "%c %.8lux %s\n", t, v, s);
|
|
}
|
|
}
|
|
|
|
#define MINLC 4
|
|
void
|
|
asmlc(void)
|
|
{
|
|
long oldpc, oldlc;
|
|
Prog *p;
|
|
long v, s;
|
|
|
|
oldpc = INITTEXT;
|
|
oldlc = 0;
|
|
for(p = firstp; p != P; p = p->link) {
|
|
if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
|
|
if(p->as == ATEXT)
|
|
curtext = p;
|
|
if(debug['L'])
|
|
Bprint(&bso, "%6lux %P\n",
|
|
p->pc, p);
|
|
continue;
|
|
}
|
|
if(debug['L'])
|
|
Bprint(&bso, "\t\t%6ld", lcsize);
|
|
v = (p->pc - oldpc) / MINLC;
|
|
while(v) {
|
|
s = 127;
|
|
if(v < 127)
|
|
s = v;
|
|
CPUT(s+128); /* 129-255 +pc */
|
|
if(debug['L'])
|
|
Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
|
|
v -= s;
|
|
lcsize++;
|
|
}
|
|
s = p->line - oldlc;
|
|
oldlc = p->line;
|
|
oldpc = p->pc + MINLC;
|
|
if(s > 64 || s < -64) {
|
|
CPUT(0); /* 0 vv +lc */
|
|
CPUT(s>>24);
|
|
CPUT(s>>16);
|
|
CPUT(s>>8);
|
|
CPUT(s);
|
|
if(debug['L']) {
|
|
if(s > 0)
|
|
Bprint(&bso, " lc+%ld(%d,%ld)\n",
|
|
s, 0, s);
|
|
else
|
|
Bprint(&bso, " lc%ld(%d,%ld)\n",
|
|
s, 0, s);
|
|
Bprint(&bso, "%6lux %P\n",
|
|
p->pc, p);
|
|
}
|
|
lcsize += 5;
|
|
continue;
|
|
}
|
|
if(s > 0) {
|
|
CPUT(0+s); /* 1-64 +lc */
|
|
if(debug['L']) {
|
|
Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
|
|
Bprint(&bso, "%6lux %P\n",
|
|
p->pc, p);
|
|
}
|
|
} else {
|
|
CPUT(64-s); /* 65-128 -lc */
|
|
if(debug['L']) {
|
|
Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
|
|
Bprint(&bso, "%6lux %P\n",
|
|
p->pc, p);
|
|
}
|
|
}
|
|
lcsize++;
|
|
}
|
|
while(lcsize & 1) {
|
|
s = 129;
|
|
CPUT(s);
|
|
lcsize++;
|
|
}
|
|
if(debug['v'] || debug['L'])
|
|
Bprint(&bso, "lcsize = %ld\n", lcsize);
|
|
Bflush(&bso);
|
|
}
|
|
|
|
void
|
|
datblk(long s, long n)
|
|
{
|
|
Prog *p;
|
|
char *cast;
|
|
long l, fl, j, d;
|
|
int i, c;
|
|
|
|
memset(buf.dbuf, 0, n+100);
|
|
for(p = datap; p != P; p = p->link) {
|
|
curp = p;
|
|
l = p->from.sym->value + p->from.offset - s;
|
|
c = p->reg;
|
|
i = 0;
|
|
if(l < 0) {
|
|
if(l+c <= 0)
|
|
continue;
|
|
while(l < 0) {
|
|
l++;
|
|
i++;
|
|
}
|
|
}
|
|
if(l >= n)
|
|
continue;
|
|
if(p->as != AINIT && p->as != ADYNT && !p->from.sym->dupok) {
|
|
for(j=l+(c-i)-1; j>=l; j--)
|
|
if(buf.dbuf[j]) {
|
|
print("%P\n", p);
|
|
diag("multiple initialization");
|
|
break;
|
|
}
|
|
}
|
|
switch(p->to.type) {
|
|
default:
|
|
diag("unknown mode in initialization\n%P", p);
|
|
break;
|
|
|
|
case D_FCONST:
|
|
switch(c) {
|
|
default:
|
|
case 4:
|
|
fl = ieeedtof(&p->to.ieee);
|
|
cast = (char*)&fl;
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi8[i+4]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 8:
|
|
cast = (char*)&p->to.ieee;
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi8[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case D_SCONST:
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = p->to.sval[i];
|
|
l++;
|
|
}
|
|
break;
|
|
|
|
case D_CONST:
|
|
d = p->to.offset;
|
|
if(p->to.sym) {
|
|
if(p->to.sym->type == SUNDEF){
|
|
ckoff(p->to.sym, d);
|
|
d += p->to.sym->value;
|
|
}
|
|
if(p->to.sym->type == STEXT ||
|
|
p->to.sym->type == SLEAF)
|
|
d += p->to.sym->value;
|
|
if(p->to.sym->type == SDATA)
|
|
d += p->to.sym->value + INITDAT;
|
|
if(p->to.sym->type == SBSS)
|
|
d += p->to.sym->value + INITDAT;
|
|
if(dlm)
|
|
dynreloc(p->to.sym, l+s+INITDAT, 1, 0, 0);
|
|
}
|
|
cast = (char*)&d;
|
|
switch(c) {
|
|
default:
|
|
diag("bad nuxi %d %d\n%P", c, i, curp);
|
|
break;
|
|
case 1:
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi1[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 2:
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi2[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 4:
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi4[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
write(cout, buf.dbuf, n);
|
|
}
|