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
4 /* Target-dependent code for Xilinx MicroBlaze.
6 - Copyright (C) 2009-2014 Free Software Foundation, Inc.
7 + Copyright (C) 2009-2013 Free Software Foundation, Inc.
9 This file is part of GDB.
16 #include "frame-base.h"
17 #include "frame-unwind.h"
18 #include "dwarf2-frame.h"
21 #include "gdb_assert.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",
35 #define MICROBLAZE_NUM_REGS ARRAY_SIZE (microblaze_register_names)
36 @@ -145,6 +146,14 @@ microblaze_push_dummy_code (struct gdbar
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"));
50 microblaze_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
51 @@ -156,14 +165,52 @@ microblaze_push_dummy_call (struct gdbar
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;
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);
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
78 + if (val == 0 && memcmp (bp, old_contents, bplen) == 0)
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);
84 + do_cleanups (cleanup);
88 static const gdb_byte *
89 microblaze_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc,
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);
98 + if (byte_order == BFD_ENDIAN_BIG)
101 + return break_insn_le;
104 /* Allocate and initialize a frame cache. */
105 @@ -178,6 +225,7 @@ microblaze_alloc_frame_cache (void)
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
115 int save_hidden_pointer_found = 0;
116 int non_stack_instruction_found = 0;
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)
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;
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;
157 + return prologue_end_addr;
161 @@ -452,6 +510,7 @@ microblaze_skip_prologue (struct gdbarch
165 +enum { REG_UNAVAIL = (CORE_ADDR) -1 };
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);
174 + CORE_ADDR current_pc;
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);
188 + microblaze_analyze_prologue (gdbarch, cache->pc, current_pc,
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;
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)
213 if (regnum == MICROBLAZE_PC_REGNUM)
214 @@ -508,11 +584,18 @@ microblaze_frame_prev_register (struct f
215 if (regnum == MICROBLAZE_SP_REGNUM)
217 return trad_frame_get_prev_register (this_frame,
218 - cache->saved_regs, regnum);
219 + cache->saved_regs, regnum);
222 - return trad_frame_get_prev_register (this_frame, cache->saved_regs,
225 + if (regnum == MICROBLAZE_PC_REGNUM)
228 + return frame_unwind_got_memory (this_frame, regnum,
229 + cache->register_offsets[MICROBLAZE_PREV_PC_REGNUM]);
232 + return trad_frame_get_prev_register (this_frame, cache->saved_regs,
237 @@ -536,6 +619,12 @@ microblaze_frame_base_address (struct fr
241 +static const struct frame_unwind *
242 +microblaze_frame_sniffer (struct frame_info *next_frame)
244 + return µblaze_frame_unwind;
247 static const struct frame_base microblaze_frame_base =
249 µblaze_frame_unwind,
250 @@ -628,6 +717,109 @@ microblaze_stabs_argument_has_addr (stru
251 return (TYPE_LENGTH (type) == 16);
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;
266 + /* Save the address and the values of the next_pc and the target */
267 + static struct sstep_breaks
271 + /* Shadow contents. */
272 + char data[INST_WORD_SIZE];
280 + enum microblaze_instr minstr;
281 + bfd_boolean isunsignednum;
282 + enum microblaze_instr_type insn_type;
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)
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);
302 + stepbreaks[0].address = pc + (delay_slots * INST_WORD_SIZE) + INST_WORD_SIZE;
303 + if (insn_type != return_inst) {
304 + stepbreaks[0].valid = TRUE;
306 + stepbreaks[0].valid = FALSE;
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) {
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);
322 + if (lrb >= 0 && lrb < MICROBLAZE_NUM_REGS)
323 + rb = get_frame_register_unsigned (frame, lrb);
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;
337 + stepbreaks[1].valid = FALSE;
340 + stepbreaks[1].valid = FALSE;
343 + /* Insert the breakpoints */
344 + for (ii = 0; ii < 2; ++ii)
347 + /* ignore invalid breakpoint. */
348 + if (stepbreaks[ii].valid) {
349 + insert_single_step_breakpoint (arch, aspace, stepbreaks[ii].address);
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];
366 +microblaze_supply_gregset (const struct microblaze_gregset *gregset,
367 + struct regcache *regcache,
368 + int regnum, const void *gregs)
370 + unsigned int *regs = gregs;
372 + regcache_raw_supply (regcache, regnum, regs + regnum);
374 + if (regnum == -1) {
377 + for (i = 0; i < 50; i++) {
378 + regcache_raw_supply (regcache, i, regs + i);
385 +microblaze_collect_gregset (const struct microblaze_gregset *gregset,
386 + const struct regcache *regcache,
387 + int regnum, void *gregs)
393 +microblaze_supply_fpregset (struct regcache *regcache,
394 + int regnum, const void *fpregs)
400 +microblaze_collect_fpregset (const struct regcache *regcache,
401 + int regnum, void *fpregs)
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");
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, µblaze_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);