GDB (API)
/home/stan/gdb/src/gdb/moxie-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for Moxie.
00002 
00003    Copyright (C) 2009-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "frame.h"
00022 #include "frame-unwind.h"
00023 #include "frame-base.h"
00024 #include "symtab.h"
00025 #include "gdbtypes.h"
00026 #include "gdbcmd.h"
00027 #include "gdbcore.h"
00028 #include "gdb_string.h"
00029 #include "value.h"
00030 #include "inferior.h"
00031 #include "symfile.h"
00032 #include "objfiles.h"
00033 #include "osabi.h"
00034 #include "language.h"
00035 #include "arch-utils.h"
00036 #include "regcache.h"
00037 #include "trad-frame.h"
00038 #include "dis-asm.h"
00039 #include "record.h"
00040 #include "record-full.h"
00041 
00042 #include "gdb_assert.h"
00043 
00044 #include "moxie-tdep.h"
00045 
00046 /* Local functions.  */
00047 
00048 extern void _initialize_moxie_tdep (void);
00049 
00050 /* Use an invalid address value as 'not available' marker.  */
00051 enum { REG_UNAVAIL = (CORE_ADDR) -1 };
00052 
00053 struct moxie_frame_cache
00054 {
00055   /* Base address.  */
00056   CORE_ADDR base;
00057   CORE_ADDR pc;
00058   LONGEST framesize;
00059   CORE_ADDR saved_regs[MOXIE_NUM_REGS];
00060   CORE_ADDR saved_sp;
00061 };
00062 
00063 /* Implement the "frame_align" gdbarch method.  */
00064 
00065 static CORE_ADDR
00066 moxie_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
00067 {
00068   /* Align to the size of an instruction (so that they can safely be
00069      pushed onto the stack.  */
00070   return sp & ~1;
00071 }
00072 
00073 /* Implement the "breakpoint_from_pc" gdbarch method.  */
00074 
00075 static const unsigned char *
00076 moxie_breakpoint_from_pc (struct gdbarch *gdbarch,
00077                           CORE_ADDR *pcptr, int *lenptr)
00078 {
00079   static unsigned char breakpoint[] = { 0x35, 0x00 };
00080 
00081   *lenptr = sizeof (breakpoint);
00082   return breakpoint;
00083 }
00084 
00085 /* Moxie register names.  */
00086 
00087 char *moxie_register_names[] = {
00088   "$fp",  "$sp",  "$r0",  "$r1",  "$r2",
00089   "$r3",  "$r4",  "$r5", "$r6", "$r7",
00090   "$r8", "$r9", "$r10", "$r11", "$r12",
00091   "$r13", "$pc", "$cc" };
00092 
00093 /* Implement the "register_name" gdbarch method.  */
00094 
00095 static const char *
00096 moxie_register_name (struct gdbarch *gdbarch, int reg_nr)
00097 {
00098   if (reg_nr < 0)
00099     return NULL;
00100   if (reg_nr >= MOXIE_NUM_REGS)
00101     return NULL;
00102   return moxie_register_names[reg_nr];
00103 }
00104 
00105 /* Implement the "register_type" gdbarch method.  */
00106 
00107 static struct type *
00108 moxie_register_type (struct gdbarch *gdbarch, int reg_nr)
00109 {
00110   if (reg_nr == MOXIE_PC_REGNUM)
00111     return  builtin_type (gdbarch)->builtin_func_ptr;
00112   else if (reg_nr == MOXIE_SP_REGNUM || reg_nr == MOXIE_FP_REGNUM)
00113     return builtin_type (gdbarch)->builtin_data_ptr;
00114   else
00115     return builtin_type (gdbarch)->builtin_int32;
00116 }
00117 
00118 /* Write into appropriate registers a function return value
00119    of type TYPE, given in virtual format.  */
00120 
00121 static void
00122 moxie_store_return_value (struct type *type, struct regcache *regcache,
00123                          const void *valbuf)
00124 {
00125   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00126   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00127   CORE_ADDR regval;
00128   int len = TYPE_LENGTH (type);
00129 
00130   /* Things always get returned in RET1_REGNUM, RET2_REGNUM.  */
00131   regval = extract_unsigned_integer (valbuf, len > 4 ? 4 : len, byte_order);
00132   regcache_cooked_write_unsigned (regcache, RET1_REGNUM, regval);
00133   if (len > 4)
00134     {
00135       regval = extract_unsigned_integer ((gdb_byte *) valbuf + 4,
00136                                          len - 4, byte_order);
00137       regcache_cooked_write_unsigned (regcache, RET1_REGNUM + 1, regval);
00138     }
00139 }
00140 
00141 /* Decode the instructions within the given address range.  Decide
00142    when we must have reached the end of the function prologue.  If a
00143    frame_info pointer is provided, fill in its saved_regs etc.
00144 
00145    Returns the address of the first instruction after the prologue.  */
00146 
00147 static CORE_ADDR
00148 moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
00149                         struct moxie_frame_cache *cache,
00150                         struct gdbarch *gdbarch)
00151 {
00152   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00153   CORE_ADDR next_addr;
00154   ULONGEST inst, inst2;
00155   LONGEST offset;
00156   int regnum;
00157 
00158   /* Record where the jsra instruction saves the PC and FP.  */
00159   cache->saved_regs[MOXIE_PC_REGNUM] = -4;
00160   cache->saved_regs[MOXIE_FP_REGNUM] = 0;
00161   cache->framesize = 0;
00162 
00163   if (start_addr >= end_addr)
00164     return end_addr;
00165 
00166   for (next_addr = start_addr; next_addr < end_addr; )
00167     {
00168       inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
00169 
00170       /* Match "push $sp $rN" where N is between 0 and 13 inclusive.  */
00171       if (inst >= 0x0612 && inst <= 0x061f)
00172         {
00173           regnum = inst & 0x000f;
00174           cache->framesize += 4;
00175           cache->saved_regs[regnum] = cache->framesize;
00176           next_addr += 2;
00177         }
00178       else
00179         break;
00180     }
00181 
00182   inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
00183 
00184   /* Optional stack allocation for args and local vars <= 4
00185      byte.  */
00186   if (inst == 0x01e0)          /* ldi.l $r12, X */
00187     {
00188       offset = read_memory_integer (next_addr + 2, 4, byte_order);
00189       inst2 = read_memory_unsigned_integer (next_addr + 6, 2, byte_order);
00190       
00191       if (inst2 == 0x291e)     /* sub.l $sp, $r12 */
00192         {
00193           cache->framesize += offset;
00194         }
00195       
00196       return (next_addr + 8);
00197     }
00198   else if ((inst & 0xff00) == 0x9100)   /* dec $sp, X */
00199     {
00200       cache->framesize += (inst & 0x00ff);
00201       next_addr += 2;
00202 
00203       while (next_addr < end_addr)
00204         {
00205           inst = read_memory_unsigned_integer (next_addr, 2, byte_order);
00206           if ((inst & 0xff00) != 0x9100) /* no more dec $sp, X */
00207             break;
00208           cache->framesize += (inst & 0x00ff);
00209           next_addr += 2;
00210         }
00211     }
00212 
00213   return next_addr;
00214 }
00215 
00216 /* Find the end of function prologue.  */
00217 
00218 static CORE_ADDR
00219 moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
00220 {
00221   CORE_ADDR func_addr = 0, func_end = 0;
00222   const char *func_name;
00223 
00224   /* See if we can determine the end of the prologue via the symbol table.
00225      If so, then return either PC, or the PC after the prologue, whichever
00226      is greater.  */
00227   if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
00228     {
00229       CORE_ADDR post_prologue_pc
00230         = skip_prologue_using_sal (gdbarch, func_addr);
00231       if (post_prologue_pc != 0)
00232         return max (pc, post_prologue_pc);
00233       else
00234         {
00235           /* Can't determine prologue from the symbol table, need to examine
00236              instructions.  */
00237           struct symtab_and_line sal;
00238           struct symbol *sym;
00239           struct moxie_frame_cache cache;
00240           CORE_ADDR plg_end;
00241           
00242           memset (&cache, 0, sizeof cache);
00243           
00244           plg_end = moxie_analyze_prologue (func_addr, 
00245                                             func_end, &cache, gdbarch);
00246           /* Found a function.  */
00247           sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
00248           /* Don't use line number debug info for assembly source
00249              files.  */
00250           if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
00251             {
00252               sal = find_pc_line (func_addr, 0);
00253               if (sal.end && sal.end < func_end)
00254                 {
00255                   /* Found a line number, use it as end of
00256                      prologue.  */
00257                   return sal.end;
00258                 }
00259             }
00260           /* No useable line symbol.  Use result of prologue parsing
00261              method.  */
00262           return plg_end;
00263         }
00264     }
00265 
00266   /* No function symbol -- just return the PC.  */
00267   return (CORE_ADDR) pc;
00268 }
00269 
00270 struct moxie_unwind_cache
00271 {
00272   /* The previous frame's inner most stack address.  Used as this
00273      frame ID's stack_addr.  */
00274   CORE_ADDR prev_sp;
00275   /* The frame's base, optionally used by the high-level debug info.  */
00276   CORE_ADDR base;
00277   int size;
00278   /* How far the SP and r13 (FP) have been offset from the start of
00279      the stack frame (as defined by the previous frame's stack
00280      pointer).  */
00281   LONGEST sp_offset;
00282   LONGEST r13_offset;
00283   int uses_frame;
00284   /* Table indicating the location of each and every register.  */
00285   struct trad_frame_saved_reg *saved_regs;
00286 };
00287 
00288 /* Implement the "read_pc" gdbarch method.  */
00289 
00290 static CORE_ADDR
00291 moxie_read_pc (struct regcache *regcache)
00292 {
00293   ULONGEST pc;
00294 
00295   regcache_cooked_read_unsigned (regcache, MOXIE_PC_REGNUM, &pc);
00296   return pc;
00297 }
00298 
00299 /* Implement the "write_pc" gdbarch method.  */
00300 
00301 static void
00302 moxie_write_pc (struct regcache *regcache, CORE_ADDR val)
00303 {
00304   regcache_cooked_write_unsigned (regcache, MOXIE_PC_REGNUM, val);
00305 }
00306 
00307 /* Implement the "unwind_sp" gdbarch method.  */
00308 
00309 static CORE_ADDR
00310 moxie_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
00311 {
00312   return frame_unwind_register_unsigned (next_frame, MOXIE_SP_REGNUM);
00313 }
00314 
00315 /* Given a return value in `regbuf' with a type `valtype', 
00316    extract and copy its value into `valbuf'.  */
00317 
00318 static void
00319 moxie_extract_return_value (struct type *type, struct regcache *regcache,
00320                            void *dst)
00321 {
00322   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00323   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00324   bfd_byte *valbuf = dst;
00325   int len = TYPE_LENGTH (type);
00326   ULONGEST tmp;
00327 
00328   /* By using store_unsigned_integer we avoid having to do
00329      anything special for small big-endian values.  */
00330   regcache_cooked_read_unsigned (regcache, RET1_REGNUM, &tmp);
00331   store_unsigned_integer (valbuf, (len > 4 ? len - 4 : len), byte_order, tmp);
00332 
00333   /* Ignore return values more than 8 bytes in size because the moxie
00334      returns anything more than 8 bytes in the stack.  */
00335   if (len > 4)
00336     {
00337       regcache_cooked_read_unsigned (regcache, RET1_REGNUM + 1, &tmp);
00338       store_unsigned_integer (valbuf + len - 4, 4, byte_order, tmp);
00339     }
00340 }
00341 
00342 /* Implement the "return_value" gdbarch method.  */
00343 
00344 static enum return_value_convention
00345 moxie_return_value (struct gdbarch *gdbarch, struct value *function,
00346                    struct type *valtype, struct regcache *regcache,
00347                    gdb_byte *readbuf, const gdb_byte *writebuf)
00348 {
00349   if (TYPE_LENGTH (valtype) > 8)
00350     return RETURN_VALUE_STRUCT_CONVENTION;
00351   else
00352     {
00353       if (readbuf != NULL)
00354         moxie_extract_return_value (valtype, regcache, readbuf);
00355       if (writebuf != NULL)
00356         moxie_store_return_value (valtype, regcache, writebuf);
00357       return RETURN_VALUE_REGISTER_CONVENTION;
00358     }
00359 }
00360 
00361 /* Allocate and initialize a moxie_frame_cache object.  */
00362 
00363 static struct moxie_frame_cache *
00364 moxie_alloc_frame_cache (void)
00365 {
00366   struct moxie_frame_cache *cache;
00367   int i;
00368 
00369   cache = FRAME_OBSTACK_ZALLOC (struct moxie_frame_cache);
00370 
00371   cache->base = 0;
00372   cache->saved_sp = 0;
00373   cache->pc = 0;
00374   cache->framesize = 0;
00375   for (i = 0; i < MOXIE_NUM_REGS; ++i)
00376     cache->saved_regs[i] = REG_UNAVAIL;
00377 
00378   return cache;
00379 }
00380 
00381 /* Populate a moxie_frame_cache object for this_frame.  */
00382 
00383 static struct moxie_frame_cache *
00384 moxie_frame_cache (struct frame_info *this_frame, void **this_cache)
00385 {
00386   struct moxie_frame_cache *cache;
00387   CORE_ADDR current_pc;
00388   int i;
00389 
00390   if (*this_cache)
00391     return *this_cache;
00392 
00393   cache = moxie_alloc_frame_cache ();
00394   *this_cache = cache;
00395 
00396   cache->base = get_frame_register_unsigned (this_frame, MOXIE_FP_REGNUM);
00397   if (cache->base == 0)
00398     return cache;
00399 
00400   cache->pc = get_frame_func (this_frame);
00401   current_pc = get_frame_pc (this_frame);
00402   if (cache->pc)
00403     {
00404       struct gdbarch *gdbarch = get_frame_arch (this_frame);
00405       moxie_analyze_prologue (cache->pc, current_pc, cache, gdbarch);
00406     }
00407 
00408   cache->saved_sp = cache->base - cache->framesize;
00409 
00410   for (i = 0; i < MOXIE_NUM_REGS; ++i)
00411     if (cache->saved_regs[i] != REG_UNAVAIL)
00412       cache->saved_regs[i] = cache->base - cache->saved_regs[i];
00413 
00414   return cache;
00415 }
00416 
00417 /* Implement the "unwind_pc" gdbarch method.  */
00418 
00419 static CORE_ADDR
00420 moxie_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
00421 {
00422   return frame_unwind_register_unsigned (next_frame, MOXIE_PC_REGNUM);
00423 }
00424 
00425 /* Given a GDB frame, determine the address of the calling function's
00426    frame.  This will be used to create a new GDB frame struct.  */
00427 
00428 static void
00429 moxie_frame_this_id (struct frame_info *this_frame,
00430                     void **this_prologue_cache, struct frame_id *this_id)
00431 {
00432   struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
00433                                                    this_prologue_cache);
00434 
00435   /* This marks the outermost frame.  */
00436   if (cache->base == 0)
00437     return;
00438 
00439   *this_id = frame_id_build (cache->saved_sp, cache->pc);
00440 }
00441 
00442 /* Get the value of register regnum in the previous stack frame.  */
00443 
00444 static struct value *
00445 moxie_frame_prev_register (struct frame_info *this_frame,
00446                           void **this_prologue_cache, int regnum)
00447 {
00448   struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
00449                                                    this_prologue_cache);
00450 
00451   gdb_assert (regnum >= 0);
00452 
00453   if (regnum == MOXIE_SP_REGNUM && cache->saved_sp)
00454     return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
00455 
00456   if (regnum < MOXIE_NUM_REGS && cache->saved_regs[regnum] != REG_UNAVAIL)
00457     return frame_unwind_got_memory (this_frame, regnum,
00458                                     cache->saved_regs[regnum]);
00459 
00460   return frame_unwind_got_register (this_frame, regnum, regnum);
00461 }
00462 
00463 static const struct frame_unwind moxie_frame_unwind = {
00464   NORMAL_FRAME,
00465   default_frame_unwind_stop_reason,
00466   moxie_frame_this_id,
00467   moxie_frame_prev_register,
00468   NULL,
00469   default_frame_sniffer
00470 };
00471 
00472 /* Return the base address of this_frame.  */
00473 
00474 static CORE_ADDR
00475 moxie_frame_base_address (struct frame_info *this_frame, void **this_cache)
00476 {
00477   struct moxie_frame_cache *cache = moxie_frame_cache (this_frame,
00478                                                        this_cache);
00479 
00480   return cache->base;
00481 }
00482 
00483 static const struct frame_base moxie_frame_base = {
00484   &moxie_frame_unwind,
00485   moxie_frame_base_address,
00486   moxie_frame_base_address,
00487   moxie_frame_base_address
00488 };
00489 
00490 static struct frame_id
00491 moxie_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
00492 {
00493   CORE_ADDR sp = get_frame_register_unsigned (this_frame, MOXIE_SP_REGNUM);
00494 
00495   return frame_id_build (sp, get_frame_pc (this_frame));
00496 }
00497 
00498 /* Read an unsigned integer from the inferior, and adjust
00499    endianess.  */
00500 static ULONGEST
00501 moxie_process_readu (CORE_ADDR addr, gdb_byte *buf,
00502                      int length, enum bfd_endian byte_order)
00503 {
00504   if (target_read_memory (addr, buf, length))
00505     {
00506       if (record_debug)
00507         printf_unfiltered (_("Process record: error reading memory at "
00508                              "addr 0x%s len = %d.\n"),
00509                            paddress (target_gdbarch (), addr), length);
00510       return -1;
00511     }
00512 
00513   return extract_unsigned_integer (buf, length, byte_order);
00514 }
00515 
00516 /* Parse the current instruction and record the values of the registers and
00517    memory that will be changed in current instruction to "record_arch_list".
00518    Return -1 if something wrong.  */
00519 
00520 static int
00521 moxie_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
00522                       CORE_ADDR addr)
00523 {
00524   gdb_byte buf[4];
00525   uint16_t inst;
00526   uint32_t tmpu32;
00527   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00528 
00529   if (record_debug > 1)
00530     fprintf_unfiltered (gdb_stdlog, "Process record: moxie_process_record "
00531                                     "addr = 0x%s\n",
00532                         paddress (target_gdbarch (), addr));
00533 
00534   inst = (uint16_t) moxie_process_readu (addr, buf, 2, byte_order);
00535 
00536   /* Decode instruction.  */
00537   if (inst & (1 << 15))
00538     {
00539       if (inst & (1 << 14))
00540         {
00541           /* This is a Form 3 instruction.  */
00542           int opcode = (inst >> 10 & 0xf);
00543           
00544           switch (opcode)
00545             {
00546             case 0x00: /* beq */
00547             case 0x01: /* bne */
00548             case 0x02: /* blt */
00549             case 0x03: /* bgt */
00550             case 0x04: /* bltu */
00551             case 0x05: /* bgtu */
00552             case 0x06: /* bge */
00553             case 0x07: /* ble */
00554             case 0x08: /* bgeu */
00555             case 0x09: /* bleu */
00556               /* Do nothing.  */
00557               break;
00558             default:
00559               {
00560                 /* Do nothing.  */
00561                 break;
00562               }
00563             }
00564         }
00565       else
00566         {
00567           /* This is a Form 2 instruction.  */
00568           int opcode = (inst >> 12 & 0x3);
00569           switch (opcode)
00570             {
00571             case 0x00: /* inc */
00572             case 0x01: /* dec */
00573             case 0x02: /* gsr */
00574               {
00575                 int reg = (inst >> 8) & 0xf;
00576                 if (record_full_arch_list_add_reg (regcache, reg))
00577                   return -1;
00578               }
00579               break;
00580             case 0x03: /* ssr */
00581               {
00582                 /* Do nothing until GDB learns about moxie's special
00583                    registers.  */
00584               }
00585               break;
00586             default:
00587               /* Do nothing.  */
00588               break;
00589             }
00590         }
00591     }
00592   else
00593     {
00594       /* This is a Form 1 instruction.  */
00595       int opcode = inst >> 8;
00596 
00597       switch (opcode)
00598         {
00599         case 0x00: /* nop */
00600           /* Do nothing.  */
00601           break;
00602         case 0x01: /* ldi.l (immediate) */
00603         case 0x02: /* mov (register-to-register) */
00604           {
00605             int reg = (inst >> 4) & 0xf;
00606             if (record_full_arch_list_add_reg (regcache, reg))
00607               return -1;
00608           }
00609           break;
00610         case 0x03: /* jsra */
00611           {
00612             regcache_raw_read (regcache, 
00613                                MOXIE_SP_REGNUM, (gdb_byte *) & tmpu32);
00614             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00615                                                4, byte_order);
00616             if (record_full_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
00617                 || (record_full_arch_list_add_reg (regcache,
00618                                                    MOXIE_SP_REGNUM))
00619                 || record_full_arch_list_add_mem (tmpu32 - 12, 12))
00620               return -1;
00621           }
00622           break;
00623         case 0x04: /* ret */
00624           {
00625             if (record_full_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
00626                 || (record_full_arch_list_add_reg (regcache,
00627                                                    MOXIE_SP_REGNUM)))
00628               return -1;
00629           }
00630           break;
00631         case 0x05: /* add.l */
00632           {
00633             int reg = (inst >> 4) & 0xf;
00634             if (record_full_arch_list_add_reg (regcache, reg))
00635               return -1;
00636           }
00637           break;
00638         case 0x06: /* push */
00639           {
00640             int reg = (inst >> 4) & 0xf;
00641             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00642             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00643                                                4, byte_order);
00644             if (record_full_arch_list_add_reg (regcache, reg)
00645                 || record_full_arch_list_add_mem (tmpu32 - 4, 4))
00646               return -1;
00647           }
00648           break;
00649         case 0x07: /* pop */
00650           {
00651             int a = (inst >> 4) & 0xf;
00652             int b = inst & 0xf;
00653             if (record_full_arch_list_add_reg (regcache, a)
00654                 || record_full_arch_list_add_reg (regcache, b))
00655               return -1;
00656           }
00657           break;
00658         case 0x08: /* lda.l */
00659           {
00660             int reg = (inst >> 4) & 0xf;
00661             if (record_full_arch_list_add_reg (regcache, reg))
00662               return -1;
00663           }
00664           break;
00665         case 0x09: /* sta.l */
00666           {
00667             tmpu32 = (uint32_t) moxie_process_readu (addr+2, buf, 
00668                                                      4, byte_order);
00669             if (record_full_arch_list_add_mem (tmpu32, 4))
00670               return -1;
00671           }
00672           break;
00673         case 0x0a: /* ld.l (register indirect) */
00674           {
00675             int reg = (inst >> 4) & 0xf;
00676             if (record_full_arch_list_add_reg (regcache, reg))
00677               return -1;
00678           }
00679           break;
00680         case 0x0b: /* st.l */
00681           {
00682             int reg = (inst >> 4) & 0xf;
00683             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00684             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00685                                                4, byte_order);
00686             if (record_full_arch_list_add_mem (tmpu32, 4))
00687               return -1;
00688           }
00689           break;
00690         case 0x0c: /* ldo.l */
00691           {
00692             int reg = (inst >> 4) & 0xf;
00693             if (record_full_arch_list_add_reg (regcache, reg))
00694               return -1;
00695           }
00696           break;
00697         case 0x0d: /* sto.l */
00698           {
00699             int reg = (inst >> 4) & 0xf;
00700             uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
00701                                                               byte_order);
00702             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00703             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00704                                                4, byte_order);
00705             tmpu32 += offset;
00706             if (record_full_arch_list_add_mem (tmpu32, 4))
00707               return -1;
00708           }
00709           break;
00710         case 0x0e: /* cmp */
00711           {
00712             if (record_full_arch_list_add_reg (regcache, MOXIE_CC_REGNUM))
00713               return -1;
00714           }
00715           break;
00716         case 0x0f:
00717         case 0x10:
00718         case 0x11:
00719         case 0x12:
00720         case 0x13:
00721         case 0x14:
00722         case 0x15:
00723         case 0x16:
00724         case 0x17:
00725         case 0x18:
00726           {
00727             /* Do nothing.  */
00728             break;
00729           }
00730         case 0x19: /* jsr */
00731           {
00732             regcache_raw_read (regcache, 
00733                                MOXIE_SP_REGNUM, (gdb_byte *) & tmpu32);
00734             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00735                                                4, byte_order);
00736             if (record_full_arch_list_add_reg (regcache, MOXIE_FP_REGNUM)
00737                 || (record_full_arch_list_add_reg (regcache,
00738                                                    MOXIE_SP_REGNUM))
00739                 || record_full_arch_list_add_mem (tmpu32 - 12, 12))
00740               return -1;
00741           }
00742           break;
00743         case 0x1a: /* jmpa */
00744           {
00745             /* Do nothing.  */
00746           }
00747           break;
00748         case 0x1b: /* ldi.b (immediate) */
00749         case 0x1c: /* ld.b (register indirect) */
00750         case 0x1d: /* lda.b */
00751           {
00752             int reg = (inst >> 4) & 0xf;
00753             if (record_full_arch_list_add_reg (regcache, reg))
00754               return -1;
00755           }
00756           break;
00757         case 0x1e: /* st.b */
00758           {
00759             int reg = (inst >> 4) & 0xf;
00760             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00761             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00762                                                4, byte_order);
00763             if (record_full_arch_list_add_mem (tmpu32, 1))
00764               return -1;
00765           }
00766           break;
00767         case 0x1f: /* sta.b */
00768           {
00769             tmpu32 = moxie_process_readu (addr+2, buf, 4, byte_order);
00770             if (record_full_arch_list_add_mem (tmpu32, 1))
00771               return -1;
00772           }
00773           break;
00774         case 0x20: /* ldi.s (immediate) */
00775         case 0x21: /* ld.s (register indirect) */
00776         case 0x22: /* lda.s */
00777           {
00778             int reg = (inst >> 4) & 0xf;
00779             if (record_full_arch_list_add_reg (regcache, reg))
00780               return -1;
00781           }
00782           break;
00783         case 0x23: /* st.s */
00784           {
00785             int reg = (inst >> 4) & 0xf;
00786             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00787             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00788                                                4, byte_order);
00789             if (record_full_arch_list_add_mem (tmpu32, 2))
00790               return -1;
00791           }
00792           break;
00793         case 0x24: /* sta.s */
00794           {
00795             tmpu32 = moxie_process_readu (addr+2, buf, 4, byte_order);
00796             if (record_full_arch_list_add_mem (tmpu32, 2))
00797               return -1;
00798           }
00799           break;
00800         case 0x25: /* jmp */
00801           {
00802             /* Do nothing.  */
00803           }
00804           break;
00805         case 0x26: /* and */
00806         case 0x27: /* lshr */
00807         case 0x28: /* ashl */
00808         case 0x29: /* sub.l */
00809         case 0x2a: /* neg */
00810         case 0x2b: /* or */
00811         case 0x2c: /* not */
00812         case 0x2d: /* ashr */
00813         case 0x2e: /* xor */
00814         case 0x2f: /* mul.l */
00815           {
00816             int reg = (inst >> 4) & 0xf;
00817             if (record_full_arch_list_add_reg (regcache, reg))
00818               return -1;
00819           }
00820           break;
00821         case 0x30: /* swi */
00822           {
00823             /* We currently implement support for libgloss' 
00824                system calls.  */
00825 
00826             int inum = moxie_process_readu (addr+2, buf, 4, byte_order);
00827 
00828             switch (inum)
00829               {
00830               case 0x1: /* SYS_exit */
00831                 {
00832                   /* Do nothing.  */
00833                 }
00834                 break;
00835               case 0x2: /* SYS_open */
00836                 {
00837                   if (record_full_arch_list_add_reg (regcache, RET1_REGNUM))
00838                     return -1;
00839                 }
00840                 break;
00841               case 0x4: /* SYS_read */
00842                 {
00843                   uint32_t length, ptr;
00844 
00845                   /* Read buffer pointer is in $r1.  */
00846                   regcache_raw_read (regcache, 3, (gdb_byte *) & ptr);
00847                   ptr = extract_unsigned_integer ((gdb_byte *) & ptr, 
00848                                                   4, byte_order);
00849 
00850                   /* String length is at 0x12($fp).  */
00851                   regcache_raw_read (regcache, 
00852                                      MOXIE_FP_REGNUM, (gdb_byte *) & tmpu32);
00853                   tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00854                                                      4, byte_order);
00855                   length = moxie_process_readu (tmpu32+20, buf, 4, byte_order);
00856 
00857                   if (record_full_arch_list_add_mem (ptr, length))
00858                     return -1;
00859                 }
00860                 break;
00861               case 0x5: /* SYS_write */
00862                 {
00863                   if (record_full_arch_list_add_reg (regcache, RET1_REGNUM))
00864                     return -1;
00865                 }
00866                 break;
00867               default:
00868                 break;
00869               }
00870           }
00871           break;
00872         case 0x31: /* div.l */
00873         case 0x32: /* udiv.l */
00874         case 0x33: /* mod.l */
00875         case 0x34: /* umod.l */
00876           {
00877             int reg = (inst >> 4) & 0xf;
00878             if (record_full_arch_list_add_reg (regcache, reg))
00879               return -1;
00880           }
00881           break;
00882         case 0x35: /* brk */
00883           /* Do nothing.  */
00884           break;
00885         case 0x36: /* ldo.b */
00886           {
00887             int reg = (inst >> 4) & 0xf;
00888             if (record_full_arch_list_add_reg (regcache, reg))
00889               return -1;
00890           }
00891           break;
00892         case 0x37: /* sto.b */
00893           {
00894             int reg = (inst >> 4) & 0xf;
00895             uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
00896                                                               byte_order);
00897             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00898             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00899                                                4, byte_order);
00900             tmpu32 += offset;
00901             if (record_full_arch_list_add_mem (tmpu32, 1))
00902               return -1;
00903           }
00904           break;
00905         case 0x38: /* ldo.s */
00906           {
00907             int reg = (inst >> 4) & 0xf;
00908             if (record_full_arch_list_add_reg (regcache, reg))
00909               return -1;
00910           }
00911           break;
00912         case 0x39: /* sto.s */
00913           {
00914             int reg = (inst >> 4) & 0xf;
00915             uint32_t offset = (uint32_t) moxie_process_readu (addr+2, buf, 4,
00916                                                               byte_order);
00917             regcache_raw_read (regcache, reg, (gdb_byte *) & tmpu32);
00918             tmpu32 = extract_unsigned_integer ((gdb_byte *) & tmpu32, 
00919                                                4, byte_order);
00920             tmpu32 += offset;
00921             if (record_full_arch_list_add_mem (tmpu32, 2))
00922               return -1;
00923           }
00924           break;
00925         default:
00926           /* Do nothing.  */
00927           break;
00928         }
00929     }
00930 
00931   if (record_full_arch_list_add_reg (regcache, MOXIE_PC_REGNUM))
00932     return -1;
00933   if (record_full_arch_list_add_end ())
00934     return -1;
00935   return 0;
00936 }
00937 
00938 /* Allocate and initialize the moxie gdbarch object.  */
00939 
00940 static struct gdbarch *
00941 moxie_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
00942 {
00943   struct gdbarch *gdbarch;
00944   struct gdbarch_tdep *tdep;
00945 
00946   /* If there is already a candidate, use it.  */
00947   arches = gdbarch_list_lookup_by_info (arches, &info);
00948   if (arches != NULL)
00949     return arches->gdbarch;
00950 
00951   /* Allocate space for the new architecture.  */
00952   tdep = XMALLOC (struct gdbarch_tdep);
00953   gdbarch = gdbarch_alloc (&info, tdep);
00954 
00955   set_gdbarch_read_pc (gdbarch, moxie_read_pc);
00956   set_gdbarch_write_pc (gdbarch, moxie_write_pc);
00957   set_gdbarch_unwind_sp (gdbarch, moxie_unwind_sp);
00958 
00959   set_gdbarch_num_regs (gdbarch, MOXIE_NUM_REGS);
00960   set_gdbarch_sp_regnum (gdbarch, MOXIE_SP_REGNUM);
00961   set_gdbarch_pc_regnum (gdbarch, MOXIE_PC_REGNUM);
00962   set_gdbarch_register_name (gdbarch, moxie_register_name);
00963   set_gdbarch_register_type (gdbarch, moxie_register_type);
00964 
00965   set_gdbarch_return_value (gdbarch, moxie_return_value);
00966 
00967   set_gdbarch_skip_prologue (gdbarch, moxie_skip_prologue);
00968   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
00969   set_gdbarch_breakpoint_from_pc (gdbarch, moxie_breakpoint_from_pc);
00970   set_gdbarch_frame_align (gdbarch, moxie_frame_align);
00971 
00972   frame_base_set_default (gdbarch, &moxie_frame_base);
00973 
00974   /* Methods for saving / extracting a dummy frame's ID.  The ID's
00975      stack address must match the SP value returned by
00976      PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos.  */
00977   set_gdbarch_dummy_id (gdbarch, moxie_dummy_id);
00978 
00979   set_gdbarch_unwind_pc (gdbarch, moxie_unwind_pc);
00980 
00981   set_gdbarch_print_insn (gdbarch, print_insn_moxie);
00982 
00983   /* Hook in ABI-specific overrides, if they have been registered.  */
00984   gdbarch_init_osabi (info, gdbarch);
00985 
00986   /* Hook in the default unwinders.  */
00987   frame_unwind_append_unwinder (gdbarch, &moxie_frame_unwind);
00988 
00989   /* Support simple overlay manager.  */
00990   set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
00991 
00992   /* Support reverse debugging.  */
00993   set_gdbarch_process_record (gdbarch, moxie_process_record);
00994 
00995   return gdbarch;
00996 }
00997 
00998 /* Register this machine's init routine.  */
00999 
01000 void
01001 _initialize_moxie_tdep (void)
01002 {
01003   register_gdbarch_init (bfd_arch_moxie, moxie_gdbarch_init);
01004 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines