13e12c5d1SDavid du Colombier #include "l.h"
23e12c5d1SDavid du Colombier
33305c317SDavid du Colombier /* can't include a.out.h due to name clashes, but these are taken from it */
43305c317SDavid du Colombier #define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7))
53305c317SDavid du Colombier #define V_MAGIC _MAGIC(0, 16) /* mips 3000 BE */
63305c317SDavid du Colombier #define M_MAGIC _MAGIC(0, 18) /* mips 4000 BE */
73305c317SDavid du Colombier #define N_MAGIC _MAGIC(0, 22) /* mips 4000 LE */
83305c317SDavid du Colombier #define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */
93305c317SDavid du Colombier
10bd389b36SDavid du Colombier long OFFSET;
11bd389b36SDavid du Colombier /*
12bd389b36SDavid du Colombier long BADOFFSET = -1;
13bd389b36SDavid du Colombier
14bd389b36SDavid du Colombier if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\
15bd389b36SDavid du Colombier abort();\
16bd389b36SDavid du Colombier OFFSET += 4;\
17bd389b36SDavid du Colombier
18bd389b36SDavid du Colombier if(OFFSET == BADOFFSET)\
19bd389b36SDavid du Colombier abort();\
20bd389b36SDavid du Colombier OFFSET++;\
21bd389b36SDavid du Colombier */
22bd389b36SDavid du Colombier
2391178603SDavid du Colombier #define LPUT(l) { \
2491178603SDavid du Colombier if (little) { \
2591178603SDavid du Colombier LLEPUT(l); \
2691178603SDavid du Colombier } else { \
2791178603SDavid du Colombier LBEPUT(l); \
2891178603SDavid du Colombier } \
2991178603SDavid du Colombier }
3091178603SDavid du Colombier
3191178603SDavid du Colombier #define LLEPUT(c)\
3291178603SDavid du Colombier {\
3391178603SDavid du Colombier cbp[0] = (c);\
3491178603SDavid du Colombier cbp[1] = (c)>>8;\
3591178603SDavid du Colombier cbp[2] = (c)>>16;\
3691178603SDavid du Colombier cbp[3] = (c)>>24;\
3791178603SDavid du Colombier cbp += 4;\
3891178603SDavid du Colombier cbc -= 4;\
3991178603SDavid du Colombier if(cbc <= 0)\
4091178603SDavid du Colombier cflush();\
4191178603SDavid du Colombier }
4291178603SDavid du Colombier
4391178603SDavid du Colombier #define LBEPUT(c)\
443e12c5d1SDavid du Colombier {\
453e12c5d1SDavid du Colombier cbp[0] = (c)>>24;\
463e12c5d1SDavid du Colombier cbp[1] = (c)>>16;\
473e12c5d1SDavid du Colombier cbp[2] = (c)>>8;\
483e12c5d1SDavid du Colombier cbp[3] = (c);\
493e12c5d1SDavid du Colombier cbp += 4;\
503e12c5d1SDavid du Colombier cbc -= 4;\
513e12c5d1SDavid du Colombier if(cbc <= 0)\
523e12c5d1SDavid du Colombier cflush();\
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier
55bfb6eab9SDavid du Colombier #define HPUT(h) { \
56bfb6eab9SDavid du Colombier if (little) { \
57bfb6eab9SDavid du Colombier HLEPUT(h); \
58bfb6eab9SDavid du Colombier } else { \
59bfb6eab9SDavid du Colombier HBEPUT(h); \
60bfb6eab9SDavid du Colombier } \
61bfb6eab9SDavid du Colombier }
62bfb6eab9SDavid du Colombier
63bfb6eab9SDavid du Colombier #define HLEPUT(c)\
64bfb6eab9SDavid du Colombier {\
65bfb6eab9SDavid du Colombier cbp[0] = (c);\
66bfb6eab9SDavid du Colombier cbp[1] = (c)>>8;\
67bfb6eab9SDavid du Colombier cbp += 2;\
68bfb6eab9SDavid du Colombier cbc -= 2;\
69bfb6eab9SDavid du Colombier if(cbc <= 0)\
70bfb6eab9SDavid du Colombier cflush();\
71bfb6eab9SDavid du Colombier }
72bfb6eab9SDavid du Colombier
73bfb6eab9SDavid du Colombier #define HBEPUT(c)\
74bfb6eab9SDavid du Colombier {\
75bfb6eab9SDavid du Colombier cbp[0] = (c)>>8;\
76bfb6eab9SDavid du Colombier cbp[1] = (c);\
77bfb6eab9SDavid du Colombier cbp += 2;\
78bfb6eab9SDavid du Colombier cbc -= 2;\
79bfb6eab9SDavid du Colombier if(cbc <= 0)\
80bfb6eab9SDavid du Colombier cflush();\
81bfb6eab9SDavid du Colombier }
82bfb6eab9SDavid du Colombier
8391178603SDavid du Colombier
843e12c5d1SDavid du Colombier #define CPUT(c)\
853e12c5d1SDavid du Colombier {\
863e12c5d1SDavid du Colombier cbp[0] = (c);\
873e12c5d1SDavid du Colombier cbp++;\
883e12c5d1SDavid du Colombier cbc--;\
893e12c5d1SDavid du Colombier if(cbc <= 0)\
903e12c5d1SDavid du Colombier cflush();\
913e12c5d1SDavid du Colombier }
923e12c5d1SDavid du Colombier
9391178603SDavid du Colombier void
cput(long l)948153b942SDavid du Colombier cput(long l)
958153b942SDavid du Colombier {
968153b942SDavid du Colombier CPUT(l);
978153b942SDavid du Colombier }
988153b942SDavid du Colombier
998153b942SDavid du Colombier void
objput(long l)10091178603SDavid du Colombier objput(long l) /* emit long in byte order appropriate to object machine */
10191178603SDavid du Colombier {
10291178603SDavid du Colombier LPUT(l);
10391178603SDavid du Colombier }
10491178603SDavid du Colombier
10591178603SDavid du Colombier void
objhput(short s)106bfb6eab9SDavid du Colombier objhput(short s)
107bfb6eab9SDavid du Colombier {
108bfb6eab9SDavid du Colombier HPUT(s);
109bfb6eab9SDavid du Colombier }
110bfb6eab9SDavid du Colombier
111bfb6eab9SDavid du Colombier void
wput(long l)1128153b942SDavid du Colombier wput(long l)
1138153b942SDavid du Colombier {
1148153b942SDavid du Colombier
1158153b942SDavid du Colombier cbp[0] = l>>8;
1168153b942SDavid du Colombier cbp[1] = l;
1178153b942SDavid du Colombier cbp += 2;
1188153b942SDavid du Colombier cbc -= 2;
1198153b942SDavid du Colombier if(cbc <= 0)
1208153b942SDavid du Colombier cflush();
1218153b942SDavid du Colombier }
1228153b942SDavid du Colombier
1238153b942SDavid du Colombier void
wputl(long l)1248153b942SDavid du Colombier wputl(long l)
1258153b942SDavid du Colombier {
1268153b942SDavid du Colombier
1278153b942SDavid du Colombier cbp[0] = l;
1288153b942SDavid du Colombier cbp[1] = l>>8;
1298153b942SDavid du Colombier cbp += 2;
1308153b942SDavid du Colombier cbc -= 2;
1318153b942SDavid du Colombier if(cbc <= 0)
1328153b942SDavid du Colombier cflush();
1338153b942SDavid du Colombier }
1348153b942SDavid du Colombier
1358153b942SDavid du Colombier void
lput(long l)13691178603SDavid du Colombier lput(long l) /* emit long in big-endian byte order */
13791178603SDavid du Colombier {
13891178603SDavid du Colombier LBEPUT(l);
13991178603SDavid du Colombier }
14091178603SDavid du Colombier
1418153b942SDavid du Colombier void
lputl(long l)1428153b942SDavid du Colombier lputl(long l) /* emit long in big-endian byte order */
1438153b942SDavid du Colombier {
1448153b942SDavid du Colombier LLEPUT(l);
1458153b942SDavid du Colombier }
1468153b942SDavid du Colombier
1478153b942SDavid du Colombier void
llput(vlong v)1488153b942SDavid du Colombier llput(vlong v)
1498153b942SDavid du Colombier {
1508153b942SDavid du Colombier lput(v>>32);
1518153b942SDavid du Colombier lput(v);
1528153b942SDavid du Colombier }
1538153b942SDavid du Colombier
1548153b942SDavid du Colombier void
llputl(vlong v)1558153b942SDavid du Colombier llputl(vlong v)
1568153b942SDavid du Colombier {
1578153b942SDavid du Colombier lputl(v);
1588153b942SDavid du Colombier lputl(v>>32);
1598153b942SDavid du Colombier }
1608153b942SDavid du Colombier
1613e12c5d1SDavid du Colombier long
entryvalue(void)1623e12c5d1SDavid du Colombier entryvalue(void)
1633e12c5d1SDavid du Colombier {
1643e12c5d1SDavid du Colombier char *a;
1653e12c5d1SDavid du Colombier Sym *s;
1663e12c5d1SDavid du Colombier
1673e12c5d1SDavid du Colombier a = INITENTRY;
1683e12c5d1SDavid du Colombier if(*a >= '0' && *a <= '9')
1693e12c5d1SDavid du Colombier return atolwhex(a);
1703e12c5d1SDavid du Colombier s = lookup(a, 0);
1713e12c5d1SDavid du Colombier if(s->type == 0)
1723e12c5d1SDavid du Colombier return INITTEXT;
1733e12c5d1SDavid du Colombier if(s->type != STEXT && s->type != SLEAF)
1743e12c5d1SDavid du Colombier diag("entry not text: %s", s->name);
1753e12c5d1SDavid du Colombier return s->value;
1763e12c5d1SDavid du Colombier }
1773e12c5d1SDavid du Colombier
1785482313dSDavid du Colombier static void
plan9bootimage(ulong sects,ulong submagicvers,ulong tm,ulong hdrtxtsz,ulong textsz,ulong textva,ulong lcsize)1795482313dSDavid du Colombier plan9bootimage(ulong sects, ulong submagicvers, ulong tm,
1805482313dSDavid du Colombier ulong hdrtxtsz, ulong textsz, ulong textva, ulong lcsize)
1815482313dSDavid du Colombier {
1825482313dSDavid du Colombier lput(0x160L<<16|sects); /* magic and sections */
1835482313dSDavid du Colombier lput(tm); /* time and date */
1845482313dSDavid du Colombier lput(hdrtxtsz+datsize); /* offset to symbol table */
1855482313dSDavid du Colombier lput(symsize); /* size of symbol table */
1865482313dSDavid du Colombier lput((0x38L<<16)|7L); /* size of optional hdr and flags */
1875482313dSDavid du Colombier lput(submagicvers); /* magic and version */
1885482313dSDavid du Colombier
1895482313dSDavid du Colombier lput(textsz); /* segment sizes */
1905482313dSDavid du Colombier lput(datsize);
1915482313dSDavid du Colombier lput(bsssize);
1925482313dSDavid du Colombier
1935482313dSDavid du Colombier lput(entryvalue()); /* va of entry */
1945482313dSDavid du Colombier lput(textva); /* va of base of text */
1955482313dSDavid du Colombier lput(INITDAT); /* va of base of data */
1965482313dSDavid du Colombier lput(INITDAT+datsize); /* va of base of bss */
1975482313dSDavid du Colombier
1985482313dSDavid du Colombier lput(~0); /* gp reg mask */
1995482313dSDavid du Colombier lput(lcsize); /* pcsize / cprmask[0] */
2005482313dSDavid du Colombier lput(0); /* coproc reg masks[1⋯3] */
2015482313dSDavid du Colombier lput(0);
2025482313dSDavid du Colombier lput(0);
2035482313dSDavid du Colombier lput(~0); /* gp value ?? */
2045482313dSDavid du Colombier }
2055482313dSDavid du Colombier
2065482313dSDavid du Colombier static void
symhdrs(ulong hdrtxtsz)2075482313dSDavid du Colombier symhdrs(ulong hdrtxtsz)
2085482313dSDavid du Colombier {
2095482313dSDavid du Colombier strnput(".text", 8); /* text segment */
2105482313dSDavid du Colombier lput(INITTEXT); /* address */
2115482313dSDavid du Colombier lput(INITTEXT);
2125482313dSDavid du Colombier lput(textsize);
2135482313dSDavid du Colombier lput(HEADR);
2145482313dSDavid du Colombier lput(0);
2155482313dSDavid du Colombier lput(HEADR+textsize+datsize+symsize);
2165482313dSDavid du Colombier lput(lcsize); /* line number size */
2175482313dSDavid du Colombier lput(0x20); /* flags */
2185482313dSDavid du Colombier
2195482313dSDavid du Colombier strnput(".data", 8); /* data segment */
2205482313dSDavid du Colombier lput(INITDAT); /* address */
2215482313dSDavid du Colombier lput(INITDAT);
2225482313dSDavid du Colombier lput(datsize);
2235482313dSDavid du Colombier lput(hdrtxtsz);
2245482313dSDavid du Colombier lput(0);
2255482313dSDavid du Colombier lput(0);
2265482313dSDavid du Colombier lput(0);
2275482313dSDavid du Colombier lput(0x40); /* flags */
2285482313dSDavid du Colombier
2295482313dSDavid du Colombier strnput(".bss", 8); /* bss segment */
2305482313dSDavid du Colombier lput(INITDAT+datsize); /* address */
2315482313dSDavid du Colombier lput(INITDAT+datsize);
2325482313dSDavid du Colombier lput(bsssize);
2335482313dSDavid du Colombier lput(0);
2345482313dSDavid du Colombier lput(0);
2355482313dSDavid du Colombier lput(0);
2365482313dSDavid du Colombier lput(0);
2375482313dSDavid du Colombier lput(0x80); /* flags */
2385482313dSDavid du Colombier }
2395482313dSDavid du Colombier
2403e12c5d1SDavid du Colombier void
asmb(void)2413e12c5d1SDavid du Colombier asmb(void)
2423e12c5d1SDavid du Colombier {
2433e12c5d1SDavid du Colombier Prog *p;
2445482313dSDavid du Colombier long tm;
2455482313dSDavid du Colombier ulong rndtxtsz;
246a587111cSDavid du Colombier vlong t, etext;
2473e12c5d1SDavid du Colombier Optab *o;
2483e12c5d1SDavid du Colombier
2493e12c5d1SDavid du Colombier if(debug['v'])
2503e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f asm\n", cputime());
2513e12c5d1SDavid du Colombier Bflush(&bso);
252bd389b36SDavid du Colombier OFFSET = HEADR;
253bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
2543e12c5d1SDavid du Colombier pc = INITTEXT;
2553e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) {
2563e12c5d1SDavid du Colombier if(p->as == ATEXT) {
2573e12c5d1SDavid du Colombier curtext = p;
2583e12c5d1SDavid du Colombier autosize = p->to.offset + 4;
2593e12c5d1SDavid du Colombier }
2603e12c5d1SDavid du Colombier if(p->pc != pc) {
261a587111cSDavid du Colombier diag("phase error %llux sb %llux", p->pc, pc);
2623e12c5d1SDavid du Colombier if(!debug['a'])
2633e12c5d1SDavid du Colombier prasm(curp);
2643e12c5d1SDavid du Colombier pc = p->pc;
2653e12c5d1SDavid du Colombier }
2663e12c5d1SDavid du Colombier curp = p;
2673e12c5d1SDavid du Colombier o = oplook(p); /* could probably avoid this call */
2683e12c5d1SDavid du Colombier if(asmout(p, o, 0)) {
2693e12c5d1SDavid du Colombier p = p->link;
2703e12c5d1SDavid du Colombier pc += 4;
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier pc += o->size;
2733e12c5d1SDavid du Colombier }
2743e12c5d1SDavid du Colombier if(debug['a'])
2753e12c5d1SDavid du Colombier Bprint(&bso, "\n");
2763e12c5d1SDavid du Colombier Bflush(&bso);
2773e12c5d1SDavid du Colombier cflush();
2783e12c5d1SDavid du Colombier
2799a747e4fSDavid du Colombier etext = INITTEXT + textsize;
2809a747e4fSDavid du Colombier for(t = pc; t < etext; t += sizeof(buf)-100) {
2819a747e4fSDavid du Colombier if(etext-t > sizeof(buf)-100)
2829a747e4fSDavid du Colombier datblk(t, sizeof(buf)-100, 1);
2839a747e4fSDavid du Colombier else
2849a747e4fSDavid du Colombier datblk(t, etext-t, 1);
2859a747e4fSDavid du Colombier }
2869a747e4fSDavid du Colombier
2879a747e4fSDavid du Colombier Bflush(&bso);
2889a747e4fSDavid du Colombier cflush();
2899a747e4fSDavid du Colombier
2903e12c5d1SDavid du Colombier curtext = P;
2913e12c5d1SDavid du Colombier switch(HEADTYPE) {
2923e12c5d1SDavid du Colombier case 0:
293219b2ee8SDavid du Colombier case 4:
294bd389b36SDavid du Colombier OFFSET = rnd(HEADR+textsize, 4096);
295bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
2963e12c5d1SDavid du Colombier break;
2973e12c5d1SDavid du Colombier case 1:
2983e12c5d1SDavid du Colombier case 2:
299219b2ee8SDavid du Colombier case 3:
300219b2ee8SDavid du Colombier case 5:
30191178603SDavid du Colombier case 6:
302*a826b788SDavid du Colombier case 7:
303bd389b36SDavid du Colombier OFFSET = HEADR+textsize;
304bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
3053e12c5d1SDavid du Colombier break;
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier for(t = 0; t < datsize; t += sizeof(buf)-100) {
3083e12c5d1SDavid du Colombier if(datsize-t > sizeof(buf)-100)
3099a747e4fSDavid du Colombier datblk(t, sizeof(buf)-100, 0);
3103e12c5d1SDavid du Colombier else
3119a747e4fSDavid du Colombier datblk(t, datsize-t, 0);
3123e12c5d1SDavid du Colombier }
3133e12c5d1SDavid du Colombier
3143e12c5d1SDavid du Colombier symsize = 0;
3153e12c5d1SDavid du Colombier lcsize = 0;
3163e12c5d1SDavid du Colombier if(!debug['s']) {
3173e12c5d1SDavid du Colombier if(debug['v'])
3183e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f sym\n", cputime());
3193e12c5d1SDavid du Colombier Bflush(&bso);
3203e12c5d1SDavid du Colombier switch(HEADTYPE) {
3213e12c5d1SDavid du Colombier case 0:
322219b2ee8SDavid du Colombier case 4:
323bd389b36SDavid du Colombier OFFSET = rnd(HEADR+textsize, 4096)+datsize;
324bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
3253e12c5d1SDavid du Colombier break;
326219b2ee8SDavid du Colombier case 3:
3273e12c5d1SDavid du Colombier case 2:
3283e12c5d1SDavid du Colombier case 1:
329219b2ee8SDavid du Colombier case 5:
33091178603SDavid du Colombier case 6:
331*a826b788SDavid du Colombier case 7:
332bd389b36SDavid du Colombier OFFSET = HEADR+textsize+datsize;
333bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
3343e12c5d1SDavid du Colombier break;
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier if(!debug['s'])
3373e12c5d1SDavid du Colombier asmsym();
3383e12c5d1SDavid du Colombier if(debug['v'])
3393e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f pc\n", cputime());
3403e12c5d1SDavid du Colombier Bflush(&bso);
3413e12c5d1SDavid du Colombier if(!debug['s'])
3423e12c5d1SDavid du Colombier asmlc();
3433e12c5d1SDavid du Colombier cflush();
3443e12c5d1SDavid du Colombier }
3453e12c5d1SDavid du Colombier
3463e12c5d1SDavid du Colombier if(debug['v'])
3473e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f header\n", cputime());
3483e12c5d1SDavid du Colombier Bflush(&bso);
349bd389b36SDavid du Colombier OFFSET = 0;
350bd389b36SDavid du Colombier seek(cout, OFFSET, 0);
3515482313dSDavid du Colombier
3525482313dSDavid du Colombier rndtxtsz = rnd(HEADR+textsize, (INITRND > 0? INITRND: 4096));
3535482313dSDavid du Colombier tm = time(0);
3543e12c5d1SDavid du Colombier switch(HEADTYPE) {
3553e12c5d1SDavid du Colombier case 0:
3565482313dSDavid du Colombier /* 0413: plan 9 boot image, text segment rounded (to 4KB) */
3575482313dSDavid du Colombier plan9bootimage(0, 0413<<16|0437, 0, rndtxtsz, rndtxtsz,
3585482313dSDavid du Colombier INITTEXT-HEADR, 0);
3593e12c5d1SDavid du Colombier break;
3603e12c5d1SDavid du Colombier case 1:
3615482313dSDavid du Colombier /* 0407: plan 9 boot image, extra word */
3625482313dSDavid du Colombier plan9bootimage(0, 0407<<16|0437, 0, HEADR+textsize, textsize,
3635482313dSDavid du Colombier INITTEXT, lcsize);
3645482313dSDavid du Colombier lput(0); /* extra; complete mystery */
3653e12c5d1SDavid du Colombier break;
3663305c317SDavid du Colombier case 2: /* plan 9 format */
36791178603SDavid du Colombier if (little)
3683305c317SDavid du Colombier lput(P_MAGIC); /* mips 3000 LE */
36991178603SDavid du Colombier else
3703305c317SDavid du Colombier lput(V_MAGIC); /* mips 3000 BE */
3713e12c5d1SDavid du Colombier lput(textsize); /* sizes */
3723e12c5d1SDavid du Colombier lput(datsize);
3733e12c5d1SDavid du Colombier lput(bsssize);
3743e12c5d1SDavid du Colombier lput(symsize); /* nsyms */
3753e12c5d1SDavid du Colombier lput(entryvalue()); /* va of entry */
3763e12c5d1SDavid du Colombier lput(0L);
3773e12c5d1SDavid du Colombier lput(lcsize);
3783e12c5d1SDavid du Colombier break;
379219b2ee8SDavid du Colombier case 3:
3805482313dSDavid du Colombier /* 0407: plan 9 mips 4k boot image with symbols */
3815482313dSDavid du Colombier plan9bootimage(3, 0407<<16|0437, tm, HEADR+textsize, textsize,
3825482313dSDavid du Colombier INITTEXT, lcsize);
3835482313dSDavid du Colombier symhdrs(HEADR+textsize);
384219b2ee8SDavid du Colombier break;
385219b2ee8SDavid du Colombier case 4:
3865482313dSDavid du Colombier /* 0413: plan 9 mips 4k boot image with symbols */
3875482313dSDavid du Colombier plan9bootimage(3, 0413<<16|01012, tm, rndtxtsz, textsize,
3885482313dSDavid du Colombier INITTEXT, lcsize);
3895482313dSDavid du Colombier symhdrs(rndtxtsz);
390219b2ee8SDavid du Colombier break;
391219b2ee8SDavid du Colombier case 5:
3928153b942SDavid du Colombier elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
39391178603SDavid du Colombier break;
39491178603SDavid du Colombier case 6:
39591178603SDavid du Colombier break;
396a587111cSDavid du Colombier case 7:
397a587111cSDavid du Colombier elf64(MIPSR4K, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
398a587111cSDavid du Colombier break;
3993e12c5d1SDavid du Colombier }
4003e12c5d1SDavid du Colombier cflush();
4013e12c5d1SDavid du Colombier }
4023e12c5d1SDavid du Colombier
4033e12c5d1SDavid du Colombier void
strnput(char * s,int n)404219b2ee8SDavid du Colombier strnput(char *s, int n)
405219b2ee8SDavid du Colombier {
406219b2ee8SDavid du Colombier for(; *s; s++){
407219b2ee8SDavid du Colombier CPUT(*s);
408219b2ee8SDavid du Colombier n--;
409219b2ee8SDavid du Colombier }
410219b2ee8SDavid du Colombier for(; n > 0; n--)
411219b2ee8SDavid du Colombier CPUT(0);
412219b2ee8SDavid du Colombier }
413219b2ee8SDavid du Colombier
414219b2ee8SDavid du Colombier void
cflush(void)4153e12c5d1SDavid du Colombier cflush(void)
4163e12c5d1SDavid du Colombier {
4173e12c5d1SDavid du Colombier int n;
4183e12c5d1SDavid du Colombier
4193e12c5d1SDavid du Colombier n = sizeof(buf.cbuf) - cbc;
4203e12c5d1SDavid du Colombier if(n)
4213e12c5d1SDavid du Colombier write(cout, buf.cbuf, n);
4223e12c5d1SDavid du Colombier cbp = buf.cbuf;
4233e12c5d1SDavid du Colombier cbc = sizeof(buf.cbuf);
4243e12c5d1SDavid du Colombier }
4253e12c5d1SDavid du Colombier
4263e12c5d1SDavid du Colombier void
nopstat(char * f,Count * c)427219b2ee8SDavid du Colombier nopstat(char *f, Count *c)
428219b2ee8SDavid du Colombier {
429219b2ee8SDavid du Colombier if(c->outof)
430219b2ee8SDavid du Colombier Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
431219b2ee8SDavid du Colombier c->outof - c->count, c->outof,
432219b2ee8SDavid du Colombier (double)(c->outof - c->count)/c->outof);
433219b2ee8SDavid du Colombier }
434219b2ee8SDavid du Colombier
435219b2ee8SDavid du Colombier void
asmsym(void)4363e12c5d1SDavid du Colombier asmsym(void)
4373e12c5d1SDavid du Colombier {
4383e12c5d1SDavid du Colombier Prog *p;
4393e12c5d1SDavid du Colombier Auto *a;
4403e12c5d1SDavid du Colombier Sym *s;
4413e12c5d1SDavid du Colombier int h;
4423e12c5d1SDavid du Colombier
4433e12c5d1SDavid du Colombier s = lookup("etext", 0);
4443e12c5d1SDavid du Colombier if(s->type == STEXT)
4453e12c5d1SDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
4463e12c5d1SDavid du Colombier
4473e12c5d1SDavid du Colombier for(h=0; h<NHASH; h++)
4483e12c5d1SDavid du Colombier for(s=hash[h]; s!=S; s=s->link)
4493e12c5d1SDavid du Colombier switch(s->type) {
450219b2ee8SDavid du Colombier case SCONST:
451219b2ee8SDavid du Colombier putsymb(s->name, 'D', s->value, s->version);
452219b2ee8SDavid du Colombier continue;
453219b2ee8SDavid du Colombier
4549a747e4fSDavid du Colombier case SSTRING:
4559a747e4fSDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
4569a747e4fSDavid du Colombier continue;
4579a747e4fSDavid du Colombier
4583e12c5d1SDavid du Colombier case SDATA:
4593e12c5d1SDavid du Colombier putsymb(s->name, 'D', s->value+INITDAT, s->version);
4603e12c5d1SDavid du Colombier continue;
4613e12c5d1SDavid du Colombier
4623e12c5d1SDavid du Colombier case SBSS:
4633e12c5d1SDavid du Colombier putsymb(s->name, 'B', s->value+INITDAT, s->version);
4643e12c5d1SDavid du Colombier continue;
4653e12c5d1SDavid du Colombier
4663e12c5d1SDavid du Colombier case SFILE:
4673e12c5d1SDavid du Colombier putsymb(s->name, 'f', s->value, s->version);
4683e12c5d1SDavid du Colombier continue;
4693e12c5d1SDavid du Colombier }
4703e12c5d1SDavid du Colombier
4713e12c5d1SDavid du Colombier for(p=textp; p!=P; p=p->cond) {
4723e12c5d1SDavid du Colombier s = p->from.sym;
4733e12c5d1SDavid du Colombier if(s->type != STEXT && s->type != SLEAF)
4743e12c5d1SDavid du Colombier continue;
4753e12c5d1SDavid du Colombier
4763e12c5d1SDavid du Colombier /* filenames first */
4773e12c5d1SDavid du Colombier for(a=p->to.autom; a; a=a->link)
4783e12c5d1SDavid du Colombier if(a->type == D_FILE)
4797dd7cddfSDavid du Colombier putsymb(a->asym->name, 'z', a->aoffset, 0);
4803e12c5d1SDavid du Colombier else
481219b2ee8SDavid du Colombier if(a->type == D_FILE1)
4827dd7cddfSDavid du Colombier putsymb(a->asym->name, 'Z', a->aoffset, 0);
4833e12c5d1SDavid du Colombier
4843e12c5d1SDavid du Colombier if(s->type == STEXT)
4853e12c5d1SDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
4863e12c5d1SDavid du Colombier else
4873e12c5d1SDavid du Colombier putsymb(s->name, 'L', s->value, s->version);
4883e12c5d1SDavid du Colombier
4893e12c5d1SDavid du Colombier /* frame, auto and param after */
490219b2ee8SDavid du Colombier putsymb(".frame", 'm', p->to.offset+4, 0);
4913e12c5d1SDavid du Colombier for(a=p->to.autom; a; a=a->link)
4923e12c5d1SDavid du Colombier if(a->type == D_AUTO)
4937dd7cddfSDavid du Colombier putsymb(a->asym->name, 'a', -a->aoffset, 0);
4943e12c5d1SDavid du Colombier else
4953e12c5d1SDavid du Colombier if(a->type == D_PARAM)
4967dd7cddfSDavid du Colombier putsymb(a->asym->name, 'p', a->aoffset, 0);
4973e12c5d1SDavid du Colombier }
4983e12c5d1SDavid du Colombier if(debug['v'] || debug['n'])
4993e12c5d1SDavid du Colombier Bprint(&bso, "symsize = %lud\n", symsize);
5003e12c5d1SDavid du Colombier Bflush(&bso);
5013e12c5d1SDavid du Colombier }
5023e12c5d1SDavid du Colombier
5033e12c5d1SDavid du Colombier void
putsymb(char * s,int t,long v,int ver)5043e12c5d1SDavid du Colombier putsymb(char *s, int t, long v, int ver)
5053e12c5d1SDavid du Colombier {
5063e12c5d1SDavid du Colombier int i, f;
5073e12c5d1SDavid du Colombier
5083e12c5d1SDavid du Colombier if(t == 'f')
5093e12c5d1SDavid du Colombier s++;
51091178603SDavid du Colombier LBEPUT(v);
5113e12c5d1SDavid du Colombier if(ver)
5123e12c5d1SDavid du Colombier t += 'a' - 'A';
513219b2ee8SDavid du Colombier CPUT(t+0x80); /* 0x80 is variable length */
514219b2ee8SDavid du Colombier
515219b2ee8SDavid du Colombier if(t == 'Z' || t == 'z') {
516219b2ee8SDavid du Colombier CPUT(s[0]);
517219b2ee8SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
518219b2ee8SDavid du Colombier CPUT(s[i]);
519219b2ee8SDavid du Colombier CPUT(s[i+1]);
520219b2ee8SDavid du Colombier }
521219b2ee8SDavid du Colombier CPUT(0);
522219b2ee8SDavid du Colombier CPUT(0);
523219b2ee8SDavid du Colombier i++;
524219b2ee8SDavid du Colombier }
525219b2ee8SDavid du Colombier else {
526219b2ee8SDavid du Colombier for(i=0; s[i]; i++)
5273e12c5d1SDavid du Colombier CPUT(s[i]);
5283e12c5d1SDavid du Colombier CPUT(0);
529219b2ee8SDavid du Colombier }
530219b2ee8SDavid du Colombier symsize += 4 + 1 + i + 1;
531219b2ee8SDavid du Colombier
5323e12c5d1SDavid du Colombier if(debug['n']) {
5333e12c5d1SDavid du Colombier if(t == 'z' || t == 'Z') {
534219b2ee8SDavid du Colombier Bprint(&bso, "%c %.8lux ", t, v);
535219b2ee8SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
5363e12c5d1SDavid du Colombier f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
537219b2ee8SDavid du Colombier Bprint(&bso, "/%x", f);
5383e12c5d1SDavid du Colombier }
539219b2ee8SDavid du Colombier Bprint(&bso, "\n");
5403e12c5d1SDavid du Colombier return;
5413e12c5d1SDavid du Colombier }
5423e12c5d1SDavid du Colombier if(ver)
5433e12c5d1SDavid du Colombier Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
5443e12c5d1SDavid du Colombier else
5453e12c5d1SDavid du Colombier Bprint(&bso, "%c %.8lux %s\n", t, v, s);
5463e12c5d1SDavid du Colombier }
5473e12c5d1SDavid du Colombier }
5483e12c5d1SDavid du Colombier
5493e12c5d1SDavid du Colombier #define MINLC 4
5503e12c5d1SDavid du Colombier void
asmlc(void)5513e12c5d1SDavid du Colombier asmlc(void)
5523e12c5d1SDavid du Colombier {
553a587111cSDavid du Colombier long oldlc, v, s;
554a587111cSDavid du Colombier vlong oldpc;
5553e12c5d1SDavid du Colombier Prog *p;
5563e12c5d1SDavid du Colombier
5573e12c5d1SDavid du Colombier oldpc = INITTEXT;
5583e12c5d1SDavid du Colombier oldlc = 0;
5593e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) {
5603e12c5d1SDavid du Colombier if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
5613e12c5d1SDavid du Colombier if(p->as == ATEXT)
5623e12c5d1SDavid du Colombier curtext = p;
563b87cd620SDavid du Colombier if(debug['V'])
564a587111cSDavid du Colombier Bprint(&bso, "%6llux %P\n", p->pc, p);
5653e12c5d1SDavid du Colombier continue;
5663e12c5d1SDavid du Colombier }
567b87cd620SDavid du Colombier if(debug['V'])
5683e12c5d1SDavid du Colombier Bprint(&bso, "\t\t%6ld", lcsize);
5693e12c5d1SDavid du Colombier v = (p->pc - oldpc) / MINLC;
5703e12c5d1SDavid du Colombier while(v) {
5713e12c5d1SDavid du Colombier s = 127;
5723e12c5d1SDavid du Colombier if(v < 127)
5733e12c5d1SDavid du Colombier s = v;
5743e12c5d1SDavid du Colombier CPUT(s+128); /* 129-255 +pc */
575b87cd620SDavid du Colombier if(debug['V'])
5763e12c5d1SDavid du Colombier Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
5773e12c5d1SDavid du Colombier v -= s;
5783e12c5d1SDavid du Colombier lcsize++;
5793e12c5d1SDavid du Colombier }
5803e12c5d1SDavid du Colombier s = p->line - oldlc;
5813e12c5d1SDavid du Colombier oldlc = p->line;
5823e12c5d1SDavid du Colombier oldpc = p->pc + MINLC;
5833e12c5d1SDavid du Colombier if(s > 64 || s < -64) {
5843e12c5d1SDavid du Colombier CPUT(0); /* 0 vv +lc */
5853e12c5d1SDavid du Colombier CPUT(s>>24);
5863e12c5d1SDavid du Colombier CPUT(s>>16);
5873e12c5d1SDavid du Colombier CPUT(s>>8);
5883e12c5d1SDavid du Colombier CPUT(s);
589b87cd620SDavid du Colombier if(debug['V']) {
5903e12c5d1SDavid du Colombier if(s > 0)
5913e12c5d1SDavid du Colombier Bprint(&bso, " lc+%ld(%d,%ld)\n",
5923e12c5d1SDavid du Colombier s, 0, s);
5933e12c5d1SDavid du Colombier else
5943e12c5d1SDavid du Colombier Bprint(&bso, " lc%ld(%d,%ld)\n",
5953e12c5d1SDavid du Colombier s, 0, s);
596a587111cSDavid du Colombier Bprint(&bso, "%6llux %P\n", p->pc, p);
5973e12c5d1SDavid du Colombier }
5983e12c5d1SDavid du Colombier lcsize += 5;
5993e12c5d1SDavid du Colombier continue;
6003e12c5d1SDavid du Colombier }
6013e12c5d1SDavid du Colombier if(s > 0) {
6023e12c5d1SDavid du Colombier CPUT(0+s); /* 1-64 +lc */
603b87cd620SDavid du Colombier if(debug['V']) {
6043e12c5d1SDavid du Colombier Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
605a587111cSDavid du Colombier Bprint(&bso, "%6llux %P\n", p->pc, p);
6063e12c5d1SDavid du Colombier }
6073e12c5d1SDavid du Colombier } else {
6083e12c5d1SDavid du Colombier CPUT(64-s); /* 65-128 -lc */
609b87cd620SDavid du Colombier if(debug['V']) {
6103e12c5d1SDavid du Colombier Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
611a587111cSDavid du Colombier Bprint(&bso, "%6llux %P\n", p->pc, p);
6123e12c5d1SDavid du Colombier }
6133e12c5d1SDavid du Colombier }
6143e12c5d1SDavid du Colombier lcsize++;
6153e12c5d1SDavid du Colombier }
6163e12c5d1SDavid du Colombier while(lcsize & 1) {
6173e12c5d1SDavid du Colombier s = 129;
6183e12c5d1SDavid du Colombier CPUT(s);
6193e12c5d1SDavid du Colombier lcsize++;
6203e12c5d1SDavid du Colombier }
621b87cd620SDavid du Colombier if(debug['v'] || debug['V'])
6223e12c5d1SDavid du Colombier Bprint(&bso, "lcsize = %ld\n", lcsize);
6233e12c5d1SDavid du Colombier Bflush(&bso);
6243e12c5d1SDavid du Colombier }
6253e12c5d1SDavid du Colombier
6263e12c5d1SDavid du Colombier void
datblk(long s,long n,int str)6279a747e4fSDavid du Colombier datblk(long s, long n, int str)
6283e12c5d1SDavid du Colombier {
6293e12c5d1SDavid du Colombier Prog *p;
6303e12c5d1SDavid du Colombier char *cast;
6313e12c5d1SDavid du Colombier long l, fl, j, d;
6323e12c5d1SDavid du Colombier int i, c;
6333e12c5d1SDavid du Colombier
6343e12c5d1SDavid du Colombier memset(buf.dbuf, 0, n+100);
6353e12c5d1SDavid du Colombier for(p = datap; p != P; p = p->link) {
6363e12c5d1SDavid du Colombier curp = p;
6379a747e4fSDavid du Colombier if(str != (p->from.sym->type == SSTRING))
6389a747e4fSDavid du Colombier continue;
6393e12c5d1SDavid du Colombier l = p->from.sym->value + p->from.offset - s;
6403e12c5d1SDavid du Colombier c = p->reg;
6413e12c5d1SDavid du Colombier i = 0;
6423e12c5d1SDavid du Colombier if(l < 0) {
6433e12c5d1SDavid du Colombier if(l+c <= 0)
6443e12c5d1SDavid du Colombier continue;
6453e12c5d1SDavid du Colombier while(l < 0) {
6463e12c5d1SDavid du Colombier l++;
6473e12c5d1SDavid du Colombier i++;
6483e12c5d1SDavid du Colombier }
6493e12c5d1SDavid du Colombier }
6503e12c5d1SDavid du Colombier if(l >= n)
6513e12c5d1SDavid du Colombier continue;
652219b2ee8SDavid du Colombier if(p->as != AINIT && p->as != ADYNT) {
6533e12c5d1SDavid du Colombier for(j=l+(c-i)-1; j>=l; j--)
6543e12c5d1SDavid du Colombier if(buf.dbuf[j]) {
6553e12c5d1SDavid du Colombier print("%P\n", p);
6566b6b9ac8SDavid du Colombier diag("multiple initialization");
6573e12c5d1SDavid du Colombier break;
6583e12c5d1SDavid du Colombier }
659219b2ee8SDavid du Colombier }
6603e12c5d1SDavid du Colombier switch(p->to.type) {
6613e12c5d1SDavid du Colombier default:
6626b6b9ac8SDavid du Colombier diag("unknown mode in initialization\n%P", p);
6633e12c5d1SDavid du Colombier break;
6643e12c5d1SDavid du Colombier
6653e12c5d1SDavid du Colombier case D_FCONST:
6663e12c5d1SDavid du Colombier switch(c) {
6673e12c5d1SDavid du Colombier default:
6683e12c5d1SDavid du Colombier case 4:
6693e12c5d1SDavid du Colombier fl = ieeedtof(p->to.ieee);
6703e12c5d1SDavid du Colombier cast = (char*)&fl;
6713e12c5d1SDavid du Colombier for(; i<c; i++) {
6723e12c5d1SDavid du Colombier buf.dbuf[l] = cast[fnuxi8[i+4]];
6733e12c5d1SDavid du Colombier l++;
6743e12c5d1SDavid du Colombier }
6753e12c5d1SDavid du Colombier break;
6763e12c5d1SDavid du Colombier case 8:
6773e12c5d1SDavid du Colombier cast = (char*)p->to.ieee;
6783e12c5d1SDavid du Colombier for(; i<c; i++) {
6793e12c5d1SDavid du Colombier buf.dbuf[l] = cast[fnuxi8[i]];
6803e12c5d1SDavid du Colombier l++;
6813e12c5d1SDavid du Colombier }
6823e12c5d1SDavid du Colombier break;
6833e12c5d1SDavid du Colombier }
6843e12c5d1SDavid du Colombier break;
6853e12c5d1SDavid du Colombier
6863e12c5d1SDavid du Colombier case D_SCONST:
6873e12c5d1SDavid du Colombier for(; i<c; i++) {
6883e12c5d1SDavid du Colombier buf.dbuf[l] = p->to.sval[i];
6893e12c5d1SDavid du Colombier l++;
6903e12c5d1SDavid du Colombier }
6913e12c5d1SDavid du Colombier break;
6923e12c5d1SDavid du Colombier
6933e12c5d1SDavid du Colombier case D_CONST:
6943e12c5d1SDavid du Colombier d = p->to.offset;
6953e12c5d1SDavid du Colombier if(p->to.sym) {
6969a747e4fSDavid du Colombier switch(p->to.sym->type) {
6979a747e4fSDavid du Colombier case STEXT:
6989a747e4fSDavid du Colombier case SLEAF:
6999a747e4fSDavid du Colombier case SSTRING:
7003e12c5d1SDavid du Colombier d += p->to.sym->value;
7019a747e4fSDavid du Colombier break;
7029a747e4fSDavid du Colombier case SDATA:
7039a747e4fSDavid du Colombier case SBSS:
7043e12c5d1SDavid du Colombier d += p->to.sym->value + INITDAT;
7059a747e4fSDavid du Colombier break;
7069a747e4fSDavid du Colombier }
7073e12c5d1SDavid du Colombier }
7083e12c5d1SDavid du Colombier cast = (char*)&d;
7093e12c5d1SDavid du Colombier switch(c) {
7103e12c5d1SDavid du Colombier default:
7116b6b9ac8SDavid du Colombier diag("bad nuxi %d %d\n%P", c, i, curp);
7123e12c5d1SDavid du Colombier break;
7133e12c5d1SDavid du Colombier case 1:
7143e12c5d1SDavid du Colombier for(; i<c; i++) {
7153e12c5d1SDavid du Colombier buf.dbuf[l] = cast[inuxi1[i]];
7163e12c5d1SDavid du Colombier l++;
7173e12c5d1SDavid du Colombier }
7183e12c5d1SDavid du Colombier break;
7193e12c5d1SDavid du Colombier case 2:
7203e12c5d1SDavid du Colombier for(; i<c; i++) {
7213e12c5d1SDavid du Colombier buf.dbuf[l] = cast[inuxi2[i]];
7223e12c5d1SDavid du Colombier l++;
7233e12c5d1SDavid du Colombier }
7243e12c5d1SDavid du Colombier break;
7253e12c5d1SDavid du Colombier case 4:
7263e12c5d1SDavid du Colombier for(; i<c; i++) {
7273e12c5d1SDavid du Colombier buf.dbuf[l] = cast[inuxi4[i]];
7283e12c5d1SDavid du Colombier l++;
7293e12c5d1SDavid du Colombier }
7303e12c5d1SDavid du Colombier break;
7313e12c5d1SDavid du Colombier }
7323e12c5d1SDavid du Colombier break;
7333e12c5d1SDavid du Colombier }
7343e12c5d1SDavid du Colombier }
7353e12c5d1SDavid du Colombier write(cout, buf.dbuf, n);
7363e12c5d1SDavid du Colombier }
7373e12c5d1SDavid du Colombier
7383e12c5d1SDavid du Colombier #define OP_RRR(op,r1,r2,r3)\
7393e12c5d1SDavid du Colombier (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11))
7403e12c5d1SDavid du Colombier #define OP_IRR(op,i,r2,r3)\
7413e12c5d1SDavid du Colombier (op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16))
7423e12c5d1SDavid du Colombier #define OP_SRR(op,s,r2,r3)\
7433e12c5d1SDavid du Colombier (op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11))
7443e12c5d1SDavid du Colombier #define OP_FRRR(op,r1,r2,r3)\
7453e12c5d1SDavid du Colombier (op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6))
7463e12c5d1SDavid du Colombier #define OP_JMP(op,i)\
7473e12c5d1SDavid du Colombier ((op)|((i)&0x3ffffffL))
7483e12c5d1SDavid du Colombier
749219b2ee8SDavid du Colombier #define OP(x,y)\
750219b2ee8SDavid du Colombier (((x)<<3)|((y)<<0))
751219b2ee8SDavid du Colombier #define SP(x,y)\
752219b2ee8SDavid du Colombier (((x)<<29)|((y)<<26))
753219b2ee8SDavid du Colombier #define BCOND(x,y)\
754219b2ee8SDavid du Colombier (((x)<<19)|((y)<<16))
755219b2ee8SDavid du Colombier #define MMU(x,y)\
756219b2ee8SDavid du Colombier (SP(2,0)|(16<<21)|((x)<<3)|((y)<<0))
757219b2ee8SDavid du Colombier #define FPF(x,y)\
758219b2ee8SDavid du Colombier (SP(2,1)|(16<<21)|((x)<<3)|((y)<<0))
759219b2ee8SDavid du Colombier #define FPD(x,y)\
760219b2ee8SDavid du Colombier (SP(2,1)|(17<<21)|((x)<<3)|((y)<<0))
761219b2ee8SDavid du Colombier #define FPW(x,y)\
762219b2ee8SDavid du Colombier (SP(2,1)|(20<<21)|((x)<<3)|((y)<<0))
763219b2ee8SDavid du Colombier
764dc5a79c1SDavid du Colombier int vshift(int);
765dc5a79c1SDavid du Colombier
7663e12c5d1SDavid du Colombier int
asmout(Prog * p,Optab * o,int aflag)7673e12c5d1SDavid du Colombier asmout(Prog *p, Optab *o, int aflag)
7683e12c5d1SDavid du Colombier {
7697dd7cddfSDavid du Colombier long o1, o2, o3, o4, o5, o6, o7, v;
7703e12c5d1SDavid du Colombier Prog *ct;
7713e12c5d1SDavid du Colombier int r, a;
7723e12c5d1SDavid du Colombier
7733e12c5d1SDavid du Colombier o1 = 0;
7743e12c5d1SDavid du Colombier o2 = 0;
7753e12c5d1SDavid du Colombier o3 = 0;
7763e12c5d1SDavid du Colombier o4 = 0;
777219b2ee8SDavid du Colombier o5 = 0;
7787dd7cddfSDavid du Colombier o6 = 0;
7797dd7cddfSDavid du Colombier o7 = 0;
7803e12c5d1SDavid du Colombier switch(o->type) {
7813e12c5d1SDavid du Colombier default:
7826b6b9ac8SDavid du Colombier diag("unknown type %d", o->type);
7833e12c5d1SDavid du Colombier if(!debug['a'])
7843e12c5d1SDavid du Colombier prasm(p);
7853e12c5d1SDavid du Colombier break;
7863e12c5d1SDavid du Colombier
7873e12c5d1SDavid du Colombier case 0: /* pseudo ops */
7883e12c5d1SDavid du Colombier if(aflag) {
7893e12c5d1SDavid du Colombier if(p->link) {
7903e12c5d1SDavid du Colombier if(p->as == ATEXT) {
7913e12c5d1SDavid du Colombier ct = curtext;
7923e12c5d1SDavid du Colombier o2 = autosize;
7933e12c5d1SDavid du Colombier curtext = p;
7943e12c5d1SDavid du Colombier autosize = p->to.offset + 4;
7953e12c5d1SDavid du Colombier o1 = asmout(p->link, oplook(p->link), aflag);
7963e12c5d1SDavid du Colombier curtext = ct;
7973e12c5d1SDavid du Colombier autosize = o2;
7983e12c5d1SDavid du Colombier } else
7993e12c5d1SDavid du Colombier o1 = asmout(p->link, oplook(p->link), aflag);
8003e12c5d1SDavid du Colombier }
8013e12c5d1SDavid du Colombier return o1;
8023e12c5d1SDavid du Colombier }
8033e12c5d1SDavid du Colombier break;
8043e12c5d1SDavid du Colombier
805219b2ee8SDavid du Colombier case 1: /* mov[v] r1,r2 ==> OR r1,r0,r2 */
8063e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg);
8073e12c5d1SDavid du Colombier break;
8083e12c5d1SDavid du Colombier
8093e12c5d1SDavid du Colombier case 2: /* add/sub r1,[r2],r3 */
8103e12c5d1SDavid du Colombier r = p->reg;
8113e12c5d1SDavid du Colombier if(r == NREG)
8123e12c5d1SDavid du Colombier r = p->to.reg;
8133e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg);
8143e12c5d1SDavid du Colombier break;
8153e12c5d1SDavid du Colombier
8163e12c5d1SDavid du Colombier case 3: /* mov $soreg, r ==> or/add $i,o,r */
8173e12c5d1SDavid du Colombier v = regoff(&p->from);
8183e12c5d1SDavid du Colombier r = p->from.reg;
8193e12c5d1SDavid du Colombier if(r == NREG)
8203e12c5d1SDavid du Colombier r = o->param;
821219b2ee8SDavid du Colombier a = AADDU;
8223e12c5d1SDavid du Colombier if(o->a1 == C_ANDCON)
8233e12c5d1SDavid du Colombier a = AOR;
8243e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(a), v, r, p->to.reg);
8253e12c5d1SDavid du Colombier break;
8263e12c5d1SDavid du Colombier
8273e12c5d1SDavid du Colombier case 4: /* add $scon,[r1],r2 */
8283e12c5d1SDavid du Colombier v = regoff(&p->from);
8293e12c5d1SDavid du Colombier r = p->reg;
8303e12c5d1SDavid du Colombier if(r == NREG)
8313e12c5d1SDavid du Colombier r = p->to.reg;
8323e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(p->as), v, r, p->to.reg);
8333e12c5d1SDavid du Colombier break;
8343e12c5d1SDavid du Colombier
8353e12c5d1SDavid du Colombier case 5: /* syscall */
8363e12c5d1SDavid du Colombier if(aflag)
8373e12c5d1SDavid du Colombier return 0;
8383e12c5d1SDavid du Colombier o1 = oprrr(p->as);
8393e12c5d1SDavid du Colombier break;
8403e12c5d1SDavid du Colombier
8413e12c5d1SDavid du Colombier case 6: /* beq r1,[r2],sbra */
8423e12c5d1SDavid du Colombier if(aflag)
8433e12c5d1SDavid du Colombier return 0;
8443e12c5d1SDavid du Colombier if(p->cond == P)
8453e12c5d1SDavid du Colombier v = -4 >> 2;
8463e12c5d1SDavid du Colombier else
8473e12c5d1SDavid du Colombier v = (p->cond->pc - pc-4) >> 2;
8487dd7cddfSDavid du Colombier if(((v << 16) >> 16) != v)
849406758d9SDavid du Colombier diag("short branch too far: %ld\n%P", v, p);
8503e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
8513e12c5d1SDavid du Colombier break;
8523e12c5d1SDavid du Colombier
8533e12c5d1SDavid du Colombier case 7: /* mov r, soreg ==> sw o(r) */
8543e12c5d1SDavid du Colombier r = p->to.reg;
8553e12c5d1SDavid du Colombier if(r == NREG)
8563e12c5d1SDavid du Colombier r = o->param;
8573e12c5d1SDavid du Colombier v = regoff(&p->to);
8583e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(p->as), v, r, p->from.reg);
8593e12c5d1SDavid du Colombier break;
8603e12c5d1SDavid du Colombier
8613e12c5d1SDavid du Colombier case 8: /* mov soreg, r ==> lw o(r) */
8623e12c5d1SDavid du Colombier r = p->from.reg;
8633e12c5d1SDavid du Colombier if(r == NREG)
8643e12c5d1SDavid du Colombier r = o->param;
8653e12c5d1SDavid du Colombier v = regoff(&p->from);
866219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg);
8673e12c5d1SDavid du Colombier break;
8683e12c5d1SDavid du Colombier
8693e12c5d1SDavid du Colombier case 9: /* asl r1,[r2],r3 */
8703e12c5d1SDavid du Colombier r = p->reg;
8713e12c5d1SDavid du Colombier if(r == NREG)
8723e12c5d1SDavid du Colombier r = p->to.reg;
8733e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
8743e12c5d1SDavid du Colombier break;
8753e12c5d1SDavid du Colombier
8763e12c5d1SDavid du Colombier case 10: /* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */
8773e12c5d1SDavid du Colombier v = regoff(&p->from);
8783e12c5d1SDavid du Colombier r = AOR;
8793e12c5d1SDavid du Colombier if(v < 0)
880219b2ee8SDavid du Colombier r = AADDU;
8813e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(r), v, 0, REGTMP);
8823e12c5d1SDavid du Colombier r = p->reg;
8833e12c5d1SDavid du Colombier if(r == NREG)
8843e12c5d1SDavid du Colombier r = p->to.reg;
8853e12c5d1SDavid du Colombier o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
8863e12c5d1SDavid du Colombier break;
8873e12c5d1SDavid du Colombier
8883e12c5d1SDavid du Colombier case 11: /* jmp lbra */
8893e12c5d1SDavid du Colombier if(aflag)
8903e12c5d1SDavid du Colombier return 0;
8913e12c5d1SDavid du Colombier if(p->cond == P)
8923e12c5d1SDavid du Colombier v = p->pc >> 2;
8933e12c5d1SDavid du Colombier else
8943e12c5d1SDavid du Colombier v = p->cond->pc >> 2;
8953e12c5d1SDavid du Colombier o1 = OP_JMP(opirr(p->as), v);
896219b2ee8SDavid du Colombier if(!debug['Y'] && p->link && p->cond && isnop(p->link)) {
897219b2ee8SDavid du Colombier nop.branch.count--;
898219b2ee8SDavid du Colombier nop.branch.outof--;
899219b2ee8SDavid du Colombier nop.jump.outof++;
9003e12c5d1SDavid du Colombier o2 = asmout(p->cond, oplook(p->cond), 1);
9013e12c5d1SDavid du Colombier if(o2) {
9023e12c5d1SDavid du Colombier o1 += 1;
9033e12c5d1SDavid du Colombier if(debug['a'])
904a587111cSDavid du Colombier Bprint(&bso, " %.8llux: %.8lux %.8lux%P\n",
905219b2ee8SDavid du Colombier p->pc, o1, o2, p);
9063e12c5d1SDavid du Colombier LPUT(o1);
9073e12c5d1SDavid du Colombier LPUT(o2);
9083e12c5d1SDavid du Colombier return 1;
9093e12c5d1SDavid du Colombier }
9103e12c5d1SDavid du Colombier }
9113e12c5d1SDavid du Colombier break;
9123e12c5d1SDavid du Colombier
9133e12c5d1SDavid du Colombier case 12: /* movbs r,r */
9143e12c5d1SDavid du Colombier v = 16;
9153e12c5d1SDavid du Colombier if(p->as == AMOVB)
9163e12c5d1SDavid du Colombier v = 24;
9173e12c5d1SDavid du Colombier o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg);
9183e12c5d1SDavid du Colombier o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg);
9193e12c5d1SDavid du Colombier break;
9203e12c5d1SDavid du Colombier
9213e12c5d1SDavid du Colombier case 13: /* movbu r,r */
9223e12c5d1SDavid du Colombier if(p->as == AMOVBU)
9233e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg);
9243e12c5d1SDavid du Colombier else
9253e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg);
9263e12c5d1SDavid du Colombier break;
9273e12c5d1SDavid du Colombier
9283e12c5d1SDavid du Colombier case 16: /* sll $c,[r1],r2 */
9293e12c5d1SDavid du Colombier v = regoff(&p->from);
9303e12c5d1SDavid du Colombier r = p->reg;
9313e12c5d1SDavid du Colombier if(r == NREG)
9323e12c5d1SDavid du Colombier r = p->to.reg;
933dc5a79c1SDavid du Colombier
934dc5a79c1SDavid du Colombier /* OP_SRR will use only the low 5 bits of the shift value */
935dc5a79c1SDavid du Colombier if(v >= 32 && vshift(p->as))
936219b2ee8SDavid du Colombier o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
937219b2ee8SDavid du Colombier else
9383e12c5d1SDavid du Colombier o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
9393e12c5d1SDavid du Colombier break;
9403e12c5d1SDavid du Colombier
9413e12c5d1SDavid du Colombier case 18: /* jmp [r1],0(r2) */
9423e12c5d1SDavid du Colombier if(aflag)
9433e12c5d1SDavid du Colombier return 0;
9443e12c5d1SDavid du Colombier r = p->reg;
9453e12c5d1SDavid du Colombier if(r == NREG)
9463e12c5d1SDavid du Colombier r = o->param;
9473e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
9483e12c5d1SDavid du Colombier break;
9493e12c5d1SDavid du Colombier
9503e12c5d1SDavid du Colombier case 19: /* mov $lcon,r ==> lu+or */
9513e12c5d1SDavid du Colombier v = regoff(&p->from);
952219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
9533e12c5d1SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg);
9543e12c5d1SDavid du Colombier break;
9553e12c5d1SDavid du Colombier
956219b2ee8SDavid du Colombier case 20: /* mov lohi,r */
957219b2ee8SDavid du Colombier r = OP(2,0); /* mfhi */
9583e12c5d1SDavid du Colombier if(p->from.type == D_LO)
959219b2ee8SDavid du Colombier r = OP(2,2); /* mflo */
960219b2ee8SDavid du Colombier o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg);
9613e12c5d1SDavid du Colombier break;
9623e12c5d1SDavid du Colombier
963219b2ee8SDavid du Colombier case 21: /* mov r,lohi */
964219b2ee8SDavid du Colombier r = OP(2,1); /* mthi */
9653e12c5d1SDavid du Colombier if(p->to.type == D_LO)
966219b2ee8SDavid du Colombier r = OP(2,3); /* mtlo */
967219b2ee8SDavid du Colombier o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO);
9683e12c5d1SDavid du Colombier break;
9693e12c5d1SDavid du Colombier
9703e12c5d1SDavid du Colombier case 22: /* mul r1,r2 */
9713e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO);
9723e12c5d1SDavid du Colombier break;
9733e12c5d1SDavid du Colombier
9743e12c5d1SDavid du Colombier case 23: /* add $lcon,r1,r2 ==> lu+or+add */
9753e12c5d1SDavid du Colombier v = regoff(&p->from);
9763e12c5d1SDavid du Colombier if(p->to.reg == REGTMP || p->reg == REGTMP)
9776b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
978219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
9793e12c5d1SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
9803e12c5d1SDavid du Colombier r = p->reg;
9813e12c5d1SDavid du Colombier if(r == NREG)
9823e12c5d1SDavid du Colombier r = p->to.reg;
9833e12c5d1SDavid du Colombier o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
9843e12c5d1SDavid du Colombier break;
9853e12c5d1SDavid du Colombier
9863e12c5d1SDavid du Colombier case 24: /* mov $ucon,,r ==> lu r */
9873e12c5d1SDavid du Colombier v = regoff(&p->from);
988219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
9893e12c5d1SDavid du Colombier break;
9903e12c5d1SDavid du Colombier
9913e12c5d1SDavid du Colombier case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
9923e12c5d1SDavid du Colombier v = regoff(&p->from);
993219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
9943e12c5d1SDavid du Colombier r = p->reg;
9953e12c5d1SDavid du Colombier if(r == NREG)
9963e12c5d1SDavid du Colombier r = p->to.reg;
9973e12c5d1SDavid du Colombier o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
9983e12c5d1SDavid du Colombier break;
9993e12c5d1SDavid du Colombier
10003e12c5d1SDavid du Colombier case 26: /* mov $lsext/auto/oreg,,r2 ==> lu+or+add */
10013e12c5d1SDavid du Colombier v = regoff(&p->from);
10023e12c5d1SDavid du Colombier if(p->to.reg == REGTMP)
10036b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
1004219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
10053e12c5d1SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
10063e12c5d1SDavid du Colombier r = p->from.reg;
10073e12c5d1SDavid du Colombier if(r == NREG)
10083e12c5d1SDavid du Colombier r = o->param;
1009219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
10103e12c5d1SDavid du Colombier break;
10113e12c5d1SDavid du Colombier
10123e12c5d1SDavid du Colombier case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
10133e12c5d1SDavid du Colombier r = p->from.reg;
10143e12c5d1SDavid du Colombier if(r == NREG)
10153e12c5d1SDavid du Colombier r = o->param;
10163e12c5d1SDavid du Colombier v = regoff(&p->from);
10173e12c5d1SDavid du Colombier switch(o->size) {
1018219b2ee8SDavid du Colombier case 20:
1019219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1020219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1021219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1022219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1);
1023219b2ee8SDavid du Colombier o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg);
10243e12c5d1SDavid du Colombier break;
1025219b2ee8SDavid du Colombier case 16:
1026219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1027219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1028219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1029219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg);
10303e12c5d1SDavid du Colombier break;
10313e12c5d1SDavid du Colombier case 8:
1032219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1);
1033219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg);
10343e12c5d1SDavid du Colombier break;
10353e12c5d1SDavid du Colombier case 4:
1036219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg);
10373e12c5d1SDavid du Colombier break;
10383e12c5d1SDavid du Colombier }
10393e12c5d1SDavid du Colombier break;
10403e12c5d1SDavid du Colombier
10413e12c5d1SDavid du Colombier case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
10423e12c5d1SDavid du Colombier r = p->to.reg;
10433e12c5d1SDavid du Colombier if(r == NREG)
10443e12c5d1SDavid du Colombier r = o->param;
10453e12c5d1SDavid du Colombier v = regoff(&p->to);
10463e12c5d1SDavid du Colombier switch(o->size) {
1047219b2ee8SDavid du Colombier case 20:
1048219b2ee8SDavid du Colombier if(r == REGTMP)
10496b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
1050219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1051219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1052219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1053219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1);
1054219b2ee8SDavid du Colombier o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg);
10553e12c5d1SDavid du Colombier break;
1056219b2ee8SDavid du Colombier case 16:
1057219b2ee8SDavid du Colombier if(r == REGTMP)
10586b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
1059219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1060219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1061219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1062219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg);
10633e12c5d1SDavid du Colombier break;
10643e12c5d1SDavid du Colombier case 8:
10653e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1);
10663e12c5d1SDavid du Colombier o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg);
10673e12c5d1SDavid du Colombier break;
10683e12c5d1SDavid du Colombier case 4:
10693e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg);
10703e12c5d1SDavid du Colombier break;
10713e12c5d1SDavid du Colombier }
10723e12c5d1SDavid du Colombier break;
10733e12c5d1SDavid du Colombier
10743e12c5d1SDavid du Colombier case 30: /* movw r,fr */
1075219b2ee8SDavid du Colombier r = SP(2,1)|(4<<21); /* mtc1 */
1076219b2ee8SDavid du Colombier o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
10773e12c5d1SDavid du Colombier break;
10783e12c5d1SDavid du Colombier
10793e12c5d1SDavid du Colombier case 31: /* movw fr,r */
1080219b2ee8SDavid du Colombier r = SP(2,1)|(0<<21); /* mfc1 */
1081219b2ee8SDavid du Colombier o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
10823e12c5d1SDavid du Colombier break;
10833e12c5d1SDavid du Colombier
10843e12c5d1SDavid du Colombier case 32: /* fadd fr1,[fr2],fr3 */
10853e12c5d1SDavid du Colombier r = p->reg;
10863e12c5d1SDavid du Colombier if(r == NREG)
10873e12c5d1SDavid du Colombier o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg);
10883e12c5d1SDavid du Colombier else
10893e12c5d1SDavid du Colombier o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg);
10903e12c5d1SDavid du Colombier break;
10913e12c5d1SDavid du Colombier
10923e12c5d1SDavid du Colombier case 33: /* fabs fr1,fr3 */
10933e12c5d1SDavid du Colombier o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg);
10943e12c5d1SDavid du Colombier break;
10953e12c5d1SDavid du Colombier
10963e12c5d1SDavid du Colombier case 34: /* mov $con,fr ==> or/add $i,r,r2 */
10973e12c5d1SDavid du Colombier v = regoff(&p->from);
1098219b2ee8SDavid du Colombier r = AADDU;
10993e12c5d1SDavid du Colombier if(o->a1 == C_ANDCON)
11003e12c5d1SDavid du Colombier r = AOR;
11013e12c5d1SDavid du Colombier o1 = OP_IRR(opirr(r), v, 0, REGTMP);
1102219b2ee8SDavid du Colombier o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg); /* mtc1 */
11033e12c5d1SDavid du Colombier break;
11043e12c5d1SDavid du Colombier
11053e12c5d1SDavid du Colombier case 35: /* mov r,lext/luto/oreg ==> sw o(r) */
1106219b2ee8SDavid du Colombier /*
1107219b2ee8SDavid du Colombier * the lowbits of the constant cannot
1108219b2ee8SDavid du Colombier * be moved into the offset of the load
1109219b2ee8SDavid du Colombier * because the mips 4000 in 64-bit mode
1110219b2ee8SDavid du Colombier * does a 64-bit add and it will screw up.
1111219b2ee8SDavid du Colombier */
11123e12c5d1SDavid du Colombier v = regoff(&p->to);
11133e12c5d1SDavid du Colombier r = p->to.reg;
11143e12c5d1SDavid du Colombier if(r == NREG)
11153e12c5d1SDavid du Colombier r = o->param;
1116219b2ee8SDavid du Colombier if(r == REGTMP)
11176b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
1118219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1119219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1120219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1121219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
11223e12c5d1SDavid du Colombier break;
11233e12c5d1SDavid du Colombier
11243e12c5d1SDavid du Colombier case 36: /* mov lext/lauto/lreg,r ==> lw o(r30) */
11253e12c5d1SDavid du Colombier v = regoff(&p->from);
11263e12c5d1SDavid du Colombier r = p->from.reg;
11273e12c5d1SDavid du Colombier if(r == NREG)
11283e12c5d1SDavid du Colombier r = o->param;
1129219b2ee8SDavid du Colombier if(r == REGTMP)
11306b6b9ac8SDavid du Colombier diag("cant synthesize large constant\n%P", p);
1131219b2ee8SDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1132219b2ee8SDavid du Colombier o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1133219b2ee8SDavid du Colombier o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1134219b2ee8SDavid du Colombier o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
11353e12c5d1SDavid du Colombier break;
11363e12c5d1SDavid du Colombier
11373e12c5d1SDavid du Colombier case 37: /* movw r,mr */
1138219b2ee8SDavid du Colombier r = SP(2,0)|(4<<21); /* mtc0 */
1139219b2ee8SDavid du Colombier if(p->as == AMOVV)
1140219b2ee8SDavid du Colombier r = SP(2,0)|(5<<21); /* dmtc0 */
1141219b2ee8SDavid du Colombier o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
11423e12c5d1SDavid du Colombier break;
11433e12c5d1SDavid du Colombier
11443e12c5d1SDavid du Colombier case 38: /* movw mr,r */
1145219b2ee8SDavid du Colombier r = SP(2,0)|(0<<21); /* mfc0 */
1146219b2ee8SDavid du Colombier if(p->as == AMOVV)
1147219b2ee8SDavid du Colombier r = SP(2,0)|(1<<21); /* dmfc0 */
1148219b2ee8SDavid du Colombier o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
11493e12c5d1SDavid du Colombier break;
11503e12c5d1SDavid du Colombier
11513e12c5d1SDavid du Colombier case 39: /* rfe ==> jmp+rfe */
11523e12c5d1SDavid du Colombier if(aflag)
11533e12c5d1SDavid du Colombier return 0;
11543e12c5d1SDavid du Colombier o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO);
11553e12c5d1SDavid du Colombier o2 = oprrr(p->as);
11563e12c5d1SDavid du Colombier break;
11573e12c5d1SDavid du Colombier
11583e12c5d1SDavid du Colombier case 40: /* word */
11593e12c5d1SDavid du Colombier if(aflag)
11603e12c5d1SDavid du Colombier return 0;
11613e12c5d1SDavid du Colombier o1 = regoff(&p->to);
11623e12c5d1SDavid du Colombier break;
11633e12c5d1SDavid du Colombier
11643e12c5d1SDavid du Colombier case 41: /* movw r,fcr */
1165219b2ee8SDavid du Colombier o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg); /* mfcc1 */
1166219b2ee8SDavid du Colombier o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */
11673e12c5d1SDavid du Colombier break;
11683e12c5d1SDavid du Colombier
11693e12c5d1SDavid du Colombier case 42: /* movw fcr,r */
1170219b2ee8SDavid du Colombier o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
11713e12c5d1SDavid du Colombier break;
11727dd7cddfSDavid du Colombier
11737dd7cddfSDavid du Colombier case 45: /* case r */
11747dd7cddfSDavid du Colombier if(p->link == P)
11757dd7cddfSDavid du Colombier v = p->pc+28;
11767dd7cddfSDavid du Colombier else
11777dd7cddfSDavid du Colombier v = p->link->pc;
11787dd7cddfSDavid du Colombier if(v & (1<<15))
11797dd7cddfSDavid du Colombier o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
11807dd7cddfSDavid du Colombier else
11817dd7cddfSDavid du Colombier o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
11827dd7cddfSDavid du Colombier o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
11837dd7cddfSDavid du Colombier o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
11847dd7cddfSDavid du Colombier o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
11857dd7cddfSDavid du Colombier o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
11867dd7cddfSDavid du Colombier o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
11877dd7cddfSDavid du Colombier o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
11887dd7cddfSDavid du Colombier break;
11897dd7cddfSDavid du Colombier
11907dd7cddfSDavid du Colombier case 46: /* bcase $con,lbra */
11917dd7cddfSDavid du Colombier if(p->cond == P)
11927dd7cddfSDavid du Colombier v = p->pc;
11937dd7cddfSDavid du Colombier else
11947dd7cddfSDavid du Colombier v = p->cond->pc;
11957dd7cddfSDavid du Colombier o1 = v;
11967dd7cddfSDavid du Colombier break;
11973e12c5d1SDavid du Colombier }
11983e12c5d1SDavid du Colombier if(aflag)
11993e12c5d1SDavid du Colombier return o1;
12003e12c5d1SDavid du Colombier v = p->pc;
12013e12c5d1SDavid du Colombier switch(o->size) {
12023e12c5d1SDavid du Colombier default:
12033e12c5d1SDavid du Colombier if(debug['a'])
12043e12c5d1SDavid du Colombier Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
12053e12c5d1SDavid du Colombier break;
12063e12c5d1SDavid du Colombier case 4:
12073e12c5d1SDavid du Colombier if(debug['a'])
12083e12c5d1SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
12093e12c5d1SDavid du Colombier LPUT(o1);
12103e12c5d1SDavid du Colombier break;
12113e12c5d1SDavid du Colombier case 8:
12123e12c5d1SDavid du Colombier if(debug['a'])
12133e12c5d1SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
12143e12c5d1SDavid du Colombier LPUT(o1);
12153e12c5d1SDavid du Colombier LPUT(o2);
12163e12c5d1SDavid du Colombier break;
12173e12c5d1SDavid du Colombier case 12:
12183e12c5d1SDavid du Colombier if(debug['a'])
12193e12c5d1SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
12203e12c5d1SDavid du Colombier LPUT(o1);
12213e12c5d1SDavid du Colombier LPUT(o2);
12223e12c5d1SDavid du Colombier LPUT(o3);
12233e12c5d1SDavid du Colombier break;
12243e12c5d1SDavid du Colombier case 16:
12253e12c5d1SDavid du Colombier if(debug['a'])
12263e12c5d1SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
12273e12c5d1SDavid du Colombier v, o1, o2, o3, o4, p);
12283e12c5d1SDavid du Colombier LPUT(o1);
12293e12c5d1SDavid du Colombier LPUT(o2);
12303e12c5d1SDavid du Colombier LPUT(o3);
12313e12c5d1SDavid du Colombier LPUT(o4);
12323e12c5d1SDavid du Colombier break;
1233219b2ee8SDavid du Colombier case 20:
1234219b2ee8SDavid du Colombier if(debug['a'])
1235219b2ee8SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1236219b2ee8SDavid du Colombier v, o1, o2, o3, o4, o5, p);
1237219b2ee8SDavid du Colombier LPUT(o1);
1238219b2ee8SDavid du Colombier LPUT(o2);
1239219b2ee8SDavid du Colombier LPUT(o3);
1240219b2ee8SDavid du Colombier LPUT(o4);
1241219b2ee8SDavid du Colombier LPUT(o5);
1242219b2ee8SDavid du Colombier break;
12437dd7cddfSDavid du Colombier
12447dd7cddfSDavid du Colombier case 28:
12457dd7cddfSDavid du Colombier if(debug['a'])
12467dd7cddfSDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
12477dd7cddfSDavid du Colombier v, o1, o2, o3, o4, o5, o6, o7, p);
12487dd7cddfSDavid du Colombier LPUT(o1);
12497dd7cddfSDavid du Colombier LPUT(o2);
12507dd7cddfSDavid du Colombier LPUT(o3);
12517dd7cddfSDavid du Colombier LPUT(o4);
12527dd7cddfSDavid du Colombier LPUT(o5);
12537dd7cddfSDavid du Colombier LPUT(o6);
12547dd7cddfSDavid du Colombier LPUT(o7);
12557dd7cddfSDavid du Colombier break;
12563e12c5d1SDavid du Colombier }
12573e12c5d1SDavid du Colombier return 0;
12583e12c5d1SDavid du Colombier }
12593e12c5d1SDavid du Colombier
1260219b2ee8SDavid du Colombier int
isnop(Prog * p)1261219b2ee8SDavid du Colombier isnop(Prog *p)
1262219b2ee8SDavid du Colombier {
1263219b2ee8SDavid du Colombier if(p->as != ANOR)
1264219b2ee8SDavid du Colombier return 0;
1265219b2ee8SDavid du Colombier if(p->reg != REGZERO && p->reg != NREG)
1266219b2ee8SDavid du Colombier return 0;
1267219b2ee8SDavid du Colombier if(p->from.type != D_REG || p->from.reg != REGZERO)
1268219b2ee8SDavid du Colombier return 0;
1269219b2ee8SDavid du Colombier if(p->to.type != D_REG || p->to.reg != REGZERO)
1270219b2ee8SDavid du Colombier return 0;
1271219b2ee8SDavid du Colombier return 1;
1272219b2ee8SDavid du Colombier }
12733e12c5d1SDavid du Colombier
12743e12c5d1SDavid du Colombier long
oprrr(int a)12753e12c5d1SDavid du Colombier oprrr(int a)
12763e12c5d1SDavid du Colombier {
12773e12c5d1SDavid du Colombier switch(a) {
12783e12c5d1SDavid du Colombier case AADD: return OP(4,0);
12793e12c5d1SDavid du Colombier case AADDU: return OP(4,1);
12803e12c5d1SDavid du Colombier case ASGT: return OP(5,2);
12813e12c5d1SDavid du Colombier case ASGTU: return OP(5,3);
12823e12c5d1SDavid du Colombier case AAND: return OP(4,4);
12833e12c5d1SDavid du Colombier case AOR: return OP(4,5);
12843e12c5d1SDavid du Colombier case AXOR: return OP(4,6);
12853e12c5d1SDavid du Colombier case ASUB: return OP(4,2);
12863e12c5d1SDavid du Colombier case ASUBU: return OP(4,3);
12873e12c5d1SDavid du Colombier case ANOR: return OP(4,7);
12883e12c5d1SDavid du Colombier case ASLL: return OP(0,4);
12893e12c5d1SDavid du Colombier case ASRL: return OP(0,6);
12903e12c5d1SDavid du Colombier case ASRA: return OP(0,7);
12913e12c5d1SDavid du Colombier
12923e12c5d1SDavid du Colombier case AREM:
12933e12c5d1SDavid du Colombier case ADIV: return OP(3,2);
12943e12c5d1SDavid du Colombier case AREMU:
12953e12c5d1SDavid du Colombier case ADIVU: return OP(3,3);
12963e12c5d1SDavid du Colombier case AMUL: return OP(3,0);
12973e12c5d1SDavid du Colombier case AMULU: return OP(3,1);
12983e12c5d1SDavid du Colombier
12993e12c5d1SDavid du Colombier case AJMP: return OP(1,0);
13003e12c5d1SDavid du Colombier case AJAL: return OP(1,1);
13013e12c5d1SDavid du Colombier
13023e12c5d1SDavid du Colombier case ABREAK: return OP(1,5);
13033e12c5d1SDavid du Colombier case ASYSCALL: return OP(1,4);
13043e12c5d1SDavid du Colombier case ATLBP: return MMU(1,0);
13053e12c5d1SDavid du Colombier case ATLBR: return MMU(0,1);
13063e12c5d1SDavid du Colombier case ATLBWI: return MMU(0,2);
13073e12c5d1SDavid du Colombier case ATLBWR: return MMU(0,6);
13083e12c5d1SDavid du Colombier case ARFE: return MMU(2,0);
13093e12c5d1SDavid du Colombier
13103e12c5d1SDavid du Colombier case ADIVF: return FPF(0,3);
13113e12c5d1SDavid du Colombier case ADIVD: return FPD(0,3);
13123e12c5d1SDavid du Colombier case AMULF: return FPF(0,2);
13133e12c5d1SDavid du Colombier case AMULD: return FPD(0,2);
13143e12c5d1SDavid du Colombier case ASUBF: return FPF(0,1);
13153e12c5d1SDavid du Colombier case ASUBD: return FPD(0,1);
13163e12c5d1SDavid du Colombier case AADDF: return FPF(0,0);
13173e12c5d1SDavid du Colombier case AADDD: return FPD(0,0);
13183e12c5d1SDavid du Colombier
13193e12c5d1SDavid du Colombier case AMOVFW: return FPF(4,4);
13203e12c5d1SDavid du Colombier case AMOVDW: return FPD(4,4);
13213e12c5d1SDavid du Colombier case AMOVWF: return FPW(4,0);
13223e12c5d1SDavid du Colombier case AMOVDF: return FPD(4,0);
13233e12c5d1SDavid du Colombier case AMOVWD: return FPW(4,1);
13243e12c5d1SDavid du Colombier case AMOVFD: return FPF(4,1);
13253e12c5d1SDavid du Colombier case AABSF: return FPF(0,5);
13263e12c5d1SDavid du Colombier case AABSD: return FPD(0,5);
13273e12c5d1SDavid du Colombier case AMOVF: return FPF(0,6);
13283e12c5d1SDavid du Colombier case AMOVD: return FPD(0,6);
13293e12c5d1SDavid du Colombier case ANEGF: return FPF(0,7);
13303e12c5d1SDavid du Colombier case ANEGD: return FPD(0,7);
13313e12c5d1SDavid du Colombier
13323e12c5d1SDavid du Colombier case ACMPEQF: return FPF(6,2);
13333e12c5d1SDavid du Colombier case ACMPEQD: return FPD(6,2);
13343e12c5d1SDavid du Colombier case ACMPGTF: return FPF(7,4);
13353e12c5d1SDavid du Colombier case ACMPGTD: return FPD(7,4);
13363e12c5d1SDavid du Colombier case ACMPGEF: return FPF(7,6);
13373e12c5d1SDavid du Colombier case ACMPGED: return FPD(7,6);
13387dd7cddfSDavid du Colombier
13397dd7cddfSDavid du Colombier case ADIVV: return OP(3,6);
13407dd7cddfSDavid du Colombier case ADIVVU: return OP(3,7);
13417dd7cddfSDavid du Colombier case AADDV: return OP(5,4);
13427dd7cddfSDavid du Colombier case AADDVU: return OP(5,5);
13433e12c5d1SDavid du Colombier }
13446b6b9ac8SDavid du Colombier diag("bad rrr %d", a);
13453e12c5d1SDavid du Colombier return 0;
13463e12c5d1SDavid du Colombier }
13473e12c5d1SDavid du Colombier
13483e12c5d1SDavid du Colombier long
opirr(int a)13493e12c5d1SDavid du Colombier opirr(int a)
13503e12c5d1SDavid du Colombier {
13513e12c5d1SDavid du Colombier switch(a) {
13523e12c5d1SDavid du Colombier case AADD: return SP(1,0);
13533e12c5d1SDavid du Colombier case AADDU: return SP(1,1);
13543e12c5d1SDavid du Colombier case ASGT: return SP(1,2);
13553e12c5d1SDavid du Colombier case ASGTU: return SP(1,3);
13563e12c5d1SDavid du Colombier case AAND: return SP(1,4);
13573e12c5d1SDavid du Colombier case AOR: return SP(1,5);
13583e12c5d1SDavid du Colombier case AXOR: return SP(1,6);
1359219b2ee8SDavid du Colombier case ALAST: return SP(1,7);
13603e12c5d1SDavid du Colombier case ASLL: return OP(0,0);
13613e12c5d1SDavid du Colombier case ASRL: return OP(0,2);
13623e12c5d1SDavid du Colombier case ASRA: return OP(0,3);
13633e12c5d1SDavid du Colombier
13643e12c5d1SDavid du Colombier case AJMP: return SP(0,2);
13653e12c5d1SDavid du Colombier case AJAL: return SP(0,3);
13663e12c5d1SDavid du Colombier case ABEQ: return SP(0,4);
13673e12c5d1SDavid du Colombier case ABNE: return SP(0,5);
13683e12c5d1SDavid du Colombier
13693e12c5d1SDavid du Colombier case ABGEZ: return SP(0,1)|BCOND(0,1);
13703e12c5d1SDavid du Colombier case ABGEZAL: return SP(0,1)|BCOND(2,1);
13713e12c5d1SDavid du Colombier case ABGTZ: return SP(0,7);
13723e12c5d1SDavid du Colombier case ABLEZ: return SP(0,6);
13733e12c5d1SDavid du Colombier case ABLTZ: return SP(0,1)|BCOND(0,0);
13743e12c5d1SDavid du Colombier case ABLTZAL: return SP(0,1)|BCOND(2,0);
13753e12c5d1SDavid du Colombier
13763e12c5d1SDavid du Colombier case ABFPT: return SP(2,1)|(257<<16);
13773e12c5d1SDavid du Colombier case ABFPF: return SP(2,1)|(256<<16);
13783e12c5d1SDavid du Colombier
13793e12c5d1SDavid du Colombier case AMOVB:
13803e12c5d1SDavid du Colombier case AMOVBU: return SP(5,0);
13813e12c5d1SDavid du Colombier case AMOVH:
13823e12c5d1SDavid du Colombier case AMOVHU: return SP(5,1);
13833e12c5d1SDavid du Colombier case AMOVW: return SP(5,3);
1384219b2ee8SDavid du Colombier case AMOVV: return SP(7,7);
13853e12c5d1SDavid du Colombier case AMOVF: return SP(7,1);
13863e12c5d1SDavid du Colombier case AMOVWL: return SP(5,2);
13873e12c5d1SDavid du Colombier case AMOVWR: return SP(5,6);
1388219b2ee8SDavid du Colombier case AMOVVL: return SP(5,4);
1389219b2ee8SDavid du Colombier case AMOVVR: return SP(5,5);
13903e12c5d1SDavid du Colombier
1391bd389b36SDavid du Colombier case ABREAK: return SP(5,7);
1392bd389b36SDavid du Colombier
1393219b2ee8SDavid du Colombier case AMOVWL+ALAST: return SP(4,2);
1394219b2ee8SDavid du Colombier case AMOVWR+ALAST: return SP(4,6);
1395219b2ee8SDavid du Colombier case AMOVVL+ALAST: return SP(3,2);
1396219b2ee8SDavid du Colombier case AMOVVR+ALAST: return SP(3,3);
1397219b2ee8SDavid du Colombier case AMOVB+ALAST: return SP(4,0);
1398219b2ee8SDavid du Colombier case AMOVBU+ALAST: return SP(4,4);
1399219b2ee8SDavid du Colombier case AMOVH+ALAST: return SP(4,1);
1400219b2ee8SDavid du Colombier case AMOVHU+ALAST: return SP(4,5);
1401219b2ee8SDavid du Colombier case AMOVW+ALAST: return SP(4,3);
1402219b2ee8SDavid du Colombier case AMOVV+ALAST: return SP(6,7);
1403219b2ee8SDavid du Colombier case AMOVF+ALAST: return SP(6,1);
14043e12c5d1SDavid du Colombier
1405219b2ee8SDavid du Colombier case ASLLV: return OP(7,0);
1406219b2ee8SDavid du Colombier case ASRLV: return OP(7,2);
1407219b2ee8SDavid du Colombier case ASRAV: return OP(7,3);
1408219b2ee8SDavid du Colombier case ASLLV+ALAST: return OP(7,4);
1409219b2ee8SDavid du Colombier case ASRLV+ALAST: return OP(7,6);
1410219b2ee8SDavid du Colombier case ASRAV+ALAST: return OP(7,7);
14117dd7cddfSDavid du Colombier
14127dd7cddfSDavid du Colombier case AADDV: return SP(3,0);
14137dd7cddfSDavid du Colombier case AADDVU: return SP(3,1);
14143e12c5d1SDavid du Colombier }
14156b6b9ac8SDavid du Colombier diag("bad irr %d", a);
1416dc5a79c1SDavid du Colombier abort();
1417dc5a79c1SDavid du Colombier return 0;
1418dc5a79c1SDavid du Colombier }
1419dc5a79c1SDavid du Colombier
1420dc5a79c1SDavid du Colombier int
vshift(int a)1421dc5a79c1SDavid du Colombier vshift(int a)
1422dc5a79c1SDavid du Colombier {
1423dc5a79c1SDavid du Colombier switch(a){
1424dc5a79c1SDavid du Colombier case ASLLV: return 1;
1425dc5a79c1SDavid du Colombier case ASRLV: return 1;
1426dc5a79c1SDavid du Colombier case ASRAV: return 1;
1427dc5a79c1SDavid du Colombier }
14283e12c5d1SDavid du Colombier return 0;
14293e12c5d1SDavid du Colombier }
1430