1 #include <u.h>
2 #include <libc.h>
3 #include "dat.h"
4 #include "fns.h"
5
6 typedef struct Optab Optab;
7 struct Optab {
8 uchar op;
9 uchar a1, a2, a3;
10 };
11
12 static Optab optab[256] = {
13 //00
14 {OADD, AEb, AGb}, {OADD, AEv, AGv}, {OADD, AGb, AEb}, {OADD, AGv, AEv},
15 {OADD, AAL, AIb}, {OADD, AAX, AIv}, {OPUSH, AES, }, {OPOP, AES },
16 {OOR, AEb, AGb}, {OOR, AEv, AGv}, {OOR, AGb, AEb}, {OOR, AGv, AEv},
17 {OOR, AAL, AIb}, {OOR, AAX, AIv}, {OPUSH, ACS, }, {O0F, },
18 //10
19 {OADC, AEb, AGb}, {OADC, AEv, AGv}, {OADC, AGb, AEb}, {OADC, AGv, AEv},
20 {OADC, AAL, AIb}, {OADC, AAX, AIv}, {OPUSH, ASS, }, {OPOP, ASS, },
21 {OSBB, AEb, AGb}, {OSBB, AEv, AGv}, {OSBB, AGb, AEb}, {OSBB, AGv, AEv},
22 {OSBB, AAL, AIb}, {OSBB, AAX, AIv}, {OPUSH, ADS, }, {OPOP, ADS, },
23 //20
24 {OAND, AEb, AGb}, {OAND, AEv, AGv}, {OAND, AGb, AEb}, {OAND, AGv, AEv},
25 {OAND, AAL, AIb}, {OAND, AAX, AIv}, {OSEG, AES, }, {ODAA, },
26 {OSUB, AEb, AGb}, {OSUB, AEv, AGv}, {OSUB, AGb, AEb}, {OSUB, AGv, AEv},
27 {OSUB, AAL, AIb}, {OSUB, AAX, AIv}, {OSEG, ACS, }, {ODAS, },
28 //30
29 {OXOR, AEb, AGb}, {OXOR, AEv, AGv}, {OXOR, AGb, AEb}, {OXOR, AGv, AEv},
30 {OXOR, AAL, AIb}, {OXOR, AAX, AIv}, {OSEG, ASS, }, {OAAA, },
31 {OCMP, AEb, AGb}, {OCMP, AEv, AGv}, {OCMP, AGb, AEb}, {OCMP, AGv, AEv},
32 {OCMP, AAL, AIb}, {OCMP, AAX, AIv}, {OSEG, ADS, }, {OAAS, },
33 //40
34 {OINC, AAX, }, {OINC, ACX, }, {OINC, ADX, }, {OINC, ABX, },
35 {OINC, ASP, }, {OINC, ABP, }, {OINC, ASI, }, {OINC, ADI, },
36 {ODEC, AAX, }, {ODEC, ACX, }, {ODEC, ADX, }, {ODEC, ABX, },
37 {ODEC, ASP, }, {ODEC, ABP, }, {ODEC, ASI, }, {ODEC, ADI, },
38 //50
39 {OPUSH, AAX, }, {OPUSH, ACX, }, {OPUSH, ADX, }, {OPUSH, ABX, },
40 {OPUSH, ASP, }, {OPUSH, ABP, }, {OPUSH, ASI, }, {OPUSH, ADI, },
41 {OPOP, AAX, }, {OPOP, ACX, }, {OPOP, ADX, }, {OPOP, ABX, },
42 {OPOP, ASP, }, {OPOP, ABP, }, {OPOP, ASI, }, {OPOP, ADI, },
43 //60
44 {OPUSHA, }, {OPOPA, }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw},
45 {OSEG, AFS, }, {OSEG, AGS, }, {OOSIZE, }, {OASIZE, },
46 {OPUSH, AIv, }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb, }, {OIMUL,AGv,AEv,AIb},
47 {OINS, AYb, ADX}, {OINS, AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv},
48 //70
49 {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, },
50 {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, },
51 {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, },
52 {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, }, {OJUMP, AJb, },
53 //80
54 {OGP1, AEb, AIb}, {OGP1, AEv, AIv}, {OGP1, AEb, AIb}, {OGP1, AEv, AIc},
55 {OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv},
56 {OMOV, AEb, AGb}, {OMOV, AEv, AGv}, {OMOV, AGb, AEb}, {OMOV, AGv, AEv},
57 {OMOV, AEw, ASw}, {OLEA, AGv, AM }, {OMOV, ASw, AEw}, {OGP10, },
58 //90
59 {ONOP, }, {OXCHG, ACX, AAX}, {OXCHG, ADX, AAX}, {OXCHG, ABX, AAX},
60 {OXCHG, ASP, AAX}, {OXCHG, ABP, AAX}, {OXCHG, ASI, AAX}, {OXCHG, ADI, AAX},
61 {OCBW, }, {OCWD, }, {OCALL, AAp, }, {OWAIT, },
62 {OPUSHF,AFv, }, {OPOPF, AFv, }, {OSAHF, AAH, }, {OLAHF, AAH, },
63 //A0
64 {OMOV, AAL, AOb}, {OMOV, AAX, AOv}, {OMOV, AOb, AAL}, {OMOV, AOv, AAX},
65 {OMOVS, AYb, AXb}, {OMOVS, AYv, AXv}, {OCMPS, AYb, AXb}, {OCMPS, AYv, AXv},
66 {OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX},
67 {OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AYb, AAL}, {OSCAS, AYv, AAX},
68 //B0
69 {OMOV, AAL, AIb}, {OMOV, ACL, AIb}, {OMOV, ADL, AIb}, {OMOV, ABL, AIb},
70 {OMOV, AAH, AIb}, {OMOV, ACH, AIb}, {OMOV, ADH, AIb}, {OMOV, ABH, AIb},
71 {OMOV, AAX, AIv}, {OMOV, ACX, AIv}, {OMOV, ADX, AIv}, {OMOV, ABX, AIv},
72 {OMOV, ASP, AIv}, {OMOV, ABP, AIv}, {OMOV, ASI, AIv}, {OMOV, ADI, AIv},
73 //C0
74 {OGP2, AEb, AIb}, {OGP2, AEv, AIb}, {ORET, AIw, }, {ORET, A0, },
75 {OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OGP12, AEb, AIb}, {OGP12, AEv, AIv},
76 {OENTER,AIw, AIb}, {OLEAVE, }, {ORETF, AIw, }, {ORETF, A0, },
77 {OINT, A3, }, {OINT, AIb, }, {OINT, A4, }, {OIRET, },
78 //D0
79 {OGP2, AEb, A1 }, {OGP2, AEv, A1 }, {OGP2, AEb, ACL}, {OGP2, AEv, ACL},
80 {OAAM, AIb, }, {OAAD, AIb, }, {OBAD, }, {OXLAT, AAL, ABX},
81 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
82 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
83 //E0
84 {OLOOPNZ,AJb, }, {OLOOPZ,AJb, }, {OLOOP, AJb, }, {OJUMP, AJb, },
85 {OIN, AAL, AIb}, {OIN, AAX, AIb}, {OOUT, AIb, AAL}, {OOUT, AIb, AAX},
86 {OCALL, AJv, }, {OJUMP, AJv, }, {OJUMP, AAp, }, {OJUMP, AJb, },
87 {OIN, AAL, ADX}, {OIN, AAX, ADX}, {OOUT, ADX, AAL}, {OOUT, ADX, AAX},
88 //F0
89 {OLOCK, }, {OBAD, }, {OREPNE, }, {OREPE, },
90 {OHLT, }, {OCMC, }, {OGP3b, }, {OGP3v, },
91 {OCLC, }, {OSTC, }, {OCLI, }, {OSTI, },
92 {OCLD, }, {OSTD, }, {OGP4, }, {OGP5, },
93 };
94
95 static Optab optab0F[256] = {
96 //00
97 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
98 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
99 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
100 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
101 //10 - mostly floating point and quadword moves
102 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
103 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
104 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
105 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
106 //20 - doubleword <-> control register moves, other arcana
107 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
108 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
109 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
110 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
111 //30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit
112 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
113 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
114 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
115 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
116 //40 - conditional moves
117 {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
118 {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
119 {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
120 {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
121 //50 - floating point, mmx stuff
122 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
123 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
124 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
125 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
126 //60 - floating point, mmx stuff
127 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
128 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
129 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
130 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
131 //70 - floating point, mmx stuff
132 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
133 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
134 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
135 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
136 //80 - long-displacement jumps
137 {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, },
138 {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, },
139 {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, },
140 {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, }, {OJUMP, AJv, },
141 //90 - conditional byte set
142 {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, },
143 {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, },
144 {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, },
145 {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, }, {OSET, AEb, },
146 //A0
147 {OPUSH, AFS, }, {OPOP, AFS, }, {OCPUID, }, {OBT, AEv, AGv},
148 {OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD, }, {OBAD, },
149 {OPUSH, AGS, }, {OPOP, AGS, }, {OBAD, }, {OBTS, AEv, AGv},
150 {OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD, }, {OIMUL, AGv,AGv,AEv},
151 //B0 - mostly arcana
152 {OBAD, }, {OBAD, }, {OLFP,ASS,AGv,AMp},{OBTR,AEv,AGv },
153 {OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OMOVZX,AGv,AEb }, {OMOVZX,AGv,AEw },
154 {OBAD, }, {OBAD, }, {OGP8, }, {OBAD, },
155 {OBSF,AGv,AEv }, {OBSR,AGv,AEv }, {OMOVSX,AGv,AEb }, {OMOVSX,AGv,AEw },
156 //C0 - more arcana
157 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
158 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
159 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
160 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
161 //D0 - mmx
162 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
163 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
164 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
165 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
166 //E0 - mmx
167 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
168 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
169 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
170 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
171 //F0 - mmx
172 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
173 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
174 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
175 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
176 };
177
178 /* some operands map to whole groups; group numbers from intel opcode map */
179 /* args filled in already (in OGP1 entries) */
180 static Optab optabgp1[8] = {
181 {OADD, }, {OOR, }, {OADC, }, {OSBB, },
182 {OAND, }, {OSUB, }, {OXOR, }, {OCMP, },
183 };
184
185 /* args filled in already (in OGP2 entries) */
186 static Optab optabgp2[8] = {
187 {OROL, }, {OROR, }, {ORCL, }, {ORCR, },
188 {OSHL, }, {OSHR, }, {OBAD, }, {OSAR, },
189 };
190
191 static Optab optabgp3b[8] = {
192 {OTEST, AEb, AIb}, {OBAD, }, {ONOT, AEb, }, {ONEG, AEb, },
193 {OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb, }, {OIDIV, AEb, },
194 };
195
196 static Optab optabgp3v[8] = {
197 {OTEST, AEv, AIv}, {OBAD, }, {ONOT, AEv, }, {ONEG, AEv, },
198 {OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv, }, {OIDIV, AEv, },
199 };
200
201 static Optab optabgp4[8] = {
202 {OINC, AEb, }, {ODEC, AEb, }, {OBAD, }, {OBAD, },
203 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
204 };
205
206 static Optab optabgp5[8] = {
207 {OINC, AEv, }, {ODEC, AEv, }, {OCALL, AEv, }, {OCALL, AMp },
208 {OJUMP, AEv, }, {OJUMP, AMp, }, {OPUSH, AEv, }, {OBAD, },
209 };
210
211 static Optab optabgp8[8] = {
212 {OMOV, }, {OBAD, }, {OBAD, }, {OBAD, },
213 {OBT, AEv, AIb }, {OBTS, AEv, AIb }, {OBTR, AEv, AIb }, {OBTC, AEv, AIb },
214 };
215
216 static Optab optabgp10[8] = {
217 {OPOP, AEv, }, {OBAD, }, {OBAD, }, {OBAD, },
218 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
219 };
220
221 static Optab optabgp12[8] = {
222 {OMOV, }, {OBAD, }, {OBAD, }, {OBAD, },
223 {OBAD, }, {OBAD, }, {OBAD, }, {OBAD, },
224 };
225
226 /* optabg6 unimplemented - mostly segment manipulation */
227 /* optabg7 unimplemented - more segment manipulation */
228 /* optabg8 unimplemented - bit tests */
229
230 /*
231 * most of optabg9 - optabg16 decode differently depending on the mod value of
232 * the modrm byte. they're mostly arcane instructions so they're not
233 * implemented.
234 */
235
236 static Optab *optabgp[NUMOP] = {
237 [OGP1] optabgp1,
238 [OGP2] optabgp2,
239 [OGP3b] optabgp3b,
240 [OGP3v] optabgp3v,
241 [OGP4] optabgp4,
242 [OGP5] optabgp5,
243 [OGP8] optabgp8,
244 [OGP10] optabgp10,
245 [OGP12] optabgp12,
246 };
247
248 static uchar modrmarg[NATYPE] = {
249 [AEb] 1,
250 [AEw] 1,
251 [AEv] 1,
252 [AGb] 1,
253 [AGw] 1,
254 [AGv] 1,
255 [AM] 1,
256 [AMp] 1,
257 [AMa] 1,
258 [AMa2] 1,
259 [ASw] 1,
260 [AJr] 1,
261 };
262
263 static void
getmodrm16(Iarg * ip,Inst * i)264 getmodrm16(Iarg *ip, Inst *i)
265 {
266 Iarg *p;
267 uchar b;
268
269 b = ar(ip); ip->off++;
270
271 i->mod = b>>6;
272 i->reg = (b>>3)&7;
273 i->rm = b&7;
274
275 if(i->mod == 3)
276 return;
277
278 switch(i->rm){
279 case 0:
280 i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RSI));
281 i->off &= 0xFFFF;
282 break;
283 case 1:
284 i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RDI));
285 i->off &= 0xFFFF;
286 break;
287 case 2:
288 i->dsreg = RSS;
289 i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RSI));
290 i->off &= 0xFFFF;
291 break;
292 case 3:
293 i->dsreg = RSS;
294 i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RDI));
295 i->off &= 0xFFFF;
296 break;
297 case 4:
298 i->off = ar(areg(ip->cpu, 2, RSI));
299 break;
300 case 5:
301 i->off = ar(areg(ip->cpu, 2, RDI));
302 break;
303 case 6:
304 if(i->mod == 0){
305 p = adup(ip); ip->off += 2;
306 p->len = 2;
307 i->off = ar(p);
308 return;
309 }
310 i->dsreg = RSS;
311 i->off = ar(areg(ip->cpu, 2, RBP));
312 break;
313 case 7:
314 i->off = ar(areg(ip->cpu, 2, RBX));
315 break;
316 }
317 switch(i->mod){
318 case 1:
319 i->off += (i->disp = ars(ip)); ip->off++;
320 i->off &= 0xFFFF;
321 break;
322 case 2:
323 p = adup(ip); ip->off += 2;
324 p->len = 2;
325 i->off += (i->disp = ars(p));
326 i->off &= 0xFFFF;
327 break;
328 }
329 }
330
331 static void
getmodrm32(Iarg * ip,Inst * i)332 getmodrm32(Iarg *ip, Inst *i)
333 {
334 static uchar scaler[] = {1, 2, 4, 8};
335 Iarg *p;
336 uchar b;
337
338 b = ar(ip); ip->off++;
339
340 i->mod = b>>6;
341 i->reg = (b>>3)&7;
342 i->rm = b&7;
343
344 if(i->mod == 3)
345 return;
346
347 switch(i->rm){
348 case 0:
349 case 1:
350 case 2:
351 case 3:
352 case 6:
353 case 7:
354 i->off = ar(areg(ip->cpu, 4, i->rm + RAX));
355 break;
356 case 4:
357 b = ar(ip); ip->off++;
358 i->scale = b>>6;
359 i->index = (b>>3)&7;
360 i->base = b&7;
361
362 if(i->base != 5){
363 i->off = ar(areg(ip->cpu, 4, i->base + RAX));
364 break;
365 }
366 case 5:
367 if(i->mod == 0){
368 p = adup(ip); ip->off += 4;
369 p->len = 4;
370 i->off = ar(p);
371 } else {
372 i->dsreg = RSS;
373 i->off = ar(areg(ip->cpu, 4, RBP));
374 }
375 break;
376 }
377
378 if(i->rm == 4 && i->index != 4)
379 i->off += ar(areg(ip->cpu, 4, i->index + RAX)) * scaler[i->scale];
380
381 switch(i->mod){
382 case 1:
383 i->off += (i->disp = ars(ip)); ip->off++;
384 break;
385 case 2:
386 p = adup(ip); ip->off += 4;
387 p->len = 4;
388 i->off += (i->disp = ars(p));
389 break;
390 }
391 }
392
393 static Iarg*
getarg(Iarg * ip,Inst * i,uchar atype)394 getarg(Iarg *ip, Inst *i, uchar atype)
395 {
396 Iarg *a;
397 uchar len, reg;
398
399 len = i->olen;
400 switch(atype){
401 default:
402 abort();
403
404 case A0:
405 case A1:
406 case A2:
407 case A3:
408 case A4:
409 a = acon(ip->cpu, len, atype - A0);
410 break;
411
412 case AEb:
413 len = 1;
414 if(0){
415 case AEw:
416 len = 2;
417 }
418 case AEv:
419 if(i->mod == 3){
420 reg = i->rm;
421 goto REG;
422 }
423 goto MEM;
424
425 case AM:
426 case AMp:
427 case AMa:
428 case AMa2:
429 if(i->mod == 3)
430 trap(ip->cpu, EBADOP);
431 MEM:
432 a = amem(ip->cpu, len, i->sreg, i->off);
433 if(atype == AMa2)
434 a->off += i->olen;
435 break;
436
437 case AGb:
438 len = 1;
439 if(0){
440 case AGw:
441 len = 2;
442 }
443 case AGv:
444 reg = i->reg;
445 REG:
446 a = areg(ip->cpu, len, reg + RAX);
447 if(len == 1 && reg >= 4){
448 a->reg -= 4;
449 a->tag |= TH;
450 }
451 break;
452
453 case AIb:
454 case AIc:
455 len = 1;
456 if(0){
457 case AIw:
458 len = 2;
459 }
460 case AIv:
461 a = adup(ip); ip->off += len;
462 a->len = len;
463 break;
464
465 case AJb:
466 len = 1;
467 case AJv:
468 a = adup(ip); ip->off += len;
469 a->len = len;
470 a->off = ip->off + ars(a);
471 break;
472
473 case AJr:
474 if(i->mod != 3)
475 trap(ip->cpu, EBADOP);
476 a = adup(ip);
477 a->off = ar(areg(ip->cpu, i->olen, i->rm + RAX));
478 break;
479
480 case AAp:
481 a = afar(ip, ip->len, len); ip->off += 2+len;
482 break;
483
484 case AOb:
485 len = 1;
486 case AOv:
487 a = adup(ip); ip->off += i->alen;
488 a->len = i->alen;
489 a = amem(ip->cpu, len, i->sreg, ar(a));
490 break;
491
492 case ASw:
493 reg = i->reg;
494 SREG:
495 a = areg(ip->cpu, 2, reg + RES);
496 break;
497
498 case AXb:
499 len = 1;
500 case AXv:
501 a = amem(ip->cpu, len, i->sreg, ar(areg(ip->cpu, i->alen, RSI)));
502 break;
503
504 case AYb:
505 len = 1;
506 case AYv:
507 a = amem(ip->cpu, len, RES, ar(areg(ip->cpu, i->alen, RDI)));
508 break;
509
510 case AFv:
511 a = areg(ip->cpu, len, RFL);
512 break;
513
514 case AAL:
515 case ACL:
516 case ADL:
517 case ABL:
518 case AAH:
519 case ACH:
520 case ADH:
521 case ABH:
522 len = 1;
523 reg = atype - AAL;
524 goto REG;
525
526 case AAX:
527 case ACX:
528 case ADX:
529 case ABX:
530 case ASP:
531 case ABP:
532 case ASI:
533 case ADI:
534 reg = atype - AAX;
535 goto REG;
536
537 case AES:
538 case ACS:
539 case ASS:
540 case ADS:
541 case AFS:
542 case AGS:
543 reg = atype - AES;
544 goto SREG;
545 }
546 a->atype = atype;
547 return a;
548 }
549
550 static int
otherlen(int a)551 otherlen(int a)
552 {
553 if(a == 2)
554 return 4;
555 else if(a == 4)
556 return 2;
557 abort();
558 return 0;
559 }
560
561 void
decode(Iarg * ip,Inst * i)562 decode(Iarg *ip, Inst *i)
563 {
564 Optab *t, *t2;
565 Cpu *cpu;
566
567 cpu = ip->cpu;
568
569 i->op = 0;
570 i->rep = 0;
571 i->sreg = 0;
572 i->dsreg = RDS;
573 i->olen = cpu->olen;
574 i->alen = cpu->alen;
575 i->a1 = i->a2 = i->a3 = nil;
576
577 for(;;){
578 i->code = ar(ip); ip->off++;
579 t = optab + i->code;
580 switch(t->op){
581 case OOSIZE:
582 i->olen = otherlen(cpu->olen);
583 continue;
584 case OASIZE:
585 i->alen = otherlen(cpu->alen);
586 continue;
587 case OREPE:
588 case OREPNE:
589 i->rep = t->op;
590 continue;
591 case OLOCK:
592 continue;
593 case OSEG:
594 i->sreg = t->a1-AES+RES;
595 continue;
596 case O0F:
597 i->code = ar(ip); ip->off++;
598 t = optab0F + i->code;
599 break;
600 }
601 break;
602 }
603 t2 = optabgp[t->op];
604 if(t2 || modrmarg[t->a1] || modrmarg[t->a2] || modrmarg[t->a3])
605 if(i->alen == 2)
606 getmodrm16(ip, i);
607 else
608 getmodrm32(ip, i);
609 if(i->sreg == 0)
610 i->sreg = i->dsreg;
611
612 for(;;){
613 if(t->a1)
614 i->a1 = getarg(ip, i, t->a1);
615 if(t->a2)
616 i->a2 = getarg(ip, i, t->a2);
617 if(t->a3)
618 i->a3 = getarg(ip, i, t->a3);
619 if(t2 == nil)
620 break;
621 t = t2 + i->reg;
622 t2 = nil;
623 }
624 i->op = t->op;
625 }
626