17dd7cddfSDavid du Colombier #include "l.h" 27dd7cddfSDavid du Colombier 37dd7cddfSDavid du Colombier long OFFSET; 47dd7cddfSDavid du Colombier 559cc4ca5SDavid du Colombier static Prog *PP; 67dd7cddfSDavid du Colombier 77dd7cddfSDavid du Colombier long 87dd7cddfSDavid du Colombier entryvalue(void) 97dd7cddfSDavid du Colombier { 107dd7cddfSDavid du Colombier char *a; 117dd7cddfSDavid du Colombier Sym *s; 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier a = INITENTRY; 147dd7cddfSDavid du Colombier if(*a >= '0' && *a <= '9') 157dd7cddfSDavid du Colombier return atolwhex(a); 167dd7cddfSDavid du Colombier s = lookup(a, 0); 177dd7cddfSDavid du Colombier if(s->type == 0) 187dd7cddfSDavid du Colombier return INITTEXT; 199a747e4fSDavid du Colombier switch(s->type) { 209a747e4fSDavid du Colombier case STEXT: 219a747e4fSDavid du Colombier case SLEAF: 229a747e4fSDavid du Colombier break; 239a747e4fSDavid du Colombier case SDATA: 24375daca8SDavid du Colombier if(dlm) 259a747e4fSDavid du Colombier return s->value+INITDAT; 269a747e4fSDavid du Colombier default: 277dd7cddfSDavid du Colombier diag("entry not text: %s", s->name); 289a747e4fSDavid du Colombier } 297dd7cddfSDavid du Colombier return s->value; 307dd7cddfSDavid du Colombier } 317dd7cddfSDavid du Colombier 327dd7cddfSDavid du Colombier void 337dd7cddfSDavid du Colombier asmb(void) 347dd7cddfSDavid du Colombier { 357dd7cddfSDavid du Colombier Prog *p; 369a747e4fSDavid du Colombier long t, etext; 377dd7cddfSDavid du Colombier Optab *o; 387dd7cddfSDavid du Colombier 397dd7cddfSDavid du Colombier if(debug['v']) 407dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f asm\n", cputime()); 417dd7cddfSDavid du Colombier Bflush(&bso); 427dd7cddfSDavid du Colombier OFFSET = HEADR; 437dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 447dd7cddfSDavid du Colombier pc = INITTEXT; 457dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) { 467dd7cddfSDavid du Colombier if(p->as == ATEXT) { 477dd7cddfSDavid du Colombier curtext = p; 487dd7cddfSDavid du Colombier autosize = p->to.offset + 4; 497dd7cddfSDavid du Colombier } 507dd7cddfSDavid du Colombier if(p->pc != pc) { 517dd7cddfSDavid du Colombier diag("phase error %lux sb %lux", 527dd7cddfSDavid du Colombier p->pc, pc); 537dd7cddfSDavid du Colombier if(!debug['a']) 547dd7cddfSDavid du Colombier prasm(curp); 557dd7cddfSDavid du Colombier pc = p->pc; 567dd7cddfSDavid du Colombier } 577dd7cddfSDavid du Colombier curp = p; 587dd7cddfSDavid du Colombier o = oplook(p); /* could probably avoid this call */ 597dd7cddfSDavid du Colombier asmout(p, o); 607dd7cddfSDavid du Colombier pc += o->size; 617dd7cddfSDavid du Colombier } 627dd7cddfSDavid du Colombier 637dd7cddfSDavid du Colombier if(debug['a']) 647dd7cddfSDavid du Colombier Bprint(&bso, "\n"); 657dd7cddfSDavid du Colombier Bflush(&bso); 667dd7cddfSDavid du Colombier cflush(); 677dd7cddfSDavid du Colombier 689a747e4fSDavid du Colombier /* output strings in text segment */ 699a747e4fSDavid du Colombier etext = INITTEXT + textsize; 709a747e4fSDavid du Colombier for(t = pc; t < etext; t += sizeof(buf)-100) { 719a747e4fSDavid du Colombier if(etext-t > sizeof(buf)-100) 729a747e4fSDavid du Colombier datblk(t, sizeof(buf)-100, 1); 739a747e4fSDavid du Colombier else 749a747e4fSDavid du Colombier datblk(t, etext-t, 1); 759a747e4fSDavid du Colombier } 769a747e4fSDavid du Colombier 777dd7cddfSDavid du Colombier curtext = P; 787dd7cddfSDavid du Colombier switch(HEADTYPE) { 7959cc4ca5SDavid du Colombier case 0: 807dd7cddfSDavid du Colombier case 1: 817dd7cddfSDavid du Colombier case 2: 8259cc4ca5SDavid du Colombier case 5: 837dd7cddfSDavid du Colombier OFFSET = HEADR+textsize; 847dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 857dd7cddfSDavid du Colombier break; 867dd7cddfSDavid du Colombier case 3: 877dd7cddfSDavid du Colombier OFFSET = rnd(HEADR+textsize, 4096); 887dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 897dd7cddfSDavid du Colombier break; 907dd7cddfSDavid du Colombier } 91375daca8SDavid du Colombier if(dlm){ 92375daca8SDavid du Colombier char buf[8]; 93375daca8SDavid du Colombier 94375daca8SDavid du Colombier write(cout, buf, INITDAT-textsize); 95375daca8SDavid du Colombier textsize = INITDAT; 96375daca8SDavid du Colombier } 977dd7cddfSDavid du Colombier for(t = 0; t < datsize; t += sizeof(buf)-100) { 987dd7cddfSDavid du Colombier if(datsize-t > sizeof(buf)-100) 999a747e4fSDavid du Colombier datblk(t, sizeof(buf)-100, 0); 1007dd7cddfSDavid du Colombier else 1019a747e4fSDavid du Colombier datblk(t, datsize-t, 0); 1027dd7cddfSDavid du Colombier } 1037dd7cddfSDavid du Colombier 1047dd7cddfSDavid du Colombier symsize = 0; 1057dd7cddfSDavid du Colombier lcsize = 0; 1067dd7cddfSDavid du Colombier if(!debug['s']) { 1077dd7cddfSDavid du Colombier if(debug['v']) 1087dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f sym\n", cputime()); 1097dd7cddfSDavid du Colombier Bflush(&bso); 1107dd7cddfSDavid du Colombier switch(HEADTYPE) { 11159cc4ca5SDavid du Colombier case 0: 1127dd7cddfSDavid du Colombier case 1: 11359cc4ca5SDavid du Colombier case 4: 11459cc4ca5SDavid du Colombier case 5: 1157dd7cddfSDavid du Colombier debug['s'] = 1; 1167dd7cddfSDavid du Colombier break; 1177dd7cddfSDavid du Colombier case 2: 1187dd7cddfSDavid du Colombier OFFSET = HEADR+textsize+datsize; 1197dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 1207dd7cddfSDavid du Colombier break; 1217dd7cddfSDavid du Colombier case 3: 1227dd7cddfSDavid du Colombier OFFSET += rnd(datsize, 4096); 1237dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 1247dd7cddfSDavid du Colombier break; 1257dd7cddfSDavid du Colombier } 1267dd7cddfSDavid du Colombier if(!debug['s']) 1277dd7cddfSDavid du Colombier asmsym(); 1287dd7cddfSDavid du Colombier if(debug['v']) 1297dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f pc\n", cputime()); 1307dd7cddfSDavid du Colombier Bflush(&bso); 1317dd7cddfSDavid du Colombier if(!debug['s']) 1327dd7cddfSDavid du Colombier asmlc(); 133375daca8SDavid du Colombier if(dlm) 134375daca8SDavid du Colombier asmdyn(); 135375daca8SDavid du Colombier cflush(); 136375daca8SDavid du Colombier } 137375daca8SDavid du Colombier else if(dlm){ 138375daca8SDavid du Colombier seek(cout, HEADR+textsize+datsize, 0); 139375daca8SDavid du Colombier asmdyn(); 1407dd7cddfSDavid du Colombier cflush(); 1417dd7cddfSDavid du Colombier } 1427dd7cddfSDavid du Colombier 1437dd7cddfSDavid du Colombier if(debug['v']) 1447dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f header\n", cputime()); 1457dd7cddfSDavid du Colombier Bflush(&bso); 1467dd7cddfSDavid du Colombier OFFSET = 0; 1477dd7cddfSDavid du Colombier seek(cout, OFFSET, 0); 1487dd7cddfSDavid du Colombier switch(HEADTYPE) { 14959cc4ca5SDavid du Colombier case 0: /* no header */ 15059cc4ca5SDavid du Colombier break; 1517dd7cddfSDavid du Colombier case 1: /* aif for risc os */ 1527dd7cddfSDavid du Colombier lputl(0xe1a00000); /* NOP - decompress code */ 1537dd7cddfSDavid du Colombier lputl(0xe1a00000); /* NOP - relocation code */ 1547dd7cddfSDavid du Colombier lputl(0xeb000000 + 12); /* BL - zero init code */ 1557dd7cddfSDavid du Colombier lputl(0xeb000000 + 1567dd7cddfSDavid du Colombier (entryvalue() 1577dd7cddfSDavid du Colombier - INITTEXT 1587dd7cddfSDavid du Colombier + HEADR 1597dd7cddfSDavid du Colombier - 12 1607dd7cddfSDavid du Colombier - 8) / 4); /* BL - entry code */ 1617dd7cddfSDavid du Colombier 1627dd7cddfSDavid du Colombier lputl(0xef000011); /* SWI - exit code */ 1637dd7cddfSDavid du Colombier lputl(textsize+HEADR); /* text size */ 1647dd7cddfSDavid du Colombier lputl(datsize); /* data size */ 1657dd7cddfSDavid du Colombier lputl(0); /* sym size */ 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier lputl(bsssize); /* bss size */ 1687dd7cddfSDavid du Colombier lputl(0); /* sym type */ 1697dd7cddfSDavid du Colombier lputl(INITTEXT-HEADR); /* text addr */ 1707dd7cddfSDavid du Colombier lputl(0); /* workspace - ignored */ 1717dd7cddfSDavid du Colombier 1727dd7cddfSDavid du Colombier lputl(32); /* addr mode / data addr flag */ 1737dd7cddfSDavid du Colombier lputl(0); /* data addr */ 1747dd7cddfSDavid du Colombier for(t=0; t<2; t++) 1757dd7cddfSDavid du Colombier lputl(0); /* reserved */ 1767dd7cddfSDavid du Colombier 1777dd7cddfSDavid du Colombier for(t=0; t<15; t++) 1787dd7cddfSDavid du Colombier lputl(0xe1a00000); /* NOP - zero init code */ 1797dd7cddfSDavid du Colombier lputl(0xe1a0f00e); /* B (R14) - zero init return */ 1807dd7cddfSDavid du Colombier break; 1817dd7cddfSDavid du Colombier case 2: /* plan 9 */ 182375daca8SDavid du Colombier if(dlm) 183375daca8SDavid du Colombier lput(0x80000000|0x647); /* magic */ 184375daca8SDavid du Colombier else 1857dd7cddfSDavid du Colombier lput(0x647); /* magic */ 1867dd7cddfSDavid du Colombier lput(textsize); /* sizes */ 1877dd7cddfSDavid du Colombier lput(datsize); 1887dd7cddfSDavid du Colombier lput(bsssize); 1897dd7cddfSDavid du Colombier lput(symsize); /* nsyms */ 1907dd7cddfSDavid du Colombier lput(entryvalue()); /* va of entry */ 1917dd7cddfSDavid du Colombier lput(0L); 1927dd7cddfSDavid du Colombier lput(lcsize); 1937dd7cddfSDavid du Colombier break; 1947dd7cddfSDavid du Colombier case 3: /* boot for NetBSD */ 1957dd7cddfSDavid du Colombier lput((143<<16)|0413); /* magic */ 1967dd7cddfSDavid du Colombier lputl(rnd(HEADR+textsize, 4096)); 1977dd7cddfSDavid du Colombier lputl(rnd(datsize, 4096)); 1987dd7cddfSDavid du Colombier lputl(bsssize); 1997dd7cddfSDavid du Colombier lputl(symsize); /* nsyms */ 2007dd7cddfSDavid du Colombier lputl(entryvalue()); /* va of entry */ 2017dd7cddfSDavid du Colombier lputl(0L); 2027dd7cddfSDavid du Colombier lputl(0L); 2037dd7cddfSDavid du Colombier break; 20459cc4ca5SDavid du Colombier case 4: /* boot for IXP1200 */ 20559cc4ca5SDavid du Colombier break; 20659cc4ca5SDavid du Colombier case 5: /* boot for ipaq */ 20759cc4ca5SDavid du Colombier lputl(0xe3300000); /* nop */ 20859cc4ca5SDavid du Colombier lputl(0xe3300000); /* nop */ 20959cc4ca5SDavid du Colombier lputl(0xe3300000); /* nop */ 21059cc4ca5SDavid du Colombier lputl(0xe3300000); /* nop */ 21159cc4ca5SDavid du Colombier break; 2127dd7cddfSDavid du Colombier } 2137dd7cddfSDavid du Colombier cflush(); 2147dd7cddfSDavid du Colombier } 2157dd7cddfSDavid du Colombier 2167dd7cddfSDavid du Colombier void 2177dd7cddfSDavid du Colombier strnput(char *s, int n) 2187dd7cddfSDavid du Colombier { 2197dd7cddfSDavid du Colombier for(; *s; s++){ 22059cc4ca5SDavid du Colombier cput(*s); 2217dd7cddfSDavid du Colombier n--; 2227dd7cddfSDavid du Colombier } 2237dd7cddfSDavid du Colombier for(; n > 0; n--) 22459cc4ca5SDavid du Colombier cput(0); 22559cc4ca5SDavid du Colombier } 22659cc4ca5SDavid du Colombier 22759cc4ca5SDavid du Colombier void 22859cc4ca5SDavid du Colombier cput(int c) 22959cc4ca5SDavid du Colombier { 23059cc4ca5SDavid du Colombier cbp[0] = c; 23159cc4ca5SDavid du Colombier cbp++; 23259cc4ca5SDavid du Colombier cbc--; 23359cc4ca5SDavid du Colombier if(cbc <= 0) 23459cc4ca5SDavid du Colombier cflush(); 2357dd7cddfSDavid du Colombier } 2367dd7cddfSDavid du Colombier 2377dd7cddfSDavid du Colombier void 238375daca8SDavid du Colombier wput(long l) 239375daca8SDavid du Colombier { 240375daca8SDavid du Colombier 241375daca8SDavid du Colombier cbp[0] = l>>8; 242375daca8SDavid du Colombier cbp[1] = l; 243375daca8SDavid du Colombier cbp += 2; 244375daca8SDavid du Colombier cbc -= 2; 245375daca8SDavid du Colombier if(cbc <= 0) 246375daca8SDavid du Colombier cflush(); 247375daca8SDavid du Colombier } 248375daca8SDavid du Colombier 249375daca8SDavid du Colombier void 2507dd7cddfSDavid du Colombier lput(long l) 2517dd7cddfSDavid du Colombier { 2527dd7cddfSDavid du Colombier 2537dd7cddfSDavid du Colombier cbp[0] = l>>24; 2547dd7cddfSDavid du Colombier cbp[1] = l>>16; 2557dd7cddfSDavid du Colombier cbp[2] = l>>8; 2567dd7cddfSDavid du Colombier cbp[3] = l; 2577dd7cddfSDavid du Colombier cbp += 4; 2587dd7cddfSDavid du Colombier cbc -= 4; 2597dd7cddfSDavid du Colombier if(cbc <= 0) 2607dd7cddfSDavid du Colombier cflush(); 2617dd7cddfSDavid du Colombier } 2627dd7cddfSDavid du Colombier 2637dd7cddfSDavid du Colombier void 2647dd7cddfSDavid du Colombier lputl(long l) 2657dd7cddfSDavid du Colombier { 2667dd7cddfSDavid du Colombier 2677dd7cddfSDavid du Colombier cbp[3] = l>>24; 2687dd7cddfSDavid du Colombier cbp[2] = l>>16; 2697dd7cddfSDavid du Colombier cbp[1] = l>>8; 2707dd7cddfSDavid du Colombier cbp[0] = l; 2717dd7cddfSDavid du Colombier cbp += 4; 2727dd7cddfSDavid du Colombier cbc -= 4; 2737dd7cddfSDavid du Colombier if(cbc <= 0) 2747dd7cddfSDavid du Colombier cflush(); 2757dd7cddfSDavid du Colombier } 2767dd7cddfSDavid du Colombier 2777dd7cddfSDavid du Colombier void 2787dd7cddfSDavid du Colombier cflush(void) 2797dd7cddfSDavid du Colombier { 2807dd7cddfSDavid du Colombier int n; 2817dd7cddfSDavid du Colombier 2827dd7cddfSDavid du Colombier n = sizeof(buf.cbuf) - cbc; 2837dd7cddfSDavid du Colombier if(n) 2847dd7cddfSDavid du Colombier write(cout, buf.cbuf, n); 2857dd7cddfSDavid du Colombier cbp = buf.cbuf; 2867dd7cddfSDavid du Colombier cbc = sizeof(buf.cbuf); 2877dd7cddfSDavid du Colombier } 2887dd7cddfSDavid du Colombier 2897dd7cddfSDavid du Colombier void 2907dd7cddfSDavid du Colombier nopstat(char *f, Count *c) 2917dd7cddfSDavid du Colombier { 2927dd7cddfSDavid du Colombier if(c->outof) 2937dd7cddfSDavid du Colombier Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f, 2947dd7cddfSDavid du Colombier c->outof - c->count, c->outof, 2957dd7cddfSDavid du Colombier (double)(c->outof - c->count)/c->outof); 2967dd7cddfSDavid du Colombier } 2977dd7cddfSDavid du Colombier 2987dd7cddfSDavid du Colombier void 2997dd7cddfSDavid du Colombier asmsym(void) 3007dd7cddfSDavid du Colombier { 3017dd7cddfSDavid du Colombier Prog *p; 3027dd7cddfSDavid du Colombier Auto *a; 3037dd7cddfSDavid du Colombier Sym *s; 3047dd7cddfSDavid du Colombier int h; 3057dd7cddfSDavid du Colombier 3067dd7cddfSDavid du Colombier s = lookup("etext", 0); 3077dd7cddfSDavid du Colombier if(s->type == STEXT) 3087dd7cddfSDavid du Colombier putsymb(s->name, 'T', s->value, s->version); 3097dd7cddfSDavid du Colombier 3107dd7cddfSDavid du Colombier for(h=0; h<NHASH; h++) 3117dd7cddfSDavid du Colombier for(s=hash[h]; s!=S; s=s->link) 3127dd7cddfSDavid du Colombier switch(s->type) { 3137dd7cddfSDavid du Colombier case SCONST: 3147dd7cddfSDavid du Colombier putsymb(s->name, 'D', s->value, s->version); 3157dd7cddfSDavid du Colombier continue; 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier case SDATA: 3187dd7cddfSDavid du Colombier putsymb(s->name, 'D', s->value+INITDAT, s->version); 3197dd7cddfSDavid du Colombier continue; 3207dd7cddfSDavid du Colombier 3217dd7cddfSDavid du Colombier case SBSS: 3227dd7cddfSDavid du Colombier putsymb(s->name, 'B', s->value+INITDAT, s->version); 3237dd7cddfSDavid du Colombier continue; 3247dd7cddfSDavid du Colombier 3259a747e4fSDavid du Colombier case SSTRING: 3269a747e4fSDavid du Colombier putsymb(s->name, 'T', s->value, s->version); 3279a747e4fSDavid du Colombier continue; 3289a747e4fSDavid du Colombier 3297dd7cddfSDavid du Colombier case SFILE: 3307dd7cddfSDavid du Colombier putsymb(s->name, 'f', s->value, s->version); 3317dd7cddfSDavid du Colombier continue; 3327dd7cddfSDavid du Colombier } 3337dd7cddfSDavid du Colombier 3347dd7cddfSDavid du Colombier for(p=textp; p!=P; p=p->cond) { 3357dd7cddfSDavid du Colombier s = p->from.sym; 3367dd7cddfSDavid du Colombier if(s->type != STEXT && s->type != SLEAF) 3377dd7cddfSDavid du Colombier continue; 3387dd7cddfSDavid du Colombier 3397dd7cddfSDavid du Colombier /* filenames first */ 3407dd7cddfSDavid du Colombier for(a=p->to.autom; a; a=a->link) 3417dd7cddfSDavid du Colombier if(a->type == D_FILE) 3427dd7cddfSDavid du Colombier putsymb(a->asym->name, 'z', a->aoffset, 0); 3437dd7cddfSDavid du Colombier else 3447dd7cddfSDavid du Colombier if(a->type == D_FILE1) 3457dd7cddfSDavid du Colombier putsymb(a->asym->name, 'Z', a->aoffset, 0); 3467dd7cddfSDavid du Colombier 3477dd7cddfSDavid du Colombier if(s->type == STEXT) 3487dd7cddfSDavid du Colombier putsymb(s->name, 'T', s->value, s->version); 3497dd7cddfSDavid du Colombier else 3507dd7cddfSDavid du Colombier putsymb(s->name, 'L', s->value, s->version); 3517dd7cddfSDavid du Colombier 3527dd7cddfSDavid du Colombier /* frame, auto and param after */ 3537dd7cddfSDavid du Colombier putsymb(".frame", 'm', p->to.offset+4, 0); 3547dd7cddfSDavid du Colombier for(a=p->to.autom; a; a=a->link) 3557dd7cddfSDavid du Colombier if(a->type == D_AUTO) 3567dd7cddfSDavid du Colombier putsymb(a->asym->name, 'a', -a->aoffset, 0); 3577dd7cddfSDavid du Colombier else 3587dd7cddfSDavid du Colombier if(a->type == D_PARAM) 3597dd7cddfSDavid du Colombier putsymb(a->asym->name, 'p', a->aoffset, 0); 3607dd7cddfSDavid du Colombier } 3617dd7cddfSDavid du Colombier if(debug['v'] || debug['n']) 3627dd7cddfSDavid du Colombier Bprint(&bso, "symsize = %lud\n", symsize); 3637dd7cddfSDavid du Colombier Bflush(&bso); 3647dd7cddfSDavid du Colombier } 3657dd7cddfSDavid du Colombier 3667dd7cddfSDavid du Colombier void 3677dd7cddfSDavid du Colombier putsymb(char *s, int t, long v, int ver) 3687dd7cddfSDavid du Colombier { 3697dd7cddfSDavid du Colombier int i, f; 3707dd7cddfSDavid du Colombier 3717dd7cddfSDavid du Colombier if(t == 'f') 3727dd7cddfSDavid du Colombier s++; 3737dd7cddfSDavid du Colombier lput(v); 3747dd7cddfSDavid du Colombier if(ver) 3757dd7cddfSDavid du Colombier t += 'a' - 'A'; 37659cc4ca5SDavid du Colombier cput(t+0x80); /* 0x80 is variable length */ 3777dd7cddfSDavid du Colombier 3787dd7cddfSDavid du Colombier if(t == 'Z' || t == 'z') { 37959cc4ca5SDavid du Colombier cput(s[0]); 3807dd7cddfSDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 38159cc4ca5SDavid du Colombier cput(s[i]); 38259cc4ca5SDavid du Colombier cput(s[i+1]); 3837dd7cddfSDavid du Colombier } 38459cc4ca5SDavid du Colombier cput(0); 38559cc4ca5SDavid du Colombier cput(0); 3867dd7cddfSDavid du Colombier i++; 3877dd7cddfSDavid du Colombier } 3887dd7cddfSDavid du Colombier else { 3897dd7cddfSDavid du Colombier for(i=0; s[i]; i++) 39059cc4ca5SDavid du Colombier cput(s[i]); 39159cc4ca5SDavid du Colombier cput(0); 3927dd7cddfSDavid du Colombier } 3937dd7cddfSDavid du Colombier symsize += 4 + 1 + i + 1; 3947dd7cddfSDavid du Colombier 3957dd7cddfSDavid du Colombier if(debug['n']) { 3967dd7cddfSDavid du Colombier if(t == 'z' || t == 'Z') { 3977dd7cddfSDavid du Colombier Bprint(&bso, "%c %.8lux ", t, v); 3987dd7cddfSDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 3997dd7cddfSDavid du Colombier f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 4007dd7cddfSDavid du Colombier Bprint(&bso, "/%x", f); 4017dd7cddfSDavid du Colombier } 4027dd7cddfSDavid du Colombier Bprint(&bso, "\n"); 4037dd7cddfSDavid du Colombier return; 4047dd7cddfSDavid du Colombier } 4057dd7cddfSDavid du Colombier if(ver) 4067dd7cddfSDavid du Colombier Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 4077dd7cddfSDavid du Colombier else 4087dd7cddfSDavid du Colombier Bprint(&bso, "%c %.8lux %s\n", t, v, s); 4097dd7cddfSDavid du Colombier } 4107dd7cddfSDavid du Colombier } 4117dd7cddfSDavid du Colombier 4127dd7cddfSDavid du Colombier #define MINLC 4 4137dd7cddfSDavid du Colombier void 4147dd7cddfSDavid du Colombier asmlc(void) 4157dd7cddfSDavid du Colombier { 4167dd7cddfSDavid du Colombier long oldpc, oldlc; 4177dd7cddfSDavid du Colombier Prog *p; 4187dd7cddfSDavid du Colombier long v, s; 4197dd7cddfSDavid du Colombier 4207dd7cddfSDavid du Colombier oldpc = INITTEXT; 4217dd7cddfSDavid du Colombier oldlc = 0; 4227dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) { 4237dd7cddfSDavid du Colombier if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 4247dd7cddfSDavid du Colombier if(p->as == ATEXT) 4257dd7cddfSDavid du Colombier curtext = p; 4267dd7cddfSDavid du Colombier if(debug['L']) 4277dd7cddfSDavid du Colombier Bprint(&bso, "%6lux %P\n", 4287dd7cddfSDavid du Colombier p->pc, p); 4297dd7cddfSDavid du Colombier continue; 4307dd7cddfSDavid du Colombier } 4317dd7cddfSDavid du Colombier if(debug['L']) 4327dd7cddfSDavid du Colombier Bprint(&bso, "\t\t%6ld", lcsize); 4337dd7cddfSDavid du Colombier v = (p->pc - oldpc) / MINLC; 4347dd7cddfSDavid du Colombier while(v) { 4357dd7cddfSDavid du Colombier s = 127; 4367dd7cddfSDavid du Colombier if(v < 127) 4377dd7cddfSDavid du Colombier s = v; 43859cc4ca5SDavid du Colombier cput(s+128); /* 129-255 +pc */ 4397dd7cddfSDavid du Colombier if(debug['L']) 4407dd7cddfSDavid du Colombier Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 4417dd7cddfSDavid du Colombier v -= s; 4427dd7cddfSDavid du Colombier lcsize++; 4437dd7cddfSDavid du Colombier } 4447dd7cddfSDavid du Colombier s = p->line - oldlc; 4457dd7cddfSDavid du Colombier oldlc = p->line; 4467dd7cddfSDavid du Colombier oldpc = p->pc + MINLC; 4477dd7cddfSDavid du Colombier if(s > 64 || s < -64) { 44859cc4ca5SDavid du Colombier cput(0); /* 0 vv +lc */ 44959cc4ca5SDavid du Colombier cput(s>>24); 45059cc4ca5SDavid du Colombier cput(s>>16); 45159cc4ca5SDavid du Colombier cput(s>>8); 45259cc4ca5SDavid du Colombier cput(s); 4537dd7cddfSDavid du Colombier if(debug['L']) { 4547dd7cddfSDavid du Colombier if(s > 0) 4557dd7cddfSDavid du Colombier Bprint(&bso, " lc+%ld(%d,%ld)\n", 4567dd7cddfSDavid du Colombier s, 0, s); 4577dd7cddfSDavid du Colombier else 4587dd7cddfSDavid du Colombier Bprint(&bso, " lc%ld(%d,%ld)\n", 4597dd7cddfSDavid du Colombier s, 0, s); 4607dd7cddfSDavid du Colombier Bprint(&bso, "%6lux %P\n", 4617dd7cddfSDavid du Colombier p->pc, p); 4627dd7cddfSDavid du Colombier } 4637dd7cddfSDavid du Colombier lcsize += 5; 4647dd7cddfSDavid du Colombier continue; 4657dd7cddfSDavid du Colombier } 4667dd7cddfSDavid du Colombier if(s > 0) { 46759cc4ca5SDavid du Colombier cput(0+s); /* 1-64 +lc */ 4687dd7cddfSDavid du Colombier if(debug['L']) { 4697dd7cddfSDavid du Colombier Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 4707dd7cddfSDavid du Colombier Bprint(&bso, "%6lux %P\n", 4717dd7cddfSDavid du Colombier p->pc, p); 4727dd7cddfSDavid du Colombier } 4737dd7cddfSDavid du Colombier } else { 47459cc4ca5SDavid du Colombier cput(64-s); /* 65-128 -lc */ 4757dd7cddfSDavid du Colombier if(debug['L']) { 4767dd7cddfSDavid du Colombier Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 4777dd7cddfSDavid du Colombier Bprint(&bso, "%6lux %P\n", 4787dd7cddfSDavid du Colombier p->pc, p); 4797dd7cddfSDavid du Colombier } 4807dd7cddfSDavid du Colombier } 4817dd7cddfSDavid du Colombier lcsize++; 4827dd7cddfSDavid du Colombier } 4837dd7cddfSDavid du Colombier while(lcsize & 1) { 4847dd7cddfSDavid du Colombier s = 129; 48559cc4ca5SDavid du Colombier cput(s); 4867dd7cddfSDavid du Colombier lcsize++; 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier if(debug['v'] || debug['L']) 4897dd7cddfSDavid du Colombier Bprint(&bso, "lcsize = %ld\n", lcsize); 4907dd7cddfSDavid du Colombier Bflush(&bso); 4917dd7cddfSDavid du Colombier } 4927dd7cddfSDavid du Colombier 4937dd7cddfSDavid du Colombier void 4949a747e4fSDavid du Colombier datblk(long s, long n, int str) 4957dd7cddfSDavid du Colombier { 4969a747e4fSDavid du Colombier Sym *v; 4977dd7cddfSDavid du Colombier Prog *p; 4987dd7cddfSDavid du Colombier char *cast; 4999a747e4fSDavid du Colombier long a, l, fl, j, d; 5007dd7cddfSDavid du Colombier int i, c; 5017dd7cddfSDavid du Colombier 5027dd7cddfSDavid du Colombier memset(buf.dbuf, 0, n+100); 5037dd7cddfSDavid du Colombier for(p = datap; p != P; p = p->link) { 5049a747e4fSDavid du Colombier if(str != (p->from.sym->type == SSTRING)) 5059a747e4fSDavid du Colombier continue; 5067dd7cddfSDavid du Colombier curp = p; 5079a747e4fSDavid du Colombier a = p->from.sym->value + p->from.offset; 5089a747e4fSDavid du Colombier l = a - s; 5097dd7cddfSDavid du Colombier c = p->reg; 5107dd7cddfSDavid du Colombier i = 0; 5117dd7cddfSDavid du Colombier if(l < 0) { 5127dd7cddfSDavid du Colombier if(l+c <= 0) 5137dd7cddfSDavid du Colombier continue; 5147dd7cddfSDavid du Colombier while(l < 0) { 5157dd7cddfSDavid du Colombier l++; 5167dd7cddfSDavid du Colombier i++; 5177dd7cddfSDavid du Colombier } 5187dd7cddfSDavid du Colombier } 5197dd7cddfSDavid du Colombier if(l >= n) 5207dd7cddfSDavid du Colombier continue; 5217dd7cddfSDavid du Colombier if(p->as != AINIT && p->as != ADYNT) { 5227dd7cddfSDavid du Colombier for(j=l+(c-i)-1; j>=l; j--) 5237dd7cddfSDavid du Colombier if(buf.dbuf[j]) { 5247dd7cddfSDavid du Colombier print("%P\n", p); 5257dd7cddfSDavid du Colombier diag("multiple initialization"); 5267dd7cddfSDavid du Colombier break; 5277dd7cddfSDavid du Colombier } 5287dd7cddfSDavid du Colombier } 5297dd7cddfSDavid du Colombier switch(p->to.type) { 5307dd7cddfSDavid du Colombier default: 5317dd7cddfSDavid du Colombier diag("unknown mode in initialization%P", p); 5327dd7cddfSDavid du Colombier break; 5337dd7cddfSDavid du Colombier 5347dd7cddfSDavid du Colombier case D_FCONST: 5357dd7cddfSDavid du Colombier switch(c) { 5367dd7cddfSDavid du Colombier default: 5377dd7cddfSDavid du Colombier case 4: 5387dd7cddfSDavid du Colombier fl = ieeedtof(p->to.ieee); 5397dd7cddfSDavid du Colombier cast = (char*)&fl; 5407dd7cddfSDavid du Colombier for(; i<c; i++) { 5417dd7cddfSDavid du Colombier buf.dbuf[l] = cast[fnuxi4[i]]; 5427dd7cddfSDavid du Colombier l++; 5437dd7cddfSDavid du Colombier } 5447dd7cddfSDavid du Colombier break; 5457dd7cddfSDavid du Colombier case 8: 5467dd7cddfSDavid du Colombier cast = (char*)p->to.ieee; 5477dd7cddfSDavid du Colombier for(; i<c; i++) { 5487dd7cddfSDavid du Colombier buf.dbuf[l] = cast[fnuxi8[i]]; 5497dd7cddfSDavid du Colombier l++; 5507dd7cddfSDavid du Colombier } 5517dd7cddfSDavid du Colombier break; 5527dd7cddfSDavid du Colombier } 5537dd7cddfSDavid du Colombier break; 5547dd7cddfSDavid du Colombier 5557dd7cddfSDavid du Colombier case D_SCONST: 5567dd7cddfSDavid du Colombier for(; i<c; i++) { 5577dd7cddfSDavid du Colombier buf.dbuf[l] = p->to.sval[i]; 5587dd7cddfSDavid du Colombier l++; 5597dd7cddfSDavid du Colombier } 5607dd7cddfSDavid du Colombier break; 5617dd7cddfSDavid du Colombier 5627dd7cddfSDavid du Colombier case D_CONST: 5637dd7cddfSDavid du Colombier d = p->to.offset; 5649a747e4fSDavid du Colombier v = p->to.sym; 5659a747e4fSDavid du Colombier if(v) { 5669a747e4fSDavid du Colombier switch(v->type) { 567375daca8SDavid du Colombier case SUNDEF: 568375daca8SDavid du Colombier ckoff(v, d); 5699a747e4fSDavid du Colombier case STEXT: 5709a747e4fSDavid du Colombier case SLEAF: 5719a747e4fSDavid du Colombier case SSTRING: 5727dd7cddfSDavid du Colombier d += p->to.sym->value; 5739a747e4fSDavid du Colombier break; 5749a747e4fSDavid du Colombier case SDATA: 5759a747e4fSDavid du Colombier case SBSS: 5767dd7cddfSDavid du Colombier d += p->to.sym->value + INITDAT; 5779a747e4fSDavid du Colombier } 578375daca8SDavid du Colombier if(dlm) 579375daca8SDavid du Colombier dynreloc(v, a+INITDAT, 1); 5807dd7cddfSDavid du Colombier } 5817dd7cddfSDavid du Colombier cast = (char*)&d; 5827dd7cddfSDavid du Colombier switch(c) { 5837dd7cddfSDavid du Colombier default: 5847dd7cddfSDavid du Colombier diag("bad nuxi %d %d%P", c, i, curp); 5857dd7cddfSDavid du Colombier break; 5867dd7cddfSDavid du Colombier case 1: 5877dd7cddfSDavid du Colombier for(; i<c; i++) { 5887dd7cddfSDavid du Colombier buf.dbuf[l] = cast[inuxi1[i]]; 5897dd7cddfSDavid du Colombier l++; 5907dd7cddfSDavid du Colombier } 5917dd7cddfSDavid du Colombier break; 5927dd7cddfSDavid du Colombier case 2: 5937dd7cddfSDavid du Colombier for(; i<c; i++) { 5947dd7cddfSDavid du Colombier buf.dbuf[l] = cast[inuxi2[i]]; 5957dd7cddfSDavid du Colombier l++; 5967dd7cddfSDavid du Colombier } 5977dd7cddfSDavid du Colombier break; 5987dd7cddfSDavid du Colombier case 4: 5997dd7cddfSDavid du Colombier for(; i<c; i++) { 6007dd7cddfSDavid du Colombier buf.dbuf[l] = cast[inuxi4[i]]; 6017dd7cddfSDavid du Colombier l++; 6027dd7cddfSDavid du Colombier } 6037dd7cddfSDavid du Colombier break; 6047dd7cddfSDavid du Colombier } 6057dd7cddfSDavid du Colombier break; 6067dd7cddfSDavid du Colombier } 6077dd7cddfSDavid du Colombier } 6087dd7cddfSDavid du Colombier write(cout, buf.dbuf, n); 6097dd7cddfSDavid du Colombier } 6107dd7cddfSDavid du Colombier 6117dd7cddfSDavid du Colombier void 6127dd7cddfSDavid du Colombier asmout(Prog *p, Optab *o) 6137dd7cddfSDavid du Colombier { 61459cc4ca5SDavid du Colombier long o1, o2, o3, o4, o5, o6, v; 61559cc4ca5SDavid du Colombier int r, rf, rt, rt2; 6169a747e4fSDavid du Colombier Sym *s; 6177dd7cddfSDavid du Colombier 61859cc4ca5SDavid du Colombier PP = p; 6197dd7cddfSDavid du Colombier o1 = 0; 6207dd7cddfSDavid du Colombier o2 = 0; 6217dd7cddfSDavid du Colombier o3 = 0; 6227dd7cddfSDavid du Colombier o4 = 0; 6237dd7cddfSDavid du Colombier o5 = 0; 62459cc4ca5SDavid du Colombier o6 = 0; 6257dd7cddfSDavid du Colombier switch(o->type) { 6267dd7cddfSDavid du Colombier default: 6277dd7cddfSDavid du Colombier diag("unknown asm %d", o->type); 6287dd7cddfSDavid du Colombier prasm(p); 6297dd7cddfSDavid du Colombier break; 6307dd7cddfSDavid du Colombier 6317dd7cddfSDavid du Colombier case 0: /* pseudo ops */ 6327dd7cddfSDavid du Colombier break; 6337dd7cddfSDavid du Colombier 6347dd7cddfSDavid du Colombier case 1: /* op R,[R],R */ 6357dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 6367dd7cddfSDavid du Colombier rf = p->from.reg; 6377dd7cddfSDavid du Colombier rt = p->to.reg; 6387dd7cddfSDavid du Colombier r = p->reg; 6397dd7cddfSDavid du Colombier if(p->to.type == D_NONE) 6407dd7cddfSDavid du Colombier rt = 0; 641*530fef66SDavid du Colombier if(p->as == AMOVW || p->as == AMVN) 642*530fef66SDavid du Colombier r = 0; 643*530fef66SDavid du Colombier else if(r == NREG) 6447dd7cddfSDavid du Colombier r = rt; 6457dd7cddfSDavid du Colombier o1 |= rf | (r<<16) | (rt<<12); 6467dd7cddfSDavid du Colombier break; 6477dd7cddfSDavid du Colombier 64859cc4ca5SDavid du Colombier case 2: /* movbu $I,[R],R */ 6497dd7cddfSDavid du Colombier aclass(&p->from); 6507dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 6517dd7cddfSDavid du Colombier o1 |= immrot(instoffset); 6527dd7cddfSDavid du Colombier rt = p->to.reg; 6537dd7cddfSDavid du Colombier r = p->reg; 6547dd7cddfSDavid du Colombier if(p->to.type == D_NONE) 6557dd7cddfSDavid du Colombier rt = 0; 656*530fef66SDavid du Colombier if(p->as == AMOVW || p->as == AMVN) 657*530fef66SDavid du Colombier r = 0; 658*530fef66SDavid du Colombier else if(r == NREG) 6597dd7cddfSDavid du Colombier r = rt; 6607dd7cddfSDavid du Colombier o1 |= (r<<16) | (rt<<12); 6617dd7cddfSDavid du Colombier break; 6627dd7cddfSDavid du Colombier 6637dd7cddfSDavid du Colombier case 3: /* add R<<[IR],[R],R */ 66459cc4ca5SDavid du Colombier mov: 6657dd7cddfSDavid du Colombier aclass(&p->from); 6667dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 6677dd7cddfSDavid du Colombier o1 |= p->from.offset; 6687dd7cddfSDavid du Colombier rt = p->to.reg; 6697dd7cddfSDavid du Colombier r = p->reg; 6707dd7cddfSDavid du Colombier if(p->to.type == D_NONE) 6717dd7cddfSDavid du Colombier rt = 0; 672*530fef66SDavid du Colombier if(p->as == AMOVW || p->as == AMVN) 673*530fef66SDavid du Colombier r = 0; 674*530fef66SDavid du Colombier else if(r == NREG) 6757dd7cddfSDavid du Colombier r = rt; 6767dd7cddfSDavid du Colombier o1 |= (r<<16) | (rt<<12); 6777dd7cddfSDavid du Colombier break; 6787dd7cddfSDavid du Colombier 6797dd7cddfSDavid du Colombier case 4: /* add $I,[R],R */ 6807dd7cddfSDavid du Colombier aclass(&p->from); 6817dd7cddfSDavid du Colombier o1 = oprrr(AADD, p->scond); 6827dd7cddfSDavid du Colombier o1 |= immrot(instoffset); 6837dd7cddfSDavid du Colombier r = p->from.reg; 6847dd7cddfSDavid du Colombier if(r == NREG) 6857dd7cddfSDavid du Colombier r = o->param; 6867dd7cddfSDavid du Colombier o1 |= r << 16; 6877dd7cddfSDavid du Colombier o1 |= p->to.reg << 12; 6887dd7cddfSDavid du Colombier break; 6897dd7cddfSDavid du Colombier 6907dd7cddfSDavid du Colombier case 5: /* bra s */ 6917dd7cddfSDavid du Colombier v = -8; 6929a747e4fSDavid du Colombier if(p->cond == UP) { 6939a747e4fSDavid du Colombier s = p->to.sym; 694375daca8SDavid du Colombier if(s->type != SUNDEF) 695375daca8SDavid du Colombier diag("bad branch sym type"); 696375daca8SDavid du Colombier v = (ulong)s->value >> (Roffset-2); 697375daca8SDavid du Colombier dynreloc(s, p->pc, 0); 6989a747e4fSDavid du Colombier } 6999a747e4fSDavid du Colombier else if(p->cond != P) 7007dd7cddfSDavid du Colombier v = (p->cond->pc - pc) - 8; 7017dd7cddfSDavid du Colombier o1 = opbra(p->as, p->scond); 7027dd7cddfSDavid du Colombier o1 |= (v >> 2) & 0xffffff; 7037dd7cddfSDavid du Colombier break; 7047dd7cddfSDavid du Colombier 7057dd7cddfSDavid du Colombier case 6: /* b ,O(R) -> add $O,R,PC */ 7067dd7cddfSDavid du Colombier aclass(&p->to); 7077dd7cddfSDavid du Colombier o1 = oprrr(AADD, p->scond); 7087dd7cddfSDavid du Colombier o1 |= immrot(instoffset); 7097dd7cddfSDavid du Colombier o1 |= p->to.reg << 16; 7107dd7cddfSDavid du Colombier o1 |= REGPC << 12; 7117dd7cddfSDavid du Colombier break; 7127dd7cddfSDavid du Colombier 7137dd7cddfSDavid du Colombier case 7: /* bl ,O(R) -> mov PC,link; add $O,R,PC */ 7147dd7cddfSDavid du Colombier aclass(&p->to); 7157dd7cddfSDavid du Colombier o1 = oprrr(AADD, p->scond); 7167dd7cddfSDavid du Colombier o1 |= immrot(0); 7177dd7cddfSDavid du Colombier o1 |= REGPC << 16; 7187dd7cddfSDavid du Colombier o1 |= REGLINK << 12; 7197dd7cddfSDavid du Colombier 7207dd7cddfSDavid du Colombier o2 = oprrr(AADD, p->scond); 7217dd7cddfSDavid du Colombier o2 |= immrot(instoffset); 7227dd7cddfSDavid du Colombier o2 |= p->to.reg << 16; 7237dd7cddfSDavid du Colombier o2 |= REGPC << 12; 7247dd7cddfSDavid du Colombier break; 7257dd7cddfSDavid du Colombier 7267dd7cddfSDavid du Colombier case 8: /* sll $c,[R],R -> mov (R<<$c),R */ 7277dd7cddfSDavid du Colombier aclass(&p->from); 7287dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 7297dd7cddfSDavid du Colombier r = p->reg; 7307dd7cddfSDavid du Colombier if(r == NREG) 7317dd7cddfSDavid du Colombier r = p->to.reg; 7327dd7cddfSDavid du Colombier o1 |= r; 7337dd7cddfSDavid du Colombier o1 |= (instoffset&31) << 7; 7347dd7cddfSDavid du Colombier o1 |= p->to.reg << 12; 7357dd7cddfSDavid du Colombier break; 7367dd7cddfSDavid du Colombier 7377dd7cddfSDavid du Colombier case 9: /* sll R,[R],R -> mov (R<<R),R */ 7387dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 7397dd7cddfSDavid du Colombier r = p->reg; 7407dd7cddfSDavid du Colombier if(r == NREG) 7417dd7cddfSDavid du Colombier r = p->to.reg; 7427dd7cddfSDavid du Colombier o1 |= r; 7437dd7cddfSDavid du Colombier o1 |= (p->from.reg << 8) | (1<<4); 7447dd7cddfSDavid du Colombier o1 |= p->to.reg << 12; 7457dd7cddfSDavid du Colombier break; 7467dd7cddfSDavid du Colombier 7477dd7cddfSDavid du Colombier case 10: /* swi [$con] */ 7487dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 7497dd7cddfSDavid du Colombier if(p->to.type != D_NONE) { 7507dd7cddfSDavid du Colombier aclass(&p->to); 7517dd7cddfSDavid du Colombier o1 |= instoffset & 0xffffff; 7527dd7cddfSDavid du Colombier } 7537dd7cddfSDavid du Colombier break; 7547dd7cddfSDavid du Colombier 7557dd7cddfSDavid du Colombier case 11: /* word */ 7569a747e4fSDavid du Colombier switch(aclass(&p->to)) { 7579a747e4fSDavid du Colombier case C_LCON: 758375daca8SDavid du Colombier if(!dlm) 7599a747e4fSDavid du Colombier break; 7609a747e4fSDavid du Colombier if(p->to.name != D_EXTERN && p->to.name != D_STATIC) 7619a747e4fSDavid du Colombier break; 7629a747e4fSDavid du Colombier case C_ADDR: 763375daca8SDavid du Colombier if(p->to.sym->type == SUNDEF) 764375daca8SDavid du Colombier ckoff(p->to.sym, p->to.offset); 765375daca8SDavid du Colombier dynreloc(p->to.sym, p->pc, 1); 7669a747e4fSDavid du Colombier } 7677dd7cddfSDavid du Colombier o1 = instoffset; 7687dd7cddfSDavid du Colombier break; 7697dd7cddfSDavid du Colombier 7707dd7cddfSDavid du Colombier case 12: /* movw $lcon, reg */ 77159cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, p->to.reg); 7727dd7cddfSDavid du Colombier break; 7737dd7cddfSDavid du Colombier 7747dd7cddfSDavid du Colombier case 13: /* op $lcon, [R], R */ 77559cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 77659cc4ca5SDavid du Colombier if(!o1) 7777dd7cddfSDavid du Colombier break; 7787dd7cddfSDavid du Colombier o2 = oprrr(p->as, p->scond); 7797dd7cddfSDavid du Colombier o2 |= REGTMP; 7807dd7cddfSDavid du Colombier r = p->reg; 781*530fef66SDavid du Colombier if(p->as == AMOVW || p->as == AMVN) 782*530fef66SDavid du Colombier r = 0; 783*530fef66SDavid du Colombier else if(r == NREG) 7847dd7cddfSDavid du Colombier r = p->to.reg; 7857dd7cddfSDavid du Colombier o2 |= r << 16; 7867dd7cddfSDavid du Colombier if(p->to.type != D_NONE) 7877dd7cddfSDavid du Colombier o2 |= p->to.reg << 12; 7887dd7cddfSDavid du Colombier break; 7897dd7cddfSDavid du Colombier 7907dd7cddfSDavid du Colombier case 14: /* movb/movbu/movh/movhu R,R */ 7917dd7cddfSDavid du Colombier o1 = oprrr(ASLL, p->scond); 7927dd7cddfSDavid du Colombier 7937dd7cddfSDavid du Colombier if(p->as == AMOVBU || p->as == AMOVHU) 7947dd7cddfSDavid du Colombier o2 = oprrr(ASRL, p->scond); 7957dd7cddfSDavid du Colombier else 7967dd7cddfSDavid du Colombier o2 = oprrr(ASRA, p->scond); 7977dd7cddfSDavid du Colombier 7987dd7cddfSDavid du Colombier r = p->to.reg; 7997dd7cddfSDavid du Colombier o1 |= (p->from.reg)|(r<<12); 8007dd7cddfSDavid du Colombier o2 |= (r)|(r<<12); 8017dd7cddfSDavid du Colombier if(p->as == AMOVB || p->as == AMOVBU) { 8027dd7cddfSDavid du Colombier o1 |= (24<<7); 8037dd7cddfSDavid du Colombier o2 |= (24<<7); 8047dd7cddfSDavid du Colombier } else { 8057dd7cddfSDavid du Colombier o1 |= (16<<7); 8067dd7cddfSDavid du Colombier o2 |= (16<<7); 8077dd7cddfSDavid du Colombier } 8087dd7cddfSDavid du Colombier break; 8097dd7cddfSDavid du Colombier 8107dd7cddfSDavid du Colombier case 15: /* mul r,[r,]r */ 8117dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 8127dd7cddfSDavid du Colombier rf = p->from.reg; 8137dd7cddfSDavid du Colombier rt = p->to.reg; 8147dd7cddfSDavid du Colombier r = p->reg; 8157dd7cddfSDavid du Colombier if(r == NREG) 8167dd7cddfSDavid du Colombier r = rt; 8177dd7cddfSDavid du Colombier if(rt == r) { 8187dd7cddfSDavid du Colombier r = rf; 8197dd7cddfSDavid du Colombier rf = rt; 8207dd7cddfSDavid du Colombier } 8217dd7cddfSDavid du Colombier if(0) 8227dd7cddfSDavid du Colombier if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) { 8237dd7cddfSDavid du Colombier diag("bad registers in MUL"); 8247dd7cddfSDavid du Colombier prasm(p); 8257dd7cddfSDavid du Colombier } 8267dd7cddfSDavid du Colombier o1 |= (rf<<8) | r | (rt<<16); 8277dd7cddfSDavid du Colombier break; 8287dd7cddfSDavid du Colombier 8297dd7cddfSDavid du Colombier 8307dd7cddfSDavid du Colombier case 16: /* div r,[r,]r */ 8317dd7cddfSDavid du Colombier o1 = 0xf << 28; 8327dd7cddfSDavid du Colombier o2 = 0; 8337dd7cddfSDavid du Colombier break; 8347dd7cddfSDavid du Colombier 83559cc4ca5SDavid du Colombier case 17: 83659cc4ca5SDavid du Colombier o1 = oprrr(p->as, p->scond); 83759cc4ca5SDavid du Colombier rf = p->from.reg; 83859cc4ca5SDavid du Colombier rt = p->to.reg; 83959cc4ca5SDavid du Colombier rt2 = p->to.offset; 84059cc4ca5SDavid du Colombier r = p->reg; 84159cc4ca5SDavid du Colombier o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12); 84259cc4ca5SDavid du Colombier break; 84359cc4ca5SDavid du Colombier 8447dd7cddfSDavid du Colombier case 20: /* mov/movb/movbu R,O(R) */ 8457dd7cddfSDavid du Colombier aclass(&p->to); 8467dd7cddfSDavid du Colombier r = p->to.reg; 8477dd7cddfSDavid du Colombier if(r == NREG) 8487dd7cddfSDavid du Colombier r = o->param; 8497dd7cddfSDavid du Colombier o1 = osr(p->as, p->from.reg, instoffset, r, p->scond); 8507dd7cddfSDavid du Colombier break; 8517dd7cddfSDavid du Colombier 8527dd7cddfSDavid du Colombier case 21: /* mov/movbu O(R),R -> lr */ 8537dd7cddfSDavid du Colombier aclass(&p->from); 8547dd7cddfSDavid du Colombier r = p->from.reg; 8557dd7cddfSDavid du Colombier if(r == NREG) 8567dd7cddfSDavid du Colombier r = o->param; 8577dd7cddfSDavid du Colombier o1 = olr(instoffset, r, p->to.reg, p->scond); 8587dd7cddfSDavid du Colombier if(p->as != AMOVW) 8597dd7cddfSDavid du Colombier o1 |= 1<<22; 8607dd7cddfSDavid du Colombier break; 8617dd7cddfSDavid du Colombier 8627dd7cddfSDavid du Colombier case 22: /* movb/movh/movhu O(R),R -> lr,shl,shr */ 8637dd7cddfSDavid du Colombier aclass(&p->from); 8647dd7cddfSDavid du Colombier r = p->from.reg; 8657dd7cddfSDavid du Colombier if(r == NREG) 8667dd7cddfSDavid du Colombier r = o->param; 8677dd7cddfSDavid du Colombier o1 = olr(instoffset, r, p->to.reg, p->scond); 8687dd7cddfSDavid du Colombier 8697dd7cddfSDavid du Colombier o2 = oprrr(ASLL, p->scond); 8707dd7cddfSDavid du Colombier o3 = oprrr(ASRA, p->scond); 8717dd7cddfSDavid du Colombier r = p->to.reg; 8727dd7cddfSDavid du Colombier if(p->as == AMOVB) { 8737dd7cddfSDavid du Colombier o2 |= (24<<7)|(r)|(r<<12); 8747dd7cddfSDavid du Colombier o3 |= (24<<7)|(r)|(r<<12); 8757dd7cddfSDavid du Colombier } else { 8767dd7cddfSDavid du Colombier o2 |= (16<<7)|(r)|(r<<12); 8777dd7cddfSDavid du Colombier if(p->as == AMOVHU) 8787dd7cddfSDavid du Colombier o3 = oprrr(ASRL, p->scond); 8797dd7cddfSDavid du Colombier o3 |= (16<<7)|(r)|(r<<12); 8807dd7cddfSDavid du Colombier } 8817dd7cddfSDavid du Colombier break; 8827dd7cddfSDavid du Colombier 8837dd7cddfSDavid du Colombier case 23: /* movh/movhu R,O(R) -> sb,sb */ 8847dd7cddfSDavid du Colombier aclass(&p->to); 8857dd7cddfSDavid du Colombier r = p->to.reg; 8867dd7cddfSDavid du Colombier if(r == NREG) 8877dd7cddfSDavid du Colombier r = o->param; 8887dd7cddfSDavid du Colombier o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond); 8897dd7cddfSDavid du Colombier 8907dd7cddfSDavid du Colombier o2 = oprrr(ASRL, p->scond); 8917dd7cddfSDavid du Colombier o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12); 8927dd7cddfSDavid du Colombier 8937dd7cddfSDavid du Colombier o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond); 8947dd7cddfSDavid du Colombier break; 8957dd7cddfSDavid du Colombier 8967dd7cddfSDavid du Colombier case 30: /* mov/movb/movbu R,L(R) */ 89759cc4ca5SDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 89859cc4ca5SDavid du Colombier if(!o1) 8997dd7cddfSDavid du Colombier break; 9007dd7cddfSDavid du Colombier r = p->to.reg; 9017dd7cddfSDavid du Colombier if(r == NREG) 9027dd7cddfSDavid du Colombier r = o->param; 9037dd7cddfSDavid du Colombier o2 = osrr(p->from.reg, REGTMP,r, p->scond); 9047dd7cddfSDavid du Colombier if(p->as != AMOVW) 9057dd7cddfSDavid du Colombier o2 |= 1<<22; 9067dd7cddfSDavid du Colombier break; 9077dd7cddfSDavid du Colombier 9087dd7cddfSDavid du Colombier case 31: /* mov/movbu L(R),R -> lr[b] */ 9097dd7cddfSDavid du Colombier case 32: /* movh/movb L(R),R -> lr[b] */ 91059cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 91159cc4ca5SDavid du Colombier if(!o1) 9127dd7cddfSDavid du Colombier break; 9137dd7cddfSDavid du Colombier r = p->from.reg; 9147dd7cddfSDavid du Colombier if(r == NREG) 9157dd7cddfSDavid du Colombier r = o->param; 9167dd7cddfSDavid du Colombier o2 = olrr(REGTMP,r, p->to.reg, p->scond); 91759cc4ca5SDavid du Colombier if(p->as == AMOVBU || p->as == AMOVB) 9187dd7cddfSDavid du Colombier o2 |= 1<<22; 9197dd7cddfSDavid du Colombier if(o->type == 31) 9207dd7cddfSDavid du Colombier break; 9217dd7cddfSDavid du Colombier 9227dd7cddfSDavid du Colombier o3 = oprrr(ASLL, p->scond); 9237dd7cddfSDavid du Colombier 9247dd7cddfSDavid du Colombier if(p->as == AMOVBU || p->as == AMOVHU) 9257dd7cddfSDavid du Colombier o4 = oprrr(ASRL, p->scond); 9267dd7cddfSDavid du Colombier else 9277dd7cddfSDavid du Colombier o4 = oprrr(ASRA, p->scond); 9287dd7cddfSDavid du Colombier 9297dd7cddfSDavid du Colombier r = p->to.reg; 9307dd7cddfSDavid du Colombier o3 |= (r)|(r<<12); 9317dd7cddfSDavid du Colombier o4 |= (r)|(r<<12); 9327dd7cddfSDavid du Colombier if(p->as == AMOVB || p->as == AMOVBU) { 9337dd7cddfSDavid du Colombier o3 |= (24<<7); 9347dd7cddfSDavid du Colombier o4 |= (24<<7); 9357dd7cddfSDavid du Colombier } else { 9367dd7cddfSDavid du Colombier o3 |= (16<<7); 9377dd7cddfSDavid du Colombier o4 |= (16<<7); 9387dd7cddfSDavid du Colombier } 9397dd7cddfSDavid du Colombier break; 9407dd7cddfSDavid du Colombier 94159cc4ca5SDavid du Colombier case 33: /* movh/movhu R,L(R) -> sb, sb */ 94259cc4ca5SDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 94359cc4ca5SDavid du Colombier if(!o1) 9447dd7cddfSDavid du Colombier break; 9457dd7cddfSDavid du Colombier r = p->to.reg; 9467dd7cddfSDavid du Colombier if(r == NREG) 9477dd7cddfSDavid du Colombier r = o->param; 94859cc4ca5SDavid du Colombier o2 = osrr(p->from.reg, REGTMP, r, p->scond); 94959cc4ca5SDavid du Colombier o2 |= (1<<22) ; 95059cc4ca5SDavid du Colombier 95159cc4ca5SDavid du Colombier o3 = oprrr(ASRL, p->scond); 95259cc4ca5SDavid du Colombier o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); 95359cc4ca5SDavid du Colombier o3 |= (1<<6); /* ROR 8 */ 95459cc4ca5SDavid du Colombier 95559cc4ca5SDavid du Colombier o4 = oprrr(AADD, p->scond); 95659cc4ca5SDavid du Colombier o4 |= (REGTMP << 12) | (REGTMP << 16); 95759cc4ca5SDavid du Colombier o4 |= immrot(1); 95859cc4ca5SDavid du Colombier 95959cc4ca5SDavid du Colombier o5 = osrr(p->from.reg, REGTMP,r,p->scond); 96059cc4ca5SDavid du Colombier o5 |= (1<<22); 96159cc4ca5SDavid du Colombier 96259cc4ca5SDavid du Colombier o6 = oprrr(ASRL, p->scond); 96359cc4ca5SDavid du Colombier o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); 96459cc4ca5SDavid du Colombier o6 |= (1<<6); /* ROL 8 */ 96559cc4ca5SDavid du Colombier 9667dd7cddfSDavid du Colombier break; 9677dd7cddfSDavid du Colombier 9687dd7cddfSDavid du Colombier case 34: /* mov $lacon,R */ 96959cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 97059cc4ca5SDavid du Colombier if(!o1) 9717dd7cddfSDavid du Colombier break; 9727dd7cddfSDavid du Colombier 9737dd7cddfSDavid du Colombier o2 = oprrr(AADD, p->scond); 9747dd7cddfSDavid du Colombier o2 |= REGTMP; 97580ee5cbfSDavid du Colombier r = p->from.reg; 9767dd7cddfSDavid du Colombier if(r == NREG) 9777dd7cddfSDavid du Colombier r = o->param; 9787dd7cddfSDavid du Colombier o2 |= r << 16; 9797dd7cddfSDavid du Colombier if(p->to.type != D_NONE) 9807dd7cddfSDavid du Colombier o2 |= p->to.reg << 12; 9817dd7cddfSDavid du Colombier break; 9827dd7cddfSDavid du Colombier 9837dd7cddfSDavid du Colombier case 35: /* mov PSR,R */ 9847dd7cddfSDavid du Colombier o1 = (2<<23) | (0xf<<16) | (0<<0); 9857dd7cddfSDavid du Colombier o1 |= (p->scond & C_SCOND) << 28; 9867dd7cddfSDavid du Colombier o1 |= (p->from.reg & 1) << 22; 9877dd7cddfSDavid du Colombier o1 |= p->to.reg << 12; 9887dd7cddfSDavid du Colombier break; 9897dd7cddfSDavid du Colombier 9907dd7cddfSDavid du Colombier case 36: /* mov R,PSR */ 9917dd7cddfSDavid du Colombier o1 = (2<<23) | (0x29f<<12) | (0<<4); 9927dd7cddfSDavid du Colombier if(p->scond & C_FBIT) 9937dd7cddfSDavid du Colombier o1 ^= 0x010 << 12; 9947dd7cddfSDavid du Colombier o1 |= (p->scond & C_SCOND) << 28; 9957dd7cddfSDavid du Colombier o1 |= (p->to.reg & 1) << 22; 9967dd7cddfSDavid du Colombier o1 |= p->from.reg << 0; 9977dd7cddfSDavid du Colombier break; 9987dd7cddfSDavid du Colombier 9997dd7cddfSDavid du Colombier case 37: /* mov $con,PSR */ 10007dd7cddfSDavid du Colombier aclass(&p->from); 10017dd7cddfSDavid du Colombier o1 = (2<<23) | (0x29f<<12) | (0<<4); 10027dd7cddfSDavid du Colombier if(p->scond & C_FBIT) 10037dd7cddfSDavid du Colombier o1 ^= 0x010 << 12; 10047dd7cddfSDavid du Colombier o1 |= (p->scond & C_SCOND) << 28; 10057dd7cddfSDavid du Colombier o1 |= immrot(instoffset); 10067dd7cddfSDavid du Colombier o1 |= (p->to.reg & 1) << 22; 10077dd7cddfSDavid du Colombier o1 |= p->from.reg << 0; 10087dd7cddfSDavid du Colombier break; 10097dd7cddfSDavid du Colombier 10107dd7cddfSDavid du Colombier case 38: /* movm $con,oreg -> stm */ 10117dd7cddfSDavid du Colombier o1 = (0x4 << 25); 10127dd7cddfSDavid du Colombier o1 |= p->from.offset & 0xffff; 10137dd7cddfSDavid du Colombier o1 |= p->to.reg << 16; 10147dd7cddfSDavid du Colombier aclass(&p->to); 10157dd7cddfSDavid du Colombier goto movm; 10167dd7cddfSDavid du Colombier 10177dd7cddfSDavid du Colombier case 39: /* movm oreg,$con -> ldm */ 10187dd7cddfSDavid du Colombier o1 = (0x4 << 25) | (1 << 20); 10197dd7cddfSDavid du Colombier o1 |= p->to.offset & 0xffff; 10207dd7cddfSDavid du Colombier o1 |= p->from.reg << 16; 10217dd7cddfSDavid du Colombier aclass(&p->from); 10227dd7cddfSDavid du Colombier movm: 10237dd7cddfSDavid du Colombier if(instoffset != 0) 10247dd7cddfSDavid du Colombier diag("offset must be zero in MOVM"); 10257dd7cddfSDavid du Colombier o1 |= (p->scond & C_SCOND) << 28; 10267dd7cddfSDavid du Colombier if(p->scond & C_PBIT) 10277dd7cddfSDavid du Colombier o1 |= 1 << 24; 10287dd7cddfSDavid du Colombier if(p->scond & C_UBIT) 10297dd7cddfSDavid du Colombier o1 |= 1 << 23; 10307dd7cddfSDavid du Colombier if(p->scond & C_SBIT) 10317dd7cddfSDavid du Colombier o1 |= 1 << 22; 10327dd7cddfSDavid du Colombier if(p->scond & C_WBIT) 10337dd7cddfSDavid du Colombier o1 |= 1 << 21; 10347dd7cddfSDavid du Colombier break; 10357dd7cddfSDavid du Colombier 10367dd7cddfSDavid du Colombier case 40: /* swp oreg,reg,reg */ 10377dd7cddfSDavid du Colombier aclass(&p->from); 10387dd7cddfSDavid du Colombier if(instoffset != 0) 10397dd7cddfSDavid du Colombier diag("offset must be zero in SWP"); 10407dd7cddfSDavid du Colombier o1 = (0x2<<23) | (0x9<<4); 10417dd7cddfSDavid du Colombier if(p->as != ASWPW) 10427dd7cddfSDavid du Colombier o1 |= 1 << 22; 10437dd7cddfSDavid du Colombier o1 |= p->from.reg << 16; 10447dd7cddfSDavid du Colombier o1 |= p->reg << 0; 10457dd7cddfSDavid du Colombier o1 |= p->to.reg << 12; 10467dd7cddfSDavid du Colombier o1 |= (p->scond & C_SCOND) << 28; 10477dd7cddfSDavid du Colombier break; 10487dd7cddfSDavid du Colombier 10497dd7cddfSDavid du Colombier case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */ 10507dd7cddfSDavid du Colombier o1 = 0xe8fd8000; 10517dd7cddfSDavid du Colombier break; 10527dd7cddfSDavid du Colombier 10537dd7cddfSDavid du Colombier case 50: /* floating point store */ 10547dd7cddfSDavid du Colombier v = regoff(&p->to); 10557dd7cddfSDavid du Colombier r = p->to.reg; 10567dd7cddfSDavid du Colombier if(r == NREG) 10577dd7cddfSDavid du Colombier r = o->param; 105859cc4ca5SDavid du Colombier o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p); 10597dd7cddfSDavid du Colombier break; 10607dd7cddfSDavid du Colombier 10617dd7cddfSDavid du Colombier case 51: /* floating point load */ 10627dd7cddfSDavid du Colombier v = regoff(&p->from); 10637dd7cddfSDavid du Colombier r = p->from.reg; 10647dd7cddfSDavid du Colombier if(r == NREG) 10657dd7cddfSDavid du Colombier r = o->param; 106659cc4ca5SDavid du Colombier o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20); 10677dd7cddfSDavid du Colombier break; 10687dd7cddfSDavid du Colombier 10697dd7cddfSDavid du Colombier case 52: /* floating point store, long offset UGLY */ 107059cc4ca5SDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 107159cc4ca5SDavid du Colombier if(!o1) 10727dd7cddfSDavid du Colombier break; 10737dd7cddfSDavid du Colombier r = p->to.reg; 10747dd7cddfSDavid du Colombier if(r == NREG) 10757dd7cddfSDavid du Colombier r = o->param; 10767dd7cddfSDavid du Colombier o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; 107759cc4ca5SDavid du Colombier o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); 10787dd7cddfSDavid du Colombier break; 10797dd7cddfSDavid du Colombier 10807dd7cddfSDavid du Colombier case 53: /* floating point load, long offset UGLY */ 108159cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 108259cc4ca5SDavid du Colombier if(!o1) 10837dd7cddfSDavid du Colombier break; 10847dd7cddfSDavid du Colombier r = p->from.reg; 10857dd7cddfSDavid du Colombier if(r == NREG) 10867dd7cddfSDavid du Colombier r = o->param; 10877dd7cddfSDavid du Colombier o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; 108859cc4ca5SDavid du Colombier o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); 10897dd7cddfSDavid du Colombier break; 10907dd7cddfSDavid du Colombier 10917dd7cddfSDavid du Colombier case 54: /* floating point arith */ 10927dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 10937dd7cddfSDavid du Colombier if(p->from.type == D_FCONST) { 10947dd7cddfSDavid du Colombier rf = chipfloat(p->from.ieee); 10957dd7cddfSDavid du Colombier if(rf < 0){ 10967dd7cddfSDavid du Colombier diag("invalid floating-point immediate\n%P", p); 10977dd7cddfSDavid du Colombier rf = 0; 10987dd7cddfSDavid du Colombier } 10997dd7cddfSDavid du Colombier rf |= (1<<3); 11007dd7cddfSDavid du Colombier } else 11017dd7cddfSDavid du Colombier rf = p->from.reg; 11027dd7cddfSDavid du Colombier rt = p->to.reg; 11037dd7cddfSDavid du Colombier r = p->reg; 11047dd7cddfSDavid du Colombier if(p->to.type == D_NONE) 11057dd7cddfSDavid du Colombier rt = 0; /* CMP[FD] */ 11067dd7cddfSDavid du Colombier else if(o1 & (1<<15)) 11077dd7cddfSDavid du Colombier r = 0; /* monadic */ 11087dd7cddfSDavid du Colombier else if(r == NREG) 11097dd7cddfSDavid du Colombier r = rt; 11107dd7cddfSDavid du Colombier o1 |= rf | (r<<16) | (rt<<12); 11117dd7cddfSDavid du Colombier break; 11127dd7cddfSDavid du Colombier 11137dd7cddfSDavid du Colombier case 55: /* floating point fix and float */ 11147dd7cddfSDavid du Colombier o1 = oprrr(p->as, p->scond); 11157dd7cddfSDavid du Colombier rf = p->from.reg; 11167dd7cddfSDavid du Colombier rt = p->to.reg; 11177dd7cddfSDavid du Colombier if(p->to.type == D_NONE){ 11187dd7cddfSDavid du Colombier rt = 0; 11197dd7cddfSDavid du Colombier diag("to.type==D_NONE (asm/fp)"); 11207dd7cddfSDavid du Colombier } 11217dd7cddfSDavid du Colombier if(p->from.type == D_REG) 11227dd7cddfSDavid du Colombier o1 |= (rf<<12) | (rt<<16); 11237dd7cddfSDavid du Colombier else 11247dd7cddfSDavid du Colombier o1 |= rf | (rt<<12); 11257dd7cddfSDavid du Colombier break; 11267dd7cddfSDavid du Colombier 11277dd7cddfSDavid du Colombier case 56: /* move to FP[CS]R */ 11287dd7cddfSDavid du Colombier o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); 11297dd7cddfSDavid du Colombier o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); 11307dd7cddfSDavid du Colombier break; 11317dd7cddfSDavid du Colombier 11327dd7cddfSDavid du Colombier case 57: /* move from FP[CS]R */ 11337dd7cddfSDavid du Colombier o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); 11347dd7cddfSDavid du Colombier o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); 11357dd7cddfSDavid du Colombier break; 113659cc4ca5SDavid du Colombier case 58: /* movbu R,R */ 11377dd7cddfSDavid du Colombier o1 = oprrr(AAND, p->scond); 11387dd7cddfSDavid du Colombier o1 |= immrot(0xff); 11397dd7cddfSDavid du Colombier rt = p->to.reg; 11407dd7cddfSDavid du Colombier r = p->from.reg; 11417dd7cddfSDavid du Colombier if(p->to.type == D_NONE) 11427dd7cddfSDavid du Colombier rt = 0; 11437dd7cddfSDavid du Colombier if(r == NREG) 11447dd7cddfSDavid du Colombier r = rt; 11457dd7cddfSDavid du Colombier o1 |= (r<<16) | (rt<<12); 11467dd7cddfSDavid du Colombier break; 114759cc4ca5SDavid du Colombier 114859cc4ca5SDavid du Colombier case 59: /* movw/bu R<<I(R),R -> ldr indexed */ 114959cc4ca5SDavid du Colombier if(p->from.reg == NREG) { 115059cc4ca5SDavid du Colombier if(p->as != AMOVW) 115159cc4ca5SDavid du Colombier diag("byte MOV from shifter operand"); 115259cc4ca5SDavid du Colombier goto mov; 115359cc4ca5SDavid du Colombier } 115459cc4ca5SDavid du Colombier if(p->from.offset&(1<<4)) 115559cc4ca5SDavid du Colombier diag("bad shift in LDR"); 115659cc4ca5SDavid du Colombier o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond); 115759cc4ca5SDavid du Colombier if(p->as == AMOVBU) 115859cc4ca5SDavid du Colombier o1 |= 1<<22; 115959cc4ca5SDavid du Colombier break; 116059cc4ca5SDavid du Colombier 116159cc4ca5SDavid du Colombier case 60: /* movb R(R),R -> ldrsb indexed */ 116259cc4ca5SDavid du Colombier if(p->from.reg == NREG) { 116359cc4ca5SDavid du Colombier diag("byte MOV from shifter operand"); 116459cc4ca5SDavid du Colombier goto mov; 116559cc4ca5SDavid du Colombier } 116659cc4ca5SDavid du Colombier if(p->from.offset&(~0xf)) 116759cc4ca5SDavid du Colombier diag("bad shift in LDRSB"); 116859cc4ca5SDavid du Colombier o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond); 116959cc4ca5SDavid du Colombier o1 ^= (1<<5)|(1<<6); 117059cc4ca5SDavid du Colombier break; 117159cc4ca5SDavid du Colombier 117259cc4ca5SDavid du Colombier case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ 117359cc4ca5SDavid du Colombier if(p->to.reg == NREG) 117459cc4ca5SDavid du Colombier diag("MOV to shifter operand"); 117559cc4ca5SDavid du Colombier o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond); 117659cc4ca5SDavid du Colombier if(p->as == AMOVB || p->as == AMOVBU) 117759cc4ca5SDavid du Colombier o1 |= 1<<22; 117859cc4ca5SDavid du Colombier break; 117959cc4ca5SDavid du Colombier 118059cc4ca5SDavid du Colombier case 62: /* case R -> movw R<<2(PC),PC */ 118159cc4ca5SDavid du Colombier o1 = olrr(p->from.reg, REGPC, REGPC, p->scond); 118259cc4ca5SDavid du Colombier o1 |= 2<<7; 118359cc4ca5SDavid du Colombier break; 118459cc4ca5SDavid du Colombier 118559cc4ca5SDavid du Colombier case 63: /* bcase */ 11869a747e4fSDavid du Colombier if(p->cond != P) { 118759cc4ca5SDavid du Colombier o1 = p->cond->pc; 1188375daca8SDavid du Colombier if(dlm) 1189375daca8SDavid du Colombier dynreloc(S, p->pc, 1); 11909a747e4fSDavid du Colombier } 11919a747e4fSDavid du Colombier break; 11929a747e4fSDavid du Colombier 11939a747e4fSDavid du Colombier /* reloc ops */ 11949a747e4fSDavid du Colombier case 64: /* mov/movb/movbu R,addr */ 11959a747e4fSDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 11969a747e4fSDavid du Colombier if(!o1) 11979a747e4fSDavid du Colombier break; 11989a747e4fSDavid du Colombier o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 11999a747e4fSDavid du Colombier break; 12009a747e4fSDavid du Colombier 12019a747e4fSDavid du Colombier case 65: /* mov/movbu addr,R */ 12029a747e4fSDavid du Colombier case 66: /* movh/movhu/movb addr,R */ 12039a747e4fSDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 12049a747e4fSDavid du Colombier if(!o1) 12059a747e4fSDavid du Colombier break; 12069a747e4fSDavid du Colombier o2 = olr(0, REGTMP, p->to.reg, p->scond); 12079a747e4fSDavid du Colombier if(p->as == AMOVBU || p->as == AMOVB) 12089a747e4fSDavid du Colombier o2 |= 1<<22; 12099a747e4fSDavid du Colombier if(o->type == 65) 12109a747e4fSDavid du Colombier break; 12119a747e4fSDavid du Colombier 12129a747e4fSDavid du Colombier o3 = oprrr(ASLL, p->scond); 12139a747e4fSDavid du Colombier 12149a747e4fSDavid du Colombier if(p->as == AMOVBU || p->as == AMOVHU) 12159a747e4fSDavid du Colombier o4 = oprrr(ASRL, p->scond); 12169a747e4fSDavid du Colombier else 12179a747e4fSDavid du Colombier o4 = oprrr(ASRA, p->scond); 12189a747e4fSDavid du Colombier 12199a747e4fSDavid du Colombier r = p->to.reg; 12209a747e4fSDavid du Colombier o3 |= (r)|(r<<12); 12219a747e4fSDavid du Colombier o4 |= (r)|(r<<12); 12229a747e4fSDavid du Colombier if(p->as == AMOVB || p->as == AMOVBU) { 12239a747e4fSDavid du Colombier o3 |= (24<<7); 12249a747e4fSDavid du Colombier o4 |= (24<<7); 12259a747e4fSDavid du Colombier } else { 12269a747e4fSDavid du Colombier o3 |= (16<<7); 12279a747e4fSDavid du Colombier o4 |= (16<<7); 12289a747e4fSDavid du Colombier } 12299a747e4fSDavid du Colombier break; 12309a747e4fSDavid du Colombier 12319a747e4fSDavid du Colombier case 67: /* movh/movhu R,addr -> sb, sb */ 12329a747e4fSDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 12339a747e4fSDavid du Colombier if(!o1) 12349a747e4fSDavid du Colombier break; 12359a747e4fSDavid du Colombier o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 12369a747e4fSDavid du Colombier 12379a747e4fSDavid du Colombier o3 = oprrr(ASRL, p->scond); 12389a747e4fSDavid du Colombier o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); 12399a747e4fSDavid du Colombier o3 |= (1<<6); /* ROR 8 */ 12409a747e4fSDavid du Colombier 12419a747e4fSDavid du Colombier o4 = oprrr(AADD, p->scond); 12429a747e4fSDavid du Colombier o4 |= (REGTMP << 12) | (REGTMP << 16); 12439a747e4fSDavid du Colombier o4 |= immrot(1); 12449a747e4fSDavid du Colombier 12459a747e4fSDavid du Colombier o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 12469a747e4fSDavid du Colombier 12479a747e4fSDavid du Colombier o6 = oprrr(ASRL, p->scond); 12489a747e4fSDavid du Colombier o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); 12499a747e4fSDavid du Colombier o6 |= (1<<6); /* ROL 8 */ 12509a747e4fSDavid du Colombier break; 12519a747e4fSDavid du Colombier 12529a747e4fSDavid du Colombier case 68: /* floating point store -> ADDR */ 12539a747e4fSDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 12549a747e4fSDavid du Colombier if(!o1) 12559a747e4fSDavid du Colombier break; 12569a747e4fSDavid du Colombier o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); 12579a747e4fSDavid du Colombier break; 12589a747e4fSDavid du Colombier 12599a747e4fSDavid du Colombier case 69: /* floating point load <- ADDR */ 12609a747e4fSDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 12619a747e4fSDavid du Colombier if(!o1) 12629a747e4fSDavid du Colombier break; 12639a747e4fSDavid du Colombier o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); 126459cc4ca5SDavid du Colombier break; 126559cc4ca5SDavid du Colombier 126659cc4ca5SDavid du Colombier /* ArmV4 ops: */ 126759cc4ca5SDavid du Colombier case 70: /* movh/movhu R,O(R) -> strh */ 126859cc4ca5SDavid du Colombier aclass(&p->to); 126959cc4ca5SDavid du Colombier r = p->to.reg; 127059cc4ca5SDavid du Colombier if(r == NREG) 127159cc4ca5SDavid du Colombier r = o->param; 127259cc4ca5SDavid du Colombier o1 = oshr(p->from.reg, instoffset, r, p->scond); 127359cc4ca5SDavid du Colombier break; 127459cc4ca5SDavid du Colombier case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ 127559cc4ca5SDavid du Colombier aclass(&p->from); 127659cc4ca5SDavid du Colombier r = p->from.reg; 127759cc4ca5SDavid du Colombier if(r == NREG) 127859cc4ca5SDavid du Colombier r = o->param; 127959cc4ca5SDavid du Colombier o1 = olhr(instoffset, r, p->to.reg, p->scond); 128059cc4ca5SDavid du Colombier if(p->as == AMOVB) 128159cc4ca5SDavid du Colombier o1 ^= (1<<5)|(1<<6); 128259cc4ca5SDavid du Colombier else if(p->as == AMOVH) 128359cc4ca5SDavid du Colombier o1 ^= (1<<6); 128459cc4ca5SDavid du Colombier break; 128559cc4ca5SDavid du Colombier case 72: /* movh/movhu R,L(R) -> strh */ 128659cc4ca5SDavid du Colombier o1 = omvl(p, &p->to, REGTMP); 128759cc4ca5SDavid du Colombier if(!o1) 128859cc4ca5SDavid du Colombier break; 128959cc4ca5SDavid du Colombier r = p->to.reg; 129059cc4ca5SDavid du Colombier if(r == NREG) 129159cc4ca5SDavid du Colombier r = o->param; 129259cc4ca5SDavid du Colombier o2 = oshrr(p->from.reg, REGTMP,r, p->scond); 129359cc4ca5SDavid du Colombier break; 129459cc4ca5SDavid du Colombier case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ 129559cc4ca5SDavid du Colombier o1 = omvl(p, &p->from, REGTMP); 129659cc4ca5SDavid du Colombier if(!o1) 129759cc4ca5SDavid du Colombier break; 129859cc4ca5SDavid du Colombier r = p->from.reg; 129959cc4ca5SDavid du Colombier if(r == NREG) 130059cc4ca5SDavid du Colombier r = o->param; 130159cc4ca5SDavid du Colombier o2 = olhrr(REGTMP, r, p->to.reg, p->scond); 130259cc4ca5SDavid du Colombier if(p->as == AMOVB) 130359cc4ca5SDavid du Colombier o2 ^= (1<<5)|(1<<6); 130459cc4ca5SDavid du Colombier else if(p->as == AMOVH) 130559cc4ca5SDavid du Colombier o2 ^= (1<<6); 130659cc4ca5SDavid du Colombier break; 13077dd7cddfSDavid du Colombier } 13087dd7cddfSDavid du Colombier 13099a747e4fSDavid du Colombier if(debug['a'] > 1) 13109a747e4fSDavid du Colombier Bprint(&bso, "%2d ", o->type); 13119a747e4fSDavid du Colombier 13127dd7cddfSDavid du Colombier v = p->pc; 13137dd7cddfSDavid du Colombier switch(o->size) { 13147dd7cddfSDavid du Colombier default: 13157dd7cddfSDavid du Colombier if(debug['a']) 13167dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux:\t\t%P\n", v, p); 13177dd7cddfSDavid du Colombier break; 13187dd7cddfSDavid du Colombier case 4: 13197dd7cddfSDavid du Colombier if(debug['a']) 13207dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); 13217dd7cddfSDavid du Colombier lputl(o1); 13227dd7cddfSDavid du Colombier break; 13237dd7cddfSDavid du Colombier case 8: 13247dd7cddfSDavid du Colombier if(debug['a']) 13257dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); 13267dd7cddfSDavid du Colombier lputl(o1); 13277dd7cddfSDavid du Colombier lputl(o2); 13287dd7cddfSDavid du Colombier break; 13297dd7cddfSDavid du Colombier case 12: 13307dd7cddfSDavid du Colombier if(debug['a']) 13317dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); 13327dd7cddfSDavid du Colombier lputl(o1); 13337dd7cddfSDavid du Colombier lputl(o2); 13347dd7cddfSDavid du Colombier lputl(o3); 13357dd7cddfSDavid du Colombier break; 13367dd7cddfSDavid du Colombier case 16: 13377dd7cddfSDavid du Colombier if(debug['a']) 13387dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", 13397dd7cddfSDavid du Colombier v, o1, o2, o3, o4, p); 13407dd7cddfSDavid du Colombier lputl(o1); 13417dd7cddfSDavid du Colombier lputl(o2); 13427dd7cddfSDavid du Colombier lputl(o3); 13437dd7cddfSDavid du Colombier lputl(o4); 13447dd7cddfSDavid du Colombier break; 13457dd7cddfSDavid du Colombier case 20: 13467dd7cddfSDavid du Colombier if(debug['a']) 13477dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 13487dd7cddfSDavid du Colombier v, o1, o2, o3, o4, o5, p); 13497dd7cddfSDavid du Colombier lputl(o1); 13507dd7cddfSDavid du Colombier lputl(o2); 13517dd7cddfSDavid du Colombier lputl(o3); 13527dd7cddfSDavid du Colombier lputl(o4); 13537dd7cddfSDavid du Colombier lputl(o5); 13547dd7cddfSDavid du Colombier break; 135559cc4ca5SDavid du Colombier case 24: 135659cc4ca5SDavid du Colombier if(debug['a']) 135759cc4ca5SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 135859cc4ca5SDavid du Colombier v, o1, o2, o3, o4, o5, o6, p); 135959cc4ca5SDavid du Colombier lputl(o1); 136059cc4ca5SDavid du Colombier lputl(o2); 136159cc4ca5SDavid du Colombier lputl(o3); 136259cc4ca5SDavid du Colombier lputl(o4); 136359cc4ca5SDavid du Colombier lputl(o5); 136459cc4ca5SDavid du Colombier lputl(o6); 136559cc4ca5SDavid du Colombier break; 13667dd7cddfSDavid du Colombier } 13677dd7cddfSDavid du Colombier } 13687dd7cddfSDavid du Colombier 13697dd7cddfSDavid du Colombier long 13707dd7cddfSDavid du Colombier oprrr(int a, int sc) 13717dd7cddfSDavid du Colombier { 13727dd7cddfSDavid du Colombier long o; 13737dd7cddfSDavid du Colombier 13747dd7cddfSDavid du Colombier o = (sc & C_SCOND) << 28; 13757dd7cddfSDavid du Colombier if(sc & C_SBIT) 13767dd7cddfSDavid du Colombier o |= 1 << 20; 13777dd7cddfSDavid du Colombier if(sc & (C_PBIT|C_WBIT)) 13787dd7cddfSDavid du Colombier diag(".P/.W on dp instruction"); 13797dd7cddfSDavid du Colombier switch(a) { 13807dd7cddfSDavid du Colombier case AMULU: 13817dd7cddfSDavid du Colombier case AMUL: return o | (0x0<<21) | (0x9<<4); 138259cc4ca5SDavid du Colombier case AMULA: return o | (0x1<<21) | (0x9<<4); 138359cc4ca5SDavid du Colombier case AMULLU: return o | (0x4<<21) | (0x9<<4); 138459cc4ca5SDavid du Colombier case AMULL: return o | (0x6<<21) | (0x9<<4); 138559cc4ca5SDavid du Colombier case AMULALU: return o | (0x5<<21) | (0x9<<4); 138659cc4ca5SDavid du Colombier case AMULAL: return o | (0x7<<21) | (0x9<<4); 13877dd7cddfSDavid du Colombier case AAND: return o | (0x0<<21); 13887dd7cddfSDavid du Colombier case AEOR: return o | (0x1<<21); 13897dd7cddfSDavid du Colombier case ASUB: return o | (0x2<<21); 13907dd7cddfSDavid du Colombier case ARSB: return o | (0x3<<21); 13917dd7cddfSDavid du Colombier case AADD: return o | (0x4<<21); 13927dd7cddfSDavid du Colombier case AADC: return o | (0x5<<21); 13937dd7cddfSDavid du Colombier case ASBC: return o | (0x6<<21); 13947dd7cddfSDavid du Colombier case ARSC: return o | (0x7<<21); 13957dd7cddfSDavid du Colombier case ATST: return o | (0x8<<21) | (1<<20); 13967dd7cddfSDavid du Colombier case ATEQ: return o | (0x9<<21) | (1<<20); 13977dd7cddfSDavid du Colombier case ACMP: return o | (0xa<<21) | (1<<20); 139859cc4ca5SDavid du Colombier case ACMN: return o | (0xb<<21) | (1<<20); 13997dd7cddfSDavid du Colombier case AORR: return o | (0xc<<21); 14007dd7cddfSDavid du Colombier case AMOVW: return o | (0xd<<21); 14017dd7cddfSDavid du Colombier case ABIC: return o | (0xe<<21); 14027dd7cddfSDavid du Colombier case AMVN: return o | (0xf<<21); 14037dd7cddfSDavid du Colombier case ASLL: return o | (0xd<<21) | (0<<5); 14047dd7cddfSDavid du Colombier case ASRL: return o | (0xd<<21) | (1<<5); 14057dd7cddfSDavid du Colombier case ASRA: return o | (0xd<<21) | (2<<5); 14067dd7cddfSDavid du Colombier case ASWI: return o | (0xf<<24); 14077dd7cddfSDavid du Colombier 14087dd7cddfSDavid du Colombier case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7); 14097dd7cddfSDavid du Colombier case AADDF: return o | (0xe<<24) | (0x0<<20) | (1<<8); 14107dd7cddfSDavid du Colombier case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7); 14117dd7cddfSDavid du Colombier case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8); 14127dd7cddfSDavid du Colombier case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7); 14137dd7cddfSDavid du Colombier case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); 14147dd7cddfSDavid du Colombier case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); 14157dd7cddfSDavid du Colombier case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); 14167dd7cddfSDavid du Colombier case ACMPD: 14177dd7cddfSDavid du Colombier case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */ 14187dd7cddfSDavid du Colombier 14197dd7cddfSDavid du Colombier case AMOVF: 14207dd7cddfSDavid du Colombier case AMOVDF: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8); 14217dd7cddfSDavid du Colombier case AMOVD: 14227dd7cddfSDavid du Colombier case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); 14237dd7cddfSDavid du Colombier 14247dd7cddfSDavid du Colombier case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4); 14257dd7cddfSDavid du Colombier case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7); 14267dd7cddfSDavid du Colombier case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4); 14277dd7cddfSDavid du Colombier case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7); 14287dd7cddfSDavid du Colombier } 14297dd7cddfSDavid du Colombier diag("bad rrr %d", a); 14307dd7cddfSDavid du Colombier prasm(curp); 14317dd7cddfSDavid du Colombier return 0; 14327dd7cddfSDavid du Colombier } 14337dd7cddfSDavid du Colombier 14347dd7cddfSDavid du Colombier long 14357dd7cddfSDavid du Colombier opbra(int a, int sc) 14367dd7cddfSDavid du Colombier { 14377dd7cddfSDavid du Colombier 14387dd7cddfSDavid du Colombier if(sc & (C_SBIT|C_PBIT|C_WBIT)) 14397dd7cddfSDavid du Colombier diag(".S/.P/.W on bra instruction"); 14407dd7cddfSDavid du Colombier sc &= C_SCOND; 14417dd7cddfSDavid du Colombier if(a == ABL) 14427dd7cddfSDavid du Colombier return (sc<<28)|(0x5<<25)|(0x1<<24); 14437dd7cddfSDavid du Colombier if(sc != 0xe) 14447dd7cddfSDavid du Colombier diag(".COND on bcond instruction"); 14457dd7cddfSDavid du Colombier switch(a) { 14467dd7cddfSDavid du Colombier case ABEQ: return (0x0<<28)|(0x5<<25); 14477dd7cddfSDavid du Colombier case ABNE: return (0x1<<28)|(0x5<<25); 14487dd7cddfSDavid du Colombier case ABCS: return (0x2<<28)|(0x5<<25); 14497dd7cddfSDavid du Colombier case ABHS: return (0x2<<28)|(0x5<<25); 14507dd7cddfSDavid du Colombier case ABCC: return (0x3<<28)|(0x5<<25); 14517dd7cddfSDavid du Colombier case ABLO: return (0x3<<28)|(0x5<<25); 14527dd7cddfSDavid du Colombier case ABMI: return (0x4<<28)|(0x5<<25); 14537dd7cddfSDavid du Colombier case ABPL: return (0x5<<28)|(0x5<<25); 14547dd7cddfSDavid du Colombier case ABVS: return (0x6<<28)|(0x5<<25); 14557dd7cddfSDavid du Colombier case ABVC: return (0x7<<28)|(0x5<<25); 14567dd7cddfSDavid du Colombier case ABHI: return (0x8<<28)|(0x5<<25); 14577dd7cddfSDavid du Colombier case ABLS: return (0x9<<28)|(0x5<<25); 14587dd7cddfSDavid du Colombier case ABGE: return (0xa<<28)|(0x5<<25); 14597dd7cddfSDavid du Colombier case ABLT: return (0xb<<28)|(0x5<<25); 14607dd7cddfSDavid du Colombier case ABGT: return (0xc<<28)|(0x5<<25); 14617dd7cddfSDavid du Colombier case ABLE: return (0xd<<28)|(0x5<<25); 14627dd7cddfSDavid du Colombier case AB: return (0xe<<28)|(0x5<<25); 14637dd7cddfSDavid du Colombier } 14647dd7cddfSDavid du Colombier diag("bad bra %A", a); 14657dd7cddfSDavid du Colombier prasm(curp); 14667dd7cddfSDavid du Colombier return 0; 14677dd7cddfSDavid du Colombier } 14687dd7cddfSDavid du Colombier 14697dd7cddfSDavid du Colombier long 14707dd7cddfSDavid du Colombier olr(long v, int b, int r, int sc) 14717dd7cddfSDavid du Colombier { 14727dd7cddfSDavid du Colombier long o; 14737dd7cddfSDavid du Colombier 14747dd7cddfSDavid du Colombier if(sc & C_SBIT) 14757dd7cddfSDavid du Colombier diag(".S on LDR/STR instruction"); 14767dd7cddfSDavid du Colombier o = (sc & C_SCOND) << 28; 14777dd7cddfSDavid du Colombier if(!(sc & C_PBIT)) 14787dd7cddfSDavid du Colombier o |= 1 << 24; 147959cc4ca5SDavid du Colombier if(!(sc & C_UBIT)) 148059cc4ca5SDavid du Colombier o |= 1 << 23; 14817dd7cddfSDavid du Colombier if(sc & C_WBIT) 14827dd7cddfSDavid du Colombier o |= 1 << 21; 148359cc4ca5SDavid du Colombier o |= (0x1<<26) | (1<<20); 14847dd7cddfSDavid du Colombier if(v < 0) { 14857dd7cddfSDavid du Colombier v = -v; 14867dd7cddfSDavid du Colombier o ^= 1 << 23; 14877dd7cddfSDavid du Colombier } 14887dd7cddfSDavid du Colombier if(v >= (1<<12)) 1489406758d9SDavid du Colombier diag("literal span too large: %ld (R%d)\n%P", v, b, PP); 14907dd7cddfSDavid du Colombier o |= v; 14917dd7cddfSDavid du Colombier o |= b << 16; 14927dd7cddfSDavid du Colombier o |= r << 12; 14937dd7cddfSDavid du Colombier return o; 14947dd7cddfSDavid du Colombier } 14957dd7cddfSDavid du Colombier 14967dd7cddfSDavid du Colombier long 149759cc4ca5SDavid du Colombier olhr(long v, int b, int r, int sc) 149859cc4ca5SDavid du Colombier { 149959cc4ca5SDavid du Colombier long o; 150059cc4ca5SDavid du Colombier 150159cc4ca5SDavid du Colombier if(sc & C_SBIT) 150259cc4ca5SDavid du Colombier diag(".S on LDRH/STRH instruction"); 150359cc4ca5SDavid du Colombier o = (sc & C_SCOND) << 28; 150459cc4ca5SDavid du Colombier if(!(sc & C_PBIT)) 150559cc4ca5SDavid du Colombier o |= 1 << 24; 150659cc4ca5SDavid du Colombier if(sc & C_WBIT) 150759cc4ca5SDavid du Colombier o |= 1 << 21; 150859cc4ca5SDavid du Colombier o |= (1<<23) | (1<<20)|(0xb<<4); 150959cc4ca5SDavid du Colombier if(v < 0) { 151059cc4ca5SDavid du Colombier v = -v; 151159cc4ca5SDavid du Colombier o ^= 1 << 23; 151259cc4ca5SDavid du Colombier } 151359cc4ca5SDavid du Colombier if(v >= (1<<8)) 1514406758d9SDavid du Colombier diag("literal span too large: %ld (R%d)\n%P", v, b, PP); 151559cc4ca5SDavid du Colombier o |= (v&0xf)|((v>>4)<<8)|(1<<22); 151659cc4ca5SDavid du Colombier o |= b << 16; 151759cc4ca5SDavid du Colombier o |= r << 12; 151859cc4ca5SDavid du Colombier return o; 151959cc4ca5SDavid du Colombier } 152059cc4ca5SDavid du Colombier 152159cc4ca5SDavid du Colombier long 15227dd7cddfSDavid du Colombier osr(int a, int r, long v, int b, int sc) 15237dd7cddfSDavid du Colombier { 15247dd7cddfSDavid du Colombier long o; 15257dd7cddfSDavid du Colombier 15267dd7cddfSDavid du Colombier o = olr(v, b, r, sc) ^ (1<<20); 15277dd7cddfSDavid du Colombier if(a != AMOVW) 15287dd7cddfSDavid du Colombier o |= 1<<22; 15297dd7cddfSDavid du Colombier return o; 15307dd7cddfSDavid du Colombier } 15317dd7cddfSDavid du Colombier 15327dd7cddfSDavid du Colombier long 153359cc4ca5SDavid du Colombier oshr(int r, long v, int b, int sc) 153459cc4ca5SDavid du Colombier { 153559cc4ca5SDavid du Colombier long o; 153659cc4ca5SDavid du Colombier 153759cc4ca5SDavid du Colombier o = olhr(v, b, r, sc) ^ (1<<20); 153859cc4ca5SDavid du Colombier return o; 153959cc4ca5SDavid du Colombier } 154059cc4ca5SDavid du Colombier 154159cc4ca5SDavid du Colombier 154259cc4ca5SDavid du Colombier long 15437dd7cddfSDavid du Colombier osrr(int r, int i, int b, int sc) 15447dd7cddfSDavid du Colombier { 15457dd7cddfSDavid du Colombier 15467dd7cddfSDavid du Colombier return olr(i, b, r, sc) ^ ((1<<25) | (1<<20)); 15477dd7cddfSDavid du Colombier } 15487dd7cddfSDavid du Colombier 15497dd7cddfSDavid du Colombier long 15507dd7cddfSDavid du Colombier oshrr(int r, int i, int b, int sc) 15517dd7cddfSDavid du Colombier { 155259cc4ca5SDavid du Colombier return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20)); 15537dd7cddfSDavid du Colombier } 15547dd7cddfSDavid du Colombier 15557dd7cddfSDavid du Colombier long 15567dd7cddfSDavid du Colombier olrr(int i, int b, int r, int sc) 15577dd7cddfSDavid du Colombier { 15587dd7cddfSDavid du Colombier 15597dd7cddfSDavid du Colombier return olr(i, b, r, sc) ^ (1<<25); 15607dd7cddfSDavid du Colombier } 15617dd7cddfSDavid du Colombier 15627dd7cddfSDavid du Colombier long 156359cc4ca5SDavid du Colombier olhrr(int i, int b, int r, int sc) 156459cc4ca5SDavid du Colombier { 156559cc4ca5SDavid du Colombier return olhr(i, b, r, sc) ^ (1<<22); 156659cc4ca5SDavid du Colombier } 156759cc4ca5SDavid du Colombier 156859cc4ca5SDavid du Colombier long 156959cc4ca5SDavid du Colombier ofsr(int a, int r, long v, int b, int sc, Prog *p) 15707dd7cddfSDavid du Colombier { 15717dd7cddfSDavid du Colombier long o; 15727dd7cddfSDavid du Colombier 15737dd7cddfSDavid du Colombier if(sc & C_SBIT) 15747dd7cddfSDavid du Colombier diag(".S on FLDR/FSTR instruction"); 15757dd7cddfSDavid du Colombier o = (sc & C_SCOND) << 28; 15767dd7cddfSDavid du Colombier if(!(sc & C_PBIT)) 15777dd7cddfSDavid du Colombier o |= 1 << 24; 15787dd7cddfSDavid du Colombier if(sc & C_WBIT) 15797dd7cddfSDavid du Colombier o |= 1 << 21; 15807dd7cddfSDavid du Colombier o |= (6<<25) | (1<<24) | (1<<23); 15817dd7cddfSDavid du Colombier if(v < 0) { 15827dd7cddfSDavid du Colombier v = -v; 15837dd7cddfSDavid du Colombier o ^= 1 << 23; 15847dd7cddfSDavid du Colombier } 15857dd7cddfSDavid du Colombier if(v & 3) 1586406758d9SDavid du Colombier diag("odd offset for floating point op: %ld\n%P", v, p); 15877dd7cddfSDavid du Colombier else if(v >= (1<<10)) 1588406758d9SDavid du Colombier diag("literal span too large: %ld\n%P", v, p); 15897dd7cddfSDavid du Colombier o |= (v>>2) & 0xFF; 15907dd7cddfSDavid du Colombier o |= b << 16; 15917dd7cddfSDavid du Colombier o |= r << 12; 15927dd7cddfSDavid du Colombier o |= 1 << 8; 15937dd7cddfSDavid du Colombier 15947dd7cddfSDavid du Colombier switch(a) { 15957dd7cddfSDavid du Colombier default: 15967dd7cddfSDavid du Colombier diag("bad fst %A", a); 15977dd7cddfSDavid du Colombier case AMOVD: 15987dd7cddfSDavid du Colombier o |= 1<<15; 15997dd7cddfSDavid du Colombier case AMOVF: 16007dd7cddfSDavid du Colombier break; 16017dd7cddfSDavid du Colombier } 16027dd7cddfSDavid du Colombier return o; 16037dd7cddfSDavid du Colombier } 16047dd7cddfSDavid du Colombier 160559cc4ca5SDavid du Colombier long 160659cc4ca5SDavid du Colombier omvl(Prog *p, Adr *a, int dr) 160759cc4ca5SDavid du Colombier { 160859cc4ca5SDavid du Colombier long v, o1; 160959cc4ca5SDavid du Colombier if(!p->cond) { 161059cc4ca5SDavid du Colombier aclass(a); 161159cc4ca5SDavid du Colombier v = immrot(~instoffset); 161259cc4ca5SDavid du Colombier if(v == 0) { 161359cc4ca5SDavid du Colombier diag("missing literal"); 161459cc4ca5SDavid du Colombier prasm(p); 161559cc4ca5SDavid du Colombier return 0; 161659cc4ca5SDavid du Colombier } 161759cc4ca5SDavid du Colombier o1 = oprrr(AMVN, p->scond&C_SCOND); 161859cc4ca5SDavid du Colombier o1 |= v; 161959cc4ca5SDavid du Colombier o1 |= dr << 12; 162059cc4ca5SDavid du Colombier } else { 162159cc4ca5SDavid du Colombier v = p->cond->pc - p->pc - 8; 162259cc4ca5SDavid du Colombier o1 = olr(v, REGPC, dr, p->scond&C_SCOND); 162359cc4ca5SDavid du Colombier } 162459cc4ca5SDavid du Colombier return o1; 162559cc4ca5SDavid du Colombier } 162659cc4ca5SDavid du Colombier 16277dd7cddfSDavid du Colombier static Ieee chipfloats[] = { 16287dd7cddfSDavid du Colombier {0x00000000, 0x00000000}, /* 0 */ 16297dd7cddfSDavid du Colombier {0x00000000, 0x3ff00000}, /* 1 */ 16307dd7cddfSDavid du Colombier {0x00000000, 0x40000000}, /* 2 */ 16317dd7cddfSDavid du Colombier {0x00000000, 0x40080000}, /* 3 */ 16327dd7cddfSDavid du Colombier {0x00000000, 0x40100000}, /* 4 */ 16337dd7cddfSDavid du Colombier {0x00000000, 0x40140000}, /* 5 */ 16347dd7cddfSDavid du Colombier {0x00000000, 0x3fe00000}, /* .5 */ 16357dd7cddfSDavid du Colombier {0x00000000, 0x40240000}, /* 10 */ 16367dd7cddfSDavid du Colombier }; 16377dd7cddfSDavid du Colombier 16387dd7cddfSDavid du Colombier int 16397dd7cddfSDavid du Colombier chipfloat(Ieee *e) 16407dd7cddfSDavid du Colombier { 16417dd7cddfSDavid du Colombier Ieee *p; 16427dd7cddfSDavid du Colombier int n; 16437dd7cddfSDavid du Colombier 16447dd7cddfSDavid du Colombier for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){ 16457dd7cddfSDavid du Colombier p = &chipfloats[n]; 16467dd7cddfSDavid du Colombier if(p->l == e->l && p->h == e->h) 16477dd7cddfSDavid du Colombier return n; 16487dd7cddfSDavid du Colombier } 16497dd7cddfSDavid du Colombier return -1; 16507dd7cddfSDavid du Colombier } 1651