1e887ea33SDavid du Colombier #include "l.h"
2e887ea33SDavid du Colombier
3e887ea33SDavid du Colombier static int rexflag;
4*40d01547SDavid du Colombier static int vexbytes;
5e887ea33SDavid du Colombier static int asmode;
6e887ea33SDavid du Colombier
7e887ea33SDavid du Colombier void
span(void)8e887ea33SDavid du Colombier span(void)
9e887ea33SDavid du Colombier {
10e887ea33SDavid du Colombier Prog *p, *q;
11e887ea33SDavid du Colombier long v;
12e887ea33SDavid du Colombier vlong c, idat;
13e887ea33SDavid du Colombier int m, n, again;
14e887ea33SDavid du Colombier
15e887ea33SDavid du Colombier xdefine("etext", STEXT, 0L);
16e887ea33SDavid du Colombier idat = INITDAT;
17e887ea33SDavid du Colombier for(p = firstp; p != P; p = p->link) {
18e887ea33SDavid du Colombier if(p->as == ATEXT)
19e887ea33SDavid du Colombier curtext = p;
20e887ea33SDavid du Colombier n = 0;
21e887ea33SDavid du Colombier if(p->to.type == D_BRANCH)
22e887ea33SDavid du Colombier if(p->pcond == P)
23e887ea33SDavid du Colombier p->pcond = p;
24e887ea33SDavid du Colombier if((q = p->pcond) != P)
25e887ea33SDavid du Colombier if(q->back != 2)
26e887ea33SDavid du Colombier n = 1;
27e887ea33SDavid du Colombier p->back = n;
28e887ea33SDavid du Colombier if(p->as == AADJSP) {
29e887ea33SDavid du Colombier p->to.type = D_SP;
30e887ea33SDavid du Colombier v = -p->from.offset;
31e887ea33SDavid du Colombier p->from.offset = v;
32e887ea33SDavid du Colombier p->as = p->mode != 64? AADDL: AADDQ;
33e887ea33SDavid du Colombier if(v < 0) {
34e887ea33SDavid du Colombier p->as = p->mode != 64? ASUBL: ASUBQ;
35e887ea33SDavid du Colombier v = -v;
36e887ea33SDavid du Colombier p->from.offset = v;
37e887ea33SDavid du Colombier }
38e887ea33SDavid du Colombier if(v == 0)
39e887ea33SDavid du Colombier p->as = ANOP;
40e887ea33SDavid du Colombier }
41e887ea33SDavid du Colombier }
42e887ea33SDavid du Colombier n = 0;
43e887ea33SDavid du Colombier
44e887ea33SDavid du Colombier start:
45e887ea33SDavid du Colombier if(debug['v'])
46e887ea33SDavid du Colombier Bprint(&bso, "%5.2f span\n", cputime());
47e887ea33SDavid du Colombier Bflush(&bso);
48e887ea33SDavid du Colombier c = INITTEXT;
49e887ea33SDavid du Colombier for(p = firstp; p != P; p = p->link) {
50e887ea33SDavid du Colombier if(p->as == ATEXT)
51e887ea33SDavid du Colombier curtext = p;
52e887ea33SDavid du Colombier if(p->to.type == D_BRANCH)
53e887ea33SDavid du Colombier if(p->back)
54e887ea33SDavid du Colombier p->pc = c;
55e887ea33SDavid du Colombier asmins(p);
56e887ea33SDavid du Colombier p->pc = c;
57e887ea33SDavid du Colombier m = andptr-and;
58e887ea33SDavid du Colombier p->mark = m;
59e887ea33SDavid du Colombier c += m;
60e887ea33SDavid du Colombier }
61e887ea33SDavid du Colombier
62e887ea33SDavid du Colombier loop:
63e887ea33SDavid du Colombier n++;
64e887ea33SDavid du Colombier if(debug['v'])
65e887ea33SDavid du Colombier Bprint(&bso, "%5.2f span %d\n", cputime(), n);
66e887ea33SDavid du Colombier Bflush(&bso);
67e887ea33SDavid du Colombier if(n > 50) {
68e887ea33SDavid du Colombier print("span must be looping\n");
69e887ea33SDavid du Colombier errorexit();
70e887ea33SDavid du Colombier }
71e887ea33SDavid du Colombier again = 0;
72e887ea33SDavid du Colombier c = INITTEXT;
73e887ea33SDavid du Colombier for(p = firstp; p != P; p = p->link) {
74e887ea33SDavid du Colombier if(p->as == ATEXT)
75e887ea33SDavid du Colombier curtext = p;
76e887ea33SDavid du Colombier if(p->to.type == D_BRANCH || p->back & 0100) {
77e887ea33SDavid du Colombier if(p->back)
78e887ea33SDavid du Colombier p->pc = c;
79e887ea33SDavid du Colombier asmins(p);
80e887ea33SDavid du Colombier m = andptr-and;
81e887ea33SDavid du Colombier if(m != p->mark) {
82e887ea33SDavid du Colombier p->mark = m;
83e887ea33SDavid du Colombier again++;
84e887ea33SDavid du Colombier }
85e887ea33SDavid du Colombier }
86e887ea33SDavid du Colombier p->pc = c;
87e887ea33SDavid du Colombier c += p->mark;
88e887ea33SDavid du Colombier }
89e887ea33SDavid du Colombier if(again) {
90e887ea33SDavid du Colombier textsize = c;
91e887ea33SDavid du Colombier goto loop;
92e887ea33SDavid du Colombier }
93e887ea33SDavid du Colombier if(INITRND) {
94e887ea33SDavid du Colombier INITDAT = rnd(c, INITRND);
95e887ea33SDavid du Colombier if(INITDAT != idat) {
96e887ea33SDavid du Colombier idat = INITDAT;
97e887ea33SDavid du Colombier goto start;
98e887ea33SDavid du Colombier }
99e887ea33SDavid du Colombier }
100e887ea33SDavid du Colombier xdefine("etext", STEXT, c);
101e887ea33SDavid du Colombier if(debug['v'])
102e887ea33SDavid du Colombier Bprint(&bso, "etext = %llux\n", c);
103e887ea33SDavid du Colombier Bflush(&bso);
104e887ea33SDavid du Colombier for(p = textp; p != P; p = p->pcond)
105e887ea33SDavid du Colombier p->from.sym->value = p->pc;
106e887ea33SDavid du Colombier textsize = c - INITTEXT;
107e887ea33SDavid du Colombier }
108e887ea33SDavid du Colombier
109e887ea33SDavid du Colombier void
xdefine(char * p,int t,vlong v)110e887ea33SDavid du Colombier xdefine(char *p, int t, vlong v)
111e887ea33SDavid du Colombier {
112e887ea33SDavid du Colombier Sym *s;
113e887ea33SDavid du Colombier
114e887ea33SDavid du Colombier s = lookup(p, 0);
115e887ea33SDavid du Colombier if(s->type == 0 || s->type == SXREF) {
116e887ea33SDavid du Colombier s->type = t;
117e887ea33SDavid du Colombier s->value = v;
118e887ea33SDavid du Colombier }
119e887ea33SDavid du Colombier if(s->type == STEXT && s->value == 0)
120e887ea33SDavid du Colombier s->value = v;
121e887ea33SDavid du Colombier }
122e887ea33SDavid du Colombier
123e887ea33SDavid du Colombier void
putsymb(char * s,int t,vlong v,int ver)124e887ea33SDavid du Colombier putsymb(char *s, int t, vlong v, int ver)
125e887ea33SDavid du Colombier {
126e887ea33SDavid du Colombier int i, f, l;
127e887ea33SDavid du Colombier
128e887ea33SDavid du Colombier if(t == 'f')
129e887ea33SDavid du Colombier s++;
130e887ea33SDavid du Colombier l = 4;
131b87cd620SDavid du Colombier switch(HEADTYPE){
132b87cd620SDavid du Colombier default:
133b87cd620SDavid du Colombier break;
134b87cd620SDavid du Colombier case 5:
135b87cd620SDavid du Colombier if(debug['8'])
136b87cd620SDavid du Colombier break;
137b87cd620SDavid du Colombier case 2:
138b87cd620SDavid du Colombier case 6:
139e887ea33SDavid du Colombier lput(v>>32);
140e887ea33SDavid du Colombier l = 8;
141b87cd620SDavid du Colombier break;
142e887ea33SDavid du Colombier }
143e887ea33SDavid du Colombier lput(v);
144e887ea33SDavid du Colombier if(ver)
145e887ea33SDavid du Colombier t += 'a' - 'A';
146e887ea33SDavid du Colombier cput(t+0x80); /* 0x80 is variable length */
147e887ea33SDavid du Colombier
148e887ea33SDavid du Colombier if(t == 'Z' || t == 'z') {
149e887ea33SDavid du Colombier cput(s[0]);
150e887ea33SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
151e887ea33SDavid du Colombier cput(s[i]);
152e887ea33SDavid du Colombier cput(s[i+1]);
153e887ea33SDavid du Colombier }
154e887ea33SDavid du Colombier cput(0);
155e887ea33SDavid du Colombier cput(0);
156e887ea33SDavid du Colombier i++;
157e887ea33SDavid du Colombier }
158e887ea33SDavid du Colombier else {
159e887ea33SDavid du Colombier for(i=0; s[i]; i++)
160e887ea33SDavid du Colombier cput(s[i]);
161e887ea33SDavid du Colombier cput(0);
162e887ea33SDavid du Colombier }
163e887ea33SDavid du Colombier symsize += l + 1 + i + 1;
164e887ea33SDavid du Colombier
165e887ea33SDavid du Colombier if(debug['n']) {
166e887ea33SDavid du Colombier if(t == 'z' || t == 'Z') {
167e887ea33SDavid du Colombier Bprint(&bso, "%c %.8llux ", t, v);
168e887ea33SDavid du Colombier for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
169e887ea33SDavid du Colombier f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
170e887ea33SDavid du Colombier Bprint(&bso, "/%x", f);
171e887ea33SDavid du Colombier }
172e887ea33SDavid du Colombier Bprint(&bso, "\n");
173e887ea33SDavid du Colombier return;
174e887ea33SDavid du Colombier }
175e887ea33SDavid du Colombier if(ver)
176e887ea33SDavid du Colombier Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
177e887ea33SDavid du Colombier else
178e887ea33SDavid du Colombier Bprint(&bso, "%c %.8llux %s\n", t, v, s);
179e887ea33SDavid du Colombier }
180e887ea33SDavid du Colombier }
181e887ea33SDavid du Colombier
182e887ea33SDavid du Colombier void
asmsym(void)183e887ea33SDavid du Colombier asmsym(void)
184e887ea33SDavid du Colombier {
185e887ea33SDavid du Colombier Prog *p;
186e887ea33SDavid du Colombier Auto *a;
187e887ea33SDavid du Colombier Sym *s;
188e887ea33SDavid du Colombier int h;
189e887ea33SDavid du Colombier
190e887ea33SDavid du Colombier s = lookup("etext", 0);
191e887ea33SDavid du Colombier if(s->type == STEXT)
192e887ea33SDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
193e887ea33SDavid du Colombier
194e887ea33SDavid du Colombier for(h=0; h<NHASH; h++)
195e887ea33SDavid du Colombier for(s=hash[h]; s!=S; s=s->link)
196e887ea33SDavid du Colombier switch(s->type) {
197e887ea33SDavid du Colombier case SCONST:
198e887ea33SDavid du Colombier putsymb(s->name, 'D', s->value, s->version);
199e887ea33SDavid du Colombier continue;
200e887ea33SDavid du Colombier
201e887ea33SDavid du Colombier case SDATA:
202e887ea33SDavid du Colombier putsymb(s->name, 'D', s->value+INITDAT, s->version);
203e887ea33SDavid du Colombier continue;
204e887ea33SDavid du Colombier
205e887ea33SDavid du Colombier case SBSS:
206e887ea33SDavid du Colombier putsymb(s->name, 'B', s->value+INITDAT, s->version);
207e887ea33SDavid du Colombier continue;
208e887ea33SDavid du Colombier
209e887ea33SDavid du Colombier case SFILE:
210e887ea33SDavid du Colombier putsymb(s->name, 'f', s->value, s->version);
211e887ea33SDavid du Colombier continue;
212e887ea33SDavid du Colombier }
213e887ea33SDavid du Colombier
214e887ea33SDavid du Colombier for(p=textp; p!=P; p=p->pcond) {
215e887ea33SDavid du Colombier s = p->from.sym;
216e887ea33SDavid du Colombier if(s->type != STEXT)
217e887ea33SDavid du Colombier continue;
218e887ea33SDavid du Colombier
219e887ea33SDavid du Colombier /* filenames first */
220e887ea33SDavid du Colombier for(a=p->to.autom; a; a=a->link)
221e887ea33SDavid du Colombier if(a->type == D_FILE)
222e887ea33SDavid du Colombier putsymb(a->asym->name, 'z', a->aoffset, 0);
223e887ea33SDavid du Colombier else
224e887ea33SDavid du Colombier if(a->type == D_FILE1)
225e887ea33SDavid du Colombier putsymb(a->asym->name, 'Z', a->aoffset, 0);
226e887ea33SDavid du Colombier
227e887ea33SDavid du Colombier putsymb(s->name, 'T', s->value, s->version);
228e887ea33SDavid du Colombier
229e887ea33SDavid du Colombier /* frame, auto and param after */
230e887ea33SDavid du Colombier putsymb(".frame", 'm', p->to.offset+8, 0);
231e887ea33SDavid du Colombier
232e887ea33SDavid du Colombier for(a=p->to.autom; a; a=a->link)
233e887ea33SDavid du Colombier if(a->type == D_AUTO)
234e887ea33SDavid du Colombier putsymb(a->asym->name, 'a', -a->aoffset, 0);
235e887ea33SDavid du Colombier else
236e887ea33SDavid du Colombier if(a->type == D_PARAM)
237e887ea33SDavid du Colombier putsymb(a->asym->name, 'p', a->aoffset, 0);
238e887ea33SDavid du Colombier }
239e887ea33SDavid du Colombier if(debug['v'] || debug['n'])
240e887ea33SDavid du Colombier Bprint(&bso, "symsize = %lud\n", symsize);
241e887ea33SDavid du Colombier Bflush(&bso);
242e887ea33SDavid du Colombier }
243e887ea33SDavid du Colombier
244e887ea33SDavid du Colombier void
asmlc(void)245e887ea33SDavid du Colombier asmlc(void)
246e887ea33SDavid du Colombier {
247e887ea33SDavid du Colombier vlong oldpc;
248e887ea33SDavid du Colombier Prog *p;
249e887ea33SDavid du Colombier long oldlc, v, s;
250e887ea33SDavid du Colombier
251e887ea33SDavid du Colombier oldpc = INITTEXT;
252e887ea33SDavid du Colombier oldlc = 0;
253e887ea33SDavid du Colombier for(p = firstp; p != P; p = p->link) {
254e887ea33SDavid du Colombier if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
255e887ea33SDavid du Colombier if(p->as == ATEXT)
256e887ea33SDavid du Colombier curtext = p;
257b87cd620SDavid du Colombier if(debug['V'])
258e887ea33SDavid du Colombier Bprint(&bso, "%6llux %P\n",
259e887ea33SDavid du Colombier p->pc, p);
260e887ea33SDavid du Colombier continue;
261e887ea33SDavid du Colombier }
262b87cd620SDavid du Colombier if(debug['V'])
263e887ea33SDavid du Colombier Bprint(&bso, "\t\t%6ld", lcsize);
264e887ea33SDavid du Colombier v = (p->pc - oldpc) / MINLC;
265e887ea33SDavid du Colombier while(v) {
266e887ea33SDavid du Colombier s = 127;
267e887ea33SDavid du Colombier if(v < 127)
268e887ea33SDavid du Colombier s = v;
269e887ea33SDavid du Colombier cput(s+128); /* 129-255 +pc */
270b87cd620SDavid du Colombier if(debug['V'])
271e887ea33SDavid du Colombier Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
272e887ea33SDavid du Colombier v -= s;
273e887ea33SDavid du Colombier lcsize++;
274e887ea33SDavid du Colombier }
275e887ea33SDavid du Colombier s = p->line - oldlc;
276e887ea33SDavid du Colombier oldlc = p->line;
277e887ea33SDavid du Colombier oldpc = p->pc + MINLC;
278e887ea33SDavid du Colombier if(s > 64 || s < -64) {
279e887ea33SDavid du Colombier cput(0); /* 0 vv +lc */
280e887ea33SDavid du Colombier cput(s>>24);
281e887ea33SDavid du Colombier cput(s>>16);
282e887ea33SDavid du Colombier cput(s>>8);
283e887ea33SDavid du Colombier cput(s);
284b87cd620SDavid du Colombier if(debug['V']) {
285e887ea33SDavid du Colombier if(s > 0)
286e887ea33SDavid du Colombier Bprint(&bso, " lc+%ld(%d,%ld)\n",
287e887ea33SDavid du Colombier s, 0, s);
288e887ea33SDavid du Colombier else
289e887ea33SDavid du Colombier Bprint(&bso, " lc%ld(%d,%ld)\n",
290e887ea33SDavid du Colombier s, 0, s);
291e887ea33SDavid du Colombier Bprint(&bso, "%6llux %P\n",
292e887ea33SDavid du Colombier p->pc, p);
293e887ea33SDavid du Colombier }
294e887ea33SDavid du Colombier lcsize += 5;
295e887ea33SDavid du Colombier continue;
296e887ea33SDavid du Colombier }
297e887ea33SDavid du Colombier if(s > 0) {
298e887ea33SDavid du Colombier cput(0+s); /* 1-64 +lc */
299b87cd620SDavid du Colombier if(debug['V']) {
300e887ea33SDavid du Colombier Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
301e887ea33SDavid du Colombier Bprint(&bso, "%6llux %P\n",
302e887ea33SDavid du Colombier p->pc, p);
303e887ea33SDavid du Colombier }
304e887ea33SDavid du Colombier } else {
305e887ea33SDavid du Colombier cput(64-s); /* 65-128 -lc */
306b87cd620SDavid du Colombier if(debug['V']) {
307e887ea33SDavid du Colombier Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
308e887ea33SDavid du Colombier Bprint(&bso, "%6llux %P\n",
309e887ea33SDavid du Colombier p->pc, p);
310e887ea33SDavid du Colombier }
311e887ea33SDavid du Colombier }
312e887ea33SDavid du Colombier lcsize++;
313e887ea33SDavid du Colombier }
314e887ea33SDavid du Colombier while(lcsize & 1) {
315e887ea33SDavid du Colombier s = 129;
316e887ea33SDavid du Colombier cput(s);
317e887ea33SDavid du Colombier lcsize++;
318e887ea33SDavid du Colombier }
319b87cd620SDavid du Colombier if(debug['v'] || debug['V'])
320e887ea33SDavid du Colombier Bprint(&bso, "lcsize = %ld\n", lcsize);
321e887ea33SDavid du Colombier Bflush(&bso);
322e887ea33SDavid du Colombier }
323e887ea33SDavid du Colombier
324e887ea33SDavid du Colombier int
prefixof(Adr * a)325*40d01547SDavid du Colombier prefixof(Adr *a)
326*40d01547SDavid du Colombier {
327*40d01547SDavid du Colombier switch(a->type) {
328*40d01547SDavid du Colombier case D_INDIR+D_CS:
329*40d01547SDavid du Colombier return 0x2e;
330*40d01547SDavid du Colombier case D_INDIR+D_DS:
331*40d01547SDavid du Colombier return 0x3e;
332*40d01547SDavid du Colombier case D_INDIR+D_ES:
333*40d01547SDavid du Colombier return 0x26;
334*40d01547SDavid du Colombier case D_INDIR+D_FS:
335*40d01547SDavid du Colombier return 0x64;
336*40d01547SDavid du Colombier case D_INDIR+D_GS:
337*40d01547SDavid du Colombier return 0x65;
338*40d01547SDavid du Colombier }
339*40d01547SDavid du Colombier return 0;
340*40d01547SDavid du Colombier }
341*40d01547SDavid du Colombier
342*40d01547SDavid du Colombier int
oclass(Adr * a)343e887ea33SDavid du Colombier oclass(Adr *a)
344e887ea33SDavid du Colombier {
345e887ea33SDavid du Colombier vlong v;
346e887ea33SDavid du Colombier long l;
347e887ea33SDavid du Colombier
348*40d01547SDavid du Colombier if(a->type < D_CONST2 && (a->type >= D_INDIR || !isxyreg(a->type) && a->index != D_NONE)) {
349e887ea33SDavid du Colombier if(a->index != D_NONE && a->scale == 0) {
350e887ea33SDavid du Colombier if(a->type == D_ADDR) {
351e887ea33SDavid du Colombier switch(a->index) {
352e887ea33SDavid du Colombier case D_EXTERN:
353e887ea33SDavid du Colombier case D_STATIC:
354e887ea33SDavid du Colombier return Yi32; /* TO DO: Yi64 */
355e887ea33SDavid du Colombier case D_AUTO:
356e887ea33SDavid du Colombier case D_PARAM:
357e887ea33SDavid du Colombier return Yiauto;
358e887ea33SDavid du Colombier }
359e887ea33SDavid du Colombier return Yxxx;
360e887ea33SDavid du Colombier }
361e887ea33SDavid du Colombier return Ycol;
362e887ea33SDavid du Colombier }
363e887ea33SDavid du Colombier return Ym;
364e887ea33SDavid du Colombier }
365e887ea33SDavid du Colombier switch(a->type)
366e887ea33SDavid du Colombier {
367e887ea33SDavid du Colombier case D_AL:
368e887ea33SDavid du Colombier return Yal;
369e887ea33SDavid du Colombier
370e887ea33SDavid du Colombier case D_AX:
371e887ea33SDavid du Colombier return Yax;
372e887ea33SDavid du Colombier
373e887ea33SDavid du Colombier /*
374e887ea33SDavid du Colombier case D_SPB:
375e887ea33SDavid du Colombier */
376e887ea33SDavid du Colombier case D_BPB:
377e887ea33SDavid du Colombier case D_SIB:
378e887ea33SDavid du Colombier case D_DIB:
379e887ea33SDavid du Colombier case D_R8B:
380e887ea33SDavid du Colombier case D_R9B:
381e887ea33SDavid du Colombier case D_R10B:
382e887ea33SDavid du Colombier case D_R11B:
383e887ea33SDavid du Colombier case D_R12B:
384e887ea33SDavid du Colombier case D_R13B:
385e887ea33SDavid du Colombier case D_R14B:
386e887ea33SDavid du Colombier case D_R15B:
387e887ea33SDavid du Colombier if(asmode != 64)
388e887ea33SDavid du Colombier return Yxxx;
389e887ea33SDavid du Colombier case D_DL:
390e887ea33SDavid du Colombier case D_BL:
391e887ea33SDavid du Colombier case D_AH:
392e887ea33SDavid du Colombier case D_CH:
393e887ea33SDavid du Colombier case D_DH:
394e887ea33SDavid du Colombier case D_BH:
395e887ea33SDavid du Colombier return Yrb;
396e887ea33SDavid du Colombier
397e887ea33SDavid du Colombier case D_CL:
398e887ea33SDavid du Colombier return Ycl;
399e887ea33SDavid du Colombier
400e887ea33SDavid du Colombier case D_CX:
401e887ea33SDavid du Colombier return Ycx;
402e887ea33SDavid du Colombier
403e887ea33SDavid du Colombier case D_DX:
404e887ea33SDavid du Colombier case D_BX:
405e887ea33SDavid du Colombier return Yrx;
406e887ea33SDavid du Colombier
407e887ea33SDavid du Colombier case D_R8: /* not really Yrl */
408e887ea33SDavid du Colombier case D_R9:
409e887ea33SDavid du Colombier case D_R10:
410e887ea33SDavid du Colombier case D_R11:
411e887ea33SDavid du Colombier case D_R12:
412e887ea33SDavid du Colombier case D_R13:
413e887ea33SDavid du Colombier case D_R14:
414e887ea33SDavid du Colombier case D_R15:
415e887ea33SDavid du Colombier if(asmode != 64)
416e887ea33SDavid du Colombier return Yxxx;
417e887ea33SDavid du Colombier case D_SP:
418e887ea33SDavid du Colombier case D_BP:
419e887ea33SDavid du Colombier case D_SI:
420e887ea33SDavid du Colombier case D_DI:
421e887ea33SDavid du Colombier return Yrl;
422e887ea33SDavid du Colombier
423*40d01547SDavid du Colombier /*
424e887ea33SDavid du Colombier case D_F0+0:
425e887ea33SDavid du Colombier return Yf0;
426e887ea33SDavid du Colombier
427e887ea33SDavid du Colombier case D_F0+1:
428e887ea33SDavid du Colombier case D_F0+2:
429e887ea33SDavid du Colombier case D_F0+3:
430e887ea33SDavid du Colombier case D_F0+4:
431e887ea33SDavid du Colombier case D_F0+5:
432e887ea33SDavid du Colombier case D_F0+6:
433e887ea33SDavid du Colombier case D_F0+7:
434e887ea33SDavid du Colombier return Yrf;
435*40d01547SDavid du Colombier */
436e887ea33SDavid du Colombier
437e887ea33SDavid du Colombier case D_M0+0:
438e887ea33SDavid du Colombier case D_M0+1:
439e887ea33SDavid du Colombier case D_M0+2:
440e887ea33SDavid du Colombier case D_M0+3:
441e887ea33SDavid du Colombier case D_M0+4:
442e887ea33SDavid du Colombier case D_M0+5:
443e887ea33SDavid du Colombier case D_M0+6:
444e887ea33SDavid du Colombier case D_M0+7:
445e887ea33SDavid du Colombier return Ymr;
446e887ea33SDavid du Colombier
447e887ea33SDavid du Colombier case D_X0+0:
448e887ea33SDavid du Colombier case D_X0+1:
449e887ea33SDavid du Colombier case D_X0+2:
450e887ea33SDavid du Colombier case D_X0+3:
451e887ea33SDavid du Colombier case D_X0+4:
452e887ea33SDavid du Colombier case D_X0+5:
453e887ea33SDavid du Colombier case D_X0+6:
454e887ea33SDavid du Colombier case D_X0+7:
455e887ea33SDavid du Colombier case D_X0+8:
456e887ea33SDavid du Colombier case D_X0+9:
457e887ea33SDavid du Colombier case D_X0+10:
458e887ea33SDavid du Colombier case D_X0+11:
459e887ea33SDavid du Colombier case D_X0+12:
460e887ea33SDavid du Colombier case D_X0+13:
461e887ea33SDavid du Colombier case D_X0+14:
462e887ea33SDavid du Colombier case D_X0+15:
463e887ea33SDavid du Colombier return Yxr;
464e887ea33SDavid du Colombier
465*40d01547SDavid du Colombier case D_Y0+0:
466*40d01547SDavid du Colombier case D_Y0+1:
467*40d01547SDavid du Colombier case D_Y0+2:
468*40d01547SDavid du Colombier case D_Y0+3:
469*40d01547SDavid du Colombier case D_Y0+4:
470*40d01547SDavid du Colombier case D_Y0+5:
471*40d01547SDavid du Colombier case D_Y0+6:
472*40d01547SDavid du Colombier case D_Y0+7:
473*40d01547SDavid du Colombier case D_Y0+8:
474*40d01547SDavid du Colombier case D_Y0+9:
475*40d01547SDavid du Colombier case D_Y0+10:
476*40d01547SDavid du Colombier case D_Y0+11:
477*40d01547SDavid du Colombier case D_Y0+12:
478*40d01547SDavid du Colombier case D_Y0+13:
479*40d01547SDavid du Colombier case D_Y0+14:
480*40d01547SDavid du Colombier case D_Y0+15:
481*40d01547SDavid du Colombier return Yyr;
482*40d01547SDavid du Colombier
483e887ea33SDavid du Colombier case D_NONE:
484e887ea33SDavid du Colombier return Ynone;
485e887ea33SDavid du Colombier
486e887ea33SDavid du Colombier case D_CS: return Ycs;
487e887ea33SDavid du Colombier case D_SS: return Yss;
488e887ea33SDavid du Colombier case D_DS: return Yds;
489e887ea33SDavid du Colombier case D_ES: return Yes;
490e887ea33SDavid du Colombier case D_FS: return Yfs;
491e887ea33SDavid du Colombier case D_GS: return Ygs;
492e887ea33SDavid du Colombier
493e887ea33SDavid du Colombier case D_GDTR: return Ygdtr;
494e887ea33SDavid du Colombier case D_IDTR: return Yidtr;
495e887ea33SDavid du Colombier case D_LDTR: return Yldtr;
496e887ea33SDavid du Colombier case D_MSW: return Ymsw;
497e887ea33SDavid du Colombier case D_TASK: return Ytask;
498e887ea33SDavid du Colombier
499e887ea33SDavid du Colombier case D_CR+0: return Ycr0;
500e887ea33SDavid du Colombier case D_CR+1: return Ycr1;
501e887ea33SDavid du Colombier case D_CR+2: return Ycr2;
502e887ea33SDavid du Colombier case D_CR+3: return Ycr3;
503e887ea33SDavid du Colombier case D_CR+4: return Ycr4;
504e887ea33SDavid du Colombier case D_CR+5: return Ycr5;
505e887ea33SDavid du Colombier case D_CR+6: return Ycr6;
506e887ea33SDavid du Colombier case D_CR+7: return Ycr7;
507e887ea33SDavid du Colombier case D_CR+8: return Ycr8;
508e887ea33SDavid du Colombier
509e887ea33SDavid du Colombier case D_DR+0: return Ydr0;
510e887ea33SDavid du Colombier case D_DR+1: return Ydr1;
511e887ea33SDavid du Colombier case D_DR+2: return Ydr2;
512e887ea33SDavid du Colombier case D_DR+3: return Ydr3;
513e887ea33SDavid du Colombier case D_DR+4: return Ydr4;
514e887ea33SDavid du Colombier case D_DR+5: return Ydr5;
515e887ea33SDavid du Colombier case D_DR+6: return Ydr6;
516e887ea33SDavid du Colombier case D_DR+7: return Ydr7;
517e887ea33SDavid du Colombier
518e887ea33SDavid du Colombier case D_TR+0: return Ytr0;
519e887ea33SDavid du Colombier case D_TR+1: return Ytr1;
520e887ea33SDavid du Colombier case D_TR+2: return Ytr2;
521e887ea33SDavid du Colombier case D_TR+3: return Ytr3;
522e887ea33SDavid du Colombier case D_TR+4: return Ytr4;
523e887ea33SDavid du Colombier case D_TR+5: return Ytr5;
524e887ea33SDavid du Colombier case D_TR+6: return Ytr6;
525e887ea33SDavid du Colombier case D_TR+7: return Ytr7;
526e887ea33SDavid du Colombier
527e887ea33SDavid du Colombier case D_EXTERN:
528e887ea33SDavid du Colombier case D_STATIC:
529e887ea33SDavid du Colombier case D_AUTO:
530e887ea33SDavid du Colombier case D_PARAM:
531e887ea33SDavid du Colombier return Ym;
532e887ea33SDavid du Colombier
533e887ea33SDavid du Colombier case D_CONST:
534e887ea33SDavid du Colombier case D_ADDR:
535e887ea33SDavid du Colombier if(a->sym == S) {
536e887ea33SDavid du Colombier v = a->offset;
537e887ea33SDavid du Colombier if(v == 0)
538e887ea33SDavid du Colombier return Yi0;
539e887ea33SDavid du Colombier if(v == 1)
540e887ea33SDavid du Colombier return Yi1;
541e887ea33SDavid du Colombier if(v >= -128 && v <= 127)
542e887ea33SDavid du Colombier return Yi8;
543e887ea33SDavid du Colombier l = v;
544e887ea33SDavid du Colombier if((vlong)l == v)
545e887ea33SDavid du Colombier return Ys32; /* can sign extend */
546e887ea33SDavid du Colombier if((v>>32) == 0)
547e887ea33SDavid du Colombier return Yi32; /* unsigned */
548e887ea33SDavid du Colombier return Yi64;
549e887ea33SDavid du Colombier }
550e887ea33SDavid du Colombier return Yi32; /* TO DO: D_ADDR as Yi64 */
551e887ea33SDavid du Colombier
552e887ea33SDavid du Colombier case D_BRANCH:
553e887ea33SDavid du Colombier return Ybr;
554e887ea33SDavid du Colombier }
555e887ea33SDavid du Colombier return Yxxx;
556e887ea33SDavid du Colombier }
557e887ea33SDavid du Colombier
558e887ea33SDavid du Colombier void
asmidx(Adr * a,int base)559e887ea33SDavid du Colombier asmidx(Adr *a, int base)
560e887ea33SDavid du Colombier {
561e887ea33SDavid du Colombier int i;
562e887ea33SDavid du Colombier
563e887ea33SDavid du Colombier switch(a->index) {
564e887ea33SDavid du Colombier default:
565e887ea33SDavid du Colombier goto bad;
566e887ea33SDavid du Colombier
567e887ea33SDavid du Colombier case D_NONE:
568e887ea33SDavid du Colombier i = 4 << 3;
569e887ea33SDavid du Colombier goto bas;
570e887ea33SDavid du Colombier
571e887ea33SDavid du Colombier case D_R8:
572e887ea33SDavid du Colombier case D_R9:
573e887ea33SDavid du Colombier case D_R10:
574e887ea33SDavid du Colombier case D_R11:
575e887ea33SDavid du Colombier case D_R12:
576e887ea33SDavid du Colombier case D_R13:
577e887ea33SDavid du Colombier case D_R14:
578e887ea33SDavid du Colombier case D_R15:
579e887ea33SDavid du Colombier if(asmode != 64)
580e887ea33SDavid du Colombier goto bad;
581e887ea33SDavid du Colombier case D_AX:
582e887ea33SDavid du Colombier case D_CX:
583e887ea33SDavid du Colombier case D_DX:
584e887ea33SDavid du Colombier case D_BX:
585e887ea33SDavid du Colombier case D_BP:
586e887ea33SDavid du Colombier case D_SI:
587e887ea33SDavid du Colombier case D_DI:
588e887ea33SDavid du Colombier i = reg[a->index] << 3;
589e887ea33SDavid du Colombier break;
590e887ea33SDavid du Colombier }
591e887ea33SDavid du Colombier switch(a->scale) {
592e887ea33SDavid du Colombier default:
593e887ea33SDavid du Colombier goto bad;
594e887ea33SDavid du Colombier case 1:
595e887ea33SDavid du Colombier break;
596e887ea33SDavid du Colombier case 2:
597e887ea33SDavid du Colombier i |= (1<<6);
598e887ea33SDavid du Colombier break;
599e887ea33SDavid du Colombier case 4:
600e887ea33SDavid du Colombier i |= (2<<6);
601e887ea33SDavid du Colombier break;
602e887ea33SDavid du Colombier case 8:
603e887ea33SDavid du Colombier i |= (3<<6);
604e887ea33SDavid du Colombier break;
605e887ea33SDavid du Colombier }
606e887ea33SDavid du Colombier bas:
607e887ea33SDavid du Colombier switch(base) {
608e887ea33SDavid du Colombier default:
609e887ea33SDavid du Colombier goto bad;
610e887ea33SDavid du Colombier case D_NONE: /* must be mod=00 */
611e887ea33SDavid du Colombier i |= 5;
612e887ea33SDavid du Colombier break;
613e887ea33SDavid du Colombier case D_R8:
614e887ea33SDavid du Colombier case D_R9:
615e887ea33SDavid du Colombier case D_R10:
616e887ea33SDavid du Colombier case D_R11:
617e887ea33SDavid du Colombier case D_R12:
618e887ea33SDavid du Colombier case D_R13:
619e887ea33SDavid du Colombier case D_R14:
620e887ea33SDavid du Colombier case D_R15:
621e887ea33SDavid du Colombier if(asmode != 64)
622e887ea33SDavid du Colombier goto bad;
623e887ea33SDavid du Colombier case D_AX:
624e887ea33SDavid du Colombier case D_CX:
625e887ea33SDavid du Colombier case D_DX:
626e887ea33SDavid du Colombier case D_BX:
627e887ea33SDavid du Colombier case D_SP:
628e887ea33SDavid du Colombier case D_BP:
629e887ea33SDavid du Colombier case D_SI:
630e887ea33SDavid du Colombier case D_DI:
631e887ea33SDavid du Colombier i |= reg[base];
632e887ea33SDavid du Colombier break;
633e887ea33SDavid du Colombier }
634e887ea33SDavid du Colombier *andptr++ = i;
635e887ea33SDavid du Colombier return;
636e887ea33SDavid du Colombier bad:
637e887ea33SDavid du Colombier diag("asmidx: bad address %D", a);
638e887ea33SDavid du Colombier *andptr++ = 0;
639e887ea33SDavid du Colombier return;
640e887ea33SDavid du Colombier }
641e887ea33SDavid du Colombier
642e887ea33SDavid du Colombier static void
put4(long v)643e887ea33SDavid du Colombier put4(long v)
644e887ea33SDavid du Colombier {
645e887ea33SDavid du Colombier if(dlm && curp != P && reloca != nil){
646e887ea33SDavid du Colombier dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
647e887ea33SDavid du Colombier reloca = nil;
648e887ea33SDavid du Colombier }
649e887ea33SDavid du Colombier andptr[0] = v;
650e887ea33SDavid du Colombier andptr[1] = v>>8;
651e887ea33SDavid du Colombier andptr[2] = v>>16;
652e887ea33SDavid du Colombier andptr[3] = v>>24;
653e887ea33SDavid du Colombier andptr += 4;
654e887ea33SDavid du Colombier }
655e887ea33SDavid du Colombier
656e887ea33SDavid du Colombier static void
put8(vlong v)657e887ea33SDavid du Colombier put8(vlong v)
658e887ea33SDavid du Colombier {
659e887ea33SDavid du Colombier if(dlm && curp != P && reloca != nil){
660e887ea33SDavid du Colombier dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1); /* TO DO */
661e887ea33SDavid du Colombier reloca = nil;
662e887ea33SDavid du Colombier }
663e887ea33SDavid du Colombier andptr[0] = v;
664e887ea33SDavid du Colombier andptr[1] = v>>8;
665e887ea33SDavid du Colombier andptr[2] = v>>16;
666e887ea33SDavid du Colombier andptr[3] = v>>24;
667e887ea33SDavid du Colombier andptr[4] = v>>32;
668e887ea33SDavid du Colombier andptr[5] = v>>40;
669e887ea33SDavid du Colombier andptr[6] = v>>48;
670e887ea33SDavid du Colombier andptr[7] = v>>56;
671e887ea33SDavid du Colombier andptr += 8;
672e887ea33SDavid du Colombier }
673e887ea33SDavid du Colombier
674e887ea33SDavid du Colombier vlong
vaddr(Adr * a)675e887ea33SDavid du Colombier vaddr(Adr *a)
676e887ea33SDavid du Colombier {
677e887ea33SDavid du Colombier int t;
678e887ea33SDavid du Colombier vlong v;
679e887ea33SDavid du Colombier Sym *s;
680e887ea33SDavid du Colombier
681e887ea33SDavid du Colombier t = a->type;
682e887ea33SDavid du Colombier v = a->offset;
683e887ea33SDavid du Colombier if(t == D_ADDR)
684e887ea33SDavid du Colombier t = a->index;
685e887ea33SDavid du Colombier switch(t) {
686e887ea33SDavid du Colombier case D_STATIC:
687e887ea33SDavid du Colombier case D_EXTERN:
688e887ea33SDavid du Colombier s = a->sym;
689e887ea33SDavid du Colombier if(s != nil) {
690e887ea33SDavid du Colombier if(dlm && curp != P)
691e887ea33SDavid du Colombier reloca = a;
692e887ea33SDavid du Colombier switch(s->type) {
693e887ea33SDavid du Colombier case SUNDEF:
694e887ea33SDavid du Colombier ckoff(s, v);
695e887ea33SDavid du Colombier case STEXT:
696e887ea33SDavid du Colombier case SCONST:
697e887ea33SDavid du Colombier if((uvlong)s->value < (uvlong)INITTEXT)
698e887ea33SDavid du Colombier v += INITTEXT; /* TO DO */
699e887ea33SDavid du Colombier v += s->value;
700e887ea33SDavid du Colombier break;
701e887ea33SDavid du Colombier default:
702e887ea33SDavid du Colombier v += INITDAT + s->value;
703e887ea33SDavid du Colombier }
704e887ea33SDavid du Colombier }
705e887ea33SDavid du Colombier }
706e887ea33SDavid du Colombier return v;
707e887ea33SDavid du Colombier }
708e887ea33SDavid du Colombier
709e887ea33SDavid du Colombier static void
asmandsz(Adr * a,int r,int rex,int m64)710e887ea33SDavid du Colombier asmandsz(Adr *a, int r, int rex, int m64)
711e887ea33SDavid du Colombier {
712e887ea33SDavid du Colombier long v;
713e887ea33SDavid du Colombier int t;
714e887ea33SDavid du Colombier Adr aa;
715e887ea33SDavid du Colombier
716*40d01547SDavid du Colombier if(r == -1)
717*40d01547SDavid du Colombier diag("asmandsz: immedate instead of register");
718*40d01547SDavid du Colombier
719e887ea33SDavid du Colombier rex &= (0x40 | Rxr);
720e887ea33SDavid du Colombier v = a->offset;
721e887ea33SDavid du Colombier t = a->type;
722*40d01547SDavid du Colombier if(a->index != D_NONE && !isxyreg(t)) {
723*40d01547SDavid du Colombier if(t >= D_INDIR && t < D_CONST2) {
724e887ea33SDavid du Colombier t -= D_INDIR;
725e887ea33SDavid du Colombier rexflag |= (regrex[a->index] & Rxx) | (regrex[t] & Rxb) | rex;
726e887ea33SDavid du Colombier if(t == D_NONE) {
727e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
728e887ea33SDavid du Colombier asmidx(a, t);
729e887ea33SDavid du Colombier put4(v);
730e887ea33SDavid du Colombier return;
731e887ea33SDavid du Colombier }
732e887ea33SDavid du Colombier if(v == 0 && t != D_BP && t != D_R13) {
733e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
734e887ea33SDavid du Colombier asmidx(a, t);
735e887ea33SDavid du Colombier return;
736e887ea33SDavid du Colombier }
737e887ea33SDavid du Colombier if(v >= -128 && v < 128) {
738e887ea33SDavid du Colombier *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
739e887ea33SDavid du Colombier asmidx(a, t);
740e887ea33SDavid du Colombier *andptr++ = v;
741e887ea33SDavid du Colombier return;
742e887ea33SDavid du Colombier }
743e887ea33SDavid du Colombier *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
744e887ea33SDavid du Colombier asmidx(a, t);
745e887ea33SDavid du Colombier put4(v);
746e887ea33SDavid du Colombier return;
747e887ea33SDavid du Colombier }
748e887ea33SDavid du Colombier switch(t) {
749e887ea33SDavid du Colombier default:
750e887ea33SDavid du Colombier goto bad;
751e887ea33SDavid du Colombier case D_STATIC:
752e887ea33SDavid du Colombier case D_EXTERN:
753e887ea33SDavid du Colombier aa.type = D_NONE+D_INDIR;
754e887ea33SDavid du Colombier break;
755e887ea33SDavid du Colombier case D_AUTO:
756e887ea33SDavid du Colombier case D_PARAM:
757e887ea33SDavid du Colombier aa.type = D_SP+D_INDIR;
758e887ea33SDavid du Colombier break;
759e887ea33SDavid du Colombier }
760e887ea33SDavid du Colombier aa.offset = vaddr(a);
761e887ea33SDavid du Colombier aa.index = a->index;
762e887ea33SDavid du Colombier aa.scale = a->scale;
763e887ea33SDavid du Colombier asmandsz(&aa, r, rex, m64);
764e887ea33SDavid du Colombier return;
765e887ea33SDavid du Colombier }
766*40d01547SDavid du Colombier if(t >= D_AL && t <= D_BH) {
767e887ea33SDavid du Colombier if(v)
768e887ea33SDavid du Colombier goto bad;
769e887ea33SDavid du Colombier *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
770e887ea33SDavid du Colombier rexflag |= (regrex[t] & (0x40 | Rxb)) | rex;
771e887ea33SDavid du Colombier return;
772e887ea33SDavid du Colombier }
773*40d01547SDavid du Colombier if(t >= D_X0 && t <= D_X15 || t >= D_Y0 && t <= D_Y15) {
774*40d01547SDavid du Colombier if(v)
775*40d01547SDavid du Colombier goto bad;
776*40d01547SDavid du Colombier *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
777*40d01547SDavid du Colombier if(t >= D_Y0 && t <= D_Y15)
778*40d01547SDavid du Colombier vexbytes |= Vexl;
779*40d01547SDavid du Colombier rexflag |= (regrex[t] & (0x40 | Rxb)) | rex;
780*40d01547SDavid du Colombier return;
781*40d01547SDavid du Colombier }
782*40d01547SDavid du Colombier if(t >= D_INDIR && t < D_CONST2) {
783e887ea33SDavid du Colombier t -= D_INDIR;
784e887ea33SDavid du Colombier rexflag |= (regrex[t] & Rxb) | rex;
785*40d01547SDavid du Colombier if(t == D_NONE || D_CS <= t && t <= D_GS) {
786e887ea33SDavid du Colombier if(asmode != 64){
787e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
788e887ea33SDavid du Colombier put4(v);
789e887ea33SDavid du Colombier return;
790e887ea33SDavid du Colombier }
791e887ea33SDavid du Colombier /* temporary */
792e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (4 << 0) | (r << 3); /* sib present */
793e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (4 << 3) | (5 << 0); /* DS:d32 */
794e887ea33SDavid du Colombier put4(v);
795e887ea33SDavid du Colombier return;
796e887ea33SDavid du Colombier }
797e887ea33SDavid du Colombier if(t == D_SP || t == D_R12) {
798e887ea33SDavid du Colombier if(v == 0) {
799e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
800e887ea33SDavid du Colombier asmidx(a, t);
801e887ea33SDavid du Colombier return;
802e887ea33SDavid du Colombier }
803e887ea33SDavid du Colombier if(v >= -128 && v < 128) {
804e887ea33SDavid du Colombier *andptr++ = (1 << 6) | (reg[t] << 0) | (r << 3);
805e887ea33SDavid du Colombier asmidx(a, t);
806e887ea33SDavid du Colombier *andptr++ = v;
807e887ea33SDavid du Colombier return;
808e887ea33SDavid du Colombier }
809e887ea33SDavid du Colombier *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
810e887ea33SDavid du Colombier asmidx(a, t);
811e887ea33SDavid du Colombier put4(v);
812e887ea33SDavid du Colombier return;
813e887ea33SDavid du Colombier }
814e887ea33SDavid du Colombier if(t >= D_AX && t <= D_R15) {
815e887ea33SDavid du Colombier if(v == 0 && t != D_BP && t != D_R13) {
816e887ea33SDavid du Colombier *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
817e887ea33SDavid du Colombier return;
818e887ea33SDavid du Colombier }
819e887ea33SDavid du Colombier if(v >= -128 && v < 128) {
820e887ea33SDavid du Colombier andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
821e887ea33SDavid du Colombier andptr[1] = v;
822e887ea33SDavid du Colombier andptr += 2;
823e887ea33SDavid du Colombier return;
824e887ea33SDavid du Colombier }
825e887ea33SDavid du Colombier *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
826e887ea33SDavid du Colombier put4(v);
827e887ea33SDavid du Colombier return;
828e887ea33SDavid du Colombier }
829e887ea33SDavid du Colombier goto bad;
830e887ea33SDavid du Colombier }
831e887ea33SDavid du Colombier switch(a->type) {
832e887ea33SDavid du Colombier default:
833e887ea33SDavid du Colombier goto bad;
834e887ea33SDavid du Colombier case D_STATIC:
835e887ea33SDavid du Colombier case D_EXTERN:
836e887ea33SDavid du Colombier aa.type = D_NONE+D_INDIR;
837e887ea33SDavid du Colombier break;
838e887ea33SDavid du Colombier case D_AUTO:
839e887ea33SDavid du Colombier case D_PARAM:
840e887ea33SDavid du Colombier aa.type = D_SP+D_INDIR;
841e887ea33SDavid du Colombier break;
842e887ea33SDavid du Colombier }
843e887ea33SDavid du Colombier aa.index = D_NONE;
844e887ea33SDavid du Colombier aa.scale = 1;
845e887ea33SDavid du Colombier aa.offset = vaddr(a);
846e887ea33SDavid du Colombier asmandsz(&aa, r, rex, m64);
847e887ea33SDavid du Colombier return;
848e887ea33SDavid du Colombier bad:
849e887ea33SDavid du Colombier diag("asmand: bad address %D", a);
850e887ea33SDavid du Colombier return;
851e887ea33SDavid du Colombier }
852e887ea33SDavid du Colombier
853*40d01547SDavid du Colombier int
isxyreg(int t)854*40d01547SDavid du Colombier isxyreg(int t)
855*40d01547SDavid du Colombier {
856*40d01547SDavid du Colombier return t >= D_X0 && t <= D_X15 || t >= D_Y0 && t <= D_Y15;
857*40d01547SDavid du Colombier }
858*40d01547SDavid du Colombier
859*40d01547SDavid du Colombier static void
vexreg(Adr * a)860*40d01547SDavid du Colombier vexreg(Adr *a)
861*40d01547SDavid du Colombier {
862*40d01547SDavid du Colombier int t;
863*40d01547SDavid du Colombier
864*40d01547SDavid du Colombier t = a->type;
865*40d01547SDavid du Colombier if(t >= D_Y0 && t <= D_Y15) {
866*40d01547SDavid du Colombier vexbytes |= Vexl;
867*40d01547SDavid du Colombier } else if(t >= D_X0 && t <= D_X15) {
868*40d01547SDavid du Colombier if(vexed)
869*40d01547SDavid du Colombier vexbytes |= Vexr; /* force vex prefix */
870*40d01547SDavid du Colombier } else
871*40d01547SDavid du Colombier return;
872*40d01547SDavid du Colombier if(a->index != D_NONE)
873*40d01547SDavid du Colombier vexbytes |= a->index << 8;
874*40d01547SDavid du Colombier }
875*40d01547SDavid du Colombier
876e887ea33SDavid du Colombier void
asmand(Adr * a,Adr * ra)877e887ea33SDavid du Colombier asmand(Adr *a, Adr *ra)
878e887ea33SDavid du Colombier {
879e887ea33SDavid du Colombier asmandsz(a, reg[ra->type], regrex[ra->type], 0);
880e887ea33SDavid du Colombier }
881e887ea33SDavid du Colombier
882e887ea33SDavid du Colombier void
asmandg(Adr * a,Adr * r,int o,int rdest,int prefix)883*40d01547SDavid du Colombier asmandg(Adr *a, Adr *r, int o, int rdest, int prefix)
884*40d01547SDavid du Colombier {
885*40d01547SDavid du Colombier Adr aa, rr;
886*40d01547SDavid du Colombier
887*40d01547SDavid du Colombier if(isxyreg(a->type)) {
888*40d01547SDavid du Colombier if(isxyreg(a->index) && r->type == D_CONST) {
889*40d01547SDavid du Colombier /*
890*40d01547SDavid du Colombier * convert sse instructions with immediate like
891*40d01547SDavid du Colombier * AESKEYGENASSIST $32, X1, X2 from
892*40d01547SDavid du Colombier * a=X1(X2*0); r=$32 to a=X1, r=X2. the
893*40d01547SDavid du Colombier * caller adds the immediate byte. vex is not required
894*40d01547SDavid du Colombier */
895*40d01547SDavid du Colombier rr.offset = 0;
896*40d01547SDavid du Colombier rr.sym = a->sym;
897*40d01547SDavid du Colombier rr.type = a->index;
898*40d01547SDavid du Colombier rr.index = D_NONE;
899*40d01547SDavid du Colombier rr.scale = 0;
900*40d01547SDavid du Colombier r = &rr;
901*40d01547SDavid du Colombier
902*40d01547SDavid du Colombier aa = *a;
903*40d01547SDavid du Colombier aa.index = D_NONE;
904*40d01547SDavid du Colombier a = &aa;
905*40d01547SDavid du Colombier }
906*40d01547SDavid du Colombier }
907*40d01547SDavid du Colombier vexreg(a);
908*40d01547SDavid du Colombier if(isxyreg(a->type)) {
909*40d01547SDavid du Colombier if(a->index != D_NONE) {
910*40d01547SDavid du Colombier aa = *a;
911*40d01547SDavid du Colombier aa.index = D_NONE;
912*40d01547SDavid du Colombier a = &aa;
913*40d01547SDavid du Colombier }
914*40d01547SDavid du Colombier }
915*40d01547SDavid du Colombier if(r == nil) {
916*40d01547SDavid du Colombier asmandsz(a, o, 0, 0);
917*40d01547SDavid du Colombier return;
918*40d01547SDavid du Colombier }
919*40d01547SDavid du Colombier vexreg(r);
920*40d01547SDavid du Colombier if(rdest && (prefix&P2) == 0 && vexbytes != 0 && (vexbytes>>8) == 0) {
921*40d01547SDavid du Colombier /* copy destination register as second source register */
922*40d01547SDavid du Colombier if(isxyreg(r->type)) {
923*40d01547SDavid du Colombier vexbytes |= r->type << 8;
924*40d01547SDavid du Colombier rexflag |= regrex[r->type] & Rxx;
925*40d01547SDavid du Colombier }
926*40d01547SDavid du Colombier }
927*40d01547SDavid du Colombier asmand(a, r);
928*40d01547SDavid du Colombier }
929*40d01547SDavid du Colombier
930*40d01547SDavid du Colombier void
asmando(Adr * a,int o)931e887ea33SDavid du Colombier asmando(Adr *a, int o)
932e887ea33SDavid du Colombier {
933*40d01547SDavid du Colombier asmandg(a, nil, o, 0, 0);
934e887ea33SDavid du Colombier }
935e887ea33SDavid du Colombier
936e887ea33SDavid du Colombier static void
bytereg(Adr * a)937e887ea33SDavid du Colombier bytereg(Adr *a)
938e887ea33SDavid du Colombier {
939e887ea33SDavid du Colombier if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15))
940e887ea33SDavid du Colombier a->type = D_AL + (a->type-D_AX);
941e887ea33SDavid du Colombier }
942e887ea33SDavid du Colombier
943e887ea33SDavid du Colombier #define E 0xff
944e887ea33SDavid du Colombier Movtab ymovtab[] =
945e887ea33SDavid du Colombier {
946e887ea33SDavid du Colombier /* push */
947e887ea33SDavid du Colombier {APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0},
948e887ea33SDavid du Colombier {APUSHL, Yss, Ynone, 0, 0x16,E,0,0},
949e887ea33SDavid du Colombier {APUSHL, Yds, Ynone, 0, 0x1e,E,0,0},
950e887ea33SDavid du Colombier {APUSHL, Yes, Ynone, 0, 0x06,E,0,0},
951e887ea33SDavid du Colombier {APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
952e887ea33SDavid du Colombier {APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
953e887ea33SDavid du Colombier {APUSHQ, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
954e887ea33SDavid du Colombier {APUSHQ, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
955e887ea33SDavid du Colombier
956e887ea33SDavid du Colombier {APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0},
957e887ea33SDavid du Colombier {APUSHW, Yss, Ynone, 0, Pe,0x16,E,0},
958e887ea33SDavid du Colombier {APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0},
959e887ea33SDavid du Colombier {APUSHW, Yes, Ynone, 0, Pe,0x06,E,0},
960e887ea33SDavid du Colombier {APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E},
961e887ea33SDavid du Colombier {APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E},
962e887ea33SDavid du Colombier
963e887ea33SDavid du Colombier /* pop */
964e887ea33SDavid du Colombier {APOPL, Ynone, Yds, 0, 0x1f,E,0,0},
965e887ea33SDavid du Colombier {APOPL, Ynone, Yes, 0, 0x07,E,0,0},
966e887ea33SDavid du Colombier {APOPL, Ynone, Yss, 0, 0x17,E,0,0},
967e887ea33SDavid du Colombier {APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
968e887ea33SDavid du Colombier {APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
969e887ea33SDavid du Colombier {APOPQ, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
970e887ea33SDavid du Colombier {APOPQ, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
971e887ea33SDavid du Colombier
972e887ea33SDavid du Colombier {APOPW, Ynone, Yds, 0, Pe,0x1f,E,0},
973e887ea33SDavid du Colombier {APOPW, Ynone, Yes, 0, Pe,0x07,E,0},
974e887ea33SDavid du Colombier {APOPW, Ynone, Yss, 0, Pe,0x17,E,0},
975e887ea33SDavid du Colombier {APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E},
976e887ea33SDavid du Colombier {APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E},
977e887ea33SDavid du Colombier
978e887ea33SDavid du Colombier /* mov seg */
979e887ea33SDavid du Colombier {AMOVW, Yes, Yml, 1, 0x8c,0,0,0},
980e887ea33SDavid du Colombier {AMOVW, Ycs, Yml, 1, 0x8c,1,0,0},
981e887ea33SDavid du Colombier {AMOVW, Yss, Yml, 1, 0x8c,2,0,0},
982e887ea33SDavid du Colombier {AMOVW, Yds, Yml, 1, 0x8c,3,0,0},
983e887ea33SDavid du Colombier {AMOVW, Yfs, Yml, 1, 0x8c,4,0,0},
984e887ea33SDavid du Colombier {AMOVW, Ygs, Yml, 1, 0x8c,5,0,0},
985e887ea33SDavid du Colombier
986e887ea33SDavid du Colombier {AMOVW, Yml, Yes, 2, 0x8e,0,0,0},
987e887ea33SDavid du Colombier {AMOVW, Yml, Ycs, 2, 0x8e,1,0,0},
988e887ea33SDavid du Colombier {AMOVW, Yml, Yss, 2, 0x8e,2,0,0},
989e887ea33SDavid du Colombier {AMOVW, Yml, Yds, 2, 0x8e,3,0,0},
990e887ea33SDavid du Colombier {AMOVW, Yml, Yfs, 2, 0x8e,4,0,0},
991e887ea33SDavid du Colombier {AMOVW, Yml, Ygs, 2, 0x8e,5,0,0},
992e887ea33SDavid du Colombier
993e887ea33SDavid du Colombier /* mov cr */
994e887ea33SDavid du Colombier {AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0},
995e887ea33SDavid du Colombier {AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0},
996e887ea33SDavid du Colombier {AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0},
997e887ea33SDavid du Colombier {AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0},
998e887ea33SDavid du Colombier {AMOVL, Ycr8, Yml, 3, 0x0f,0x20,8,0},
999e887ea33SDavid du Colombier {AMOVQ, Ycr0, Yml, 3, 0x0f,0x20,0,0},
1000e887ea33SDavid du Colombier {AMOVQ, Ycr2, Yml, 3, 0x0f,0x20,2,0},
1001e887ea33SDavid du Colombier {AMOVQ, Ycr3, Yml, 3, 0x0f,0x20,3,0},
1002e887ea33SDavid du Colombier {AMOVQ, Ycr4, Yml, 3, 0x0f,0x20,4,0},
1003e887ea33SDavid du Colombier {AMOVQ, Ycr8, Yml, 3, 0x0f,0x20,8,0},
1004e887ea33SDavid du Colombier
1005e887ea33SDavid du Colombier {AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0},
1006e887ea33SDavid du Colombier {AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0},
1007e887ea33SDavid du Colombier {AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0},
1008e887ea33SDavid du Colombier {AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0},
1009e887ea33SDavid du Colombier {AMOVL, Yml, Ycr8, 4, 0x0f,0x22,8,0},
1010e887ea33SDavid du Colombier {AMOVQ, Yml, Ycr0, 4, 0x0f,0x22,0,0},
1011e887ea33SDavid du Colombier {AMOVQ, Yml, Ycr2, 4, 0x0f,0x22,2,0},
1012e887ea33SDavid du Colombier {AMOVQ, Yml, Ycr3, 4, 0x0f,0x22,3,0},
1013e887ea33SDavid du Colombier {AMOVQ, Yml, Ycr4, 4, 0x0f,0x22,4,0},
1014e887ea33SDavid du Colombier {AMOVQ, Yml, Ycr8, 4, 0x0f,0x22,8,0},
1015e887ea33SDavid du Colombier
1016e887ea33SDavid du Colombier /* mov dr */
1017e887ea33SDavid du Colombier {AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0},
1018e887ea33SDavid du Colombier {AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0},
1019e887ea33SDavid du Colombier {AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0},
1020e887ea33SDavid du Colombier {AMOVQ, Ydr0, Yml, 3, 0x0f,0x21,0,0},
1021e887ea33SDavid du Colombier {AMOVQ, Ydr6, Yml, 3, 0x0f,0x21,6,0},
1022e887ea33SDavid du Colombier {AMOVQ, Ydr7, Yml, 3, 0x0f,0x21,7,0},
1023e887ea33SDavid du Colombier
1024e887ea33SDavid du Colombier {AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0},
1025e887ea33SDavid du Colombier {AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0},
1026e887ea33SDavid du Colombier {AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0},
1027e887ea33SDavid du Colombier {AMOVQ, Yml, Ydr0, 4, 0x0f,0x23,0,0},
1028e887ea33SDavid du Colombier {AMOVQ, Yml, Ydr6, 4, 0x0f,0x23,6,0},
1029e887ea33SDavid du Colombier {AMOVQ, Yml, Ydr7, 4, 0x0f,0x23,7,0},
1030e887ea33SDavid du Colombier
1031e887ea33SDavid du Colombier /* mov tr */
1032e887ea33SDavid du Colombier {AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0},
1033e887ea33SDavid du Colombier {AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0},
1034e887ea33SDavid du Colombier
1035e887ea33SDavid du Colombier {AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E},
1036e887ea33SDavid du Colombier {AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E},
1037e887ea33SDavid du Colombier
1038e887ea33SDavid du Colombier /* lgdt, sgdt, lidt, sidt */
1039e887ea33SDavid du Colombier {AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
1040e887ea33SDavid du Colombier {AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
1041e887ea33SDavid du Colombier {AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0},
1042e887ea33SDavid du Colombier {AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0},
1043e887ea33SDavid du Colombier {AMOVQ, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
1044e887ea33SDavid du Colombier {AMOVQ, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
1045e887ea33SDavid du Colombier {AMOVQ, Ym, Yidtr, 4, 0x0f,0x01,3,0},
1046e887ea33SDavid du Colombier {AMOVQ, Yidtr, Ym, 3, 0x0f,0x01,1,0},
1047e887ea33SDavid du Colombier
1048e887ea33SDavid du Colombier /* lldt, sldt */
1049e887ea33SDavid du Colombier {AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0},
1050e887ea33SDavid du Colombier {AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0},
1051e887ea33SDavid du Colombier
1052e887ea33SDavid du Colombier /* lmsw, smsw */
1053e887ea33SDavid du Colombier {AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0},
1054e887ea33SDavid du Colombier {AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0},
1055e887ea33SDavid du Colombier
1056e887ea33SDavid du Colombier /* ltr, str */
1057e887ea33SDavid du Colombier {AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0},
1058e887ea33SDavid du Colombier {AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0},
1059e887ea33SDavid du Colombier
1060e887ea33SDavid du Colombier /* load full pointer */
1061e887ea33SDavid du Colombier {AMOVL, Yml, Ycol, 5, 0,0,0,0},
1062e887ea33SDavid du Colombier {AMOVW, Yml, Ycol, 5, Pe,0,0,0},
1063e887ea33SDavid du Colombier
1064e887ea33SDavid du Colombier /* double shift */
1065e887ea33SDavid du Colombier {ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0},
1066e887ea33SDavid du Colombier {ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0},
1067e887ea33SDavid du Colombier {ASHLQ, Ycol, Yml, 6, Pw,0xa4,0xa5,0},
1068e887ea33SDavid du Colombier {ASHRQ, Ycol, Yml, 6, Pw,0xac,0xad,0},
1069e887ea33SDavid du Colombier {ASHLW, Ycol, Yml, 6, Pe,0xa4,0xa5,0},
1070e887ea33SDavid du Colombier {ASHRW, Ycol, Yml, 6, Pe,0xac,0xad,0},
1071e887ea33SDavid du Colombier 0
1072e887ea33SDavid du Colombier };
1073e887ea33SDavid du Colombier
1074e887ea33SDavid du Colombier int
isax(Adr * a)1075e887ea33SDavid du Colombier isax(Adr *a)
1076e887ea33SDavid du Colombier {
1077e887ea33SDavid du Colombier
1078e887ea33SDavid du Colombier switch(a->type) {
1079e887ea33SDavid du Colombier case D_AX:
1080e887ea33SDavid du Colombier case D_AL:
1081e887ea33SDavid du Colombier case D_AH:
1082e887ea33SDavid du Colombier case D_INDIR+D_AX:
1083e887ea33SDavid du Colombier return 1;
1084e887ea33SDavid du Colombier }
1085e887ea33SDavid du Colombier if(a->index == D_AX)
1086e887ea33SDavid du Colombier return 1;
1087e887ea33SDavid du Colombier return 0;
1088e887ea33SDavid du Colombier }
1089e887ea33SDavid du Colombier
1090e887ea33SDavid du Colombier void
subreg(Prog * p,int from,int to)1091e887ea33SDavid du Colombier subreg(Prog *p, int from, int to)
1092e887ea33SDavid du Colombier {
1093e887ea33SDavid du Colombier
1094e887ea33SDavid du Colombier if(debug['Q'])
1095e887ea33SDavid du Colombier print("\n%P s/%R/%R/\n", p, from, to);
1096e887ea33SDavid du Colombier
1097e887ea33SDavid du Colombier if(p->from.type == from)
1098e887ea33SDavid du Colombier p->from.type = to;
1099e887ea33SDavid du Colombier if(p->to.type == from)
1100e887ea33SDavid du Colombier p->to.type = to;
1101e887ea33SDavid du Colombier
1102e887ea33SDavid du Colombier if(p->from.index == from)
1103e887ea33SDavid du Colombier p->from.index = to;
1104e887ea33SDavid du Colombier if(p->to.index == from)
1105e887ea33SDavid du Colombier p->to.index = to;
1106e887ea33SDavid du Colombier
1107e887ea33SDavid du Colombier from += D_INDIR;
1108e887ea33SDavid du Colombier if(p->from.type == from)
1109e887ea33SDavid du Colombier p->from.type = to+D_INDIR;
1110e887ea33SDavid du Colombier if(p->to.type == from)
1111e887ea33SDavid du Colombier p->to.type = to+D_INDIR;
1112e887ea33SDavid du Colombier
1113e887ea33SDavid du Colombier if(debug['Q'])
1114e887ea33SDavid du Colombier print("%P\n", p);
1115e887ea33SDavid du Colombier }
1116e887ea33SDavid du Colombier
1117e887ea33SDavid du Colombier static int
mediaop(Optab * o,int op,int osize,int z)1118e887ea33SDavid du Colombier mediaop(Optab *o, int op, int osize, int z)
1119e887ea33SDavid du Colombier {
1120e887ea33SDavid du Colombier switch(op){
1121*40d01547SDavid du Colombier case Pm38:
1122*40d01547SDavid du Colombier case Pm3a:
1123*40d01547SDavid du Colombier *andptr++ = Pm; /* 0f */
1124*40d01547SDavid du Colombier *andptr++ = op; /* 38 | 3a */
1125*40d01547SDavid du Colombier op = o->op[++z];
1126*40d01547SDavid du Colombier break;
1127*40d01547SDavid du Colombier
1128e887ea33SDavid du Colombier case Pm:
1129e887ea33SDavid du Colombier case Pe:
1130e887ea33SDavid du Colombier case Pf2:
1131e887ea33SDavid du Colombier case Pf3:
1132e887ea33SDavid du Colombier if(osize != 1){
1133e887ea33SDavid du Colombier if(op != Pm)
1134e887ea33SDavid du Colombier *andptr++ = op;
1135e887ea33SDavid du Colombier *andptr++ = Pm;
1136e887ea33SDavid du Colombier op = o->op[++z];
1137*40d01547SDavid du Colombier if(op == Pm38 || op == Pm3a) {
1138*40d01547SDavid du Colombier *andptr++ = op;
1139*40d01547SDavid du Colombier op = o->op[++z];
1140*40d01547SDavid du Colombier }
1141e887ea33SDavid du Colombier break;
1142e887ea33SDavid du Colombier }
1143e887ea33SDavid du Colombier default:
1144e887ea33SDavid du Colombier if(andptr == and || andptr[-1] != Pm)
1145e887ea33SDavid du Colombier *andptr++ = Pm;
1146e887ea33SDavid du Colombier break;
1147e887ea33SDavid du Colombier }
1148e887ea33SDavid du Colombier *andptr++ = op;
1149e887ea33SDavid du Colombier return z;
1150e887ea33SDavid du Colombier }
1151e887ea33SDavid du Colombier
1152e887ea33SDavid du Colombier void
doasm(Prog * p)1153e887ea33SDavid du Colombier doasm(Prog *p)
1154e887ea33SDavid du Colombier {
1155e887ea33SDavid du Colombier Optab *o;
1156e887ea33SDavid du Colombier Prog *q, pp;
1157e887ea33SDavid du Colombier uchar *t;
1158e887ea33SDavid du Colombier Movtab *mo;
1159*40d01547SDavid du Colombier int z, op, ft, tt, xo, l, pre;
1160e887ea33SDavid du Colombier vlong v;
1161*40d01547SDavid du Colombier Adr vmi;
1162*40d01547SDavid du Colombier
1163*40d01547SDavid du Colombier pre = prefixof(&p->from);
1164*40d01547SDavid du Colombier if(pre)
1165*40d01547SDavid du Colombier *andptr++ = pre;
1166*40d01547SDavid du Colombier pre = prefixof(&p->to);
1167*40d01547SDavid du Colombier if(pre)
1168*40d01547SDavid du Colombier *andptr++ = pre;
1169e887ea33SDavid du Colombier
1170e887ea33SDavid du Colombier o = opindex[p->as];
1171e887ea33SDavid du Colombier if(o == nil) {
1172e887ea33SDavid du Colombier diag("asmins: missing op %P", p);
1173e887ea33SDavid du Colombier return;
1174e887ea33SDavid du Colombier }
1175e887ea33SDavid du Colombier ft = oclass(&p->from) * Ymax;
1176e887ea33SDavid du Colombier tt = oclass(&p->to) * Ymax;
1177e887ea33SDavid du Colombier t = o->ytab;
1178e887ea33SDavid du Colombier if(t == 0) {
1179e887ea33SDavid du Colombier diag("asmins: noproto %P", p);
1180e887ea33SDavid du Colombier return;
1181e887ea33SDavid du Colombier }
1182*40d01547SDavid du Colombier xo = o->op[0] == Pm;
1183e887ea33SDavid du Colombier for(z=0; *t; z+=t[3]+xo,t+=4)
1184e887ea33SDavid du Colombier if(ycover[ft+t[0]])
1185e887ea33SDavid du Colombier if(ycover[tt+t[1]])
1186e887ea33SDavid du Colombier goto found;
1187e887ea33SDavid du Colombier goto domov;
1188e887ea33SDavid du Colombier
1189e887ea33SDavid du Colombier found:
1190*40d01547SDavid du Colombier switch(o->prefix & 0xFF) {
1191e887ea33SDavid du Colombier case Pq: /* 16 bit escape and opcode escape */
1192e887ea33SDavid du Colombier *andptr++ = Pe;
1193e887ea33SDavid du Colombier *andptr++ = Pm;
1194e887ea33SDavid du Colombier break;
1195e887ea33SDavid du Colombier
1196e887ea33SDavid du Colombier case Pf2: /* xmm opcode escape */
1197e887ea33SDavid du Colombier case Pf3:
1198*40d01547SDavid du Colombier *andptr++ = o->prefix & 0xFF;
1199e887ea33SDavid du Colombier *andptr++ = Pm;
1200e887ea33SDavid du Colombier break;
1201e887ea33SDavid du Colombier
1202e887ea33SDavid du Colombier case Pm: /* opcode escape */
1203e887ea33SDavid du Colombier *andptr++ = Pm;
1204e887ea33SDavid du Colombier break;
1205e887ea33SDavid du Colombier
1206e887ea33SDavid du Colombier case Pe: /* 16 bit escape */
1207e887ea33SDavid du Colombier *andptr++ = Pe;
1208e887ea33SDavid du Colombier break;
1209e887ea33SDavid du Colombier
1210e887ea33SDavid du Colombier case Pw: /* 64-bit escape */
1211e887ea33SDavid du Colombier if(p->mode != 64)
1212e887ea33SDavid du Colombier diag("asmins: illegal 64: %P", p);
1213e887ea33SDavid du Colombier rexflag |= Pw;
1214e887ea33SDavid du Colombier break;
1215e887ea33SDavid du Colombier
1216e887ea33SDavid du Colombier case Pb: /* botch */
1217e887ea33SDavid du Colombier bytereg(&p->from);
1218e887ea33SDavid du Colombier bytereg(&p->to);
1219e887ea33SDavid du Colombier break;
1220e887ea33SDavid du Colombier
1221e887ea33SDavid du Colombier case P32: /* 32 bit but illegal if 64-bit mode */
1222e887ea33SDavid du Colombier if(p->mode == 64)
1223e887ea33SDavid du Colombier diag("asmins: illegal in 64-bit mode: %P", p);
1224e887ea33SDavid du Colombier break;
1225e887ea33SDavid du Colombier
1226e887ea33SDavid du Colombier case Py: /* 64-bit only, no prefix */
1227e887ea33SDavid du Colombier if(p->mode != 64)
1228e887ea33SDavid du Colombier diag("asmins: illegal in %d-bit mode: %P", p->mode, p);
1229e887ea33SDavid du Colombier break;
1230e887ea33SDavid du Colombier }
1231e887ea33SDavid du Colombier v = vaddr(&p->from);
1232e887ea33SDavid du Colombier op = o->op[z];
1233e887ea33SDavid du Colombier if(op == 0x0f) {
1234e887ea33SDavid du Colombier *andptr++ = op;
1235e887ea33SDavid du Colombier op = o->op[++z];
1236e887ea33SDavid du Colombier }
1237e887ea33SDavid du Colombier switch(t[2]) {
1238e887ea33SDavid du Colombier default:
1239e887ea33SDavid du Colombier diag("asmins: unknown z %d %P", t[2], p);
1240e887ea33SDavid du Colombier return;
1241e887ea33SDavid du Colombier
1242e887ea33SDavid du Colombier case Zpseudo:
1243e887ea33SDavid du Colombier break;
1244e887ea33SDavid du Colombier
1245e887ea33SDavid du Colombier case Zlit:
1246e887ea33SDavid du Colombier for(; op = o->op[z]; z++)
1247e887ea33SDavid du Colombier *andptr++ = op;
1248e887ea33SDavid du Colombier break;
1249e887ea33SDavid du Colombier
1250e887ea33SDavid du Colombier case Zmb_r:
1251e887ea33SDavid du Colombier bytereg(&p->from);
1252e887ea33SDavid du Colombier /* fall through */
1253e887ea33SDavid du Colombier case Zm_r:
1254e887ea33SDavid du Colombier *andptr++ = op;
1255*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1256e887ea33SDavid du Colombier break;
1257e887ea33SDavid du Colombier
1258e887ea33SDavid du Colombier case Zm_r_xm:
1259e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1260*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1261e887ea33SDavid du Colombier break;
1262e887ea33SDavid du Colombier
1263e887ea33SDavid du Colombier case Zm_r_xm_nr:
1264e887ea33SDavid du Colombier rexflag = 0;
1265e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1266*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1267e887ea33SDavid du Colombier break;
1268e887ea33SDavid du Colombier
1269e887ea33SDavid du Colombier case Zm_r_i_xm:
1270e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1271*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1272e887ea33SDavid du Colombier *andptr++ = p->to.offset;
1273e887ea33SDavid du Colombier break;
1274e887ea33SDavid du Colombier
1275e887ea33SDavid du Colombier case Zm_r_3d:
1276e887ea33SDavid du Colombier *andptr++ = 0x0f;
1277e887ea33SDavid du Colombier *andptr++ = 0x0f;
1278*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1279e887ea33SDavid du Colombier *andptr++ = op;
1280e887ea33SDavid du Colombier break;
1281e887ea33SDavid du Colombier
1282e887ea33SDavid du Colombier case Zibm_r:
1283e887ea33SDavid du Colombier *andptr++ = op;
1284*40d01547SDavid du Colombier asmandg(&p->from, &p->to, 0, 1, o->prefix);
1285e887ea33SDavid du Colombier *andptr++ = p->to.offset;
1286e887ea33SDavid du Colombier break;
1287e887ea33SDavid du Colombier
1288e887ea33SDavid du Colombier case Zaut_r:
1289e887ea33SDavid du Colombier *andptr++ = 0x8d; /* leal */
1290e887ea33SDavid du Colombier if(p->from.type != D_ADDR)
1291e887ea33SDavid du Colombier diag("asmins: Zaut sb type ADDR");
1292e887ea33SDavid du Colombier p->from.type = p->from.index;
1293e887ea33SDavid du Colombier p->from.index = D_NONE;
1294e887ea33SDavid du Colombier asmand(&p->from, &p->to);
1295e887ea33SDavid du Colombier p->from.index = p->from.type;
1296e887ea33SDavid du Colombier p->from.type = D_ADDR;
1297e887ea33SDavid du Colombier break;
1298e887ea33SDavid du Colombier
1299e887ea33SDavid du Colombier case Zm_o:
1300e887ea33SDavid du Colombier *andptr++ = op;
1301e887ea33SDavid du Colombier asmando(&p->from, o->op[z+1]);
1302e887ea33SDavid du Colombier break;
1303e887ea33SDavid du Colombier
1304e887ea33SDavid du Colombier case Zr_m:
1305e887ea33SDavid du Colombier *andptr++ = op;
1306e887ea33SDavid du Colombier asmand(&p->to, &p->from);
1307e887ea33SDavid du Colombier break;
1308e887ea33SDavid du Colombier
1309e887ea33SDavid du Colombier case Zr_m_xm:
1310e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1311*40d01547SDavid du Colombier asmandg(&p->to, &p->from, 0, 0, o->prefix);
1312e887ea33SDavid du Colombier break;
1313e887ea33SDavid du Colombier
1314e887ea33SDavid du Colombier case Zr_m_xm_nr:
1315e887ea33SDavid du Colombier rexflag = 0;
1316e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1317*40d01547SDavid du Colombier asmandg(&p->to, &p->from, 0, 0, o->prefix);
1318e887ea33SDavid du Colombier break;
1319e887ea33SDavid du Colombier
1320e887ea33SDavid du Colombier case Zr_m_i_xm:
1321e887ea33SDavid du Colombier mediaop(o, op, t[3], z);
1322*40d01547SDavid du Colombier asmandg(&p->to, &p->from, 0, 0, o->prefix);
1323e887ea33SDavid du Colombier *andptr++ = p->from.offset;
1324e887ea33SDavid du Colombier break;
1325e887ea33SDavid du Colombier
1326e887ea33SDavid du Colombier case Zo_m:
1327e887ea33SDavid du Colombier *andptr++ = op;
1328e887ea33SDavid du Colombier asmando(&p->to, o->op[z+1]);
1329e887ea33SDavid du Colombier break;
1330e887ea33SDavid du Colombier
1331e887ea33SDavid du Colombier case Zo_m64:
1332e887ea33SDavid du Colombier *andptr++ = op;
1333e887ea33SDavid du Colombier asmandsz(&p->to, o->op[z+1], 0, 1);
1334e887ea33SDavid du Colombier break;
1335e887ea33SDavid du Colombier
1336e887ea33SDavid du Colombier case Zm_ibo:
1337e887ea33SDavid du Colombier v = vaddr(&p->to);
1338e887ea33SDavid du Colombier *andptr++ = op;
1339e887ea33SDavid du Colombier asmando(&p->from, o->op[z+1]);
1340e887ea33SDavid du Colombier *andptr++ = v;
1341e887ea33SDavid du Colombier break;
1342e887ea33SDavid du Colombier
1343e887ea33SDavid du Colombier case Zibo_m:
1344e887ea33SDavid du Colombier *andptr++ = op;
1345e887ea33SDavid du Colombier asmando(&p->to, o->op[z+1]);
1346e887ea33SDavid du Colombier *andptr++ = v;
1347e887ea33SDavid du Colombier break;
1348e887ea33SDavid du Colombier
1349e887ea33SDavid du Colombier case Zibo_m_xm:
1350*40d01547SDavid du Colombier vmi = p->to;
1351*40d01547SDavid du Colombier if(p->to.index != D_NONE) { /* VMI has "non-destructive dest" with dest in Vex.vvvv */
1352*40d01547SDavid du Colombier vmi.type = p->to.index;
1353*40d01547SDavid du Colombier vmi.index = p->to.type;
1354*40d01547SDavid du Colombier }
1355e887ea33SDavid du Colombier z = mediaop(o, op, t[3], z);
1356*40d01547SDavid du Colombier asmando(&vmi, o->op[z+1]);
1357e887ea33SDavid du Colombier *andptr++ = v;
1358e887ea33SDavid du Colombier break;
1359e887ea33SDavid du Colombier
1360e887ea33SDavid du Colombier case Z_ib:
1361e887ea33SDavid du Colombier v = vaddr(&p->to);
1362e887ea33SDavid du Colombier case Zib_:
1363e887ea33SDavid du Colombier *andptr++ = op;
1364e887ea33SDavid du Colombier *andptr++ = v;
1365e887ea33SDavid du Colombier break;
1366e887ea33SDavid du Colombier
1367e887ea33SDavid du Colombier case Zib_rp:
1368e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & (Rxb|0x40);
1369e887ea33SDavid du Colombier *andptr++ = op + reg[p->to.type];
1370e887ea33SDavid du Colombier *andptr++ = v;
1371e887ea33SDavid du Colombier break;
1372e887ea33SDavid du Colombier
1373e887ea33SDavid du Colombier case Zil_rp:
1374e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & Rxb;
1375e887ea33SDavid du Colombier *andptr++ = op + reg[p->to.type];
1376e887ea33SDavid du Colombier if(o->prefix == Pe) {
1377e887ea33SDavid du Colombier *andptr++ = v;
1378e887ea33SDavid du Colombier *andptr++ = v>>8;
1379e887ea33SDavid du Colombier }
1380e887ea33SDavid du Colombier else
1381e887ea33SDavid du Colombier put4(v);
1382e887ea33SDavid du Colombier break;
1383e887ea33SDavid du Colombier
1384e887ea33SDavid du Colombier case Zo_iw:
1385e887ea33SDavid du Colombier *andptr++ = op;
1386e887ea33SDavid du Colombier if(p->from.type != D_NONE){
1387e887ea33SDavid du Colombier *andptr++ = v;
1388e887ea33SDavid du Colombier *andptr++ = v>>8;
1389e887ea33SDavid du Colombier }
1390e887ea33SDavid du Colombier break;
1391e887ea33SDavid du Colombier
1392e887ea33SDavid du Colombier case Ziq_rp:
1393e887ea33SDavid du Colombier l = v>>32;
1394e887ea33SDavid du Colombier if(l == 0){
1395e887ea33SDavid du Colombier //p->mark |= 0100;
1396e887ea33SDavid du Colombier //print("zero: %llux %P\n", v, p);
1397e887ea33SDavid du Colombier rexflag &= ~(0x40|Rxw);
1398e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & Rxb;
1399e887ea33SDavid du Colombier *andptr++ = 0xb8 + reg[p->to.type];
1400e887ea33SDavid du Colombier put4(v);
1401e887ea33SDavid du Colombier }else if(l == -1 && (v&((uvlong)1<<31))!=0){ /* sign extend */
1402e887ea33SDavid du Colombier //p->mark |= 0100;
1403e887ea33SDavid du Colombier //print("sign: %llux %P\n", v, p);
1404e887ea33SDavid du Colombier *andptr ++ = 0xc7;
1405e887ea33SDavid du Colombier asmando(&p->to, 0);
1406e887ea33SDavid du Colombier put4(v);
1407e887ea33SDavid du Colombier }else{ /* need all 8 */
1408e887ea33SDavid du Colombier //print("all: %llux %P\n", v, p);
1409e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & Rxb;
1410e887ea33SDavid du Colombier *andptr++ = op + reg[p->to.type];
1411e887ea33SDavid du Colombier put8(v);
1412e887ea33SDavid du Colombier }
1413e887ea33SDavid du Colombier break;
1414e887ea33SDavid du Colombier
1415e887ea33SDavid du Colombier case Zib_rr:
1416e887ea33SDavid du Colombier *andptr++ = op;
1417e887ea33SDavid du Colombier asmand(&p->to, &p->to);
1418e887ea33SDavid du Colombier *andptr++ = v;
1419e887ea33SDavid du Colombier break;
1420e887ea33SDavid du Colombier
1421e887ea33SDavid du Colombier case Z_il:
1422e887ea33SDavid du Colombier v = vaddr(&p->to);
1423e887ea33SDavid du Colombier case Zil_:
1424e887ea33SDavid du Colombier *andptr++ = op;
1425e887ea33SDavid du Colombier if(o->prefix == Pe) {
1426e887ea33SDavid du Colombier *andptr++ = v;
1427e887ea33SDavid du Colombier *andptr++ = v>>8;
1428e887ea33SDavid du Colombier }
1429e887ea33SDavid du Colombier else
1430e887ea33SDavid du Colombier put4(v);
1431e887ea33SDavid du Colombier break;
1432e887ea33SDavid du Colombier
1433e887ea33SDavid du Colombier case Zm_ilo:
1434e887ea33SDavid du Colombier v = vaddr(&p->to);
1435e887ea33SDavid du Colombier *andptr++ = op;
1436e887ea33SDavid du Colombier asmando(&p->from, o->op[z+1]);
1437e887ea33SDavid du Colombier if(o->prefix == Pe) {
1438e887ea33SDavid du Colombier *andptr++ = v;
1439e887ea33SDavid du Colombier *andptr++ = v>>8;
1440e887ea33SDavid du Colombier }
1441e887ea33SDavid du Colombier else
1442e887ea33SDavid du Colombier put4(v);
1443e887ea33SDavid du Colombier break;
1444e887ea33SDavid du Colombier
1445e887ea33SDavid du Colombier case Zilo_m:
1446e887ea33SDavid du Colombier *andptr++ = op;
1447e887ea33SDavid du Colombier asmando(&p->to, o->op[z+1]);
1448e887ea33SDavid du Colombier if(o->prefix == Pe) {
1449e887ea33SDavid du Colombier *andptr++ = v;
1450e887ea33SDavid du Colombier *andptr++ = v>>8;
1451e887ea33SDavid du Colombier }
1452e887ea33SDavid du Colombier else
1453e887ea33SDavid du Colombier put4(v);
1454e887ea33SDavid du Colombier break;
1455e887ea33SDavid du Colombier
1456e887ea33SDavid du Colombier case Zil_rr:
1457e887ea33SDavid du Colombier *andptr++ = op;
1458e887ea33SDavid du Colombier asmand(&p->to, &p->to);
1459e887ea33SDavid du Colombier if(o->prefix == Pe) {
1460e887ea33SDavid du Colombier *andptr++ = v;
1461e887ea33SDavid du Colombier *andptr++ = v>>8;
1462e887ea33SDavid du Colombier }
1463e887ea33SDavid du Colombier else
1464e887ea33SDavid du Colombier put4(v);
1465e887ea33SDavid du Colombier break;
1466e887ea33SDavid du Colombier
1467e887ea33SDavid du Colombier case Z_rp:
1468e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & (Rxb|0x40);
1469e887ea33SDavid du Colombier *andptr++ = op + reg[p->to.type];
1470e887ea33SDavid du Colombier break;
1471e887ea33SDavid du Colombier
1472e887ea33SDavid du Colombier case Zrp_:
1473e887ea33SDavid du Colombier rexflag |= regrex[p->from.type] & (Rxb|0x40);
1474e887ea33SDavid du Colombier *andptr++ = op + reg[p->from.type];
1475e887ea33SDavid du Colombier break;
1476e887ea33SDavid du Colombier
1477e887ea33SDavid du Colombier case Zclr:
1478e887ea33SDavid du Colombier *andptr++ = op;
1479e887ea33SDavid du Colombier asmand(&p->to, &p->to);
1480e887ea33SDavid du Colombier break;
1481e887ea33SDavid du Colombier
1482e887ea33SDavid du Colombier case Zbr:
1483e887ea33SDavid du Colombier q = p->pcond;
1484e887ea33SDavid du Colombier if(q) {
1485e887ea33SDavid du Colombier v = q->pc - p->pc - 2;
1486e887ea33SDavid du Colombier if(v >= -128 && v <= 127) {
1487e887ea33SDavid du Colombier *andptr++ = op;
1488e887ea33SDavid du Colombier *andptr++ = v;
1489e887ea33SDavid du Colombier } else {
1490e887ea33SDavid du Colombier v -= 6-2;
1491e887ea33SDavid du Colombier *andptr++ = 0x0f;
1492e887ea33SDavid du Colombier *andptr++ = o->op[z+1];
1493e887ea33SDavid du Colombier *andptr++ = v;
1494e887ea33SDavid du Colombier *andptr++ = v>>8;
1495e887ea33SDavid du Colombier *andptr++ = v>>16;
1496e887ea33SDavid du Colombier *andptr++ = v>>24;
1497e887ea33SDavid du Colombier }
1498e887ea33SDavid du Colombier }
1499e887ea33SDavid du Colombier break;
1500e887ea33SDavid du Colombier
1501e887ea33SDavid du Colombier case Zcall:
1502e887ea33SDavid du Colombier q = p->pcond;
1503e887ea33SDavid du Colombier if(q) {
1504e887ea33SDavid du Colombier v = q->pc - p->pc - 5;
1505e887ea33SDavid du Colombier if(dlm && curp != P && p->to.sym->type == SUNDEF){
1506e887ea33SDavid du Colombier /* v = 0 - p->pc - 5; */
1507e887ea33SDavid du Colombier v = 0;
1508e887ea33SDavid du Colombier ckoff(p->to.sym, v);
1509e887ea33SDavid du Colombier v += p->to.sym->value;
1510e887ea33SDavid du Colombier dynreloc(p->to.sym, p->pc+1, 0);
1511e887ea33SDavid du Colombier }
1512e887ea33SDavid du Colombier *andptr++ = op;
1513e887ea33SDavid du Colombier *andptr++ = v;
1514e887ea33SDavid du Colombier *andptr++ = v>>8;
1515e887ea33SDavid du Colombier *andptr++ = v>>16;
1516e887ea33SDavid du Colombier *andptr++ = v>>24;
1517e887ea33SDavid du Colombier }
1518e887ea33SDavid du Colombier break;
1519e887ea33SDavid du Colombier
1520e887ea33SDavid du Colombier case Zjmp:
1521e887ea33SDavid du Colombier q = p->pcond;
1522e887ea33SDavid du Colombier if(q) {
1523e887ea33SDavid du Colombier v = q->pc - p->pc - 2;
1524e887ea33SDavid du Colombier if(v >= -128 && v <= 127) {
1525e887ea33SDavid du Colombier *andptr++ = op;
1526e887ea33SDavid du Colombier *andptr++ = v;
1527e887ea33SDavid du Colombier } else {
1528e887ea33SDavid du Colombier v -= 5-2;
1529e887ea33SDavid du Colombier *andptr++ = o->op[z+1];
1530e887ea33SDavid du Colombier *andptr++ = v;
1531e887ea33SDavid du Colombier *andptr++ = v>>8;
1532e887ea33SDavid du Colombier *andptr++ = v>>16;
1533e887ea33SDavid du Colombier *andptr++ = v>>24;
1534e887ea33SDavid du Colombier }
1535e887ea33SDavid du Colombier }
1536e887ea33SDavid du Colombier break;
1537e887ea33SDavid du Colombier
1538e887ea33SDavid du Colombier case Zloop:
1539e887ea33SDavid du Colombier q = p->pcond;
1540e887ea33SDavid du Colombier if(q) {
1541e887ea33SDavid du Colombier v = q->pc - p->pc - 2;
1542b9d84512SDavid du Colombier if(v < -128 || v > 127)
1543e887ea33SDavid du Colombier diag("loop too far: %P", p);
1544e887ea33SDavid du Colombier *andptr++ = op;
1545e887ea33SDavid du Colombier *andptr++ = v;
1546e887ea33SDavid du Colombier }
1547e887ea33SDavid du Colombier break;
1548e887ea33SDavid du Colombier
1549e887ea33SDavid du Colombier case Zbyte:
1550e887ea33SDavid du Colombier *andptr++ = v;
1551e887ea33SDavid du Colombier if(op > 1) {
1552e887ea33SDavid du Colombier *andptr++ = v>>8;
1553e887ea33SDavid du Colombier if(op > 2) {
1554e887ea33SDavid du Colombier *andptr++ = v>>16;
1555e887ea33SDavid du Colombier *andptr++ = v>>24;
1556e887ea33SDavid du Colombier if(op > 4) {
1557e887ea33SDavid du Colombier *andptr++ = v>>32;
1558e887ea33SDavid du Colombier *andptr++ = v>>40;
1559e887ea33SDavid du Colombier *andptr++ = v>>48;
1560e887ea33SDavid du Colombier *andptr++ = v>>56;
1561e887ea33SDavid du Colombier }
1562e887ea33SDavid du Colombier }
1563e887ea33SDavid du Colombier }
1564e887ea33SDavid du Colombier break;
1565e887ea33SDavid du Colombier }
1566e887ea33SDavid du Colombier return;
1567e887ea33SDavid du Colombier
1568e887ea33SDavid du Colombier domov:
1569e887ea33SDavid du Colombier for(mo=ymovtab; mo->as; mo++)
1570e887ea33SDavid du Colombier if(p->as == mo->as)
1571e887ea33SDavid du Colombier if(ycover[ft+mo->ft])
1572e887ea33SDavid du Colombier if(ycover[tt+mo->tt]){
1573e887ea33SDavid du Colombier t = mo->op;
1574e887ea33SDavid du Colombier goto mfound;
1575e887ea33SDavid du Colombier }
1576e887ea33SDavid du Colombier bad:
1577e887ea33SDavid du Colombier if(p->mode != 64){
1578e887ea33SDavid du Colombier /*
1579e887ea33SDavid du Colombier * here, the assembly has failed.
1580e887ea33SDavid du Colombier * if its a byte instruction that has
1581e887ea33SDavid du Colombier * unaddressable registers, try to
1582e887ea33SDavid du Colombier * exchange registers and reissue the
1583e887ea33SDavid du Colombier * instruction with the operands renamed.
1584e887ea33SDavid du Colombier */
1585e887ea33SDavid du Colombier pp = *p;
1586e887ea33SDavid du Colombier z = p->from.type;
1587e887ea33SDavid du Colombier if(z >= D_BP && z <= D_DI) {
1588e887ea33SDavid du Colombier if(isax(&p->to)) {
1589e887ea33SDavid du Colombier *andptr++ = 0x87; /* xchg lhs,bx */
1590e887ea33SDavid du Colombier asmando(&p->from, reg[D_BX]);
1591e887ea33SDavid du Colombier subreg(&pp, z, D_BX);
1592e887ea33SDavid du Colombier doasm(&pp);
1593e887ea33SDavid du Colombier *andptr++ = 0x87; /* xchg lhs,bx */
1594e887ea33SDavid du Colombier asmando(&p->from, reg[D_BX]);
1595e887ea33SDavid du Colombier } else {
1596e887ea33SDavid du Colombier *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1597e887ea33SDavid du Colombier subreg(&pp, z, D_AX);
1598e887ea33SDavid du Colombier doasm(&pp);
1599e887ea33SDavid du Colombier *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1600e887ea33SDavid du Colombier }
1601e887ea33SDavid du Colombier return;
1602e887ea33SDavid du Colombier }
1603e887ea33SDavid du Colombier z = p->to.type;
1604e887ea33SDavid du Colombier if(z >= D_BP && z <= D_DI) {
1605e887ea33SDavid du Colombier if(isax(&p->from)) {
1606e887ea33SDavid du Colombier *andptr++ = 0x87; /* xchg rhs,bx */
1607e887ea33SDavid du Colombier asmando(&p->to, reg[D_BX]);
1608e887ea33SDavid du Colombier subreg(&pp, z, D_BX);
1609e887ea33SDavid du Colombier doasm(&pp);
1610e887ea33SDavid du Colombier *andptr++ = 0x87; /* xchg rhs,bx */
1611e887ea33SDavid du Colombier asmando(&p->to, reg[D_BX]);
1612e887ea33SDavid du Colombier } else {
1613e887ea33SDavid du Colombier *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1614e887ea33SDavid du Colombier subreg(&pp, z, D_AX);
1615e887ea33SDavid du Colombier doasm(&pp);
1616e887ea33SDavid du Colombier *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1617e887ea33SDavid du Colombier }
1618e887ea33SDavid du Colombier return;
1619e887ea33SDavid du Colombier }
1620e887ea33SDavid du Colombier }
1621*40d01547SDavid du Colombier if(0) {
1622*40d01547SDavid du Colombier int ft = oclass(&p->from), tt = oclass(&p->to); extern char* yclname[];
1623*40d01547SDavid du Colombier fprint(2, "ft=%d [%s] tt=%d [%s]\n", ft, yclname[ft], tt, yclname[tt]);
1624*40d01547SDavid du Colombier }
1625e887ea33SDavid du Colombier diag("doasm: notfound from=%ux to=%ux %P", p->from.type, p->to.type, p);
1626e887ea33SDavid du Colombier return;
1627e887ea33SDavid du Colombier
1628e887ea33SDavid du Colombier mfound:
1629e887ea33SDavid du Colombier switch(mo->code) {
1630e887ea33SDavid du Colombier default:
1631e887ea33SDavid du Colombier diag("asmins: unknown mov %d %P", mo->code, p);
1632e887ea33SDavid du Colombier break;
1633e887ea33SDavid du Colombier
1634e887ea33SDavid du Colombier case 0: /* lit */
1635e887ea33SDavid du Colombier for(z=0; t[z]!=E; z++)
1636e887ea33SDavid du Colombier *andptr++ = t[z];
1637e887ea33SDavid du Colombier break;
1638e887ea33SDavid du Colombier
1639e887ea33SDavid du Colombier case 1: /* r,m */
1640e887ea33SDavid du Colombier *andptr++ = t[0];
1641e887ea33SDavid du Colombier asmando(&p->to, t[1]);
1642e887ea33SDavid du Colombier break;
1643e887ea33SDavid du Colombier
1644e887ea33SDavid du Colombier case 2: /* m,r */
1645e887ea33SDavid du Colombier *andptr++ = t[0];
1646e887ea33SDavid du Colombier asmando(&p->from, t[1]);
1647e887ea33SDavid du Colombier break;
1648e887ea33SDavid du Colombier
1649e887ea33SDavid du Colombier case 3: /* r,m - 2op */
1650e887ea33SDavid du Colombier *andptr++ = t[0];
1651e887ea33SDavid du Colombier *andptr++ = t[1];
1652e887ea33SDavid du Colombier asmando(&p->to, t[2]);
1653e887ea33SDavid du Colombier rexflag |= regrex[p->from.type] & (Rxr|0x40);
1654e887ea33SDavid du Colombier break;
1655e887ea33SDavid du Colombier
1656e887ea33SDavid du Colombier case 4: /* m,r - 2op */
1657e887ea33SDavid du Colombier *andptr++ = t[0];
1658e887ea33SDavid du Colombier *andptr++ = t[1];
1659e887ea33SDavid du Colombier asmando(&p->from, t[2]);
1660e887ea33SDavid du Colombier rexflag |= regrex[p->to.type] & (Rxr|0x40);
1661e887ea33SDavid du Colombier break;
1662e887ea33SDavid du Colombier
1663e887ea33SDavid du Colombier case 5: /* load full pointer, trash heap */
1664e887ea33SDavid du Colombier if(t[0])
1665e887ea33SDavid du Colombier *andptr++ = t[0];
1666e887ea33SDavid du Colombier switch(p->to.index) {
1667e887ea33SDavid du Colombier default:
1668e887ea33SDavid du Colombier goto bad;
1669e887ea33SDavid du Colombier case D_DS:
1670e887ea33SDavid du Colombier *andptr++ = 0xc5;
1671e887ea33SDavid du Colombier break;
1672e887ea33SDavid du Colombier case D_SS:
1673e887ea33SDavid du Colombier *andptr++ = 0x0f;
1674e887ea33SDavid du Colombier *andptr++ = 0xb2;
1675e887ea33SDavid du Colombier break;
1676e887ea33SDavid du Colombier case D_ES:
1677e887ea33SDavid du Colombier *andptr++ = 0xc4;
1678e887ea33SDavid du Colombier break;
1679e887ea33SDavid du Colombier case D_FS:
1680e887ea33SDavid du Colombier *andptr++ = 0x0f;
1681e887ea33SDavid du Colombier *andptr++ = 0xb4;
1682e887ea33SDavid du Colombier break;
1683e887ea33SDavid du Colombier case D_GS:
1684e887ea33SDavid du Colombier *andptr++ = 0x0f;
1685e887ea33SDavid du Colombier *andptr++ = 0xb5;
1686e887ea33SDavid du Colombier break;
1687e887ea33SDavid du Colombier }
1688e887ea33SDavid du Colombier asmand(&p->from, &p->to);
1689e887ea33SDavid du Colombier break;
1690e887ea33SDavid du Colombier
1691e887ea33SDavid du Colombier case 6: /* double shift */
1692e887ea33SDavid du Colombier if(t[0] == Pw){
1693e887ea33SDavid du Colombier if(p->mode != 64)
1694e887ea33SDavid du Colombier diag("asmins: illegal 64: %P", p);
1695e887ea33SDavid du Colombier rexflag |= Pw;
1696e887ea33SDavid du Colombier t++;
1697e887ea33SDavid du Colombier }else if(t[0] == Pe){
1698e887ea33SDavid du Colombier *andptr++ = Pe;
1699e887ea33SDavid du Colombier t++;
1700e887ea33SDavid du Colombier }
1701e887ea33SDavid du Colombier z = p->from.type;
1702e887ea33SDavid du Colombier switch(z) {
1703e887ea33SDavid du Colombier default:
1704e887ea33SDavid du Colombier goto bad;
1705e887ea33SDavid du Colombier case D_CONST:
1706e887ea33SDavid du Colombier *andptr++ = 0x0f;
1707e887ea33SDavid du Colombier *andptr++ = t[0];
1708e887ea33SDavid du Colombier asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
1709e887ea33SDavid du Colombier *andptr++ = p->from.offset;
1710e887ea33SDavid du Colombier break;
1711e887ea33SDavid du Colombier case D_CL:
1712e887ea33SDavid du Colombier case D_CX:
1713e887ea33SDavid du Colombier *andptr++ = 0x0f;
1714e887ea33SDavid du Colombier *andptr++ = t[1];
1715e887ea33SDavid du Colombier asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
1716e887ea33SDavid du Colombier break;
1717e887ea33SDavid du Colombier }
1718e887ea33SDavid du Colombier break;
1719*40d01547SDavid du Colombier
1720*40d01547SDavid du Colombier case 7: /* imul rm,r */
1721*40d01547SDavid du Colombier *andptr++ = t[4];
1722*40d01547SDavid du Colombier *andptr++ = t[5];
1723*40d01547SDavid du Colombier asmand(&p->from, &p->to);
1724*40d01547SDavid du Colombier break;
1725e887ea33SDavid du Colombier }
1726e887ea33SDavid du Colombier }
1727e887ea33SDavid du Colombier
1728e887ea33SDavid du Colombier void
asmins(Prog * p)1729e887ea33SDavid du Colombier asmins(Prog *p)
1730e887ea33SDavid du Colombier {
1731*40d01547SDavid du Colombier int n, np, o, c, t, v1, v2, vexlen;
1732e887ea33SDavid du Colombier
1733*40d01547SDavid du Colombier vexbytes = 0;
1734e887ea33SDavid du Colombier rexflag = 0;
1735e887ea33SDavid du Colombier andptr = and;
1736e887ea33SDavid du Colombier asmode = p->mode;
1737e887ea33SDavid du Colombier doasm(p);
1738*40d01547SDavid du Colombier if(vexbytes == 0) {
1739e887ea33SDavid du Colombier if(rexflag) {
1740*40d01547SDavid du Colombier if(0) fprint(2, "rexflag=%#ux %P\n", rexflag, p);
1741e887ea33SDavid du Colombier /*
1742e887ea33SDavid du Colombier * the rex prefix must appear before the first opcode byte
1743*40d01547SDavid du Colombier * and thus after any 66/67/f2/f3/26/2e/3e prefix bytes, but
1744*40d01547SDavid du Colombier * before the 0f opcode escape.
1745e887ea33SDavid du Colombier * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'.
1746e887ea33SDavid du Colombier */
1747e887ea33SDavid du Colombier if(p->mode != 64)
1748e887ea33SDavid du Colombier diag("asmins: illegal in mode %d: %P", p->mode, p);
1749e887ea33SDavid du Colombier n = andptr - and;
1750e887ea33SDavid du Colombier for(np = 0; np < n; np++) {
1751e887ea33SDavid du Colombier c = and[np];
175242ae7379SDavid du Colombier if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26)
1753e887ea33SDavid du Colombier break;
1754e887ea33SDavid du Colombier }
1755e887ea33SDavid du Colombier memmove(and+np+1, and+np, n-np);
1756e887ea33SDavid du Colombier and[np] = 0x40 | rexflag;
1757e887ea33SDavid du Colombier andptr++;
1758e887ea33SDavid du Colombier }
1759*40d01547SDavid du Colombier return;
1760*40d01547SDavid du Colombier }
1761*40d01547SDavid du Colombier if(0) if(rexflag||vexbytes)fprint(2, "rexflag=%#ux vexbytes=%#ux %P\n", rexflag, vexbytes, p);
1762*40d01547SDavid du Colombier n = andptr - and;
1763*40d01547SDavid du Colombier //vex if need vvvv register or W or L. never need R X B (must be 1 in 32-bit)
1764*40d01547SDavid du Colombier //note: 4th register encoding in immediate byte
1765*40d01547SDavid du Colombier /* media/sse/vex: seg* (66|F3|F2)? 0F (38|3A)? op -> seg* vex2|vex3 op */
1766*40d01547SDavid du Colombier for(np = 0; np < n; np++) { /* seg* */
1767*40d01547SDavid du Colombier c = and[np];
1768*40d01547SDavid du Colombier if(c != 0x2e && c != 0x3e && c != 0x26 && c != 0x64 && c != 0x65)
1769*40d01547SDavid du Colombier break;
1770*40d01547SDavid du Colombier }
1771*40d01547SDavid du Colombier o = np;
1772*40d01547SDavid du Colombier if(np+1 < n) {
1773*40d01547SDavid du Colombier v1 = 0;
1774*40d01547SDavid du Colombier v2 = (vexbytes & Vexl) | Vexp0;
1775*40d01547SDavid du Colombier switch(and[np]) {
1776*40d01547SDavid du Colombier case 0x66:
1777*40d01547SDavid du Colombier v2 |= Vexp66;
1778*40d01547SDavid du Colombier np++;
1779*40d01547SDavid du Colombier break;
1780*40d01547SDavid du Colombier case 0xF3:
1781*40d01547SDavid du Colombier v2 |= Vexpf3;
1782*40d01547SDavid du Colombier np++;
1783*40d01547SDavid du Colombier break;
1784*40d01547SDavid du Colombier case 0xF2:
1785*40d01547SDavid du Colombier v2 |= Vexpf2;
1786*40d01547SDavid du Colombier np++;
1787*40d01547SDavid du Colombier break;
1788*40d01547SDavid du Colombier }
1789*40d01547SDavid du Colombier c = and[np];
1790*40d01547SDavid du Colombier if(c == Vex2 || c == Vex3)
1791*40d01547SDavid du Colombier return; /* already vexed */
1792*40d01547SDavid du Colombier if(and[np] != 0x0F) {
1793*40d01547SDavid du Colombier diag("internal: inconsistent vex state: %P", p);
1794*40d01547SDavid du Colombier return;
1795*40d01547SDavid du Colombier }
1796*40d01547SDavid du Colombier np++;
1797*40d01547SDavid du Colombier if(np < n) {
1798*40d01547SDavid du Colombier switch(and[np]) {
1799*40d01547SDavid du Colombier case 0x38:
1800*40d01547SDavid du Colombier v1 = Vex0f38;
1801*40d01547SDavid du Colombier np++;
1802*40d01547SDavid du Colombier break;
1803*40d01547SDavid du Colombier case 0x3a:
1804*40d01547SDavid du Colombier v1 = Vex0f3a;
1805*40d01547SDavid du Colombier np++;
1806*40d01547SDavid du Colombier break;
1807*40d01547SDavid du Colombier default:
1808*40d01547SDavid du Colombier if(rexflag & (Rxw|Rxx|Rxb))
1809*40d01547SDavid du Colombier v1 = Vex0f; /* force 3-byte vex */
1810*40d01547SDavid du Colombier break;
1811*40d01547SDavid du Colombier }
1812*40d01547SDavid du Colombier }
1813*40d01547SDavid du Colombier t = vexbytes >> 8;
1814*40d01547SDavid du Colombier if(t >= D_Y0 && t <= D_Y15)
1815*40d01547SDavid du Colombier t -= D_Y0;
1816*40d01547SDavid du Colombier else if(t >= D_X0 && t <= D_X15)
1817*40d01547SDavid du Colombier t -= D_X0;
1818*40d01547SDavid du Colombier v2 |= (~t & 0xF) << 3;
1819*40d01547SDavid du Colombier vexlen = 2;
1820*40d01547SDavid du Colombier if(v1 != 0)
1821*40d01547SDavid du Colombier vexlen = 3;
1822*40d01547SDavid du Colombier if(o+vexlen != np) {
1823*40d01547SDavid du Colombier memmove(and+o+vexlen, and+np, n-np);
1824*40d01547SDavid du Colombier andptr = and+(o+vexlen)+(n-np);
1825*40d01547SDavid du Colombier }
1826*40d01547SDavid du Colombier if(vexlen == 2) {
1827*40d01547SDavid du Colombier and[o] = Vex2;
1828*40d01547SDavid du Colombier and[o+1] = v2 | ((~rexflag<<5) & Vexr);
1829*40d01547SDavid du Colombier } else {
1830*40d01547SDavid du Colombier and[o] = Vex3;
1831*40d01547SDavid du Colombier and[o+1] = v1 | ((~rexflag<<5) & (Vexr | Vexx | Vexb));
1832*40d01547SDavid du Colombier if(rexflag & Rxw)
1833*40d01547SDavid du Colombier v2 |= Vexw;
1834*40d01547SDavid du Colombier and[o+2] = v2;
1835*40d01547SDavid du Colombier }
1836*40d01547SDavid du Colombier }
1837e887ea33SDavid du Colombier }
1838e887ea33SDavid du Colombier
1839e887ea33SDavid du Colombier enum{
1840e887ea33SDavid du Colombier ABSD = 0,
1841e887ea33SDavid du Colombier ABSU = 1,
1842e887ea33SDavid du Colombier RELD = 2,
1843e887ea33SDavid du Colombier RELU = 3,
1844e887ea33SDavid du Colombier };
1845e887ea33SDavid du Colombier
1846e887ea33SDavid du Colombier int modemap[4] = { 0, 1, -1, 2, };
1847e887ea33SDavid du Colombier
1848e887ea33SDavid du Colombier typedef struct Reloc Reloc;
1849e887ea33SDavid du Colombier
1850e887ea33SDavid du Colombier struct Reloc
1851e887ea33SDavid du Colombier {
1852e887ea33SDavid du Colombier int n;
1853e887ea33SDavid du Colombier int t;
1854e887ea33SDavid du Colombier uchar *m;
1855e887ea33SDavid du Colombier ulong *a;
1856e887ea33SDavid du Colombier };
1857e887ea33SDavid du Colombier
1858e887ea33SDavid du Colombier Reloc rels;
1859e887ea33SDavid du Colombier
1860e887ea33SDavid du Colombier static void
grow(Reloc * r)1861e887ea33SDavid du Colombier grow(Reloc *r)
1862e887ea33SDavid du Colombier {
1863e887ea33SDavid du Colombier int t;
1864e887ea33SDavid du Colombier uchar *m, *nm;
1865e887ea33SDavid du Colombier ulong *a, *na;
1866e887ea33SDavid du Colombier
1867e887ea33SDavid du Colombier t = r->t;
1868e887ea33SDavid du Colombier r->t += 64;
1869e887ea33SDavid du Colombier m = r->m;
1870e887ea33SDavid du Colombier a = r->a;
1871e887ea33SDavid du Colombier r->m = nm = malloc(r->t*sizeof(uchar));
1872e887ea33SDavid du Colombier r->a = na = malloc(r->t*sizeof(ulong));
1873e887ea33SDavid du Colombier memmove(nm, m, t*sizeof(uchar));
1874e887ea33SDavid du Colombier memmove(na, a, t*sizeof(ulong));
1875e887ea33SDavid du Colombier free(m);
1876e887ea33SDavid du Colombier free(a);
1877e887ea33SDavid du Colombier }
1878e887ea33SDavid du Colombier
1879e887ea33SDavid du Colombier void
dynreloc(Sym * s,ulong v,int abs)1880e887ea33SDavid du Colombier dynreloc(Sym *s, ulong v, int abs)
1881e887ea33SDavid du Colombier {
1882e887ea33SDavid du Colombier int i, k, n;
1883e887ea33SDavid du Colombier uchar *m;
1884e887ea33SDavid du Colombier ulong *a;
1885e887ea33SDavid du Colombier Reloc *r;
1886e887ea33SDavid du Colombier
1887e887ea33SDavid du Colombier if(s->type == SUNDEF)
1888e887ea33SDavid du Colombier k = abs ? ABSU : RELU;
1889e887ea33SDavid du Colombier else
1890e887ea33SDavid du Colombier k = abs ? ABSD : RELD;
1891e887ea33SDavid du Colombier /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1892e887ea33SDavid du Colombier k = modemap[k];
1893e887ea33SDavid du Colombier r = &rels;
1894e887ea33SDavid du Colombier n = r->n;
1895e887ea33SDavid du Colombier if(n >= r->t)
1896e887ea33SDavid du Colombier grow(r);
1897e887ea33SDavid du Colombier m = r->m;
1898e887ea33SDavid du Colombier a = r->a;
1899e887ea33SDavid du Colombier for(i = n; i > 0; i--){
1900e887ea33SDavid du Colombier if(v < a[i-1]){ /* happens occasionally for data */
1901e887ea33SDavid du Colombier m[i] = m[i-1];
1902e887ea33SDavid du Colombier a[i] = a[i-1];
1903e887ea33SDavid du Colombier }
1904e887ea33SDavid du Colombier else
1905e887ea33SDavid du Colombier break;
1906e887ea33SDavid du Colombier }
1907e887ea33SDavid du Colombier m[i] = k;
1908e887ea33SDavid du Colombier a[i] = v;
1909e887ea33SDavid du Colombier r->n++;
1910e887ea33SDavid du Colombier }
1911e887ea33SDavid du Colombier
1912e887ea33SDavid du Colombier static int
sput(char * s)1913e887ea33SDavid du Colombier sput(char *s)
1914e887ea33SDavid du Colombier {
1915e887ea33SDavid du Colombier char *p;
1916e887ea33SDavid du Colombier
1917e887ea33SDavid du Colombier p = s;
1918e887ea33SDavid du Colombier while(*s)
1919e887ea33SDavid du Colombier cput(*s++);
1920e887ea33SDavid du Colombier cput(0);
1921e887ea33SDavid du Colombier return s-p+1;
1922e887ea33SDavid du Colombier }
1923e887ea33SDavid du Colombier
1924e887ea33SDavid du Colombier void
asmdyn()1925e887ea33SDavid du Colombier asmdyn()
1926e887ea33SDavid du Colombier {
1927e887ea33SDavid du Colombier int i, n, t, c;
1928e887ea33SDavid du Colombier Sym *s;
1929e887ea33SDavid du Colombier ulong la, ra, *a;
1930e887ea33SDavid du Colombier vlong off;
1931e887ea33SDavid du Colombier uchar *m;
1932e887ea33SDavid du Colombier Reloc *r;
1933e887ea33SDavid du Colombier
1934e887ea33SDavid du Colombier cflush();
1935e887ea33SDavid du Colombier off = seek(cout, 0, 1);
1936e887ea33SDavid du Colombier lput(0);
1937e887ea33SDavid du Colombier t = 0;
1938e887ea33SDavid du Colombier lput(imports);
1939e887ea33SDavid du Colombier t += 4;
1940e887ea33SDavid du Colombier for(i = 0; i < NHASH; i++)
1941e887ea33SDavid du Colombier for(s = hash[i]; s != S; s = s->link)
1942e887ea33SDavid du Colombier if(s->type == SUNDEF){
1943e887ea33SDavid du Colombier lput(s->sig);
1944e887ea33SDavid du Colombier t += 4;
1945e887ea33SDavid du Colombier t += sput(s->name);
1946e887ea33SDavid du Colombier }
1947e887ea33SDavid du Colombier
1948e887ea33SDavid du Colombier la = 0;
1949e887ea33SDavid du Colombier r = &rels;
1950e887ea33SDavid du Colombier n = r->n;
1951e887ea33SDavid du Colombier m = r->m;
1952e887ea33SDavid du Colombier a = r->a;
1953e887ea33SDavid du Colombier lput(n);
1954e887ea33SDavid du Colombier t += 4;
1955e887ea33SDavid du Colombier for(i = 0; i < n; i++){
1956e887ea33SDavid du Colombier ra = *a-la;
1957e887ea33SDavid du Colombier if(*a < la)
1958e887ea33SDavid du Colombier diag("bad relocation order");
1959e887ea33SDavid du Colombier if(ra < 256)
1960e887ea33SDavid du Colombier c = 0;
1961e887ea33SDavid du Colombier else if(ra < 65536)
1962e887ea33SDavid du Colombier c = 1;
1963e887ea33SDavid du Colombier else
1964e887ea33SDavid du Colombier c = 2;
1965e887ea33SDavid du Colombier cput((c<<6)|*m++);
1966e887ea33SDavid du Colombier t++;
1967e887ea33SDavid du Colombier if(c == 0){
1968e887ea33SDavid du Colombier cput(ra);
1969e887ea33SDavid du Colombier t++;
1970e887ea33SDavid du Colombier }
1971e887ea33SDavid du Colombier else if(c == 1){
1972e887ea33SDavid du Colombier wput(ra);
1973e887ea33SDavid du Colombier t += 2;
1974e887ea33SDavid du Colombier }
1975e887ea33SDavid du Colombier else{
1976e887ea33SDavid du Colombier lput(ra);
1977e887ea33SDavid du Colombier t += 4;
1978e887ea33SDavid du Colombier }
1979e887ea33SDavid du Colombier la = *a++;
1980e887ea33SDavid du Colombier }
1981e887ea33SDavid du Colombier
1982e887ea33SDavid du Colombier cflush();
1983e887ea33SDavid du Colombier seek(cout, off, 0);
1984e887ea33SDavid du Colombier lput(t);
1985e887ea33SDavid du Colombier
1986e887ea33SDavid du Colombier if(debug['v']){
1987e887ea33SDavid du Colombier Bprint(&bso, "import table entries = %d\n", imports);
1988e887ea33SDavid du Colombier Bprint(&bso, "export table entries = %d\n", exports);
1989e887ea33SDavid du Colombier }
1990e887ea33SDavid du Colombier }
1991*40d01547SDavid du Colombier
1992*40d01547SDavid du Colombier char* yclname[] ={
1993*40d01547SDavid du Colombier [Yxxx] "Yxxx",
1994*40d01547SDavid du Colombier [Ynone] "Ynone",
1995*40d01547SDavid du Colombier [Yi0] "Yi0",
1996*40d01547SDavid du Colombier [Yi1] "Yi1",
1997*40d01547SDavid du Colombier [Yi8] "Yi8",
1998*40d01547SDavid du Colombier [Ys32] "Ys32",
1999*40d01547SDavid du Colombier [Yi32] "Yi32",
2000*40d01547SDavid du Colombier [Yi64] "Yi64",
2001*40d01547SDavid du Colombier [Yiauto] "Yiauto",
2002*40d01547SDavid du Colombier [Yal] "Yal",
2003*40d01547SDavid du Colombier [Ycl] "Ycl",
2004*40d01547SDavid du Colombier [Yax] "Yax",
2005*40d01547SDavid du Colombier [Ycx] "Ycx",
2006*40d01547SDavid du Colombier [Yrb] "Yrb",
2007*40d01547SDavid du Colombier [Yrl] "Yrl",
2008*40d01547SDavid du Colombier [Yrf] "Yrf",
2009*40d01547SDavid du Colombier [Yf0] "Yf0",
2010*40d01547SDavid du Colombier [Yrx] "Yrx",
2011*40d01547SDavid du Colombier [Ymb] "Ymb",
2012*40d01547SDavid du Colombier [Yml] "Yml",
2013*40d01547SDavid du Colombier [Ym] "Ym",
2014*40d01547SDavid du Colombier [Ybr] "Ybr",
2015*40d01547SDavid du Colombier [Ycol] "Ycol",
2016*40d01547SDavid du Colombier [Ycs] "Ycs",
2017*40d01547SDavid du Colombier [Yss] "Yss",
2018*40d01547SDavid du Colombier [Yds] "Yds",
2019*40d01547SDavid du Colombier [Yes] "Yes",
2020*40d01547SDavid du Colombier [Yfs] "Yfs",
2021*40d01547SDavid du Colombier [Ygs] "Ygs",
2022*40d01547SDavid du Colombier [Ygdtr] "Ygdtr",
2023*40d01547SDavid du Colombier [Yidtr] "Yidtr",
2024*40d01547SDavid du Colombier [Yldtr] "Yldtr",
2025*40d01547SDavid du Colombier [Ymsw] "Ymsw",
2026*40d01547SDavid du Colombier [Ytask] "Ytask",
2027*40d01547SDavid du Colombier [Ycr0] "Ycr0",
2028*40d01547SDavid du Colombier [Ycr1] "Ycr1",
2029*40d01547SDavid du Colombier [Ycr2] "Ycr2",
2030*40d01547SDavid du Colombier [Ycr3] "Ycr3",
2031*40d01547SDavid du Colombier [Ycr4] "Ycr4",
2032*40d01547SDavid du Colombier [Ycr5] "Ycr5",
2033*40d01547SDavid du Colombier [Ycr6] "Ycr6",
2034*40d01547SDavid du Colombier [Ycr7] "Ycr7",
2035*40d01547SDavid du Colombier [Ycr8] "Ycr8",
2036*40d01547SDavid du Colombier [Ydr0] "Ydr0",
2037*40d01547SDavid du Colombier [Ydr1] "Ydr1",
2038*40d01547SDavid du Colombier [Ydr2] "Ydr2",
2039*40d01547SDavid du Colombier [Ydr3] "Ydr3",
2040*40d01547SDavid du Colombier [Ydr4] "Ydr4",
2041*40d01547SDavid du Colombier [Ydr5] "Ydr5",
2042*40d01547SDavid du Colombier [Ydr6] "Ydr6",
2043*40d01547SDavid du Colombier [Ydr7] "Ydr7",
2044*40d01547SDavid du Colombier [Ytr0] "Ytr0",
2045*40d01547SDavid du Colombier [Ytr1] "Ytr1",
2046*40d01547SDavid du Colombier [Ytr2] "Ytr2",
2047*40d01547SDavid du Colombier [Ytr3] "Ytr3",
2048*40d01547SDavid du Colombier [Ytr4] "Ytr4",
2049*40d01547SDavid du Colombier [Ytr5] "Ytr5",
2050*40d01547SDavid du Colombier [Ytr6] "Ytr6",
2051*40d01547SDavid du Colombier [Ytr7] "Ytr7",
2052*40d01547SDavid du Colombier [Yrl32] "Yrl32",
2053*40d01547SDavid du Colombier [Yrl64] "Yrl64",
2054*40d01547SDavid du Colombier [Ymr] "Ymr",
2055*40d01547SDavid du Colombier [Ymm] "Ymm",
2056*40d01547SDavid du Colombier [Yxr] "Yxr",
2057*40d01547SDavid du Colombier [Yxm] "Yxm",
2058*40d01547SDavid du Colombier [Yyr] "Yyr",
2059*40d01547SDavid du Colombier [Yxyr] "Yxyr",
2060*40d01547SDavid du Colombier [Ymax] "Ymax",
2061*40d01547SDavid du Colombier };
2062