1*ce95e1b3SDavid du Colombier #include "l.h"
2*ce95e1b3SDavid du Colombier
3*ce95e1b3SDavid du Colombier long OFFSET;
4*ce95e1b3SDavid du Colombier
5*ce95e1b3SDavid du Colombier xlong
entryvalue(void)6*ce95e1b3SDavid du Colombier entryvalue(void)
7*ce95e1b3SDavid du Colombier {
8*ce95e1b3SDavid du Colombier char *a;
9*ce95e1b3SDavid du Colombier Sym *s;
10*ce95e1b3SDavid du Colombier
11*ce95e1b3SDavid du Colombier a = INITENTRY;
12*ce95e1b3SDavid du Colombier if(*a >= '0' && *a <= '9')
13*ce95e1b3SDavid du Colombier return atolwhex(a);
14*ce95e1b3SDavid du Colombier s = lookup(a, 0);
15*ce95e1b3SDavid du Colombier if(s->type == 0)
16*ce95e1b3SDavid du Colombier return INITTEXT;
17*ce95e1b3SDavid du Colombier if(s->type != STEXT && s->type != SLEAF)
18*ce95e1b3SDavid du Colombier diag("entry not text: %s", s->name);
19*ce95e1b3SDavid du Colombier return s->value + INITTEXT;
20*ce95e1b3SDavid du Colombier }
21*ce95e1b3SDavid du Colombier
22*ce95e1b3SDavid du Colombier void
asmb(void)23*ce95e1b3SDavid du Colombier asmb(void)
24*ce95e1b3SDavid du Colombier {
25*ce95e1b3SDavid du Colombier Prog *p;
26*ce95e1b3SDavid du Colombier long t, etext;
27*ce95e1b3SDavid du Colombier Optab *o;
28*ce95e1b3SDavid du Colombier
29*ce95e1b3SDavid du Colombier if(debug['v'])
30*ce95e1b3SDavid du Colombier Bprint(&bso, "%5.2f asm\n", cputime());
31*ce95e1b3SDavid du Colombier Bflush(&bso);
32*ce95e1b3SDavid du Colombier OFFSET = HEADR;
33*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
34*ce95e1b3SDavid du Colombier pc = 0;
35*ce95e1b3SDavid du Colombier for(p = firstp; p != P; p = p->link) {
36*ce95e1b3SDavid du Colombier if(p->as == ATEXT) {
37*ce95e1b3SDavid du Colombier /* align on word boundary */
38*ce95e1b3SDavid du Colombier if(!debug['c'] && (pc & 2) != 0){
39*ce95e1b3SDavid du Colombier nopalign.pc = pc;
40*ce95e1b3SDavid du Colombier pc += asmout(&nopalign, oplook(&nopalign), 0);
41*ce95e1b3SDavid du Colombier }
42*ce95e1b3SDavid du Colombier curtext = p;
43*ce95e1b3SDavid du Colombier autosize = p->to.offset + ptrsize;
44*ce95e1b3SDavid du Colombier }
45*ce95e1b3SDavid du Colombier if(p->pc != pc) {
46*ce95e1b3SDavid du Colombier diag("phase error %lux sb %lux",
47*ce95e1b3SDavid du Colombier p->pc, pc);
48*ce95e1b3SDavid du Colombier if(!debug['a'])
49*ce95e1b3SDavid du Colombier prasm(curp);
50*ce95e1b3SDavid du Colombier pc = p->pc;
51*ce95e1b3SDavid du Colombier }
52*ce95e1b3SDavid du Colombier curp = p;
53*ce95e1b3SDavid du Colombier o = oplook(p); /* could probably avoid this call */
54*ce95e1b3SDavid du Colombier pc += asmout(p, o, 0);
55*ce95e1b3SDavid du Colombier }
56*ce95e1b3SDavid du Colombier if(debug['a'])
57*ce95e1b3SDavid du Colombier Bprint(&bso, "\n");
58*ce95e1b3SDavid du Colombier Bflush(&bso);
59*ce95e1b3SDavid du Colombier cflush();
60*ce95e1b3SDavid du Colombier
61*ce95e1b3SDavid du Colombier etext = textsize;
62*ce95e1b3SDavid du Colombier for(t = pc; t < etext; t += sizeof(buf)-100) {
63*ce95e1b3SDavid du Colombier if(etext-t > sizeof(buf)-100)
64*ce95e1b3SDavid du Colombier datblk(t, sizeof(buf)-100, 1);
65*ce95e1b3SDavid du Colombier else
66*ce95e1b3SDavid du Colombier datblk(t, etext-t, 1);
67*ce95e1b3SDavid du Colombier }
68*ce95e1b3SDavid du Colombier
69*ce95e1b3SDavid du Colombier Bflush(&bso);
70*ce95e1b3SDavid du Colombier cflush();
71*ce95e1b3SDavid du Colombier
72*ce95e1b3SDavid du Colombier curtext = P;
73*ce95e1b3SDavid du Colombier switch(HEADTYPE) {
74*ce95e1b3SDavid du Colombier case 0:
75*ce95e1b3SDavid du Colombier case 4:
76*ce95e1b3SDavid du Colombier OFFSET = rnd(HEADR+textsize, 4096);
77*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
78*ce95e1b3SDavid du Colombier break;
79*ce95e1b3SDavid du Colombier case 1:
80*ce95e1b3SDavid du Colombier case 2:
81*ce95e1b3SDavid du Colombier case 3:
82*ce95e1b3SDavid du Colombier case 5:
83*ce95e1b3SDavid du Colombier case 6:
84*ce95e1b3SDavid du Colombier OFFSET = HEADR+textsize;
85*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
86*ce95e1b3SDavid du Colombier break;
87*ce95e1b3SDavid du Colombier }
88*ce95e1b3SDavid du Colombier for(t = 0; t < datsize; t += sizeof(buf)-100) {
89*ce95e1b3SDavid du Colombier if(datsize-t > sizeof(buf)-100)
90*ce95e1b3SDavid du Colombier datblk(t, sizeof(buf)-100, 0);
91*ce95e1b3SDavid du Colombier else
92*ce95e1b3SDavid du Colombier datblk(t, datsize-t, 0);
93*ce95e1b3SDavid du Colombier }
94*ce95e1b3SDavid du Colombier
95*ce95e1b3SDavid du Colombier symsize = 0;
96*ce95e1b3SDavid du Colombier lcsize = 0;
97*ce95e1b3SDavid du Colombier if(!debug['s']) {
98*ce95e1b3SDavid du Colombier if(debug['v'])
99*ce95e1b3SDavid du Colombier Bprint(&bso, "%5.2f sym\n", cputime());
100*ce95e1b3SDavid du Colombier Bflush(&bso);
101*ce95e1b3SDavid du Colombier switch(HEADTYPE) {
102*ce95e1b3SDavid du Colombier case 0:
103*ce95e1b3SDavid du Colombier case 4:
104*ce95e1b3SDavid du Colombier OFFSET = rnd(HEADR+textsize, 4096)+datsize;
105*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
106*ce95e1b3SDavid du Colombier break;
107*ce95e1b3SDavid du Colombier case 3:
108*ce95e1b3SDavid du Colombier case 2:
109*ce95e1b3SDavid du Colombier case 1:
110*ce95e1b3SDavid du Colombier case 5:
111*ce95e1b3SDavid du Colombier case 6:
112*ce95e1b3SDavid du Colombier OFFSET = HEADR+textsize+datsize;
113*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
114*ce95e1b3SDavid du Colombier break;
115*ce95e1b3SDavid du Colombier }
116*ce95e1b3SDavid du Colombier if(!debug['s'])
117*ce95e1b3SDavid du Colombier asmsym();
118*ce95e1b3SDavid du Colombier if(debug['v'])
119*ce95e1b3SDavid du Colombier Bprint(&bso, "%5.2f pc\n", cputime());
120*ce95e1b3SDavid du Colombier Bflush(&bso);
121*ce95e1b3SDavid du Colombier if(!debug['s'])
122*ce95e1b3SDavid du Colombier asmlc();
123*ce95e1b3SDavid du Colombier cflush();
124*ce95e1b3SDavid du Colombier }
125*ce95e1b3SDavid du Colombier
126*ce95e1b3SDavid du Colombier if(debug['v'])
127*ce95e1b3SDavid du Colombier Bprint(&bso, "%5.2f header\n", cputime());
128*ce95e1b3SDavid du Colombier Bflush(&bso);
129*ce95e1b3SDavid du Colombier OFFSET = 0;
130*ce95e1b3SDavid du Colombier seek(cout, OFFSET, 0);
131*ce95e1b3SDavid du Colombier switch(HEADTYPE) {
132*ce95e1b3SDavid du Colombier case 1:
133*ce95e1b3SDavid du Colombier break;
134*ce95e1b3SDavid du Colombier case 2:
135*ce95e1b3SDavid du Colombier /* XXX expanded header needed? */
136*ce95e1b3SDavid du Colombier t = thechar == 'j' ? 30 : 29;
137*ce95e1b3SDavid du Colombier lput(((((4*t)+0)*t)+7)); /* magic */
138*ce95e1b3SDavid du Colombier lput(textsize); /* sizes */
139*ce95e1b3SDavid du Colombier lput(datsize);
140*ce95e1b3SDavid du Colombier lput(bsssize);
141*ce95e1b3SDavid du Colombier lput(symsize); /* nsyms */
142*ce95e1b3SDavid du Colombier lput(entryvalue()); /* va of entry */
143*ce95e1b3SDavid du Colombier lput(0L);
144*ce95e1b3SDavid du Colombier lput(lcsize);
145*ce95e1b3SDavid du Colombier break;
146*ce95e1b3SDavid du Colombier case 5:
147*ce95e1b3SDavid du Colombier if(thechar == 'j')
148*ce95e1b3SDavid du Colombier elf64(243, ELFDATA2LSB, 0, nil); /* 243 is RISCV */
149*ce95e1b3SDavid du Colombier else
150*ce95e1b3SDavid du Colombier elf32(243, ELFDATA2LSB, 0, nil);
151*ce95e1b3SDavid du Colombier }
152*ce95e1b3SDavid du Colombier cflush();
153*ce95e1b3SDavid du Colombier }
154*ce95e1b3SDavid du Colombier
155*ce95e1b3SDavid du Colombier void
strnput(char * s,int n)156*ce95e1b3SDavid du Colombier strnput(char *s, int n)
157*ce95e1b3SDavid du Colombier {
158*ce95e1b3SDavid du Colombier for(; *s; s++){
159*ce95e1b3SDavid du Colombier cput(*s);
160*ce95e1b3SDavid du Colombier n--;
161*ce95e1b3SDavid du Colombier }
162*ce95e1b3SDavid du Colombier for(; n > 0; n--)
163*ce95e1b3SDavid du Colombier cput(0);
164*ce95e1b3SDavid du Colombier }
165*ce95e1b3SDavid du Colombier
166*ce95e1b3SDavid du Colombier void
cput(int c)167*ce95e1b3SDavid du Colombier cput(int c)
168*ce95e1b3SDavid du Colombier {
169*ce95e1b3SDavid du Colombier cbp[0] = c;
170*ce95e1b3SDavid du Colombier cbp++;
171*ce95e1b3SDavid du Colombier cbc--;
172*ce95e1b3SDavid du Colombier if(cbc <= 0)
173*ce95e1b3SDavid du Colombier cflush();
174*ce95e1b3SDavid du Colombier }
175*ce95e1b3SDavid du Colombier
176*ce95e1b3SDavid du Colombier void
wput(long l)177*ce95e1b3SDavid du Colombier wput(long l)
178*ce95e1b3SDavid du Colombier {
179*ce95e1b3SDavid du Colombier
180*ce95e1b3SDavid du Colombier cbp[0] = l>>8;
181*ce95e1b3SDavid du Colombier cbp[1] = l;
182*ce95e1b3SDavid du Colombier cbp += 2;
183*ce95e1b3SDavid du Colombier cbc -= 2;
184*ce95e1b3SDavid du Colombier if(cbc <= 0)
185*ce95e1b3SDavid du Colombier cflush();
186*ce95e1b3SDavid du Colombier }
187*ce95e1b3SDavid du Colombier
188*ce95e1b3SDavid du Colombier void
wputl(long l)189*ce95e1b3SDavid du Colombier wputl(long l)
190*ce95e1b3SDavid du Colombier {
191*ce95e1b3SDavid du Colombier
192*ce95e1b3SDavid du Colombier cbp[0] = l;
193*ce95e1b3SDavid du Colombier cbp[1] = l>>8;
194*ce95e1b3SDavid du Colombier cbp += 2;
195*ce95e1b3SDavid du Colombier cbc -= 2;
196*ce95e1b3SDavid du Colombier if(cbc <= 0)
197*ce95e1b3SDavid du Colombier cflush();
198*ce95e1b3SDavid du Colombier }
199*ce95e1b3SDavid du Colombier
200*ce95e1b3SDavid du Colombier void
lput(long l)201*ce95e1b3SDavid du Colombier lput(long l)
202*ce95e1b3SDavid du Colombier {
203*ce95e1b3SDavid du Colombier
204*ce95e1b3SDavid du Colombier cbp[0] = l>>24;
205*ce95e1b3SDavid du Colombier cbp[1] = l>>16;
206*ce95e1b3SDavid du Colombier cbp[2] = l>>8;
207*ce95e1b3SDavid du Colombier cbp[3] = l;
208*ce95e1b3SDavid du Colombier cbp += 4;
209*ce95e1b3SDavid du Colombier cbc -= 4;
210*ce95e1b3SDavid du Colombier if(cbc <= 0)
211*ce95e1b3SDavid du Colombier cflush();
212*ce95e1b3SDavid du Colombier }
213*ce95e1b3SDavid du Colombier
214*ce95e1b3SDavid du Colombier void
lputl(long l)215*ce95e1b3SDavid du Colombier lputl(long l)
216*ce95e1b3SDavid du Colombier {
217*ce95e1b3SDavid du Colombier
218*ce95e1b3SDavid du Colombier cbp[3] = l>>24;
219*ce95e1b3SDavid du Colombier cbp[2] = l>>16;
220*ce95e1b3SDavid du Colombier cbp[1] = l>>8;
221*ce95e1b3SDavid du Colombier cbp[0] = l;
222*ce95e1b3SDavid du Colombier cbp += 4;
223*ce95e1b3SDavid du Colombier cbc -= 4;
224*ce95e1b3SDavid du Colombier if(cbc <= 0)
225*ce95e1b3SDavid du Colombier cflush();
226*ce95e1b3SDavid du Colombier }
227*ce95e1b3SDavid du Colombier
228*ce95e1b3SDavid du Colombier void
llput(vlong v)229*ce95e1b3SDavid du Colombier llput(vlong v)
230*ce95e1b3SDavid du Colombier {
231*ce95e1b3SDavid du Colombier lput(v>>32);
232*ce95e1b3SDavid du Colombier lput(v);
233*ce95e1b3SDavid du Colombier }
234*ce95e1b3SDavid du Colombier
235*ce95e1b3SDavid du Colombier void
llputl(vlong v)236*ce95e1b3SDavid du Colombier llputl(vlong v)
237*ce95e1b3SDavid du Colombier {
238*ce95e1b3SDavid du Colombier lputl(v);
239*ce95e1b3SDavid du Colombier lputl(v>>32);
240*ce95e1b3SDavid du Colombier }
241*ce95e1b3SDavid du Colombier
242*ce95e1b3SDavid du Colombier void
cflush(void)243*ce95e1b3SDavid du Colombier cflush(void)
244*ce95e1b3SDavid du Colombier {
245*ce95e1b3SDavid du Colombier int n;
246*ce95e1b3SDavid du Colombier
247*ce95e1b3SDavid du Colombier n = sizeof(buf.cbuf) - cbc;
248*ce95e1b3SDavid du Colombier if(n)
249*ce95e1b3SDavid du Colombier write(cout, buf.cbuf, n);
250*ce95e1b3SDavid du Colombier cbp = buf.cbuf;
251*ce95e1b3SDavid du Colombier cbc = sizeof(buf.cbuf);
252*ce95e1b3SDavid du Colombier }
253*ce95e1b3SDavid du Colombier
254*ce95e1b3SDavid du Colombier void
nopstat(char * f,Count * c)255*ce95e1b3SDavid du Colombier nopstat(char *f, Count *c)
256*ce95e1b3SDavid du Colombier {
257*ce95e1b3SDavid du Colombier if(c->outof)
258*ce95e1b3SDavid du Colombier Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
259*ce95e1b3SDavid du Colombier c->outof - c->count, c->outof,
260*ce95e1b3SDavid du Colombier (double)(c->outof - c->count)/c->outof);
261*ce95e1b3SDavid du Colombier }
262*ce95e1b3SDavid du Colombier
263*ce95e1b3SDavid du Colombier void
asmsym(void)264*ce95e1b3SDavid du Colombier asmsym(void)
265*ce95e1b3SDavid du Colombier {
266*ce95e1b3SDavid du Colombier Prog *p;
267*ce95e1b3SDavid du Colombier Auto *a;
268*ce95e1b3SDavid du Colombier Sym *s;
269*ce95e1b3SDavid du Colombier int h;
270*ce95e1b3SDavid du Colombier
271*ce95e1b3SDavid du Colombier s = lookup("etext", 0);
272*ce95e1b3SDavid du Colombier if(s->type == STEXT)
273*ce95e1b3SDavid du Colombier putsymb(s->name, 'T', s->value+INITTEXT, s->version);
274*ce95e1b3SDavid du Colombier
275*ce95e1b3SDavid du Colombier for(h=0; h<NHASH; h++)
276*ce95e1b3SDavid du Colombier for(s=hash[h]; s!=S; s=s->link)
277*ce95e1b3SDavid du Colombier switch(s->type) {
278*ce95e1b3SDavid du Colombier case SCONST:
279*ce95e1b3SDavid du Colombier putsymb(s->name, 'D', s->value, s->version);
280*ce95e1b3SDavid du Colombier continue;
281*ce95e1b3SDavid du Colombier
282*ce95e1b3SDavid du Colombier case SSTRING:
283*ce95e1b3SDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
284*ce95e1b3SDavid du Colombier continue;
285*ce95e1b3SDavid du Colombier
286*ce95e1b3SDavid du Colombier case SDATA:
287*ce95e1b3SDavid du Colombier putsymb(s->name, 'D', s->value+INITDAT, s->version);
288*ce95e1b3SDavid du Colombier continue;
289*ce95e1b3SDavid du Colombier
290*ce95e1b3SDavid du Colombier case SBSS:
291*ce95e1b3SDavid du Colombier putsymb(s->name, 'B', s->value+INITDAT, s->version);
292*ce95e1b3SDavid du Colombier continue;
293*ce95e1b3SDavid du Colombier
294*ce95e1b3SDavid du Colombier case SFILE:
295*ce95e1b3SDavid du Colombier putsymb(s->name, 'f', s->value, s->version);
296*ce95e1b3SDavid du Colombier continue;
297*ce95e1b3SDavid du Colombier }
298*ce95e1b3SDavid du Colombier
299*ce95e1b3SDavid du Colombier for(p=textp; p!=P; p=p->cond) {
300*ce95e1b3SDavid du Colombier s = p->from.sym;
301*ce95e1b3SDavid du Colombier if(s->type != STEXT && s->type != SLEAF)
302*ce95e1b3SDavid du Colombier continue;
303*ce95e1b3SDavid du Colombier
304*ce95e1b3SDavid du Colombier /* filenames first */
305*ce95e1b3SDavid du Colombier for(a=p->to.autom; a; a=a->link)
306*ce95e1b3SDavid du Colombier if(a->type == D_FILE)
307*ce95e1b3SDavid du Colombier putsymb(a->asym->name, 'z', a->aoffset, 0);
308*ce95e1b3SDavid du Colombier else
309*ce95e1b3SDavid du Colombier if(a->type == D_FILE1)
310*ce95e1b3SDavid du Colombier putsymb(a->asym->name, 'Z', a->aoffset, 0);
311*ce95e1b3SDavid du Colombier
312*ce95e1b3SDavid du Colombier if(s->type == STEXT)
313*ce95e1b3SDavid du Colombier putsymb(s->name, 'T', s->value+INITTEXT, s->version);
314*ce95e1b3SDavid du Colombier else
315*ce95e1b3SDavid du Colombier putsymb(s->name, 'L', s->value+INITTEXT, s->version);
316*ce95e1b3SDavid du Colombier
317*ce95e1b3SDavid du Colombier /* frame, auto and param after */
318*ce95e1b3SDavid du Colombier putsymb(".frame", 'm', p->to.offset+ptrsize, 0);
319*ce95e1b3SDavid du Colombier for(a=p->to.autom; a; a=a->link)
320*ce95e1b3SDavid du Colombier if(a->type == D_AUTO)
321*ce95e1b3SDavid du Colombier putsymb(a->asym->name, 'a', -a->aoffset, 0);
322*ce95e1b3SDavid du Colombier else
323*ce95e1b3SDavid du Colombier if(a->type == D_PARAM)
324*ce95e1b3SDavid du Colombier putsymb(a->asym->name, 'p', a->aoffset, 0);
325*ce95e1b3SDavid du Colombier }
326*ce95e1b3SDavid du Colombier if(debug['v'] || debug['n'])
327*ce95e1b3SDavid du Colombier Bprint(&bso, "symsize = %lud\n", symsize);
328*ce95e1b3SDavid du Colombier Bflush(&bso);
329*ce95e1b3SDavid du Colombier }
330*ce95e1b3SDavid du Colombier
331*ce95e1b3SDavid du Colombier void
putsymb(char * s,int t,vlong v,int ver)332*ce95e1b3SDavid du Colombier putsymb(char *s, int t, vlong v, int ver)
333*ce95e1b3SDavid du Colombier {
334*ce95e1b3SDavid du Colombier int i, f, l;
335*ce95e1b3SDavid du Colombier
336*ce95e1b3SDavid du Colombier if(t == 'f')
337*ce95e1b3SDavid du Colombier s++;
338*ce95e1b3SDavid du Colombier if(thechar == 'j'){
339*ce95e1b3SDavid du Colombier l = 8;
340*ce95e1b3SDavid du Colombier llput(v);
341*ce95e1b3SDavid du Colombier }else{
342*ce95e1b3SDavid du Colombier l = 4;
343*ce95e1b3SDavid du Colombier lput(v);
344*ce95e1b3SDavid du Colombier }
345*ce95e1b3SDavid du Colombier if(ver)
346*ce95e1b3SDavid du Colombier t += 'a' - 'A';
347*ce95e1b3SDavid du Colombier cput(t+0x80); /* 0x80 is variable length */
348*ce95e1b3SDavid du Colombier
349*ce95e1b3SDavid du Colombier if(t == 'Z' || t == 'z') {
350*ce95e1b3SDavid du Colombier cput(s[0]);
351*ce95e1b3SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
352*ce95e1b3SDavid du Colombier cput(s[i]);
353*ce95e1b3SDavid du Colombier cput(s[i+1]);
354*ce95e1b3SDavid du Colombier }
355*ce95e1b3SDavid du Colombier cput(0);
356*ce95e1b3SDavid du Colombier cput(0);
357*ce95e1b3SDavid du Colombier i++;
358*ce95e1b3SDavid du Colombier }
359*ce95e1b3SDavid du Colombier else {
360*ce95e1b3SDavid du Colombier for(i=0; s[i]; i++)
361*ce95e1b3SDavid du Colombier cput(s[i]);
362*ce95e1b3SDavid du Colombier cput(0);
363*ce95e1b3SDavid du Colombier }
364*ce95e1b3SDavid du Colombier symsize += l + 1 + i + 1;
365*ce95e1b3SDavid du Colombier
366*ce95e1b3SDavid du Colombier if(debug['n']) {
367*ce95e1b3SDavid du Colombier if(t == 'z' || t == 'Z') {
368*ce95e1b3SDavid du Colombier Bprint(&bso, "%c %.8llux ", t, v);
369*ce95e1b3SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
370*ce95e1b3SDavid du Colombier f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
371*ce95e1b3SDavid du Colombier Bprint(&bso, "/%x", f);
372*ce95e1b3SDavid du Colombier }
373*ce95e1b3SDavid du Colombier Bprint(&bso, "\n");
374*ce95e1b3SDavid du Colombier return;
375*ce95e1b3SDavid du Colombier }
376*ce95e1b3SDavid du Colombier if(ver)
377*ce95e1b3SDavid du Colombier Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
378*ce95e1b3SDavid du Colombier else
379*ce95e1b3SDavid du Colombier Bprint(&bso, "%c %.8llux %s\n", t, v, s);
380*ce95e1b3SDavid du Colombier }
381*ce95e1b3SDavid du Colombier }
382*ce95e1b3SDavid du Colombier
383*ce95e1b3SDavid du Colombier #define MINLC 2
384*ce95e1b3SDavid du Colombier void
asmlc(void)385*ce95e1b3SDavid du Colombier asmlc(void)
386*ce95e1b3SDavid du Colombier {
387*ce95e1b3SDavid du Colombier long oldpc, oldlc;
388*ce95e1b3SDavid du Colombier Prog *p;
389*ce95e1b3SDavid du Colombier long v, s;
390*ce95e1b3SDavid du Colombier
391*ce95e1b3SDavid du Colombier oldpc = 0;
392*ce95e1b3SDavid du Colombier oldlc = 0;
393*ce95e1b3SDavid du Colombier for(p = firstp; p != P; p = p->link) {
394*ce95e1b3SDavid du Colombier if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
395*ce95e1b3SDavid du Colombier if(p->as == ATEXT)
396*ce95e1b3SDavid du Colombier curtext = p;
397*ce95e1b3SDavid du Colombier if(debug['L'])
398*ce95e1b3SDavid du Colombier Bprint(&bso, "%6lux %P\n",
399*ce95e1b3SDavid du Colombier p->pc, p);
400*ce95e1b3SDavid du Colombier continue;
401*ce95e1b3SDavid du Colombier }
402*ce95e1b3SDavid du Colombier if(debug['L'])
403*ce95e1b3SDavid du Colombier Bprint(&bso, "\t\t%6ld", lcsize);
404*ce95e1b3SDavid du Colombier v = (p->pc - oldpc) / MINLC;
405*ce95e1b3SDavid du Colombier while(v) {
406*ce95e1b3SDavid du Colombier s = 127;
407*ce95e1b3SDavid du Colombier if(v < 127)
408*ce95e1b3SDavid du Colombier s = v;
409*ce95e1b3SDavid du Colombier cput(s+128); /* 129-255 +pc */
410*ce95e1b3SDavid du Colombier if(debug['L'])
411*ce95e1b3SDavid du Colombier Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
412*ce95e1b3SDavid du Colombier v -= s;
413*ce95e1b3SDavid du Colombier lcsize++;
414*ce95e1b3SDavid du Colombier }
415*ce95e1b3SDavid du Colombier s = p->line - oldlc;
416*ce95e1b3SDavid du Colombier oldlc = p->line;
417*ce95e1b3SDavid du Colombier oldpc = p->pc + MINLC;
418*ce95e1b3SDavid du Colombier if(s > 64 || s < -64) {
419*ce95e1b3SDavid du Colombier cput(0); /* 0 vv +lc */
420*ce95e1b3SDavid du Colombier cput(s>>24);
421*ce95e1b3SDavid du Colombier cput(s>>16);
422*ce95e1b3SDavid du Colombier cput(s>>8);
423*ce95e1b3SDavid du Colombier cput(s);
424*ce95e1b3SDavid du Colombier if(debug['L']) {
425*ce95e1b3SDavid du Colombier if(s > 0)
426*ce95e1b3SDavid du Colombier Bprint(&bso, " lc+%ld(%d,%ld)\n",
427*ce95e1b3SDavid du Colombier s, 0, s);
428*ce95e1b3SDavid du Colombier else
429*ce95e1b3SDavid du Colombier Bprint(&bso, " lc%ld(%d,%ld)\n",
430*ce95e1b3SDavid du Colombier s, 0, s);
431*ce95e1b3SDavid du Colombier Bprint(&bso, "%6lux %P\n",
432*ce95e1b3SDavid du Colombier p->pc, p);
433*ce95e1b3SDavid du Colombier }
434*ce95e1b3SDavid du Colombier lcsize += 5;
435*ce95e1b3SDavid du Colombier continue;
436*ce95e1b3SDavid du Colombier }
437*ce95e1b3SDavid du Colombier if(s > 0) {
438*ce95e1b3SDavid du Colombier cput(0+s); /* 1-64 +lc */
439*ce95e1b3SDavid du Colombier if(debug['L']) {
440*ce95e1b3SDavid du Colombier Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
441*ce95e1b3SDavid du Colombier Bprint(&bso, "%6lux %P\n",
442*ce95e1b3SDavid du Colombier p->pc, p);
443*ce95e1b3SDavid du Colombier }
444*ce95e1b3SDavid du Colombier } else {
445*ce95e1b3SDavid du Colombier cput(64-s); /* 65-128 -lc */
446*ce95e1b3SDavid du Colombier if(debug['L']) {
447*ce95e1b3SDavid du Colombier Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
448*ce95e1b3SDavid du Colombier Bprint(&bso, "%6lux %P\n",
449*ce95e1b3SDavid du Colombier p->pc, p);
450*ce95e1b3SDavid du Colombier }
451*ce95e1b3SDavid du Colombier }
452*ce95e1b3SDavid du Colombier lcsize++;
453*ce95e1b3SDavid du Colombier }
454*ce95e1b3SDavid du Colombier while(lcsize & 1) {
455*ce95e1b3SDavid du Colombier s = 129;
456*ce95e1b3SDavid du Colombier cput(s);
457*ce95e1b3SDavid du Colombier lcsize++;
458*ce95e1b3SDavid du Colombier }
459*ce95e1b3SDavid du Colombier if(debug['v'] || debug['L'])
460*ce95e1b3SDavid du Colombier Bprint(&bso, "lcsize = %ld\n", lcsize);
461*ce95e1b3SDavid du Colombier Bflush(&bso);
462*ce95e1b3SDavid du Colombier }
463*ce95e1b3SDavid du Colombier
464*ce95e1b3SDavid du Colombier void
datblk(long s,long n,int str)465*ce95e1b3SDavid du Colombier datblk(long s, long n, int str)
466*ce95e1b3SDavid du Colombier {
467*ce95e1b3SDavid du Colombier Prog *p;
468*ce95e1b3SDavid du Colombier char *cast;
469*ce95e1b3SDavid du Colombier vlong d;
470*ce95e1b3SDavid du Colombier long l, fl, j;
471*ce95e1b3SDavid du Colombier int i, c;
472*ce95e1b3SDavid du Colombier
473*ce95e1b3SDavid du Colombier memset(buf.dbuf, 0, n+100);
474*ce95e1b3SDavid du Colombier for(p = datap; p != P; p = p->link) {
475*ce95e1b3SDavid du Colombier curp = p;
476*ce95e1b3SDavid du Colombier if(str != (p->from.sym->type == SSTRING))
477*ce95e1b3SDavid du Colombier continue;
478*ce95e1b3SDavid du Colombier l = p->from.sym->value + p->from.offset - s;
479*ce95e1b3SDavid du Colombier c = p->reg;
480*ce95e1b3SDavid du Colombier i = 0;
481*ce95e1b3SDavid du Colombier if(l < 0) {
482*ce95e1b3SDavid du Colombier if(l+c <= 0)
483*ce95e1b3SDavid du Colombier continue;
484*ce95e1b3SDavid du Colombier while(l < 0) {
485*ce95e1b3SDavid du Colombier l++;
486*ce95e1b3SDavid du Colombier i++;
487*ce95e1b3SDavid du Colombier }
488*ce95e1b3SDavid du Colombier }
489*ce95e1b3SDavid du Colombier if(l >= n)
490*ce95e1b3SDavid du Colombier continue;
491*ce95e1b3SDavid du Colombier if(p->as != AINIT && p->as != ADYNT) {
492*ce95e1b3SDavid du Colombier for(j=l+(c-i)-1; j>=l; j--)
493*ce95e1b3SDavid du Colombier if(buf.dbuf[j]) {
494*ce95e1b3SDavid du Colombier print("%P\n", p);
495*ce95e1b3SDavid du Colombier diag("multiple initialization");
496*ce95e1b3SDavid du Colombier break;
497*ce95e1b3SDavid du Colombier }
498*ce95e1b3SDavid du Colombier }
499*ce95e1b3SDavid du Colombier switch(p->to.type) {
500*ce95e1b3SDavid du Colombier default:
501*ce95e1b3SDavid du Colombier diag("unknown mode in initialization\n%P", p);
502*ce95e1b3SDavid du Colombier break;
503*ce95e1b3SDavid du Colombier
504*ce95e1b3SDavid du Colombier case D_FCONST:
505*ce95e1b3SDavid du Colombier switch(c) {
506*ce95e1b3SDavid du Colombier default:
507*ce95e1b3SDavid du Colombier case 4:
508*ce95e1b3SDavid du Colombier fl = ieeedtof(p->to.ieee);
509*ce95e1b3SDavid du Colombier cast = (char*)&fl;
510*ce95e1b3SDavid du Colombier for(; i<c; i++) {
511*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[fnuxi8[i]];
512*ce95e1b3SDavid du Colombier l++;
513*ce95e1b3SDavid du Colombier }
514*ce95e1b3SDavid du Colombier break;
515*ce95e1b3SDavid du Colombier case 8:
516*ce95e1b3SDavid du Colombier cast = (char*)p->to.ieee;
517*ce95e1b3SDavid du Colombier for(; i<c; i++) {
518*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[fnuxi8[i]];
519*ce95e1b3SDavid du Colombier l++;
520*ce95e1b3SDavid du Colombier }
521*ce95e1b3SDavid du Colombier break;
522*ce95e1b3SDavid du Colombier }
523*ce95e1b3SDavid du Colombier break;
524*ce95e1b3SDavid du Colombier
525*ce95e1b3SDavid du Colombier case D_SCONST:
526*ce95e1b3SDavid du Colombier for(; i<c; i++) {
527*ce95e1b3SDavid du Colombier buf.dbuf[l] = p->to.sval[i];
528*ce95e1b3SDavid du Colombier l++;
529*ce95e1b3SDavid du Colombier }
530*ce95e1b3SDavid du Colombier break;
531*ce95e1b3SDavid du Colombier
532*ce95e1b3SDavid du Colombier case D_VCONST:
533*ce95e1b3SDavid du Colombier d = *p->to.vval;
534*ce95e1b3SDavid du Colombier goto dconst;
535*ce95e1b3SDavid du Colombier
536*ce95e1b3SDavid du Colombier case D_CONST:
537*ce95e1b3SDavid du Colombier d = p->to.offset;
538*ce95e1b3SDavid du Colombier dconst:
539*ce95e1b3SDavid du Colombier if(p->to.sym) {
540*ce95e1b3SDavid du Colombier switch(p->to.sym->type) {
541*ce95e1b3SDavid du Colombier case STEXT:
542*ce95e1b3SDavid du Colombier case SLEAF:
543*ce95e1b3SDavid du Colombier case SSTRING:
544*ce95e1b3SDavid du Colombier d += (p->to.sym->value + INITTEXT);
545*ce95e1b3SDavid du Colombier break;
546*ce95e1b3SDavid du Colombier case SDATA:
547*ce95e1b3SDavid du Colombier case SBSS:
548*ce95e1b3SDavid du Colombier d += (p->to.sym->value + INITDAT);
549*ce95e1b3SDavid du Colombier break;
550*ce95e1b3SDavid du Colombier }
551*ce95e1b3SDavid du Colombier }
552*ce95e1b3SDavid du Colombier cast = (char*)&d;
553*ce95e1b3SDavid du Colombier switch(c) {
554*ce95e1b3SDavid du Colombier default:
555*ce95e1b3SDavid du Colombier diag("bad nuxi %d %d\n%P", c, i, curp);
556*ce95e1b3SDavid du Colombier break;
557*ce95e1b3SDavid du Colombier case 1:
558*ce95e1b3SDavid du Colombier for(; i<c; i++) {
559*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[inuxi1[i]];
560*ce95e1b3SDavid du Colombier l++;
561*ce95e1b3SDavid du Colombier }
562*ce95e1b3SDavid du Colombier break;
563*ce95e1b3SDavid du Colombier case 2:
564*ce95e1b3SDavid du Colombier for(; i<c; i++) {
565*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[inuxi2[i]];
566*ce95e1b3SDavid du Colombier l++;
567*ce95e1b3SDavid du Colombier }
568*ce95e1b3SDavid du Colombier break;
569*ce95e1b3SDavid du Colombier case 4:
570*ce95e1b3SDavid du Colombier for(; i<c; i++) {
571*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[inuxi4[i]];
572*ce95e1b3SDavid du Colombier l++;
573*ce95e1b3SDavid du Colombier }
574*ce95e1b3SDavid du Colombier break;
575*ce95e1b3SDavid du Colombier case 8:
576*ce95e1b3SDavid du Colombier for(; i<c; i++) {
577*ce95e1b3SDavid du Colombier buf.dbuf[l] = cast[inuxi8[i]];
578*ce95e1b3SDavid du Colombier l++;
579*ce95e1b3SDavid du Colombier }
580*ce95e1b3SDavid du Colombier break;
581*ce95e1b3SDavid du Colombier }
582*ce95e1b3SDavid du Colombier break;
583*ce95e1b3SDavid du Colombier }
584*ce95e1b3SDavid du Colombier if(debug['d'] && i == c) {
585*ce95e1b3SDavid du Colombier Bprint(&bso, "%.8llux", l+s+INITDAT-c);
586*ce95e1b3SDavid du Colombier for(j = -c; j<0; j++)
587*ce95e1b3SDavid du Colombier Bprint(&bso, " %.2ux", ((uchar*)buf.dbuf)[l + j]);
588*ce95e1b3SDavid du Colombier Bprint(&bso, "\t%P\n", curp);
589*ce95e1b3SDavid du Colombier }
590*ce95e1b3SDavid du Colombier }
591*ce95e1b3SDavid du Colombier write(cout, buf.dbuf, n);
592*ce95e1b3SDavid du Colombier }
593*ce95e1b3SDavid du Colombier
594*ce95e1b3SDavid du Colombier #define R(r) ((r)&0x1F)
595*ce95e1b3SDavid du Colombier #define OPX (0x3 | o->op<<2)
596*ce95e1b3SDavid du Colombier #define OPF (OPX | o->func3<<12)
597*ce95e1b3SDavid du Colombier #define OP_R(rs1,rs2,rd)\
598*ce95e1b3SDavid du Colombier (OPF | rd<<7 | R(rs1)<<15 | R(rs2)<<20 | o->param<<25)
599*ce95e1b3SDavid du Colombier #define OP_RF(rs1,rs2,rd,rm)\
600*ce95e1b3SDavid du Colombier (OPX | rm<<12 | rd<<7 | R(rs1)<<15 | R(rs2)<<20 | o->param<<25)
601*ce95e1b3SDavid du Colombier #define OP_RO(rs1,rs2,rd)\
602*ce95e1b3SDavid du Colombier (0x3 | OOP<<2 | o->func3<<12 | rd<<7 | R(rs1)<<15 | R(rs2)<<20)
603*ce95e1b3SDavid du Colombier #define OP_ADD(rs1,rs2,rd)\
604*ce95e1b3SDavid du Colombier (0x3 | OOP<<2 | rd<<7 | R(rs1)<<15 | R(rs2)<<20)
605*ce95e1b3SDavid du Colombier #define OP_I(rs1,rd,imm)\
606*ce95e1b3SDavid du Colombier (OPF | rd<<7 | R(rs1)<<15 | (imm)<<20)
607*ce95e1b3SDavid du Colombier #define OP_FI(func3,rs1,rd,imm)\
608*ce95e1b3SDavid du Colombier (OPX | func3<<12 | rd<<7 | R(rs1)<<15 | (imm)<<20)
609*ce95e1b3SDavid du Colombier #define OP_S(rs1,rs2,imm)\
610*ce95e1b3SDavid du Colombier (OPF | (imm&0x1F)<<7 | R(rs1)<<15 | R(rs2)<<20 | (imm>>5)<<25)
611*ce95e1b3SDavid du Colombier #define OP_B(rs1,rs2,imm)\
612*ce95e1b3SDavid du Colombier (OPF | R(rs1)<<15 | R(rs2)<<20 | (imm&0x800)>>4 | (imm&0x1E)<<7 | \
613*ce95e1b3SDavid du Colombier (imm&0x7E0)<<20 | (imm&0x1000)<<19)
614*ce95e1b3SDavid du Colombier #define OP_U(rd,imm)\
615*ce95e1b3SDavid du Colombier (0x3 | OLUI<<2 | rd<<7 | (imm&0xFFFFF000))
616*ce95e1b3SDavid du Colombier #define OP_UP(rd,imm)\
617*ce95e1b3SDavid du Colombier (0x3 | OAUIPC<<2 | rd<<7 | (imm&0xFFFFF000))
618*ce95e1b3SDavid du Colombier #define OP_J(rd,imm)\
619*ce95e1b3SDavid du Colombier (OPX | rd<<7 | (imm&0xff000) | (imm&0x800)<<9 | (imm&0x7FE)<<20 | (imm&0x100000)<<11)
620*ce95e1b3SDavid du Colombier
621*ce95e1b3SDavid du Colombier /*
622*ce95e1b3SDavid du Colombier * aflag: 0 - assemble to object file
623*ce95e1b3SDavid du Colombier * 1 - return assembled instruction
624*ce95e1b3SDavid du Colombier * 2 - first pass, return length of assembled instruction
625*ce95e1b3SDavid du Colombier * 3 - later pass, return length of assembled instruction
626*ce95e1b3SDavid du Colombier */
627*ce95e1b3SDavid du Colombier int
asmout(Prog * p,Optab * o,int aflag)628*ce95e1b3SDavid du Colombier asmout(Prog *p, Optab *o, int aflag)
629*ce95e1b3SDavid du Colombier {
630*ce95e1b3SDavid du Colombier vlong vv;
631*ce95e1b3SDavid du Colombier long o1, o2, o3, v;
632*ce95e1b3SDavid du Colombier int r;
633*ce95e1b3SDavid du Colombier
634*ce95e1b3SDavid du Colombier o1 = 0;
635*ce95e1b3SDavid du Colombier o2 = 0;
636*ce95e1b3SDavid du Colombier o3 = 0;
637*ce95e1b3SDavid du Colombier r = p->reg;
638*ce95e1b3SDavid du Colombier if(r == NREG) switch(p->as){
639*ce95e1b3SDavid du Colombier case AMOVF:
640*ce95e1b3SDavid du Colombier case AMOVD:
641*ce95e1b3SDavid du Colombier if(p->from.type == D_FREG && p->to.type == D_FREG)
642*ce95e1b3SDavid du Colombier r = p->from.reg;
643*ce95e1b3SDavid du Colombier break;
644*ce95e1b3SDavid du Colombier case AMOV:
645*ce95e1b3SDavid du Colombier case AJMP:
646*ce95e1b3SDavid du Colombier r = REGZERO;
647*ce95e1b3SDavid du Colombier break;
648*ce95e1b3SDavid du Colombier case AJAL:
649*ce95e1b3SDavid du Colombier r = REGLINK;
650*ce95e1b3SDavid du Colombier break;
651*ce95e1b3SDavid du Colombier default:
652*ce95e1b3SDavid du Colombier r = p->to.reg;
653*ce95e1b3SDavid du Colombier break;
654*ce95e1b3SDavid du Colombier }
655*ce95e1b3SDavid du Colombier if(!debug['c'] && o->ctype){
656*ce95e1b3SDavid du Colombier o1 = asmcompressed(p, o, r, aflag == 2);
657*ce95e1b3SDavid du Colombier if(o1 != 0){
658*ce95e1b3SDavid du Colombier switch(aflag){
659*ce95e1b3SDavid du Colombier case 1:
660*ce95e1b3SDavid du Colombier return o1;
661*ce95e1b3SDavid du Colombier case 2:
662*ce95e1b3SDavid du Colombier case 3:
663*ce95e1b3SDavid du Colombier return 2;
664*ce95e1b3SDavid du Colombier }
665*ce95e1b3SDavid du Colombier if(debug['a']){
666*ce95e1b3SDavid du Colombier v = p->pc + INITTEXT;
667*ce95e1b3SDavid du Colombier Bprint(&bso, " %.8lux: %.4lux \t%P\n", v, o1, p);
668*ce95e1b3SDavid du Colombier }
669*ce95e1b3SDavid du Colombier wputl(o1);
670*ce95e1b3SDavid du Colombier return 2;
671*ce95e1b3SDavid du Colombier }
672*ce95e1b3SDavid du Colombier }
673*ce95e1b3SDavid du Colombier if(aflag >= 2)
674*ce95e1b3SDavid du Colombier return o->size;
675*ce95e1b3SDavid du Colombier switch(o->type) {
676*ce95e1b3SDavid du Colombier default:
677*ce95e1b3SDavid du Colombier diag("unknown type %d", o->type);
678*ce95e1b3SDavid du Colombier if(!debug['a'])
679*ce95e1b3SDavid du Colombier prasm(p);
680*ce95e1b3SDavid du Colombier break;
681*ce95e1b3SDavid du Colombier
682*ce95e1b3SDavid du Colombier case 0: /* add S,[R,]D */
683*ce95e1b3SDavid du Colombier o1 = OP_R(r, p->from.reg, p->to.reg);
684*ce95e1b3SDavid du Colombier break;
685*ce95e1b3SDavid du Colombier
686*ce95e1b3SDavid du Colombier case 1: /* slli $I,[R,]D */
687*ce95e1b3SDavid du Colombier v = p->from.offset & 0x3F;
688*ce95e1b3SDavid du Colombier v |= (o->param<<5);
689*ce95e1b3SDavid du Colombier o1 = OP_I(r, p->to.reg, v);
690*ce95e1b3SDavid du Colombier break;
691*ce95e1b3SDavid du Colombier
692*ce95e1b3SDavid du Colombier case 2: /* addi $I,[R,]D */
693*ce95e1b3SDavid du Colombier v = p->from.offset;
694*ce95e1b3SDavid du Colombier if(v < -BIG || v >= BIG)
695*ce95e1b3SDavid du Colombier diag("imm out of range\n%P", p);
696*ce95e1b3SDavid du Colombier o1 = OP_I(r, p->to.reg, v);
697*ce95e1b3SDavid du Colombier break;
698*ce95e1b3SDavid du Colombier
699*ce95e1b3SDavid du Colombier case 3: /* beq S,[R,]L */
700*ce95e1b3SDavid du Colombier if(r == NREG)
701*ce95e1b3SDavid du Colombier r = REGZERO;
702*ce95e1b3SDavid du Colombier if(p->cond == P)
703*ce95e1b3SDavid du Colombier v = 0;
704*ce95e1b3SDavid du Colombier else
705*ce95e1b3SDavid du Colombier v = (p->cond->pc - pc);
706*ce95e1b3SDavid du Colombier if(v < -0x1000 || v >= 0x1000)
707*ce95e1b3SDavid du Colombier diag("branch out of range\n%P", p);
708*ce95e1b3SDavid du Colombier o1 = OP_B(r, p->from.reg, v);
709*ce95e1b3SDavid du Colombier break;
710*ce95e1b3SDavid du Colombier
711*ce95e1b3SDavid du Colombier case 4: /* jal [D,]L */
712*ce95e1b3SDavid du Colombier if(p->cond == P)
713*ce95e1b3SDavid du Colombier v = 0;
714*ce95e1b3SDavid du Colombier else
715*ce95e1b3SDavid du Colombier v = (p->cond->pc - pc);
716*ce95e1b3SDavid du Colombier if(v < -0x100000 || v >= 0x100000)
717*ce95e1b3SDavid du Colombier diag("jump out of range\n%P", p);
718*ce95e1b3SDavid du Colombier o1 = OP_J(r, v);
719*ce95e1b3SDavid du Colombier break;
720*ce95e1b3SDavid du Colombier
721*ce95e1b3SDavid du Colombier case 5: /* jalr [D,]I(S) */
722*ce95e1b3SDavid du Colombier v = regoff(&p->to);
723*ce95e1b3SDavid du Colombier if(v < -BIG || v >= BIG)
724*ce95e1b3SDavid du Colombier diag("imm out of range\n%P", p);
725*ce95e1b3SDavid du Colombier o1 = OP_I(classreg(&p->to), r, v);
726*ce95e1b3SDavid du Colombier break;
727*ce95e1b3SDavid du Colombier
728*ce95e1b3SDavid du Colombier case 6: /* sb R,I(S) */
729*ce95e1b3SDavid du Colombier v = regoff(&p->to);
730*ce95e1b3SDavid du Colombier r = classreg(&p->to);
731*ce95e1b3SDavid du Colombier if(v < -BIG || v >= BIG)
732*ce95e1b3SDavid du Colombier diag("imm out of range\n%P", p);
733*ce95e1b3SDavid du Colombier o1 = OP_S(r, p->from.reg, v);
734*ce95e1b3SDavid du Colombier break;
735*ce95e1b3SDavid du Colombier
736*ce95e1b3SDavid du Colombier case 7: /* lb I(S),D */
737*ce95e1b3SDavid du Colombier v = regoff(&p->from);
738*ce95e1b3SDavid du Colombier r = classreg(&p->from);
739*ce95e1b3SDavid du Colombier if(v < -BIG || v >= BIG)
740*ce95e1b3SDavid du Colombier diag("imm out of range\n%P", p);
741*ce95e1b3SDavid du Colombier o1 = OP_I(r, p->to.reg, v);
742*ce95e1b3SDavid du Colombier break;
743*ce95e1b3SDavid du Colombier
744*ce95e1b3SDavid du Colombier case 8: /* lui I,D */
745*ce95e1b3SDavid du Colombier v = p->from.offset;
746*ce95e1b3SDavid du Colombier o1 = OP_U(p->to.reg, v);
747*ce95e1b3SDavid du Colombier break;
748*ce95e1b3SDavid du Colombier
749*ce95e1b3SDavid du Colombier case 9: /* lui I1,D; addi I0,D */
750*ce95e1b3SDavid du Colombier v = regoff(&p->from);
751*ce95e1b3SDavid du Colombier if(thechar == 'j' && v >= 0x7ffff800){
752*ce95e1b3SDavid du Colombier /* awkward edge case */
753*ce95e1b3SDavid du Colombier o1 = OP_U(p->to.reg, -v);
754*ce95e1b3SDavid du Colombier v &= 0xFFF;
755*ce95e1b3SDavid du Colombier o2 = OP_FI(4, p->to.reg, p->to.reg, v); /* xori */
756*ce95e1b3SDavid du Colombier break;
757*ce95e1b3SDavid du Colombier }
758*ce95e1b3SDavid du Colombier if(v & 0x800)
759*ce95e1b3SDavid du Colombier v += 0x1000;
760*ce95e1b3SDavid du Colombier o1 = OP_U(p->to.reg, v);
761*ce95e1b3SDavid du Colombier v &= 0xFFF;
762*ce95e1b3SDavid du Colombier o2 = OP_I(p->to.reg, p->to.reg, v);
763*ce95e1b3SDavid du Colombier break;
764*ce95e1b3SDavid du Colombier
765*ce95e1b3SDavid du Colombier case 10: /* sign extend */
766*ce95e1b3SDavid du Colombier if(p->as == AMOVBU) {
767*ce95e1b3SDavid du Colombier o1 = OP_I(p->from.reg, p->to.reg, o->param);
768*ce95e1b3SDavid du Colombier break;
769*ce95e1b3SDavid du Colombier }
770*ce95e1b3SDavid du Colombier v = o->param;
771*ce95e1b3SDavid du Colombier if(thechar == 'j')
772*ce95e1b3SDavid du Colombier v += 32;
773*ce95e1b3SDavid du Colombier o1 = OP_FI(1, p->from.reg, p->to.reg, v & 0x3F); /* slli */
774*ce95e1b3SDavid du Colombier o2 = OP_I(p->to.reg, p->to.reg, v); /* srli or srai */
775*ce95e1b3SDavid du Colombier break;
776*ce95e1b3SDavid du Colombier
777*ce95e1b3SDavid du Colombier case 11: /* addi $I,R,D */
778*ce95e1b3SDavid du Colombier v = regoff(&p->from);
779*ce95e1b3SDavid du Colombier if(v < -BIG || v >= BIG)
780*ce95e1b3SDavid du Colombier diag("imm out of range\n%P", p);
781*ce95e1b3SDavid du Colombier o1 = OP_I(classreg(&p->from), p->to.reg, v);
782*ce95e1b3SDavid du Colombier break;
783*ce95e1b3SDavid du Colombier
784*ce95e1b3SDavid du Colombier case 12: /* mov r,lext => lui/auipc I1,T; sb r,I0(T) */
785*ce95e1b3SDavid du Colombier v = regoff(&p->to);
786*ce95e1b3SDavid du Colombier if(thechar == 'j'){
787*ce95e1b3SDavid du Colombier vv = v + INITDAT + BIG - INITTEXT - pc;
788*ce95e1b3SDavid du Colombier v = (long)vv;
789*ce95e1b3SDavid du Colombier if(v != vv || (v&~0x7FF) == 0x7FFFF800)
790*ce95e1b3SDavid du Colombier diag("address out of range\n%P", p);
791*ce95e1b3SDavid du Colombier }else
792*ce95e1b3SDavid du Colombier v += INITDAT + BIG;
793*ce95e1b3SDavid du Colombier if(v & 0x800)
794*ce95e1b3SDavid du Colombier v += 0x1000;
795*ce95e1b3SDavid du Colombier o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
796*ce95e1b3SDavid du Colombier v &= 0xFFF;
797*ce95e1b3SDavid du Colombier o2 = OP_S(REGTMP, p->from.reg, v);
798*ce95e1b3SDavid du Colombier break;
799*ce95e1b3SDavid du Colombier
800*ce95e1b3SDavid du Colombier case 13: /* mov lext, r => lui/auipc I1,T; lb r,I0(T) */
801*ce95e1b3SDavid du Colombier v = regoff(&p->from);
802*ce95e1b3SDavid du Colombier if(thechar == 'j'){
803*ce95e1b3SDavid du Colombier vv = v + INITDAT + BIG - INITTEXT - pc;
804*ce95e1b3SDavid du Colombier v = (long)vv;
805*ce95e1b3SDavid du Colombier if(v != vv || (v&~0x7FF) == 0x7FFFF800)
806*ce95e1b3SDavid du Colombier diag("address out of range\n%P", p);
807*ce95e1b3SDavid du Colombier }else
808*ce95e1b3SDavid du Colombier v += INITDAT + BIG;
809*ce95e1b3SDavid du Colombier if(v & 0x800)
810*ce95e1b3SDavid du Colombier v += 0x1000;
811*ce95e1b3SDavid du Colombier o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
812*ce95e1b3SDavid du Colombier v &= 0xFFF;
813*ce95e1b3SDavid du Colombier o2 = OP_I(REGTMP, p->to.reg, v);
814*ce95e1b3SDavid du Colombier break;
815*ce95e1b3SDavid du Colombier
816*ce95e1b3SDavid du Colombier case 14: /* op $lcon,[r,]d => lui L1,T; addi $L0,T,T; op T,r,d */
817*ce95e1b3SDavid du Colombier v = regoff(&p->from);
818*ce95e1b3SDavid du Colombier if(p->as == AMOVW || p->as == AMOV)
819*ce95e1b3SDavid du Colombier r = classreg(&p->from);
820*ce95e1b3SDavid du Colombier if(thechar == 'j' && v >= 0x7ffff800){
821*ce95e1b3SDavid du Colombier /* awkward edge case */
822*ce95e1b3SDavid du Colombier o1 = OP_U(p->to.reg, -v);
823*ce95e1b3SDavid du Colombier v &= 0xFFF;
824*ce95e1b3SDavid du Colombier o2 = OP_FI(4, p->to.reg, p->to.reg, v); /* xori */
825*ce95e1b3SDavid du Colombier }else{
826*ce95e1b3SDavid du Colombier if(v & 0x800)
827*ce95e1b3SDavid du Colombier v += 0x1000;
828*ce95e1b3SDavid du Colombier o1 = OP_U(REGTMP, v);
829*ce95e1b3SDavid du Colombier v &= 0xFFF;
830*ce95e1b3SDavid du Colombier o2 = OP_FI(0, REGTMP, REGTMP, v); /* addi */
831*ce95e1b3SDavid du Colombier }
832*ce95e1b3SDavid du Colombier o3 = OP_RO(r, REGTMP, p->to.reg);
833*ce95e1b3SDavid du Colombier break;
834*ce95e1b3SDavid du Colombier
835*ce95e1b3SDavid du Colombier case 15: /* mov r,L(s) => lui L1,T; add s,T,T; sb r,L0(T) */
836*ce95e1b3SDavid du Colombier v = regoff(&p->to);
837*ce95e1b3SDavid du Colombier r = classreg(&p->to);
838*ce95e1b3SDavid du Colombier if(v & 0x800)
839*ce95e1b3SDavid du Colombier v += 0x1000;
840*ce95e1b3SDavid du Colombier o1 = OP_U(REGTMP, v);
841*ce95e1b3SDavid du Colombier v &= 0xFFF;
842*ce95e1b3SDavid du Colombier o2 = OP_ADD(r, REGTMP, REGTMP);
843*ce95e1b3SDavid du Colombier o3 = OP_S(REGTMP, p->from.reg, v);
844*ce95e1b3SDavid du Colombier break;
845*ce95e1b3SDavid du Colombier
846*ce95e1b3SDavid du Colombier case 16: /* mov L(s),r => lui L1,T; add s,T,T; lb r,L0(T) */
847*ce95e1b3SDavid du Colombier v = regoff(&p->from);
848*ce95e1b3SDavid du Colombier r = classreg(&p->from);
849*ce95e1b3SDavid du Colombier if(v & 0x800)
850*ce95e1b3SDavid du Colombier v += 0x1000;
851*ce95e1b3SDavid du Colombier o1 = OP_U(REGTMP, v);
852*ce95e1b3SDavid du Colombier v &= 0xFFF;
853*ce95e1b3SDavid du Colombier o2 = OP_ADD(r, REGTMP, REGTMP);
854*ce95e1b3SDavid du Colombier o3 = OP_I(REGTMP, p->to.reg, v);
855*ce95e1b3SDavid du Colombier break;
856*ce95e1b3SDavid du Colombier
857*ce95e1b3SDavid du Colombier case 17: /* fcvt S,D */
858*ce95e1b3SDavid du Colombier v = 7; /* dynamic rounding mode */
859*ce95e1b3SDavid du Colombier if(o->a3 == C_REG) /* convert to int? */
860*ce95e1b3SDavid du Colombier v = 1; /* round towards zero */
861*ce95e1b3SDavid du Colombier o1 = OP_RF(p->from.reg, o->func3, p->to.reg, v);
862*ce95e1b3SDavid du Colombier break;
863*ce95e1b3SDavid du Colombier
864*ce95e1b3SDavid du Colombier case 18: /* lui L1, T; jal [r,]L0(T) */
865*ce95e1b3SDavid du Colombier if(p->cond == P)
866*ce95e1b3SDavid du Colombier v = 0;
867*ce95e1b3SDavid du Colombier else
868*ce95e1b3SDavid du Colombier v = p->cond->pc;
869*ce95e1b3SDavid du Colombier if(thechar == 'j'){
870*ce95e1b3SDavid du Colombier vv = v + INITTEXT;
871*ce95e1b3SDavid du Colombier v = (long)vv;
872*ce95e1b3SDavid du Colombier if(v != vv || (v&~0x7FF) == 0x7FFFF800)
873*ce95e1b3SDavid du Colombier diag("branch out of range\n%P", p);
874*ce95e1b3SDavid du Colombier }else
875*ce95e1b3SDavid du Colombier v += INITTEXT;
876*ce95e1b3SDavid du Colombier if(v & 0x800)
877*ce95e1b3SDavid du Colombier v += 0x1000;
878*ce95e1b3SDavid du Colombier o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
879*ce95e1b3SDavid du Colombier v &= 0xFFF;
880*ce95e1b3SDavid du Colombier o2 = OP_I(REGTMP, r, v);
881*ce95e1b3SDavid du Colombier break;
882*ce95e1b3SDavid du Colombier
883*ce95e1b3SDavid du Colombier case 19: /* addiw $0, rs, rd */
884*ce95e1b3SDavid du Colombier v = 0;
885*ce95e1b3SDavid du Colombier o1 = OP_I(p->from.reg, p->to.reg, v);
886*ce95e1b3SDavid du Colombier break;
887*ce95e1b3SDavid du Colombier
888*ce95e1b3SDavid du Colombier case 20: /* lui/auipc I1,D; addi I0; D */
889*ce95e1b3SDavid du Colombier if(thechar == 'j'){
890*ce95e1b3SDavid du Colombier vv = regoff(&p->from) + instoffx - (pc + INITTEXT);
891*ce95e1b3SDavid du Colombier v = (long)vv;
892*ce95e1b3SDavid du Colombier if(v != vv || (v&~0x7FF) == 0x7FFFF800)
893*ce95e1b3SDavid du Colombier diag("address %llux out of range\n%P", regoff(&p->from) + instoffx, p);
894*ce95e1b3SDavid du Colombier }else{
895*ce95e1b3SDavid du Colombier v = regoff(&p->from) + instoffx;
896*ce95e1b3SDavid du Colombier }
897*ce95e1b3SDavid du Colombier if(v & 0x800)
898*ce95e1b3SDavid du Colombier v += 0x1000;
899*ce95e1b3SDavid du Colombier o1 = thechar == 'j' ? OP_UP(p->to.reg, v) : OP_U(p->to.reg, v);
900*ce95e1b3SDavid du Colombier v &= 0xFFF;
901*ce95e1b3SDavid du Colombier o2 = OP_I(p->to.reg, p->to.reg, v);
902*ce95e1b3SDavid du Colombier break;
903*ce95e1b3SDavid du Colombier
904*ce95e1b3SDavid du Colombier case 21: /* lui I,D; s[lr]ai N,D */
905*ce95e1b3SDavid du Colombier vv = *p->from.vval;
906*ce95e1b3SDavid du Colombier v = vconshift(vv);
907*ce95e1b3SDavid du Colombier if(v < 0)
908*ce95e1b3SDavid du Colombier diag("64 bit constant error:\n%P", p);
909*ce95e1b3SDavid du Colombier if(v < 12)
910*ce95e1b3SDavid du Colombier vv <<= 12 - v;
911*ce95e1b3SDavid du Colombier else
912*ce95e1b3SDavid du Colombier vv >>= v - 12;
913*ce95e1b3SDavid du Colombier o1 = OP_U(p->to.reg, (long)vv);
914*ce95e1b3SDavid du Colombier if (v > 12)
915*ce95e1b3SDavid du Colombier o2 = OP_FI(1, p->to.reg, p->to.reg, v - 12); /* slli */
916*ce95e1b3SDavid du Colombier else
917*ce95e1b3SDavid du Colombier o2 = OP_I(p->to.reg, p->to.reg, 12 - v); /* srai */
918*ce95e1b3SDavid du Colombier break;
919*ce95e1b3SDavid du Colombier
920*ce95e1b3SDavid du Colombier case 22: /* CSRRx C, rs, rd */
921*ce95e1b3SDavid du Colombier v = p->from.offset & 0xFFF;
922*ce95e1b3SDavid du Colombier o1 = OP_I(p->reg, p->to.reg, v);
923*ce95e1b3SDavid du Colombier break;
924*ce95e1b3SDavid du Colombier
925*ce95e1b3SDavid du Colombier case 24: /* SYS */
926*ce95e1b3SDavid du Colombier v = p->to.offset & 0xFFF;
927*ce95e1b3SDavid du Colombier o1 = OP_I(0, 0, v);
928*ce95e1b3SDavid du Colombier break;
929*ce95e1b3SDavid du Colombier
930*ce95e1b3SDavid du Colombier case 25: /* word $x */
931*ce95e1b3SDavid du Colombier o1 = regoff(&p->to);
932*ce95e1b3SDavid du Colombier break;
933*ce95e1b3SDavid du Colombier
934*ce95e1b3SDavid du Colombier case 26: /* pseudo ops */
935*ce95e1b3SDavid du Colombier break;
936*ce95e1b3SDavid du Colombier }
937*ce95e1b3SDavid du Colombier if(aflag)
938*ce95e1b3SDavid du Colombier return o1;
939*ce95e1b3SDavid du Colombier v = p->pc + INITTEXT;
940*ce95e1b3SDavid du Colombier switch(o->size) {
941*ce95e1b3SDavid du Colombier default:
942*ce95e1b3SDavid du Colombier if(debug['a'])
943*ce95e1b3SDavid du Colombier Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
944*ce95e1b3SDavid du Colombier break;
945*ce95e1b3SDavid du Colombier case 4:
946*ce95e1b3SDavid du Colombier if(debug['a'])
947*ce95e1b3SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
948*ce95e1b3SDavid du Colombier lputl(o1);
949*ce95e1b3SDavid du Colombier break;
950*ce95e1b3SDavid du Colombier case 8:
951*ce95e1b3SDavid du Colombier if(debug['a'])
952*ce95e1b3SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
953*ce95e1b3SDavid du Colombier lputl(o1);
954*ce95e1b3SDavid du Colombier lputl(o2);
955*ce95e1b3SDavid du Colombier break;
956*ce95e1b3SDavid du Colombier case 12:
957*ce95e1b3SDavid du Colombier if(debug['a'])
958*ce95e1b3SDavid du Colombier Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
959*ce95e1b3SDavid du Colombier lputl(o1);
960*ce95e1b3SDavid du Colombier lputl(o2);
961*ce95e1b3SDavid du Colombier lputl(o3);
962*ce95e1b3SDavid du Colombier break;
963*ce95e1b3SDavid du Colombier }
964*ce95e1b3SDavid du Colombier return o->size;
965*ce95e1b3SDavid du Colombier }
966*ce95e1b3SDavid du Colombier
967