1 /* Target-dependent code for Moxie.
3 Copyright (C) 2009 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "frame-unwind.h"
23 #include "frame-base.h"
28 #include "gdb_string.h"
35 #include "arch-utils.h"
37 #include "trad-frame.h"
40 #include "gdb_assert.h"
42 #include "moxie-tdep.h"
44 /* Local functions. */
46 extern void _initialize_moxie_tdep (void);
48 /* Use an invalid address value as 'not available' marker. */
49 enum { REG_UNAVAIL
= (CORE_ADDR
) -1 };
51 struct moxie_frame_cache
57 CORE_ADDR saved_regs
[MOXIE_NUM_REGS
];
61 /* Implement the "frame_align" gdbarch method. */
64 moxie_frame_align (struct gdbarch
*gdbarch
, CORE_ADDR sp
)
66 /* Align to the size of an instruction (so that they can safely be
67 pushed onto the stack. */
71 /* Implement the "breakpoint_from_pc" gdbarch method. */
73 const static unsigned char *
74 moxie_breakpoint_from_pc (struct gdbarch
*gdbarch
,
75 CORE_ADDR
*pcptr
, int *lenptr
)
77 static unsigned char breakpoint
[] = { 0x35, 0x00 };
79 *lenptr
= sizeof (breakpoint
);
83 /* Moxie register names. */
85 char *moxie_register_names
[] = {
86 "$fp", "$sp", "$r0", "$r1", "$r2",
87 "$r3", "$r4", "$r5", "$r6", "$r7",
88 "$r8", "$r9", "$r10", "$r11", "$r12",
89 "$r13", "$pc", "$cc" };
91 /* Implement the "register_name" gdbarch method. */
94 moxie_register_name (struct gdbarch
*gdbarch
, int reg_nr
)
98 if (reg_nr
>= MOXIE_NUM_REGS
)
100 return moxie_register_names
[reg_nr
];
103 /* Implement the "register_type" gdbarch method. */
106 moxie_register_type (struct gdbarch
*gdbarch
, int reg_nr
)
108 if (reg_nr
== MOXIE_PC_REGNUM
)
109 return builtin_type (gdbarch
)->builtin_func_ptr
;
110 else if (reg_nr
== MOXIE_SP_REGNUM
|| reg_nr
== MOXIE_FP_REGNUM
)
111 return builtin_type (gdbarch
)->builtin_data_ptr
;
113 return builtin_type (gdbarch
)->builtin_int32
;
116 /* Write into appropriate registers a function return value
117 of type TYPE, given in virtual format. */
120 moxie_store_return_value (struct type
*type
, struct regcache
*regcache
,
124 int len
= TYPE_LENGTH (type
);
126 /* Things always get returned in RET1_REGNUM, RET2_REGNUM. */
127 regval
= extract_unsigned_integer (valbuf
, len
> 4 ? 4 : len
);
128 regcache_cooked_write_unsigned (regcache
, RET1_REGNUM
, regval
);
131 regval
= extract_unsigned_integer ((gdb_byte
*) valbuf
+ 4, len
- 4);
132 regcache_cooked_write_unsigned (regcache
, RET1_REGNUM
+ 1, regval
);
136 /* Decode the instructions within the given address range. Decide
137 when we must have reached the end of the function prologue. If a
138 frame_info pointer is provided, fill in its saved_regs etc.
140 Returns the address of the first instruction after the prologue. */
143 moxie_analyze_prologue (CORE_ADDR start_addr
, CORE_ADDR end_addr
,
144 struct moxie_frame_cache
*cache
,
145 struct frame_info
*this_frame
)
148 ULONGEST inst
, inst2
;
152 /* Record where the jsra instruction saves the PC and FP. */
153 cache
->saved_regs
[MOXIE_PC_REGNUM
] = -4;
154 cache
->saved_regs
[MOXIE_FP_REGNUM
] = 0;
155 cache
->framesize
= 0;
157 if (start_addr
>= end_addr
)
160 for (next_addr
= start_addr
; next_addr
< end_addr
; )
162 inst
= read_memory_unsigned_integer (next_addr
, 2);
164 /* Match "push $rN" where N is between 2 and 13 inclusive. */
165 if (inst
>= 0x0614 && inst
<= 0x061f)
167 regnum
= inst
& 0x000f;
168 cache
->framesize
+= 4;
169 cache
->saved_regs
[regnum
] = cache
->framesize
;
173 /* Optional stack allocation for args and local vars <= 4
175 else if (inst
== 0x01f0) /* ldi.l $r12, X */
177 offset
= read_memory_integer (next_addr
+ 2, 4);
178 inst2
= read_memory_unsigned_integer (next_addr
+ 6, 2);
180 if (inst2
== 0x051f) /* add.l $sp, $r12 */
182 cache
->framesize
+= offset
;
185 return (next_addr
+ 8);
187 else /* This is not a prologue instruction. */
194 /* Find the end of function prologue. */
197 moxie_skip_prologue (struct gdbarch
*gdbarch
, CORE_ADDR pc
)
199 CORE_ADDR func_addr
= 0, func_end
= 0;
202 /* See if we can determine the end of the prologue via the symbol table.
203 If so, then return either PC, or the PC after the prologue, whichever
205 if (find_pc_partial_function (pc
, &func_name
, &func_addr
, &func_end
))
207 CORE_ADDR post_prologue_pc
208 = skip_prologue_using_sal (gdbarch
, func_addr
);
209 if (post_prologue_pc
!= 0)
210 return max (pc
, post_prologue_pc
);
213 /* Can't determine prologue from the symbol table, need to examine
215 struct symtab_and_line sal
;
217 struct moxie_frame_cache cache
;
220 memset (&cache
, 0, sizeof cache
);
222 plg_end
= moxie_analyze_prologue (func_addr
,
223 func_end
, &cache
, NULL
);
224 /* Found a function. */
225 sym
= lookup_symbol (func_name
, NULL
, VAR_DOMAIN
, NULL
);
226 /* Don't use line number debug info for assembly source
228 if (sym
&& SYMBOL_LANGUAGE (sym
) != language_asm
)
230 sal
= find_pc_line (func_addr
, 0);
231 if (sal
.end
&& sal
.end
< func_end
)
233 /* Found a line number, use it as end of
238 /* No useable line symbol. Use result of prologue parsing
244 /* No function symbol -- just return the PC. */
245 return (CORE_ADDR
) pc
;
248 struct moxie_unwind_cache
250 /* The previous frame's inner most stack address. Used as this
251 frame ID's stack_addr. */
253 /* The frame's base, optionally used by the high-level debug info. */
256 /* How far the SP and r13 (FP) have been offset from the start of
257 the stack frame (as defined by the previous frame's stack
262 /* Table indicating the location of each and every register. */
263 struct trad_frame_saved_reg
*saved_regs
;
266 /* Implement the "read_pc" gdbarch method. */
269 moxie_read_pc (struct regcache
*regcache
)
273 regcache_cooked_read_unsigned (regcache
, MOXIE_PC_REGNUM
, &pc
);
277 /* Implement the "write_pc" gdbarch method. */
280 moxie_write_pc (struct regcache
*regcache
, CORE_ADDR val
)
282 regcache_cooked_write_unsigned (regcache
, MOXIE_PC_REGNUM
, val
);
285 /* Implement the "unwind_pc" gdbarch method. */
288 moxie_unwind_sp (struct gdbarch
*gdbarch
, struct frame_info
*next_frame
)
290 return frame_unwind_register_unsigned (next_frame
, MOXIE_SP_REGNUM
);
293 /* Given a return value in `regbuf' with a type `valtype',
294 extract and copy its value into `valbuf'. */
297 moxie_extract_return_value (struct type
*type
, struct regcache
*regcache
,
300 bfd_byte
*valbuf
= dst
;
301 int len
= TYPE_LENGTH (type
);
304 /* By using store_unsigned_integer we avoid having to do
305 anything special for small big-endian values. */
306 regcache_cooked_read_unsigned (regcache
, RET1_REGNUM
, &tmp
);
307 store_unsigned_integer (valbuf
, (len
> 4 ? len
- 4 : len
), tmp
);
309 /* Ignore return values more than 8 bytes in size because the moxie
310 returns anything more than 8 bytes in the stack. */
313 regcache_cooked_read_unsigned (regcache
, RET1_REGNUM
+ 1, &tmp
);
314 store_unsigned_integer (valbuf
+ len
- 4, 4, tmp
);
318 /* Implement the "return_value" gdbarch method. */
320 static enum return_value_convention
321 moxie_return_value (struct gdbarch
*gdbarch
, struct type
*func_type
,
322 struct type
*valtype
, struct regcache
*regcache
,
323 gdb_byte
*readbuf
, const gdb_byte
*writebuf
)
325 if (TYPE_LENGTH (valtype
) > 8)
326 return RETURN_VALUE_STRUCT_CONVENTION
;
330 moxie_extract_return_value (valtype
, regcache
, readbuf
);
331 if (writebuf
!= NULL
)
332 moxie_store_return_value (valtype
, regcache
, writebuf
);
333 return RETURN_VALUE_REGISTER_CONVENTION
;
337 /* Allocate and initialize a moxie_frame_cache object. */
339 static struct moxie_frame_cache
*
340 moxie_alloc_frame_cache (void)
342 struct moxie_frame_cache
*cache
;
345 cache
= FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache
);
350 cache
->framesize
= 0;
351 for (i
= 0; i
< MOXIE_NUM_REGS
; ++i
)
352 cache
->saved_regs
[i
] = REG_UNAVAIL
;
357 /* Populate a moxie_frame_cache object for this_frame. */
359 static struct moxie_frame_cache
*
360 moxie_frame_cache (struct frame_info
*this_frame
, void **this_cache
)
362 struct moxie_frame_cache
*cache
;
363 CORE_ADDR current_pc
;
369 cache
= moxie_alloc_frame_cache ();
372 cache
->base
= get_frame_register_unsigned (this_frame
, MOXIE_FP_REGNUM
);
373 if (cache
->base
== 0)
376 cache
->pc
= get_frame_func (this_frame
);
377 current_pc
= get_frame_pc (this_frame
);
379 moxie_analyze_prologue (cache
->pc
, current_pc
, cache
, this_frame
);
381 cache
->saved_sp
= cache
->base
- cache
->framesize
;
383 for (i
= 0; i
< MOXIE_NUM_REGS
; ++i
)
384 if (cache
->saved_regs
[i
] != REG_UNAVAIL
)
385 cache
->saved_regs
[i
] = cache
->base
- cache
->saved_regs
[i
];
390 /* Implement the "unwind_pc" gdbarch method. */
393 moxie_unwind_pc (struct gdbarch
*gdbarch
, struct frame_info
*next_frame
)
395 return frame_unwind_register_unsigned (next_frame
, MOXIE_PC_REGNUM
);
398 /* Given a GDB frame, determine the address of the calling function's
399 frame. This will be used to create a new GDB frame struct. */
402 moxie_frame_this_id (struct frame_info
*this_frame
,
403 void **this_prologue_cache
, struct frame_id
*this_id
)
405 struct moxie_frame_cache
*cache
= moxie_frame_cache (this_frame
,
406 this_prologue_cache
);
408 /* This marks the outermost frame. */
409 if (cache
->base
== 0)
412 *this_id
= frame_id_build (cache
->saved_sp
, cache
->pc
);
415 /* Get the value of register regnum in the previous stack frame. */
417 static struct value
*
418 moxie_frame_prev_register (struct frame_info
*this_frame
,
419 void **this_prologue_cache
, int regnum
)
421 struct moxie_frame_cache
*cache
= moxie_frame_cache (this_frame
,
422 this_prologue_cache
);
424 gdb_assert (regnum
>= 0);
426 if (regnum
== MOXIE_SP_REGNUM
&& cache
->saved_sp
)
427 return frame_unwind_got_constant (this_frame
, regnum
, cache
->saved_sp
);
429 if (regnum
< MOXIE_NUM_REGS
&& cache
->saved_regs
[regnum
] != REG_UNAVAIL
)
430 return frame_unwind_got_memory (this_frame
, regnum
,
431 cache
->saved_regs
[regnum
]);
433 return frame_unwind_got_register (this_frame
, regnum
, regnum
);
436 static const struct frame_unwind moxie_frame_unwind
= {
439 moxie_frame_prev_register
,
441 default_frame_sniffer
444 /* Return the base address of this_frame. */
447 moxie_frame_base_address (struct frame_info
*this_frame
, void **this_cache
)
449 struct moxie_frame_cache
*cache
= moxie_frame_cache (this_frame
,
455 static const struct frame_base moxie_frame_base
= {
457 moxie_frame_base_address
,
458 moxie_frame_base_address
,
459 moxie_frame_base_address
462 static struct frame_id
463 moxie_dummy_id (struct gdbarch
*gdbarch
, struct frame_info
*this_frame
)
465 CORE_ADDR sp
= get_frame_register_unsigned (this_frame
, MOXIE_SP_REGNUM
);
467 return frame_id_build (sp
, get_frame_pc (this_frame
));
470 /* Allocate and initialize the moxie gdbarch object. */
472 static struct gdbarch
*
473 moxie_gdbarch_init (struct gdbarch_info info
, struct gdbarch_list
*arches
)
475 struct gdbarch
*gdbarch
;
476 struct gdbarch_tdep
*tdep
;
478 /* If there is already a candidate, use it. */
479 arches
= gdbarch_list_lookup_by_info (arches
, &info
);
481 return arches
->gdbarch
;
483 /* Allocate space for the new architecture. */
484 tdep
= XMALLOC (struct gdbarch_tdep
);
485 gdbarch
= gdbarch_alloc (&info
, tdep
);
487 set_gdbarch_read_pc (gdbarch
, moxie_read_pc
);
488 set_gdbarch_write_pc (gdbarch
, moxie_write_pc
);
489 set_gdbarch_unwind_sp (gdbarch
, moxie_unwind_sp
);
491 set_gdbarch_num_regs (gdbarch
, MOXIE_NUM_REGS
);
492 set_gdbarch_sp_regnum (gdbarch
, MOXIE_SP_REGNUM
);
493 set_gdbarch_register_name (gdbarch
, moxie_register_name
);
494 set_gdbarch_register_type (gdbarch
, moxie_register_type
);
496 set_gdbarch_return_value (gdbarch
, moxie_return_value
);
498 set_gdbarch_skip_prologue (gdbarch
, moxie_skip_prologue
);
499 set_gdbarch_inner_than (gdbarch
, core_addr_lessthan
);
500 set_gdbarch_breakpoint_from_pc (gdbarch
, moxie_breakpoint_from_pc
);
501 set_gdbarch_frame_align (gdbarch
, moxie_frame_align
);
503 frame_base_set_default (gdbarch
, &moxie_frame_base
);
505 /* Methods for saving / extracting a dummy frame's ID. The ID's
506 stack address must match the SP value returned by
507 PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
508 set_gdbarch_dummy_id (gdbarch
, moxie_dummy_id
);
510 set_gdbarch_unwind_pc (gdbarch
, moxie_unwind_pc
);
512 set_gdbarch_print_insn (gdbarch
, print_insn_moxie
);
514 /* Hook in ABI-specific overrides, if they have been registered. */
515 gdbarch_init_osabi (info
, gdbarch
);
517 /* Hook in the default unwinders. */
518 frame_unwind_append_unwinder (gdbarch
, &moxie_frame_unwind
);
520 /* Support simple overlay manager. */
521 set_gdbarch_overlay_update (gdbarch
, simple_overlay_update
);
526 /* Register this machine's init routine. */
529 _initialize_moxie_tdep (void)
531 register_gdbarch_init (bfd_arch_moxie
, moxie_gdbarch_init
);