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

  1. /* Definitions to make GDB run on a mips box under 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. /* Mach specific routines for little endian mips (e.g. pmax)
  21.  * running Mach 3.0
  22.  *
  23.  * Author: Jukka Virtanen <jtv@hut.fi>
  24.  */
  25.  
  26. #include "defs.h"
  27. #include "inferior.h"
  28.  
  29. #include <stdio.h>
  30.  
  31. #include <mach.h>
  32. #include <mach/message.h>
  33. #include <mach/exception.h>
  34. #include <mach_error.h>
  35.  
  36. /* Find offsets to thread states at compile time.
  37.  * If your compiler does not grok this, check the hand coded
  38.  * offsets and use them.
  39.  */
  40.  
  41. #if 1
  42.  
  43. #define  REG_OFFSET(reg) (int)(&((struct mips_thread_state *)0)->reg)
  44. #define CREG_OFFSET(reg) (int)(&((struct mips_float_state *)0)->reg)
  45. #define EREG_OFFSET(reg) (int)(&((struct mips_exc_state *)0)->reg)
  46.  
  47. /* at reg_offset[i] is the offset to the mips_thread_state
  48.  * location where the gdb registers[i] is stored.
  49.  *
  50.  * -1 means mach does not save it anywhere.
  51.  */
  52. static int reg_offset[] = 
  53. {
  54.   /*  zero        at          v0            v1       */
  55.       -1,           REG_OFFSET(r1),   REG_OFFSET(r2),   REG_OFFSET(r3),
  56.  
  57.   /*  a0        a1          a2            a3       */
  58.   REG_OFFSET(r4),   REG_OFFSET(r5),   REG_OFFSET(r6),   REG_OFFSET(r7),
  59.  
  60.   /*  t0        t1          t2            t3       */
  61.   REG_OFFSET(r8),   REG_OFFSET(r9),   REG_OFFSET(r10),  REG_OFFSET(r11),
  62.  
  63.   /*  t4        t5          t6            t7       */
  64.   REG_OFFSET(r12),  REG_OFFSET(r13),  REG_OFFSET(r14),  REG_OFFSET(r15),
  65.  
  66.   /*  s0        s1          s2            s3       */
  67.   REG_OFFSET(r16),  REG_OFFSET(r17),  REG_OFFSET(r18),  REG_OFFSET(r19),
  68.  
  69.   /*  s4        s5          s6            s7       */
  70.   REG_OFFSET(r20),  REG_OFFSET(r21),  REG_OFFSET(r22),  REG_OFFSET(r23),
  71.  
  72.   /*  t8        t9          k0            k1       */
  73.   REG_OFFSET(r24),  REG_OFFSET(r25),  REG_OFFSET(r26),  REG_OFFSET(r27),
  74.  
  75.   /*  gp        sp          s8(30) == fp(72)        ra       */
  76.   REG_OFFSET(r28),  REG_OFFSET(r29),  REG_OFFSET(r30),  REG_OFFSET(r31),
  77.  
  78.   /*  sr(32) PS_REGNUM   */
  79.   EREG_OFFSET(coproc_state),
  80.  
  81.   /*  lo(33)        hi(34)    */
  82.   REG_OFFSET(mdlo), REG_OFFSET(mdhi),
  83.  
  84.   /*  bad(35)                    cause(36)             pc(37)  */
  85.   EREG_OFFSET(address),  EREG_OFFSET(cause), REG_OFFSET(pc),
  86.  
  87.   /*  f0(38)         f1(39)            f2(40)           f3(41)   */
  88.   CREG_OFFSET(r0),   CREG_OFFSET(r1),   CREG_OFFSET(r2),   CREG_OFFSET(r3),
  89.   CREG_OFFSET(r4),   CREG_OFFSET(r5),   CREG_OFFSET(r6),   CREG_OFFSET(r7),
  90.   CREG_OFFSET(r8),   CREG_OFFSET(r9),   CREG_OFFSET(r10),  CREG_OFFSET(r11),
  91.   CREG_OFFSET(r12),  CREG_OFFSET(r13),  CREG_OFFSET(r14),  CREG_OFFSET(r15),
  92.   CREG_OFFSET(r16),  CREG_OFFSET(r17),  CREG_OFFSET(r18),  CREG_OFFSET(r19),
  93.   CREG_OFFSET(r20),  CREG_OFFSET(r21),  CREG_OFFSET(r22),  CREG_OFFSET(r23),
  94.   CREG_OFFSET(r24),  CREG_OFFSET(r25),  CREG_OFFSET(r26),  CREG_OFFSET(r27),
  95.   CREG_OFFSET(r28),  CREG_OFFSET(r29),  CREG_OFFSET(r30),  CREG_OFFSET(r31),
  96.  
  97.   /*  fsr(70)        fir(71)        fp(72) == s8(30) */
  98.   CREG_OFFSET(csr),  CREG_OFFSET(esr),  REG_OFFSET(r30)
  99. };
  100. #else
  101. /* If the compiler does not grok the above defines */
  102. static int reg_offset[] = 
  103. {
  104. /* mach_thread_state offsets: */
  105.   -1,  0,  4,  8,  12, 16, 20, 24,  28, 32, 36, 40,  44, 48, 52, 56,
  106.   60, 64, 68, 72,  76, 80, 84, 88,  92, 96,100,104, 108,112,116,120,
  107. /*sr, lo, hi,addr,cause,pc   */
  108.    8,124,128,  4,   0,132,
  109. /* mach_float_state offsets: */
  110.    0,  4,  8, 12,  16, 20, 24, 28,  32, 36, 40, 44,  48, 52, 56, 60,
  111.   64, 68, 72, 76,  80, 84, 88, 92,  96,100,104,108, 112,116,120,124,
  112. /*fsr,fir*/
  113.  128,132,
  114. /* FP_REGNUM pseudo maps to s8==r30 in mach_thread_state */
  115.  116
  116. };
  117. #endif
  118.  
  119. /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
  120.  * Caller knows that the regs handled in one transaction are of same size.
  121.  */
  122. #define FETCH_REGS(state, regnum, count) \
  123.   memcpy (®isters[REGISTER_BYTE (regnum)], \
  124.       (char *)state+reg_offset[ regnum ], \
  125.       count*REGISTER_SIZE)
  126.  
  127. /* Store COUNT contiguous registers to thread STATE starting from REGNUM */
  128. #define STORE_REGS(state, regnum, count) \
  129.   memcpy ((char *)state+reg_offset[ regnum ], \
  130.       ®isters[REGISTER_BYTE (regnum)], \
  131.       count*REGISTER_SIZE)
  132.  
  133. #define REGS_ALL    -1
  134. #define REGS_NORMAL  1
  135. #define REGS_EXC     2
  136. #define REGS_COP1    4
  137.  
  138. /* Hardware regs that matches FP_REGNUM */
  139. #define MACH_FP_REGNUM 30
  140.  
  141. /* Fech thread's registers. if regno == -1, fetch all regs */
  142. void
  143. fetch_inferior_registers (regno)
  144.      int regno;
  145. {
  146.   kern_return_t ret;  
  147.  
  148.   thread_state_data_t      state;
  149.   struct mips_exc_state    exc_state;
  150.  
  151.   int stateCnt   = MIPS_THREAD_STATE_COUNT;
  152.  
  153.   int which_regs = 0; /* A bit mask */
  154.  
  155.   if (! MACH_PORT_VALID (current_thread))
  156.     error ("fetch inferior registers: Invalid thread");
  157.   
  158.   if (regno < -1 || regno >= NUM_REGS)
  159.     error ("invalid register %d supplied to fetch_inferior_registers", regno);
  160.  
  161.   if (regno == -1)
  162.     which_regs = REGS_ALL;
  163.   else if (regno == ZERO_REGNUM)
  164.     {
  165.       int zero = 0;
  166.       supply_register (ZERO_REGNUM, &zero);
  167.       return;
  168.     }
  169.   else if ((ZERO_REGNUM < regno && regno < PS_REGNUM)
  170.        || regno == FP_REGNUM
  171.        || regno == LO_REGNUM
  172.        || regno == HI_REGNUM
  173.        || regno == PC_REGNUM)
  174.     which_regs = REGS_NORMAL;
  175.   else if (FP0_REGNUM <= regno && regno <= FCRIR_REGNUM)
  176.     which_regs = REGS_COP1 | REGS_EXC;
  177.   else
  178.     which_regs = REGS_EXC;
  179.  
  180.   /* fetch regs saved to mips_thread_state */
  181.   if (which_regs & REGS_NORMAL)
  182.     {
  183.       ret = thread_get_state (current_thread,
  184.                   MIPS_THREAD_STATE,
  185.                   state,
  186.                   &stateCnt);
  187.       CHK ("fetch inferior registers: thread_get_state", ret);
  188.  
  189.       if (which_regs == REGS_NORMAL)
  190.     {
  191.       /* Fetch also FP_REGNUM if fetching MACH_FP_REGNUM and vice versa */
  192.       if (regno == MACH_FP_REGNUM || regno == FP_REGNUM)
  193.         {
  194.           supply_register (FP_REGNUM,
  195.                    (char *)state+reg_offset[ MACH_FP_REGNUM ]);
  196.           supply_register (MACH_FP_REGNUM,
  197.                    (char *)state+reg_offset[ MACH_FP_REGNUM ]);
  198.         }
  199.       else
  200.         supply_register (regno,
  201.                  (char *)state+reg_offset[ regno ]);
  202.       return;
  203.     }
  204.                
  205.       /* ZERO_REGNUM is always zero */
  206.       *(int *) registers = 0;
  207.       
  208.       /* Copy thread saved regs 1..31 to gdb's reg value array
  209.        * Luckily, they are contiquous
  210.        */
  211.       FETCH_REGS (state, 1, 31);
  212.       
  213.       /* Copy mdlo and mdhi */
  214.       FETCH_REGS (state, LO_REGNUM, 2);
  215.  
  216.       /* Copy PC */
  217.       FETCH_REGS (state, PC_REGNUM, 1);
  218.  
  219.       /* Mach 3.0 saves FP to MACH_FP_REGNUM.
  220.        * For some reason gdb wants to assign a pseudo register for it.
  221.        */
  222.       FETCH_REGS (state, FP_REGNUM, 1);
  223.     }
  224.  
  225.   /* Read exc state. Also read if need to fetch floats */
  226.   if (which_regs & REGS_EXC)
  227.     {
  228.       stateCnt = MIPS_EXC_STATE_COUNT;
  229.       ret = thread_get_state (current_thread,
  230.                   MIPS_EXC_STATE,
  231.                   (thread_state_t) &exc_state,
  232.                   &stateCnt);
  233.       CHK ("fetch inferior regs (exc): thread_get_state", ret);
  234.  
  235.       /* We need to fetch exc_state to see if the floating
  236.        * state is valid for the thread.
  237.        */
  238.  
  239.       /* cproc_state: Which coprocessors the thread uses */
  240.       supply_register (PS_REGNUM,
  241.                (char *)&exc_state+reg_offset[ PS_REGNUM ]);
  242.       
  243.       if (which_regs == REGS_EXC || which_regs == REGS_ALL)
  244.     {
  245.       supply_register (BADVADDR_REGNUM,
  246.                (char *)&exc_state+reg_offset[ BADVADDR_REGNUM ]);
  247.       
  248.       supply_register (CAUSE_REGNUM,
  249.                (char *)&exc_state+reg_offset[ CAUSE_REGNUM ]);
  250.       if (which_regs == REGS_EXC)
  251.         return;
  252.     }
  253.     }
  254.  
  255.  
  256.   if (which_regs & REGS_COP1)
  257.     {
  258.       /* If the thread does not have saved COPROC1, set regs to zero */
  259.       
  260.       if (! (exc_state.coproc_state & MIPS_STATUS_USE_COP1))
  261.     bzero (®isters[ REGISTER_BYTE (FP0_REGNUM) ],
  262.            sizeof (struct mips_float_state));
  263.       else
  264.     {
  265.       stateCnt = MIPS_FLOAT_STATE_COUNT;
  266.       ret = thread_get_state (current_thread,
  267.                   MIPS_FLOAT_STATE,
  268.                   state,
  269.                   &stateCnt);
  270.       CHK ("fetch inferior regs (floats): thread_get_state", ret);
  271.       
  272.       if (regno != -1)
  273.         {
  274.           supply_register (regno,
  275.                    (char *)state+reg_offset[ regno ]);
  276.           return;
  277.         }
  278.       
  279.       FETCH_REGS (state, FP0_REGNUM, 34);
  280.     }
  281.     }
  282.   
  283.   /* All registers are valid, if not returned yet */
  284.   registers_fetched ();
  285. }
  286.  
  287. /* Store gdb's view of registers to the thread.
  288.  * All registers are always valid when entering here.
  289.  * @@ ahem, maybe that is too strict, we could validate the necessary ones
  290.  *    here.
  291.  *
  292.  * Hmm. It seems that gdb set $reg=value command first reads everything,
  293.  * then sets the reg and then stores everything. -> we must make sure
  294.  * that the immutable registers are not changed by reading them first.
  295.  */
  296.  
  297. void
  298. store_inferior_registers (regno)
  299.      register int regno;
  300. {
  301.   thread_state_data_t state;
  302.   kern_return_t ret;
  303.   
  304.   if (! MACH_PORT_VALID (current_thread))
  305.     error ("store inferior registers: Invalid thread");
  306.   
  307.   /* Check for read only regs.
  308.    * @@ If some of these is can be changed, fix this
  309.    */
  310.   if (regno == ZERO_REGNUM    ||
  311.       regno == PS_REGNUM    ||
  312.       regno == BADVADDR_REGNUM    ||
  313.       regno == CAUSE_REGNUM    ||
  314.       regno == FCRIR_REGNUM)
  315.     {
  316.       message ("You can not alter read-only register `%s'",
  317.            reg_names[ regno ]);
  318.       fetch_inferior_registers (regno);
  319.       return;
  320.     }
  321.  
  322.   if (regno == -1)
  323.     {
  324.       /* Don't allow these to change */
  325.  
  326.       /* ZERO_REGNUM */
  327.       *(int *)registers = 0;
  328.       
  329.       fetch_inferior_registers (PS_REGNUM);
  330.       fetch_inferior_registers (BADVADDR_REGNUM);
  331.       fetch_inferior_registers (CAUSE_REGNUM);
  332.       fetch_inferior_registers (FCRIR_REGNUM);
  333.     }
  334.  
  335.   if (regno == -1 || (ZERO_REGNUM < regno && regno <= PC_REGNUM))
  336.     {
  337. #if 1
  338.       /* Mach 3.0 saves thread's FP to MACH_FP_REGNUM.
  339.        * GDB wants assigns a pseudo register FP_REGNUM for frame pointer.
  340.        *
  341.        * @@@ Here I assume (!) that gdb's FP has the value that
  342.        *     should go to threads frame pointer. If not true, this
  343.        *     fails badly!!!!!
  344.        */
  345.       memcpy (®isters[REGISTER_BYTE (MACH_FP_REGNUM)],
  346.           ®isters[REGISTER_BYTE (FP_REGNUM)],
  347.           REGISTER_RAW_SIZE (FP_REGNUM));
  348. #endif
  349.       
  350.       /* Save gdb's regs 1..31 to thread saved regs 1..31
  351.        * Luckily, they are contiquous
  352.        */
  353.       STORE_REGS (state, 1, 31);
  354.  
  355.       /* Save mdlo, mdhi */
  356.       STORE_REGS (state, LO_REGNUM, 2);
  357.  
  358.      /* Save PC */
  359.       STORE_REGS (state, PC_REGNUM, 1);
  360.  
  361.       ret = thread_set_state (current_thread,
  362.                   MIPS_THREAD_STATE,
  363.                   state,
  364.                   MIPS_FLOAT_STATE_COUNT);
  365.       CHK ("store inferior regs : thread_set_state", ret);
  366.     }
  367.   
  368.   if (regno == -1 || regno >= FP0_REGNUM)
  369.     {
  370.       /* If thread has floating state, save it */
  371.       if (read_register (PS_REGNUM) & MIPS_STATUS_USE_COP1)
  372.     {
  373.       /* Do NOT save FCRIR_REGNUM */
  374.       STORE_REGS (state, FP0_REGNUM, 33);
  375.     
  376.       ret = thread_set_state (current_thread,
  377.                   MIPS_FLOAT_STATE,
  378.                   state,
  379.                   MIPS_FLOAT_STATE_COUNT);
  380.       CHK ("store inferior registers (floats): thread_set_state", ret);
  381.     }
  382.       else if (regno != -1)
  383.     message
  384.       ("Thread does not use floating point unit, floating regs not saved");
  385.     }
  386. }
  387.