comparison gen_x86.c @ 792:724bbec47f86

Use a new fatal_error function instead of calling fprintf and exit for fatal errors. This new function more gracefully handles the case in which BlastEm was not started from a terminal or disconnected from ther terminal (Windows).
author Michael Pavone <pavone@retrodev.com>
date Sat, 25 Jul 2015 18:22:07 -0700
parents 7306b3967c51
children a7774fc2de4b
comparison
equal deleted inserted replaced
791:60686f8d5e48 792:724bbec47f86
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)