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