home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / i386m3-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-26  |  11.1 KB  |  422 lines

  1. /* Low level interface to I386 running mach 3.0.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "defs.h"
  21. #include "inferior.h"
  22. #include "floatformat.h"
  23.  
  24. #include <stdio.h>
  25.  
  26. #include <mach.h>
  27. #include <mach/message.h>
  28. #include <mach/exception.h>
  29. #include <mach_error.h>
  30.  
  31. /* Hmmm... Should this not be here?
  32.  * Now for i386_float_info() target_has_execution
  33.  */
  34. #include <target.h>
  35.  
  36. /* This mess is duplicated in bfd/i386mach3.h
  37.  *
  38.  * This is an ugly way to hack around the incorrect
  39.  * definition of UPAGES in i386/machparam.h.
  40.  *
  41.  * The definition should specify the size reserved
  42.  * for "struct user" in core files in PAGES,
  43.  * but instead it gives it in 512-byte core-clicks
  44.  * for i386 and i860.
  45.  */
  46. #include <sys/param.h>
  47. #if UPAGES == 16
  48. #define UAREA_SIZE ctob(UPAGES)
  49. #elif UPAGES == 2
  50. #define UAREA_SIZE (NBPG*UPAGES)
  51. #else
  52. FIXME!! UPAGES is neither 2 nor 16
  53. #endif
  54.  
  55. /* @@@ Should move print_387_status() to i387-tdep.c */
  56. extern void print_387_control_word ();        /* i387-tdep.h */
  57. extern void print_387_status_word ();
  58.  
  59. #define private static
  60.  
  61.  
  62. /* Find offsets to thread states at compile time.
  63.  * If your compiler does not grok this, calculate offsets
  64.  * offsets yourself and use them (or get a compatible compiler :-)
  65.  */
  66.  
  67. #define  REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
  68.  
  69. /* at reg_offset[i] is the offset to the i386_thread_state
  70.  * location where the gdb registers[i] is stored.
  71.  */
  72.  
  73. static int reg_offset[] = 
  74. {
  75.   REG_OFFSET(eax),  REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
  76.   REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
  77.   REG_OFFSET(eip),  REG_OFFSET(efl), REG_OFFSET(cs),  REG_OFFSET(ss),
  78.   REG_OFFSET(ds),   REG_OFFSET(es),  REG_OFFSET(fs),  REG_OFFSET(gs)
  79. };
  80.  
  81. #define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
  82.  
  83. /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
  84.  * Caller knows that the regs handled in one transaction are of same size.
  85.  */
  86. #define FETCH_REGS(state, regnum, count) \
  87.   memcpy (®isters[REGISTER_BYTE (regnum)], \
  88.       REG_ADDRESS (state, regnum), \
  89.       count*REGISTER_SIZE)
  90.  
  91. /* Store COUNT contiguous registers to thread STATE starting from REGNUM */
  92. #define STORE_REGS(state, regnum, count) \
  93.   memcpy (REG_ADDRESS (state, regnum), \
  94.       ®isters[REGISTER_BYTE (regnum)], \
  95.       count*REGISTER_SIZE)
  96.  
  97. /*
  98.  * Fetch inferiors registers for gdb.
  99.  * REGNO specifies which (as gdb views it) register, -1 for all.
  100.  */
  101.  
  102. void
  103. fetch_inferior_registers (regno)
  104.      int regno;
  105. {
  106.   kern_return_t ret;
  107.   thread_state_data_t state;
  108.   unsigned int stateCnt = i386_THREAD_STATE_COUNT;
  109.   int index;
  110.   
  111.   if (! MACH_PORT_VALID (current_thread))
  112.     error ("fetch inferior registers: Invalid thread");
  113.  
  114.   if (must_suspend_thread)
  115.     setup_thread (current_thread, 1);
  116.  
  117.   ret = thread_get_state (current_thread,
  118.               i386_THREAD_STATE,
  119.               state,
  120.               &stateCnt);
  121.  
  122.   if (ret != KERN_SUCCESS)
  123.     warning ("fetch_inferior_registers: %s ",
  124.          mach_error_string (ret));
  125. #if 0
  126.   /* It may be more effective to store validate all of them,
  127.    * since we fetched them all anyway
  128.    */
  129.   else if (regno != -1)
  130.     supply_register (regno, (char *)state+reg_offset[regno]);
  131. #endif
  132.   else
  133.     {
  134.       for (index = 0; index < NUM_REGS; index++) 
  135.     supply_register (index, (char *)state+reg_offset[index]);
  136.     }
  137.  
  138.   if (must_suspend_thread)
  139.     setup_thread (current_thread, 0);
  140. }
  141.  
  142. /* Store our register values back into the inferior.
  143.  * If REGNO is -1, do this for all registers.
  144.  * Otherwise, REGNO specifies which register
  145.  *
  146.  * On mach3 all registers are always saved in one call.
  147.  */
  148. void
  149. store_inferior_registers (regno)
  150.      int regno;
  151. {
  152.   kern_return_t ret;
  153.   thread_state_data_t state;
  154.   unsigned int stateCnt = i386_THREAD_STATE_COUNT;
  155.   register int index;
  156.  
  157.   if (! MACH_PORT_VALID (current_thread))
  158.     error ("store inferior registers: Invalid thread");
  159.  
  160.   if (must_suspend_thread)
  161.     setup_thread (current_thread, 1);
  162.  
  163.   /* Fetch the state of the current thread */
  164.   ret = thread_get_state (current_thread,
  165.               i386_THREAD_STATE,
  166.               state,
  167.               &stateCnt);
  168.  
  169.    if (ret != KERN_SUCCESS) 
  170.     {
  171.       warning ("store_inferior_registers (get): %s",
  172.            mach_error_string (ret));
  173.       if (must_suspend_thread)
  174.     setup_thread (current_thread, 0);
  175.       return;
  176.     }
  177.  
  178.   /* move gdb's registers to thread's state
  179.    *
  180.    * Since we save all registers anyway, save the ones
  181.    * that gdb thinks are valid (e.g. ignore the regno
  182.    * parameter)
  183.    */
  184. #if 0
  185.   if (regno != -1)
  186.     STORE_REGS (state, regno, 1);
  187.   else
  188. #endif
  189.     {
  190.       for (index = 0; index < NUM_REGS; index++) 
  191.     STORE_REGS (state, index, 1);
  192.     }
  193.   
  194.   /* Write gdb's current view of register to the thread
  195.    */
  196.   ret = thread_set_state (current_thread,
  197.               i386_THREAD_STATE,
  198.               state,
  199.               i386_THREAD_STATE_COUNT);
  200.   
  201.   if (ret != KERN_SUCCESS)
  202.     warning ("store_inferior_registers (set): %s",
  203.          mach_error_string (ret));
  204.  
  205.   if (must_suspend_thread)
  206.     setup_thread (current_thread, 0);
  207. }
  208.  
  209.  
  210.  
  211. /* Return the address in the core dump or inferior of register REGNO.
  212.  * BLOCKEND should be the address of the end of the UPAGES area read
  213.  * in memory, but it's not?
  214.  *
  215.  * Currently our UX server dumps the whole thread state to the
  216.  * core file. If your UX does something else, adapt the routine
  217.  * below to return the offset to the given register.
  218.  * 
  219.  * Called by coredep.c(fetch_core_registers)
  220.  */
  221.  
  222. unsigned int
  223. register_addr (regno, blockend)
  224.      int regno;
  225.      int blockend;
  226. {
  227.   unsigned int addr;
  228.  
  229.   if (regno < 0 || regno >= NUM_REGS)
  230.     error ("Invalid register number %d.", regno);
  231.  
  232.   /* UAREA_SIZE == 8 kB in i386 */
  233.   addr = (unsigned int)REG_ADDRESS (UAREA_SIZE - sizeof(struct i386_thread_state), regno);
  234.  
  235.   return addr;
  236. }
  237.  
  238. /* jtv@hut.fi: I copied and modified this 387 code from
  239.  * gdb/i386-xdep.c. Modifications for Mach 3.0.
  240.  *
  241.  * i387 status dumper. See also i387-tdep.c
  242.  */
  243. struct env387 
  244. {
  245.   unsigned short control;
  246.   unsigned short r0;
  247.   unsigned short status;
  248.   unsigned short r1;
  249.   unsigned short tag;
  250.   unsigned short r2;
  251.   unsigned long eip;
  252.   unsigned short code_seg;
  253.   unsigned short opcode;
  254.   unsigned long operand;
  255.   unsigned short operand_seg;
  256.   unsigned short r3;
  257.   unsigned char regs[8][10];
  258. };
  259. /* This routine is machine independent?
  260.  * Should move it to i387-tdep.c but you need to export struct env387
  261.  */
  262. private
  263. print_387_status (status, ep)
  264.      unsigned short status;
  265.      struct env387 *ep;
  266. {
  267.   int i;
  268.   int bothstatus;
  269.   int top;
  270.   int fpreg;
  271.   unsigned char *p;
  272.   
  273.   bothstatus = ((status != 0) && (ep->status != 0));
  274.   if (status != 0) 
  275.     {
  276.       if (bothstatus)
  277.     printf_unfiltered ("u: ");
  278.       print_387_status_word (status);
  279.     }
  280.   
  281.   if (ep->status != 0) 
  282.     {
  283.       if (bothstatus)
  284.     printf_unfiltered ("e: ");
  285.       print_387_status_word (ep->status);
  286.     }
  287.   
  288.   print_387_control_word (ep->control);
  289.   printf_unfiltered ("last exception: ");
  290.   printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
  291.   printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
  292.   printf_unfiltered ("%s; ", local_hex_string(ep->eip));
  293.   printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
  294.   printf_unfiltered (":%s\n", local_hex_string(ep->operand));
  295.   
  296.   top = (ep->status >> 11) & 7;
  297.   
  298.   printf_unfiltered ("regno  tag  msb              lsb  value\n");
  299.   for (fpreg = 7; fpreg >= 0; fpreg--) 
  300.     {
  301.       double val;
  302.       
  303.       printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg);
  304.       
  305.       switch ((ep->tag >> (fpreg * 2)) & 3) 
  306.     {
  307.     case 0: printf_unfiltered ("valid "); break;
  308.     case 1: printf_unfiltered ("zero  "); break;
  309.     case 2: printf_unfiltered ("trap  "); break;
  310.     case 3: printf_unfiltered ("empty "); break;
  311.     }
  312.       for (i = 9; i >= 0; i--)
  313.     printf_unfiltered ("%02x", ep->regs[fpreg][i]);
  314.       
  315.       floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
  316.                    &val);
  317.       printf_unfiltered ("  %g\n", val);
  318.     }
  319.   if (ep->r0)
  320.     printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
  321.   if (ep->r1)
  322.     printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
  323.   if (ep->r2)
  324.     printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
  325.   if (ep->r3)
  326.     printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
  327. }
  328.     
  329. /*
  330.  * values that go into fp_kind (from <i386/fpreg.h>)
  331.  */
  332. #define FP_NO   0       /* no fp chip, no emulator (no fp support)      */
  333. #define FP_SW   1       /* no fp chip, using software emulator          */
  334. #define FP_HW   2       /* chip present bit                             */
  335. #define FP_287  2       /* 80287 chip present                           */
  336. #define FP_387  3       /* 80387 chip present                           */
  337.  
  338. typedef struct fpstate {
  339. #if 1
  340.   unsigned char    state[FP_STATE_BYTES]; /* "hardware" state */
  341. #else
  342.   struct env387    state;    /* Actually this */
  343. #endif
  344.   int status;        /* Duplicate status */
  345. } *fpstate_t;
  346.  
  347. /* Mach 3 specific routines.
  348.  */
  349. private boolean_t
  350. get_i387_state (fstate)
  351.      struct fpstate *fstate;
  352. {
  353.   kern_return_t ret;
  354.   thread_state_data_t state;
  355.   unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
  356.   struct i386_float_state *fsp;
  357.   
  358.   ret = thread_get_state (current_thread,
  359.               i386_FLOAT_STATE,
  360.               state,
  361.               &fsCnt);
  362.  
  363.   if (ret != KERN_SUCCESS)
  364.     {
  365.       warning ("Can not get live floating point state: %s",
  366.            mach_error_string (ret));
  367.       return FALSE;
  368.     }
  369.  
  370.   fsp = (struct i386_float_state *)state;
  371.   /* The 387 chip (also 486 counts) or a software emulator? */
  372.   if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
  373.     return FALSE;
  374.  
  375.   /* Clear the target then copy thread's float state there.
  376.      Make a copy of the status word, for some reason?
  377.    */
  378.   memset (fstate, 0, sizeof (struct fpstate));
  379.  
  380.   fstate->status = fsp->exc_status;
  381.  
  382.   memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
  383.  
  384.   return TRUE;
  385. }
  386.  
  387. private boolean_t
  388. get_i387_core_state (fstate)
  389.      struct fpstate *fstate;
  390. {
  391.   /* Not implemented yet. Core files do not contain float state. */
  392.   return FALSE;
  393. }
  394.  
  395. /*
  396.  * This is called by "info float" command
  397.  */
  398. void
  399. i386_mach3_float_info()
  400. {
  401.   char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
  402.   boolean_t valid = FALSE;
  403.   fpstate_t fps;
  404.   
  405.   if (target_has_execution)
  406.     valid = get_i387_state (buf);
  407. #if 0  
  408.   else if (WE HAVE CORE FILE)  /* @@@@ Core files not supported */
  409.     valid = get_i387_core_state (buf);
  410. #endif    
  411.  
  412.   if (!valid) 
  413.     {
  414.       warning ("no floating point status saved");
  415.       return;
  416.     }
  417.   
  418.   fps = (fpstate_t) buf;
  419.  
  420.   print_387_status (fps->status, (struct env387 *)fps->state);
  421. }
  422.