* mn10300.igen (OP_F0F4): Need to load contents of register AN0
[platform/upstream/binutils.git] / gdb / i386lynx-nat.c
1 <<<<<<< 2.6 is dead >>>>>>>
2 /* Native-dependent code for Lynx running on i386's, for GDB.
3    Copyright 1988, 1989, 1991, 1992, 1993
4    Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "inferior.h"
25 #include "target.h"
26
27 #include <sys/ptrace.h>
28 #include "/usr/include/sys/wait.h"
29
30 /* these values indicate the offset of the named register in the econtext
31    structure */
32
33 #define EAX     10
34 #define ECX     9
35 #define EDX     8
36 #define EBX     7
37 #define ESP     16
38 #define EBP     5
39 #define ESI     4
40 #define EDI     3
41 #define EIP     13
42 #define EFL     15
43 #define CS      14
44 #define SS      17
45 #define DS      2
46 #define ES      1
47
48 /* Currently these are not being used. So set them to 0 */
49
50 #define FS      0
51 #define GS      0
52
53 /* this table must line up with REGISTER_NAMES in m-i386.h */
54 static unsigned int regmap[] = 
55 {
56   EAX, ECX, EDX, EBX,
57   ESP, EBP, ESI, EDI,
58   EIP, EFL, CS, SS,
59   DS, ES, FS, GS,
60 };
61
62 /* Return the address in the core dump or inferior of register REGNO.
63    BLOCKEND is the address of the econtext structure */
64
65 static unsigned int
66 register_addr (regno, blockend)
67      int regno, blockend;
68 {
69   if (regno < 0 || regno >= NUM_REGS)
70     error ("Invalid register number %d.", regno);
71
72   return (blockend + regmap[regno] * sizeof (long));
73 }
74
75 /* Fetch one register.  */
76
77 static void
78 fetch_register (regno, offset, bpid)
79      int regno, bpid;
80      unsigned int offset;
81 {
82   unsigned int regaddr;
83   char buf[MAX_REGISTER_RAW_SIZE];
84   char mess[128];                               /* For messages */
85   int i;
86
87   regaddr = register_addr (regno, offset);
88   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
89     {
90       errno = 0;
91       *(int *) &buf[i] = ptrace (PTRACE_PEEKTHREAD, bpid,
92                                  (PTRACE_ARG3_TYPE) regaddr, 0);
93       regaddr += sizeof (int);
94       if (errno != 0)
95         {
96           sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
97           perror_with_name (mess);
98         }
99     }
100   supply_register (regno, buf);
101 }
102
103 /* Store our register values back into the inferior.
104    If REGNO is -1, do this for all registers.
105    Otherwise, REGNO specifies which register (so we can save time).  */
106
107 static void
108 store_register (regno, offset, bpid)
109      int regno, bpid;
110      unsigned int offset;
111 {
112   unsigned int regaddr;
113   char mess[128];
114   extern char registers[];
115   int i;
116
117   regaddr = register_addr (regno, offset);
118   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
119     {
120       errno = 0;
121       ptrace (PTRACE_POKEUSER, bpid, (PTRACE_ARG3_TYPE) regaddr,
122               *(int *) &registers[REGISTER_BYTE (regno) + i]);
123       if (errno != 0)
124         {  
125           sprintf (mess, "writing register number %d(%d)", regno, i);
126           perror_with_name (mess);
127         }
128       regaddr += sizeof(int);
129     }
130 }
131
132 /* return an offset for use with register_addr() */
133
134 static unsigned int
135 fetch_offset (pid)
136     int pid;
137 {
138   struct st_entry s;
139   unsigned int specpage_off, offset = (char *) &s.ecp - (char *) &s;
140
141   errno = 0;
142   specpage_off = ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 0);
143   if (errno != 0)
144     perror_with_name ("ptrace");
145   errno = 0;
146   offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0)
147       - specpage_off;
148   if (errno != 0)
149     perror_with_name ("ptrace");
150   return offset;
151 }
152
153 /* Fetch all registers, or just one, from the child process.  */
154
155 void
156 fetch_inferior_registers (regno)
157      int regno;
158 {
159   unsigned int offset = fetch_offset (inferior_pid);
160
161   if (regno == -1)
162     {
163       for (regno = 0; regno < NUM_REGS; regno++)
164         fetch_register (regno, offset, inferior_pid);
165     }
166   else
167     fetch_register (regno, offset, inferior_pid);
168 }
169
170 /* Store all registers, or just one, to the child process.  */
171
172 void
173 store_inferior_registers (regno)
174      int regno;
175 {
176     unsigned int offset = fetch_offset (inferior_pid);
177
178     if (regno == -1)
179       {
180         for (regno = 0; regno < NUM_REGS; regno++)
181           store_register (regno, offset, inferior_pid);
182       }
183     else
184       store_register (regno, offset, inferior_pid);
185 }
186
187 /* Wait for child to do something.  Return pid of child, or -1 in case
188    of error; store status through argument pointer STATUS.  */
189
190 int
191 child_wait (pid, status)
192      int pid;
193      int *status;
194 {
195   int save_errno;
196   int thread;
197
198   while (1)
199     {
200       int sig;
201
202       if (attach_flag)
203         set_sigint_trap();      /* Causes SIGINT to be passed on to the
204                                    attached process. */
205       pid = wait (status);
206       save_errno = errno;
207
208       if (attach_flag)
209         clear_sigint_trap();
210
211       if (pid == -1)
212         {
213           if (save_errno == EINTR)
214             continue;
215           fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
216                    safe_strerror (save_errno));
217           *status = 42;         /* Claim it exited with signal 42 */
218           return -1;
219         }
220
221       if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
222         continue;
223
224 /*      thread = WIFTID (*status);*/
225       thread = *status >> 16;
226
227       /* Initial thread value can only be acquired via wait, so we have to
228          resort to this hack.  */
229
230       if (TIDGET (inferior_pid) == 0)
231         {
232           inferior_pid = BUILDPID (inferior_pid, thread);
233           add_thread (inferior_pid);
234         }
235
236       pid = BUILDPID (pid, thread);
237
238       return pid;
239     }
240 }
241
242 /* Convert a Lynx process ID to a string.  Returns the string in a static
243    buffer.  */
244
245 char *
246 i386lynx_pid_to_str (pid)
247      int pid;
248 {
249   static char buf[40];
250
251   sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
252
253   return buf;
254 }
255
256 /* Extract the register values out of the core file and store
257    them where `read_register' will find them.
258
259    CORE_REG_SECT points to the register values themselves, read into memory.
260    CORE_REG_SIZE is the size of that area.
261    WHICH says which set of registers we are handling (0 = int, 2 = float
262          on machines where they are discontiguous).
263    REG_ADDR is the offset from u.u_ar0 to the register values relative to
264             core_reg_sect.  This is used with old-fashioned core files to
265             locate the registers in a large upage-plus-stack ".reg" section.
266             Original upage address X is at location core_reg_sect+x+reg_addr.
267  */
268
269 void
270 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
271      char *core_reg_sect;
272      unsigned core_reg_size;
273      int which;
274      unsigned reg_addr;
275 {
276   struct st_entry s;
277   unsigned int regno, addr;
278
279   for (regno = 0; regno < NUM_REGS; regno++)
280     {
281       addr = register_addr (regno, (char *) &s.ec - (char *) &s);
282       supply_register (regno, core_reg_sect + addr);
283     }
284 }