]> Git Repo - binutils.git/blob - gdb/arm-tdep.c
* gdb.base/scope.exp (text_at_main): Add "hppa*-*-hpux*"
[binutils.git] / gdb / arm-tdep.c
1 /* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
2    Copyright 1988, 1989, 1991, 1992, 1993, 1995 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 "frame.h"
22 #include "inferior.h"
23
24 #if 0
25 #include "gdbcore.h"
26 #include <sys/param.h>
27 #include <sys/dir.h>
28 #include <signal.h>
29 #include <sys/ioctl.h>
30 #include <sys/ptrace.h>
31 #include <machine/reg.h>
32
33 #define N_TXTADDR(hdr) 0x8000
34 #define N_DATADDR(hdr) (hdr.a_text + 0x8000)
35
36 #include <sys/user.h>           /* After a.out.h  */
37 #include <sys/file.h>
38 #include "gdb_stat.h"
39
40 #include <errno.h>
41 #endif
42
43 \f
44 #if 0
45 /* Work with core dump and executable files, for GDB. 
46    This code would be in core.c if it weren't machine-dependent. */
47
48 /* Structure to describe the chain of shared libraries used
49    by the execfile.
50    e.g. prog shares Xt which shares X11 which shares c. */
51
52 struct shared_library {
53     struct exec_header header;
54     char name[SHLIBLEN];
55     CORE_ADDR text_start;       /* CORE_ADDR of 1st byte of text, this file */
56     long data_offset;           /* offset of data section in file */
57     int chan;                   /* file descriptor for the file */
58     struct shared_library *shares; /* library this one shares */
59 };
60 static struct shared_library *shlib = 0;
61
62 /* Hook for `exec_file_command' command to call.  */
63
64 extern void (*exec_file_display_hook) ();
65    
66 static CORE_ADDR unshared_text_start;
67
68 /* extended header from exec file (for shared library info) */
69
70 static struct exec_header exec_header;
71
72 void
73 exec_file_command (filename, from_tty)
74      char *filename;
75      int from_tty;
76 {
77   int val;
78
79   /* Eliminate all traces of old exec file.
80      Mark text segment as empty.  */
81
82   if (execfile)
83     free (execfile);
84   execfile = 0;
85   data_start = 0;
86   data_end -= exec_data_start;
87   text_start = 0;
88   unshared_text_start = 0;
89   text_end = 0;
90   exec_data_start = 0;
91   exec_data_end = 0;
92   if (execchan >= 0)
93     close (execchan);
94   execchan = -1;
95   if (shlib) {
96       close_shared_library(shlib);
97       shlib = 0;
98   }
99
100   /* Now open and digest the file the user requested, if any.  */
101
102   if (filename)
103     {
104       filename = tilde_expand (filename);
105       make_cleanup (free, filename);
106
107       execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
108                         &execfile);
109       if (execchan < 0)
110         perror_with_name (filename);
111
112       {
113         struct stat st_exec;
114
115 #ifdef HEADER_SEEK_FD
116         HEADER_SEEK_FD (execchan);
117 #endif
118         
119         val = myread (execchan, &exec_header, sizeof exec_header);
120         exec_aouthdr = exec_header.a_exec;
121
122         if (val < 0)
123           perror_with_name (filename);
124
125         text_start = 0x8000;
126
127         /* Look for shared library if needed */
128         if (exec_header.a_exec.a_magic & MF_USES_SL)
129             shlib = open_shared_library(exec_header.a_shlibname, text_start);
130
131         text_offset = N_TXTOFF (exec_aouthdr);
132         exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
133
134         if (shlib) {
135             unshared_text_start = shared_text_end(shlib) & ~0x7fff;
136             stack_start = shlib->header.a_exec.a_sldatabase;
137             stack_end = STACK_END_ADDR;
138         } else
139             unshared_text_start = 0x8000;
140         text_end = unshared_text_start + exec_aouthdr.a_text;
141
142         exec_data_start = unshared_text_start + exec_aouthdr.a_text;
143         exec_data_end = exec_data_start + exec_aouthdr.a_data;
144
145         data_start = exec_data_start;
146         data_end += exec_data_start;
147
148         fstat (execchan, &st_exec);
149         exec_mtime = st_exec.st_mtime;
150       }
151
152       validate_files ();
153     }
154   else if (from_tty)
155     printf ("No exec file now.\n");
156
157   /* Tell display code (if any) about the changed file name.  */
158   if (exec_file_display_hook)
159     (*exec_file_display_hook) (filename);
160 }
161 #endif
162
163 #if 0
164 /* Read from the program's memory (except for inferior processes).
165    This function is misnamed, since it only reads, never writes; and
166    since it will use the core file and/or executable file as necessary.
167
168    It should be extended to write as well as read, FIXME, for patching files.
169
170    Return 0 if address could be read, EIO if addresss out of bounds.  */
171
172 int
173 xfer_core_file (memaddr, myaddr, len)
174      CORE_ADDR memaddr;
175      char *myaddr;
176      int len;
177 {
178   register int i;
179   register int val;
180   int xferchan;
181   char **xferfile;
182   int fileptr;
183   int returnval = 0;
184
185   while (len > 0)
186     {
187       xferfile = 0;
188       xferchan = 0;
189
190       /* Determine which file the next bunch of addresses reside in,
191          and where in the file.  Set the file's read/write pointer
192          to point at the proper place for the desired address
193          and set xferfile and xferchan for the correct file.
194
195          If desired address is nonexistent, leave them zero.
196
197          i is set to the number of bytes that can be handled
198          along with the next address.
199
200          We put the most likely tests first for efficiency.  */
201
202       /* Note that if there is no core file
203          data_start and data_end are equal.  */
204       if (memaddr >= data_start && memaddr < data_end)
205         {
206           i = min (len, data_end - memaddr);
207           fileptr = memaddr - data_start + data_offset;
208           xferfile = &corefile;
209           xferchan = corechan;
210         }
211       /* Note that if there is no core file
212          stack_start and stack_end define the shared library data.  */
213       else if (memaddr >= stack_start && memaddr < stack_end)
214         {
215             if (corechan < 0) {
216                 struct shared_library *lib;
217                 for (lib = shlib; lib; lib = lib->shares)
218                     if (memaddr >= lib->header.a_exec.a_sldatabase &&
219                         memaddr < lib->header.a_exec.a_sldatabase +
220                           lib->header.a_exec.a_data)
221                         break;
222                 if (lib) {
223                     i = min (len, lib->header.a_exec.a_sldatabase +
224                              lib->header.a_exec.a_data - memaddr);
225                     fileptr = lib->data_offset + memaddr -
226                         lib->header.a_exec.a_sldatabase;
227                     xferfile = execfile;
228                     xferchan = lib->chan;
229                 }
230             } else {
231                 i = min (len, stack_end - memaddr);
232                 fileptr = memaddr - stack_start + stack_offset;
233                 xferfile = &corefile;
234                 xferchan = corechan;
235             }
236         }
237       else if (corechan < 0
238                && memaddr >= exec_data_start && memaddr < exec_data_end)
239         {
240           i = min (len, exec_data_end - memaddr);
241           fileptr = memaddr - exec_data_start + exec_data_offset;
242           xferfile = &execfile;
243           xferchan = execchan;
244         }
245       else if (memaddr >= text_start && memaddr < text_end)
246         {
247             struct shared_library *lib;
248             for (lib = shlib; lib; lib = lib->shares)
249                 if (memaddr >= lib->text_start &&
250                     memaddr < lib->text_start + lib->header.a_exec.a_text)
251                     break;
252             if (lib) {
253                 i = min (len, lib->header.a_exec.a_text +
254                          lib->text_start - memaddr);
255                 fileptr = memaddr - lib->text_start + text_offset;
256                 xferfile = &execfile;
257                 xferchan = lib->chan;
258             } else {
259                 i = min (len, text_end - memaddr);
260                 fileptr = memaddr - unshared_text_start + text_offset;
261                 xferfile = &execfile;
262                 xferchan = execchan;
263             }
264         }
265       else if (memaddr < text_start)
266         {
267           i = min (len, text_start - memaddr);
268         }
269       else if (memaddr >= text_end
270                && memaddr < (corechan >= 0? data_start : exec_data_start))
271         {
272           i = min (len, data_start - memaddr);
273         }
274       else if (corechan >= 0
275                && memaddr >= data_end && memaddr < stack_start)
276         {
277           i = min (len, stack_start - memaddr);
278         }
279       else if (corechan < 0 && memaddr >= exec_data_end)
280         {
281           i = min (len, - memaddr);
282         }
283       else if (memaddr >= stack_end && stack_end != 0)
284         {
285           i = min (len, - memaddr);
286         }
287       else
288         {
289           /* Address did not classify into one of the known ranges.
290              This shouldn't happen; we catch the endpoints.  */
291           fatal ("Internal: Bad case logic in xfer_core_file.");
292         }
293
294       /* Now we know which file to use.
295          Set up its pointer and transfer the data.  */
296       if (xferfile)
297         {
298           if (*xferfile == 0)
299             if (xferfile == &execfile)
300               error ("No program file to examine.");
301             else
302               error ("No core dump file or running program to examine.");
303           val = lseek (xferchan, fileptr, 0);
304           if (val < 0)
305             perror_with_name (*xferfile);
306           val = myread (xferchan, myaddr, i);
307           if (val < 0)
308             perror_with_name (*xferfile);
309         }
310       /* If this address is for nonexistent memory,
311          read zeros if reading, or do nothing if writing.
312          Actually, we never right.  */
313       else
314         {
315           memset (myaddr, '\0', i);
316           returnval = EIO;
317         }
318
319       memaddr += i;
320       myaddr += i;
321       len -= i;
322     }
323   return returnval;
324 }
325 #endif
326 \f
327 /* APCS (ARM procedure call standard) defines the following prologue:
328
329    mov          ip, sp
330   [stmfd        sp!, {a1,a2,a3,a4}]
331    stmfd        sp!, {...,fp,ip,lr,pc}
332   [stfe         f7, [sp, #-12]!]
333   [stfe         f6, [sp, #-12]!]
334   [stfe         f5, [sp, #-12]!]
335   [stfe         f4, [sp, #-12]!]
336    sub          fp, ip, #nn     // nn == 20 or 4 depending on second ins
337 */
338
339 CORE_ADDR
340 skip_prologue(pc)
341 CORE_ADDR pc;
342 {
343     CORE_ADDR skip_pc = pc;
344 #if 0
345     union insn_fmt op;
346
347     op.ins = read_memory_integer(skip_pc, 4);
348     /* look for the "mov ip,sp" */
349     if (op.generic.type != TYPE_ARITHMETIC ||
350         op.arith.opcode != OPCODE_MOV ||
351         op.arith.dest != SPTEMP ||
352         op.arith.operand2 != SP) return pc;
353     skip_pc += 4;
354     /* skip the "stmfd sp!,{a1,a2,a3,a4}" if its there */
355     op.ins = read_memory_integer(skip_pc, 4);
356     if (op.generic.type == TYPE_BLOCK_BRANCH &&
357         op.generic.subtype == SUBTYPE_BLOCK &&
358         op.block.mask == 0xf &&
359         op.block.base == SP &&
360         op.block.is_load == 0 &&
361         op.block.writeback == 1 &&
362         op.block.increment == 0 &&
363         op.block.before == 1) skip_pc += 4;
364     /* skip the "stmfd sp!,{...,fp,ip,lr,pc} */
365     op.ins = read_memory_integer(skip_pc, 4);
366     if (op.generic.type != TYPE_BLOCK_BRANCH ||
367         op.generic.subtype != SUBTYPE_BLOCK ||
368         /* the mask should look like 110110xxxxxx0000 */
369         (op.block.mask & 0xd800) != 0xd800 ||
370         op.block.base != SP ||
371         op.block.is_load != 0 ||
372         op.block.writeback != 1 ||
373         op.block.increment != 0 ||
374         op.block.before != 1) return pc;
375     skip_pc += 4;
376     /* check for "sub fp,ip,#nn" */
377     op.ins = read_memory_integer(skip_pc, 4);
378     if (op.generic.type != TYPE_ARITHMETIC ||
379         op.arith.opcode != OPCODE_SUB ||
380         op.arith.dest != FP ||
381         op.arith.operand1 != SPTEMP) return pc;
382 #endif
383     return skip_pc + 4;
384 }
385
386 void
387 arm_frame_find_saved_regs (frame_info, saved_regs_addr)
388      struct frame_info *frame_info;
389      struct frame_saved_regs *saved_regs_addr;
390 {
391   register int regnum;
392   register int frame;
393   register int next_addr;
394   register int return_data_save;
395   register int saved_register_mask;
396
397   memset (saved_regs_addr, '\0', sizeof (*saved_regs_addr));
398   frame = frame_info->frame;
399   return_data_save = read_memory_integer (frame, 4) & 0x03fffffc - 12;
400   saved_register_mask = read_memory_integer (return_data_save, 4);
401   next_addr = frame - 12;
402   for (regnum = 4; regnum < 10; regnum++)
403     if (saved_register_mask & (1 << regnum))
404       {
405         next_addr -= 4;
406         saved_regs_addr->regs[regnum] = next_addr;
407       }
408   if (read_memory_integer (return_data_save + 4, 4) == 0xed6d7103)
409     {
410       next_addr -= 12;
411       saved_regs_addr->regs[F0_REGNUM + 7] = next_addr;
412     }
413   if (read_memory_integer (return_data_save + 8, 4) == 0xed6d6103)
414     {
415       next_addr -= 12;
416       saved_regs_addr->regs[F0_REGNUM + 6] = next_addr;
417     }
418   if (read_memory_integer (return_data_save + 12, 4) == 0xed6d5103)
419     {
420       next_addr -= 12;
421       saved_regs_addr->regs[F0_REGNUM + 5] = next_addr;
422     }
423   if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103)
424     {
425       next_addr -= 12;
426       saved_regs_addr->regs[F0_REGNUM + 4] = next_addr;
427     }
428   saved_regs_addr->regs[SP_REGNUM] = next_addr;
429   saved_regs_addr->regs[PC_REGNUM] = frame - 4;
430   saved_regs_addr->regs[PS_REGNUM] = frame - 4;
431   saved_regs_addr->regs[FP_REGNUM] = frame - 12;
432 }
433
434 static void
435 print_fpu_flags(flags)
436 int flags;
437 {
438     if (flags & (1 << 0)) fputs("IVO ", stdout);
439     if (flags & (1 << 1)) fputs("DVZ ", stdout);
440     if (flags & (1 << 2)) fputs("OFL ", stdout);
441     if (flags & (1 << 3)) fputs("UFL ", stdout);
442     if (flags & (1 << 4)) fputs("INX ", stdout);
443     putchar('\n');
444 }
445
446 void
447 arm_float_info()
448 {
449     register unsigned long status = read_register(FPS_REGNUM);
450     int type;
451
452     type = (status >> 24) & 127;
453     printf("%s FPU type %d\n",
454            (status & (1<<31)) ? "Hardware" : "Software",
455            type);
456     fputs("mask: ", stdout);
457     print_fpu_flags(status >> 16);
458     fputs("flags: ", stdout);
459     print_fpu_flags(status);
460 }
461
462 void
463 _initialize_arm_tdep ()
464 {
465   tm_print_insn = print_insn_little_arm;
466 }
467
468
469 /* FIXME:  Fill in with the 'right thing', see asm 
470    template in arm-convert.s */
471
472 void 
473 convert_from_extended (ptr, dbl)
474 void *ptr;
475 double *dbl;
476 {
477   *dbl = *(double*)ptr;
478 }
479
480
481 void 
482 convert_to_extended (dbl, ptr)
483 void *ptr;
484 double *dbl;
485 {
486   *(double*)ptr = *dbl;
487 }
488
This page took 0.053318 seconds and 4 git commands to generate.