Mercurial > repos > blastem
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; |