comparison gen_x86.c @ 728:cb1c005880e7

Generate an error in x86-32 builds for most cases when a REX prefix would be generated
author Michael Pavone <pavone@retrodev.com>
date Sat, 23 May 2015 20:25:16 -0700
parents e11e68918691
children cfa402c6ced8
comparison
equal deleted inserted replaced
727:59a98179d3ba 728:cb1c005880e7
128 X86_R13, 128 X86_R13,
129 X86_R14, 129 X86_R14,
130 X86_R15 130 X86_R15
131 } x86_regs_enc; 131 } x86_regs_enc;
132 132
133 char * x86_reg_names[] = {
134 #ifdef X86_64
135 "rax",
136 "rcx",
137 "rdx",
138 "rbx",
139 "rsp",
140 "rbp",
141 "rsi",
142 "rdi",
143 #else
144 "eax",
145 "ecx",
146 "edx",
147 "ebx",
148 "esp",
149 "ebp",
150 "esi",
151 "edi",
152 #endif
153 "ah",
154 "ch",
155 "dh",
156 "bh",
157 "r8",
158 "r9",
159 "r10",
160 "r11",
161 "r12",
162 "r13",
163 "r14",
164 "r15",
165 };
166
167 char * x86_sizes[] = {
168 "b", "w", "d", "q"
169 };
170
133 void jmp_nocheck(code_info *code, code_ptr dest) 171 void jmp_nocheck(code_info *code, code_ptr dest)
134 { 172 {
135 code_ptr out = code->cur; 173 code_ptr out = code->cur;
136 ptrdiff_t disp = dest-(out+2); 174 ptrdiff_t disp = dest-(out+2);
137 if (disp <= 0x7F && disp >= -0x80) { 175 if (disp <= 0x7F && disp >= -0x80) {
188 tmp = dst; 226 tmp = dst;
189 dst = src; 227 dst = src;
190 src = tmp; 228 src = tmp;
191 } 229 }
192 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { 230 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) {
231 #ifdef X86_64
193 *out = PRE_REX; 232 *out = PRE_REX;
194 if (src >= AH && src <= BH || dst >= AH && dst <= BH) { 233 if (src >= AH && src <= BH || dst >= AH && dst <= BH) {
195 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); 234 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
196 exit(1); 235 exit(1);
197 } 236 }
205 if (dst >= R8) { 244 if (dst >= R8) {
206 *out |= REX_RM_FIELD; 245 *out |= REX_RM_FIELD;
207 dst -= (R8 - X86_R8); 246 dst -= (R8 - X86_R8);
208 } 247 }
209 out++; 248 out++;
249 #else
250 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, src: %s, dst: %s, size: %s\n", opcode, x86_reg_names[src], x86_reg_names[dst], x86_sizes[size]);
251 exit(1);
252 #endif
210 } 253 }
211 if (size == SZ_B) { 254 if (size == SZ_B) {
212 if (src >= AH && src <= BH) { 255 if (src >= AH && src <= BH) {
213 src -= (AH-X86_AH); 256 src -= (AH-X86_AH);
214 } 257 }
236 uint8_t tmp; 279 uint8_t tmp;
237 if (size == SZ_W) { 280 if (size == SZ_W) {
238 *(out++) = PRE_SIZE; 281 *(out++) = PRE_SIZE;
239 } 282 }
240 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { 283 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
284 #ifdef X86_64
241 *out = PRE_REX; 285 *out = PRE_REX;
242 if (reg >= AH && reg <= BH) { 286 if (reg >= AH && reg <= BH) {
243 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); 287 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
244 exit(1); 288 exit(1);
245 } 289 }
253 if (base >= R8) { 297 if (base >= R8) {
254 *out |= REX_RM_FIELD; 298 *out |= REX_RM_FIELD;
255 base -= (R8 - X86_R8); 299 base -= (R8 - X86_R8);
256 } 300 }
257 out++; 301 out++;
302 #else
303 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
304 exit(1);
305 #endif
258 } 306 }
259 if (size == SZ_B) { 307 if (size == SZ_B) {
260 if (reg >= AH && reg <= BH) { 308 if (reg >= AH && reg <= BH) {
261 reg -= (AH-X86_AH); 309 reg -= (AH-X86_AH);
262 } 310 }
296 uint8_t tmp; 344 uint8_t tmp;
297 if (size == SZ_W) { 345 if (size == SZ_W) {
298 *(out++) = PRE_SIZE; 346 *(out++) = PRE_SIZE;
299 } 347 }
300 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { 348 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
349 #ifdef X86_64
301 *out = PRE_REX; 350 *out = PRE_REX;
302 if (reg >= AH && reg <= BH) { 351 if (reg >= AH && reg <= BH) {
303 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); 352 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
304 exit(1); 353 exit(1);
305 } 354 }
313 if (base >= R8) { 362 if (base >= R8) {
314 *out |= REX_RM_FIELD; 363 *out |= REX_RM_FIELD;
315 base -= (R8 - X86_R8); 364 base -= (R8 - X86_R8);
316 } 365 }
317 out++; 366 out++;
367 #else
368 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
369 exit(1);
370 #endif
318 } 371 }
319 if (size == SZ_B) { 372 if (size == SZ_B) {
320 if (reg >= AH && reg <= BH) { 373 if (reg >= AH && reg <= BH) {
321 reg -= (AH-X86_AH); 374 reg -= (AH-X86_AH);
322 } 375 }
347 uint8_t tmp; 400 uint8_t tmp;
348 if (size == SZ_W) { 401 if (size == SZ_W) {
349 *(out++) = PRE_SIZE; 402 *(out++) = PRE_SIZE;
350 } 403 }
351 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { 404 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
405 #ifdef X86_64
352 *out = PRE_REX; 406 *out = PRE_REX;
353 if (reg >= AH && reg <= BH) { 407 if (reg >= AH && reg <= BH) {
354 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); 408 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
355 exit(1); 409 exit(1);
356 } 410 }
368 if (index >= R8) { 422 if (index >= R8) {
369 *out |= REX_SIB_FIELD; 423 *out |= REX_SIB_FIELD;
370 index -= (R8 - X86_R8); 424 index -= (R8 - X86_R8);
371 } 425 }
372 out++; 426 out++;
427 #else
428 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
429 exit(1);
430 #endif
373 } 431 }
374 if (size == SZ_B) { 432 if (size == SZ_B) {
375 if (reg >= AH && reg <= BH) { 433 if (reg >= AH && reg <= BH) {
376 reg -= (AH-X86_AH); 434 reg -= (AH-X86_AH);
377 } 435 }
398 uint8_t tmp; 456 uint8_t tmp;
399 if (size == SZ_W) { 457 if (size == SZ_W) {
400 *(out++) = PRE_SIZE; 458 *(out++) = PRE_SIZE;
401 } 459 }
402 if (size == SZ_Q || dst >= R8) { 460 if (size == SZ_Q || dst >= R8) {
461 #ifdef X86_64
403 *out = PRE_REX; 462 *out = PRE_REX;
404 if (dst >= AH && dst <= BH) { 463 if (dst >= AH && dst <= BH) {
405 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); 464 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
406 exit(1); 465 exit(1);
407 } 466 }
411 if (dst >= R8) { 470 if (dst >= R8) {
412 *out |= REX_RM_FIELD; 471 *out |= REX_RM_FIELD;
413 dst -= (R8 - X86_R8); 472 dst -= (R8 - X86_R8);
414 } 473 }
415 out++; 474 out++;
475 #else
476 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]);
477 exit(1);
478 #endif
416 } 479 }
417 if (size == SZ_B) { 480 if (size == SZ_B) {
418 if (dst >= AH && dst <= BH) { 481 if (dst >= AH && dst <= BH) {
419 dst -= (AH-X86_AH); 482 dst -= (AH-X86_AH);
420 } 483 }
433 uint8_t tmp; 496 uint8_t tmp;
434 if (size == SZ_W) { 497 if (size == SZ_W) {
435 *(out++) = PRE_SIZE; 498 *(out++) = PRE_SIZE;
436 } 499 }
437 if (size == SZ_Q || dst >= R8) { 500 if (size == SZ_Q || dst >= R8) {
501 #ifdef X86_64
438 *out = PRE_REX; 502 *out = PRE_REX;
439 if (size == SZ_Q) { 503 if (size == SZ_Q) {
440 *out |= REX_QUAD; 504 *out |= REX_QUAD;
441 } 505 }
442 if (dst >= R8) { 506 if (dst >= R8) {
443 *out |= REX_RM_FIELD; 507 *out |= REX_RM_FIELD;
444 dst -= (R8 - X86_R8); 508 dst -= (R8 - X86_R8);
445 } 509 }
446 out++; 510 out++;
511 #else
512 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]);
513 exit(1);
514 #endif
447 } 515 }
448 if (size != SZ_B) { 516 if (size != SZ_B) {
449 opcode |= BIT_SIZE; 517 opcode |= BIT_SIZE;
450 } 518 }
451 *(out++) = opcode; 519 *(out++) = opcode;
476 } 544 }
477 if (dst == RAX && !sign_extend) { 545 if (dst == RAX && !sign_extend) {
478 if (size != SZ_B) { 546 if (size != SZ_B) {
479 al_opcode |= BIT_SIZE; 547 al_opcode |= BIT_SIZE;
480 if (size == SZ_Q) { 548 if (size == SZ_Q) {
549 #ifdef X86_64
481 *out = PRE_REX | REX_QUAD; 550 *out = PRE_REX | REX_QUAD;
551 #else
552 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, size: %s\n", al_opcode, x86_reg_names[dst], x86_sizes[size]);
553 exit(1);
554 #endif
482 } 555 }
483 } 556 }
484 *(out++) = al_opcode | BIT_IMMED_RAX; 557 *(out++) = al_opcode | BIT_IMMED_RAX;
485 } else { 558 } else {
486 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) { 559 if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
560 #ifdef X86_64
487 *out = PRE_REX; 561 *out = PRE_REX;
488 if (size == SZ_Q) { 562 if (size == SZ_Q) {
489 *out |= REX_QUAD; 563 *out |= REX_QUAD;
490 } 564 }
491 if (dst >= R8) { 565 if (dst >= R8) {
492 *out |= REX_RM_FIELD; 566 *out |= REX_RM_FIELD;
493 dst -= (R8 - X86_R8); 567 dst -= (R8 - X86_R8);
494 } 568 }
495 out++; 569 out++;
570 #else
571 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]);
572 exit(1);
573 #endif
496 } 574 }
497 if (dst >= AH && dst <= BH) { 575 if (dst >= AH && dst <= BH) {
498 dst -= (AH-X86_AH); 576 dst -= (AH-X86_AH);
499 } 577 }
500 if (size != SZ_B) { 578 if (size != SZ_B) {
529 if (size == SZ_W) { 607 if (size == SZ_W) {
530 *(out++) = PRE_SIZE; 608 *(out++) = PRE_SIZE;
531 } 609 }
532 610
533 if (size == SZ_Q || dst >= R8) { 611 if (size == SZ_Q || dst >= R8) {
612 #ifdef X86_64
534 *out = PRE_REX; 613 *out = PRE_REX;
535 if (size == SZ_Q) { 614 if (size == SZ_Q) {
536 *out |= REX_QUAD; 615 *out |= REX_QUAD;
537 } 616 }
538 if (dst >= R8) { 617 if (dst >= R8) {
539 *out |= REX_RM_FIELD; 618 *out |= REX_RM_FIELD;
540 dst -= (R8 - X86_R8); 619 dst -= (R8 - X86_R8);
541 } 620 }
542 out++; 621 out++;
622 #else
623 fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]);
624 exit(1);
625 #endif
543 } 626 }
544 if (size != SZ_B) { 627 if (size != SZ_B) {
545 opcode |= BIT_SIZE; 628 opcode |= BIT_SIZE;
546 } 629 }
547 *(out++) = opcode; 630 *(out++) = opcode;