--- i386-tdep.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 212 insertions(+), 15 deletions(-) --- a/i386-tdep.c +++ b/i386-tdep.c @@ -3217,6 +3217,7 @@ i386_process_record (struct gdbarch *gdb int rex = 0; uint8_t rex_w = -1; uint8_t rex_r = 0; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); memset (&ir, 0, sizeof (struct i386_record_s)); ir.regcache = regcache; @@ -3226,7 +3227,7 @@ i386_process_record (struct gdbarch *gdb ir.dflag = 1; ir.override = -1; ir.popl_esp_hack = 0; - ir.regmap = gdbarch_tdep (gdbarch)->record_regmap; + ir.regmap = tdep->record_regmap; ir.gdbarch = gdbarch; if (record_debug > 1) @@ -4868,7 +4869,7 @@ reswitch: } ir.addr++; if (tmpu8 != 0x80 - || gdbarch_tdep (gdbarch)->i386_intx80_record == NULL) + || tdep->i386_intx80_record == NULL) { printf_unfiltered (_("Process record doesn't support " "instruction int 0x%02x.\n"), @@ -4876,7 +4877,7 @@ reswitch: ir.addr -= 2; goto no_support; } - ret = gdbarch_tdep (gdbarch)->i386_intx80_record (ir.regcache); + ret = tdep->i386_intx80_record (ir.regcache); if (ret) return ret; } @@ -4973,14 +4974,14 @@ reswitch: ir.addr -= 2; goto no_support; } - if (gdbarch_tdep (gdbarch)->i386_sysenter_record == NULL) + if (tdep->i386_sysenter_record == NULL) { printf_unfiltered (_("Process record doesn't support " "instruction sysenter.\n")); ir.addr -= 2; goto no_support; } - ret = gdbarch_tdep (gdbarch)->i386_sysenter_record (ir.regcache); + ret = tdep->i386_sysenter_record (ir.regcache); if (ret) return ret; } @@ -4998,14 +4999,14 @@ reswitch: case 0x0f05: { int ret; - if (gdbarch_tdep (gdbarch)->i386_syscall_record == NULL) + if (tdep->i386_syscall_record == NULL) { printf_unfiltered (_("Process record doesn't support " "instruction syscall.\n")); ir.addr -= 2; goto no_support; } - ret = gdbarch_tdep (gdbarch)->i386_syscall_record (ir.regcache); + ret = tdep->i386_syscall_record (ir.regcache); if (ret) return ret; } @@ -5349,14 +5350,209 @@ reswitch: I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; - /* MMX/SSE/SSE2/PNI support */ - /* XXX */ + /* MMX 3DNow! SSE SSE2 SSE3 SSSE3 SSE4 */ + /* 3DNow! prefetch */ + case 0x0f0d: + break; + + /* 3DNow! femms */ + case 0x0f0e: + /* emms */ + case 0x0f77: + if (i386_fpc_regnum_p (gdbarch, I387_FTAG_REGNUM(tdep))) + goto no_support; + record_arch_list_add_reg (ir.regcache, I387_FTAG_REGNUM(tdep)); + break; + + /* 3DNow! data */ + case 0x0f0f: + if (i386_record_modrm (&ir)) + return -1; + if (target_read_memory (ir.addr, &tmpu8, 1)) + { + if (record_debug) + printf_unfiltered (_("Process record: error reading memory at " + "addr %s len = 1.\n"), + paddress (gdbarch, ir.addr)); + return -1; + } + ir.addr++; + switch (tmpu8) + { + /* 3DNow! pi2fw */ + case 0x0c: + /* 3DNow! pi2fd */ + case 0x0d: + /* 3DNow! pf2iw */ + case 0x1c: + /* 3DNow! pf2id */ + case 0x1d: + /* 3DNow! pfnacc */ + case 0x8a: + /* 3DNow! pfpnacc */ + case 0x8e: + /* 3DNow! pfcmpge */ + case 0x90: + /* 3DNow! pfmin */ + case 0x94: + /* 3DNow! pfrcp */ + case 0x96: + /* 3DNow! pfrsqrt */ + case 0x97: + /* 3DNow! pfsub */ + case 0x9a: + /* 3DNow! pfadd */ + case 0x9e: + /* 3DNow! pfcmpgt */ + case 0xa0: + /* 3DNow! pfmax */ + case 0xa4: + /* 3DNow! pfrcpit1 */ + case 0xa6: + /* 3DNow! pfrsqit1 */ + case 0xa7: + /* 3DNow! pfsubr */ + case 0xaa: + /* 3DNow! pfacc */ + case 0xae: + /* 3DNow! pfcmpeq */ + case 0xb0: + /* 3DNow! pfmul */ + case 0xb4: + /* 3DNow! pfrcpit2 */ + case 0xb6: + /* 3DNow! pmulhrw */ + case 0xb7: + /* 3DNow! pswapd */ + case 0xbb: + /* 3DNow! pavgusb */ + case 0xbf: + if (i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg)) + goto no_support_3dnow_data; + record_arch_list_add_reg (ir.regcache, ir.reg); + break; + + default: +no_support_3dnow_data: + opcode = (opcode << 8) | tmpu8; + goto no_support; + break; + } + break; + + /* rsm */ + case 0x0faa: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REBX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM); + break; + + case 0x0fae: + if (i386_record_modrm (&ir)) + return -1; + switch(ir.reg) + { + /* fxsave */ + case 0: + { + uint64_t tmpu64; + + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) + return -1; + if (record_arch_list_add_mem (tmpu64, 512)) + return -1; + } + break; + + /* fxrstor */ + case 1: + { + int i; + + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + + for (i = I387_MM0_REGNUM (tdep); + i386_mmx_regnum_p (gdbarch, i); i++) + record_arch_list_add_reg (ir.regcache, i); + + for (i = I387_XMM0_REGNUM (tdep); + i386_sse_regnum_p (gdbarch, i); i++) + record_arch_list_add_reg (ir.regcache, i); + + if (i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep))) + record_arch_list_add_reg (ir.regcache, I387_MXCSR_REGNUM(tdep)); + + for (i = I387_ST0_REGNUM (tdep); + i386_fp_regnum_p (gdbarch, i); i++) + record_arch_list_add_reg (ir.regcache, i); + + for (i = I387_FCTRL_REGNUM (tdep); + i386_fpc_regnum_p (gdbarch, i); i++) + record_arch_list_add_reg (ir.regcache, i); + } + break; + + /* ldmxcsr */ + case 2: + if (i386_mxcsr_regnum_p (gdbarch, I387_MXCSR_REGNUM(tdep))) + goto no_support; + record_arch_list_add_reg (ir.regcache, I387_MXCSR_REGNUM(tdep)); + break; + + /* stmxcsr */ + case 3: + ir.ot = OT_LONG; + if (i386_record_lea_modrm (&ir)) + return -1; + break; + + /* lfence */ + case 5: + /* mfence */ + case 6: + /* sfence clflush */ + case 7: + break; + + default: + opcode = (opcode << 8) | ir.modrm; + goto no_support; + break; + } + break; + + /* popcnt */ + case 0x0fb8: + /* Check if the first byte of this insn is 0xf3. */ + if ((prefixes & (PREFIX_REPZ + | PREFIX_LOCK | PREFIX_REPNZ)) != PREFIX_REPZ) + goto no_support; + if (i386_record_modrm (&ir)) + return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + + /* movnti */ + case 0x0fc3: + ir.ot = (ir.dflag == 2) ? OT_QUAD : OT_LONG; + if (i386_record_modrm (&ir)) + return -1; + if (ir.mod == 3) + goto no_support; + ir.reg |= rex_r; + if (i386_record_lea_modrm (&ir)) + return -1; + break; default: - if (opcode > 0xff) - ir.addr -= 2; - else - ir.addr -= 1; goto no_support; break; } @@ -5370,8 +5566,9 @@ reswitch: no_support: printf_unfiltered (_("Process record doesn't support instruction 0x%02x " - "at address %s.\n"), - (unsigned int) (opcode), paddress (gdbarch, ir.addr)); + "at address %s.\n"), + (unsigned int) (opcode), + paddress (gdbarch, ir.orig_addr)); return -1; }