]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/moxie-tdep.c
Fix function prologue analyzer for moxie.
[thirdparty/binutils-gdb.git] / gdb / moxie-tdep.c
1 /* Target-dependent code for Moxie.
2
3 Copyright (C) 2009-2012 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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/>. */
19
20 #include "defs.h"
21 #include "frame.h"
22 #include "frame-unwind.h"
23 #include "frame-base.h"
24 #include "symtab.h"
25 #include "gdbtypes.h"
26 #include "gdbcmd.h"
27 #include "gdbcore.h"
28 #include "gdb_string.h"
29 #include "value.h"
30 #include "inferior.h"
31 #include "symfile.h"
32 #include "objfiles.h"
33 #include "osabi.h"
34 #include "language.h"
35 #include "arch-utils.h"
36 #include "regcache.h"
37 #include "trad-frame.h"
38 #include "dis-asm.h"
39 #include "record.h"
40
41 #include "gdb_assert.h"
42
43 #include "moxie-tdep.h"
44
45 /* Local functions. */
46
47 extern void _initialize_moxie_tdep (void);
48
49 /* Use an invalid address value as 'not available' marker. */
50 enum { REG_UNAVAIL = (CORE_ADDR) -1 };
51
52 struct moxie_frame_cache
53 {
54 /* Base address. */
55 CORE_ADDR base;
56 CORE_ADDR pc;
57 LONGEST framesize;
58 CORE_ADDR saved_regs[MOXIE_NUM_REGS];
59 CORE_ADDR saved_sp;
60 };
61
62 /* Implement the "frame_align" gdbarch method. */
63
64 static CORE_ADDR
65 moxie_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
66 {
67 /* Align to the size of an instruction (so that they can safely be
68 pushed onto the stack. */
69 return sp & ~1;
70 }
71
72 /* Implement the "breakpoint_from_pc" gdbarch method. */
73
74 const static unsigned char *
75 moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
76 CORE_ADDR *pcptr, int *lenptr)
77 {
78 static unsigned char breakpoint[] = { 0x35, 0x00 };
79
80 *lenptr = sizeof (breakpoint);
81 return breakpoint;
82 }
83
84 /* Moxie register names. */
85
86 char *moxie_register_names[] = {
87 "$fp", "$sp", "$r0", "$r1", "$r2",
88 "$r3", "$r4", "$r5", "$r6", "$r7",
89 "$r8", "$r9", "$r10", "$r11", "$r12",
90 "$r13", "$pc", "$cc" };
91
92 /* Implement the "register_name" gdbarch method. */
93
94 static const char *
95 moxie_register_name (struct gdbarch *gdbarch, int reg_nr)
96 {
97 if (reg_nr < 0)
98 return NULL;
99 if (reg_nr >= MOXIE_NUM_REGS)
100 return NULL;
101 return moxie_register_names[reg_nr];
102 }
103
104 /* Implement the "register_type" gdbarch method. */
105
106 static struct type *
107 moxie_register_type (struct gdbarch *gdbarch, int reg_nr)
108 {
109 if (reg_nr == MOXIE_PC_REGNUM)
110 return builtin_type (gdbarch)->builtin_func_ptr;
111 else if (reg_nr == MOXIE_SP_REGNUM || reg_nr == MOXIE_FP_REGNUM)
112 return builtin_type (gdbarch)->builtin_data_ptr;
113 else
114 return builtin_type (gdbarch)->builtin_int32;
115 }
116
117 /* Write into appropriate registers a function return value
118 of type TYPE, given in virtual format. */
119
120 static void
121 moxie_store_return_value (struct type *type, struct regcache *regcache,
122 const void *valbuf)
123 {
124 struct gdbarch *gdbarch = get_regcache_arch (regcache);
125 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
126 CORE_ADDR regval;
127 int len = TYPE_LENGTH (type);
128
129 /* Things always get returned in RET1_REGNUM, RET2_REGNUM. */
130 regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len, byte_order);
131 regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval);
132 if (len > 4)
133 {
134 regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4,
135 len - 4, byte_order);
136 regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval);
137 }
138 }
139
140 /* Decode the instructions within the given address range. Decide
141 when we must have reached the end of the function prologue. If a
142 frame_info pointer is provided, fill in its saved_regs etc.
143
144 Returns the address of the first instruction after the prologue. */
145
146 static CORE_ADDR
147 moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
148 struct moxie_frame_cache *cache,
149 struct gdbarch *gdbarch)
150 {
151 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
152 CORE_ADDR next_addr;
153 ULONGEST inst, inst2;
154 LONGEST offset;
155 int regnum;
156
157 /* Record where the jsra instruction saves the PC and FP. */
158 cache->saved_regs[MOXIE_PC_REGNUM] = -4;
159 cache->saved_regs[MOXIE_FP_REGNUM] = 0;
160 cache->framesize = 0;
161
162 if (start_addr >= end_addr)
163 return end_addr;
164
165 for (next_addr = start_addr; next_addr < end_addr; )
166 {
167 inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
168
169 /* Match "push $sp $rN" where N is between 0 and 13 inclusive. */
170 if (inst >= 0x0612 && inst <= 0x061f)
171 {
172 regnum = inst & 0x000f;
173 cache->framesize += 4;
174 cache->saved_regs[regnum] = cache->framesize;
175 next_addr += 2;
176 }
177 else
178 break;
179 }
180
181 inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
182
183 /* Optional stack allocation for args and local vars <= 4
184 byte. */
185 if (inst == 0x01e0) /* ldi.l $r12, X */
186 {
187 offset = read_memory_integer (next_addr + 2, 4, byte_order);
188 inst2 = read_memory_unsigned_integer (next_addr + 6, 2, byte_order);
189
190 if (inst2 == 0x291e) /* sub.l $sp, $r12 */
191 {
192 cache->framesize += offset;
193 }
194
195 return (next_addr + 8);
196 }
197 else if ((inst & 0xff00) == 0x9100) /* dec $sp, X */
198 {
199 cache->framesize += (inst & 0x00ff);
200 next_addr += 2;
201
202 while (next_addr < end_addr)
203 {
204 inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
205 if ((inst & 0xff00) != 0x9100) /* no more dec $sp, X */
206 break;
207 cache->framesize += (inst & 0x00ff);
208 next_addr += 2;
209 }
210 }
211
212 return next_addr;
213 }
214
215 /* Find the end of function prologue. */
216
217 static CORE_ADDR
218 moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
219 {
220 CORE_ADDR func_addr = 0, func_end = 0;
221 const char *func_name;
222
223 /* See if we can determine the end of the prologue via the symbol table.
224 If so, then return either PC, or the PC after the prologue, whichever
225 is greater. */
226 if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
227 {
228 CORE_ADDR post_prologue_pc
229 = skip_prologue_using_sal (gdbarch, func_addr);
230 if (post_prologue_pc != 0)
231 return max (pc, post_prologue_pc);
232 else
233 {
234 /* Can't determine prologue from the symbol table, need to examine
235 instructions. */
236 struct symtab_and_line sal;
237 struct symbol *sym;
238 struct moxie_frame_cache cache;
239 CORE_ADDR plg_end;
240
241 memset (&cache, 0, sizeof cache);
242
243 plg_end = moxie_analyze_prologue (func_addr,
244 func_end, &cache, gdbarch);
245 /* Found a function. */
246 sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
247 /* Don't use line number debug info for assembly source
248 files. */
249 if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
250 {
251 sal = find_pc_line (func_addr, 0);
252 if (sal.end && sal.end < func_end)
253 {
254 /* Found a line number, use it as end of
255 prologue. */
256 return sal.end;
257 }
258 }
259 /* No useable line symbol. Use result of prologue parsing
260 method. */
261 return plg_end;
262 }
263 }
264
265 /* No function symbol -- just return the PC. */
266 return (CORE_ADDR) pc;
267 }
268
269 struct moxie_unwind_cache
270 {
271 /* The previous frame's inner most stack address. Used as this
272 frame ID's stack_addr. */
273 CORE_ADDR prev_sp;
274 /* The frame's base, optionally used by the high-level debug info. */
275 CORE_ADDR base;
276 int size;
277 /* How far the SP and r13 (FP) have been offset from the start of
278 the stack frame (as defined by the previous frame's stack
279 pointer). */
280 LONGEST sp_offset;
281 LONGEST r13_offset;
282 int uses_frame;
283 /* Table indicating the location of each and every register. */
284 struct trad_frame_saved_reg *saved_regs;
285 };
286
287 /* Implement the "read_pc" gdbarch method. */
288
289 static CORE_ADDR
290 moxie_read_pc (struct regcache *regcache)
291 {
292 ULONGEST pc;
293
294 regcache_cooked_read_unsigned (regcache, MOXIE_PC_REGNUM, &pc);
295 return pc;
296 }
297
298 /* Implement the "write_pc" gdbarch method. */
299
300 static void
301 moxie_write_pc (struct regcache *regcache, CORE_ADDR val)
302 {
303 regcache_cooked_write_unsigned (regcache, MOXIE_PC_REGNUM, val);
304 }
305
306 /* Implement the "unwind_sp" gdbarch method. */
307
308 static CORE_ADDR
309 moxie_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
310 {
311 return frame_unwind_register_unsigned (next_frame, MOXIE_SP_REGNUM);
312 }
313
314 /* Given a return value in `regbuf' with a type `valtype',
315 extract and copy its value into `valbuf'. */
316
317 static void
318 moxie_extract_return_value (struct type *type, struct regcache *regcache,
319 void *dst)
320 {
321 struct gdbarch *gdbarch = get_regcache_arch (regcache);
322 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
323 bfd_byte *valbuf = dst;
324 int len = TYPE_LENGTH (type);
325 ULONGEST tmp;
326
327 /* By using store_unsigned_integer we avoid having to do
328 anything special for small big-endian values. */
329 regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &tmp);
330 store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), byte_order, tmp);
331
332 /* Ignore return values more than 8 bytes in size because the moxie
333 returns anything more than 8 bytes in the stack. */
334 if (len > 4)
335 {
336 regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp);
337 store_unsigned_integer (valbuf + len - 4, 4, byte_order, tmp);
338 }
339 }
340
341 /* Implement the "return_value" gdbarch method. */
342
343 static enum return_value_convention
344 moxie_return_value (struct gdbarch *gdbarch, struct value *function,
345 struct type *valtype, struct regcache *regcache,
346 gdb_byte *readbuf, const gdb_byte *writebuf)
347 {
348 if (TYPE_LENGTH (valtype) > 8)
349 return RETURN_VALUE_STRUCT_CONVENTION;
350 else
351 {
352 if (readbuf != NULL)
353 moxie_extract_return_value (valtype, regcache, readbuf);
354 if (writebuf != NULL)
355 moxie_store_return_value (valtype, regcache, writebuf);
356 return RETURN_VALUE_REGISTER_CONVENTION;
357 }
358 }
359
360 /* Allocate and initialize a moxie_frame_cache object. */
361
362 static struct moxie_frame_cache *
363 moxie_alloc_frame_cache (void)
364 {
365 struct moxie_frame_cache *cache;
366 int i;
367
368 cache = FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache);
369
370 cache->base = 0;
371 cache->saved_sp = 0;
372 cache->pc = 0;
373 cache->framesize = 0;
374 for (i = 0; i < MOXIE_NUM_REGS; ++i)
375 cache->saved_regs[i] = REG_UNAVAIL;
376
377 return cache;
378 }
379
380 /* Populate a moxie_frame_cache object for this_frame. */
381
382 static struct moxie_frame_cache *
383 moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
384 {
385 struct moxie_frame_cache *cache;
386 CORE_ADDR current_pc;
387 int i;
388
389 if (*this_cache)
390 return *this_cache;
391
392 cache = moxie_alloc_frame_cache ();
393 *this_cache = cache;
394
395 cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
396 if (cache->base == 0)
397 return cache;
398
399 cache->pc = get_frame_func (this_frame);
400 current_pc = get_frame_pc (this_frame);
401 if (cache->pc)
402 {
403 struct gdbarch *gdbarch = get_frame_arch (this_frame);
404 moxie_analyze_prologue (cache->pc, current_pc, cache, gdbarch);
405 }
406
407 cache->saved_sp = cache->base - cache->framesize;
408
409 for (i = 0; i < MOXIE_NUM_REGS; ++i)
410 if (cache->saved_regs[i] != REG_UNAVAIL)
411 cache->saved_regs[i] = cache->base - cache->saved_regs[i];
412
413 return cache;
414 }
415
416 /* Implement the "unwind_pc" gdbarch method. */
417
418 static CORE_ADDR
419 moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
420 {
421 return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
422 }
423
424 /* Given a GDB frame, determine the address of the calling function's
425 frame. This will be used to create a new GDB frame struct. */
426
427 static void
428 moxie_frame_this_id (struct frame_info *this_frame,
429 void **this_prologue_cache, struct frame_id *this_id)
430 {
431 struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
432 this_prologue_cache);
433
434 /* This marks the outermost frame. */
435 if (cache->base == 0)
436 return;
437
438 *this_id = frame_id_build (cache->saved_sp, cache->pc);
439 }
440
441 /* Get the value of register regnum in the previous stack frame. */
442
443 static struct value *
444 moxie_frame_prev_register (struct frame_info *this_frame,
445 void **this_prologue_cache, int regnum)
446 {
447 struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
448 this_prologue_cache);
449
450 gdb_assert (regnum >= 0);
451
452 if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
453 return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
454
455 if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
456 return frame_unwind_got_memory (this_frame, regnum,
457 cache->saved_regs[regnum]);
458
459 return frame_unwind_got_register (this_frame, regnum, regnum);
460 }
461
462 static const struct frame_unwind moxie_frame_unwind = {
463 NORMAL_FRAME,
464 default_frame_unwind_stop_reason,
465 moxie_frame_this_id,
466 moxie_frame_prev_register,
467 NULL,
468 default_frame_sniffer
469 };
470
471 /* Return the base address of this_frame. */
472
473 static CORE_ADDR
474 moxie_frame_base_address (struct frame_info *this_frame, void **this_cache)
475 {
476 struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
477 this_cache);
478
479 return cache->base;
480 }
481
482 static const struct frame_base moxie_frame_base = {
483 &moxie_frame_unwind,
484 moxie_frame_base_address,
485 moxie_frame_base_address,
486 moxie_frame_base_address
487 };
488
489 static struct frame_id
490 moxie_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
491 {
492 CORE_ADDR sp = get_frame_register_unsigned (this_frame, MOXIE_SP_REGNUM);
493
494 return frame_id_build (sp, get_frame_pc (this_frame));
495 }
496
497 /* Read an unsigned integer from the inferior, and adjust
498 endianess. */
499 static ULONGEST
500 moxie_process_readu (CORE_ADDR addr, char *buf,
501 int length, enum bfd_endian byte_order)
502 {
503 if (target_read_memory (addr, buf, length))
504 {
505 if (record_debug)
506 printf_unfiltered (_("Process record: error reading memory at "
507 "addr 0x%s len = %d.\n"),
508 paddress (target_gdbarch, addr), length);
509 return -1;
510 }
511
512 return extract_unsigned_integer (buf, length, byte_order);
513 }
514
515 /* Parse the current instruction and record the values of the registers and
516 memory that will be changed in current instruction to "record_arch_list".
517 Return -1 if something wrong. */
518
519 static int
520 moxie_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
521 CORE_ADDR addr)
522 {
523 gdb_byte buf[4];
524 uint16_t inst;
525 uint32_t tmpu32;
526 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
527
528 if (record_debug > 1)
529 fprintf_unfiltered (gdb_stdlog, "Process record: moxie_process_record "
530 "addr = 0x%s\n",
531 paddress (target_gdbarch, addr));
532
533 inst = (uint16_t) moxie_process_readu (addr, buf, 2, byte_order);
534
535 /* Decode instruction. */
536 if (inst & (1 << 15))
537 {
538 if (inst & (1 << 14))
539 {
540 /* This is a Form 3 instruction. */
541 int opcode = (inst >> 10 & 0xf);
542
543 switch (opcode)
544 {
545 case 0x00: /* beq */
546 case 0x01: /* bne */
547 case 0x02: /* blt */
548 case 0x03: /* bgt */
549 case 0x04: /* bltu */
550 case 0x05: /* bgtu */
551 case 0x06: /* bge */
552 case 0x07: /* ble */
553 case 0x08: /* bgeu */
554 case 0x09: /* bleu */
555 /* Do nothing. */
556 break;
557 default:
558 {
559 /* Do nothing. */
560 break;
561 }
562 }
563 }
564 else
565 {
566 /* This is a Form 2 instruction. */
567 int opcode = (inst >> 12 & 0x3);
568 switch (opcode)
569 {
570 case 0x00: /* inc */
571 case 0x01: /* dec */
572 case 0x02: /* gsr */
573 {
574 int reg = (inst >> 8) & 0xf;
575 if (record_arch_list_add_reg (regcache, reg))
576 return -1;
577 }
578 break;
579 case 0x03: /* ssr */
580 {
581 /* Do nothing until GDB learns about moxie's special
582 registers. */
583 }
584 break;
585 default:
586 /* Do nothing. */
587 break;
588 }
589 }
590 }
591 else
592 {
593 /* This is a Form 1 instruction. */
594 int opcode = inst >> 8;
595
596 switch (opcode)
597 {
598 case 0x00: /* nop */
599 /* Do nothing. */
600 break;
601 case 0x01: /* ldi.l (immediate) */
602 case 0x02: /* mov (register-to-register) */
603 {
604 int reg = (inst >> 4) & 0xf;
605 if (record_arch_list_add_reg (regcache, reg))
606 return -1;
607 }
608 break;
609 case 0x03: /* jsra */
610 {
611 regcache_raw_read (regcache,
612 MOXIE_SP_REGNUM, (gdb_byte *) & tmpu32);
613 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
614 4, byte_order);
615 if (record_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
616 || (record_arch_list_add_reg (regcache,
617 MOXIE_SP_REGNUM))
618 || record_arch_list_add_mem (tmpu32 - 12, 12))
619 return -1;
620 }
621 break;
622 case 0x04: /* ret */
623 {
624 if (record_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
625 || (record_arch_list_add_reg (regcache,
626 MOXIE_SP_REGNUM)))
627 return -1;
628 }
629 break;
630 case 0x05: /* add.l */
631 {
632 int reg = (inst >> 4) & 0xf;
633 if (record_arch_list_add_reg (regcache, reg))
634 return -1;
635 }
636 break;
637 case 0x06: /* push */
638 {
639 int reg = (inst >> 4) & 0xf;
640 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
641 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
642 4, byte_order);
643 if (record_arch_list_add_reg (regcache, reg)
644 || record_arch_list_add_mem (tmpu32 - 4, 4))
645 return -1;
646 }
647 break;
648 case 0x07: /* pop */
649 {
650 int a = (inst >> 4) & 0xf;
651 int b = inst & 0xf;
652 if (record_arch_list_add_reg (regcache, a)
653 || record_arch_list_add_reg (regcache, b))
654 return -1;
655 }
656 break;
657 case 0x08: /* lda.l */
658 {
659 int reg = (inst >> 4) & 0xf;
660 if (record_arch_list_add_reg (regcache, reg))
661 return -1;
662 }
663 break;
664 case 0x09: /* sta.l */
665 {
666 tmpu32 = (uint32_t) moxie_process_readu (addr+2, buf,
667 4, byte_order);
668 if (record_arch_list_add_mem (tmpu32, 4))
669 return -1;
670 }
671 break;
672 case 0x0a: /* ld.l (register indirect) */
673 {
674 int reg = (inst >> 4) & 0xf;
675 if (record_arch_list_add_reg (regcache, reg))
676 return -1;
677 }
678 break;
679 case 0x0b: /* st.l */
680 {
681 int reg = (inst >> 4) & 0xf;
682 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
683 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
684 4, byte_order);
685 if (record_arch_list_add_mem (tmpu32, 4))
686 return -1;
687 }
688 break;
689 case 0x0c: /* ldo.l */
690 {
691 int reg = (inst >> 4) & 0xf;
692 if (record_arch_list_add_reg (regcache, reg))
693 return -1;
694 }
695 break;
696 case 0x0d: /* sto.l */
697 {
698 int reg = (inst >> 4) & 0xf;
699 uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
700 byte_order);
701 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
702 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
703 4, byte_order);
704 tmpu32 += offset;
705 if (record_arch_list_add_mem (tmpu32, 4))
706 return -1;
707 }
708 break;
709 case 0x0e: /* cmp */
710 {
711 if (record_arch_list_add_reg (regcache, MOXIE_CC_REGNUM))
712 return -1;
713 }
714 break;
715 case 0x0f:
716 case 0x10:
717 case 0x11:
718 case 0x12:
719 case 0x13:
720 case 0x14:
721 case 0x15:
722 case 0x16:
723 case 0x17:
724 case 0x18:
725 {
726 /* Do nothing. */
727 break;
728 }
729 case 0x19: /* jsr */
730 {
731 regcache_raw_read (regcache,
732 MOXIE_SP_REGNUM, (gdb_byte *) & tmpu32);
733 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
734 4, byte_order);
735 if (record_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
736 || (record_arch_list_add_reg (regcache,
737 MOXIE_SP_REGNUM))
738 || record_arch_list_add_mem (tmpu32 - 12, 12))
739 return -1;
740 }
741 break;
742 case 0x1a: /* jmpa */
743 {
744 /* Do nothing. */
745 }
746 break;
747 case 0x1b: /* ldi.b (immediate) */
748 case 0x1c: /* ld.b (register indirect) */
749 case 0x1d: /* lda.b */
750 {
751 int reg = (inst >> 4) & 0xf;
752 if (record_arch_list_add_reg (regcache, reg))
753 return -1;
754 }
755 break;
756 case 0x1e: /* st.b */
757 {
758 int reg = (inst >> 4) & 0xf;
759 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
760 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
761 4, byte_order);
762 if (record_arch_list_add_mem (tmpu32, 1))
763 return -1;
764 }
765 break;
766 case 0x1f: /* sta.b */
767 {
768 tmpu32 = moxie_process_readu (addr+2, (char *) buf,
769 4, byte_order);
770 if (record_arch_list_add_mem (tmpu32, 1))
771 return -1;
772 }
773 break;
774 case 0x20: /* ldi.s (immediate) */
775 case 0x21: /* ld.s (register indirect) */
776 case 0x22: /* lda.s */
777 {
778 int reg = (inst >> 4) & 0xf;
779 if (record_arch_list_add_reg (regcache, reg))
780 return -1;
781 }
782 break;
783 case 0x23: /* st.s */
784 {
785 int reg = (inst >> 4) & 0xf;
786 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
787 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
788 4, byte_order);
789 if (record_arch_list_add_mem (tmpu32, 2))
790 return -1;
791 }
792 break;
793 case 0x24: /* sta.s */
794 {
795 tmpu32 = moxie_process_readu (addr+2, (char *) buf,
796 4, byte_order);
797 if (record_arch_list_add_mem (tmpu32, 2))
798 return -1;
799 }
800 break;
801 case 0x25: /* jmp */
802 {
803 /* Do nothing. */
804 }
805 break;
806 case 0x26: /* and */
807 case 0x27: /* lshr */
808 case 0x28: /* ashl */
809 case 0x29: /* sub.l */
810 case 0x2a: /* neg */
811 case 0x2b: /* or */
812 case 0x2c: /* not */
813 case 0x2d: /* ashr */
814 case 0x2e: /* xor */
815 case 0x2f: /* mul.l */
816 {
817 int reg = (inst >> 4) & 0xf;
818 if (record_arch_list_add_reg (regcache, reg))
819 return -1;
820 }
821 break;
822 case 0x30: /* swi */
823 {
824 /* We currently implement support for libgloss'
825 system calls. */
826
827 int inum = moxie_process_readu (addr+2, (char *) buf,
828 4, byte_order);
829
830 switch (inum)
831 {
832 case 0x1: /* SYS_exit */
833 {
834 /* Do nothing. */
835 }
836 break;
837 case 0x2: /* SYS_open */
838 {
839 if (record_arch_list_add_reg (regcache, RET1_REGNUM))
840 return -1;
841 }
842 break;
843 case 0x4: /* SYS_read */
844 {
845 uint32_t length, ptr;
846
847 /* Read buffer pointer is in $r1. */
848 regcache_raw_read (regcache, 3, (gdb_byte *) & ptr);
849 ptr = extract_unsigned_integer ((gdb_byte *) & ptr,
850 4, byte_order);
851
852 /* String length is at 0x12($fp). */
853 regcache_raw_read (regcache,
854 MOXIE_FP_REGNUM, (gdb_byte *) & tmpu32);
855 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
856 4, byte_order);
857 length = moxie_process_readu (tmpu32+20, (char *) buf,
858 4, byte_order);
859
860 if (record_arch_list_add_mem (ptr, length))
861 return -1;
862 }
863 break;
864 case 0x5: /* SYS_write */
865 {
866 if (record_arch_list_add_reg (regcache, RET1_REGNUM))
867 return -1;
868 }
869 break;
870 default:
871 break;
872 }
873 }
874 break;
875 case 0x31: /* div.l */
876 case 0x32: /* udiv.l */
877 case 0x33: /* mod.l */
878 case 0x34: /* umod.l */
879 {
880 int reg = (inst >> 4) & 0xf;
881 if (record_arch_list_add_reg (regcache, reg))
882 return -1;
883 }
884 break;
885 case 0x35: /* brk */
886 /* Do nothing. */
887 break;
888 case 0x36: /* ldo.b */
889 {
890 int reg = (inst >> 4) & 0xf;
891 if (record_arch_list_add_reg (regcache, reg))
892 return -1;
893 }
894 break;
895 case 0x37: /* sto.b */
896 {
897 int reg = (inst >> 4) & 0xf;
898 uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
899 byte_order);
900 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
901 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
902 4, byte_order);
903 tmpu32 += offset;
904 if (record_arch_list_add_mem (tmpu32, 1))
905 return -1;
906 }
907 break;
908 case 0x38: /* ldo.s */
909 {
910 int reg = (inst >> 4) & 0xf;
911 if (record_arch_list_add_reg (regcache, reg))
912 return -1;
913 }
914 break;
915 case 0x39: /* sto.s */
916 {
917 int reg = (inst >> 4) & 0xf;
918 uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
919 byte_order);
920 regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
921 tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32,
922 4, byte_order);
923 tmpu32 += offset;
924 if (record_arch_list_add_mem (tmpu32, 2))
925 return -1;
926 }
927 break;
928 default:
929 /* Do nothing. */
930 break;
931 }
932 }
933
934 if (record_arch_list_add_reg (regcache, MOXIE_PC_REGNUM))
935 return -1;
936 if (record_arch_list_add_end ())
937 return -1;
938 return 0;
939 }
940
941 /* Allocate and initialize the moxie gdbarch object. */
942
943 static struct gdbarch *
944 moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
945 {
946 struct gdbarch *gdbarch;
947 struct gdbarch_tdep *tdep;
948
949 /* If there is already a candidate, use it. */
950 arches = gdbarch_list_lookup_by_info (arches, &info);
951 if (arches != NULL)
952 return arches->gdbarch;
953
954 /* Allocate space for the new architecture. */
955 tdep = XMALLOC (struct gdbarch_tdep);
956 gdbarch = gdbarch_alloc (&info, tdep);
957
958 set_gdbarch_read_pc (gdbarch, moxie_read_pc);
959 set_gdbarch_write_pc (gdbarch, moxie_write_pc);
960 set_gdbarch_unwind_sp (gdbarch, moxie_unwind_sp);
961
962 set_gdbarch_num_regs (gdbarch, MOXIE_NUM_REGS);
963 set_gdbarch_sp_regnum (gdbarch, MOXIE_SP_REGNUM);
964 set_gdbarch_pc_regnum (gdbarch, MOXIE_PC_REGNUM);
965 set_gdbarch_register_name (gdbarch, moxie_register_name);
966 set_gdbarch_register_type (gdbarch, moxie_register_type);
967
968 set_gdbarch_return_value (gdbarch, moxie_return_value);
969
970 set_gdbarch_skip_prologue (gdbarch, moxie_skip_prologue);
971 set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
972 set_gdbarch_breakpoint_from_pc (gdbarch, moxie_breakpoint_from_pc);
973 set_gdbarch_frame_align (gdbarch, moxie_frame_align);
974
975 frame_base_set_default (gdbarch, &moxie_frame_base);
976
977 /* Methods for saving / extracting a dummy frame's ID. The ID's
978 stack address must match the SP value returned by
979 PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
980 set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
981
982 set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
983
984 set_gdbarch_print_insn (gdbarch, print_insn_moxie);
985
986 /* Hook in ABI-specific overrides, if they have been registered. */
987 gdbarch_init_osabi (info, gdbarch);
988
989 /* Hook in the default unwinders. */
990 frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
991
992 /* Support simple overlay manager. */
993 set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
994
995 /* Support reverse debugging. */
996 set_gdbarch_process_record (gdbarch, moxie_process_record);
997
998 return gdbarch;
999 }
1000
1001 /* Register this machine's init routine. */
1002
1003 void
1004 _initialize_moxie_tdep (void)
1005 {
1006 register_gdbarch_init (bfd_arch_moxie, moxie_gdbarch_init);
1007 }