Mercurial > repos > blastem
comparison gen_x86.c @ 799:0b692b5d154b
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 26 Jul 2015 13:25:31 -0700 |
parents | 724bbec47f86 |
children | a7774fc2de4b |
comparison
equal
deleted
inserted
replaced
798:062a2199daf6 | 799:0b692b5d154b |
---|---|
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "gen_x86.h" | 6 #include "gen_x86.h" |
7 #include "mem.h" | 7 #include "mem.h" |
8 #include "util.h" | |
8 #include <stddef.h> | 9 #include <stddef.h> |
9 #include <stdio.h> | 10 #include <stdio.h> |
10 #include <stdlib.h> | 11 #include <stdlib.h> |
11 #include <stdarg.h> | 12 #include <stdarg.h> |
12 #include <string.h> | 13 #include <string.h> |
185 disp >>= 8; | 186 disp >>= 8; |
186 *(out++) = disp; | 187 *(out++) = disp; |
187 disp >>= 8; | 188 disp >>= 8; |
188 *(out++) = disp; | 189 *(out++) = disp; |
189 } else { | 190 } else { |
190 fprintf(stderr, "jmp: %p - %p = %lX\n", dest, out + 6, (long)disp); | 191 fatal_error("jmp: %p - %p = %l which is out of range of a 32-bit displacementX\n", dest, out + 6, (long)disp); |
191 exit(1); | |
192 } | 192 } |
193 } | 193 } |
194 code->cur = out; | 194 code->cur = out; |
195 } | 195 } |
196 | 196 |
198 { | 198 { |
199 if (code->cur + inst_size > code->last) { | 199 if (code->cur + inst_size > code->last) { |
200 size_t size = CODE_ALLOC_SIZE; | 200 size_t size = CODE_ALLOC_SIZE; |
201 code_ptr next_code = alloc_code(&size); | 201 code_ptr next_code = alloc_code(&size); |
202 if (!next_code) { | 202 if (!next_code) { |
203 fputs("Failed to allocate memory for generated code\n", stderr); | 203 fatal_error("Failed to allocate memory for generated code\n"); |
204 exit(1); | |
205 } | 204 } |
206 if (next_code != code->last + RESERVE_WORDS) { | 205 if (next_code != code->last + RESERVE_WORDS) { |
207 //new chunk is not contiguous with the current one | 206 //new chunk is not contiguous with the current one |
208 jmp_nocheck(code, next_code); | 207 jmp_nocheck(code, next_code); |
209 code->cur = next_code; | 208 code->cur = next_code; |
229 } | 228 } |
230 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { | 229 if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) { |
231 #ifdef X86_64 | 230 #ifdef X86_64 |
232 *out = PRE_REX; | 231 *out = PRE_REX; |
233 if (src >= AH && src <= BH || dst >= AH && dst <= BH) { | 232 if (src >= AH && src <= BH || dst >= AH && dst <= BH) { |
234 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); | 233 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); |
235 exit(1); | |
236 } | 234 } |
237 if (size == SZ_Q) { | 235 if (size == SZ_Q) { |
238 *out |= REX_QUAD; | 236 *out |= REX_QUAD; |
239 } | 237 } |
240 if (src >= R8) { | 238 if (src >= R8) { |
245 *out |= REX_RM_FIELD; | 243 *out |= REX_RM_FIELD; |
246 dst -= (R8 - X86_R8); | 244 dst -= (R8 - X86_R8); |
247 } | 245 } |
248 out++; | 246 out++; |
249 #else | 247 #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]); | 248 fatal_error("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 | 249 #endif |
253 } | 250 } |
254 if (size == SZ_B) { | 251 if (size == SZ_B) { |
255 if (src >= AH && src <= BH) { | 252 if (src >= AH && src <= BH) { |
256 src -= (AH-X86_AH); | 253 src -= (AH-X86_AH); |
282 } | 279 } |
283 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { | 280 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { |
284 #ifdef X86_64 | 281 #ifdef X86_64 |
285 *out = PRE_REX; | 282 *out = PRE_REX; |
286 if (reg >= AH && reg <= BH) { | 283 if (reg >= AH && reg <= BH) { |
287 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); | 284 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); |
288 exit(1); | |
289 } | 285 } |
290 if (size == SZ_Q) { | 286 if (size == SZ_Q) { |
291 *out |= REX_QUAD; | 287 *out |= REX_QUAD; |
292 } | 288 } |
293 if (reg >= R8) { | 289 if (reg >= R8) { |
298 *out |= REX_RM_FIELD; | 294 *out |= REX_RM_FIELD; |
299 base -= (R8 - X86_R8); | 295 base -= (R8 - X86_R8); |
300 } | 296 } |
301 out++; | 297 out++; |
302 #else | 298 #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]); | 299 fatal_error("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 | 300 #endif |
306 } | 301 } |
307 if (size == SZ_B) { | 302 if (size == SZ_B) { |
308 if (reg >= AH && reg <= BH) { | 303 if (reg >= AH && reg <= BH) { |
309 reg -= (AH-X86_AH); | 304 reg -= (AH-X86_AH); |
347 } | 342 } |
348 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { | 343 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { |
349 #ifdef X86_64 | 344 #ifdef X86_64 |
350 *out = PRE_REX; | 345 *out = PRE_REX; |
351 if (reg >= AH && reg <= BH) { | 346 if (reg >= AH && reg <= BH) { |
352 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); | 347 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); |
353 exit(1); | |
354 } | 348 } |
355 if (size == SZ_Q) { | 349 if (size == SZ_Q) { |
356 *out |= REX_QUAD; | 350 *out |= REX_QUAD; |
357 } | 351 } |
358 if (reg >= R8) { | 352 if (reg >= R8) { |
363 *out |= REX_RM_FIELD; | 357 *out |= REX_RM_FIELD; |
364 base -= (R8 - X86_R8); | 358 base -= (R8 - X86_R8); |
365 } | 359 } |
366 out++; | 360 out++; |
367 #else | 361 #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]); | 362 fatal_error("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 | 363 #endif |
371 } | 364 } |
372 if (size == SZ_B) { | 365 if (size == SZ_B) { |
373 if (reg >= AH && reg <= BH) { | 366 if (reg >= AH && reg <= BH) { |
374 reg -= (AH-X86_AH); | 367 reg -= (AH-X86_AH); |
403 } | 396 } |
404 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { | 397 if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) { |
405 #ifdef X86_64 | 398 #ifdef X86_64 |
406 *out = PRE_REX; | 399 *out = PRE_REX; |
407 if (reg >= AH && reg <= BH) { | 400 if (reg >= AH && reg <= BH) { |
408 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); | 401 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); |
409 exit(1); | |
410 } | 402 } |
411 if (size == SZ_Q) { | 403 if (size == SZ_Q) { |
412 *out |= REX_QUAD; | 404 *out |= REX_QUAD; |
413 } | 405 } |
414 if (reg >= R8) { | 406 if (reg >= R8) { |
423 *out |= REX_SIB_FIELD; | 415 *out |= REX_SIB_FIELD; |
424 index -= (R8 - X86_R8); | 416 index -= (R8 - X86_R8); |
425 } | 417 } |
426 out++; | 418 out++; |
427 #else | 419 #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]); | 420 fatal_error("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 | 421 #endif |
431 } | 422 } |
432 if (size == SZ_B) { | 423 if (size == SZ_B) { |
433 if (reg >= AH && reg <= BH) { | 424 if (reg >= AH && reg <= BH) { |
434 reg -= (AH-X86_AH); | 425 reg -= (AH-X86_AH); |
459 } | 450 } |
460 if (size == SZ_Q || dst >= R8) { | 451 if (size == SZ_Q || dst >= R8) { |
461 #ifdef X86_64 | 452 #ifdef X86_64 |
462 *out = PRE_REX; | 453 *out = PRE_REX; |
463 if (dst >= AH && dst <= BH) { | 454 if (dst >= AH && dst <= BH) { |
464 fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); | 455 fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); |
465 exit(1); | |
466 } | 456 } |
467 if (size == SZ_Q) { | 457 if (size == SZ_Q) { |
468 *out |= REX_QUAD; | 458 *out |= REX_QUAD; |
469 } | 459 } |
470 if (dst >= R8) { | 460 if (dst >= R8) { |
471 *out |= REX_RM_FIELD; | 461 *out |= REX_RM_FIELD; |
472 dst -= (R8 - X86_R8); | 462 dst -= (R8 - X86_R8); |
473 } | 463 } |
474 out++; | 464 out++; |
475 #else | 465 #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]); | 466 fatal_error("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 | 467 #endif |
479 } | 468 } |
480 if (size == SZ_B) { | 469 if (size == SZ_B) { |
481 if (dst >= AH && dst <= BH) { | 470 if (dst >= AH && dst <= BH) { |
482 dst -= (AH-X86_AH); | 471 dst -= (AH-X86_AH); |
507 *out |= REX_RM_FIELD; | 496 *out |= REX_RM_FIELD; |
508 dst -= (R8 - X86_R8); | 497 dst -= (R8 - X86_R8); |
509 } | 498 } |
510 out++; | 499 out++; |
511 #else | 500 #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]); | 501 fatal_error("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 | 502 #endif |
515 } | 503 } |
516 if (size != SZ_B) { | 504 if (size != SZ_B) { |
517 opcode |= BIT_SIZE; | 505 opcode |= BIT_SIZE; |
518 } | 506 } |
547 al_opcode |= BIT_SIZE; | 535 al_opcode |= BIT_SIZE; |
548 if (size == SZ_Q) { | 536 if (size == SZ_Q) { |
549 #ifdef X86_64 | 537 #ifdef X86_64 |
550 *out = PRE_REX | REX_QUAD; | 538 *out = PRE_REX | REX_QUAD; |
551 #else | 539 #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]); | 540 fatal_error("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 | 541 #endif |
555 } | 542 } |
556 } | 543 } |
557 *(out++) = al_opcode | BIT_IMMED_RAX; | 544 *(out++) = al_opcode | BIT_IMMED_RAX; |
558 } else { | 545 } else { |
566 *out |= REX_RM_FIELD; | 553 *out |= REX_RM_FIELD; |
567 dst -= (R8 - X86_R8); | 554 dst -= (R8 - X86_R8); |
568 } | 555 } |
569 out++; | 556 out++; |
570 #else | 557 #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]); | 558 fatal_error("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 | 559 #endif |
574 } | 560 } |
575 if (dst >= AH && dst <= BH) { | 561 if (dst >= AH && dst <= BH) { |
576 dst -= (AH-X86_AH); | 562 dst -= (AH-X86_AH); |
577 } | 563 } |
618 *out |= REX_RM_FIELD; | 604 *out |= REX_RM_FIELD; |
619 dst -= (R8 - X86_R8); | 605 dst -= (R8 - X86_R8); |
620 } | 606 } |
621 out++; | 607 out++; |
622 #else | 608 #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]); | 609 fatal_error("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 | 610 #endif |
626 } | 611 } |
627 if (size != SZ_B) { | 612 if (size != SZ_B) { |
628 opcode |= BIT_SIZE; | 613 opcode |= BIT_SIZE; |
629 } | 614 } |
1919 disp >>= 8; | 1904 disp >>= 8; |
1920 *(out++) = disp; | 1905 *(out++) = disp; |
1921 disp >>= 8; | 1906 disp >>= 8; |
1922 *(out++) = disp; | 1907 *(out++) = disp; |
1923 } else { | 1908 } else { |
1924 fprintf(stderr, "jcc: %p - %p = %lX\n", dest, out + 6, (long)disp); | 1909 fatal_error("jcc: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); |
1925 exit(1); | |
1926 } | 1910 } |
1927 } | 1911 } |
1928 code->cur = out; | 1912 code->cur = out; |
1929 } | 1913 } |
1930 | 1914 |
1946 disp >>= 8; | 1930 disp >>= 8; |
1947 *(out++) = disp; | 1931 *(out++) = disp; |
1948 disp >>= 8; | 1932 disp >>= 8; |
1949 *(out++) = disp; | 1933 *(out++) = disp; |
1950 } else { | 1934 } else { |
1951 fprintf(stderr, "jmp: %p - %p = %lX\n", dest, out + 6, (long)disp); | 1935 fatal_error("jmp: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); |
1952 exit(1); | |
1953 } | 1936 } |
1954 } | 1937 } |
1955 code->cur = out; | 1938 code->cur = out; |
1956 } | 1939 } |
1957 | 1940 |
1995 *(out++) = disp; | 1978 *(out++) = disp; |
1996 disp >>= 8; | 1979 disp >>= 8; |
1997 *(out++) = disp; | 1980 *(out++) = disp; |
1998 } else { | 1981 } else { |
1999 //TODO: Implement far call??? | 1982 //TODO: Implement far call??? |
2000 fprintf(stderr, "%p - %p = %lX\n", fun, out + 5, (long)disp); | 1983 fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp); |
2001 exit(1); | |
2002 } | 1984 } |
2003 code->cur = out; | 1985 code->cur = out; |
2004 } | 1986 } |
2005 | 1987 |
2006 void call_raxfallback(code_info *code, code_ptr fun) | 1988 void call_raxfallback(code_info *code, code_ptr fun) |