X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmips-tdep.c;h=e0706dba3765352405821e73c34191c6c9fe95af;hb=d441430b752a617fe476e745b95f544fe4463fec;hp=523d11b3b7bbde0215dddd8dbee5c13fdf7745f0;hpb=1bbce132647e6d72aaa065cce5c1d5dd6585c2b2;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 523d11b3b7..e0706dba37 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger. - Copyright (C) 1988-2013 Free Software Foundation, Inc. + Copyright (C) 1988-2015 Free Software Foundation, Inc. Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin. @@ -21,8 +21,6 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" -#include "gdb_assert.h" #include "frame.h" #include "inferior.h" #include "symtab.h" @@ -62,11 +60,21 @@ static const struct objfile_data *mips_pdr_data; static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum); -static int mips32_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR); -static int micromips_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR, - int); -static int mips16_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR, - int); +static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, + ULONGEST inst); +static int micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32); +static int mips16_instruction_has_delay_slot (unsigned short inst, + int mustbe32); + +static int mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, + CORE_ADDR addr); +static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, + CORE_ADDR addr, int mustbe32); +static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, + CORE_ADDR addr, int mustbe32); + +static void mips_print_float_info (struct gdbarch *, struct ui_file *, + struct frame_info *, const char *); /* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */ /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */ @@ -335,6 +343,15 @@ make_compact_addr (CORE_ADDR addr) return ((addr) | (CORE_ADDR) 1); } +/* Extern version of unmake_compact_addr; we use a separate function + so that unmake_compact_addr can be inlined throughout this file. */ + +CORE_ADDR +mips_unmake_compact_addr (CORE_ADDR addr) +{ + return unmake_compact_addr (addr); +} + /* Functions for setting and testing a bit in a minimal symbol that marks it as MIPS16 or microMIPS function. The MSB of the minimal symbol's "info" field is used for this purpose. @@ -364,9 +381,15 @@ mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym) return; if (ELF_ST_IS_MICROMIPS (st_other)) - MSYMBOL_TARGET_FLAG_2 (msym) = 1; + { + MSYMBOL_TARGET_FLAG_MICROMIPS (msym) = 1; + SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1); + } else if (ELF_ST_IS_MIPS16 (st_other)) - MSYMBOL_TARGET_FLAG_1 (msym) = 1; + { + MSYMBOL_TARGET_FLAG_MIPS16 (msym) = 1; + SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1); + } } /* Return one iff MSYM refers to standard ISA code. */ @@ -374,7 +397,8 @@ mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym) static int msymbol_is_mips (struct minimal_symbol *msym) { - return !(MSYMBOL_TARGET_FLAG_1 (msym) | MSYMBOL_TARGET_FLAG_2 (msym)); + return !(MSYMBOL_TARGET_FLAG_MIPS16 (msym) + | MSYMBOL_TARGET_FLAG_MICROMIPS (msym)); } /* Return one iff MSYM refers to MIPS16 code. */ @@ -382,7 +406,7 @@ msymbol_is_mips (struct minimal_symbol *msym) static int msymbol_is_mips16 (struct minimal_symbol *msym) { - return MSYMBOL_TARGET_FLAG_1 (msym); + return MSYMBOL_TARGET_FLAG_MIPS16 (msym); } /* Return one iff MSYM refers to microMIPS code. */ @@ -390,7 +414,36 @@ msymbol_is_mips16 (struct minimal_symbol *msym) static int msymbol_is_micromips (struct minimal_symbol *msym) { - return MSYMBOL_TARGET_FLAG_2 (msym); + return MSYMBOL_TARGET_FLAG_MICROMIPS (msym); +} + +/* Set the ISA bit in the main symbol too, complementing the corresponding + minimal symbol setting and reflecting the run-time value of the symbol. + The need for comes from the ISA bit having been cleared as code in + `_bfd_mips_elf_symbol_processing' separated it into the ELF symbol's + `st_other' STO_MIPS16 or STO_MICROMIPS annotation, making the values + of symbols referring to compressed code different in GDB to the values + used by actual code. That in turn makes them evaluate incorrectly in + expressions, producing results different to what the same expressions + yield when compiled into the program being debugged. */ + +static void +mips_make_symbol_special (struct symbol *sym, struct objfile *objfile) +{ + if (SYMBOL_CLASS (sym) == LOC_BLOCK) + { + /* We are in symbol reading so it is OK to cast away constness. */ + struct block *block = (struct block *) SYMBOL_BLOCK_VALUE (sym); + CORE_ADDR compact_block_start; + struct bound_minimal_symbol msym; + + compact_block_start = BLOCK_START (block) | 1; + msym = lookup_minimal_symbol_by_pc (compact_block_start); + if (msym.minsym && !msymbol_is_mips (msym.minsym)) + { + BLOCK_START (block) = compact_block_start; + } + } } /* XFER a value from the big/little/left end of the register. @@ -1127,7 +1180,7 @@ mips_pc_is_mips (CORE_ADDR memaddr) stored by elfread.c in the high bit of the info field. Use this to decide if the function is standard MIPS. Otherwise if bit 0 of the address is clear, then this is a standard MIPS function. */ - sym = lookup_minimal_symbol_by_pc (memaddr); + sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr)); if (sym.minsym) return msymbol_is_mips (sym.minsym); else @@ -1145,7 +1198,7 @@ mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr) elfread.c in the high bit of the info field. Use this to decide if the function is MIPS16. Otherwise if bit 0 of the address is set, then ELF file flags will tell if this is a MIPS16 function. */ - sym = lookup_minimal_symbol_by_pc (memaddr); + sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr)); if (sym.minsym) return msymbol_is_mips16 (sym.minsym); else @@ -1164,7 +1217,7 @@ mips_pc_is_micromips (struct gdbarch *gdbarch, CORE_ADDR memaddr) if the function is microMIPS. Otherwise if bit 0 of the address is set, then ELF file flags will tell if this is a microMIPS function. */ - sym = lookup_minimal_symbol_by_pc (memaddr); + sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr)); if (sym.minsym) return msymbol_is_micromips (sym.minsym); else @@ -1184,7 +1237,7 @@ mips_pc_isa (struct gdbarch *gdbarch, CORE_ADDR memaddr) this to decide if the function is MIPS16 or microMIPS or normal MIPS. Otherwise if bit 0 of the address is set, then ELF file flags will tell if this is a MIPS16 or a microMIPS function. */ - sym = lookup_minimal_symbol_by_pc (memaddr); + sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr)); if (sym.minsym) { if (msymbol_is_micromips (sym.minsym)) @@ -1205,6 +1258,67 @@ mips_pc_isa (struct gdbarch *gdbarch, CORE_ADDR memaddr) } } +/* Set the ISA bit correctly in the PC, used by DWARF-2 machinery. + The need for comes from the ISA bit having been cleared, making + addresses in FDE, range records, etc. referring to compressed code + different to those in line information, the symbol table and finally + the PC register. That in turn confuses many operations. */ + +static CORE_ADDR +mips_adjust_dwarf2_addr (CORE_ADDR pc) +{ + pc = unmake_compact_addr (pc); + return mips_pc_is_mips (pc) ? pc : make_compact_addr (pc); +} + +/* Recalculate the line record requested so that the resulting PC has + the ISA bit set correctly, used by DWARF-2 machinery. The need for + this adjustment comes from some records associated with compressed + code having the ISA bit cleared, most notably at function prologue + ends. The ISA bit is in this context retrieved from the minimal + symbol covering the address requested, which in turn has been + constructed from the binary's symbol table rather than DWARF-2 + information. The correct setting of the ISA bit is required for + breakpoint addresses to correctly match against the stop PC. + + As line entries can specify relative address adjustments we need to + keep track of the absolute value of the last line address recorded + in line information, so that we can calculate the actual address to + apply the ISA bit adjustment to. We use PC for this tracking and + keep the original address there. + + As such relative address adjustments can be odd within compressed + code we need to keep track of the last line address with the ISA + bit adjustment applied too, as the original address may or may not + have had the ISA bit set. We use ADJ_PC for this tracking and keep + the adjusted address there. + + For relative address adjustments we then use these variables to + calculate the address intended by line information, which will be + PC-relative, and return an updated adjustment carrying ISA bit + information, which will be ADJ_PC-relative. For absolute address + adjustments we just return the same address that we store in ADJ_PC + too. + + As the first line entry can be relative to an implied address value + of 0 we need to have the initial address set up that we store in PC + and ADJ_PC. This is arranged with a call from `dwarf_decode_lines_1' + that sets PC to 0 and ADJ_PC accordingly, usually 0 as well. */ + +static CORE_ADDR +mips_adjust_dwarf2_line (CORE_ADDR addr, int rel) +{ + static CORE_ADDR adj_pc; + static CORE_ADDR pc; + CORE_ADDR isa_pc; + + pc = rel ? pc + addr : addr; + isa_pc = mips_adjust_dwarf2_addr (pc); + addr = rel ? isa_pc - adj_pc : isa_pc; + adj_pc = isa_pc; + return addr; +} + /* Various MIPS16 thunk (aka stub or trampoline) names. */ static const char mips_str_mips16_call_stub[] = "__mips16_call_stub_"; @@ -1231,14 +1345,13 @@ mips_in_frame_stub (CORE_ADDR pc) return 0; /* If the PC is in __mips16_call_stub_*, this is a call/return stub. */ - if (strncmp (name, mips_str_mips16_call_stub, - strlen (mips_str_mips16_call_stub)) == 0) + if (startswith (name, mips_str_mips16_call_stub)) return 1; /* If the PC is in __call_stub_*, this is a call/return or a call stub. */ - if (strncmp (name, mips_str_call_stub, strlen (mips_str_call_stub)) == 0) + if (startswith (name, mips_str_call_stub)) return 1; /* If the PC is in __fn_stub_*, this is a call stub. */ - if (strncmp (name, mips_str_fn_stub, strlen (mips_str_fn_stub)) == 0) + if (startswith (name, mips_str_fn_stub)) return 1; return 0; /* Not a stub. */ @@ -1254,8 +1367,6 @@ mips_read_pc (struct regcache *regcache) LONGEST pc; regcache_cooked_read_signed (regcache, regnum, &pc); - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); return pc; } @@ -1265,8 +1376,6 @@ mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) CORE_ADDR pc; pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch)); - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); /* macro/2012-04-20: This hack skips over MIPS16 call thunks as intermediate frames. In this case we can get the caller's address from $ra, or if $ra contains an address within a thunk as well, then @@ -1276,15 +1385,9 @@ mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { pc = frame_unwind_register_signed (next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM); - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); if (mips_in_frame_stub (pc)) - { - pc = frame_unwind_register_signed - (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM); - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); - } + pc = frame_unwind_register_signed + (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM); } return pc; } @@ -1318,10 +1421,7 @@ mips_write_pc (struct regcache *regcache, CORE_ADDR pc) { int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache)); - if (mips_pc_is_mips (pc)) - regcache_cooked_write_unsigned (regcache, regnum, pc); - else - regcache_cooked_write_unsigned (regcache, regnum, make_compact_addr (pc)); + regcache_cooked_write_unsigned (regcache, regnum, pc); } /* Fetch and return instruction from the specified location. Handle @@ -2042,7 +2142,8 @@ fetch_mips_16 (struct gdbarch *gdbarch, CORE_ADDR pc) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte buf[8]; - pc &= 0xfffffffe; /* Clear the low order bit. */ + + pc = unmake_compact_addr (pc); /* Clear the low order bit. */ target_read_memory (pc, buf, 2); return extract_unsigned_integer (buf, 2, byte_order); } @@ -2120,10 +2221,13 @@ unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc, } +/* Calculate the destination of a branch whose 16-bit opcode word is at PC, + and having a signed 16-bit OFFSET. */ + static CORE_ADDR add_offset_16 (CORE_ADDR pc, int offset) { - return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff))); + return pc + (offset << 1) + 2; } static CORE_ADDR @@ -2138,7 +2242,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc, { struct upk_mips16 upk; unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk); - pc += (upk.offset << 1) + 2; + pc = add_offset_16 (pc, upk.offset); break; } case 3: /* JAL , JALX - Watch out, these are 32 bit @@ -2146,7 +2250,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc, { struct upk_mips16 upk; unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk); - pc = add_offset_16 (pc, upk.offset); + pc = ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)) | (upk.offset << 2); if ((insn >> 10) & 0x01) /* Exchange mode */ pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode. */ else @@ -2160,7 +2264,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc, unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk); reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]); if (reg == 0) - pc += (upk.offset << 1) + 2; + pc = add_offset_16 (pc, upk.offset); else pc += 2; break; @@ -2172,7 +2276,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc, unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk); reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]); if (reg != 0) - pc += (upk.offset << 1) + 2; + pc = add_offset_16 (pc, upk.offset); else pc += 2; break; @@ -2186,8 +2290,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc, reg = get_frame_register_signed (frame, 24); /* Test register is 24 */ if (((upk.regx == 0) && (reg == 0)) /* BTEZ */ || ((upk.regx == 1) && (reg != 0))) /* BTNEZ */ - /* pc = add_offset_16(pc,upk.offset) ; */ - pc += (upk.offset << 1) + 2; + pc = add_offset_16 (pc, upk.offset); else pc += 2; break; @@ -2242,7 +2345,7 @@ mips16_next_pc (struct frame_info *frame, CORE_ADDR pc) /* The mips_next_pc function supports single_step when the remote target monitor or stub is not developed enough to do a single_step. It works by decoding the current instruction and predicting where a - branch will go. This isnt hard because all the data is available. + branch will go. This isn't hard because all the data is available. The MIPS32, MIPS16 and microMIPS variants are quite different. */ static CORE_ADDR mips_next_pc (struct frame_info *frame, CORE_ADDR pc) @@ -2257,6 +2360,48 @@ mips_next_pc (struct frame_info *frame, CORE_ADDR pc) return mips32_next_pc (frame, pc); } +/* Return non-zero if the MIPS16 instruction INSN is a compact branch + or jump. */ + +static int +mips16_instruction_is_compact_branch (unsigned short insn) +{ + switch (insn & 0xf800) + { + case 0xe800: + return (insn & 0x009f) == 0x80; /* JALRC/JRC */ + case 0x6000: + return (insn & 0x0600) == 0; /* BTNEZ/BTEQZ */ + case 0x2800: /* BNEZ */ + case 0x2000: /* BEQZ */ + case 0x1000: /* B */ + return 1; + default: + return 0; + } +} + +/* Return non-zero if the microMIPS instruction INSN is a compact branch + or jump. */ + +static int +micromips_instruction_is_compact_branch (unsigned short insn) +{ + switch (micromips_op (insn)) + { + case 0x11: /* POOL16C: bits 010001 */ + return (b5s5_op (insn) == 0x18 + /* JRADDIUSP: bits 010001 11000 */ + || b5s5_op (insn) == 0xd); + /* JRC: bits 010011 01101 */ + case 0x10: /* POOL32I: bits 010000 */ + return (b5s5_op (insn) & 0x1d) == 0x5; + /* BEQZC/BNEZC: bits 010000 001x1 */ + default: + return 0; + } +} + struct mips_frame_cache { CORE_ADDR base; @@ -2334,6 +2479,10 @@ mips16_scan_prologue (struct gdbarch *gdbarch, struct frame_info *this_frame, struct mips_frame_cache *this_cache) { + int prev_non_prologue_insn = 0; + int this_non_prologue_insn; + int non_prologue_insns = 0; + CORE_ADDR prev_pc; CORE_ADDR cur_pc; CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer. */ CORE_ADDR sp; @@ -2344,11 +2493,13 @@ mips16_scan_prologue (struct gdbarch *gdbarch, unsigned inst = 0; /* current instruction */ unsigned entry_inst = 0; /* the entry instruction */ unsigned save_inst = 0; /* the save instruction */ + int prev_delay_slot = 0; + int in_delay_slot; int reg, offset; int extend_bytes = 0; - int prev_extend_bytes; - CORE_ADDR end_prologue_addr = 0; + int prev_extend_bytes = 0; + CORE_ADDR end_prologue_addr; /* Can be called when there's no process, and hence when there's no THIS_FRAME. */ @@ -2361,9 +2512,16 @@ mips16_scan_prologue (struct gdbarch *gdbarch, if (limit_pc > start_pc + 200) limit_pc = start_pc + 200; + prev_pc = start_pc; + /* Permit at most one non-prologue non-control-transfer instruction + in the middle which may have been reordered by the compiler for + optimisation. */ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE) { + this_non_prologue_insn = 0; + in_delay_slot = 0; + /* Save the previous instruction. If it's an EXTEND, we'll extract the immediate offset extension from it in mips16_get_imm. */ prev_inst = inst; @@ -2453,21 +2611,40 @@ mips16_scan_prologue (struct gdbarch *gdbarch, if (prev_extend_bytes) /* extend */ save_inst |= prev_inst << 16; } - else if ((inst & 0xf800) == 0x1800) /* jal(x) */ - cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */ else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */ { /* This instruction is part of the prologue, but we don't need to do anything special to handle it. */ } + else if (mips16_instruction_has_delay_slot (inst, 0)) + /* JAL/JALR/JALX/JR */ + { + /* The instruction in the delay slot can be a part + of the prologue, so move forward once more. */ + in_delay_slot = 1; + if (mips16_instruction_has_delay_slot (inst, 1)) + /* JAL/JALX */ + { + prev_extend_bytes = MIPS_INSN16_SIZE; + cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */ + } + } else { - /* This instruction is not an instruction typically found - in a prologue, so we must have reached the end of the - prologue. */ - if (end_prologue_addr == 0) - end_prologue_addr = cur_pc - prev_extend_bytes; + this_non_prologue_insn = 1; } + + non_prologue_insns += this_non_prologue_insn; + + /* A jump or branch, or enough non-prologue insns seen? If so, + then we must have reached the end of the prologue by now. */ + if (prev_delay_slot || non_prologue_insns > 1 + || mips16_instruction_is_compact_branch (inst)) + break; + + prev_non_prologue_insn = this_non_prologue_insn; + prev_delay_slot = in_delay_slot; + prev_pc = cur_pc - prev_extend_bytes; } /* The entry instruction is typically the first instruction in a function, @@ -2620,11 +2797,12 @@ mips16_scan_prologue (struct gdbarch *gdbarch, = this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM]; } - /* If we didn't reach the end of the prologue when scanning the function - instructions, then set end_prologue_addr to the address of the - instruction immediately after the last one we scanned. */ - if (end_prologue_addr == 0) - end_prologue_addr = cur_pc; + /* Set end_prologue_addr to the address of the instruction immediately + after the last one we scanned. Unless the last one looked like a + non-prologue instruction (and we looked ahead), in which case use + its address instead. */ + end_prologue_addr = (prev_non_prologue_insn || prev_delay_slot + ? prev_pc : cur_pc - prev_extend_bytes); return end_prologue_addr; } @@ -2761,7 +2939,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch, struct frame_info *this_frame, struct mips_frame_cache *this_cache) { - CORE_ADDR end_prologue_addr = 0; + CORE_ADDR end_prologue_addr; int prev_non_prologue_insn = 0; int frame_reg = MIPS_SP_REGNUM; int this_non_prologue_insn; @@ -2769,6 +2947,8 @@ micromips_scan_prologue (struct gdbarch *gdbarch, long frame_offset = 0; /* Size of stack frame. */ long frame_adjust = 0; /* Offset of FP from SP. */ CORE_ADDR frame_addr = 0; /* Value of $30, used as frame pointer. */ + int prev_delay_slot = 0; + int in_delay_slot; CORE_ADDR prev_pc; CORE_ADDR cur_pc; ULONGEST insn; /* current instruction */ @@ -2805,6 +2985,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch, for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += loc) { this_non_prologue_insn = 0; + in_delay_slot = 0; sp_adj = 0; loc = 0; insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, cur_pc, NULL); @@ -2911,7 +3092,7 @@ micromips_scan_prologue (struct gdbarch *gdbarch, break; /* LUI $v1 is used for larger $sp adjustments. */ - /* Discard LUI $gp is used for PIC code. */ + /* Discard LUI $gp used for PIC code. */ case 0x10: /* POOL32I: bits 010000 */ if (b5s5_op (insn >> 16) == 0xd /* LUI: bits 010000 001101 */ @@ -2957,9 +3138,15 @@ micromips_scan_prologue (struct gdbarch *gdbarch, break; default: - this_non_prologue_insn = 1; + /* The instruction in the delay slot can be a part + of the prologue, so move forward once more. */ + if (micromips_instruction_has_delay_slot (insn, 0)) + in_delay_slot = 1; + else + this_non_prologue_insn = 1; break; } + insn >>= 16; break; /* 16-bit instructions. */ @@ -3014,7 +3201,12 @@ micromips_scan_prologue (struct gdbarch *gdbarch, break; default: - this_non_prologue_insn = 1; + /* The instruction in the delay slot can be a part + of the prologue, so move forward once more. */ + if (micromips_instruction_has_delay_slot (insn << 16, 0)) + in_delay_slot = 1; + else + this_non_prologue_insn = 1; break; } break; @@ -3023,13 +3215,16 @@ micromips_scan_prologue (struct gdbarch *gdbarch, frame_offset -= sp_adj; non_prologue_insns += this_non_prologue_insn; - /* Enough non-prologue insns seen or positive stack adjustment? */ - if (end_prologue_addr == 0 && (non_prologue_insns > 1 || sp_adj > 0)) - { - end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc; - break; - } + + /* A jump or branch, enough non-prologue insns seen or positive + stack adjustment? If so, then we must have reached the end + of the prologue by now. */ + if (prev_delay_slot || non_prologue_insns > 1 || sp_adj > 0 + || micromips_instruction_is_compact_branch (insn)) + break; + prev_non_prologue_insn = this_non_prologue_insn; + prev_delay_slot = in_delay_slot; prev_pc = cur_pc; } @@ -3047,13 +3242,12 @@ micromips_scan_prologue (struct gdbarch *gdbarch, = this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM]; } - /* If we didn't reach the end of the prologue when scanning the function - instructions, then set end_prologue_addr to the address of the - instruction immediately after the last one we scanned. Unless the - last one looked like a non-prologue instruction (and we looked ahead), - in which case use its address instead. */ - if (end_prologue_addr == 0) - end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc; + /* Set end_prologue_addr to the address of the instruction immediately + after the last one we scanned. Unless the last one looked like a + non-prologue instruction (and we looked ahead), in which case use + its address instead. */ + end_prologue_addr + = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc; return end_prologue_addr; } @@ -3201,17 +3395,22 @@ mips32_scan_prologue (struct gdbarch *gdbarch, struct frame_info *this_frame, struct mips_frame_cache *this_cache) { - CORE_ADDR cur_pc; + int prev_non_prologue_insn; + int this_non_prologue_insn; + int non_prologue_insns; CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer. */ + int prev_delay_slot; + CORE_ADDR prev_pc; + CORE_ADDR cur_pc; CORE_ADDR sp; long frame_offset; int frame_reg = MIPS_SP_REGNUM; - CORE_ADDR end_prologue_addr = 0; + CORE_ADDR end_prologue_addr; int seen_sp_adjust = 0; int load_immediate_bytes = 0; - int in_delay_slot = 0; + int in_delay_slot; int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8); /* Can be called when there's no process, and hence when there's no @@ -3227,28 +3426,39 @@ mips32_scan_prologue (struct gdbarch *gdbarch, limit_pc = start_pc + 200; restart: + prev_non_prologue_insn = 0; + non_prologue_insns = 0; + prev_delay_slot = 0; + prev_pc = start_pc; + /* Permit at most one non-prologue non-control-transfer instruction + in the middle which may have been reordered by the compiler for + optimisation. */ frame_offset = 0; for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE) { - unsigned long inst, high_word, low_word; + unsigned long inst, high_word; + long offset; int reg; + this_non_prologue_insn = 0; + in_delay_slot = 0; + /* Fetch the instruction. */ inst = (unsigned long) mips_fetch_instruction (gdbarch, ISA_MIPS, cur_pc, NULL); /* Save some code by pre-extracting some useful fields. */ high_word = (inst >> 16) & 0xffff; - low_word = inst & 0xffff; + offset = ((inst & 0xffff) ^ 0x8000) - 0x8000; reg = high_word & 0x1f; if (high_word == 0x27bd /* addiu $sp,$sp,-i */ || high_word == 0x23bd /* addi $sp,$sp,-i */ || high_word == 0x67bd) /* daddiu $sp,$sp,-i */ { - if (low_word & 0x8000) /* Negative stack adjustment? */ - frame_offset += 0x10000 - low_word; + if (offset < 0) /* Negative stack adjustment? */ + frame_offset -= offset; else /* Exit loop if a positive stack adjustment is found, which usually means that the stack cleanup code in the function @@ -3259,19 +3469,19 @@ restart: else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */ && !regsize_is_64_bits) { - set_reg_offset (gdbarch, this_cache, reg, sp + low_word); + set_reg_offset (gdbarch, this_cache, reg, sp + offset); } else if (((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */ && regsize_is_64_bits) { /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */ - set_reg_offset (gdbarch, this_cache, reg, sp + low_word); + set_reg_offset (gdbarch, this_cache, reg, sp + offset); } else if (high_word == 0x27be) /* addiu $30,$sp,size */ { /* Old gcc frame, r30 is virtual frame pointer. */ - if ((long) low_word != frame_offset) - frame_addr = sp + low_word; + if (offset != frame_offset) + frame_addr = sp + offset; else if (this_frame && frame_reg == MIPS_SP_REGNUM) { unsigned alloca_adjust; @@ -3281,7 +3491,7 @@ restart: (this_frame, gdbarch_num_regs (gdbarch) + 30); frame_offset = 0; - alloca_adjust = (unsigned) (frame_addr - (sp + low_word)); + alloca_adjust = (unsigned) (frame_addr - (sp + offset)); if (alloca_adjust > 0) { /* FP > SP + frame_size. This may be because of @@ -3330,7 +3540,7 @@ restart: else if ((high_word & 0xFFE0) == 0xafc0 /* sw reg,offset($30) */ && !regsize_is_64_bits) { - set_reg_offset (gdbarch, this_cache, reg, frame_addr + low_word); + set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset); } else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */ || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */ @@ -3350,6 +3560,7 @@ restart: initialize a local variable, so we accept them only before a stack adjustment instruction was seen. */ else if (!seen_sp_adjust + && !prev_delay_slot && (high_word == 0x3c01 /* lui $at,n */ || high_word == 0x3c08 /* lui $t0,n */ || high_word == 0x3421 /* ori $at,$at,n */ @@ -3358,31 +3569,32 @@ restart: || high_word == 0x3408 /* ori $t0,$zero,n */ )) { - if (end_prologue_addr == 0) - load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */ + load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */ } + /* Check for branches and jumps. The instruction in the delay + slot can be a part of the prologue, so move forward once more. */ + else if (mips32_instruction_has_delay_slot (gdbarch, inst)) + { + in_delay_slot = 1; + } + /* This instruction is not an instruction typically found + in a prologue, so we must have reached the end of the + prologue. */ else { - /* This instruction is not an instruction typically found - in a prologue, so we must have reached the end of the - prologue. */ - /* FIXME: brobecker/2004-10-10: Can't we just break out of this - loop now? Why would we need to continue scanning the function - instructions? */ - if (end_prologue_addr == 0) - end_prologue_addr = cur_pc; - - /* Check for branches and jumps. For now, only jump to - register are caught (i.e. returns). */ - if ((itype_op (inst) & 0x07) == 0 && rtype_funct (inst) == 8) - in_delay_slot = 1; + this_non_prologue_insn = 1; } - /* If the previous instruction was a jump, we must have reached - the end of the prologue by now. Stop scanning so that we do - not go past the function return. */ - if (in_delay_slot) + non_prologue_insns += this_non_prologue_insn; + + /* A jump or branch, or enough non-prologue insns seen? If so, + then we must have reached the end of the prologue by now. */ + if (prev_delay_slot || non_prologue_insns > 1) break; + + prev_non_prologue_insn = this_non_prologue_insn; + prev_delay_slot = in_delay_slot; + prev_pc = cur_pc; } if (this_cache != NULL) @@ -3400,14 +3612,12 @@ restart: + MIPS_RA_REGNUM]; } - /* If we didn't reach the end of the prologue when scanning the function - instructions, then set end_prologue_addr to the address of the - instruction immediately after the last one we scanned. */ - /* brobecker/2004-10-10: I don't think this would ever happen, but - we may as well be careful and do our best if we have a null - end_prologue_addr. */ - if (end_prologue_addr == 0) - end_prologue_addr = cur_pc; + /* Set end_prologue_addr to the address of the instruction immediately + after the last one we scanned. Unless the last one looked like a + non-prologue instruction (and we looked ahead), in which case use + its address instead. */ + end_prologue_addr + = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc; /* In a frameless function, we might have incorrectly skipped some load immediate instructions. Undo the skipping @@ -3601,8 +3811,8 @@ mips_stub_frame_sniffer (const struct frame_unwind *self, stub. The stub for foo is named ".pic.foo". */ msym = lookup_minimal_symbol_by_pc (pc); if (msym.minsym != NULL - && SYMBOL_LINKAGE_NAME (msym.minsym) != NULL - && strncmp (SYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) == 0) + && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL + && startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic.")) return 1; return 0; @@ -3651,9 +3861,6 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (is_compact_addr (addr)) - addr = unmake_compact_addr (addr); - if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL)) /* This hack is a work-around for existing boards using PMON, the simulator, and any other 64-bit targets that doesn't have true @@ -3942,7 +4149,7 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch, /* Effectively inserts the breakpoints. */ for (index = 0; index <= last_breakpoint; index++) - insert_single_step_breakpoint (gdbarch, aspace, breaks[index]); + insert_single_step_breakpoint (gdbarch, aspace, breaks[index]); return 1; } @@ -4352,25 +4559,9 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, "mips_eabi_push_dummy_call: %d len=%d type=%d", argnum + 1, len, (int) typecode); - /* Function pointer arguments to mips16 code need to be made into - mips16 pointers. */ - if (typecode == TYPE_CODE_PTR - && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC) - { - CORE_ADDR addr = extract_signed_integer (value_contents (arg), - len, byte_order); - if (mips_pc_is_mips (addr)) - val = value_contents (arg); - else - { - store_signed_integer (valbuf, len, byte_order, - make_compact_addr (addr)); - val = valbuf; - } - } /* The EABI passes structures that do not fit in a register by reference. */ - else if (len > regsize + if (len > regsize && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) { store_unsigned_integer (valbuf, regsize, byte_order, @@ -5735,7 +5926,6 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, for (argnum = 0; argnum < nargs; argnum++) { const gdb_byte *val; - gdb_byte valbuf[MAX_REGISTER_SIZE]; struct value *arg = args[argnum]; struct type *arg_type = check_typedef (value_type (arg)); int len = TYPE_LENGTH (arg_type); @@ -5748,21 +5938,6 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, val = value_contents (arg); - /* Function pointer arguments to mips16 code need to be made into - mips16 pointers. */ - if (typecode == TYPE_CODE_PTR - && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC) - { - CORE_ADDR addr = extract_signed_integer (value_contents (arg), - len, byte_order); - if (!mips_pc_is_mips (addr)) - { - store_signed_integer (valbuf, len, byte_order, - make_compact_addr (addr)); - val = valbuf; - } - } - /* Floating point arguments passed in registers have to be treated specially. On 32-bit architectures, doubles are passed in register pairs; the even FP register gets the @@ -6195,12 +6370,6 @@ mips_print_register (struct ui_file *file, struct frame_info *frame, } val = get_frame_register_value (frame, regnum); - if (value_optimized_out (val)) - { - fprintf_filtered (file, "%s: [Invalid]", - gdbarch_register_name (gdbarch, regnum)); - return; - } fputs_filtered (gdbarch_register_name (gdbarch, regnum), file); @@ -6221,6 +6390,94 @@ mips_print_register (struct ui_file *file, struct frame_info *frame, &opts, 0, file); } +/* Print IEEE exception condition bits in FLAGS. */ + +static void +print_fpu_flags (struct ui_file *file, int flags) +{ + if (flags & (1 << 0)) + fputs_filtered (" inexact", file); + if (flags & (1 << 1)) + fputs_filtered (" uflow", file); + if (flags & (1 << 2)) + fputs_filtered (" oflow", file); + if (flags & (1 << 3)) + fputs_filtered (" div0", file); + if (flags & (1 << 4)) + fputs_filtered (" inval", file); + if (flags & (1 << 5)) + fputs_filtered (" unimp", file); + fputc_filtered ('\n', file); +} + +/* Print interesting information about the floating point processor + (if present) or emulator. */ + +static void +mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, + struct frame_info *frame, const char *args) +{ + int fcsr = mips_regnum (gdbarch)->fp_control_status; + enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch); + ULONGEST fcs = 0; + int i; + + if (fcsr == -1 || !read_frame_register_unsigned (frame, fcsr, &fcs)) + type = MIPS_FPU_NONE; + + fprintf_filtered (file, "fpu type: %s\n", + type == MIPS_FPU_DOUBLE ? "double-precision" + : type == MIPS_FPU_SINGLE ? "single-precision" + : "none / unused"); + + if (type == MIPS_FPU_NONE) + return; + + fprintf_filtered (file, "reg size: %d bits\n", + register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8); + + fputs_filtered ("cond :", file); + if (fcs & (1 << 23)) + fputs_filtered (" 0", file); + for (i = 1; i <= 7; i++) + if (fcs & (1 << (24 + i))) + fprintf_filtered (file, " %d", i); + fputc_filtered ('\n', file); + + fputs_filtered ("cause :", file); + print_fpu_flags (file, (fcs >> 12) & 0x3f); + fputs ("mask :", stdout); + print_fpu_flags (file, (fcs >> 7) & 0x1f); + fputs ("flags :", stdout); + print_fpu_flags (file, (fcs >> 2) & 0x1f); + + fputs_filtered ("rounding: ", file); + switch (fcs & 3) + { + case 0: fputs_filtered ("nearest\n", file); break; + case 1: fputs_filtered ("zero\n", file); break; + case 2: fputs_filtered ("+inf\n", file); break; + case 3: fputs_filtered ("-inf\n", file); break; + } + + fputs_filtered ("flush :", file); + if (fcs & (1 << 21)) + fputs_filtered (" nearest", file); + if (fcs & (1 << 22)) + fputs_filtered (" override", file); + if (fcs & (1 << 24)) + fputs_filtered (" zero", file); + if ((fcs & (0xb << 21)) == 0) + fputs_filtered (" no", file); + fputc_filtered ('\n', file); + + fprintf_filtered (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no"); + fprintf_filtered (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no"); + fputc_filtered ('\n', file); + + default_print_float_info (gdbarch, file, frame, args); +} + /* Replacement for generic do_registers_info. Print regs in pretty columns. */ @@ -6377,11 +6634,11 @@ mips_single_step_through_delay (struct gdbarch *gdbarch, int size; if ((mips_pc_is_mips (pc) - && !mips32_instruction_has_delay_slot (gdbarch, pc)) + && !mips32_insn_at_pc_has_delay_slot (gdbarch, pc)) || (mips_pc_is_micromips (gdbarch, pc) - && !micromips_instruction_has_delay_slot (gdbarch, pc, 0)) + && !micromips_insn_at_pc_has_delay_slot (gdbarch, pc, 0)) || (mips_pc_is_mips16 (gdbarch, pc) - && !mips16_instruction_has_delay_slot (gdbarch, pc, 0))) + && !mips16_insn_at_pc_has_delay_slot (gdbarch, pc, 0))) return 0; isa = mips_pc_isa (gdbarch, pc); @@ -6436,10 +6693,11 @@ mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) return mips32_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL); } -/* Check whether the PC is in a function epilogue (32-bit version). - This is a helper function for mips_in_function_epilogue_p. */ +/* Implement the stack_frame_destroyed_p gdbarch method (32-bit version). + This is a helper function for mips_stack_frame_destroyed_p. */ + static int -mips32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0, func_end = 0; @@ -6474,11 +6732,11 @@ mips32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } -/* Check whether the PC is in a function epilogue (microMIPS version). - This is a helper function for mips_in_function_epilogue_p. */ +/* Implement the stack_frame_destroyed_p gdbarch method (microMIPS version). + This is a helper function for mips_stack_frame_destroyed_p. */ static int -micromips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +micromips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0; CORE_ADDR func_end = 0; @@ -6575,10 +6833,11 @@ micromips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 1; } -/* Check whether the PC is in a function epilogue (16-bit version). - This is a helper function for mips_in_function_epilogue_p. */ +/* Implement the stack_frame_destroyed_p gdbarch method (16-bit version). + This is a helper function for mips_stack_frame_destroyed_p. */ + static int -mips16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +mips16_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR func_addr = 0, func_end = 0; @@ -6615,17 +6874,20 @@ mips16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } -/* The epilogue is defined here as the area at the end of a function, +/* Implement the stack_frame_destroyed_p gdbarch method. + + The epilogue is defined here as the area at the end of a function, after an instruction which destroys the function's stack frame. */ + static int -mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +mips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) { if (mips_pc_is_mips16 (gdbarch, pc)) - return mips16_in_function_epilogue_p (gdbarch, pc); + return mips16_stack_frame_destroyed_p (gdbarch, pc); else if (mips_pc_is_micromips (gdbarch, pc)) - return micromips_in_function_epilogue_p (gdbarch, pc); + return micromips_stack_frame_destroyed_p (gdbarch, pc); else - return mips32_in_function_epilogue_p (gdbarch, pc); + return mips32_stack_frame_destroyed_p (gdbarch, pc); } /* Root of all "set mips "/"show mips " commands. This will eventually be @@ -6971,23 +7233,17 @@ mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, *kindptr = 4; } -/* Return non-zero if the ADDR instruction has a branch delay slot - (i.e. it is a jump or branch instruction). This function is based - on mips32_next_pc. */ +/* Return non-zero if the standard MIPS instruction INST has a branch + delay slot (i.e. it is a jump or branch instruction). This function + is based on mips32_next_pc. */ static int -mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr) +mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst) { - unsigned long inst; - int status; int op; int rs; int rt; - inst = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status); - if (status) - return 0; - op = itype_op (inst); if ((inst & 0xe0000000) != 0) { @@ -7027,93 +7283,139 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr) } } -/* Return non-zero if the ADDR instruction, which must be a 32-bit - instruction if MUSTBE32 is set or can be any instruction otherwise, - has a branch delay slot (i.e. it is a non-compact jump instruction). */ +/* Return non-zero if a standard MIPS instruction at ADDR has a branch + delay slot (i.e. it is a jump or branch instruction). */ static int -micromips_instruction_has_delay_slot (struct gdbarch *gdbarch, - CORE_ADDR addr, int mustbe32) +mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr) { ULONGEST insn; int status; - insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); + insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status); if (status) return 0; - if (!mustbe32) /* 16-bit instructions. */ - return (micromips_op (insn) == 0x11 - /* POOL16C: bits 010001 */ - && (b5s5_op (insn) == 0xc + return mips32_instruction_has_delay_slot (gdbarch, insn); +} + +/* Return non-zero if the microMIPS instruction INSN, comprising the + 16-bit major opcode word in the high 16 bits and any second word + in the low 16 bits, has a branch delay slot (i.e. it is a non-compact + jump or branch instruction). The instruction must be 32-bit if + MUSTBE32 is set or can be any instruction otherwise. */ + +static int +micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32) +{ + ULONGEST major = insn >> 16; + + switch (micromips_op (major)) + { + /* 16-bit instructions. */ + case 0x33: /* B16: bits 110011 */ + case 0x2b: /* BNEZ16: bits 101011 */ + case 0x23: /* BEQZ16: bits 100011 */ + return !mustbe32; + case 0x11: /* POOL16C: bits 010001 */ + return (!mustbe32 + && ((b5s5_op (major) == 0xc /* JR16: bits 010001 01100 */ - || (b5s5_op (insn) & 0x1e) == 0xe)) + || (b5s5_op (major) & 0x1e) == 0xe))); /* JALR16, JALRS16: bits 010001 0111x */ - || (micromips_op (insn) & 0x37) == 0x23 - /* BEQZ16, BNEZ16: bits 10x011 */ - || micromips_op (insn) == 0x33; - /* B16: bits 110011 */ - - /* 32-bit instructions. */ - if (micromips_op (insn) == 0x0) - /* POOL32A: bits 000000 */ - { - insn <<= 16; - insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); - if (status) - return 0; - return b0s6_op (insn) == 0x3c - /* POOL32Axf: bits 000000 ... 111100 */ - && (b6s10_ext (insn) & 0x2bf) == 0x3c; - /* JALR, JALR.HB: 000000 000x111100 111100 */ - /* JALRS, JALRS.HB: 000000 010x111100 111100 */ - } - - return (micromips_op (insn) == 0x10 - /* POOL32I: bits 010000 */ - && ((b5s5_op (insn) & 0x1c) == 0x0 + /* 32-bit instructions. */ + case 0x3d: /* JAL: bits 111101 */ + case 0x3c: /* JALX: bits 111100 */ + case 0x35: /* J: bits 110101 */ + case 0x2d: /* BNE: bits 101101 */ + case 0x25: /* BEQ: bits 100101 */ + case 0x1d: /* JALS: bits 011101 */ + return 1; + case 0x10: /* POOL32I: bits 010000 */ + return ((b5s5_op (major) & 0x1c) == 0x0 /* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */ - || (b5s5_op (insn) & 0x1d) == 0x4 + || (b5s5_op (major) & 0x1d) == 0x4 /* BLEZ, BGTZ: bits 010000 001x0 */ - || (b5s5_op (insn) & 0x1d) == 0x11 + || (b5s5_op (major) & 0x1d) == 0x11 /* BLTZALS, BGEZALS: bits 010000 100x1 */ - || ((b5s5_op (insn) & 0x1e) == 0x14 - && (insn & 0x3) == 0x0) + || ((b5s5_op (major) & 0x1e) == 0x14 + && (major & 0x3) == 0x0) /* BC2F, BC2T: bits 010000 1010x xxx00 */ - || (b5s5_op (insn) & 0x1e) == 0x1a + || (b5s5_op (major) & 0x1e) == 0x1a /* BPOSGE64, BPOSGE32: bits 010000 1101x */ - || ((b5s5_op (insn) & 0x1e) == 0x1c - && (insn & 0x3) == 0x0) + || ((b5s5_op (major) & 0x1e) == 0x1c + && (major & 0x3) == 0x0) /* BC1F, BC1T: bits 010000 1110x xxx00 */ - || ((b5s5_op (insn) & 0x1c) == 0x1c - && (insn & 0x3) == 0x1))) + || ((b5s5_op (major) & 0x1c) == 0x1c + && (major & 0x3) == 0x1)); /* BC1ANY*: bits 010000 111xx xxx01 */ - || (micromips_op (insn) & 0x1f) == 0x1d - /* JALS, JAL: bits x11101 */ - || (micromips_op (insn) & 0x37) == 0x25 - /* BEQ, BNE: bits 10x101 */ - || micromips_op (insn) == 0x35 - /* J: bits 110101 */ - || micromips_op (insn) == 0x3c; - /* JALX: bits 111100 */ + case 0x0: /* POOL32A: bits 000000 */ + return (b0s6_op (insn) == 0x3c + /* POOL32Axf: bits 000000 ... 111100 */ + && (b6s10_ext (insn) & 0x2bf) == 0x3c); + /* JALR, JALR.HB: 000000 000x111100 111100 */ + /* JALRS, JALRS.HB: 000000 010x111100 111100 */ + default: + return 0; + } } +/* Return non-zero if a microMIPS instruction at ADDR has a branch delay + slot (i.e. it is a non-compact jump instruction). The instruction + must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */ + static int -mips16_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr, - int mustbe32) +micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, + CORE_ADDR addr, int mustbe32) { - unsigned short inst; + ULONGEST insn; int status; - inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status); + insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); if (status) return 0; + insn <<= 16; + if (mips_insn_size (ISA_MICROMIPS, insn) == 2 * MIPS_INSN16_SIZE) + { + insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); + if (status) + return 0; + } - if (!mustbe32) - return (inst & 0xf89f) == 0xe800; /* JR/JALR (16-bit instruction) */ + return micromips_instruction_has_delay_slot (insn, mustbe32); +} + +/* Return non-zero if the MIPS16 instruction INST, which must be + a 32-bit instruction if MUSTBE32 is set or can be any instruction + otherwise, has a branch delay slot (i.e. it is a non-compact jump + instruction). This function is based on mips16_next_pc. */ + +static int +mips16_instruction_has_delay_slot (unsigned short inst, int mustbe32) +{ + if ((inst & 0xf89f) == 0xe800) /* JR/JALR (16-bit instruction) */ + return !mustbe32; return (inst & 0xf800) == 0x1800; /* JAL/JALX (32-bit instruction) */ } +/* Return non-zero if a MIPS16 instruction at ADDR has a branch delay + slot (i.e. it is a non-compact jump instruction). The instruction + must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */ + +static int +mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, + CORE_ADDR addr, int mustbe32) +{ + unsigned short insn; + int status; + + insn = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status); + if (status) + return 0; + + return mips16_instruction_has_delay_slot (insn, mustbe32); +} + /* Calculate the starting address of the MIPS memory segment BPADDR is in. This assumes KSSEG exists. */ @@ -7205,12 +7507,12 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) /* If the previous instruction has a branch delay slot, we have to move the breakpoint to the branch instruction. */ prev_addr = bpaddr - 4; - if (mips32_instruction_has_delay_slot (gdbarch, prev_addr)) + if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr)) bpaddr = prev_addr; } else { - int (*instruction_has_delay_slot) (struct gdbarch *, CORE_ADDR, int); + int (*insn_at_pc_has_delay_slot) (struct gdbarch *, CORE_ADDR, int); CORE_ADDR addr, jmpaddr; int i; @@ -7224,9 +7526,9 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) 2 bytes, so the idea is the same. FIXME: We have to assume that bpaddr is not the second half of an extended instruction. */ - instruction_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr) - ? micromips_instruction_has_delay_slot - : mips16_instruction_has_delay_slot); + insn_at_pc_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr) + ? micromips_insn_at_pc_has_delay_slot + : mips16_insn_at_pc_has_delay_slot); jmpaddr = 0; addr = bpaddr; @@ -7235,12 +7537,12 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) if (unmake_compact_addr (addr) == boundary) break; addr -= MIPS_INSN16_SIZE; - if (i == 1 && instruction_has_delay_slot (gdbarch, addr, 0)) + if (i == 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 0)) /* Looks like a JR/JALR at [target-1], but it could be the second word of a previous JAL/JALX, so record it and check back one more. */ jmpaddr = addr; - else if (i > 1 && instruction_has_delay_slot (gdbarch, addr, 1)) + else if (i > 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 1)) { if (i == 2) /* Looks like a JAL/JALX at [target-2], but it could also @@ -7548,8 +7850,8 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc) /* If the PC is in __call_stub_* or __fn_stub*, this is one of the compiler-generated call or call/return stubs. */ - if (strncmp (name, mips_str_fn_stub, strlen (mips_str_fn_stub)) == 0 - || strncmp (name, mips_str_call_stub, strlen (mips_str_call_stub)) == 0) + if (startswith (name, mips_str_fn_stub) + || startswith (name, mips_str_call_stub)) { if (pc == start_addr) /* This is the 'call' part of a call stub. Call this helper @@ -7634,9 +7936,9 @@ mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc) which jumps to foo. */ msym = lookup_minimal_symbol_by_pc (pc); if (msym.minsym == NULL - || SYMBOL_VALUE_ADDRESS (msym.minsym) != pc - || SYMBOL_LINKAGE_NAME (msym.minsym) == NULL - || strncmp (SYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) != 0) + || BMSYMBOL_VALUE_ADDRESS (msym) != pc + || MSYMBOL_LINKAGE_NAME (msym.minsym) == NULL + || !startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic.")) return 0; /* A two-instruction header. */ @@ -7685,27 +7987,15 @@ mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) new_pc = mips_skip_mips16_trampoline_code (frame, pc); if (new_pc) - { - pc = new_pc; - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); - } + pc = new_pc; new_pc = find_solib_trampoline_target (frame, pc); if (new_pc) - { - pc = new_pc; - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); - } + pc = new_pc; new_pc = mips_skip_pic_trampoline_code (frame, pc); if (new_pc) - { - pc = new_pc; - if (is_compact_addr (pc)) - pc = unmake_compact_addr (pc); - } + pc = new_pc; } while (pc != target_pc); @@ -7813,7 +8103,7 @@ mips_find_abi_section (bfd *abfd, asection *sect, void *obj) if (*abip != MIPS_ABI_UNKNOWN) return; - if (strncmp (name, ".mdebug.", 8) != 0) + if (!startswith (name, ".mdebug.")) return; if (strcmp (name, ".mdebug.abi32") == 0) @@ -7838,11 +8128,11 @@ mips_find_long_section (bfd *abfd, asection *sect, void *obj) int *lbp = (int *) obj; const char *name = bfd_get_section_name (abfd, sect); - if (strncmp (name, ".gcc_compiled_long32", 20) == 0) + if (startswith (name, ".gcc_compiled_long32")) *lbp = 32; - else if (strncmp (name, ".gcc_compiled_long64", 20) == 0) + else if (startswith (name, ".gcc_compiled_long64")) *lbp = 64; - else if (strncmp (name, ".gcc_compiled_long", 18) == 0) + else if (startswith (name, ".gcc_compiled_long")) warning (_("unrecognized .gcc_compiled_longXX")); } @@ -7909,7 +8199,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int i, num_regs; enum mips_fpu_type fpu_type; struct tdesc_arch_data *tdesc_data = NULL; - int elf_fpu_type = 0; + int elf_fpu_type = Val_GNU_MIPS_ABI_FP_ANY; const char **reg_names; struct mips_regnum mips_regnum, *regnum; enum mips_isa mips_isa; @@ -8234,17 +8524,17 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (!mips_fpu_type_auto) fpu_type = mips_fpu_type; - else if (elf_fpu_type != 0) + else if (elf_fpu_type != Val_GNU_MIPS_ABI_FP_ANY) { switch (elf_fpu_type) { - case 1: + case Val_GNU_MIPS_ABI_FP_DOUBLE: fpu_type = MIPS_FPU_DOUBLE; break; - case 2: + case Val_GNU_MIPS_ABI_FP_SINGLE: fpu_type = MIPS_FPU_SINGLE; break; - case 3: + case Val_GNU_MIPS_ABI_FP_SOFT: default: /* Soft float or unknown. */ fpu_type = MIPS_FPU_NONE; @@ -8295,12 +8585,14 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) arches != NULL; arches = gdbarch_list_lookup_by_info (arches->next, &info)) { - /* MIPS needs to be pedantic about which ABI the object is - using. */ + /* MIPS needs to be pedantic about which ABI and the compressed + ISA variation the object is using. */ if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags) continue; if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi) continue; + if (gdbarch_tdep (arches->gdbarch)->mips_isa != mips_isa) + continue; /* Need to be pedantic about which register virtual size is used. */ if (gdbarch_tdep (arches->gdbarch)->mips64_transfers_32bit_regs_p @@ -8326,10 +8618,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->mips_fpu_type = fpu_type; tdep->register_size_valid_p = 0; tdep->register_size = 0; - tdep->gregset = NULL; - tdep->gregset64 = NULL; - tdep->fpregset = NULL; - tdep->fpregset64 = NULL; if (info.target_desc) { @@ -8363,6 +8651,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_elf_make_msymbol_special (gdbarch, mips_elf_make_msymbol_special); + set_gdbarch_make_symbol_special (gdbarch, mips_make_symbol_special); + set_gdbarch_adjust_dwarf2_addr (gdbarch, mips_adjust_dwarf2_addr); + set_gdbarch_adjust_dwarf2_line (gdbarch, mips_adjust_dwarf2_line); regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum); *regnum = mips_regnum; @@ -8542,6 +8833,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code); set_gdbarch_frame_align (gdbarch, mips_frame_align); + set_gdbarch_print_float_info (gdbarch, mips_print_float_info); + set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p); set_gdbarch_register_to_value (gdbarch, mips_register_to_value); set_gdbarch_value_to_register (gdbarch, mips_value_to_register); @@ -8555,7 +8848,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, mips_in_function_epilogue_p); + set_gdbarch_stack_frame_destroyed_p (gdbarch, mips_stack_frame_destroyed_p); set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address); set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);