libunwind: update to 1.8.1
[openadk.git] / package / gdb-microblaze / patches / patch-gdb_microblaze-tdep_c
blobab19e4d7c43b72db480f77ba1d84a6cf91cc79bb
1 --- gdb-7.8.2.orig/gdb/microblaze-tdep.c        2015-01-15 11:58:12.000000000 +0100
2 +++ gdb-7.8.2/gdb/microblaze-tdep.c     2016-09-21 10:34:30.029222319 +0200
3 @@ -1,6 +1,6 @@
4  /* Target-dependent code for Xilinx MicroBlaze.
5  
6 -   Copyright (C) 2009-2014 Free Software Foundation, Inc.
7 +   Copyright (C) 2009-2013 Free Software Foundation, Inc.
8  
9     This file is part of GDB.
11 @@ -29,13 +29,13 @@
12  #include "inferior.h"
13  #include "regcache.h"
14  #include "target.h"
15 +#include "frame.h"
16  #include "frame-base.h"
17  #include "frame-unwind.h"
18  #include "dwarf2-frame.h"
19  #include "osabi.h"
21  #include "gdb_assert.h"
22 -#include <string.h>
23  #include "target-descriptions.h"
24  #include "opcodes/microblaze-opcm.h"
25  #include "opcodes/microblaze-dis.h"
26 @@ -73,7 +73,8 @@ static const char *microblaze_register_n
27    "rpc",  "rmsr", "rear", "resr", "rfsr", "rbtr",
28    "rpvr0", "rpvr1", "rpvr2", "rpvr3", "rpvr4", "rpvr5", "rpvr6",
29    "rpvr7", "rpvr8", "rpvr9", "rpvr10", "rpvr11",
30 -  "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi"
31 +  "redr", "rpid", "rzpr", "rtlbx", "rtlbsx", "rtlblo", "rtlbhi",
32 +  "rslr", "rshr"
33  };
35  #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names)
36 @@ -145,6 +146,14 @@ microblaze_push_dummy_code (struct gdbar
37    return sp;
38  }
40 +static CORE_ADDR
41 +microblaze_store_arguments (struct regcache *regcache, int nargs,
42 +                           struct value **args, CORE_ADDR sp,
43 +                           int struct_return, CORE_ADDR struct_addr)
45 +  error (_("store_arguments not implemented"));
46 +  return sp;
49  static CORE_ADDR
50  microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
51 @@ -156,14 +165,52 @@ microblaze_push_dummy_call (struct gdbar
52    return sp;
53  }
55 +static int
56 +microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
57 +                                   struct bp_target_info *bp_tgt)
59 +  CORE_ADDR addr = bp_tgt->placed_address;
60 +  const unsigned char *bp;
61 +  int val;
62 +  int bplen;
63 +  gdb_byte old_contents[BREAKPOINT_MAX];
64 +  struct cleanup *cleanup;
66 +  /* Determine appropriate breakpoint contents and size for this address.  */
67 +  bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen);
68 +  if (bp == NULL)
69 +    error (_("Software breakpoints not implemented for this target."));
71 +  /* Make sure we see the memory breakpoints.  */
72 +  cleanup = make_show_memory_breakpoints_cleanup (1);
73 +  val = target_read_memory (addr, old_contents, bplen);
75 +  /* If our breakpoint is no longer at the address, this means that the
76 +     program modified the code on us, so it is wrong to put back the
77 +     old value.  */
78 +  if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
79 +  {
80 +    val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen);
81 +    microblaze_debug ("microblaze_linux_memory_remove_breakpoint writing back to memory at addr 0x%lx\n", addr);
82 +  }
84 +  do_cleanups (cleanup);
85 +  return val;
88  static const gdb_byte *
89  microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, 
90                                int *len)
91  {
92 +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
93    static gdb_byte break_insn[] = MICROBLAZE_BREAKPOINT;
94 +  static gdb_byte break_insn_le[] = MICROBLAZE_BREAKPOINT_LE;
96    *len = sizeof (break_insn);
97 -  return break_insn;
98 +  if (byte_order == BFD_ENDIAN_BIG)
99 +    return break_insn;
100 +  else
101 +    return break_insn_le;
103  \f
104  /* Allocate and initialize a frame cache.  */
105 @@ -178,6 +225,7 @@ microblaze_alloc_frame_cache (void)
106    /* Base address.  */
107    cache->base = 0;
108    cache->pc = 0;
109 +  cache->saved_sp = 0;
111    /* Frameless until proven otherwise.  */
112    cache->frameless_p = 1;
113 @@ -234,6 +282,8 @@ microblaze_analyze_prologue (struct gdba
114    int flags = 0;
115    int save_hidden_pointer_found = 0;
116    int non_stack_instruction_found = 0;
117 +  int n_insns;
118 +  unsigned int *insn_block;
120    /* Find the start of this function.  */
121    find_pc_partial_function (pc, &name, &func_addr, &func_end);
122 @@ -273,11 +323,18 @@ microblaze_analyze_prologue (struct gdba
123                     name, paddress (gdbarch, func_addr), 
124                     paddress (gdbarch, stop));
126 +/* Do a block read to minimize the transaction with the Debug Agent */
127 +  n_insns = (stop == func_addr) ? 1 : ((stop - func_addr) / INST_WORD_SIZE);
128 +  insn_block = calloc(n_insns, sizeof(unsigned long));
130 +  target_read_memory (func_addr, (void*) insn_block, n_insns * INST_WORD_SIZE );
132    for (addr = func_addr; addr < stop; addr += INST_WORD_SIZE)
133      {
134        insn = microblaze_fetch_instruction (addr);
135 +      //insn = insn_block[(addr - func_addr) / INST_WORD_SIZE];
136        op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
137 -      microblaze_debug ("%s %08lx\n", paddress (gdbarch, pc), insn);
138 +      microblaze_debug ("%s %08lx op=%x r%d r%d imm=%d\n", paddress (gdbarch, addr), insn, op, rd, ra, imm);
140        /* This code is very sensitive to what functions are present in the
141          prologue.  It assumes that the (addi, addik, swi, sw) can be the 
142 @@ -291,6 +348,7 @@ microblaze_analyze_prologue (struct gdba
143           cache->frameless_p = 0; /* Frame found.  */
144           save_hidden_pointer_found = 0;
145           non_stack_instruction_found = 0;
146 +         cache->register_offsets[rd] = -imm;
147           continue;
148         }
149        else if (IS_SPILL_SP(op, rd, ra))
150 @@ -401,8 +459,8 @@ microblaze_analyze_prologue (struct gdba
151       part of the prologue.  */
152    if (save_hidden_pointer_found)
153      prologue_end_addr -= INST_WORD_SIZE;
155 -  return prologue_end_addr;
156 +    free(insn_block);
157 +    return prologue_end_addr;
160  static CORE_ADDR
161 @@ -452,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch
162    return start_pc;
165 +enum { REG_UNAVAIL = (CORE_ADDR) -1 };
166  /* Normal frames.  */
168  static struct microblaze_frame_cache *
169 @@ -459,7 +518,7 @@ microblaze_frame_cache (struct frame_inf
171    struct microblaze_frame_cache *cache;
172    struct gdbarch *gdbarch = get_frame_arch (next_frame);
173 -  CORE_ADDR func;
174 +  CORE_ADDR current_pc;
175    int rn;
177    if (*this_cache)
178 @@ -473,9 +532,18 @@ microblaze_frame_cache (struct frame_inf
179    for (rn = 0; rn < gdbarch_num_regs (gdbarch); rn++)
180      cache->register_offsets[rn] = -1;
182 -  func = get_frame_func (next_frame);
183 +  cache->pc = get_frame_func (next_frame);
184 +  current_pc = get_frame_pc (next_frame);
186 -  cache->pc = get_frame_address_in_block (next_frame);
187 +  if (cache->pc)
188 +    microblaze_analyze_prologue (gdbarch, cache->pc, current_pc,
189 +                                cache);
191 +  cache->base = get_frame_register_unsigned (next_frame, gdbarch_sp_regnum (gdbarch));
192 +  cache->saved_sp = cache->base + cache->framesize;
194 +  cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM] = cache->base;
195 +  cache->register_offsets[MICROBLAZE_SP_REGNUM] = cache->saved_sp;
197    return cache;
199 @@ -501,6 +569,14 @@ microblaze_frame_prev_register (struct f
200    struct microblaze_frame_cache *cache =
201      microblaze_frame_cache (this_frame, this_cache);
203 +  if ((regnum == MICROBLAZE_SP_REGNUM &&
204 +      cache->register_offsets[MICROBLAZE_SP_REGNUM])
205 +      || (regnum == MICROBLAZE_FP_REGNUM &&
206 +      cache->register_offsets[MICROBLAZE_SP_REGNUM]))
208 +     return frame_unwind_got_constant (this_frame, regnum,
209 +                                       cache->register_offsets[MICROBLAZE_SP_REGNUM]);
211    if (cache->frameless_p)
212      {
213        if (regnum == MICROBLAZE_PC_REGNUM)
214 @@ -508,11 +584,18 @@ microblaze_frame_prev_register (struct f
215        if (regnum == MICROBLAZE_SP_REGNUM)
216          regnum = 1;
217        return trad_frame_get_prev_register (this_frame,
218 -                                          cache->saved_regs, regnum);
219 +            cache->saved_regs, regnum);
220      }
221 -  else
222 -    return trad_frame_get_prev_register (this_frame, cache->saved_regs,
223 -                                        regnum);
225 +  if (regnum == MICROBLAZE_PC_REGNUM)
226 +    {
227 +      regnum = 15;
228 +      return frame_unwind_got_memory (this_frame, regnum,
229 +                                      cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]);
230 +    }
232 +  return trad_frame_get_prev_register (this_frame, cache->saved_regs,
233 +                                       regnum);
237 @@ -536,6 +619,12 @@ microblaze_frame_base_address (struct fr
238    return cache->base;
241 +static const struct frame_unwind *
242 +microblaze_frame_sniffer (struct frame_info *next_frame)
244 +  return &microblaze_frame_unwind;
247  static const struct frame_base microblaze_frame_base =
249    &microblaze_frame_unwind,
250 @@ -628,6 +717,109 @@ microblaze_stabs_argument_has_addr (stru
251    return (TYPE_LENGTH (type) == 16);
254 +int
255 +microblaze_software_single_step (struct frame_info *frame)
257 +  struct gdbarch *arch = get_frame_arch (frame);
258 +  struct address_space *aspace = get_frame_address_space (frame);
259 +  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
260 +  static char le_breakp[] = MICROBLAZE_BREAKPOINT_LE;
261 +  static char be_breakp[] = MICROBLAZE_BREAKPOINT;
262 +  enum bfd_endian byte_order = gdbarch_byte_order (arch);
263 +  char *breakp = byte_order == BFD_ENDIAN_BIG ? be_breakp : le_breakp;
264 +  int ret = 0;
266 +  /* Save the address and the values of the next_pc and the target */
267 +  static struct sstep_breaks
268 +  {
269 +    CORE_ADDR address;
270 +    bfd_boolean valid;
271 +    /* Shadow contents.  */
272 +    char data[INST_WORD_SIZE];
273 +  } stepbreaks[2];
274 +  int ii;
276 +  if (1)
277 +    {
278 +      CORE_ADDR pc;
279 +      long insn;
280 +      enum microblaze_instr minstr;
281 +      bfd_boolean isunsignednum;
282 +      enum microblaze_instr_type insn_type;
283 +      short delay_slots;
284 +      int imm;
285 +      bfd_boolean immfound = FALSE;
287 +      /* Set a breakpoint at the next instruction */
288 +      /* If the current instruction is an imm, set it at the inst after */
289 +      /* If the instruction has a delay slot, skip the delay slot */
290 +      pc = get_frame_pc (frame);
291 +      insn = microblaze_fetch_instruction (pc);
292 +      minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
293 +      if (insn_type == immediate_inst)
294 +       {
295 +         int rd, ra, rb;
296 +         immfound = TRUE;
297 +         minstr = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm);
298 +         pc = pc + INST_WORD_SIZE;
299 +         insn = microblaze_fetch_instruction (pc);
300 +         minstr = get_insn_microblaze (insn, &isunsignednum, &insn_type, &delay_slots);
301 +       }
302 +      stepbreaks[0].address = pc + (delay_slots * INST_WORD_SIZE) + INST_WORD_SIZE;
303 +      if (insn_type != return_inst) {
304 +       stepbreaks[0].valid = TRUE;
305 +      } else {
306 +       stepbreaks[0].valid = FALSE;
307 +      }
309 +      microblaze_debug ("single-step insn_type=%x insn=%x\n", insn_type, insn);
310 +      /* Now check for branch or return instructions */
311 +      if (insn_type == branch_inst || insn_type == return_inst) {
312 +       int limm;
313 +       int lrd, lra, lrb;
314 +       int ra, rb;
315 +       bfd_boolean targetvalid;
316 +       bfd_boolean unconditionalbranch;
317 +       microblaze_decode_insn(insn, &lrd, &lra, &lrb, &limm);
318 +       if (lra >= 0 && lra < MICROBLAZE_NUM_REGS)
319 +         ra = get_frame_register_unsigned (frame, lra);
320 +       else
321 +         ra = 0;
322 +       if (lrb >= 0 && lrb < MICROBLAZE_NUM_REGS)
323 +         rb = get_frame_register_unsigned (frame, lrb);
324 +       else
325 +         rb = 0;
327 +       stepbreaks[1].address = microblaze_get_target_address (insn, immfound, imm, pc, ra, rb, &targetvalid, &unconditionalbranch);
328 +       microblaze_debug ("single-step uncondbr=%d targetvalid=%d target=%x\n", unconditionalbranch, targetvalid, stepbreaks[1].address);
330 +       if (unconditionalbranch)
331 +         stepbreaks[0].valid = FALSE; /* This is a unconditional branch: will not come to the next address */
332 +       if (targetvalid && (stepbreaks[0].valid == FALSE ||
333 +                           (stepbreaks[0].address != stepbreaks[1].address))
334 +                       && (stepbreaks[1].address != pc)) {
335 +         stepbreaks[1].valid = TRUE;
336 +       } else {
337 +         stepbreaks[1].valid = FALSE;
338 +       }
339 +      } else {
340 +       stepbreaks[1].valid = FALSE;
341 +      }
343 +      /* Insert the breakpoints */
344 +      for (ii = 0; ii < 2; ++ii)
345 +        {
347 +          /* ignore invalid breakpoint. */
348 +          if (stepbreaks[ii].valid) {
349 +            insert_single_step_breakpoint (arch, aspace, stepbreaks[ii].address);
350 +            ret = 1;
351 +         }
352 +       }
353 +    }
354 +    return ret;
357  static void
358  microblaze_write_pc (struct regcache *regcache, CORE_ADDR pc)
360 @@ -664,6 +856,70 @@ microblaze_dwarf2_reg_to_regnum (struct
361    return dwarf2_to_reg_map[reg];
365 +void
366 +microblaze_supply_gregset (const struct microblaze_gregset *gregset,
367 +                        struct regcache *regcache,
368 +                        int regnum, const void *gregs)
370 +  unsigned int *regs = gregs;
371 +  if (regnum >= 0)
372 +    regcache_raw_supply (regcache, regnum, regs + regnum);
374 +  if (regnum == -1) {
375 +    int i;
377 +    for (i = 0; i < 50; i++) {
378 +      regcache_raw_supply (regcache, i, regs + i);
379 +    }
380 +  }
384 +void
385 +microblaze_collect_gregset (const struct microblaze_gregset *gregset,
386 +                         const struct regcache *regcache,
387 +                         int regnum, void *gregs)
389 +   /* FIXME.  */
392 +void
393 +microblaze_supply_fpregset (struct regcache *regcache,
394 +                         int regnum, const void *fpregs)
396 +   /* FIXME.  */
399 +void
400 +microblaze_collect_fpregset (const struct regcache *regcache,
401 +                          int regnum, void *fpregs)
403 +   /* FIXME.  */
407 +/* Return the appropriate register set for the core section identified
408 +   by SECT_NAME and SECT_SIZE.  */
410 +const struct regset *
411 +microblaze_regset_from_core_section (struct gdbarch *gdbarch,
412 +                                     const char *sect_name, size_t sect_size)
414 +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
416 +  microblaze_debug ("microblaze_regset_from_core_section, sect_name = %s\n", sect_name);
418 +  if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
419 +    return tdep->gregset;
421 +  if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
422 +    return tdep->fpregset;
424 +  microblaze_debug ("microblaze_regset_from_core_section returning null :-( \n");
425 +  return NULL;
428  static struct gdbarch *
429  microblaze_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
431 @@ -679,6 +935,11 @@ microblaze_gdbarch_init (struct gdbarch_
432    tdep = XNEW (struct gdbarch_tdep);
433    gdbarch = gdbarch_alloc (&info, tdep);
435 +  tdep->gregset = NULL;
436 +  tdep->sizeof_gregset = 0;
437 +  tdep->fpregset = NULL;
438 +  tdep->sizeof_fpregset = 0;
440    set_gdbarch_long_double_bit (gdbarch, 128);
442    set_gdbarch_num_regs (gdbarch, MICROBLAZE_NUM_REGS);
443 @@ -706,7 +967,10 @@ microblaze_gdbarch_init (struct gdbarch_
444    /* Stack grows downward.  */
445    set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
447 +  set_gdbarch_memory_remove_breakpoint (gdbarch, microblaze_linux_memory_remove_breakpoint);
449    set_gdbarch_breakpoint_from_pc (gdbarch, microblaze_breakpoint_from_pc);
450 +  set_gdbarch_software_single_step (gdbarch, microblaze_software_single_step);
452    set_gdbarch_frame_args_skip (gdbarch, 8);
454 @@ -725,6 +989,13 @@ microblaze_gdbarch_init (struct gdbarch_
455    dwarf2_append_unwinders (gdbarch);
456    frame_unwind_append_unwinder (gdbarch, &microblaze_frame_unwind);
457    frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
458 +  //frame_base_append_sniffer (gdbarch, microblaze_frame_sniffer);
460 +  /* If we have register sets, enable the generic core file support.  */
461 +  if (tdep->gregset) {
462 +      set_gdbarch_regset_from_core_section (gdbarch,
463 +                                          microblaze_regset_from_core_section);
464 +  }
466    return gdbarch;