pdblock build_dblock(pdcluster rc, pdcluster cc, uint l, bool(*admissible) (pdcluster rc, pdcluster cc, uint l, uint * rd, uint * cd, void *data), void *data) { pdblock b; uint rd, cd; uint i, j; b = 0; if (admissible(rc, cc, l, &rd, &cd, data)) { b = new_dblock(rc, cc, rd, cd, 0, 0); b->adm = true; } else if (rc->sons == 0 || cc->sons == 0) { b = new_dblock(rc, cc, 0, 0, 0, 0); } else { assert(rc->sons > 0); assert(cc->sons > 0); b = new_dblock(rc, cc, 0, 0, rc->sons, cc->sons); for (j = 0; j < cc->sons; j++) for (i = 0; i < rc->sons; i++) b->son[i + j * rc->sons] = build_dblock(rc->son[i], cc->son[j], l + 1, admissible, data); } update_dblock(b); return b; }
static char *string(char *s,dblock **result) { dblock *db=new_dblock(); taddr size; char *p,esc; if(*s!='\"') ierror(0); else s++; p=s; size=0; while(*s&&*s!='\"'){ if(*s=='\\') s=escape(s,&esc); else s++; size++; } db->size=size; db->data=mymalloc(db->size); s=p; p=db->data; while(*s&&*s!='\"'){ if(*s=='\\') s=escape(s,p++); else *p++=*s++; } *result=db; if(*s=!'\"') syntax_error(7); else s++; return s; }
static taddr new_stabstr(char *name) { section *str; taddr index; dblock *db; if (!(str = find_section(stabstrname,stabstrattr))) ierror(0); index = str->pc; db = new_dblock(); db->size = strlen(name) + 1; db->data = name; add_atom(str,new_data_atom(db,1)); return index; }
static void stab_entry(char *name,int type,int othr,int desc,char *s) { section *stabs; if (!(stabs = find_section(stabname,stabattr))) { section *str; dblock *db; stabs = new_section(stabname,stabattr,4); if (!(str = find_section(stabstrname,stabstrattr))) { str = new_section(stabstrname,stabstrattr,1); } else { if (str->pc != 0) ierror(0); } /* first byte of .stabstr is 0 */ add_atom(str,new_space_atom(number_expr(1),1,0)); /* compilation unit header has to be patched by output module */ new_stabstr(getfilename()); db = new_dblock(); db->size = 12; db->data = mymalloc(12); add_atom(stabs,new_data_atom(db,1)); } add_const_datadef(stabs,name?new_stabstr(name):0,32,1); add_const_datadef(stabs,type,8,1); add_const_datadef(stabs,othr,8,1); add_const_datadef(stabs,desc,16,1); if (s) { operand *op = new_operand(); int len = oplen(skip_operand(s),s); if (parse_operand(s,len,op,DATA_OPERAND(32))) { atom *a = new_datadef_atom(32,op); a->align = 1; add_atom(stabs,a); } else syntax_error(8); } else add_atom(stabs,new_space_atom(number_expr(4),1,0)); /* no value */ }
/* Convert an instruction into a DATA atom including relocations, if necessary. */ dblock *eval_instruction(instruction *p,section *sec,taddr pc) { /* Auch simpel. Fehlerchecks fehlen. */ taddr size=instruction_size(p,sec,pc); dblock *db=new_dblock(); int c=opt_inst(p,sec,pc); char *d; taddr val; db->size=size; d=db->data=mymalloc(size); *d=c; if(p->qualifiers[0]){ if(c>5) cpu_error(1,p->qualifiers[0]); else if(!strcmp(p->qualifiers[0],"b")) *d|=128; else if(strcmp(p->qualifiers[0],"w")) cpu_error(1,p->qualifiers[0]); } d++; if(c==5){ /* addq */ taddr val; if(!eval_expr(p->op[0]->offset,&val,sec,pc)||val>15) cpu_error(0); *d=((val<<4)|operand_code(p->op[1])); return db; } if(c==7){ expr *tree=p->op[0]->offset; if(!(tree->type==SYM&&tree->c.sym->sec==sec&&tree->c.sym->type==LABSYM&& tree->c.sym->pc-pc>=-128&&tree->c.sym->pc-pc<=127)) cpu_error(0); else *d=tree->c.sym->pc-pc; return db; } *d=((operand_code(p->op[0])<<4)|operand_code(p->op[1])); d++; d=fill_operand(p->op[0],sec,pc,d,&db->relocs,d-db->data); d=fill_operand(p->op[1],sec,pc,d,&db->relocs,d-db->data); return db; }
static void handle_data(char *s,int size,int noalign,int zeroterm) { expr *tree; dblock *db; do{ char *opstart=s; operand *op; if(size==8&&*s=='\"'){ s=string(s,&db); add_atom(0,new_data_atom(db,1)); }else{ op=new_operand(); s=skip_operand(s); if(!parse_operand(opstart,s-opstart,op,DATA_OPERAND(size))){ syntax_error(8); }else{ atom *a=new_datadef_atom(size,op); if(noalign) a->align=1; add_atom(0,a); } } s=skip(s); if(*s==','){ s=skip(s+1); }else if(*s) syntax_error(9); }while(*s); if(zeroterm){ if(size!=8) ierror(0); db=new_dblock(); db->size=1; db->data=mymalloc(1); *db->data=0; add_atom(0,new_data_atom(db,1)); } eol(s); }
/* Convert an instruction into a DATA atom including relocations, if necessary. */ dblock *eval_instruction(instruction *p,section *sec,taddr pc) { dblock *db=new_dblock(); int c,sz,enc,cc,ww,m=0; unsigned long code,code2,code3; rlist *relocs=0; if(p->qualifiers[0]){ int i; for(i=0;i<15;i++){ if(!strcmp(p->qualifiers[0],ccs[i])){ cc=i; break; } } if(i>15) ierror(0); }else cc=14; c=translate(p,sec,pc); enc=mnemonics[c].ext.encoding; db->size=sz=oplen(enc); db->data=mymalloc(db->size); code=mnemonics[c].ext.code; switch(enc){ case EN_ARITHR16: if(cc!=14) cpu_error(3); code=0x40000000|(code<<24); code|=(p->op[0]->reg<<16)|(p->op[1]->reg<<20); break; case EN_ARITHI16: if(cc!=14) cpu_error(3); code=0x60000000|((code>>1)<<25); code|=(p->op[0]->reg<<16)|(absval(p->op[1]->offset,sec,pc,5,0)<<20); break; case EN_FIX16: if(cc!=14) cpu_error(3); break; case EN_IBRANCH16: if(cc!=14) cpu_error(3); code|=(p->op[0]->reg<<16); break; case EN_RBRANCH16: code=0x18000000; code|=cc<<23; code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe)>>1)&127)<<16; break; case EN_MREG16: if(cc!=14) cpu_error(3); code|=(p->op[0]->dreg<<21)|(p->op[0]->reg<<16); break; case EN_RBRANCH32: if(code==0x90000000) code|=cc<<24; else code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,8,4,0xF000000)>>24)&0xf)<<24; code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,16,16,0x1fffe)>>1)&0x7fffff); code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe0000)>>17)&0x7f)<<16; break; case EN_FUNARY32: code=0xC0000040|(code<<21); code|=p->op[0]->reg<<16; code|=p->op[1]->reg<<11; code|=cc<<7; break; case EN_ARITHR32: code=0xC0000000|(code<<21); code|=p->op[0]->reg<<16; if(p->op[2]){ code|=p->op[1]->reg<<11; code|=p->op[2]->reg; }else{ code|=p->op[0]->reg<<11; code|=p->op[1]->reg; } code|=cc<<7; break; case EN_ARITHI32: code=0xC0000040|(code<<21); code|=p->op[0]->reg<<16; if(p->op[2]){ code|=p->op[1]->reg<<11; code|=absval(p->op[2]->offset,sec,pc,6,1); }else{ code|=p->op[0]->reg<<11; code|=absval(p->op[1]->offset,sec,pc,6,1); } code|=cc<<7; break; case EN_ADDCMPB64: // Large offset: invert CC, place a long branch after // so we really generate the following: // addcmpb<~cc> d, a, b, skip // b <destination> // skip: // <rest of code> m=1; if(cc&1) cc--; else cc++; case EN_ADDCMPB32: code=0x80000000|(code<<14); code|=cc<<24; code|=p->op[0]->reg<<16; if(code&0x4000){ code|=absval(p->op[1]->offset,sec,pc,4,1)<<20; }else{ code|=p->op[1]->reg<<20; } if(code&0x8000){ code|=absval(p->op[2]->offset,sec,pc,6,0)<<8; if(m) code|=4; else code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,9,0x1ff)>>1)&0xff); }else{