Mercurial > repos > blastem
comparison gen_x86.c @ 656:24ccfd70133a
Added 2 new functions to gen_x86.c for handling passing args according to the C abi of the host system and adapted the code in m68k_core_x86.c to use that instead of doing everything by hand
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 01 Jan 2015 19:15:05 -0800 |
parents | 8c7b63f9fab8 |
children | d0943769353b |
comparison
equal
deleted
inserted
replaced
655:38006d43f5a3 | 656:24ccfd70133a |
---|---|
6 #include "gen_x86.h" | 6 #include "gen_x86.h" |
7 #include "mem.h" | 7 #include "mem.h" |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 #include <stdlib.h> | 10 #include <stdlib.h> |
11 #include <stdarg.h> | |
12 #include <string.h> | |
11 | 13 |
12 #define REX_RM_FIELD 0x1 | 14 #define REX_RM_FIELD 0x1 |
13 #define REX_SIB_FIELD 0x2 | 15 #define REX_SIB_FIELD 0x2 |
14 #define REX_REG_FIELD 0x4 | 16 #define REX_REG_FIELD 0x4 |
15 #define REX_QUAD 0x8 | 17 #define REX_QUAD 0x8 |
1951 *(out++) = OP_LOOP; | 1953 *(out++) = OP_LOOP; |
1952 *(out++) = disp; | 1954 *(out++) = disp; |
1953 code->cur = out; | 1955 code->cur = out; |
1954 } | 1956 } |
1955 | 1957 |
1958 uint32_t prep_args(code_info *code, uint32_t num_args, va_list args) | |
1959 { | |
1960 uint8_t *arg_arr = malloc(num_args); | |
1961 for (int i = 0; i < num_args; i ++) | |
1962 { | |
1963 arg_arr[i] = va_arg(args, int); | |
1964 } | |
1965 #ifdef X86_64 | |
1966 uint32_t stack_args = 0; | |
1967 uint8_t abi_regs[] = {RDI, RSI, RDX, RCX, R8, R9}; | |
1968 int8_t reg_swap[R15+1]; | |
1969 uint32_t usage = 0; | |
1970 memset(reg_swap, -1, sizeof(reg_swap)); | |
1971 for (int i = 0; i < num_args; i ++) | |
1972 { | |
1973 usage |= 1 << arg_arr[i]; | |
1974 } | |
1975 for (int i = 0; i < num_args; i ++) | |
1976 { | |
1977 uint8_t reg_arg = arg_arr[i]; | |
1978 if (i < sizeof(abi_regs)) { | |
1979 if (reg_swap[reg_arg] >= 0) { | |
1980 reg_arg = reg_swap[reg_arg]; | |
1981 } | |
1982 if (reg_arg != abi_regs[i]) { | |
1983 if (usage & (1 << abi_regs[i])) { | |
1984 xchg_rr(code, reg_arg, abi_regs[i], SZ_PTR); | |
1985 reg_swap[abi_regs[i]] = reg_arg; | |
1986 } else { | |
1987 mov_rr(code, reg_arg, abi_regs[i], SZ_PTR); | |
1988 } | |
1989 } | |
1990 } else { | |
1991 arg_arr[stack_args++] = reg_arg; | |
1992 } | |
1993 } | |
1994 #else | |
1995 #define stack_args num_args | |
1996 #endif | |
1997 for (int i = stack_args -1; i >= 0; i--) | |
1998 { | |
1999 push_r(code, arg_arr[i]); | |
2000 } | |
2001 | |
2002 return stack_args * sizeof(void *); | |
2003 } | |
2004 | |
2005 void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...) | |
2006 { | |
2007 va_list args; | |
2008 va_start(args, num_args); | |
2009 uint32_t adjust = prep_args(code, num_args, args); | |
2010 va_end(args); | |
2011 call(code, fun); | |
2012 if (adjust) { | |
2013 add_ir(code, adjust, RSP, SZ_PTR); | |
2014 } | |
2015 } | |
2016 | |
2017 void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...) | |
2018 { | |
2019 va_list args; | |
2020 va_start(args, num_args); | |
2021 uint32_t adjust = prep_args(code, num_args, args); | |
2022 va_end(args); | |
2023 #ifdef X86_64 | |
2024 test_ir(code, 8, RSP, SZ_PTR); //check stack alignment | |
2025 code_ptr do_adjust_rsp = code->cur + 1; | |
2026 jcc(code, CC_NZ, code->cur + 2); | |
2027 #endif | |
2028 call(code, fun); | |
2029 if (adjust) { | |
2030 add_ir(code, adjust, RSP, SZ_PTR); | |
2031 } | |
2032 #ifdef X86_64 | |
2033 code_ptr no_adjust_rsp = code->cur + 1; | |
2034 jmp(code, code->cur + 2); | |
2035 *do_adjust_rsp = code->cur - (do_adjust_rsp+1); | |
2036 sub_ir(code, 8, RSP, SZ_PTR); | |
2037 call(code, fun); | |
2038 add_ir(code, adjust + 8 , RSP, SZ_PTR); | |
2039 *no_adjust_rsp = code->cur - (no_adjust_rsp+1); | |
2040 #endif | |
2041 } |