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