diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-i386.c | 83 | ||||
-rw-r--r-- | gas/config/tc-i386.h | 15 |
2 files changed, 98 insertions, 0 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 92540ad..9a3bbbb 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -30,6 +30,7 @@ #include "safe-ctype.h" #include "subsegs.h" #include "dwarf2dbg.h" +#include "dw2gencfi.h" #include "opcode/i386.h" #ifndef REGISTER_WARNINGS @@ -6299,3 +6300,85 @@ intel_putback_token () prev_token.reg = NULL; prev_token.str = NULL; } + +void +tc_x86_cfi_init (void) +{ + struct cfi_config cfi_config; + + if (flag_code == CODE_64BIT) + { + cfi_config.addr_length = 8; + cfi_config.eh_align = 8; + cfi_config.code_align = 1; + cfi_config.data_align = -8; + cfi_config.ra_column = 0x10; + cfi_config.reloc_type = BFD_RELOC_64; + } + else + { + cfi_config.addr_length = 4; + cfi_config.eh_align = 4; + cfi_config.code_align = 1; + cfi_config.data_align = -4; + cfi_config.ra_column = 0x08; + cfi_config.reloc_type = BFD_RELOC_32; + } + + cfi_set_config (&cfi_config); +} + +unsigned long +tc_x86_regname_to_dw2regnum (const char *regname) +{ + unsigned int regnum; + unsigned int regnames_count; + char *regnames_32[] = + { + "eax", "ebx", "ecx", "edx", + "edi", "esi", "ebp", "esp", + "eip" + }; + char *regnames_64[] = + { + "rax", "rbx", "rcx", "rdx", + "rdi", "rsi", "rbp", "rsp", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + "rip" + }; + char **regnames; + + if (flag_code == CODE_64BIT) + { + regnames = regnames_64; + regnames_count = sizeof (regnames_64); + } + else + { + regnames = regnames_32; + regnames_count = sizeof (regnames_32); + } + + for (regnum = 0; regnum < regnames_count; regnum++) + if (strcmp (regname, regnames[regnum]) == 0) + return regnum; + + as_bad (_("unknown register name '%s'"), regname); + return -1; +} + +void +tc_x86_frame_initial_instructions (void) +{ + if (flag_code == CODE_64BIT) + { + cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("rsp"), 8); + cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("rip"), -8); + } + else + { + cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("esp"), 4); + cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("eip"), -4); + } +} diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 45c3acf..aa131ba 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -545,4 +545,19 @@ void i386_print_statistics PARAMS ((FILE *)); extern void sco_id PARAMS ((void)); #endif +/* We want .cfi_* pseudo-ops for generating unwind info. */ +#define TARGET_USE_CFIPOP +#ifdef TARGET_USE_CFIPOP + +#define tc_cfi_init() tc_x86_cfi_init () +extern void tc_x86_cfi_init PARAMS ((void)); + +#define tc_regname_to_dw2regnum tc_x86_regname_to_dw2regnum +extern unsigned long tc_x86_regname_to_dw2regnum PARAMS ((const char *regname)); + +#define tc_cfi_frame_initial_instructions tc_x86_frame_initial_instructions +extern void tc_x86_frame_initial_instructions PARAMS ((void)); + +#endif /* TARGET_USE_CFIPOP */ + #endif /* TC_I386 */ |