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