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 }