xref: /plan9-contrib/sys/src/cmd/aux/realemu/decode.c (revision ccaec48a6a7d481d90233fb80c88e608b0a02604)
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