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