Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86_misc_for_v6.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 instruction decoder update from Borislav Petkov:

- Add instruction decoding support for the XOP-prefixed instruction set
present on the AMD Bulldozer uarch

[ These instructions don't normally happen, but a X86_NATIVE_CPU build
on a bulldozer host can make the compiler then use these unusual
instruction encodings ]

* tag 'x86_misc_for_v6.18_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/insn: Add XOP prefix instructions decoder support

+513 -27
+15
arch/x86/include/asm/inat.h
··· 37 37 #define INAT_PFX_EVEX 15 /* EVEX prefix */ 38 38 /* x86-64 REX2 prefix */ 39 39 #define INAT_PFX_REX2 16 /* 0xD5 */ 40 + /* AMD XOP prefix */ 41 + #define INAT_PFX_XOP 17 /* 0x8F */ 40 42 41 43 #define INAT_LSTPFX_MAX 3 42 44 #define INAT_LGCPFX_MAX 11 ··· 79 77 #define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3)) 80 78 #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) 81 79 #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) 80 + #define INAT_XOPOK INAT_VEXOK 82 81 #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) 83 82 #define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7)) 84 83 #define INAT_NO_REX2 (1 << (INAT_FLAG_OFFS + 8)) ··· 114 111 extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, 115 112 insn_byte_t vex_m, 116 113 insn_byte_t vex_pp); 114 + extern insn_attr_t inat_get_xop_attribute(insn_byte_t opcode, 115 + insn_byte_t map_select); 117 116 118 117 /* Attribute checking functions */ 119 118 static inline int inat_is_legacy_prefix(insn_attr_t attr) ··· 167 162 static inline int inat_is_vex3_prefix(insn_attr_t attr) 168 163 { 169 164 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; 165 + } 166 + 167 + static inline int inat_is_xop_prefix(insn_attr_t attr) 168 + { 169 + return (attr & INAT_PFX_MASK) == INAT_PFX_XOP; 170 170 } 171 171 172 172 static inline int inat_is_escape(insn_attr_t attr) ··· 237 227 static inline int inat_accept_vex(insn_attr_t attr) 238 228 { 239 229 return attr & INAT_VEXOK; 230 + } 231 + 232 + static inline int inat_accept_xop(insn_attr_t attr) 233 + { 234 + return attr & INAT_XOPOK; 240 235 } 241 236 242 237 static inline int inat_must_vex(insn_attr_t attr)
+48 -3
arch/x86/include/asm/insn.h
··· 71 71 * prefixes.bytes[3]: last prefix 72 72 */ 73 73 struct insn_field rex_prefix; /* REX prefix */ 74 - struct insn_field vex_prefix; /* VEX prefix */ 74 + union { 75 + struct insn_field vex_prefix; /* VEX prefix */ 76 + struct insn_field xop_prefix; /* XOP prefix */ 77 + }; 75 78 struct insn_field opcode; /* 76 79 * opcode.bytes[0]: opcode1 77 80 * opcode.bytes[1]: opcode2 ··· 138 135 #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ 139 136 #define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */ 140 137 #define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */ 138 + /* XOP bit fields */ 139 + #define X86_XOP_R(xop) ((xop) & 0x80) /* XOP Byte2 */ 140 + #define X86_XOP_X(xop) ((xop) & 0x40) /* XOP Byte2 */ 141 + #define X86_XOP_B(xop) ((xop) & 0x20) /* XOP Byte2 */ 142 + #define X86_XOP_M(xop) ((xop) & 0x1f) /* XOP Byte2 */ 143 + #define X86_XOP_W(xop) ((xop) & 0x80) /* XOP Byte3 */ 144 + #define X86_XOP_V(xop) ((xop) & 0x78) /* XOP Byte3 */ 145 + #define X86_XOP_L(xop) ((xop) & 0x04) /* XOP Byte3 */ 146 + #define X86_XOP_P(xop) ((xop) & 0x03) /* XOP Byte3 */ 147 + #define X86_XOP_M_MIN 0x08 /* Min of XOP.M */ 148 + #define X86_XOP_M_MAX 0x1f /* Max of XOP.M */ 141 149 142 150 extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64); 143 151 extern int insn_get_prefixes(struct insn *insn); ··· 192 178 return X86_REX2_M(insn->rex_prefix.bytes[1]); 193 179 } 194 180 195 - static inline int insn_is_avx(struct insn *insn) 181 + static inline int insn_is_avx_or_xop(struct insn *insn) 196 182 { 197 183 if (!insn->prefixes.got) 198 184 insn_get_prefixes(insn); ··· 204 190 if (!insn->prefixes.got) 205 191 insn_get_prefixes(insn); 206 192 return (insn->vex_prefix.nbytes == 4); 193 + } 194 + 195 + /* If we already know this is AVX/XOP encoded */ 196 + static inline int avx_insn_is_xop(struct insn *insn) 197 + { 198 + insn_attr_t attr = inat_get_opcode_attribute(insn->vex_prefix.bytes[0]); 199 + 200 + return inat_is_xop_prefix(attr); 201 + } 202 + 203 + static inline int insn_is_xop(struct insn *insn) 204 + { 205 + if (!insn_is_avx_or_xop(insn)) 206 + return 0; 207 + 208 + return avx_insn_is_xop(insn); 207 209 } 208 210 209 211 static inline int insn_has_emulate_prefix(struct insn *insn) ··· 252 222 return X86_VEX_W(insn->vex_prefix.bytes[2]); 253 223 } 254 224 225 + static inline insn_byte_t insn_xop_map_bits(struct insn *insn) 226 + { 227 + if (insn->xop_prefix.nbytes < 3) /* XOP is 3 bytes */ 228 + return 0; 229 + return X86_XOP_M(insn->xop_prefix.bytes[1]); 230 + } 231 + 232 + static inline insn_byte_t insn_xop_p_bits(struct insn *insn) 233 + { 234 + return X86_XOP_P(insn->vex_prefix.bytes[2]); 235 + } 236 + 255 237 /* Get the last prefix id from last prefix or VEX prefix */ 256 238 static inline int insn_last_prefix_id(struct insn *insn) 257 239 { 258 - if (insn_is_avx(insn)) 240 + if (insn_is_avx_or_xop(insn)) { 241 + if (avx_insn_is_xop(insn)) 242 + return insn_xop_p_bits(insn); 259 243 return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */ 244 + } 260 245 261 246 if (insn->prefixes.bytes[3]) 262 247 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
+13
arch/x86/lib/inat.c
··· 81 81 return table[opcode]; 82 82 } 83 83 84 + insn_attr_t inat_get_xop_attribute(insn_byte_t opcode, insn_byte_t map_select) 85 + { 86 + const insn_attr_t *table; 87 + 88 + if (map_select < X86_XOP_M_MIN || map_select > X86_XOP_M_MAX) 89 + return 0; 90 + map_select -= X86_XOP_M_MIN; 91 + /* At first, this checks the master table */ 92 + table = inat_xop_tables[map_select]; 93 + if (!table) 94 + return 0; 95 + return table[opcode]; 96 + }
+26 -9
arch/x86/lib/insn.c
··· 200 200 } 201 201 insn->rex_prefix.got = 1; 202 202 203 - /* Decode VEX prefix */ 203 + /* Decode VEX/XOP prefix */ 204 204 b = peek_next(insn_byte_t, insn); 205 - attr = inat_get_opcode_attribute(b); 206 - if (inat_is_vex_prefix(attr)) { 205 + if (inat_is_vex_prefix(attr) || inat_is_xop_prefix(attr)) { 207 206 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1); 208 - if (!insn->x86_64) { 207 + 208 + if (inat_is_xop_prefix(attr) && X86_MODRM_REG(b2) == 0) { 209 + /* Grp1A.0 is always POP Ev */ 210 + goto vex_end; 211 + } else if (!insn->x86_64) { 209 212 /* 210 213 * In 32-bits mode, if the [7:6] bits (mod bits of 211 214 * ModRM) on the second byte are not 11b, it is ··· 229 226 if (insn->x86_64 && X86_VEX_W(b2)) 230 227 /* VEX.W overrides opnd_size */ 231 228 insn->opnd_bytes = 8; 232 - } else if (inat_is_vex3_prefix(attr)) { 229 + } else if (inat_is_vex3_prefix(attr) || inat_is_xop_prefix(attr)) { 233 230 b2 = peek_nbyte_next(insn_byte_t, insn, 2); 234 231 insn_set_byte(&insn->vex_prefix, 2, b2); 235 232 insn->vex_prefix.nbytes = 3; 236 233 insn->next_byte += 3; 237 234 if (insn->x86_64 && X86_VEX_W(b2)) 238 - /* VEX.W overrides opnd_size */ 235 + /* VEX.W/XOP.W overrides opnd_size */ 239 236 insn->opnd_bytes = 8; 240 237 } else { 241 238 /* ··· 291 288 insn_set_byte(opcode, 0, op); 292 289 opcode->nbytes = 1; 293 290 294 - /* Check if there is VEX prefix or not */ 295 - if (insn_is_avx(insn)) { 291 + /* Check if there is VEX/XOP prefix or not */ 292 + if (insn_is_avx_or_xop(insn)) { 296 293 insn_byte_t m, p; 294 + 295 + /* XOP prefix has different encoding */ 296 + if (unlikely(avx_insn_is_xop(insn))) { 297 + m = insn_xop_map_bits(insn); 298 + insn->attr = inat_get_xop_attribute(op, m); 299 + if (!inat_accept_xop(insn->attr)) { 300 + insn->attr = 0; 301 + return -EINVAL; 302 + } 303 + /* XOP has only 1 byte for opcode */ 304 + goto end; 305 + } 306 + 297 307 m = insn_vex_m_bits(insn); 298 308 p = insn_vex_p_bits(insn); 299 309 insn->attr = inat_get_avx_attribute(op, m, p); ··· 399 383 pfx_id = insn_last_prefix_id(insn); 400 384 insn->attr = inat_get_group_attribute(mod, pfx_id, 401 385 insn->attr); 402 - if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) { 386 + if (insn_is_avx_or_xop(insn) && !inat_accept_vex(insn->attr) && 387 + !inat_accept_xop(insn->attr)) { 403 388 /* Bad insn */ 404 389 insn->attr = 0; 405 390 return -EINVAL;
+110 -1
arch/x86/lib/x86-opcode-map.txt
··· 27 27 # (evo): this opcode is changed by EVEX prefix (EVEX opcode) 28 28 # (v): this opcode requires VEX prefix. 29 29 # (v1): this opcode only supports 128bit VEX. 30 + # (xop): this opcode accepts XOP prefix. 31 + # 32 + # XOP Superscripts 33 + # (W=0): this opcode requires XOP.W == 0 34 + # (W=1): this opcode requires XOP.W == 1 30 35 # 31 36 # Last Prefix Superscripts 32 37 # - (66): the last prefix is 0x66 ··· 199 194 8c: MOV Ev,Sw 200 195 8d: LEA Gv,M 201 196 8e: MOV Sw,Ew 202 - 8f: Grp1A (1A) | POP Ev (d64) 197 + 8f: Grp1A (1A) | POP Ev (d64) | XOP (Prefix) 203 198 # 0x90 - 0x9f 204 199 90: NOP | PAUSE (F3) | XCHG r8,rAX 205 200 91: XCHG rCX/r9,rAX ··· 1111 1106 f8: URDMSR Rq,Id (F2),(v1),(11B) | UWRMSR Id,Rq (F3),(v1),(11B) 1112 1107 EndTable 1113 1108 1109 + # From AMD64 Architecture Programmer's Manual Vol3, Appendix A.1.5 1110 + Table: XOP map 8h 1111 + Referrer: 1112 + XOPcode: 0 1113 + 85: VPMACSSWW Vo,Ho,Wo,Lo 1114 + 86: VPMACSSWD Vo,Ho,Wo,Lo 1115 + 87: VPMACSSDQL Vo,Ho,Wo,Lo 1116 + 8e: VPMACSSDD Vo,Ho,Wo,Lo 1117 + 8f: VPMACSSDQH Vo,Ho,Wo,Lo 1118 + 95: VPMACSWW Vo,Ho,Wo,Lo 1119 + 96: VPMACSWD Vo,Ho,Wo,Lo 1120 + 97: VPMACSDQL Vo,Ho,Wo,Lo 1121 + 9e: VPMACSDD Vo,Ho,Wo,Lo 1122 + 9f: VPMACSDQH Vo,Ho,Wo,Lo 1123 + a2: VPCMOV Vx,Hx,Wx,Lx (W=0) | VPCMOV Vx,Hx,Lx,Wx (W=1) 1124 + a3: VPPERM Vo,Ho,Wo,Lo (W=0) | VPPERM Vo,Ho,Lo,Wo (W=1) 1125 + a6: VPMADCSSWD Vo,Ho,Wo,Lo 1126 + b6: VPMADCSWD Vo,Ho,Wo,Lo 1127 + c0: VPROTB Vo,Wo,Ib 1128 + c1: VPROTW Vo,Wo,Ib 1129 + c2: VPROTD Vo,Wo,Ib 1130 + c3: VPROTQ Vo,Wo,Ib 1131 + cc: VPCOMccB Vo,Ho,Wo,Ib 1132 + cd: VPCOMccW Vo,Ho,Wo,Ib 1133 + ce: VPCOMccD Vo,Ho,Wo,Ib 1134 + cf: VPCOMccQ Vo,Ho,Wo,Ib 1135 + ec: VPCOMccUB Vo,Ho,Wo,Ib 1136 + ed: VPCOMccUW Vo,Ho,Wo,Ib 1137 + ee: VPCOMccUD Vo,Ho,Wo,Ib 1138 + ef: VPCOMccUQ Vo,Ho,Wo,Ib 1139 + EndTable 1140 + 1141 + Table: XOP map 9h 1142 + Referrer: 1143 + XOPcode: 1 1144 + 01: GrpXOP1 1145 + 02: GrpXOP2 1146 + 12: GrpXOP3 1147 + 80: VFRCZPS Vx,Wx 1148 + 81: VFRCZPD Vx,Wx 1149 + 82: VFRCZSS Vq,Wss 1150 + 83: VFRCZSD Vq,Wsd 1151 + 90: VPROTB Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1152 + 91: VPROTW Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1153 + 92: VPROTD Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1154 + 93: VPROTQ Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1155 + 94: VPSHLB Vo,Wo,Ho (W=0) | VPSHLB Vo,Ho,Wo (W=1) 1156 + 95: VPSHLW Vo,Wo,Ho (W=0) | VPSHLW Vo,Ho,Wo (W=1) 1157 + 96: VPSHLD Vo,Wo,Ho (W=0) | VPSHLD Vo,Ho,Wo (W=1) 1158 + 97: VPSHLQ Vo,Wo,Ho (W=0) | VPSHLQ Vo,Ho,Wo (W=1) 1159 + 98: VPSHAB Vo,Wo,Ho (W=0) | VPSHAB Vo,Ho,Wo (W=1) 1160 + 99: VPSHAW Vo,Wo,Ho (W=0) | VPSHAW Vo,Ho,Wo (W=1) 1161 + 9a: VPSHAD Vo,Wo,Ho (W=0) | VPSHAD Vo,Ho,Wo (W=1) 1162 + 9b: VPSHAQ Vo,Wo,Ho (W=0) | VPSHAQ Vo,Ho,Wo (W=1) 1163 + c1: VPHADDBW Vo,Wo 1164 + c2: VPHADDBD Vo,Wo 1165 + c3: VPHADDBQ Vo,Wo 1166 + c6: VPHADDWD Vo,Wo 1167 + c7: VPHADDWQ Vo,Wo 1168 + cb: VPHADDDQ Vo,Wo 1169 + d1: VPHADDUBWD Vo,Wo 1170 + d2: VPHADDUBD Vo,Wo 1171 + d3: VPHADDUBQ Vo,Wo 1172 + d6: VPHADDUWD Vo,Wo 1173 + d7: VPHADDUWQ Vo,Wo 1174 + db: VPHADDUDQ Vo,Wo 1175 + e1: VPHSUBBW Vo,Wo 1176 + e2: VPHSUBWD Vo,Wo 1177 + e3: VPHSUBDQ Vo,Wo 1178 + EndTable 1179 + 1180 + Table: XOP map Ah 1181 + Referrer: 1182 + XOPcode: 2 1183 + 10: BEXTR Gy,Ey,Id 1184 + 12: GrpXOP4 1185 + EndTable 1186 + 1114 1187 GrpTable: Grp1 1115 1188 0: ADD 1116 1189 1: OR ··· 1402 1319 2: xcrypt-cbc 1403 1320 4: xcrypt-cfb 1404 1321 5: xcrypt-ofb 1322 + EndTable 1323 + 1324 + # GrpXOP1-4 is shown in AMD APM Vol.3 Appendix A as XOP group #1-4 1325 + GrpTable: GrpXOP1 1326 + 1: BLCFILL By,Ey (xop) 1327 + 2: BLSFILL By,Ey (xop) 1328 + 3: BLCS By,Ey (xop) 1329 + 4: TZMSK By,Ey (xop) 1330 + 5: BLCIC By,Ey (xop) 1331 + 6: BLSIC By,Ey (xop) 1332 + 7: T1MSKC By,Ey (xop) 1333 + EndTable 1334 + 1335 + GrpTable: GrpXOP2 1336 + 1: BLCMSK By,Ey (xop) 1337 + 6: BLCI By,Ey (xop) 1338 + EndTable 1339 + 1340 + GrpTable: GrpXOP3 1341 + 0: LLWPCB Ry (xop) 1342 + 1: SLWPCB Ry (xop) 1343 + EndTable 1344 + 1345 + GrpTable: GrpXOP4 1346 + 0: LWPINS By,Ed,Id (xop) 1347 + 1: LWPVAL By,Ed,Id (xop) 1405 1348 EndTable
+44
arch/x86/tools/gen-insn-attr-x86.awk
··· 21 21 eid = -1 # escape id 22 22 gid = -1 # group id 23 23 aid = -1 # AVX id 24 + xopid = -1 # XOP id 24 25 tname = "" 25 26 } 26 27 ··· 40 39 ggid = 1 41 40 geid = 1 42 41 gaid = 0 42 + gxopid = 0 43 43 delete etable 44 44 delete gtable 45 45 delete atable 46 + delete xoptable 46 47 47 48 opnd_expr = "^[A-Za-z/]" 48 49 ext_expr = "^\\(" ··· 64 61 imm_flag["Ob"] = "INAT_MOFFSET" 65 62 imm_flag["Ov"] = "INAT_MOFFSET" 66 63 imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" 64 + imm_flag["Lo"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" 67 65 68 66 modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])" 69 67 force64_expr = "\\([df]64\\)" ··· 91 87 evexonly_expr = "\\(ev\\)" 92 88 # (es) is the same as (ev) but also "SCALABLE" i.e. W and pp determine operand size 93 89 evex_scalable_expr = "\\(es\\)" 90 + # All opcodes in XOP table or with (xop) superscript accept XOP prefix 91 + xopok_expr = "\\(xop\\)" 94 92 95 93 prefix_expr = "\\(Prefix\\)" 96 94 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" ··· 112 106 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" 113 107 prefix_num["EVEX"] = "INAT_PFX_EVEX" 114 108 prefix_num["REX2"] = "INAT_PFX_REX2" 109 + prefix_num["XOP"] = "INAT_PFX_XOP" 115 110 116 111 clear_vars() 117 112 } ··· 154 147 if (NF != 1) { 155 148 # AVX/escape opcode table 156 149 aid = $2 150 + xopid = -1 157 151 if (gaid <= aid) 158 152 gaid = aid + 1 159 153 if (tname == "") # AVX only opcode table 160 154 tname = sprintf("inat_avx_table_%d", $2) 161 155 } 162 156 if (aid == -1 && eid == -1) # primary opcode table 157 + tname = "inat_primary_table" 158 + } 159 + 160 + /^XOPcode:/ { 161 + if (NF != 1) { 162 + # XOP opcode table 163 + xopid = $2 164 + aid = -1 165 + if (gxopid <= xopid) 166 + gxopid = xopid + 1 167 + if (tname == "") # XOP only opcode table 168 + tname = sprintf("inat_xop_table_%d", $2) 169 + } 170 + if (xopid == -1 && eid == -1) # primary opcode table 163 171 tname = "inat_primary_table" 164 172 } 165 173 ··· 228 206 etable[eid,0] = tname 229 207 if (aid >= 0) 230 208 atable[aid,0] = tname 209 + else if (xopid >= 0) 210 + xoptable[xopid] = tname 231 211 } 232 212 if (array_size(lptable1) != 0) { 233 213 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]", ··· 371 347 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") 372 348 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) 373 349 flags = add_flags(flags, "INAT_VEXOK") 350 + else if (match(ext, xopok_expr) || xopid >= 0) 351 + flags = add_flags(flags, "INAT_XOPOK") 374 352 375 353 # check prefixes 376 354 if (match(ext, prefix_expr)) { ··· 439 413 print " ["i"]["j"] = "atable[i,j]"," 440 414 print "};\n" 441 415 416 + print "/* XOP opcode map array */" 417 + print "const insn_attr_t * const inat_xop_tables[X86_XOP_M_MAX - X86_XOP_M_MIN + 1]" \ 418 + " = {" 419 + for (i = 0; i < gxopid; i++) 420 + if (xoptable[i]) 421 + print " ["i"] = "xoptable[i]"," 422 + print "};" 423 + 442 424 print "#else /* !__BOOT_COMPRESSED */\n" 443 425 444 426 print "/* Escape opcode map array */" ··· 462 428 print "/* AVX opcode map array */" 463 429 print "static const insn_attr_t *inat_avx_tables[X86_VEX_M_MAX + 1]"\ 464 430 "[INAT_LSTPFX_MAX + 1];" 431 + print "" 432 + 433 + print "/* XOP opcode map array */" 434 + print "static const insn_attr_t *inat_xop_tables[X86_XOP_M_MAX - X86_XOP_M_MIN + 1];" 465 435 print "" 466 436 467 437 print "static void inat_init_tables(void)" ··· 492 454 for (j = 0; j < max_lprefix; j++) 493 455 if (atable[i,j]) 494 456 print "\tinat_avx_tables["i"]["j"] = "atable[i,j]";" 457 + 458 + print "" 459 + print "\t/* Print XOP opcode map array */" 460 + for (i = 0; i < gxopid; i++) 461 + if (xoptable[i]) 462 + print "\tinat_xop_tables["i"] = "xoptable[i]";" 495 463 496 464 print "}" 497 465 print "#endif"
+15
tools/arch/x86/include/asm/inat.h
··· 37 37 #define INAT_PFX_EVEX 15 /* EVEX prefix */ 38 38 /* x86-64 REX2 prefix */ 39 39 #define INAT_PFX_REX2 16 /* 0xD5 */ 40 + /* AMD XOP prefix */ 41 + #define INAT_PFX_XOP 17 /* 0x8F */ 40 42 41 43 #define INAT_LSTPFX_MAX 3 42 44 #define INAT_LGCPFX_MAX 11 ··· 79 77 #define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3)) 80 78 #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) 81 79 #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) 80 + #define INAT_XOPOK INAT_VEXOK 82 81 #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) 83 82 #define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7)) 84 83 #define INAT_NO_REX2 (1 << (INAT_FLAG_OFFS + 8)) ··· 114 111 extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, 115 112 insn_byte_t vex_m, 116 113 insn_byte_t vex_pp); 114 + extern insn_attr_t inat_get_xop_attribute(insn_byte_t opcode, 115 + insn_byte_t map_select); 117 116 118 117 /* Attribute checking functions */ 119 118 static inline int inat_is_legacy_prefix(insn_attr_t attr) ··· 167 162 static inline int inat_is_vex3_prefix(insn_attr_t attr) 168 163 { 169 164 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; 165 + } 166 + 167 + static inline int inat_is_xop_prefix(insn_attr_t attr) 168 + { 169 + return (attr & INAT_PFX_MASK) == INAT_PFX_XOP; 170 170 } 171 171 172 172 static inline int inat_is_escape(insn_attr_t attr) ··· 237 227 static inline int inat_accept_vex(insn_attr_t attr) 238 228 { 239 229 return attr & INAT_VEXOK; 230 + } 231 + 232 + static inline int inat_accept_xop(insn_attr_t attr) 233 + { 234 + return attr & INAT_XOPOK; 240 235 } 241 236 242 237 static inline int inat_must_vex(insn_attr_t attr)
+48 -3
tools/arch/x86/include/asm/insn.h
··· 71 71 * prefixes.bytes[3]: last prefix 72 72 */ 73 73 struct insn_field rex_prefix; /* REX prefix */ 74 - struct insn_field vex_prefix; /* VEX prefix */ 74 + union { 75 + struct insn_field vex_prefix; /* VEX prefix */ 76 + struct insn_field xop_prefix; /* XOP prefix */ 77 + }; 75 78 struct insn_field opcode; /* 76 79 * opcode.bytes[0]: opcode1 77 80 * opcode.bytes[1]: opcode2 ··· 138 135 #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ 139 136 #define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */ 140 137 #define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */ 138 + /* XOP bit fields */ 139 + #define X86_XOP_R(xop) ((xop) & 0x80) /* XOP Byte2 */ 140 + #define X86_XOP_X(xop) ((xop) & 0x40) /* XOP Byte2 */ 141 + #define X86_XOP_B(xop) ((xop) & 0x20) /* XOP Byte2 */ 142 + #define X86_XOP_M(xop) ((xop) & 0x1f) /* XOP Byte2 */ 143 + #define X86_XOP_W(xop) ((xop) & 0x80) /* XOP Byte3 */ 144 + #define X86_XOP_V(xop) ((xop) & 0x78) /* XOP Byte3 */ 145 + #define X86_XOP_L(xop) ((xop) & 0x04) /* XOP Byte3 */ 146 + #define X86_XOP_P(xop) ((xop) & 0x03) /* XOP Byte3 */ 147 + #define X86_XOP_M_MIN 0x08 /* Min of XOP.M */ 148 + #define X86_XOP_M_MAX 0x1f /* Max of XOP.M */ 141 149 142 150 extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64); 143 151 extern int insn_get_prefixes(struct insn *insn); ··· 192 178 return X86_REX2_M(insn->rex_prefix.bytes[1]); 193 179 } 194 180 195 - static inline int insn_is_avx(struct insn *insn) 181 + static inline int insn_is_avx_or_xop(struct insn *insn) 196 182 { 197 183 if (!insn->prefixes.got) 198 184 insn_get_prefixes(insn); ··· 204 190 if (!insn->prefixes.got) 205 191 insn_get_prefixes(insn); 206 192 return (insn->vex_prefix.nbytes == 4); 193 + } 194 + 195 + /* If we already know this is AVX/XOP encoded */ 196 + static inline int avx_insn_is_xop(struct insn *insn) 197 + { 198 + insn_attr_t attr = inat_get_opcode_attribute(insn->vex_prefix.bytes[0]); 199 + 200 + return inat_is_xop_prefix(attr); 201 + } 202 + 203 + static inline int insn_is_xop(struct insn *insn) 204 + { 205 + if (!insn_is_avx_or_xop(insn)) 206 + return 0; 207 + 208 + return avx_insn_is_xop(insn); 207 209 } 208 210 209 211 static inline int insn_has_emulate_prefix(struct insn *insn) ··· 252 222 return X86_VEX_W(insn->vex_prefix.bytes[2]); 253 223 } 254 224 225 + static inline insn_byte_t insn_xop_map_bits(struct insn *insn) 226 + { 227 + if (insn->xop_prefix.nbytes < 3) /* XOP is 3 bytes */ 228 + return 0; 229 + return X86_XOP_M(insn->xop_prefix.bytes[1]); 230 + } 231 + 232 + static inline insn_byte_t insn_xop_p_bits(struct insn *insn) 233 + { 234 + return X86_XOP_P(insn->vex_prefix.bytes[2]); 235 + } 236 + 255 237 /* Get the last prefix id from last prefix or VEX prefix */ 256 238 static inline int insn_last_prefix_id(struct insn *insn) 257 239 { 258 - if (insn_is_avx(insn)) 240 + if (insn_is_avx_or_xop(insn)) { 241 + if (avx_insn_is_xop(insn)) 242 + return insn_xop_p_bits(insn); 259 243 return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */ 244 + } 260 245 261 246 if (insn->prefixes.bytes[3]) 262 247 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
+13
tools/arch/x86/lib/inat.c
··· 81 81 return table[opcode]; 82 82 } 83 83 84 + insn_attr_t inat_get_xop_attribute(insn_byte_t opcode, insn_byte_t map_select) 85 + { 86 + const insn_attr_t *table; 87 + 88 + if (map_select < X86_XOP_M_MIN || map_select > X86_XOP_M_MAX) 89 + return 0; 90 + map_select -= X86_XOP_M_MIN; 91 + /* At first, this checks the master table */ 92 + table = inat_xop_tables[map_select]; 93 + if (!table) 94 + return 0; 95 + return table[opcode]; 96 + }
+26 -9
tools/arch/x86/lib/insn.c
··· 200 200 } 201 201 insn->rex_prefix.got = 1; 202 202 203 - /* Decode VEX prefix */ 203 + /* Decode VEX/XOP prefix */ 204 204 b = peek_next(insn_byte_t, insn); 205 - attr = inat_get_opcode_attribute(b); 206 - if (inat_is_vex_prefix(attr)) { 205 + if (inat_is_vex_prefix(attr) || inat_is_xop_prefix(attr)) { 207 206 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1); 208 - if (!insn->x86_64) { 207 + 208 + if (inat_is_xop_prefix(attr) && X86_MODRM_REG(b2) == 0) { 209 + /* Grp1A.0 is always POP Ev */ 210 + goto vex_end; 211 + } else if (!insn->x86_64) { 209 212 /* 210 213 * In 32-bits mode, if the [7:6] bits (mod bits of 211 214 * ModRM) on the second byte are not 11b, it is ··· 229 226 if (insn->x86_64 && X86_VEX_W(b2)) 230 227 /* VEX.W overrides opnd_size */ 231 228 insn->opnd_bytes = 8; 232 - } else if (inat_is_vex3_prefix(attr)) { 229 + } else if (inat_is_vex3_prefix(attr) || inat_is_xop_prefix(attr)) { 233 230 b2 = peek_nbyte_next(insn_byte_t, insn, 2); 234 231 insn_set_byte(&insn->vex_prefix, 2, b2); 235 232 insn->vex_prefix.nbytes = 3; 236 233 insn->next_byte += 3; 237 234 if (insn->x86_64 && X86_VEX_W(b2)) 238 - /* VEX.W overrides opnd_size */ 235 + /* VEX.W/XOP.W overrides opnd_size */ 239 236 insn->opnd_bytes = 8; 240 237 } else { 241 238 /* ··· 291 288 insn_set_byte(opcode, 0, op); 292 289 opcode->nbytes = 1; 293 290 294 - /* Check if there is VEX prefix or not */ 295 - if (insn_is_avx(insn)) { 291 + /* Check if there is VEX/XOP prefix or not */ 292 + if (insn_is_avx_or_xop(insn)) { 296 293 insn_byte_t m, p; 294 + 295 + /* XOP prefix has different encoding */ 296 + if (unlikely(avx_insn_is_xop(insn))) { 297 + m = insn_xop_map_bits(insn); 298 + insn->attr = inat_get_xop_attribute(op, m); 299 + if (!inat_accept_xop(insn->attr)) { 300 + insn->attr = 0; 301 + return -EINVAL; 302 + } 303 + /* XOP has only 1 byte for opcode */ 304 + goto end; 305 + } 306 + 297 307 m = insn_vex_m_bits(insn); 298 308 p = insn_vex_p_bits(insn); 299 309 insn->attr = inat_get_avx_attribute(op, m, p); ··· 399 383 pfx_id = insn_last_prefix_id(insn); 400 384 insn->attr = inat_get_group_attribute(mod, pfx_id, 401 385 insn->attr); 402 - if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) { 386 + if (insn_is_avx_or_xop(insn) && !inat_accept_vex(insn->attr) && 387 + !inat_accept_xop(insn->attr)) { 403 388 /* Bad insn */ 404 389 insn->attr = 0; 405 390 return -EINVAL;
+110 -1
tools/arch/x86/lib/x86-opcode-map.txt
··· 27 27 # (evo): this opcode is changed by EVEX prefix (EVEX opcode) 28 28 # (v): this opcode requires VEX prefix. 29 29 # (v1): this opcode only supports 128bit VEX. 30 + # (xop): this opcode accepts XOP prefix. 31 + # 32 + # XOP Superscripts 33 + # (W=0): this opcode requires XOP.W == 0 34 + # (W=1): this opcode requires XOP.W == 1 30 35 # 31 36 # Last Prefix Superscripts 32 37 # - (66): the last prefix is 0x66 ··· 199 194 8c: MOV Ev,Sw 200 195 8d: LEA Gv,M 201 196 8e: MOV Sw,Ew 202 - 8f: Grp1A (1A) | POP Ev (d64) 197 + 8f: Grp1A (1A) | POP Ev (d64) | XOP (Prefix) 203 198 # 0x90 - 0x9f 204 199 90: NOP | PAUSE (F3) | XCHG r8,rAX 205 200 91: XCHG rCX/r9,rAX ··· 1111 1106 f8: URDMSR Rq,Id (F2),(v1),(11B) | UWRMSR Id,Rq (F3),(v1),(11B) 1112 1107 EndTable 1113 1108 1109 + # From AMD64 Architecture Programmer's Manual Vol3, Appendix A.1.5 1110 + Table: XOP map 8h 1111 + Referrer: 1112 + XOPcode: 0 1113 + 85: VPMACSSWW Vo,Ho,Wo,Lo 1114 + 86: VPMACSSWD Vo,Ho,Wo,Lo 1115 + 87: VPMACSSDQL Vo,Ho,Wo,Lo 1116 + 8e: VPMACSSDD Vo,Ho,Wo,Lo 1117 + 8f: VPMACSSDQH Vo,Ho,Wo,Lo 1118 + 95: VPMACSWW Vo,Ho,Wo,Lo 1119 + 96: VPMACSWD Vo,Ho,Wo,Lo 1120 + 97: VPMACSDQL Vo,Ho,Wo,Lo 1121 + 9e: VPMACSDD Vo,Ho,Wo,Lo 1122 + 9f: VPMACSDQH Vo,Ho,Wo,Lo 1123 + a2: VPCMOV Vx,Hx,Wx,Lx (W=0) | VPCMOV Vx,Hx,Lx,Wx (W=1) 1124 + a3: VPPERM Vo,Ho,Wo,Lo (W=0) | VPPERM Vo,Ho,Lo,Wo (W=1) 1125 + a6: VPMADCSSWD Vo,Ho,Wo,Lo 1126 + b6: VPMADCSWD Vo,Ho,Wo,Lo 1127 + c0: VPROTB Vo,Wo,Ib 1128 + c1: VPROTW Vo,Wo,Ib 1129 + c2: VPROTD Vo,Wo,Ib 1130 + c3: VPROTQ Vo,Wo,Ib 1131 + cc: VPCOMccB Vo,Ho,Wo,Ib 1132 + cd: VPCOMccW Vo,Ho,Wo,Ib 1133 + ce: VPCOMccD Vo,Ho,Wo,Ib 1134 + cf: VPCOMccQ Vo,Ho,Wo,Ib 1135 + ec: VPCOMccUB Vo,Ho,Wo,Ib 1136 + ed: VPCOMccUW Vo,Ho,Wo,Ib 1137 + ee: VPCOMccUD Vo,Ho,Wo,Ib 1138 + ef: VPCOMccUQ Vo,Ho,Wo,Ib 1139 + EndTable 1140 + 1141 + Table: XOP map 9h 1142 + Referrer: 1143 + XOPcode: 1 1144 + 01: GrpXOP1 1145 + 02: GrpXOP2 1146 + 12: GrpXOP3 1147 + 80: VFRCZPS Vx,Wx 1148 + 81: VFRCZPD Vx,Wx 1149 + 82: VFRCZSS Vq,Wss 1150 + 83: VFRCZSD Vq,Wsd 1151 + 90: VPROTB Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1152 + 91: VPROTW Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1153 + 92: VPROTD Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1154 + 93: VPROTQ Vo,Wo,Ho (W=0) | VPROTB Vo,Ho,Wo (W=1) 1155 + 94: VPSHLB Vo,Wo,Ho (W=0) | VPSHLB Vo,Ho,Wo (W=1) 1156 + 95: VPSHLW Vo,Wo,Ho (W=0) | VPSHLW Vo,Ho,Wo (W=1) 1157 + 96: VPSHLD Vo,Wo,Ho (W=0) | VPSHLD Vo,Ho,Wo (W=1) 1158 + 97: VPSHLQ Vo,Wo,Ho (W=0) | VPSHLQ Vo,Ho,Wo (W=1) 1159 + 98: VPSHAB Vo,Wo,Ho (W=0) | VPSHAB Vo,Ho,Wo (W=1) 1160 + 99: VPSHAW Vo,Wo,Ho (W=0) | VPSHAW Vo,Ho,Wo (W=1) 1161 + 9a: VPSHAD Vo,Wo,Ho (W=0) | VPSHAD Vo,Ho,Wo (W=1) 1162 + 9b: VPSHAQ Vo,Wo,Ho (W=0) | VPSHAQ Vo,Ho,Wo (W=1) 1163 + c1: VPHADDBW Vo,Wo 1164 + c2: VPHADDBD Vo,Wo 1165 + c3: VPHADDBQ Vo,Wo 1166 + c6: VPHADDWD Vo,Wo 1167 + c7: VPHADDWQ Vo,Wo 1168 + cb: VPHADDDQ Vo,Wo 1169 + d1: VPHADDUBWD Vo,Wo 1170 + d2: VPHADDUBD Vo,Wo 1171 + d3: VPHADDUBQ Vo,Wo 1172 + d6: VPHADDUWD Vo,Wo 1173 + d7: VPHADDUWQ Vo,Wo 1174 + db: VPHADDUDQ Vo,Wo 1175 + e1: VPHSUBBW Vo,Wo 1176 + e2: VPHSUBWD Vo,Wo 1177 + e3: VPHSUBDQ Vo,Wo 1178 + EndTable 1179 + 1180 + Table: XOP map Ah 1181 + Referrer: 1182 + XOPcode: 2 1183 + 10: BEXTR Gy,Ey,Id 1184 + 12: GrpXOP4 1185 + EndTable 1186 + 1114 1187 GrpTable: Grp1 1115 1188 0: ADD 1116 1189 1: OR ··· 1402 1319 2: xcrypt-cbc 1403 1320 4: xcrypt-cfb 1404 1321 5: xcrypt-ofb 1322 + EndTable 1323 + 1324 + # GrpXOP1-4 is shown in AMD APM Vol.3 Appendix A as XOP group #1-4 1325 + GrpTable: GrpXOP1 1326 + 1: BLCFILL By,Ey (xop) 1327 + 2: BLSFILL By,Ey (xop) 1328 + 3: BLCS By,Ey (xop) 1329 + 4: TZMSK By,Ey (xop) 1330 + 5: BLCIC By,Ey (xop) 1331 + 6: BLSIC By,Ey (xop) 1332 + 7: T1MSKC By,Ey (xop) 1333 + EndTable 1334 + 1335 + GrpTable: GrpXOP2 1336 + 1: BLCMSK By,Ey (xop) 1337 + 6: BLCI By,Ey (xop) 1338 + EndTable 1339 + 1340 + GrpTable: GrpXOP3 1341 + 0: LLWPCB Ry (xop) 1342 + 1: SLWPCB Ry (xop) 1343 + EndTable 1344 + 1345 + GrpTable: GrpXOP4 1346 + 0: LWPINS By,Ed,Id (xop) 1347 + 1: LWPVAL By,Ed,Id (xop) 1405 1348 EndTable
+44
tools/arch/x86/tools/gen-insn-attr-x86.awk
··· 21 21 eid = -1 # escape id 22 22 gid = -1 # group id 23 23 aid = -1 # AVX id 24 + xopid = -1 # XOP id 24 25 tname = "" 25 26 } 26 27 ··· 40 39 ggid = 1 41 40 geid = 1 42 41 gaid = 0 42 + gxopid = 0 43 43 delete etable 44 44 delete gtable 45 45 delete atable 46 + delete xoptable 46 47 47 48 opnd_expr = "^[A-Za-z/]" 48 49 ext_expr = "^\\(" ··· 64 61 imm_flag["Ob"] = "INAT_MOFFSET" 65 62 imm_flag["Ov"] = "INAT_MOFFSET" 66 63 imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" 64 + imm_flag["Lo"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)" 67 65 68 66 modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])" 69 67 force64_expr = "\\([df]64\\)" ··· 91 87 evexonly_expr = "\\(ev\\)" 92 88 # (es) is the same as (ev) but also "SCALABLE" i.e. W and pp determine operand size 93 89 evex_scalable_expr = "\\(es\\)" 90 + # All opcodes in XOP table or with (xop) superscript accept XOP prefix 91 + xopok_expr = "\\(xop\\)" 94 92 95 93 prefix_expr = "\\(Prefix\\)" 96 94 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" ··· 112 106 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" 113 107 prefix_num["EVEX"] = "INAT_PFX_EVEX" 114 108 prefix_num["REX2"] = "INAT_PFX_REX2" 109 + prefix_num["XOP"] = "INAT_PFX_XOP" 115 110 116 111 clear_vars() 117 112 } ··· 154 147 if (NF != 1) { 155 148 # AVX/escape opcode table 156 149 aid = $2 150 + xopid = -1 157 151 if (gaid <= aid) 158 152 gaid = aid + 1 159 153 if (tname == "") # AVX only opcode table 160 154 tname = sprintf("inat_avx_table_%d", $2) 161 155 } 162 156 if (aid == -1 && eid == -1) # primary opcode table 157 + tname = "inat_primary_table" 158 + } 159 + 160 + /^XOPcode:/ { 161 + if (NF != 1) { 162 + # XOP opcode table 163 + xopid = $2 164 + aid = -1 165 + if (gxopid <= xopid) 166 + gxopid = xopid + 1 167 + if (tname == "") # XOP only opcode table 168 + tname = sprintf("inat_xop_table_%d", $2) 169 + } 170 + if (xopid == -1 && eid == -1) # primary opcode table 163 171 tname = "inat_primary_table" 164 172 } 165 173 ··· 228 206 etable[eid,0] = tname 229 207 if (aid >= 0) 230 208 atable[aid,0] = tname 209 + else if (xopid >= 0) 210 + xoptable[xopid] = tname 231 211 } 232 212 if (array_size(lptable1) != 0) { 233 213 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]", ··· 371 347 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") 372 348 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) 373 349 flags = add_flags(flags, "INAT_VEXOK") 350 + else if (match(ext, xopok_expr) || xopid >= 0) 351 + flags = add_flags(flags, "INAT_XOPOK") 374 352 375 353 # check prefixes 376 354 if (match(ext, prefix_expr)) { ··· 439 413 print " ["i"]["j"] = "atable[i,j]"," 440 414 print "};\n" 441 415 416 + print "/* XOP opcode map array */" 417 + print "const insn_attr_t * const inat_xop_tables[X86_XOP_M_MAX - X86_XOP_M_MIN + 1]" \ 418 + " = {" 419 + for (i = 0; i < gxopid; i++) 420 + if (xoptable[i]) 421 + print " ["i"] = "xoptable[i]"," 422 + print "};" 423 + 442 424 print "#else /* !__BOOT_COMPRESSED */\n" 443 425 444 426 print "/* Escape opcode map array */" ··· 462 428 print "/* AVX opcode map array */" 463 429 print "static const insn_attr_t *inat_avx_tables[X86_VEX_M_MAX + 1]"\ 464 430 "[INAT_LSTPFX_MAX + 1];" 431 + print "" 432 + 433 + print "/* XOP opcode map array */" 434 + print "static const insn_attr_t *inat_xop_tables[X86_XOP_M_MAX - X86_XOP_M_MIN + 1];" 465 435 print "" 466 436 467 437 print "static void inat_init_tables(void)" ··· 492 454 for (j = 0; j < max_lprefix; j++) 493 455 if (atable[i,j]) 494 456 print "\tinat_avx_tables["i"]["j"] = "atable[i,j]";" 457 + 458 + print "" 459 + print "\t/* Print XOP opcode map array */" 460 + for (i = 0; i < gxopid; i++) 461 + if (xoptable[i]) 462 + print "\tinat_xop_tables["i"] = "xoptable[i]";" 495 463 496 464 print "}" 497 465 print "#endif"
+1 -1
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
··· 32 32 intel_pt_insn->rel = 0; 33 33 intel_pt_insn->emulated_ptwrite = false; 34 34 35 - if (insn_is_avx(insn)) { 35 + if (insn_is_avx_or_xop(insn)) { 36 36 intel_pt_insn->op = INTEL_PT_OP_OTHER; 37 37 intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH; 38 38 intel_pt_insn->length = insn->length;