xref: /openbsd-src/gnu/usr.bin/binutils/gdb/sh64-tdep.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Target-dependent code for Renesas Super-H, for GDB.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
4b725ae77Skettenis    2002, 2003, 2004 Free Software Foundation, Inc.
5b725ae77Skettenis 
6b725ae77Skettenis    This file is part of GDB.
7b725ae77Skettenis 
8b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
9b725ae77Skettenis    it under the terms of the GNU General Public License as published by
10b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
11b725ae77Skettenis    (at your option) any later version.
12b725ae77Skettenis 
13b725ae77Skettenis    This program is distributed in the hope that it will be useful,
14b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
15b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b725ae77Skettenis    GNU General Public License for more details.
17b725ae77Skettenis 
18b725ae77Skettenis    You should have received a copy of the GNU General Public License
19b725ae77Skettenis    along with this program; if not, write to the Free Software
20b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
21b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
22b725ae77Skettenis 
23b725ae77Skettenis /*
24b725ae77Skettenis    Contributed by Steve Chamberlain
25b725ae77Skettenis    sac@cygnus.com
26b725ae77Skettenis  */
27b725ae77Skettenis 
28b725ae77Skettenis #include "defs.h"
29b725ae77Skettenis #include "frame.h"
30b725ae77Skettenis #include "symtab.h"
31b725ae77Skettenis #include "objfiles.h"
32b725ae77Skettenis #include "gdbtypes.h"
33b725ae77Skettenis #include "gdbcmd.h"
34b725ae77Skettenis #include "gdbcore.h"
35b725ae77Skettenis #include "value.h"
36b725ae77Skettenis #include "dis-asm.h"
37b725ae77Skettenis #include "inferior.h"
38b725ae77Skettenis #include "gdb_string.h"
39b725ae77Skettenis #include "arch-utils.h"
40b725ae77Skettenis #include "floatformat.h"
41b725ae77Skettenis #include "regcache.h"
42b725ae77Skettenis #include "doublest.h"
43b725ae77Skettenis #include "osabi.h"
44b725ae77Skettenis 
45b725ae77Skettenis #include "elf-bfd.h"
46b725ae77Skettenis #include "solib-svr4.h"
47b725ae77Skettenis 
48b725ae77Skettenis /* sh flags */
49b725ae77Skettenis #include "elf/sh.h"
50b725ae77Skettenis /* registers numbers shared with the simulator */
51b725ae77Skettenis #include "gdb/sim-sh.h"
52b725ae77Skettenis 
53b725ae77Skettenis /* Information that is dependent on the processor variant.  */
54b725ae77Skettenis enum sh_abi
55b725ae77Skettenis   {
56b725ae77Skettenis     SH_ABI_UNKNOWN,
57b725ae77Skettenis     SH_ABI_32,
58b725ae77Skettenis     SH_ABI_64
59b725ae77Skettenis   };
60b725ae77Skettenis 
61b725ae77Skettenis struct gdbarch_tdep
62b725ae77Skettenis   {
63b725ae77Skettenis     enum sh_abi sh_abi;
64b725ae77Skettenis   };
65b725ae77Skettenis 
66b725ae77Skettenis /* Registers of SH5 */
67b725ae77Skettenis enum
68b725ae77Skettenis   {
69b725ae77Skettenis     R0_REGNUM = 0,
70b725ae77Skettenis     DEFAULT_RETURN_REGNUM = 2,
71b725ae77Skettenis     STRUCT_RETURN_REGNUM = 2,
72b725ae77Skettenis     ARG0_REGNUM = 2,
73b725ae77Skettenis     ARGLAST_REGNUM = 9,
74b725ae77Skettenis     FLOAT_ARGLAST_REGNUM = 11,
75b725ae77Skettenis     PR_REGNUM = 18,
76b725ae77Skettenis     SR_REGNUM = 65,
77b725ae77Skettenis     DR0_REGNUM = 141,
78b725ae77Skettenis     DR_LAST_REGNUM = 172,
79b725ae77Skettenis     /* FPP stands for Floating Point Pair, to avoid confusion with
80b725ae77Skettenis        GDB's FP0_REGNUM, which is the number of the first Floating
81b725ae77Skettenis        point register. Unfortunately on the sh5, the floating point
82b725ae77Skettenis        registers are called FR, and the floating point pairs are called FP.  */
83b725ae77Skettenis     FPP0_REGNUM = 173,
84b725ae77Skettenis     FPP_LAST_REGNUM = 204,
85b725ae77Skettenis     FV0_REGNUM = 205,
86b725ae77Skettenis     FV_LAST_REGNUM = 220,
87b725ae77Skettenis     R0_C_REGNUM = 221,
88b725ae77Skettenis     R_LAST_C_REGNUM = 236,
89b725ae77Skettenis     PC_C_REGNUM = 237,
90b725ae77Skettenis     GBR_C_REGNUM = 238,
91b725ae77Skettenis     MACH_C_REGNUM = 239,
92b725ae77Skettenis     MACL_C_REGNUM = 240,
93b725ae77Skettenis     PR_C_REGNUM = 241,
94b725ae77Skettenis     T_C_REGNUM = 242,
95b725ae77Skettenis     FPSCR_C_REGNUM = 243,
96b725ae77Skettenis     FPUL_C_REGNUM = 244,
97b725ae77Skettenis     FP0_C_REGNUM = 245,
98b725ae77Skettenis     FP_LAST_C_REGNUM = 260,
99b725ae77Skettenis     DR0_C_REGNUM = 261,
100b725ae77Skettenis     DR_LAST_C_REGNUM = 268,
101b725ae77Skettenis     FV0_C_REGNUM = 269,
102b725ae77Skettenis     FV_LAST_C_REGNUM = 272,
103b725ae77Skettenis     FPSCR_REGNUM = SIM_SH64_FPCSR_REGNUM,
104b725ae77Skettenis     SSR_REGNUM = SIM_SH64_SSR_REGNUM,
105b725ae77Skettenis     SPC_REGNUM = SIM_SH64_SPC_REGNUM,
106b725ae77Skettenis     TR7_REGNUM = SIM_SH64_TR0_REGNUM + 7,
107b725ae77Skettenis     FP_LAST_REGNUM = SIM_SH64_FR0_REGNUM + SIM_SH64_NR_FP_REGS - 1
108b725ae77Skettenis   };
109b725ae77Skettenis 
110b725ae77Skettenis 
111b725ae77Skettenis /* Define other aspects of the stack frame.
112b725ae77Skettenis    we keep a copy of the worked out return pc lying around, since it
113b725ae77Skettenis    is a useful bit of info */
114b725ae77Skettenis 
115b725ae77Skettenis struct frame_extra_info
116b725ae77Skettenis {
117b725ae77Skettenis   CORE_ADDR return_pc;
118b725ae77Skettenis   int leaf_function;
119b725ae77Skettenis   int f_offset;
120b725ae77Skettenis };
121b725ae77Skettenis 
122b725ae77Skettenis static const char *
sh64_register_name(int reg_nr)123b725ae77Skettenis sh64_register_name (int reg_nr)
124b725ae77Skettenis {
125b725ae77Skettenis   static char *register_names[] =
126b725ae77Skettenis   {
127b725ae77Skettenis     /* SH MEDIA MODE (ISA 32) */
128b725ae77Skettenis     /* general registers (64-bit) 0-63 */
129b725ae77Skettenis     "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
130b725ae77Skettenis     "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
131b725ae77Skettenis     "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
132b725ae77Skettenis     "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",
133b725ae77Skettenis     "r32",  "r33",  "r34",  "r35",  "r36",  "r37",  "r38",  "r39",
134b725ae77Skettenis     "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",
135b725ae77Skettenis     "r48",  "r49",  "r50",  "r51",  "r52",  "r53",  "r54",  "r55",
136b725ae77Skettenis     "r56",  "r57",  "r58",  "r59",  "r60",  "r61",  "r62",  "r63",
137b725ae77Skettenis 
138b725ae77Skettenis     /* pc (64-bit) 64 */
139b725ae77Skettenis     "pc",
140b725ae77Skettenis 
141b725ae77Skettenis     /* status reg., saved status reg., saved pc reg. (64-bit) 65-67 */
142b725ae77Skettenis     "sr",  "ssr",  "spc",
143b725ae77Skettenis 
144b725ae77Skettenis     /* target registers (64-bit) 68-75*/
145b725ae77Skettenis     "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7",
146b725ae77Skettenis 
147b725ae77Skettenis     /* floating point state control register (32-bit) 76 */
148b725ae77Skettenis     "fpscr",
149b725ae77Skettenis 
150b725ae77Skettenis     /* single precision floating point registers (32-bit) 77-140*/
151b725ae77Skettenis     "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",
152b725ae77Skettenis     "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
153b725ae77Skettenis     "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
154b725ae77Skettenis     "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
155b725ae77Skettenis     "fr32", "fr33", "fr34", "fr35", "fr36", "fr37", "fr38", "fr39",
156b725ae77Skettenis     "fr40", "fr41", "fr42", "fr43", "fr44", "fr45", "fr46", "fr47",
157b725ae77Skettenis     "fr48", "fr49", "fr50", "fr51", "fr52", "fr53", "fr54", "fr55",
158b725ae77Skettenis     "fr56", "fr57", "fr58", "fr59", "fr60", "fr61", "fr62", "fr63",
159b725ae77Skettenis 
160b725ae77Skettenis     /* double precision registers (pseudo) 141-172 */
161b725ae77Skettenis     "dr0",  "dr2",  "dr4",  "dr6",  "dr8",  "dr10", "dr12", "dr14",
162b725ae77Skettenis     "dr16", "dr18", "dr20", "dr22", "dr24", "dr26", "dr28", "dr30",
163b725ae77Skettenis     "dr32", "dr34", "dr36", "dr38", "dr40", "dr42", "dr44", "dr46",
164b725ae77Skettenis     "dr48", "dr50", "dr52", "dr54", "dr56", "dr58", "dr60", "dr62",
165b725ae77Skettenis 
166b725ae77Skettenis     /* floating point pairs (pseudo) 173-204*/
167b725ae77Skettenis     "fp0",  "fp2",  "fp4",  "fp6",  "fp8",  "fp10", "fp12", "fp14",
168b725ae77Skettenis     "fp16", "fp18", "fp20", "fp22", "fp24", "fp26", "fp28", "fp30",
169b725ae77Skettenis     "fp32", "fp34", "fp36", "fp38", "fp40", "fp42", "fp44", "fp46",
170b725ae77Skettenis     "fp48", "fp50", "fp52", "fp54", "fp56", "fp58", "fp60", "fp62",
171b725ae77Skettenis 
172b725ae77Skettenis     /* floating point vectors (4 floating point regs) (pseudo) 205-220*/
173b725ae77Skettenis     "fv0",  "fv4",  "fv8",  "fv12", "fv16", "fv20", "fv24", "fv28",
174b725ae77Skettenis     "fv32", "fv36", "fv40", "fv44", "fv48", "fv52", "fv56", "fv60",
175b725ae77Skettenis 
176b725ae77Skettenis     /* SH COMPACT MODE (ISA 16) (all pseudo) 221-272*/
177b725ae77Skettenis     "r0_c", "r1_c", "r2_c",  "r3_c",  "r4_c",  "r5_c",  "r6_c",  "r7_c",
178b725ae77Skettenis     "r8_c", "r9_c", "r10_c", "r11_c", "r12_c", "r13_c", "r14_c", "r15_c",
179b725ae77Skettenis     "pc_c",
180b725ae77Skettenis     "gbr_c", "mach_c", "macl_c", "pr_c", "t_c",
181b725ae77Skettenis     "fpscr_c", "fpul_c",
182b725ae77Skettenis     "fr0_c", "fr1_c", "fr2_c",  "fr3_c",  "fr4_c",  "fr5_c",  "fr6_c",  "fr7_c",
183b725ae77Skettenis     "fr8_c", "fr9_c", "fr10_c", "fr11_c", "fr12_c", "fr13_c", "fr14_c", "fr15_c",
184b725ae77Skettenis     "dr0_c", "dr2_c", "dr4_c",  "dr6_c",  "dr8_c",  "dr10_c", "dr12_c", "dr14_c",
185b725ae77Skettenis     "fv0_c", "fv4_c", "fv8_c",  "fv12_c",
186b725ae77Skettenis     /* FIXME!!!! XF0 XF15, XD0 XD14 ?????*/
187b725ae77Skettenis   };
188b725ae77Skettenis 
189b725ae77Skettenis   if (reg_nr < 0)
190b725ae77Skettenis     return NULL;
191b725ae77Skettenis   if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
192b725ae77Skettenis     return NULL;
193b725ae77Skettenis   return register_names[reg_nr];
194b725ae77Skettenis }
195b725ae77Skettenis 
196b725ae77Skettenis #define NUM_PSEUDO_REGS_SH_MEDIA 80
197b725ae77Skettenis #define NUM_PSEUDO_REGS_SH_COMPACT 51
198b725ae77Skettenis 
199b725ae77Skettenis /* Macros and functions for setting and testing a bit in a minimal
200b725ae77Skettenis    symbol that marks it as 32-bit function.  The MSB of the minimal
201b725ae77Skettenis    symbol's "info" field is used for this purpose.
202b725ae77Skettenis 
203b725ae77Skettenis    ELF_MAKE_MSYMBOL_SPECIAL
204b725ae77Skettenis    tests whether an ELF symbol is "special", i.e. refers
205b725ae77Skettenis    to a 32-bit function, and sets a "special" bit in a
206b725ae77Skettenis    minimal symbol to mark it as a 32-bit function
207b725ae77Skettenis    MSYMBOL_IS_SPECIAL   tests the "special" bit in a minimal symbol  */
208b725ae77Skettenis 
209b725ae77Skettenis #define MSYMBOL_IS_SPECIAL(msym) \
210b725ae77Skettenis   (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
211b725ae77Skettenis 
212b725ae77Skettenis static void
sh64_elf_make_msymbol_special(asymbol * sym,struct minimal_symbol * msym)213b725ae77Skettenis sh64_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
214b725ae77Skettenis {
215b725ae77Skettenis   if (msym == NULL)
216b725ae77Skettenis     return;
217b725ae77Skettenis 
218b725ae77Skettenis   if (((elf_symbol_type *)(sym))->internal_elf_sym.st_other == STO_SH5_ISA32)
219b725ae77Skettenis     {
220b725ae77Skettenis       MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000);
221b725ae77Skettenis       SYMBOL_VALUE_ADDRESS (msym) |= 1;
222b725ae77Skettenis     }
223b725ae77Skettenis }
224b725ae77Skettenis 
225b725ae77Skettenis /* ISA32 (shmedia) function addresses are odd (bit 0 is set).  Here
226b725ae77Skettenis    are some macros to test, set, or clear bit 0 of addresses.  */
227b725ae77Skettenis #define IS_ISA32_ADDR(addr)	 ((addr) & 1)
228b725ae77Skettenis #define MAKE_ISA32_ADDR(addr)	 ((addr) | 1)
229b725ae77Skettenis #define UNMAKE_ISA32_ADDR(addr)  ((addr) & ~1)
230b725ae77Skettenis 
231b725ae77Skettenis static int
pc_is_isa32(bfd_vma memaddr)232b725ae77Skettenis pc_is_isa32 (bfd_vma memaddr)
233b725ae77Skettenis {
234b725ae77Skettenis   struct minimal_symbol *sym;
235b725ae77Skettenis 
236b725ae77Skettenis   /* If bit 0 of the address is set, assume this is a
237b725ae77Skettenis      ISA32 (shmedia) address.  */
238b725ae77Skettenis   if (IS_ISA32_ADDR (memaddr))
239b725ae77Skettenis     return 1;
240b725ae77Skettenis 
241b725ae77Skettenis   /* A flag indicating that this is a ISA32 function is stored by elfread.c in
242b725ae77Skettenis      the high bit of the info field.  Use this to decide if the function is
243b725ae77Skettenis      ISA16 or ISA32.  */
244b725ae77Skettenis   sym = lookup_minimal_symbol_by_pc (memaddr);
245b725ae77Skettenis   if (sym)
246b725ae77Skettenis     return MSYMBOL_IS_SPECIAL (sym);
247b725ae77Skettenis   else
248b725ae77Skettenis     return 0;
249b725ae77Skettenis }
250b725ae77Skettenis 
251b725ae77Skettenis static const unsigned char *
sh64_breakpoint_from_pc(CORE_ADDR * pcptr,int * lenptr)252b725ae77Skettenis sh64_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
253b725ae77Skettenis {
254b725ae77Skettenis   /* The BRK instruction for shmedia is
255b725ae77Skettenis      01101111 11110101 11111111 11110000
256b725ae77Skettenis      which translates in big endian mode to 0x6f, 0xf5, 0xff, 0xf0
257b725ae77Skettenis      and in little endian mode to 0xf0, 0xff, 0xf5, 0x6f */
258b725ae77Skettenis 
259b725ae77Skettenis   /* The BRK instruction for shcompact is
260b725ae77Skettenis      00000000 00111011
261b725ae77Skettenis      which translates in big endian mode to 0x0, 0x3b
262b725ae77Skettenis      and in little endian mode to 0x3b, 0x0*/
263b725ae77Skettenis 
264b725ae77Skettenis   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
265b725ae77Skettenis     {
266b725ae77Skettenis       if (pc_is_isa32 (*pcptr))
267b725ae77Skettenis 	{
268b725ae77Skettenis 	  static unsigned char big_breakpoint_media[] = {0x6f, 0xf5, 0xff, 0xf0};
269b725ae77Skettenis 	  *pcptr = UNMAKE_ISA32_ADDR (*pcptr);
270b725ae77Skettenis 	  *lenptr = sizeof (big_breakpoint_media);
271b725ae77Skettenis 	  return big_breakpoint_media;
272b725ae77Skettenis 	}
273b725ae77Skettenis       else
274b725ae77Skettenis 	{
275b725ae77Skettenis 	  static unsigned char big_breakpoint_compact[] = {0x0, 0x3b};
276b725ae77Skettenis 	  *lenptr = sizeof (big_breakpoint_compact);
277b725ae77Skettenis 	  return big_breakpoint_compact;
278b725ae77Skettenis 	}
279b725ae77Skettenis     }
280b725ae77Skettenis   else
281b725ae77Skettenis     {
282b725ae77Skettenis       if (pc_is_isa32 (*pcptr))
283b725ae77Skettenis 	{
284b725ae77Skettenis 	  static unsigned char little_breakpoint_media[] = {0xf0, 0xff, 0xf5, 0x6f};
285b725ae77Skettenis 	  *pcptr = UNMAKE_ISA32_ADDR (*pcptr);
286b725ae77Skettenis 	  *lenptr = sizeof (little_breakpoint_media);
287b725ae77Skettenis 	  return little_breakpoint_media;
288b725ae77Skettenis 	}
289b725ae77Skettenis       else
290b725ae77Skettenis 	{
291b725ae77Skettenis 	  static unsigned char little_breakpoint_compact[] = {0x3b, 0x0};
292b725ae77Skettenis 	  *lenptr = sizeof (little_breakpoint_compact);
293b725ae77Skettenis 	  return little_breakpoint_compact;
294b725ae77Skettenis 	}
295b725ae77Skettenis     }
296b725ae77Skettenis }
297b725ae77Skettenis 
298b725ae77Skettenis /* Prologue looks like
299b725ae77Skettenis    [mov.l       <regs>,@-r15]...
300b725ae77Skettenis    [sts.l       pr,@-r15]
301b725ae77Skettenis    [mov.l       r14,@-r15]
302b725ae77Skettenis    [mov         r15,r14]
303b725ae77Skettenis 
304b725ae77Skettenis    Actually it can be more complicated than this.  For instance, with
305b725ae77Skettenis    newer gcc's:
306b725ae77Skettenis 
307b725ae77Skettenis    mov.l   r14,@-r15
308b725ae77Skettenis    add     #-12,r15
309b725ae77Skettenis    mov     r15,r14
310b725ae77Skettenis    mov     r4,r1
311b725ae77Skettenis    mov     r5,r2
312b725ae77Skettenis    mov.l   r6,@(4,r14)
313b725ae77Skettenis    mov.l   r7,@(8,r14)
314b725ae77Skettenis    mov.b   r1,@r14
315b725ae77Skettenis    mov     r14,r1
316b725ae77Skettenis    mov     r14,r1
317b725ae77Skettenis    add     #2,r1
318b725ae77Skettenis    mov.w   r2,@r1
319b725ae77Skettenis 
320b725ae77Skettenis  */
321b725ae77Skettenis 
322b725ae77Skettenis /* PTABS/L Rn, TRa       0110101111110001nnnnnnl00aaa0000
323b725ae77Skettenis    with l=1 and n = 18   0110101111110001010010100aaa0000 */
324b725ae77Skettenis #define IS_PTABSL_R18(x)  (((x) & 0xffffff8f) == 0x6bf14a00)
325b725ae77Skettenis 
326b725ae77Skettenis /* STS.L PR,@-r0   0100000000100010
327b725ae77Skettenis    r0-4-->r0, PR-->(r0) */
328b725ae77Skettenis #define IS_STS_R0(x)  		((x) == 0x4022)
329b725ae77Skettenis 
330b725ae77Skettenis /* STS PR, Rm      0000mmmm00101010
331b725ae77Skettenis    PR-->Rm */
332b725ae77Skettenis #define IS_STS_PR(x)            (((x) & 0xf0ff) == 0x2a)
333b725ae77Skettenis 
334b725ae77Skettenis /* MOV.L Rm,@(disp,r15)  00011111mmmmdddd
335b725ae77Skettenis    Rm-->(dispx4+r15) */
336b725ae77Skettenis #define IS_MOV_TO_R15(x)              (((x) & 0xff00) == 0x1f00)
337b725ae77Skettenis 
338b725ae77Skettenis /* MOV.L R14,@(disp,r15)  000111111110dddd
339b725ae77Skettenis    R14-->(dispx4+r15) */
340b725ae77Skettenis #define IS_MOV_R14(x)              (((x) & 0xfff0) == 0x1fe0)
341b725ae77Skettenis 
342b725ae77Skettenis /* ST.Q R14, disp, R18    101011001110dddddddddd0100100000
343b725ae77Skettenis    R18-->(dispx8+R14) */
344b725ae77Skettenis #define IS_STQ_R18_R14(x)          (((x) & 0xfff003ff) == 0xace00120)
345b725ae77Skettenis 
346b725ae77Skettenis /* ST.Q R15, disp, R18    101011001111dddddddddd0100100000
347b725ae77Skettenis    R18-->(dispx8+R15) */
348b725ae77Skettenis #define IS_STQ_R18_R15(x)          (((x) & 0xfff003ff) == 0xacf00120)
349b725ae77Skettenis 
350b725ae77Skettenis /* ST.L R15, disp, R18    101010001111dddddddddd0100100000
351b725ae77Skettenis    R18-->(dispx4+R15) */
352b725ae77Skettenis #define IS_STL_R18_R15(x)          (((x) & 0xfff003ff) == 0xa8f00120)
353b725ae77Skettenis 
354b725ae77Skettenis /* ST.Q R15, disp, R14    1010 1100 1111 dddd dddd dd00 1110 0000
355b725ae77Skettenis    R14-->(dispx8+R15) */
356b725ae77Skettenis #define IS_STQ_R14_R15(x)          (((x) & 0xfff003ff) == 0xacf000e0)
357b725ae77Skettenis 
358b725ae77Skettenis /* ST.L R15, disp, R14    1010 1000 1111 dddd dddd dd00 1110 0000
359b725ae77Skettenis    R14-->(dispx4+R15) */
360b725ae77Skettenis #define IS_STL_R14_R15(x)          (((x) & 0xfff003ff) == 0xa8f000e0)
361b725ae77Skettenis 
362b725ae77Skettenis /* ADDI.L R15,imm,R15     1101 0100 1111 ssss ssss ss00 1111 0000
363b725ae77Skettenis    R15 + imm --> R15 */
364b725ae77Skettenis #define IS_ADDIL_SP_MEDIA(x)         (((x) & 0xfff003ff) == 0xd4f000f0)
365b725ae77Skettenis 
366b725ae77Skettenis /* ADDI R15,imm,R15     1101 0000 1111 ssss ssss ss00 1111 0000
367b725ae77Skettenis    R15 + imm --> R15 */
368b725ae77Skettenis #define IS_ADDI_SP_MEDIA(x)         (((x) & 0xfff003ff) == 0xd0f000f0)
369b725ae77Skettenis 
370b725ae77Skettenis /* ADD.L R15,R63,R14    0000 0000 1111 1000 1111 1100 1110 0000
371b725ae77Skettenis    R15 + R63 --> R14 */
372b725ae77Skettenis #define IS_ADDL_SP_FP_MEDIA(x)  	((x) == 0x00f8fce0)
373b725ae77Skettenis 
374b725ae77Skettenis /* ADD R15,R63,R14    0000 0000 1111 1001 1111 1100 1110 0000
375b725ae77Skettenis    R15 + R63 --> R14 */
376b725ae77Skettenis #define IS_ADD_SP_FP_MEDIA(x)  	((x) == 0x00f9fce0)
377b725ae77Skettenis 
378b725ae77Skettenis #define IS_MOV_SP_FP_MEDIA(x)  	(IS_ADDL_SP_FP_MEDIA(x) || IS_ADD_SP_FP_MEDIA(x))
379b725ae77Skettenis 
380b725ae77Skettenis /* MOV #imm, R0    1110 0000 ssss ssss
381b725ae77Skettenis    #imm-->R0 */
382b725ae77Skettenis #define IS_MOV_R0(x) 		(((x) & 0xff00) == 0xe000)
383b725ae77Skettenis 
384b725ae77Skettenis /* MOV.L @(disp,PC), R0    1101 0000 iiii iiii  */
385b725ae77Skettenis #define IS_MOVL_R0(x) 		(((x) & 0xff00) == 0xd000)
386b725ae77Skettenis 
387b725ae77Skettenis /* ADD r15,r0      0011 0000 1111 1100
388b725ae77Skettenis    r15+r0-->r0 */
389b725ae77Skettenis #define IS_ADD_SP_R0(x)	        ((x) == 0x30fc)
390b725ae77Skettenis 
391b725ae77Skettenis /* MOV.L R14 @-R0  0010 0000 1110 0110
392b725ae77Skettenis    R14-->(R0-4), R0-4-->R0 */
393b725ae77Skettenis #define IS_MOV_R14_R0(x)        ((x) == 0x20e6)
394b725ae77Skettenis 
395b725ae77Skettenis /* ADD Rm,R63,Rn  Rm+R63-->Rn  0000 00mm mmmm 1001 1111 11nn nnnn 0000
396b725ae77Skettenis    where Rm is one of r2-r9 which are the argument registers.  */
397b725ae77Skettenis /* FIXME: Recognize the float and double register moves too! */
398b725ae77Skettenis #define IS_MEDIA_IND_ARG_MOV(x) \
399b725ae77Skettenis ((((x) & 0xfc0ffc0f) == 0x0009fc00) && (((x) & 0x03f00000) >= 0x00200000 && ((x) & 0x03f00000) <= 0x00900000))
400b725ae77Skettenis 
401b725ae77Skettenis /* ST.Q Rn,0,Rm  Rm-->Rn+0  1010 11nn nnnn 0000 0000 00mm mmmm 0000
402b725ae77Skettenis    or ST.L Rn,0,Rm  Rm-->Rn+0  1010 10nn nnnn 0000 0000 00mm mmmm 0000
403b725ae77Skettenis    where Rm is one of r2-r9 which are the argument registers.  */
404b725ae77Skettenis #define IS_MEDIA_ARG_MOV(x) \
405b725ae77Skettenis (((((x) & 0xfc0ffc0f) == 0xac000000) || (((x) & 0xfc0ffc0f) == 0xa8000000)) \
406b725ae77Skettenis    && (((x) & 0x000003f0) >= 0x00000020 && ((x) & 0x000003f0) <= 0x00000090))
407b725ae77Skettenis 
408b725ae77Skettenis /* ST.B R14,0,Rn     Rn-->(R14+0) 1010 0000 1110 0000 0000 00nn nnnn 0000*/
409b725ae77Skettenis /* ST.W R14,0,Rn     Rn-->(R14+0) 1010 0100 1110 0000 0000 00nn nnnn 0000*/
410b725ae77Skettenis /* ST.L R14,0,Rn     Rn-->(R14+0) 1010 1000 1110 0000 0000 00nn nnnn 0000*/
411b725ae77Skettenis /* FST.S R14,0,FRn   Rn-->(R14+0) 1011 0100 1110 0000 0000 00nn nnnn 0000*/
412b725ae77Skettenis /* FST.D R14,0,DRn   Rn-->(R14+0) 1011 1100 1110 0000 0000 00nn nnnn 0000*/
413b725ae77Skettenis #define IS_MEDIA_MOV_TO_R14(x)  \
414b725ae77Skettenis ((((x) & 0xfffffc0f) == 0xa0e00000) \
415b725ae77Skettenis || (((x) & 0xfffffc0f) == 0xa4e00000) \
416b725ae77Skettenis || (((x) & 0xfffffc0f) == 0xa8e00000) \
417b725ae77Skettenis || (((x) & 0xfffffc0f) == 0xb4e00000) \
418b725ae77Skettenis || (((x) & 0xfffffc0f) == 0xbce00000))
419b725ae77Skettenis 
420b725ae77Skettenis /* MOV Rm, Rn  Rm-->Rn 0110 nnnn mmmm 0011
421b725ae77Skettenis    where Rm is r2-r9 */
422b725ae77Skettenis #define IS_COMPACT_IND_ARG_MOV(x) \
423b725ae77Skettenis ((((x) & 0xf00f) == 0x6003) && (((x) & 0x00f0) >= 0x0020) && (((x) & 0x00f0) <= 0x0090))
424b725ae77Skettenis 
425b725ae77Skettenis /* compact direct arg move!
426b725ae77Skettenis    MOV.L Rn, @r14     0010 1110 mmmm 0010 */
427b725ae77Skettenis #define IS_COMPACT_ARG_MOV(x) \
428b725ae77Skettenis (((((x) & 0xff0f) == 0x2e02) && (((x) & 0x00f0) >= 0x0020) && ((x) & 0x00f0) <= 0x0090))
429b725ae77Skettenis 
430b725ae77Skettenis /* MOV.B Rm, @R14     0010 1110 mmmm 0000
431b725ae77Skettenis    MOV.W Rm, @R14     0010 1110 mmmm 0001 */
432b725ae77Skettenis #define IS_COMPACT_MOV_TO_R14(x) \
433b725ae77Skettenis ((((x) & 0xff0f) == 0x2e00) || (((x) & 0xff0f) == 0x2e01))
434b725ae77Skettenis 
435b725ae77Skettenis #define IS_JSR_R0(x)           ((x) == 0x400b)
436b725ae77Skettenis #define IS_NOP(x)              ((x) == 0x0009)
437b725ae77Skettenis 
438b725ae77Skettenis 
439b725ae77Skettenis /* MOV r15,r14     0110111011110011
440b725ae77Skettenis    r15-->r14  */
441b725ae77Skettenis #define IS_MOV_SP_FP(x)  	((x) == 0x6ef3)
442b725ae77Skettenis 
443b725ae77Skettenis /* ADD #imm,r15    01111111iiiiiiii
444b725ae77Skettenis    r15+imm-->r15 */
445b725ae77Skettenis #define IS_ADD_SP(x) 		(((x) & 0xff00) == 0x7f00)
446b725ae77Skettenis 
447b725ae77Skettenis /* Skip any prologue before the guts of a function */
448b725ae77Skettenis 
449b725ae77Skettenis /* Skip the prologue using the debug information.  If this fails we'll
450b725ae77Skettenis    fall back on the 'guess' method below.  */
451b725ae77Skettenis static CORE_ADDR
after_prologue(CORE_ADDR pc)452b725ae77Skettenis after_prologue (CORE_ADDR pc)
453b725ae77Skettenis {
454b725ae77Skettenis   struct symtab_and_line sal;
455b725ae77Skettenis   CORE_ADDR func_addr, func_end;
456b725ae77Skettenis 
457b725ae77Skettenis   /* If we can not find the symbol in the partial symbol table, then
458b725ae77Skettenis      there is no hope we can determine the function's start address
459b725ae77Skettenis      with this code.  */
460b725ae77Skettenis   if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
461b725ae77Skettenis     return 0;
462b725ae77Skettenis 
463b725ae77Skettenis   /* Get the line associated with FUNC_ADDR.  */
464b725ae77Skettenis   sal = find_pc_line (func_addr, 0);
465b725ae77Skettenis 
466b725ae77Skettenis   /* There are only two cases to consider.  First, the end of the source line
467b725ae77Skettenis      is within the function bounds.  In that case we return the end of the
468b725ae77Skettenis      source line.  Second is the end of the source line extends beyond the
469b725ae77Skettenis      bounds of the current function.  We need to use the slow code to
470b725ae77Skettenis      examine instructions in that case.  */
471b725ae77Skettenis   if (sal.end < func_end)
472b725ae77Skettenis     return sal.end;
473b725ae77Skettenis   else
474b725ae77Skettenis     return 0;
475b725ae77Skettenis }
476b725ae77Skettenis 
477b725ae77Skettenis static CORE_ADDR
look_for_args_moves(CORE_ADDR start_pc,int media_mode)478b725ae77Skettenis look_for_args_moves (CORE_ADDR start_pc, int media_mode)
479b725ae77Skettenis {
480b725ae77Skettenis   CORE_ADDR here, end;
481b725ae77Skettenis   int w;
482b725ae77Skettenis   int insn_size = (media_mode ? 4 : 2);
483b725ae77Skettenis 
484b725ae77Skettenis   for (here = start_pc, end = start_pc + (insn_size * 28); here < end;)
485b725ae77Skettenis     {
486b725ae77Skettenis       if (media_mode)
487b725ae77Skettenis 	{
488b725ae77Skettenis 	  w = read_memory_integer (UNMAKE_ISA32_ADDR (here), insn_size);
489b725ae77Skettenis 	  here += insn_size;
490b725ae77Skettenis 	  if (IS_MEDIA_IND_ARG_MOV (w))
491b725ae77Skettenis 	    {
492b725ae77Skettenis 	      /* This must be followed by a store to r14, so the argument
493b725ae77Skettenis 		 is where the debug info says it is. This can happen after
494b725ae77Skettenis 		 the SP has been saved, unfortunately.  */
495b725ae77Skettenis 
496b725ae77Skettenis 	      int next_insn = read_memory_integer (UNMAKE_ISA32_ADDR (here),
497b725ae77Skettenis 						   insn_size);
498b725ae77Skettenis 	      here += insn_size;
499b725ae77Skettenis 	      if (IS_MEDIA_MOV_TO_R14 (next_insn))
500b725ae77Skettenis 		start_pc = here;
501b725ae77Skettenis 	    }
502b725ae77Skettenis 	  else if (IS_MEDIA_ARG_MOV (w))
503b725ae77Skettenis 	    {
504b725ae77Skettenis 	      /* These instructions store directly the argument in r14.  */
505b725ae77Skettenis 	      start_pc = here;
506b725ae77Skettenis 	    }
507b725ae77Skettenis 	  else
508b725ae77Skettenis 	    break;
509b725ae77Skettenis 	}
510b725ae77Skettenis       else
511b725ae77Skettenis 	{
512b725ae77Skettenis 	  w = read_memory_integer (here, insn_size);
513b725ae77Skettenis 	  w = w & 0xffff;
514b725ae77Skettenis 	  here += insn_size;
515b725ae77Skettenis 	  if (IS_COMPACT_IND_ARG_MOV (w))
516b725ae77Skettenis 	    {
517b725ae77Skettenis 	      /* This must be followed by a store to r14, so the argument
518b725ae77Skettenis 		 is where the debug info says it is. This can happen after
519b725ae77Skettenis 		 the SP has been saved, unfortunately.  */
520b725ae77Skettenis 
521b725ae77Skettenis 	      int next_insn = 0xffff & read_memory_integer (here, insn_size);
522b725ae77Skettenis 	      here += insn_size;
523b725ae77Skettenis 	      if (IS_COMPACT_MOV_TO_R14 (next_insn))
524b725ae77Skettenis 		start_pc = here;
525b725ae77Skettenis 	    }
526b725ae77Skettenis 	  else if (IS_COMPACT_ARG_MOV (w))
527b725ae77Skettenis 	    {
528b725ae77Skettenis 	      /* These instructions store directly the argument in r14.  */
529b725ae77Skettenis 	      start_pc = here;
530b725ae77Skettenis 	    }
531b725ae77Skettenis 	  else if (IS_MOVL_R0 (w))
532b725ae77Skettenis 	    {
533b725ae77Skettenis 	      /* There is a function that gcc calls to get the arguments
534b725ae77Skettenis 		 passed correctly to the function. Only after this
535b725ae77Skettenis 		 function call the arguments will be found at the place
536b725ae77Skettenis 		 where they are supposed to be. This happens in case the
537b725ae77Skettenis 		 argument has to be stored into a 64-bit register (for
538b725ae77Skettenis 		 instance doubles, long longs).  SHcompact doesn't have
539b725ae77Skettenis 		 access to the full 64-bits, so we store the register in
540b725ae77Skettenis 		 stack slot and store the address of the stack slot in
541b725ae77Skettenis 		 the register, then do a call through a wrapper that
542b725ae77Skettenis 		 loads the memory value into the register.  A SHcompact
543b725ae77Skettenis 		 callee calls an argument decoder
544b725ae77Skettenis 		 (GCC_shcompact_incoming_args) that stores the 64-bit
545b725ae77Skettenis 		 value in a stack slot and stores the address of the
546b725ae77Skettenis 		 stack slot in the register.  GCC thinks the argument is
547b725ae77Skettenis 		 just passed by transparent reference, but this is only
548b725ae77Skettenis 		 true after the argument decoder is called. Such a call
549b725ae77Skettenis 		 needs to be considered part of the prologue.  */
550b725ae77Skettenis 
551b725ae77Skettenis 	      /* This must be followed by a JSR @r0 instruction and by
552b725ae77Skettenis                  a NOP instruction. After these, the prologue is over!  */
553b725ae77Skettenis 
554b725ae77Skettenis 	      int next_insn = 0xffff & read_memory_integer (here, insn_size);
555b725ae77Skettenis 	      here += insn_size;
556b725ae77Skettenis 	      if (IS_JSR_R0 (next_insn))
557b725ae77Skettenis 		{
558b725ae77Skettenis 		  next_insn = 0xffff & read_memory_integer (here, insn_size);
559b725ae77Skettenis 		  here += insn_size;
560b725ae77Skettenis 
561b725ae77Skettenis 		  if (IS_NOP (next_insn))
562b725ae77Skettenis 		    start_pc = here;
563b725ae77Skettenis 		}
564b725ae77Skettenis 	    }
565b725ae77Skettenis 	  else
566b725ae77Skettenis 	    break;
567b725ae77Skettenis 	}
568b725ae77Skettenis     }
569b725ae77Skettenis 
570b725ae77Skettenis   return start_pc;
571b725ae77Skettenis }
572b725ae77Skettenis 
573b725ae77Skettenis static CORE_ADDR
sh64_skip_prologue_hard_way(CORE_ADDR start_pc)574b725ae77Skettenis sh64_skip_prologue_hard_way (CORE_ADDR start_pc)
575b725ae77Skettenis {
576b725ae77Skettenis   CORE_ADDR here, end;
577b725ae77Skettenis   int updated_fp = 0;
578b725ae77Skettenis   int insn_size = 4;
579b725ae77Skettenis   int media_mode = 1;
580b725ae77Skettenis 
581b725ae77Skettenis   if (!start_pc)
582b725ae77Skettenis     return 0;
583b725ae77Skettenis 
584b725ae77Skettenis   if (pc_is_isa32 (start_pc) == 0)
585b725ae77Skettenis     {
586b725ae77Skettenis       insn_size = 2;
587b725ae77Skettenis       media_mode = 0;
588b725ae77Skettenis     }
589b725ae77Skettenis 
590b725ae77Skettenis   for (here = start_pc, end = start_pc + (insn_size * 28); here < end;)
591b725ae77Skettenis     {
592b725ae77Skettenis 
593b725ae77Skettenis       if (media_mode)
594b725ae77Skettenis 	{
595b725ae77Skettenis 	  int w = read_memory_integer (UNMAKE_ISA32_ADDR (here), insn_size);
596b725ae77Skettenis 	  here += insn_size;
597b725ae77Skettenis 	  if (IS_STQ_R18_R14 (w) || IS_STQ_R18_R15 (w) || IS_STQ_R14_R15 (w)
598b725ae77Skettenis 	      || IS_STL_R14_R15 (w) || IS_STL_R18_R15 (w)
599b725ae77Skettenis 	      || IS_ADDIL_SP_MEDIA (w) || IS_ADDI_SP_MEDIA (w) || IS_PTABSL_R18 (w))
600b725ae77Skettenis 	    {
601b725ae77Skettenis 	      start_pc = here;
602b725ae77Skettenis 	    }
603b725ae77Skettenis 	  else if (IS_MOV_SP_FP (w) || IS_MOV_SP_FP_MEDIA(w))
604b725ae77Skettenis 	    {
605b725ae77Skettenis 	      start_pc = here;
606b725ae77Skettenis 	      updated_fp = 1;
607b725ae77Skettenis 	    }
608b725ae77Skettenis 	  else
609b725ae77Skettenis 	    if (updated_fp)
610b725ae77Skettenis 	      {
611b725ae77Skettenis 		/* Don't bail out yet, we may have arguments stored in
612b725ae77Skettenis 		   registers here, according to the debug info, so that
613b725ae77Skettenis 		   gdb can print the frames correctly.  */
614b725ae77Skettenis 		start_pc = look_for_args_moves (here - insn_size, media_mode);
615b725ae77Skettenis 		break;
616b725ae77Skettenis 	      }
617b725ae77Skettenis 	}
618b725ae77Skettenis       else
619b725ae77Skettenis 	{
620b725ae77Skettenis 	  int w = 0xffff & read_memory_integer (here, insn_size);
621b725ae77Skettenis 	  here += insn_size;
622b725ae77Skettenis 
623b725ae77Skettenis 	  if (IS_STS_R0 (w) || IS_STS_PR (w)
624b725ae77Skettenis 	      || IS_MOV_TO_R15 (w) || IS_MOV_R14 (w)
625b725ae77Skettenis 	      || IS_MOV_R0 (w) || IS_ADD_SP_R0 (w) || IS_MOV_R14_R0 (w))
626b725ae77Skettenis 	    {
627b725ae77Skettenis 	      start_pc = here;
628b725ae77Skettenis 	    }
629b725ae77Skettenis 	  else if (IS_MOV_SP_FP (w))
630b725ae77Skettenis 	    {
631b725ae77Skettenis 	      start_pc = here;
632b725ae77Skettenis 	      updated_fp = 1;
633b725ae77Skettenis 	    }
634b725ae77Skettenis 	  else
635b725ae77Skettenis 	    if (updated_fp)
636b725ae77Skettenis 	      {
637b725ae77Skettenis 		/* Don't bail out yet, we may have arguments stored in
638b725ae77Skettenis 		   registers here, according to the debug info, so that
639b725ae77Skettenis 		   gdb can print the frames correctly.  */
640b725ae77Skettenis 		start_pc = look_for_args_moves (here - insn_size, media_mode);
641b725ae77Skettenis 		break;
642b725ae77Skettenis 	      }
643b725ae77Skettenis 	}
644b725ae77Skettenis     }
645b725ae77Skettenis 
646b725ae77Skettenis   return start_pc;
647b725ae77Skettenis }
648b725ae77Skettenis 
649b725ae77Skettenis static CORE_ADDR
sh_skip_prologue(CORE_ADDR pc)650b725ae77Skettenis sh_skip_prologue (CORE_ADDR pc)
651b725ae77Skettenis {
652b725ae77Skettenis   CORE_ADDR post_prologue_pc;
653b725ae77Skettenis 
654b725ae77Skettenis   /* See if we can determine the end of the prologue via the symbol table.
655b725ae77Skettenis      If so, then return either PC, or the PC after the prologue, whichever
656b725ae77Skettenis      is greater.  */
657b725ae77Skettenis   post_prologue_pc = after_prologue (pc);
658b725ae77Skettenis 
659b725ae77Skettenis   /* If after_prologue returned a useful address, then use it.  Else
660b725ae77Skettenis      fall back on the instruction skipping code.  */
661b725ae77Skettenis   if (post_prologue_pc != 0)
662b725ae77Skettenis     return max (pc, post_prologue_pc);
663b725ae77Skettenis   else
664b725ae77Skettenis     return sh64_skip_prologue_hard_way (pc);
665b725ae77Skettenis }
666b725ae77Skettenis 
667b725ae77Skettenis /* Immediately after a function call, return the saved pc.
668b725ae77Skettenis    Can't always go through the frames for this because on some machines
669b725ae77Skettenis    the new frame is not set up until the new function executes
670b725ae77Skettenis    some instructions.
671b725ae77Skettenis 
672b725ae77Skettenis    The return address is the value saved in the PR register + 4  */
673b725ae77Skettenis static CORE_ADDR
sh_saved_pc_after_call(struct frame_info * frame)674b725ae77Skettenis sh_saved_pc_after_call (struct frame_info *frame)
675b725ae77Skettenis {
676b725ae77Skettenis   return (ADDR_BITS_REMOVE (read_register (PR_REGNUM)));
677b725ae77Skettenis }
678b725ae77Skettenis 
679b725ae77Skettenis /* Should call_function allocate stack space for a struct return?  */
680b725ae77Skettenis static int
sh64_use_struct_convention(int gcc_p,struct type * type)681b725ae77Skettenis sh64_use_struct_convention (int gcc_p, struct type *type)
682b725ae77Skettenis {
683b725ae77Skettenis   return (TYPE_LENGTH (type) > 8);
684b725ae77Skettenis }
685b725ae77Skettenis 
686b725ae77Skettenis /* Store the address of the place in which to copy the structure the
687b725ae77Skettenis    subroutine will return.  This is called from call_function.
688b725ae77Skettenis 
689b725ae77Skettenis    We store structs through a pointer passed in R2 */
690b725ae77Skettenis static void
sh64_store_struct_return(CORE_ADDR addr,CORE_ADDR sp)691b725ae77Skettenis sh64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
692b725ae77Skettenis {
693b725ae77Skettenis   write_register (STRUCT_RETURN_REGNUM, (addr));
694b725ae77Skettenis }
695b725ae77Skettenis 
696b725ae77Skettenis /* Disassemble an instruction.  */
697b725ae77Skettenis static int
gdb_print_insn_sh(bfd_vma memaddr,disassemble_info * info)698b725ae77Skettenis gdb_print_insn_sh (bfd_vma memaddr, disassemble_info *info)
699b725ae77Skettenis {
700b725ae77Skettenis   info->endian = TARGET_BYTE_ORDER;
701b725ae77Skettenis   return print_insn_sh (memaddr, info);
702b725ae77Skettenis }
703b725ae77Skettenis 
704b725ae77Skettenis /* Given a register number RN as it appears in an assembly
705b725ae77Skettenis    instruction, find the corresponding register number in the GDB
706b725ae77Skettenis    scheme.  */
707b725ae77Skettenis static int
translate_insn_rn(int rn,int media_mode)708b725ae77Skettenis translate_insn_rn (int rn, int media_mode)
709b725ae77Skettenis {
710b725ae77Skettenis   /* FIXME: this assumes that the number rn is for a not pseudo
711b725ae77Skettenis      register only.  */
712b725ae77Skettenis   if (media_mode)
713b725ae77Skettenis     return rn;
714b725ae77Skettenis   else
715b725ae77Skettenis     {
716b725ae77Skettenis       /* These registers don't have a corresponding compact one.  */
717b725ae77Skettenis       /* FIXME: This is probably not enough.  */
718b725ae77Skettenis #if 0
719b725ae77Skettenis       if ((rn >= 16 && rn <= 63) || (rn >= 93 && rn <= 140))
720b725ae77Skettenis 	return rn;
721b725ae77Skettenis #endif
722b725ae77Skettenis       if (rn >= 0 && rn <= R0_C_REGNUM)
723b725ae77Skettenis 	return R0_C_REGNUM + rn;
724b725ae77Skettenis       else
725b725ae77Skettenis 	return rn;
726b725ae77Skettenis     }
727b725ae77Skettenis }
728b725ae77Skettenis 
729b725ae77Skettenis /* Given a GDB frame, determine the address of the calling function's
730b725ae77Skettenis    frame.  This will be used to create a new GDB frame struct, and
731b725ae77Skettenis    then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
732b725ae77Skettenis    will be called for the new frame.
733b725ae77Skettenis 
734b725ae77Skettenis    For us, the frame address is its stack pointer value, so we look up
735b725ae77Skettenis    the function prologue to determine the caller's sp value, and return it.  */
736b725ae77Skettenis static CORE_ADDR
sh64_frame_chain(struct frame_info * frame)737b725ae77Skettenis sh64_frame_chain (struct frame_info *frame)
738b725ae77Skettenis {
739*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
740b725ae77Skettenis     return get_frame_base (frame);    /* dummy frame same as caller's frame */
741*11efff7fSkettenis   if (get_frame_pc (frame))
742b725ae77Skettenis     {
743b725ae77Skettenis       int media_mode = pc_is_isa32 (get_frame_pc (frame));
744b725ae77Skettenis       int size;
745b725ae77Skettenis       if (gdbarch_tdep (current_gdbarch)->sh_abi == SH_ABI_32)
746b725ae77Skettenis 	size = 4;
747b725ae77Skettenis       else
748b725ae77Skettenis 	size = register_size (current_gdbarch,
749b725ae77Skettenis 			      translate_insn_rn (DEPRECATED_FP_REGNUM,
750b725ae77Skettenis 						 media_mode));
751b725ae77Skettenis       return read_memory_integer (get_frame_base (frame)
752b725ae77Skettenis 				  + get_frame_extra_info (frame)->f_offset,
753b725ae77Skettenis 				  size);
754b725ae77Skettenis     }
755b725ae77Skettenis   else
756b725ae77Skettenis     return 0;
757b725ae77Skettenis }
758b725ae77Skettenis 
759b725ae77Skettenis static CORE_ADDR
sh64_get_saved_pr(struct frame_info * fi,int pr_regnum)760b725ae77Skettenis sh64_get_saved_pr (struct frame_info *fi, int pr_regnum)
761b725ae77Skettenis {
762b725ae77Skettenis   int media_mode = 0;
763b725ae77Skettenis 
764b725ae77Skettenis   for (; fi; fi = get_next_frame (fi))
765*11efff7fSkettenis     if (deprecated_pc_in_call_dummy (get_frame_pc (fi)))
766b725ae77Skettenis       /* When the caller requests PR from the dummy frame, we return
767b725ae77Skettenis          PC because that's where the previous routine appears to have
768b725ae77Skettenis          done a call from.  */
769b725ae77Skettenis       return deprecated_read_register_dummy (get_frame_pc (fi),
770b725ae77Skettenis 					     get_frame_base (fi), pr_regnum);
771b725ae77Skettenis     else
772b725ae77Skettenis       {
773b725ae77Skettenis 	DEPRECATED_FRAME_INIT_SAVED_REGS (fi);
774b725ae77Skettenis 	if (!get_frame_pc (fi))
775b725ae77Skettenis 	  return 0;
776b725ae77Skettenis 
777b725ae77Skettenis 	media_mode = pc_is_isa32 (get_frame_pc (fi));
778b725ae77Skettenis 
779b725ae77Skettenis 	if (deprecated_get_frame_saved_regs (fi)[pr_regnum] != 0)
780b725ae77Skettenis 	  {
781b725ae77Skettenis 	    int gdb_reg_num = translate_insn_rn (pr_regnum, media_mode);
782b725ae77Skettenis 	    int size = ((gdbarch_tdep (current_gdbarch)->sh_abi == SH_ABI_32)
783b725ae77Skettenis 			? 4
784b725ae77Skettenis 			: register_size (current_gdbarch, gdb_reg_num));
785b725ae77Skettenis 	    return read_memory_integer (deprecated_get_frame_saved_regs (fi)[pr_regnum], size);
786b725ae77Skettenis 	  }
787b725ae77Skettenis       }
788b725ae77Skettenis   return read_register (pr_regnum);
789b725ae77Skettenis }
790b725ae77Skettenis 
791b725ae77Skettenis /* For vectors of 4 floating point registers.  */
792b725ae77Skettenis static int
fv_reg_base_num(int fv_regnum)793b725ae77Skettenis fv_reg_base_num (int fv_regnum)
794b725ae77Skettenis {
795b725ae77Skettenis   int fp_regnum;
796b725ae77Skettenis 
797b725ae77Skettenis   fp_regnum = FP0_REGNUM +
798b725ae77Skettenis     (fv_regnum - FV0_REGNUM) * 4;
799b725ae77Skettenis   return fp_regnum;
800b725ae77Skettenis }
801b725ae77Skettenis 
802b725ae77Skettenis /* For double precision floating point registers, i.e 2 fp regs.*/
803b725ae77Skettenis static int
dr_reg_base_num(int dr_regnum)804b725ae77Skettenis dr_reg_base_num (int dr_regnum)
805b725ae77Skettenis {
806b725ae77Skettenis   int fp_regnum;
807b725ae77Skettenis 
808b725ae77Skettenis   fp_regnum = FP0_REGNUM +
809b725ae77Skettenis     (dr_regnum - DR0_REGNUM) * 2;
810b725ae77Skettenis   return fp_regnum;
811b725ae77Skettenis }
812b725ae77Skettenis 
813b725ae77Skettenis /* For pairs of floating point registers */
814b725ae77Skettenis static int
fpp_reg_base_num(int fpp_regnum)815b725ae77Skettenis fpp_reg_base_num (int fpp_regnum)
816b725ae77Skettenis {
817b725ae77Skettenis   int fp_regnum;
818b725ae77Skettenis 
819b725ae77Skettenis   fp_regnum = FP0_REGNUM +
820b725ae77Skettenis     (fpp_regnum - FPP0_REGNUM) * 2;
821b725ae77Skettenis   return fp_regnum;
822b725ae77Skettenis }
823b725ae77Skettenis 
824b725ae77Skettenis static int
is_media_pseudo(int rn)825b725ae77Skettenis is_media_pseudo (int rn)
826b725ae77Skettenis {
827b725ae77Skettenis   return (rn >= DR0_REGNUM && rn <= FV_LAST_REGNUM);
828b725ae77Skettenis }
829b725ae77Skettenis 
830b725ae77Skettenis static int
sh64_media_reg_base_num(int reg_nr)831b725ae77Skettenis sh64_media_reg_base_num (int reg_nr)
832b725ae77Skettenis {
833b725ae77Skettenis   int base_regnum = -1;
834b725ae77Skettenis 
835b725ae77Skettenis   if (reg_nr >= DR0_REGNUM
836b725ae77Skettenis       && reg_nr <= DR_LAST_REGNUM)
837b725ae77Skettenis     base_regnum = dr_reg_base_num (reg_nr);
838b725ae77Skettenis 
839b725ae77Skettenis   else if (reg_nr >= FPP0_REGNUM
840b725ae77Skettenis 	   && reg_nr <= FPP_LAST_REGNUM)
841b725ae77Skettenis     base_regnum = fpp_reg_base_num (reg_nr);
842b725ae77Skettenis 
843b725ae77Skettenis   else if (reg_nr >= FV0_REGNUM
844b725ae77Skettenis 	   && reg_nr <= FV_LAST_REGNUM)
845b725ae77Skettenis     base_regnum = fv_reg_base_num (reg_nr);
846b725ae77Skettenis 
847b725ae77Skettenis   return base_regnum;
848b725ae77Skettenis }
849b725ae77Skettenis 
850b725ae77Skettenis /* *INDENT-OFF* */
851b725ae77Skettenis /*
852b725ae77Skettenis     SH COMPACT MODE (ISA 16) (all pseudo) 221-272
853b725ae77Skettenis        GDB_REGNUM  BASE_REGNUM
854b725ae77Skettenis  r0_c       221      0
855b725ae77Skettenis  r1_c       222      1
856b725ae77Skettenis  r2_c       223      2
857b725ae77Skettenis  r3_c       224      3
858b725ae77Skettenis  r4_c       225      4
859b725ae77Skettenis  r5_c       226      5
860b725ae77Skettenis  r6_c       227      6
861b725ae77Skettenis  r7_c       228      7
862b725ae77Skettenis  r8_c       229      8
863b725ae77Skettenis  r9_c       230      9
864b725ae77Skettenis  r10_c      231      10
865b725ae77Skettenis  r11_c      232      11
866b725ae77Skettenis  r12_c      233      12
867b725ae77Skettenis  r13_c      234      13
868b725ae77Skettenis  r14_c      235      14
869b725ae77Skettenis  r15_c      236      15
870b725ae77Skettenis 
871b725ae77Skettenis  pc_c       237      64
872b725ae77Skettenis  gbr_c      238      16
873b725ae77Skettenis  mach_c     239      17
874b725ae77Skettenis  macl_c     240      17
875b725ae77Skettenis  pr_c       241      18
876b725ae77Skettenis  t_c        242      19
877b725ae77Skettenis  fpscr_c    243      76
878b725ae77Skettenis  fpul_c     244      109
879b725ae77Skettenis 
880b725ae77Skettenis  fr0_c      245      77
881b725ae77Skettenis  fr1_c      246      78
882b725ae77Skettenis  fr2_c      247      79
883b725ae77Skettenis  fr3_c      248      80
884b725ae77Skettenis  fr4_c      249      81
885b725ae77Skettenis  fr5_c      250      82
886b725ae77Skettenis  fr6_c      251      83
887b725ae77Skettenis  fr7_c      252      84
888b725ae77Skettenis  fr8_c      253      85
889b725ae77Skettenis  fr9_c      254      86
890b725ae77Skettenis  fr10_c     255      87
891b725ae77Skettenis  fr11_c     256      88
892b725ae77Skettenis  fr12_c     257      89
893b725ae77Skettenis  fr13_c     258      90
894b725ae77Skettenis  fr14_c     259      91
895b725ae77Skettenis  fr15_c     260      92
896b725ae77Skettenis 
897b725ae77Skettenis  dr0_c      261      77
898b725ae77Skettenis  dr2_c      262      79
899b725ae77Skettenis  dr4_c      263      81
900b725ae77Skettenis  dr6_c      264      83
901b725ae77Skettenis  dr8_c      265      85
902b725ae77Skettenis  dr10_c     266      87
903b725ae77Skettenis  dr12_c     267      89
904b725ae77Skettenis  dr14_c     268      91
905b725ae77Skettenis 
906b725ae77Skettenis  fv0_c      269      77
907b725ae77Skettenis  fv4_c      270      81
908b725ae77Skettenis  fv8_c      271      85
909b725ae77Skettenis  fv12_c     272      91
910b725ae77Skettenis */
911b725ae77Skettenis /* *INDENT-ON* */
912b725ae77Skettenis static int
sh64_compact_reg_base_num(int reg_nr)913b725ae77Skettenis sh64_compact_reg_base_num (int reg_nr)
914b725ae77Skettenis {
915b725ae77Skettenis   int base_regnum = -1;
916b725ae77Skettenis 
917b725ae77Skettenis   /* general register N maps to general register N */
918b725ae77Skettenis   if (reg_nr >= R0_C_REGNUM
919b725ae77Skettenis       && reg_nr <= R_LAST_C_REGNUM)
920b725ae77Skettenis     base_regnum = reg_nr - R0_C_REGNUM;
921b725ae77Skettenis 
922b725ae77Skettenis   /* floating point register N maps to floating point register N */
923b725ae77Skettenis   else if (reg_nr >= FP0_C_REGNUM
924b725ae77Skettenis 	    && reg_nr <= FP_LAST_C_REGNUM)
925b725ae77Skettenis     base_regnum = reg_nr - FP0_C_REGNUM + FP0_REGNUM;
926b725ae77Skettenis 
927b725ae77Skettenis   /* double prec register N maps to base regnum for double prec register N */
928b725ae77Skettenis   else if (reg_nr >= DR0_C_REGNUM
929b725ae77Skettenis 	    && reg_nr <= DR_LAST_C_REGNUM)
930b725ae77Skettenis     base_regnum = dr_reg_base_num (DR0_REGNUM
931b725ae77Skettenis 				   + reg_nr - DR0_C_REGNUM);
932b725ae77Skettenis 
933b725ae77Skettenis   /* vector N maps to base regnum for vector register N */
934b725ae77Skettenis   else if (reg_nr >= FV0_C_REGNUM
935b725ae77Skettenis 	    && reg_nr <= FV_LAST_C_REGNUM)
936b725ae77Skettenis     base_regnum = fv_reg_base_num (FV0_REGNUM
937b725ae77Skettenis 				   + reg_nr - FV0_C_REGNUM);
938b725ae77Skettenis 
939b725ae77Skettenis   else if (reg_nr == PC_C_REGNUM)
940b725ae77Skettenis     base_regnum = PC_REGNUM;
941b725ae77Skettenis 
942b725ae77Skettenis   else if (reg_nr == GBR_C_REGNUM)
943b725ae77Skettenis     base_regnum = 16;
944b725ae77Skettenis 
945b725ae77Skettenis   else if (reg_nr == MACH_C_REGNUM
946b725ae77Skettenis 	   || reg_nr == MACL_C_REGNUM)
947b725ae77Skettenis     base_regnum = 17;
948b725ae77Skettenis 
949b725ae77Skettenis   else if (reg_nr == PR_C_REGNUM)
950b725ae77Skettenis     base_regnum = 18;
951b725ae77Skettenis 
952b725ae77Skettenis   else if (reg_nr == T_C_REGNUM)
953b725ae77Skettenis     base_regnum = 19;
954b725ae77Skettenis 
955b725ae77Skettenis   else if (reg_nr == FPSCR_C_REGNUM)
956b725ae77Skettenis     base_regnum = FPSCR_REGNUM; /*???? this register is a mess.  */
957b725ae77Skettenis 
958b725ae77Skettenis   else if (reg_nr == FPUL_C_REGNUM)
959b725ae77Skettenis     base_regnum = FP0_REGNUM + 32;
960b725ae77Skettenis 
961b725ae77Skettenis   return base_regnum;
962b725ae77Skettenis }
963b725ae77Skettenis 
964b725ae77Skettenis /* Given a register number RN (according to the gdb scheme) , return
965b725ae77Skettenis    its corresponding architectural register.  In media mode, only a
966b725ae77Skettenis    subset of the registers is pseudo registers. For compact mode, all
967b725ae77Skettenis    the registers are pseudo.  */
968b725ae77Skettenis static int
translate_rn_to_arch_reg_num(int rn,int media_mode)969b725ae77Skettenis translate_rn_to_arch_reg_num (int rn, int media_mode)
970b725ae77Skettenis {
971b725ae77Skettenis 
972b725ae77Skettenis   if (media_mode)
973b725ae77Skettenis     {
974b725ae77Skettenis       if (!is_media_pseudo (rn))
975b725ae77Skettenis 	return rn;
976b725ae77Skettenis       else
977b725ae77Skettenis 	return sh64_media_reg_base_num (rn);
978b725ae77Skettenis     }
979b725ae77Skettenis   else
980b725ae77Skettenis     /* All compact registers are pseudo.  */
981b725ae77Skettenis     return sh64_compact_reg_base_num (rn);
982b725ae77Skettenis }
983b725ae77Skettenis 
984b725ae77Skettenis static int
sign_extend(int value,int bits)985b725ae77Skettenis sign_extend (int value, int bits)
986b725ae77Skettenis {
987b725ae77Skettenis   value = value & ((1 << bits) - 1);
988b725ae77Skettenis   return (value & (1 << (bits - 1))
989b725ae77Skettenis 	  ? value | (~((1 << bits) - 1))
990b725ae77Skettenis 	  : value);
991b725ae77Skettenis }
992b725ae77Skettenis 
993b725ae77Skettenis static void
sh64_nofp_frame_init_saved_regs(struct frame_info * fi)994b725ae77Skettenis sh64_nofp_frame_init_saved_regs (struct frame_info *fi)
995b725ae77Skettenis {
996b725ae77Skettenis   int *where = (int *) alloca ((NUM_REGS + NUM_PSEUDO_REGS) * sizeof (int));
997b725ae77Skettenis   int rn;
998b725ae77Skettenis   int have_fp = 0;
999b725ae77Skettenis   int fp_regnum;
1000b725ae77Skettenis   int sp_regnum;
1001b725ae77Skettenis   int depth;
1002b725ae77Skettenis   int pc;
1003b725ae77Skettenis   int opc;
1004b725ae77Skettenis   int insn;
1005b725ae77Skettenis   int r0_val = 0;
1006b725ae77Skettenis   int media_mode = 0;
1007b725ae77Skettenis   int insn_size;
1008b725ae77Skettenis   int gdb_register_number;
1009b725ae77Skettenis   int register_number;
1010b725ae77Skettenis   char *dummy_regs = deprecated_generic_find_dummy_frame (get_frame_pc (fi),
1011b725ae77Skettenis 							  get_frame_base (fi));
1012b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1013b725ae77Skettenis 
1014b725ae77Skettenis   if (deprecated_get_frame_saved_regs (fi) == NULL)
1015b725ae77Skettenis     frame_saved_regs_zalloc (fi);
1016b725ae77Skettenis   else
1017b725ae77Skettenis     memset (deprecated_get_frame_saved_regs (fi), 0, SIZEOF_FRAME_SAVED_REGS);
1018b725ae77Skettenis 
1019b725ae77Skettenis   if (dummy_regs)
1020b725ae77Skettenis     {
1021b725ae77Skettenis       /* DANGER!  This is ONLY going to work if the char buffer format of
1022b725ae77Skettenis          the saved registers is byte-for-byte identical to the
1023b725ae77Skettenis          CORE_ADDR regs[NUM_REGS] format used by struct frame_saved_regs! */
1024b725ae77Skettenis       memcpy (deprecated_get_frame_saved_regs (fi), dummy_regs, SIZEOF_FRAME_SAVED_REGS);
1025b725ae77Skettenis       return;
1026b725ae77Skettenis     }
1027b725ae77Skettenis 
1028b725ae77Skettenis   get_frame_extra_info (fi)->leaf_function = 1;
1029b725ae77Skettenis   get_frame_extra_info (fi)->f_offset = 0;
1030b725ae77Skettenis 
1031b725ae77Skettenis   for (rn = 0; rn < NUM_REGS + NUM_PSEUDO_REGS; rn++)
1032b725ae77Skettenis     where[rn] = -1;
1033b725ae77Skettenis 
1034b725ae77Skettenis   depth = 0;
1035b725ae77Skettenis 
1036b725ae77Skettenis   /* Loop around examining the prologue insns until we find something
1037b725ae77Skettenis      that does not appear to be part of the prologue.  But give up
1038b725ae77Skettenis      after 20 of them, since we're getting silly then.  */
1039b725ae77Skettenis 
1040b725ae77Skettenis   pc = get_frame_func (fi);
1041b725ae77Skettenis   if (!pc)
1042b725ae77Skettenis     {
1043b725ae77Skettenis       deprecated_update_frame_pc_hack (fi, 0);
1044b725ae77Skettenis       return;
1045b725ae77Skettenis     }
1046b725ae77Skettenis 
1047b725ae77Skettenis   if (pc_is_isa32 (pc))
1048b725ae77Skettenis     {
1049b725ae77Skettenis       media_mode = 1;
1050b725ae77Skettenis       insn_size = 4;
1051b725ae77Skettenis     }
1052b725ae77Skettenis   else
1053b725ae77Skettenis     {
1054b725ae77Skettenis       media_mode = 0;
1055b725ae77Skettenis       insn_size = 2;
1056b725ae77Skettenis     }
1057b725ae77Skettenis 
1058b725ae77Skettenis  /* The frame pointer register is general register 14 in shmedia and
1059b725ae77Skettenis     shcompact modes. In sh compact it is a pseudo register.  Same goes
1060b725ae77Skettenis     for the stack pointer register, which is register 15.  */
1061b725ae77Skettenis   fp_regnum = translate_insn_rn (DEPRECATED_FP_REGNUM, media_mode);
1062b725ae77Skettenis   sp_regnum = translate_insn_rn (SP_REGNUM, media_mode);
1063b725ae77Skettenis 
1064b725ae77Skettenis   for (opc = pc + (insn_size * 28); pc < opc; pc += insn_size)
1065b725ae77Skettenis     {
1066b725ae77Skettenis       insn = read_memory_integer (media_mode ? UNMAKE_ISA32_ADDR (pc) : pc,
1067b725ae77Skettenis 				  insn_size);
1068b725ae77Skettenis 
1069b725ae77Skettenis       if (media_mode == 0)
1070b725ae77Skettenis 	{
1071b725ae77Skettenis 	  if (IS_STS_PR (insn))
1072b725ae77Skettenis 	    {
1073b725ae77Skettenis 	      int next_insn = read_memory_integer (pc + insn_size, insn_size);
1074b725ae77Skettenis 	      if (IS_MOV_TO_R15 (next_insn))
1075b725ae77Skettenis 		{
1076b725ae77Skettenis 		  int reg_nr = PR_C_REGNUM;
1077b725ae77Skettenis 
1078b725ae77Skettenis 		  where[reg_nr] = depth - ((((next_insn & 0xf) ^ 0x8) - 0x8) << 2);
1079b725ae77Skettenis 		  get_frame_extra_info (fi)->leaf_function = 0;
1080b725ae77Skettenis 		  pc += insn_size;
1081b725ae77Skettenis 		}
1082b725ae77Skettenis 	    }
1083b725ae77Skettenis 	  else if (IS_MOV_R14 (insn))
1084b725ae77Skettenis 	    {
1085b725ae77Skettenis 	      where[fp_regnum] = depth - ((((insn & 0xf) ^ 0x8) - 0x8) << 2);
1086b725ae77Skettenis 	    }
1087b725ae77Skettenis 
1088b725ae77Skettenis 	  else if (IS_MOV_R0 (insn))
1089b725ae77Skettenis 	    {
1090b725ae77Skettenis 	      /* Put in R0 the offset from SP at which to store some
1091b725ae77Skettenis 		 registers. We are interested in this value, because it
1092b725ae77Skettenis 		 will tell us where the given registers are stored within
1093b725ae77Skettenis 		 the frame.  */
1094b725ae77Skettenis 	      r0_val = ((insn & 0xff) ^ 0x80) - 0x80;
1095b725ae77Skettenis 	    }
1096b725ae77Skettenis 	  else if (IS_ADD_SP_R0 (insn))
1097b725ae77Skettenis 	    {
1098b725ae77Skettenis 	      /* This instruction still prepares r0, but we don't care.
1099b725ae77Skettenis 		 We already have the offset in r0_val.  */
1100b725ae77Skettenis 	    }
1101b725ae77Skettenis 	  else if (IS_STS_R0 (insn))
1102b725ae77Skettenis 	    {
1103b725ae77Skettenis 	      /* Store PR at r0_val-4 from SP. Decrement r0 by 4*/
1104b725ae77Skettenis 	      int reg_nr = PR_C_REGNUM;
1105b725ae77Skettenis 	      where[reg_nr] = depth - (r0_val - 4);
1106b725ae77Skettenis 	      r0_val -= 4;
1107b725ae77Skettenis 	      get_frame_extra_info (fi)->leaf_function = 0;
1108b725ae77Skettenis 	    }
1109b725ae77Skettenis 	  else if (IS_MOV_R14_R0 (insn))
1110b725ae77Skettenis 	    {
1111b725ae77Skettenis 	      /* Store R14 at r0_val-4 from SP. Decrement r0 by 4 */
1112b725ae77Skettenis 	      where[fp_regnum] = depth - (r0_val - 4);
1113b725ae77Skettenis 	      r0_val -= 4;
1114b725ae77Skettenis 	    }
1115b725ae77Skettenis 
1116b725ae77Skettenis 	  else if (IS_ADD_SP (insn))
1117b725ae77Skettenis 	    {
1118b725ae77Skettenis 	      depth -= ((insn & 0xff) ^ 0x80) - 0x80;
1119b725ae77Skettenis 	    }
1120b725ae77Skettenis 	  else if (IS_MOV_SP_FP (insn))
1121b725ae77Skettenis 	    break;
1122b725ae77Skettenis 	}
1123b725ae77Skettenis       else
1124b725ae77Skettenis 	{
1125b725ae77Skettenis 	  if (IS_ADDIL_SP_MEDIA (insn)
1126b725ae77Skettenis 	      || IS_ADDI_SP_MEDIA (insn))
1127b725ae77Skettenis 	    {
1128b725ae77Skettenis 	      depth -= sign_extend ((((insn & 0xffc00) ^ 0x80000) - 0x80000) >> 10, 9);
1129b725ae77Skettenis 	    }
1130b725ae77Skettenis 
1131b725ae77Skettenis 	  else if (IS_STQ_R18_R15 (insn))
1132b725ae77Skettenis 	    {
1133b725ae77Skettenis 	      where[PR_REGNUM] =
1134b725ae77Skettenis 		depth - (sign_extend ((insn & 0xffc00) >> 10, 9) << 3);
1135b725ae77Skettenis 	      get_frame_extra_info (fi)->leaf_function = 0;
1136b725ae77Skettenis 	    }
1137b725ae77Skettenis 
1138b725ae77Skettenis 	  else if (IS_STL_R18_R15 (insn))
1139b725ae77Skettenis 	    {
1140b725ae77Skettenis 	      where[PR_REGNUM] =
1141b725ae77Skettenis 		depth - (sign_extend ((insn & 0xffc00) >> 10, 9) << 2);
1142b725ae77Skettenis 	      get_frame_extra_info (fi)->leaf_function = 0;
1143b725ae77Skettenis 	    }
1144b725ae77Skettenis 
1145b725ae77Skettenis 	  else if (IS_STQ_R14_R15 (insn))
1146b725ae77Skettenis 	    {
1147b725ae77Skettenis 	      where[fp_regnum] = depth - (sign_extend ((insn & 0xffc00) >> 10, 9) << 3);
1148b725ae77Skettenis 	    }
1149b725ae77Skettenis 
1150b725ae77Skettenis 	  else if (IS_STL_R14_R15 (insn))
1151b725ae77Skettenis 	    {
1152b725ae77Skettenis 	      where[fp_regnum] = depth - (sign_extend ((insn & 0xffc00) >> 10, 9) << 2);
1153b725ae77Skettenis 	    }
1154b725ae77Skettenis 
1155b725ae77Skettenis 	  else if (IS_MOV_SP_FP_MEDIA (insn))
1156b725ae77Skettenis 	    break;
1157b725ae77Skettenis 	}
1158b725ae77Skettenis     }
1159b725ae77Skettenis 
1160b725ae77Skettenis   /* Now we know how deep things are, we can work out their addresses.  */
1161b725ae77Skettenis   for (rn = 0; rn < NUM_REGS + NUM_PSEUDO_REGS; rn++)
1162b725ae77Skettenis     {
1163b725ae77Skettenis       register_number = translate_rn_to_arch_reg_num (rn, media_mode);
1164b725ae77Skettenis 
1165b725ae77Skettenis       if (where[rn] >= 0)
1166b725ae77Skettenis 	{
1167b725ae77Skettenis 	  if (rn == fp_regnum)
1168b725ae77Skettenis 	    have_fp = 1;
1169b725ae77Skettenis 
1170b725ae77Skettenis 	  /* Watch out! saved_regs is only for the real registers, and
1171b725ae77Skettenis 	     doesn't include space for the pseudo registers.  */
1172b725ae77Skettenis 	  deprecated_get_frame_saved_regs (fi)[register_number]
1173b725ae77Skettenis 	    = get_frame_base (fi) - where[rn] + depth;
1174b725ae77Skettenis 	}
1175b725ae77Skettenis       else
1176b725ae77Skettenis 	deprecated_get_frame_saved_regs (fi)[register_number] = 0;
1177b725ae77Skettenis     }
1178b725ae77Skettenis 
1179b725ae77Skettenis   if (have_fp)
1180b725ae77Skettenis     {
1181b725ae77Skettenis       /* SP_REGNUM is 15. For shmedia 15 is the real register. For
1182b725ae77Skettenis 	 shcompact 15 is the arch register corresponding to the pseudo
1183b725ae77Skettenis 	 register r15 which still is the SP register.  */
1184b725ae77Skettenis       /* The place on the stack where fp is stored contains the sp of
1185b725ae77Skettenis          the caller.  */
1186b725ae77Skettenis       /* Again, saved_registers contains only space for the real
1187b725ae77Skettenis 	 registers, so we store in DEPRECATED_FP_REGNUM position.  */
1188b725ae77Skettenis       int size;
1189b725ae77Skettenis       if (tdep->sh_abi == SH_ABI_32)
1190b725ae77Skettenis 	size = 4;
1191b725ae77Skettenis       else
1192b725ae77Skettenis 	size = register_size (current_gdbarch, fp_regnum);
1193b725ae77Skettenis       deprecated_get_frame_saved_regs (fi)[sp_regnum]
1194b725ae77Skettenis 	= read_memory_integer (deprecated_get_frame_saved_regs (fi)[fp_regnum],
1195b725ae77Skettenis 			       size);
1196b725ae77Skettenis     }
1197b725ae77Skettenis   else
1198b725ae77Skettenis     deprecated_get_frame_saved_regs (fi)[sp_regnum] = get_frame_base (fi);
1199b725ae77Skettenis 
1200b725ae77Skettenis   get_frame_extra_info (fi)->f_offset = depth - where[fp_regnum];
1201b725ae77Skettenis }
1202b725ae77Skettenis 
1203b725ae77Skettenis /* Initialize the extra info saved in a FRAME */
1204b725ae77Skettenis static void
sh64_init_extra_frame_info(int fromleaf,struct frame_info * fi)1205b725ae77Skettenis sh64_init_extra_frame_info (int fromleaf, struct frame_info *fi)
1206b725ae77Skettenis {
1207b725ae77Skettenis   int media_mode = pc_is_isa32 (get_frame_pc (fi));
1208b725ae77Skettenis 
1209b725ae77Skettenis   frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
1210b725ae77Skettenis 
1211b725ae77Skettenis   if (get_next_frame (fi))
1212b725ae77Skettenis     deprecated_update_frame_pc_hack (fi, DEPRECATED_FRAME_SAVED_PC (get_next_frame (fi)));
1213b725ae77Skettenis 
1214*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (get_frame_pc (fi)))
1215b725ae77Skettenis     {
1216b725ae77Skettenis       /* We need to setup fi->frame here because call_function_by_hand
1217b725ae77Skettenis          gets it wrong by assuming it's always FP.  */
1218b725ae77Skettenis       deprecated_update_frame_base_hack (fi, deprecated_read_register_dummy (get_frame_pc (fi), get_frame_base (fi), SP_REGNUM));
1219b725ae77Skettenis       get_frame_extra_info (fi)->return_pc =
1220b725ae77Skettenis 	deprecated_read_register_dummy (get_frame_pc (fi),
1221b725ae77Skettenis 					get_frame_base (fi), PC_REGNUM);
1222*11efff7fSkettenis       get_frame_extra_info (fi)->f_offset = -4;
1223b725ae77Skettenis       get_frame_extra_info (fi)->leaf_function = 0;
1224b725ae77Skettenis       return;
1225b725ae77Skettenis     }
1226b725ae77Skettenis   else
1227b725ae77Skettenis     {
1228b725ae77Skettenis       DEPRECATED_FRAME_INIT_SAVED_REGS (fi);
1229b725ae77Skettenis       get_frame_extra_info (fi)->return_pc =
1230b725ae77Skettenis 	sh64_get_saved_pr (fi, PR_REGNUM);
1231b725ae77Skettenis     }
1232b725ae77Skettenis }
1233b725ae77Skettenis 
1234b725ae77Skettenis static void
sh64_get_saved_register(char * raw_buffer,int * optimized,CORE_ADDR * addrp,struct frame_info * frame,int regnum,enum lval_type * lval)1235b725ae77Skettenis sh64_get_saved_register (char *raw_buffer, int *optimized, CORE_ADDR *addrp,
1236b725ae77Skettenis 			 struct frame_info *frame, int regnum,
1237b725ae77Skettenis 			 enum lval_type *lval)
1238b725ae77Skettenis {
1239b725ae77Skettenis   int media_mode;
1240b725ae77Skettenis   int live_regnum = regnum;
1241b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1242b725ae77Skettenis 
1243b725ae77Skettenis   if (!target_has_registers)
1244b725ae77Skettenis     error ("No registers.");
1245b725ae77Skettenis 
1246b725ae77Skettenis   /* Normal systems don't optimize out things with register numbers.  */
1247b725ae77Skettenis   if (optimized != NULL)
1248b725ae77Skettenis     *optimized = 0;
1249b725ae77Skettenis 
1250b725ae77Skettenis   if (addrp)			/* default assumption: not found in memory */
1251b725ae77Skettenis     *addrp = 0;
1252b725ae77Skettenis 
1253b725ae77Skettenis   if (raw_buffer)
1254b725ae77Skettenis     memset (raw_buffer, 0, sizeof (raw_buffer));
1255b725ae77Skettenis 
1256b725ae77Skettenis   /* We must do this here, before the following while loop changes
1257b725ae77Skettenis      frame, and makes it NULL. If this is a media register number,
1258b725ae77Skettenis      but we are in compact mode, it will become the corresponding
1259b725ae77Skettenis      compact pseudo register. If there is no corresponding compact
1260b725ae77Skettenis      pseudo-register what do we do?*/
1261b725ae77Skettenis   media_mode = pc_is_isa32 (get_frame_pc (frame));
1262b725ae77Skettenis   live_regnum = translate_insn_rn (regnum, media_mode);
1263b725ae77Skettenis 
1264b725ae77Skettenis   /* Note: since the current frame's registers could only have been
1265b725ae77Skettenis      saved by frames INTERIOR TO the current frame, we skip examining
1266b725ae77Skettenis      the current frame itself: otherwise, we would be getting the
1267b725ae77Skettenis      previous frame's registers which were saved by the current frame.  */
1268b725ae77Skettenis 
1269b725ae77Skettenis   while (frame && ((frame = get_next_frame (frame)) != NULL))
1270b725ae77Skettenis     {
1271*11efff7fSkettenis       if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
1272b725ae77Skettenis 	{
1273b725ae77Skettenis 	  if (lval)		/* found it in a CALL_DUMMY frame */
1274b725ae77Skettenis 	    *lval = not_lval;
1275b725ae77Skettenis 	  if (raw_buffer)
1276b725ae77Skettenis 	    memcpy (raw_buffer,
1277b725ae77Skettenis 		    (deprecated_generic_find_dummy_frame (get_frame_pc (frame), get_frame_base (frame))
1278b725ae77Skettenis 		     + DEPRECATED_REGISTER_BYTE (regnum)),
1279b725ae77Skettenis 		    register_size (current_gdbarch, regnum));
1280b725ae77Skettenis 	  return;
1281b725ae77Skettenis 	}
1282b725ae77Skettenis 
1283b725ae77Skettenis       DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
1284b725ae77Skettenis       if (deprecated_get_frame_saved_regs (frame) != NULL
1285b725ae77Skettenis 	  && deprecated_get_frame_saved_regs (frame)[regnum] != 0)
1286b725ae77Skettenis 	{
1287b725ae77Skettenis 	  if (lval)		/* found it saved on the stack */
1288b725ae77Skettenis 	    *lval = lval_memory;
1289b725ae77Skettenis 	  if (regnum == SP_REGNUM)
1290b725ae77Skettenis 	    {
1291b725ae77Skettenis 	      if (raw_buffer)	/* SP register treated specially */
1292b725ae77Skettenis 		store_unsigned_integer (raw_buffer,
1293b725ae77Skettenis 					register_size (current_gdbarch,
1294b725ae77Skettenis 						       regnum),
1295b725ae77Skettenis 					deprecated_get_frame_saved_regs (frame)[regnum]);
1296b725ae77Skettenis 	    }
1297b725ae77Skettenis 	  else
1298b725ae77Skettenis 	    { /* any other register */
1299b725ae77Skettenis 
1300b725ae77Skettenis 	      if (addrp)
1301b725ae77Skettenis 		*addrp = deprecated_get_frame_saved_regs (frame)[regnum];
1302b725ae77Skettenis 	      if (raw_buffer)
1303b725ae77Skettenis 		{
1304b725ae77Skettenis 		  int size;
1305b725ae77Skettenis 		  if (tdep->sh_abi == SH_ABI_32
1306b725ae77Skettenis 		      && (live_regnum == DEPRECATED_FP_REGNUM
1307b725ae77Skettenis 			  || live_regnum == PR_REGNUM))
1308b725ae77Skettenis 		    size = 4;
1309b725ae77Skettenis 		  else
1310b725ae77Skettenis 		    size = register_size (current_gdbarch, live_regnum);
1311b725ae77Skettenis 		  if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
1312b725ae77Skettenis 		    read_memory (deprecated_get_frame_saved_regs (frame)[regnum],
1313b725ae77Skettenis 				 raw_buffer, size);
1314b725ae77Skettenis 		  else
1315b725ae77Skettenis 		    read_memory (deprecated_get_frame_saved_regs (frame)[regnum],
1316b725ae77Skettenis 				 raw_buffer
1317b725ae77Skettenis 				 + register_size (current_gdbarch, live_regnum)
1318b725ae77Skettenis 				 - size,
1319b725ae77Skettenis 				 size);
1320b725ae77Skettenis 		}
1321b725ae77Skettenis 	    }
1322b725ae77Skettenis 	  return;
1323b725ae77Skettenis 	}
1324b725ae77Skettenis     }
1325b725ae77Skettenis 
1326b725ae77Skettenis   /* If we get thru the loop to this point, it means the register was
1327b725ae77Skettenis      not saved in any frame.  Return the actual live-register value.  */
1328b725ae77Skettenis 
1329b725ae77Skettenis   if (lval)			/* found it in a live register */
1330b725ae77Skettenis     *lval = lval_register;
1331b725ae77Skettenis   if (addrp)
1332b725ae77Skettenis     *addrp = DEPRECATED_REGISTER_BYTE (live_regnum);
1333b725ae77Skettenis   if (raw_buffer)
1334b725ae77Skettenis     deprecated_read_register_gen (live_regnum, raw_buffer);
1335b725ae77Skettenis }
1336b725ae77Skettenis 
1337b725ae77Skettenis static CORE_ADDR
sh64_extract_struct_value_address(struct regcache * regcache)1338b725ae77Skettenis sh64_extract_struct_value_address (struct regcache *regcache)
1339b725ae77Skettenis {
1340b725ae77Skettenis   /* FIXME: cagney/2004-01-17: Does the ABI guarantee that the return
1341b725ae77Skettenis      address regster is preserved across function calls?  Probably
1342b725ae77Skettenis      not, making this function wrong.  */
1343b725ae77Skettenis   ULONGEST val;
1344b725ae77Skettenis   regcache_raw_read_unsigned (regcache, STRUCT_RETURN_REGNUM, &val);
1345b725ae77Skettenis   return val;
1346b725ae77Skettenis }
1347b725ae77Skettenis 
1348b725ae77Skettenis static CORE_ADDR
sh_frame_saved_pc(struct frame_info * frame)1349b725ae77Skettenis sh_frame_saved_pc (struct frame_info *frame)
1350b725ae77Skettenis {
1351b725ae77Skettenis   return (get_frame_extra_info (frame)->return_pc);
1352b725ae77Skettenis }
1353b725ae77Skettenis 
1354b725ae77Skettenis /* Discard from the stack the innermost frame, restoring all saved registers.
1355b725ae77Skettenis    Used in the 'return' command.  */
1356b725ae77Skettenis static void
sh64_pop_frame(void)1357b725ae77Skettenis sh64_pop_frame (void)
1358b725ae77Skettenis {
1359b725ae77Skettenis   struct frame_info *frame = get_current_frame ();
1360b725ae77Skettenis   CORE_ADDR fp;
1361b725ae77Skettenis   int regnum;
1362b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
1363b725ae77Skettenis 
1364b725ae77Skettenis   int media_mode = pc_is_isa32 (get_frame_pc (frame));
1365b725ae77Skettenis 
1366*11efff7fSkettenis   if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
1367*11efff7fSkettenis     deprecated_pop_dummy_frame ();
1368b725ae77Skettenis   else
1369b725ae77Skettenis     {
1370b725ae77Skettenis       fp = get_frame_base (frame);
1371b725ae77Skettenis       DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
1372b725ae77Skettenis 
1373b725ae77Skettenis       /* Copy regs from where they were saved in the frame */
1374b725ae77Skettenis       for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
1375b725ae77Skettenis 	if (deprecated_get_frame_saved_regs (frame)[regnum])
1376b725ae77Skettenis 	  {
1377b725ae77Skettenis 	    int size;
1378b725ae77Skettenis 	    if (tdep->sh_abi == SH_ABI_32
1379b725ae77Skettenis 		&& (regnum == DEPRECATED_FP_REGNUM
1380b725ae77Skettenis 		    || regnum ==  PR_REGNUM))
1381b725ae77Skettenis 	      size = 4;
1382b725ae77Skettenis 	    else
1383b725ae77Skettenis 	      size = register_size (current_gdbarch,
1384b725ae77Skettenis 				    translate_insn_rn (regnum, media_mode));
1385b725ae77Skettenis 	    write_register (regnum,
1386b725ae77Skettenis 			    read_memory_integer (deprecated_get_frame_saved_regs (frame)[regnum],
1387b725ae77Skettenis 						 size));
1388b725ae77Skettenis 	  }
1389b725ae77Skettenis 
1390b725ae77Skettenis       write_register (PC_REGNUM, get_frame_extra_info (frame)->return_pc);
1391b725ae77Skettenis       write_register (SP_REGNUM, fp + 8);
1392b725ae77Skettenis     }
1393b725ae77Skettenis   flush_cached_frames ();
1394b725ae77Skettenis }
1395b725ae77Skettenis 
1396b725ae77Skettenis static CORE_ADDR
sh_frame_align(struct gdbarch * ignore,CORE_ADDR sp)1397b725ae77Skettenis sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
1398b725ae77Skettenis {
1399b725ae77Skettenis   return sp & ~3;
1400b725ae77Skettenis }
1401b725ae77Skettenis 
1402b725ae77Skettenis /* Function: push_arguments
1403b725ae77Skettenis    Setup the function arguments for calling a function in the inferior.
1404b725ae77Skettenis 
1405b725ae77Skettenis    On the Renesas SH architecture, there are four registers (R4 to R7)
1406b725ae77Skettenis    which are dedicated for passing function arguments.  Up to the first
1407b725ae77Skettenis    four arguments (depending on size) may go into these registers.
1408b725ae77Skettenis    The rest go on the stack.
1409b725ae77Skettenis 
1410b725ae77Skettenis    Arguments that are smaller than 4 bytes will still take up a whole
1411b725ae77Skettenis    register or a whole 32-bit word on the stack, and will be
1412b725ae77Skettenis    right-justified in the register or the stack word.  This includes
1413b725ae77Skettenis    chars, shorts, and small aggregate types.
1414b725ae77Skettenis 
1415b725ae77Skettenis    Arguments that are larger than 4 bytes may be split between two or
1416b725ae77Skettenis    more registers.  If there are not enough registers free, an argument
1417b725ae77Skettenis    may be passed partly in a register (or registers), and partly on the
1418b725ae77Skettenis    stack.  This includes doubles, long longs, and larger aggregates.
1419b725ae77Skettenis    As far as I know, there is no upper limit to the size of aggregates
1420b725ae77Skettenis    that will be passed in this way; in other words, the convention of
1421b725ae77Skettenis    passing a pointer to a large aggregate instead of a copy is not used.
1422b725ae77Skettenis 
1423b725ae77Skettenis    An exceptional case exists for struct arguments (and possibly other
1424b725ae77Skettenis    aggregates such as arrays) if the size is larger than 4 bytes but
1425b725ae77Skettenis    not a multiple of 4 bytes.  In this case the argument is never split
1426b725ae77Skettenis    between the registers and the stack, but instead is copied in its
1427b725ae77Skettenis    entirety onto the stack, AND also copied into as many registers as
1428b725ae77Skettenis    there is room for.  In other words, space in registers permitting,
1429b725ae77Skettenis    two copies of the same argument are passed in.  As far as I can tell,
1430b725ae77Skettenis    only the one on the stack is used, although that may be a function
1431b725ae77Skettenis    of the level of compiler optimization.  I suspect this is a compiler
1432b725ae77Skettenis    bug.  Arguments of these odd sizes are left-justified within the
1433b725ae77Skettenis    word (as opposed to arguments smaller than 4 bytes, which are
1434b725ae77Skettenis    right-justified).
1435b725ae77Skettenis 
1436b725ae77Skettenis    If the function is to return an aggregate type such as a struct, it
1437b725ae77Skettenis    is either returned in the normal return value register R0 (if its
1438b725ae77Skettenis    size is no greater than one byte), or else the caller must allocate
1439b725ae77Skettenis    space into which the callee will copy the return value (if the size
1440b725ae77Skettenis    is greater than one byte).  In this case, a pointer to the return
1441b725ae77Skettenis    value location is passed into the callee in register R2, which does
1442b725ae77Skettenis    not displace any of the other arguments passed in via registers R4
1443b725ae77Skettenis    to R7.   */
1444b725ae77Skettenis 
1445b725ae77Skettenis /* R2-R9 for integer types and integer equivalent (char, pointers) and
1446b725ae77Skettenis    non-scalar (struct, union) elements (even if the elements are
1447b725ae77Skettenis    floats).
1448b725ae77Skettenis    FR0-FR11 for single precision floating point (float)
1449b725ae77Skettenis    DR0-DR10 for double precision floating point (double)
1450b725ae77Skettenis 
1451b725ae77Skettenis    If a float is argument number 3 (for instance) and arguments number
1452b725ae77Skettenis    1,2, and 4 are integer, the mapping will be:
1453b725ae77Skettenis    arg1 -->R2, arg2 --> R3, arg3 -->FR0, arg4 --> R5. I.e. R4 is not used.
1454b725ae77Skettenis 
1455b725ae77Skettenis    If a float is argument number 10 (for instance) and arguments number
1456b725ae77Skettenis    1 through 10 are integer, the mapping will be:
1457b725ae77Skettenis    arg1->R2, arg2->R3, arg3->R4, arg4->R5, arg5->R6, arg6->R7, arg7->R8,
1458b725ae77Skettenis    arg8->R9, arg9->(0,SP)stack(8-byte aligned), arg10->FR0, arg11->stack(16,SP).
1459b725ae77Skettenis    I.e. there is hole in the stack.
1460b725ae77Skettenis 
1461b725ae77Skettenis    Different rules apply for variable arguments functions, and for functions
1462b725ae77Skettenis    for which the prototype is not known.  */
1463b725ae77Skettenis 
1464b725ae77Skettenis static CORE_ADDR
sh64_push_arguments(int nargs,struct value ** args,CORE_ADDR sp,int struct_return,CORE_ADDR struct_addr)1465b725ae77Skettenis sh64_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
1466b725ae77Skettenis 		     int struct_return, CORE_ADDR struct_addr)
1467b725ae77Skettenis {
1468b725ae77Skettenis   int stack_offset, stack_alloc;
1469b725ae77Skettenis   int int_argreg;
1470b725ae77Skettenis   int float_argreg;
1471b725ae77Skettenis   int double_argreg;
1472b725ae77Skettenis   int float_arg_index = 0;
1473b725ae77Skettenis   int double_arg_index = 0;
1474b725ae77Skettenis   int argnum;
1475b725ae77Skettenis   struct type *type;
1476b725ae77Skettenis   CORE_ADDR regval;
1477b725ae77Skettenis   char *val;
1478b725ae77Skettenis   char valbuf[8];
1479b725ae77Skettenis   char valbuf_tmp[8];
1480b725ae77Skettenis   int len;
1481b725ae77Skettenis   int argreg_size;
1482b725ae77Skettenis   int fp_args[12];
1483b725ae77Skettenis 
1484b725ae77Skettenis   memset (fp_args, 0, sizeof (fp_args));
1485b725ae77Skettenis 
1486b725ae77Skettenis   /* first force sp to a 8-byte alignment */
1487b725ae77Skettenis   sp = sp & ~7;
1488b725ae77Skettenis 
1489b725ae77Skettenis   /* The "struct return pointer" pseudo-argument has its own dedicated
1490b725ae77Skettenis      register */
1491b725ae77Skettenis 
1492b725ae77Skettenis   if (struct_return)
1493b725ae77Skettenis     write_register (STRUCT_RETURN_REGNUM, struct_addr);
1494b725ae77Skettenis 
1495b725ae77Skettenis   /* Now make sure there's space on the stack */
1496b725ae77Skettenis   for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
1497b725ae77Skettenis     stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 7) & ~7);
1498b725ae77Skettenis   sp -= stack_alloc;		/* make room on stack for args */
1499b725ae77Skettenis 
1500b725ae77Skettenis   /* Now load as many as possible of the first arguments into
1501b725ae77Skettenis      registers, and push the rest onto the stack.  There are 64 bytes
1502b725ae77Skettenis      in eight registers available.  Loop thru args from first to last.  */
1503b725ae77Skettenis 
1504b725ae77Skettenis   int_argreg = ARG0_REGNUM;
1505b725ae77Skettenis   float_argreg = FP0_REGNUM;
1506b725ae77Skettenis   double_argreg = DR0_REGNUM;
1507b725ae77Skettenis 
1508b725ae77Skettenis   for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
1509b725ae77Skettenis     {
1510b725ae77Skettenis       type = VALUE_TYPE (args[argnum]);
1511b725ae77Skettenis       len = TYPE_LENGTH (type);
1512b725ae77Skettenis       memset (valbuf, 0, sizeof (valbuf));
1513b725ae77Skettenis 
1514b725ae77Skettenis       if (TYPE_CODE (type) != TYPE_CODE_FLT)
1515b725ae77Skettenis 	{
1516b725ae77Skettenis 	  argreg_size = register_size (current_gdbarch, int_argreg);
1517b725ae77Skettenis 
1518b725ae77Skettenis 	  if (len < argreg_size)
1519b725ae77Skettenis 	    {
1520b725ae77Skettenis 	      /* value gets right-justified in the register or stack word */
1521b725ae77Skettenis 	      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
1522b725ae77Skettenis 		memcpy (valbuf + argreg_size - len,
1523b725ae77Skettenis 			(char *) VALUE_CONTENTS (args[argnum]), len);
1524b725ae77Skettenis 	      else
1525b725ae77Skettenis 		memcpy (valbuf, (char *) VALUE_CONTENTS (args[argnum]), len);
1526b725ae77Skettenis 
1527b725ae77Skettenis 	      val = valbuf;
1528b725ae77Skettenis 	    }
1529b725ae77Skettenis 	  else
1530b725ae77Skettenis 	    val = (char *) VALUE_CONTENTS (args[argnum]);
1531b725ae77Skettenis 
1532b725ae77Skettenis 	  while (len > 0)
1533b725ae77Skettenis 	    {
1534b725ae77Skettenis 	      if (int_argreg > ARGLAST_REGNUM)
1535b725ae77Skettenis 		{
1536b725ae77Skettenis 		  /* must go on the stack */
1537b725ae77Skettenis 		  write_memory (sp + stack_offset, val, argreg_size);
1538b725ae77Skettenis 		  stack_offset += 8;/*argreg_size;*/
1539b725ae77Skettenis 		}
1540b725ae77Skettenis 	      /* NOTE WELL!!!!!  This is not an "else if" clause!!!
1541b725ae77Skettenis 		 That's because some *&^%$ things get passed on the stack
1542b725ae77Skettenis 		 AND in the registers!   */
1543b725ae77Skettenis 	      if (int_argreg <= ARGLAST_REGNUM)
1544b725ae77Skettenis 		{
1545b725ae77Skettenis 		  /* there's room in a register */
1546b725ae77Skettenis 		  regval = extract_unsigned_integer (val, argreg_size);
1547b725ae77Skettenis 		  write_register (int_argreg, regval);
1548b725ae77Skettenis 		}
1549b725ae77Skettenis 	      /* Store the value 8 bytes at a time.  This means that
1550b725ae77Skettenis 		 things larger than 8 bytes may go partly in registers
1551b725ae77Skettenis 		 and partly on the stack. FIXME: argreg is incremented
1552b725ae77Skettenis 		 before we use its size.  */
1553b725ae77Skettenis 	      len -= argreg_size;
1554b725ae77Skettenis 	      val += argreg_size;
1555b725ae77Skettenis 	      int_argreg++;
1556b725ae77Skettenis 	    }
1557b725ae77Skettenis 	}
1558b725ae77Skettenis       else
1559b725ae77Skettenis 	{
1560b725ae77Skettenis 	  val = (char *) VALUE_CONTENTS (args[argnum]);
1561b725ae77Skettenis 	  if (len == 4)
1562b725ae77Skettenis 	    {
1563b725ae77Skettenis 	      /* Where is it going to be stored? */
1564b725ae77Skettenis 	      while (fp_args[float_arg_index])
1565b725ae77Skettenis 		float_arg_index ++;
1566b725ae77Skettenis 
1567b725ae77Skettenis 	      /* Now float_argreg points to the register where it
1568b725ae77Skettenis 		 should be stored.  Are we still within the allowed
1569b725ae77Skettenis 		 register set? */
1570b725ae77Skettenis 	      if (float_arg_index <= FLOAT_ARGLAST_REGNUM)
1571b725ae77Skettenis 		{
1572b725ae77Skettenis 		  /* Goes in FR0...FR11 */
1573b725ae77Skettenis 		  deprecated_write_register_gen (FP0_REGNUM + float_arg_index,
1574b725ae77Skettenis 						 val);
1575b725ae77Skettenis 		  fp_args[float_arg_index] = 1;
1576b725ae77Skettenis 		  /* Skip the corresponding general argument register.  */
1577b725ae77Skettenis 		  int_argreg ++;
1578b725ae77Skettenis 		}
1579b725ae77Skettenis 	      else
1580b725ae77Skettenis 		;
1581b725ae77Skettenis 		/* Store it as the integers, 8 bytes at the time, if
1582b725ae77Skettenis 		   necessary spilling on the stack.  */
1583b725ae77Skettenis 
1584b725ae77Skettenis 	    }
1585b725ae77Skettenis 	    else if (len == 8)
1586b725ae77Skettenis 	      {
1587b725ae77Skettenis 		/* Where is it going to be stored? */
1588b725ae77Skettenis 		while (fp_args[double_arg_index])
1589b725ae77Skettenis 		  double_arg_index += 2;
1590b725ae77Skettenis 		/* Now double_argreg points to the register
1591b725ae77Skettenis 		   where it should be stored.
1592b725ae77Skettenis 		   Are we still within the allowed register set? */
1593b725ae77Skettenis 		if (double_arg_index < FLOAT_ARGLAST_REGNUM)
1594b725ae77Skettenis 		  {
1595b725ae77Skettenis 		    /* Goes in DR0...DR10 */
1596b725ae77Skettenis 		    /* The numbering of the DRi registers is consecutive,
1597b725ae77Skettenis 		       i.e. includes odd numbers.  */
1598b725ae77Skettenis 		    int double_register_offset = double_arg_index / 2;
1599b725ae77Skettenis 		    int regnum = DR0_REGNUM +
1600b725ae77Skettenis 		                 double_register_offset;
1601b725ae77Skettenis #if 0
1602b725ae77Skettenis 		    if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
1603b725ae77Skettenis 		      {
1604b725ae77Skettenis 			memset (valbuf_tmp, 0, sizeof (valbuf_tmp));
1605b725ae77Skettenis 			DEPRECATED_REGISTER_CONVERT_TO_VIRTUAL (regnum,
1606b725ae77Skettenis 								type, val,
1607b725ae77Skettenis 								valbuf_tmp);
1608b725ae77Skettenis 			val = valbuf_tmp;
1609b725ae77Skettenis 		      }
1610b725ae77Skettenis #endif
1611b725ae77Skettenis 		    /* Note: must use write_register_gen here instead
1612b725ae77Skettenis 		       of regcache_raw_write, because
1613b725ae77Skettenis 		       regcache_raw_write works only for real
1614b725ae77Skettenis 		       registers, not pseudo.  write_register_gen will
1615b725ae77Skettenis 		       call the gdbarch function to do register
1616b725ae77Skettenis 		       writes, and that will properly know how to deal
1617b725ae77Skettenis 		       with pseudoregs.  */
1618b725ae77Skettenis 		    deprecated_write_register_gen (regnum, val);
1619b725ae77Skettenis 		    fp_args[double_arg_index] = 1;
1620b725ae77Skettenis 		    fp_args[double_arg_index + 1] = 1;
1621b725ae77Skettenis 		    /* Skip the corresponding general argument register.  */
1622b725ae77Skettenis 		    int_argreg ++;
1623b725ae77Skettenis 		  }
1624b725ae77Skettenis 		else
1625b725ae77Skettenis 		  ;
1626b725ae77Skettenis 		  /* Store it as the integers, 8 bytes at the time, if
1627b725ae77Skettenis                      necessary spilling on the stack.  */
1628b725ae77Skettenis 	      }
1629b725ae77Skettenis 	}
1630b725ae77Skettenis     }
1631b725ae77Skettenis   return sp;
1632b725ae77Skettenis }
1633b725ae77Skettenis 
1634b725ae77Skettenis /* Function: push_return_address (pc)
1635b725ae77Skettenis    Set up the return address for the inferior function call.
1636b725ae77Skettenis    Needed for targets where we don't actually execute a JSR/BSR instruction */
1637b725ae77Skettenis 
1638b725ae77Skettenis static CORE_ADDR
sh64_push_return_address(CORE_ADDR pc,CORE_ADDR sp)1639b725ae77Skettenis sh64_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
1640b725ae77Skettenis {
1641b725ae77Skettenis   write_register (PR_REGNUM, entry_point_address ());
1642b725ae77Skettenis   return sp;
1643b725ae77Skettenis }
1644b725ae77Skettenis 
1645b725ae77Skettenis /* Find a function's return value in the appropriate registers (in
1646b725ae77Skettenis    regbuf), and copy it into valbuf.  Extract from an array REGBUF
1647b725ae77Skettenis    containing the (raw) register state a function return value of type
1648b725ae77Skettenis    TYPE, and copy that, in virtual format, into VALBUF.  */
1649b725ae77Skettenis static void
sh64_extract_return_value(struct type * type,char * regbuf,char * valbuf)1650b725ae77Skettenis sh64_extract_return_value (struct type *type, char *regbuf, char *valbuf)
1651b725ae77Skettenis {
1652b725ae77Skettenis   int offset;
1653b725ae77Skettenis   int return_register;
1654b725ae77Skettenis   int len = TYPE_LENGTH (type);
1655b725ae77Skettenis 
1656b725ae77Skettenis   if (TYPE_CODE (type) == TYPE_CODE_FLT)
1657b725ae77Skettenis     {
1658b725ae77Skettenis       if (len == 4)
1659b725ae77Skettenis 	{
1660b725ae77Skettenis 	  /* Return value stored in FP0_REGNUM */
1661b725ae77Skettenis 	  return_register = FP0_REGNUM;
1662b725ae77Skettenis 	  offset = DEPRECATED_REGISTER_BYTE (return_register);
1663b725ae77Skettenis 	  memcpy (valbuf, (char *) regbuf + offset, len);
1664b725ae77Skettenis 	}
1665b725ae77Skettenis       else if (len == 8)
1666b725ae77Skettenis 	{
1667b725ae77Skettenis 	  /* return value stored in DR0_REGNUM */
1668b725ae77Skettenis 	  DOUBLEST val;
1669b725ae77Skettenis 
1670b725ae77Skettenis 	  return_register = DR0_REGNUM;
1671b725ae77Skettenis 	  offset = DEPRECATED_REGISTER_BYTE (return_register);
1672b725ae77Skettenis 
1673b725ae77Skettenis 	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
1674b725ae77Skettenis 	    floatformat_to_doublest (&floatformat_ieee_double_littlebyte_bigword,
1675b725ae77Skettenis 				     (char *) regbuf + offset, &val);
1676b725ae77Skettenis 	  else
1677b725ae77Skettenis 	    floatformat_to_doublest (&floatformat_ieee_double_big,
1678b725ae77Skettenis 				     (char *) regbuf + offset, &val);
1679b725ae77Skettenis 	  store_typed_floating (valbuf, type, val);
1680b725ae77Skettenis 	}
1681b725ae77Skettenis     }
1682b725ae77Skettenis   else
1683b725ae77Skettenis     {
1684b725ae77Skettenis       if (len <= 8)
1685b725ae77Skettenis 	{
1686b725ae77Skettenis 	  /* Result is in register 2. If smaller than 8 bytes, it is padded
1687b725ae77Skettenis 	     at the most significant end.  */
1688b725ae77Skettenis 	  return_register = DEFAULT_RETURN_REGNUM;
1689b725ae77Skettenis 	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
1690b725ae77Skettenis 	    offset = DEPRECATED_REGISTER_BYTE (return_register) +
1691b725ae77Skettenis 	      register_size (current_gdbarch, return_register) - len;
1692b725ae77Skettenis 	  else
1693b725ae77Skettenis 	    offset = DEPRECATED_REGISTER_BYTE (return_register);
1694b725ae77Skettenis 	  memcpy (valbuf, (char *) regbuf + offset, len);
1695b725ae77Skettenis 	}
1696b725ae77Skettenis       else
1697b725ae77Skettenis 	error ("bad size for return value");
1698b725ae77Skettenis     }
1699b725ae77Skettenis }
1700b725ae77Skettenis 
1701b725ae77Skettenis /* Write into appropriate registers a function return value
1702b725ae77Skettenis    of type TYPE, given in virtual format.
1703b725ae77Skettenis    If the architecture is sh4 or sh3e, store a function's return value
1704b725ae77Skettenis    in the R0 general register or in the FP0 floating point register,
1705b725ae77Skettenis    depending on the type of the return value. In all the other cases
1706b725ae77Skettenis    the result is stored in r0, left-justified.  */
1707b725ae77Skettenis 
1708b725ae77Skettenis static void
sh64_store_return_value(struct type * type,char * valbuf)1709b725ae77Skettenis sh64_store_return_value (struct type *type, char *valbuf)
1710b725ae77Skettenis {
1711b725ae77Skettenis   char buf[64];	/* more than enough...  */
1712b725ae77Skettenis   int len = TYPE_LENGTH (type);
1713b725ae77Skettenis 
1714b725ae77Skettenis   if (TYPE_CODE (type) == TYPE_CODE_FLT)
1715b725ae77Skettenis     {
1716b725ae77Skettenis       if (len == 4)
1717b725ae77Skettenis 	{
1718b725ae77Skettenis 	  /* Return value stored in FP0_REGNUM */
1719b725ae77Skettenis 	  deprecated_write_register_gen (FP0_REGNUM, valbuf);
1720b725ae77Skettenis 	}
1721b725ae77Skettenis       if (len == 8)
1722b725ae77Skettenis 	{
1723b725ae77Skettenis 	  /* return value stored in DR0_REGNUM */
1724b725ae77Skettenis 	  /* FIXME: Implement */
1725b725ae77Skettenis 	}
1726b725ae77Skettenis     }
1727b725ae77Skettenis   else
1728b725ae77Skettenis     {
1729b725ae77Skettenis       int return_register = DEFAULT_RETURN_REGNUM;
1730b725ae77Skettenis       int offset = 0;
1731b725ae77Skettenis 
1732b725ae77Skettenis       if (len <= register_size (current_gdbarch, return_register))
1733b725ae77Skettenis 	{
1734b725ae77Skettenis 	  /* Pad with zeros.  */
1735b725ae77Skettenis 	  memset (buf, 0, register_size (current_gdbarch, return_register));
1736b725ae77Skettenis 	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
1737b725ae77Skettenis 	    offset = 0; /*register_size (current_gdbarch,
1738b725ae77Skettenis 			  return_register) - len;*/
1739b725ae77Skettenis 	  else
1740b725ae77Skettenis 	    offset = register_size (current_gdbarch, return_register) - len;
1741b725ae77Skettenis 
1742b725ae77Skettenis 	  memcpy (buf + offset, valbuf, len);
1743b725ae77Skettenis 	  deprecated_write_register_gen (return_register, buf);
1744b725ae77Skettenis 	}
1745b725ae77Skettenis       else
1746b725ae77Skettenis 	deprecated_write_register_gen (return_register, valbuf);
1747b725ae77Skettenis     }
1748b725ae77Skettenis }
1749b725ae77Skettenis 
1750b725ae77Skettenis static void
sh64_show_media_regs(void)1751b725ae77Skettenis sh64_show_media_regs (void)
1752b725ae77Skettenis {
1753b725ae77Skettenis   int i;
1754b725ae77Skettenis 
1755b725ae77Skettenis   printf_filtered ("PC=%s SR=%016llx \n",
1756b725ae77Skettenis 		   paddr (read_register (PC_REGNUM)),
1757b725ae77Skettenis 		   (long long) read_register (SR_REGNUM));
1758b725ae77Skettenis 
1759b725ae77Skettenis   printf_filtered ("SSR=%016llx SPC=%016llx \n",
1760b725ae77Skettenis 		   (long long) read_register (SSR_REGNUM),
1761b725ae77Skettenis 		   (long long) read_register (SPC_REGNUM));
1762b725ae77Skettenis   printf_filtered ("FPSCR=%016lx\n ",
1763b725ae77Skettenis 		   (long) read_register (FPSCR_REGNUM));
1764b725ae77Skettenis 
1765b725ae77Skettenis   for (i = 0; i < 64; i = i + 4)
1766b725ae77Skettenis     printf_filtered ("\nR%d-R%d  %016llx %016llx %016llx %016llx\n",
1767b725ae77Skettenis 		     i, i + 3,
1768b725ae77Skettenis 		     (long long) read_register (i + 0),
1769b725ae77Skettenis 		     (long long) read_register (i + 1),
1770b725ae77Skettenis 		     (long long) read_register (i + 2),
1771b725ae77Skettenis 		     (long long) read_register (i + 3));
1772b725ae77Skettenis 
1773b725ae77Skettenis   printf_filtered ("\n");
1774b725ae77Skettenis 
1775b725ae77Skettenis   for (i = 0; i < 64; i = i + 8)
1776b725ae77Skettenis     printf_filtered ("FR%d-FR%d  %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
1777b725ae77Skettenis 		     i, i + 7,
1778b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 0),
1779b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 1),
1780b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 2),
1781b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 3),
1782b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 4),
1783b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 5),
1784b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 6),
1785b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 7));
1786b725ae77Skettenis }
1787b725ae77Skettenis 
1788b725ae77Skettenis static void
sh64_show_compact_regs(void)1789b725ae77Skettenis sh64_show_compact_regs (void)
1790b725ae77Skettenis {
1791b725ae77Skettenis   int i;
1792b725ae77Skettenis 
1793b725ae77Skettenis   printf_filtered ("PC=%s \n",
1794b725ae77Skettenis 		   paddr (read_register (PC_C_REGNUM)));
1795b725ae77Skettenis 
1796b725ae77Skettenis   printf_filtered ("GBR=%08lx MACH=%08lx MACL=%08lx PR=%08lx T=%08lx\n",
1797b725ae77Skettenis 		   (long) read_register (GBR_C_REGNUM),
1798b725ae77Skettenis 		   (long) read_register (MACH_C_REGNUM),
1799b725ae77Skettenis 		   (long) read_register (MACL_C_REGNUM),
1800b725ae77Skettenis 		   (long) read_register (PR_C_REGNUM),
1801b725ae77Skettenis 		   (long) read_register (T_C_REGNUM));
1802b725ae77Skettenis   printf_filtered ("FPSCR=%08lx FPUL=%08lx\n",
1803b725ae77Skettenis 		   (long) read_register (FPSCR_C_REGNUM),
1804b725ae77Skettenis 		   (long) read_register (FPUL_C_REGNUM));
1805b725ae77Skettenis 
1806b725ae77Skettenis   for (i = 0; i < 16; i = i + 4)
1807b725ae77Skettenis     printf_filtered ("\nR%d-R%d  %08lx %08lx %08lx %08lx\n",
1808b725ae77Skettenis 		     i, i + 3,
1809b725ae77Skettenis 		     (long) read_register (i + 0),
1810b725ae77Skettenis 		     (long) read_register (i + 1),
1811b725ae77Skettenis 		     (long) read_register (i + 2),
1812b725ae77Skettenis 		     (long) read_register (i + 3));
1813b725ae77Skettenis 
1814b725ae77Skettenis   printf_filtered ("\n");
1815b725ae77Skettenis 
1816b725ae77Skettenis   for (i = 0; i < 16; i = i + 8)
1817b725ae77Skettenis     printf_filtered ("FR%d-FR%d  %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
1818b725ae77Skettenis 		     i, i + 7,
1819b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 0),
1820b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 1),
1821b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 2),
1822b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 3),
1823b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 4),
1824b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 5),
1825b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 6),
1826b725ae77Skettenis 		     (long) read_register (FP0_REGNUM + i + 7));
1827b725ae77Skettenis }
1828b725ae77Skettenis 
1829b725ae77Skettenis /* FIXME!!! This only shows the registers for shmedia, excluding the
1830b725ae77Skettenis    pseudo registers.  */
1831b725ae77Skettenis void
sh64_show_regs(void)1832b725ae77Skettenis sh64_show_regs (void)
1833b725ae77Skettenis {
1834b725ae77Skettenis   if (deprecated_selected_frame
1835b725ae77Skettenis       && pc_is_isa32 (get_frame_pc (deprecated_selected_frame)))
1836b725ae77Skettenis     sh64_show_media_regs ();
1837b725ae77Skettenis   else
1838b725ae77Skettenis     sh64_show_compact_regs ();
1839b725ae77Skettenis }
1840b725ae77Skettenis 
1841b725ae77Skettenis /* *INDENT-OFF* */
1842b725ae77Skettenis /*
1843b725ae77Skettenis     SH MEDIA MODE (ISA 32)
1844b725ae77Skettenis     general registers (64-bit) 0-63
1845b725ae77Skettenis 0    r0,   r1,   r2,   r3,   r4,   r5,   r6,   r7,
1846b725ae77Skettenis 64   r8,   r9,   r10,  r11,  r12,  r13,  r14,  r15,
1847b725ae77Skettenis 128  r16,  r17,  r18,  r19,  r20,  r21,  r22,  r23,
1848b725ae77Skettenis 192  r24,  r25,  r26,  r27,  r28,  r29,  r30,  r31,
1849b725ae77Skettenis 256  r32,  r33,  r34,  r35,  r36,  r37,  r38,  r39,
1850b725ae77Skettenis 320  r40,  r41,  r42,  r43,  r44,  r45,  r46,  r47,
1851b725ae77Skettenis 384  r48,  r49,  r50,  r51,  r52,  r53,  r54,  r55,
1852b725ae77Skettenis 448  r56,  r57,  r58,  r59,  r60,  r61,  r62,  r63,
1853b725ae77Skettenis 
1854b725ae77Skettenis     pc (64-bit) 64
1855b725ae77Skettenis 512  pc,
1856b725ae77Skettenis 
1857b725ae77Skettenis     status reg., saved status reg., saved pc reg. (64-bit) 65-67
1858b725ae77Skettenis 520  sr,  ssr,  spc,
1859b725ae77Skettenis 
1860b725ae77Skettenis     target registers (64-bit) 68-75
1861b725ae77Skettenis 544  tr0,  tr1,  tr2,  tr3,  tr4,  tr5,  tr6,  tr7,
1862b725ae77Skettenis 
1863b725ae77Skettenis     floating point state control register (32-bit) 76
1864b725ae77Skettenis 608  fpscr,
1865b725ae77Skettenis 
1866b725ae77Skettenis     single precision floating point registers (32-bit) 77-140
1867b725ae77Skettenis 612  fr0,  fr1,  fr2,  fr3,  fr4,  fr5,  fr6,  fr7,
1868b725ae77Skettenis 644  fr8,  fr9,  fr10, fr11, fr12, fr13, fr14, fr15,
1869b725ae77Skettenis 676  fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
1870b725ae77Skettenis 708  fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31,
1871b725ae77Skettenis 740  fr32, fr33, fr34, fr35, fr36, fr37, fr38, fr39,
1872b725ae77Skettenis 772  fr40, fr41, fr42, fr43, fr44, fr45, fr46, fr47,
1873b725ae77Skettenis 804  fr48, fr49, fr50, fr51, fr52, fr53, fr54, fr55,
1874b725ae77Skettenis 836  fr56, fr57, fr58, fr59, fr60, fr61, fr62, fr63,
1875b725ae77Skettenis 
1876b725ae77Skettenis TOTAL SPACE FOR REGISTERS: 868 bytes
1877b725ae77Skettenis 
1878b725ae77Skettenis From here on they are all pseudo registers: no memory allocated.
1879b725ae77Skettenis REGISTER_BYTE returns the register byte for the base register.
1880b725ae77Skettenis 
1881b725ae77Skettenis     double precision registers (pseudo) 141-172
1882b725ae77Skettenis      dr0,  dr2,  dr4,  dr6,  dr8,  dr10, dr12, dr14,
1883b725ae77Skettenis      dr16, dr18, dr20, dr22, dr24, dr26, dr28, dr30,
1884b725ae77Skettenis      dr32, dr34, dr36, dr38, dr40, dr42, dr44, dr46,
1885b725ae77Skettenis      dr48, dr50, dr52, dr54, dr56, dr58, dr60, dr62,
1886b725ae77Skettenis 
1887b725ae77Skettenis     floating point pairs (pseudo) 173-204
1888b725ae77Skettenis      fp0,  fp2,  fp4,  fp6,  fp8,  fp10, fp12, fp14,
1889b725ae77Skettenis      fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30,
1890b725ae77Skettenis      fp32, fp34, fp36, fp38, fp40, fp42, fp44, fp46,
1891b725ae77Skettenis      fp48, fp50, fp52, fp54, fp56, fp58, fp60, fp62,
1892b725ae77Skettenis 
1893b725ae77Skettenis     floating point vectors (4 floating point regs) (pseudo) 205-220
1894b725ae77Skettenis      fv0,  fv4,  fv8,  fv12, fv16, fv20, fv24, fv28,
1895b725ae77Skettenis      fv32, fv36, fv40, fv44, fv48, fv52, fv56, fv60,
1896b725ae77Skettenis 
1897b725ae77Skettenis     SH COMPACT MODE (ISA 16) (all pseudo) 221-272
1898b725ae77Skettenis      r0_c, r1_c, r2_c,  r3_c,  r4_c,  r5_c,  r6_c,  r7_c,
1899b725ae77Skettenis      r8_c, r9_c, r10_c, r11_c, r12_c, r13_c, r14_c, r15_c,
1900b725ae77Skettenis      pc_c,
1901b725ae77Skettenis      gbr_c, mach_c, macl_c, pr_c, t_c,
1902b725ae77Skettenis      fpscr_c, fpul_c,
1903b725ae77Skettenis      fr0_c, fr1_c, fr2_c,  fr3_c,  fr4_c,  fr5_c,  fr6_c,  fr7_c,
1904b725ae77Skettenis      fr8_c, fr9_c, fr10_c, fr11_c, fr12_c, fr13_c, fr14_c, fr15_c
1905b725ae77Skettenis      dr0_c, dr2_c, dr4_c,  dr6_c,  dr8_c,  dr10_c, dr12_c, dr14_c
1906b725ae77Skettenis      fv0_c, fv4_c, fv8_c,  fv12_c
1907b725ae77Skettenis */
1908b725ae77Skettenis /* *INDENT-ON* */
1909b725ae77Skettenis static int
sh64_register_byte(int reg_nr)1910b725ae77Skettenis sh64_register_byte (int reg_nr)
1911b725ae77Skettenis {
1912b725ae77Skettenis   int base_regnum = -1;
1913b725ae77Skettenis 
1914b725ae77Skettenis   /* If it is a pseudo register, get the number of the first floating
1915b725ae77Skettenis      point register that is part of it.  */
1916b725ae77Skettenis   if (reg_nr >= DR0_REGNUM
1917b725ae77Skettenis       && reg_nr <= DR_LAST_REGNUM)
1918b725ae77Skettenis     base_regnum = dr_reg_base_num (reg_nr);
1919b725ae77Skettenis 
1920b725ae77Skettenis   else if (reg_nr >= FPP0_REGNUM
1921b725ae77Skettenis 	    && reg_nr <= FPP_LAST_REGNUM)
1922b725ae77Skettenis     base_regnum = fpp_reg_base_num (reg_nr);
1923b725ae77Skettenis 
1924b725ae77Skettenis   else if (reg_nr >= FV0_REGNUM
1925b725ae77Skettenis 	    && reg_nr <= FV_LAST_REGNUM)
1926b725ae77Skettenis     base_regnum = fv_reg_base_num (reg_nr);
1927b725ae77Skettenis 
1928b725ae77Skettenis   /* sh compact pseudo register. FPSCR is a pathological case, need to
1929b725ae77Skettenis      treat it as special.  */
1930b725ae77Skettenis   else if ((reg_nr >= R0_C_REGNUM
1931b725ae77Skettenis 	    && reg_nr <= FV_LAST_C_REGNUM)
1932b725ae77Skettenis 	   && reg_nr != FPSCR_C_REGNUM)
1933b725ae77Skettenis     base_regnum = sh64_compact_reg_base_num (reg_nr);
1934b725ae77Skettenis 
1935b725ae77Skettenis   /* Now return the offset in bytes within the register cache.  */
1936b725ae77Skettenis   /* sh media pseudo register, i.e. any of DR, FFP, FV registers.  */
1937b725ae77Skettenis   if (reg_nr >= DR0_REGNUM
1938b725ae77Skettenis       && reg_nr <= FV_LAST_REGNUM)
1939b725ae77Skettenis     return (base_regnum - FP0_REGNUM + 1) * 4
1940b725ae77Skettenis       + (TR7_REGNUM + 1) * 8;
1941b725ae77Skettenis 
1942b725ae77Skettenis   /* sh compact pseudo register: general register */
1943b725ae77Skettenis   if ((reg_nr >= R0_C_REGNUM
1944b725ae77Skettenis        && reg_nr <= R_LAST_C_REGNUM))
1945b725ae77Skettenis     return (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
1946b725ae77Skettenis 	    ? base_regnum * 8 + 4
1947b725ae77Skettenis 	    : base_regnum * 8);
1948b725ae77Skettenis 
1949b725ae77Skettenis   /* sh compact pseudo register: */
1950b725ae77Skettenis   if (reg_nr == PC_C_REGNUM
1951b725ae77Skettenis        || reg_nr == GBR_C_REGNUM
1952b725ae77Skettenis        || reg_nr == MACL_C_REGNUM
1953b725ae77Skettenis        || reg_nr == PR_C_REGNUM)
1954b725ae77Skettenis     return (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
1955b725ae77Skettenis 	    ? base_regnum * 8 + 4
1956b725ae77Skettenis 	    : base_regnum * 8);
1957b725ae77Skettenis 
1958b725ae77Skettenis   if (reg_nr == MACH_C_REGNUM)
1959b725ae77Skettenis     return base_regnum * 8;
1960b725ae77Skettenis 
1961b725ae77Skettenis   if (reg_nr == T_C_REGNUM)
1962b725ae77Skettenis     return base_regnum * 8; /* FIXME??? how do we get bit 0? Do we have to? */
1963b725ae77Skettenis 
1964b725ae77Skettenis   /* sh compact pseudo register: floating point register */
1965b725ae77Skettenis   else if (reg_nr >= FP0_C_REGNUM
1966b725ae77Skettenis 	   && reg_nr <= FV_LAST_C_REGNUM)
1967b725ae77Skettenis     return (base_regnum  - FP0_REGNUM) * 4
1968b725ae77Skettenis       + (TR7_REGNUM + 1) * 8 + 4;
1969b725ae77Skettenis 
1970b725ae77Skettenis   else if (reg_nr == FPSCR_C_REGNUM)
1971b725ae77Skettenis     /* This is complicated, for now return the beginning of the
1972b725ae77Skettenis        architectural FPSCR register.  */
1973b725ae77Skettenis     return (TR7_REGNUM + 1) * 8;
1974b725ae77Skettenis 
1975b725ae77Skettenis   else if (reg_nr == FPUL_C_REGNUM)
1976b725ae77Skettenis     return ((base_regnum - FP0_REGNUM) * 4 +
1977b725ae77Skettenis 	    (TR7_REGNUM + 1) * 8 + 4);
1978b725ae77Skettenis 
1979b725ae77Skettenis   /* It is not a pseudo register.  */
1980b725ae77Skettenis   /* It is a 64 bit register.  */
1981b725ae77Skettenis   else if (reg_nr <= TR7_REGNUM)
1982b725ae77Skettenis     return reg_nr * 8;
1983b725ae77Skettenis 
1984b725ae77Skettenis   /* It is a 32 bit register.  */
1985b725ae77Skettenis   else if (reg_nr == FPSCR_REGNUM)
1986b725ae77Skettenis     return (FPSCR_REGNUM * 8);
1987b725ae77Skettenis 
1988b725ae77Skettenis   /* It is floating point 32-bit register */
1989b725ae77Skettenis   else
1990b725ae77Skettenis     return ((TR7_REGNUM + 1) * 8
1991b725ae77Skettenis       + (reg_nr - FP0_REGNUM + 1) * 4);
1992b725ae77Skettenis }
1993b725ae77Skettenis 
1994b725ae77Skettenis static struct type *
sh64_build_float_register_type(int high)1995b725ae77Skettenis sh64_build_float_register_type (int high)
1996b725ae77Skettenis {
1997b725ae77Skettenis   struct type *temp;
1998b725ae77Skettenis 
1999b725ae77Skettenis   temp = create_range_type (NULL, builtin_type_int, 0, high);
2000b725ae77Skettenis   return create_array_type (NULL, builtin_type_float, temp);
2001b725ae77Skettenis }
2002b725ae77Skettenis 
2003b725ae77Skettenis /* Return the GDB type object for the "standard" data type
2004b725ae77Skettenis    of data in register REG_NR.  */
2005b725ae77Skettenis static struct type *
sh64_register_type(struct gdbarch * gdbarch,int reg_nr)2006b725ae77Skettenis sh64_register_type (struct gdbarch *gdbarch, int reg_nr)
2007b725ae77Skettenis {
2008b725ae77Skettenis   if ((reg_nr >= FP0_REGNUM
2009b725ae77Skettenis        && reg_nr <= FP_LAST_REGNUM)
2010b725ae77Skettenis       || (reg_nr >= FP0_C_REGNUM
2011b725ae77Skettenis 	  && reg_nr <= FP_LAST_C_REGNUM))
2012b725ae77Skettenis     return builtin_type_float;
2013b725ae77Skettenis   else if ((reg_nr >= DR0_REGNUM
2014b725ae77Skettenis 	    && reg_nr <= DR_LAST_REGNUM)
2015b725ae77Skettenis 	   || (reg_nr >= DR0_C_REGNUM
2016b725ae77Skettenis 	       && reg_nr <= DR_LAST_C_REGNUM))
2017b725ae77Skettenis     return builtin_type_double;
2018b725ae77Skettenis   else if  (reg_nr >= FPP0_REGNUM
2019b725ae77Skettenis 	    && reg_nr <= FPP_LAST_REGNUM)
2020b725ae77Skettenis     return sh64_build_float_register_type (1);
2021b725ae77Skettenis   else if ((reg_nr >= FV0_REGNUM
2022b725ae77Skettenis 	    && reg_nr <= FV_LAST_REGNUM)
2023b725ae77Skettenis 	   ||(reg_nr >= FV0_C_REGNUM
2024b725ae77Skettenis 	      && reg_nr <= FV_LAST_C_REGNUM))
2025b725ae77Skettenis     return sh64_build_float_register_type (3);
2026b725ae77Skettenis   else if (reg_nr == FPSCR_REGNUM)
2027b725ae77Skettenis     return builtin_type_int;
2028b725ae77Skettenis   else if (reg_nr >= R0_C_REGNUM
2029b725ae77Skettenis 	   && reg_nr < FP0_C_REGNUM)
2030b725ae77Skettenis     return builtin_type_int;
2031b725ae77Skettenis   else
2032b725ae77Skettenis     return builtin_type_long_long;
2033b725ae77Skettenis }
2034b725ae77Skettenis 
2035b725ae77Skettenis static void
sh64_register_convert_to_virtual(int regnum,struct type * type,char * from,char * to)2036b725ae77Skettenis sh64_register_convert_to_virtual (int regnum, struct type *type,
2037b725ae77Skettenis 				     char *from, char *to)
2038b725ae77Skettenis {
2039b725ae77Skettenis   if (TARGET_BYTE_ORDER != BFD_ENDIAN_LITTLE)
2040b725ae77Skettenis     {
2041b725ae77Skettenis       /* It is a no-op.  */
2042b725ae77Skettenis       memcpy (to, from, register_size (current_gdbarch, regnum));
2043b725ae77Skettenis       return;
2044b725ae77Skettenis     }
2045b725ae77Skettenis 
2046b725ae77Skettenis   if ((regnum >= DR0_REGNUM
2047b725ae77Skettenis        && regnum <= DR_LAST_REGNUM)
2048b725ae77Skettenis       || (regnum >= DR0_C_REGNUM
2049b725ae77Skettenis 	  && regnum <= DR_LAST_C_REGNUM))
2050b725ae77Skettenis     {
2051b725ae77Skettenis       DOUBLEST val;
2052b725ae77Skettenis       floatformat_to_doublest (&floatformat_ieee_double_littlebyte_bigword,
2053b725ae77Skettenis 			       from, &val);
2054b725ae77Skettenis       store_typed_floating (to, type, val);
2055b725ae77Skettenis     }
2056b725ae77Skettenis   else
2057b725ae77Skettenis     error ("sh64_register_convert_to_virtual called with non DR register number");
2058b725ae77Skettenis }
2059b725ae77Skettenis 
2060b725ae77Skettenis static void
sh64_register_convert_to_raw(struct type * type,int regnum,const void * from,void * to)2061b725ae77Skettenis sh64_register_convert_to_raw (struct type *type, int regnum,
2062b725ae77Skettenis 				 const void *from, void *to)
2063b725ae77Skettenis {
2064b725ae77Skettenis   if (TARGET_BYTE_ORDER != BFD_ENDIAN_LITTLE)
2065b725ae77Skettenis     {
2066b725ae77Skettenis       /* It is a no-op.  */
2067b725ae77Skettenis       memcpy (to, from, register_size (current_gdbarch, regnum));
2068b725ae77Skettenis       return;
2069b725ae77Skettenis     }
2070b725ae77Skettenis 
2071b725ae77Skettenis   if ((regnum >= DR0_REGNUM
2072b725ae77Skettenis        && regnum <= DR_LAST_REGNUM)
2073b725ae77Skettenis       || (regnum >= DR0_C_REGNUM
2074b725ae77Skettenis 	  && regnum <= DR_LAST_C_REGNUM))
2075b725ae77Skettenis     {
2076b725ae77Skettenis       DOUBLEST val = deprecated_extract_floating (from, TYPE_LENGTH(type));
2077b725ae77Skettenis       floatformat_from_doublest (&floatformat_ieee_double_littlebyte_bigword,
2078b725ae77Skettenis 				 &val, to);
2079b725ae77Skettenis     }
2080b725ae77Skettenis   else
2081b725ae77Skettenis     error ("sh64_register_convert_to_raw called with non DR register number");
2082b725ae77Skettenis }
2083b725ae77Skettenis 
2084b725ae77Skettenis static void
sh64_pseudo_register_read(struct gdbarch * gdbarch,struct regcache * regcache,int reg_nr,void * buffer)2085b725ae77Skettenis sh64_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
2086b725ae77Skettenis 			   int reg_nr, void *buffer)
2087b725ae77Skettenis {
2088b725ae77Skettenis   int base_regnum;
2089b725ae77Skettenis   int portion;
2090b725ae77Skettenis   int offset = 0;
2091b725ae77Skettenis   char temp_buffer[MAX_REGISTER_SIZE];
2092b725ae77Skettenis 
2093b725ae77Skettenis   if (reg_nr >= DR0_REGNUM
2094b725ae77Skettenis       && reg_nr <= DR_LAST_REGNUM)
2095b725ae77Skettenis     {
2096b725ae77Skettenis       base_regnum = dr_reg_base_num (reg_nr);
2097b725ae77Skettenis 
2098b725ae77Skettenis       /* Build the value in the provided buffer.  */
2099b725ae77Skettenis       /* DR regs are double precision registers obtained by
2100b725ae77Skettenis 	 concatenating 2 single precision floating point registers.  */
2101b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2102b725ae77Skettenis 	regcache_raw_read (regcache, base_regnum + portion,
2103b725ae77Skettenis 			   (temp_buffer
2104b725ae77Skettenis 			    + register_size (gdbarch, base_regnum) * portion));
2105b725ae77Skettenis 
2106b725ae77Skettenis       /* We must pay attention to the endianness.  */
2107b725ae77Skettenis       sh64_register_convert_to_virtual (reg_nr,
2108b725ae77Skettenis 					gdbarch_register_type (gdbarch,
2109b725ae77Skettenis 							       reg_nr),
2110b725ae77Skettenis 					temp_buffer, buffer);
2111b725ae77Skettenis 
2112b725ae77Skettenis     }
2113b725ae77Skettenis 
2114b725ae77Skettenis   else if (reg_nr >= FPP0_REGNUM
2115b725ae77Skettenis 	   && reg_nr <= FPP_LAST_REGNUM)
2116b725ae77Skettenis     {
2117b725ae77Skettenis       base_regnum = fpp_reg_base_num (reg_nr);
2118b725ae77Skettenis 
2119b725ae77Skettenis       /* Build the value in the provided buffer.  */
2120b725ae77Skettenis       /* FPP regs are pairs of single precision registers obtained by
2121b725ae77Skettenis 	 concatenating 2 single precision floating point registers.  */
2122b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2123b725ae77Skettenis 	regcache_raw_read (regcache, base_regnum + portion,
2124b725ae77Skettenis 			   ((char *) buffer
2125b725ae77Skettenis 			    + register_size (gdbarch, base_regnum) * portion));
2126b725ae77Skettenis     }
2127b725ae77Skettenis 
2128b725ae77Skettenis   else if (reg_nr >= FV0_REGNUM
2129b725ae77Skettenis 	   && reg_nr <= FV_LAST_REGNUM)
2130b725ae77Skettenis     {
2131b725ae77Skettenis       base_regnum = fv_reg_base_num (reg_nr);
2132b725ae77Skettenis 
2133b725ae77Skettenis       /* Build the value in the provided buffer.  */
2134b725ae77Skettenis       /* FV regs are vectors of single precision registers obtained by
2135b725ae77Skettenis 	 concatenating 4 single precision floating point registers.  */
2136b725ae77Skettenis       for (portion = 0; portion < 4; portion++)
2137b725ae77Skettenis 	regcache_raw_read (regcache, base_regnum + portion,
2138b725ae77Skettenis 			   ((char *) buffer
2139b725ae77Skettenis 			    + register_size (gdbarch, base_regnum) * portion));
2140b725ae77Skettenis     }
2141b725ae77Skettenis 
2142b725ae77Skettenis   /* sh compact pseudo registers. 1-to-1 with a shmedia register */
2143b725ae77Skettenis   else if (reg_nr >= R0_C_REGNUM
2144b725ae77Skettenis 	   && reg_nr <= T_C_REGNUM)
2145b725ae77Skettenis     {
2146b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2147b725ae77Skettenis 
2148b725ae77Skettenis       /* Build the value in the provided buffer.  */
2149b725ae77Skettenis       regcache_raw_read (regcache, base_regnum, temp_buffer);
2150b725ae77Skettenis       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
2151b725ae77Skettenis 	offset = 4;
2152b725ae77Skettenis       memcpy (buffer, temp_buffer + offset, 4); /* get LOWER 32 bits only????*/
2153b725ae77Skettenis     }
2154b725ae77Skettenis 
2155b725ae77Skettenis   else if (reg_nr >= FP0_C_REGNUM
2156b725ae77Skettenis 	   && reg_nr <= FP_LAST_C_REGNUM)
2157b725ae77Skettenis     {
2158b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2159b725ae77Skettenis 
2160b725ae77Skettenis       /* Build the value in the provided buffer.  */
2161b725ae77Skettenis       /* Floating point registers map 1-1 to the media fp regs,
2162b725ae77Skettenis 	 they have the same size and endianness.  */
2163b725ae77Skettenis       regcache_raw_read (regcache, base_regnum, buffer);
2164b725ae77Skettenis     }
2165b725ae77Skettenis 
2166b725ae77Skettenis   else if (reg_nr >= DR0_C_REGNUM
2167b725ae77Skettenis 	   && reg_nr <= DR_LAST_C_REGNUM)
2168b725ae77Skettenis     {
2169b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2170b725ae77Skettenis 
2171b725ae77Skettenis       /* DR_C regs are double precision registers obtained by
2172b725ae77Skettenis 	 concatenating 2 single precision floating point registers.  */
2173b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2174b725ae77Skettenis 	regcache_raw_read (regcache, base_regnum + portion,
2175b725ae77Skettenis 			   (temp_buffer
2176b725ae77Skettenis 			    + register_size (gdbarch, base_regnum) * portion));
2177b725ae77Skettenis 
2178b725ae77Skettenis       /* We must pay attention to the endianness.  */
2179b725ae77Skettenis       sh64_register_convert_to_virtual (reg_nr,
2180b725ae77Skettenis 					gdbarch_register_type (gdbarch,
2181b725ae77Skettenis 							       reg_nr),
2182b725ae77Skettenis 					temp_buffer, buffer);
2183b725ae77Skettenis     }
2184b725ae77Skettenis 
2185b725ae77Skettenis   else if (reg_nr >= FV0_C_REGNUM
2186b725ae77Skettenis 	   && reg_nr <= FV_LAST_C_REGNUM)
2187b725ae77Skettenis     {
2188b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2189b725ae77Skettenis 
2190b725ae77Skettenis       /* Build the value in the provided buffer.  */
2191b725ae77Skettenis       /* FV_C regs are vectors of single precision registers obtained by
2192b725ae77Skettenis 	 concatenating 4 single precision floating point registers.  */
2193b725ae77Skettenis       for (portion = 0; portion < 4; portion++)
2194b725ae77Skettenis 	regcache_raw_read (regcache, base_regnum + portion,
2195b725ae77Skettenis 			   ((char *) buffer
2196b725ae77Skettenis 			    + register_size (gdbarch, base_regnum) * portion));
2197b725ae77Skettenis     }
2198b725ae77Skettenis 
2199b725ae77Skettenis   else if (reg_nr == FPSCR_C_REGNUM)
2200b725ae77Skettenis     {
2201b725ae77Skettenis       int fpscr_base_regnum;
2202b725ae77Skettenis       int sr_base_regnum;
2203b725ae77Skettenis       unsigned int fpscr_value;
2204b725ae77Skettenis       unsigned int sr_value;
2205b725ae77Skettenis       unsigned int fpscr_c_value;
2206b725ae77Skettenis       unsigned int fpscr_c_part1_value;
2207b725ae77Skettenis       unsigned int fpscr_c_part2_value;
2208b725ae77Skettenis 
2209b725ae77Skettenis       fpscr_base_regnum = FPSCR_REGNUM;
2210b725ae77Skettenis       sr_base_regnum = SR_REGNUM;
2211b725ae77Skettenis 
2212b725ae77Skettenis       /* Build the value in the provided buffer.  */
2213b725ae77Skettenis       /* FPSCR_C is a very weird register that contains sparse bits
2214b725ae77Skettenis 	 from the FPSCR and the SR architectural registers.
2215b725ae77Skettenis 	 Specifically: */
2216b725ae77Skettenis       /* *INDENT-OFF* */
2217b725ae77Skettenis       /*
2218b725ae77Skettenis 	 FPSRC_C bit
2219b725ae77Skettenis             0         Bit 0 of FPSCR
2220b725ae77Skettenis             1         reserved
2221b725ae77Skettenis             2-17      Bit 2-18 of FPSCR
2222b725ae77Skettenis             18-20     Bits 12,13,14 of SR
2223b725ae77Skettenis             21-31     reserved
2224b725ae77Skettenis        */
2225b725ae77Skettenis       /* *INDENT-ON* */
2226b725ae77Skettenis       /* Get FPSCR into a local buffer */
2227b725ae77Skettenis       regcache_raw_read (regcache, fpscr_base_regnum, temp_buffer);
2228b725ae77Skettenis       /* Get value as an int.  */
2229b725ae77Skettenis       fpscr_value = extract_unsigned_integer (temp_buffer, 4);
2230b725ae77Skettenis       /* Get SR into a local buffer */
2231b725ae77Skettenis       regcache_raw_read (regcache, sr_base_regnum, temp_buffer);
2232b725ae77Skettenis       /* Get value as an int.  */
2233b725ae77Skettenis       sr_value = extract_unsigned_integer (temp_buffer, 4);
2234b725ae77Skettenis       /* Build the new value.  */
2235b725ae77Skettenis       fpscr_c_part1_value = fpscr_value & 0x3fffd;
2236b725ae77Skettenis       fpscr_c_part2_value = (sr_value & 0x7000) << 6;
2237b725ae77Skettenis       fpscr_c_value = fpscr_c_part1_value | fpscr_c_part2_value;
2238b725ae77Skettenis       /* Store that in out buffer!!! */
2239b725ae77Skettenis       store_unsigned_integer (buffer, 4, fpscr_c_value);
2240b725ae77Skettenis       /* FIXME There is surely an endianness gotcha here.  */
2241b725ae77Skettenis     }
2242b725ae77Skettenis 
2243b725ae77Skettenis   else if (reg_nr == FPUL_C_REGNUM)
2244b725ae77Skettenis     {
2245b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2246b725ae77Skettenis 
2247b725ae77Skettenis       /* FPUL_C register is floating point register 32,
2248b725ae77Skettenis 	 same size, same endianness.  */
2249b725ae77Skettenis       regcache_raw_read (regcache, base_regnum, buffer);
2250b725ae77Skettenis     }
2251b725ae77Skettenis }
2252b725ae77Skettenis 
2253b725ae77Skettenis static void
sh64_pseudo_register_write(struct gdbarch * gdbarch,struct regcache * regcache,int reg_nr,const void * buffer)2254b725ae77Skettenis sh64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
2255b725ae77Skettenis 			    int reg_nr, const void *buffer)
2256b725ae77Skettenis {
2257b725ae77Skettenis   int base_regnum, portion;
2258b725ae77Skettenis   int offset;
2259b725ae77Skettenis   char temp_buffer[MAX_REGISTER_SIZE];
2260b725ae77Skettenis 
2261b725ae77Skettenis   if (reg_nr >= DR0_REGNUM
2262b725ae77Skettenis       && reg_nr <= DR_LAST_REGNUM)
2263b725ae77Skettenis     {
2264b725ae77Skettenis       base_regnum = dr_reg_base_num (reg_nr);
2265b725ae77Skettenis       /* We must pay attention to the endianness.  */
2266b725ae77Skettenis       sh64_register_convert_to_raw (gdbarch_register_type (gdbarch, reg_nr),
2267b725ae77Skettenis 				    reg_nr,
2268b725ae77Skettenis 				    buffer, temp_buffer);
2269b725ae77Skettenis 
2270b725ae77Skettenis       /* Write the real regs for which this one is an alias.  */
2271b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2272b725ae77Skettenis 	regcache_raw_write (regcache, base_regnum + portion,
2273b725ae77Skettenis 			    (temp_buffer
2274b725ae77Skettenis 			     + register_size (gdbarch,
2275b725ae77Skettenis 					      base_regnum) * portion));
2276b725ae77Skettenis     }
2277b725ae77Skettenis 
2278b725ae77Skettenis   else if (reg_nr >= FPP0_REGNUM
2279b725ae77Skettenis 	   && reg_nr <= FPP_LAST_REGNUM)
2280b725ae77Skettenis     {
2281b725ae77Skettenis       base_regnum = fpp_reg_base_num (reg_nr);
2282b725ae77Skettenis 
2283b725ae77Skettenis       /* Write the real regs for which this one is an alias.  */
2284b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2285b725ae77Skettenis 	regcache_raw_write (regcache, base_regnum + portion,
2286b725ae77Skettenis 			    ((char *) buffer
2287b725ae77Skettenis 			     + register_size (gdbarch,
2288b725ae77Skettenis 					      base_regnum) * portion));
2289b725ae77Skettenis     }
2290b725ae77Skettenis 
2291b725ae77Skettenis   else if (reg_nr >= FV0_REGNUM
2292b725ae77Skettenis 	   && reg_nr <= FV_LAST_REGNUM)
2293b725ae77Skettenis     {
2294b725ae77Skettenis       base_regnum = fv_reg_base_num (reg_nr);
2295b725ae77Skettenis 
2296b725ae77Skettenis       /* Write the real regs for which this one is an alias.  */
2297b725ae77Skettenis       for (portion = 0; portion < 4; portion++)
2298b725ae77Skettenis 	regcache_raw_write (regcache, base_regnum + portion,
2299b725ae77Skettenis 			    ((char *) buffer
2300b725ae77Skettenis 			     + register_size (gdbarch,
2301b725ae77Skettenis 					      base_regnum) * portion));
2302b725ae77Skettenis     }
2303b725ae77Skettenis 
2304b725ae77Skettenis   /* sh compact general pseudo registers. 1-to-1 with a shmedia
2305b725ae77Skettenis      register but only 4 bytes of it.  */
2306b725ae77Skettenis   else if (reg_nr >= R0_C_REGNUM
2307b725ae77Skettenis 	   && reg_nr <= T_C_REGNUM)
2308b725ae77Skettenis     {
2309b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2310b725ae77Skettenis       /* reg_nr is 32 bit here, and base_regnum is 64 bits.  */
2311b725ae77Skettenis       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
2312b725ae77Skettenis 	offset = 4;
2313b725ae77Skettenis       else
2314b725ae77Skettenis 	offset = 0;
2315b725ae77Skettenis       /* Let's read the value of the base register into a temporary
2316b725ae77Skettenis 	 buffer, so that overwriting the last four bytes with the new
2317b725ae77Skettenis 	 value of the pseudo will leave the upper 4 bytes unchanged.  */
2318b725ae77Skettenis       regcache_raw_read (regcache, base_regnum, temp_buffer);
2319b725ae77Skettenis       /* Write as an 8 byte quantity */
2320b725ae77Skettenis       memcpy (temp_buffer + offset, buffer, 4);
2321b725ae77Skettenis       regcache_raw_write (regcache, base_regnum, temp_buffer);
2322b725ae77Skettenis     }
2323b725ae77Skettenis 
2324b725ae77Skettenis   /* sh floating point compact pseudo registers. 1-to-1 with a shmedia
2325b725ae77Skettenis      registers. Both are 4 bytes.  */
2326b725ae77Skettenis   else if (reg_nr >= FP0_C_REGNUM
2327b725ae77Skettenis 	       && reg_nr <= FP_LAST_C_REGNUM)
2328b725ae77Skettenis     {
2329b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2330b725ae77Skettenis       regcache_raw_write (regcache, base_regnum, buffer);
2331b725ae77Skettenis     }
2332b725ae77Skettenis 
2333b725ae77Skettenis   else if (reg_nr >= DR0_C_REGNUM
2334b725ae77Skettenis 	   && reg_nr <= DR_LAST_C_REGNUM)
2335b725ae77Skettenis     {
2336b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2337b725ae77Skettenis       for (portion = 0; portion < 2; portion++)
2338b725ae77Skettenis 	{
2339b725ae77Skettenis 	  /* We must pay attention to the endianness.  */
2340b725ae77Skettenis 	  sh64_register_convert_to_raw (gdbarch_register_type (gdbarch,
2341b725ae77Skettenis 							       reg_nr),
2342b725ae77Skettenis 					reg_nr,
2343b725ae77Skettenis 					buffer, temp_buffer);
2344b725ae77Skettenis 
2345b725ae77Skettenis 	  regcache_raw_write (regcache, base_regnum + portion,
2346b725ae77Skettenis 			      (temp_buffer
2347b725ae77Skettenis 			       + register_size (gdbarch,
2348b725ae77Skettenis 						base_regnum) * portion));
2349b725ae77Skettenis 	}
2350b725ae77Skettenis     }
2351b725ae77Skettenis 
2352b725ae77Skettenis   else if (reg_nr >= FV0_C_REGNUM
2353b725ae77Skettenis 	   && reg_nr <= FV_LAST_C_REGNUM)
2354b725ae77Skettenis     {
2355b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2356b725ae77Skettenis 
2357b725ae77Skettenis       for (portion = 0; portion < 4; portion++)
2358b725ae77Skettenis 	{
2359b725ae77Skettenis 	  regcache_raw_write (regcache, base_regnum + portion,
2360b725ae77Skettenis 			      ((char *) buffer
2361b725ae77Skettenis 			       + register_size (gdbarch,
2362b725ae77Skettenis 						base_regnum) * portion));
2363b725ae77Skettenis 	}
2364b725ae77Skettenis     }
2365b725ae77Skettenis 
2366b725ae77Skettenis   else if (reg_nr == FPSCR_C_REGNUM)
2367b725ae77Skettenis     {
2368b725ae77Skettenis       int fpscr_base_regnum;
2369b725ae77Skettenis       int sr_base_regnum;
2370b725ae77Skettenis       unsigned int fpscr_value;
2371b725ae77Skettenis       unsigned int sr_value;
2372b725ae77Skettenis       unsigned int old_fpscr_value;
2373b725ae77Skettenis       unsigned int old_sr_value;
2374b725ae77Skettenis       unsigned int fpscr_c_value;
2375b725ae77Skettenis       unsigned int fpscr_mask;
2376b725ae77Skettenis       unsigned int sr_mask;
2377b725ae77Skettenis 
2378b725ae77Skettenis       fpscr_base_regnum = FPSCR_REGNUM;
2379b725ae77Skettenis       sr_base_regnum = SR_REGNUM;
2380b725ae77Skettenis 
2381b725ae77Skettenis       /* FPSCR_C is a very weird register that contains sparse bits
2382b725ae77Skettenis 	 from the FPSCR and the SR architectural registers.
2383b725ae77Skettenis 	 Specifically: */
2384b725ae77Skettenis       /* *INDENT-OFF* */
2385b725ae77Skettenis       /*
2386b725ae77Skettenis 	 FPSRC_C bit
2387b725ae77Skettenis             0         Bit 0 of FPSCR
2388b725ae77Skettenis             1         reserved
2389b725ae77Skettenis             2-17      Bit 2-18 of FPSCR
2390b725ae77Skettenis             18-20     Bits 12,13,14 of SR
2391b725ae77Skettenis             21-31     reserved
2392b725ae77Skettenis        */
2393b725ae77Skettenis       /* *INDENT-ON* */
2394b725ae77Skettenis       /* Get value as an int.  */
2395b725ae77Skettenis       fpscr_c_value = extract_unsigned_integer (buffer, 4);
2396b725ae77Skettenis 
2397b725ae77Skettenis       /* Build the new values.  */
2398b725ae77Skettenis       fpscr_mask = 0x0003fffd;
2399b725ae77Skettenis       sr_mask = 0x001c0000;
2400b725ae77Skettenis 
2401b725ae77Skettenis       fpscr_value = fpscr_c_value & fpscr_mask;
2402b725ae77Skettenis       sr_value = (fpscr_value & sr_mask) >> 6;
2403b725ae77Skettenis 
2404b725ae77Skettenis       regcache_raw_read (regcache, fpscr_base_regnum, temp_buffer);
2405b725ae77Skettenis       old_fpscr_value = extract_unsigned_integer (temp_buffer, 4);
2406b725ae77Skettenis       old_fpscr_value &= 0xfffc0002;
2407b725ae77Skettenis       fpscr_value |= old_fpscr_value;
2408b725ae77Skettenis       store_unsigned_integer (temp_buffer, 4, fpscr_value);
2409b725ae77Skettenis       regcache_raw_write (regcache, fpscr_base_regnum, temp_buffer);
2410b725ae77Skettenis 
2411b725ae77Skettenis       regcache_raw_read (regcache, sr_base_regnum, temp_buffer);
2412b725ae77Skettenis       old_sr_value = extract_unsigned_integer (temp_buffer, 4);
2413b725ae77Skettenis       old_sr_value &= 0xffff8fff;
2414b725ae77Skettenis       sr_value |= old_sr_value;
2415b725ae77Skettenis       store_unsigned_integer (temp_buffer, 4, sr_value);
2416b725ae77Skettenis       regcache_raw_write (regcache, sr_base_regnum, temp_buffer);
2417b725ae77Skettenis     }
2418b725ae77Skettenis 
2419b725ae77Skettenis   else if (reg_nr == FPUL_C_REGNUM)
2420b725ae77Skettenis     {
2421b725ae77Skettenis       base_regnum = sh64_compact_reg_base_num (reg_nr);
2422b725ae77Skettenis       regcache_raw_write (regcache, base_regnum, buffer);
2423b725ae77Skettenis     }
2424b725ae77Skettenis }
2425b725ae77Skettenis 
2426b725ae77Skettenis /* Floating point vector of 4 float registers.  */
2427b725ae77Skettenis static void
do_fv_register_info(struct gdbarch * gdbarch,struct ui_file * file,int fv_regnum)2428b725ae77Skettenis do_fv_register_info (struct gdbarch *gdbarch, struct ui_file *file,
2429b725ae77Skettenis 		     int fv_regnum)
2430b725ae77Skettenis {
2431b725ae77Skettenis   int first_fp_reg_num = fv_reg_base_num (fv_regnum);
2432b725ae77Skettenis   fprintf_filtered (file, "fv%d\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n",
2433b725ae77Skettenis 		     fv_regnum - FV0_REGNUM,
2434b725ae77Skettenis 		     (int) read_register (first_fp_reg_num),
2435b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 1),
2436b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 2),
2437b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 3));
2438b725ae77Skettenis }
2439b725ae77Skettenis 
2440b725ae77Skettenis /* Floating point vector of 4 float registers, compact mode.  */
2441b725ae77Skettenis static void
do_fv_c_register_info(int fv_regnum)2442b725ae77Skettenis do_fv_c_register_info (int fv_regnum)
2443b725ae77Skettenis {
2444b725ae77Skettenis   int first_fp_reg_num = sh64_compact_reg_base_num (fv_regnum);
2445b725ae77Skettenis   printf_filtered ("fv%d_c\t0x%08x\t0x%08x\t0x%08x\t0x%08x\n",
2446b725ae77Skettenis 		     fv_regnum - FV0_C_REGNUM,
2447b725ae77Skettenis 		     (int) read_register (first_fp_reg_num),
2448b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 1),
2449b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 2),
2450b725ae77Skettenis 		     (int) read_register (first_fp_reg_num + 3));
2451b725ae77Skettenis }
2452b725ae77Skettenis 
2453b725ae77Skettenis /* Pairs of single regs. The DR are instead double precision
2454b725ae77Skettenis    registers.  */
2455b725ae77Skettenis static void
do_fpp_register_info(int fpp_regnum)2456b725ae77Skettenis do_fpp_register_info (int fpp_regnum)
2457b725ae77Skettenis {
2458b725ae77Skettenis   int first_fp_reg_num = fpp_reg_base_num (fpp_regnum);
2459b725ae77Skettenis 
2460b725ae77Skettenis   printf_filtered ("fpp%d\t0x%08x\t0x%08x\n",
2461b725ae77Skettenis 		    fpp_regnum - FPP0_REGNUM,
2462b725ae77Skettenis 		    (int) read_register (first_fp_reg_num),
2463b725ae77Skettenis 		    (int) read_register (first_fp_reg_num + 1));
2464b725ae77Skettenis }
2465b725ae77Skettenis 
2466b725ae77Skettenis /* Double precision registers.  */
2467b725ae77Skettenis static void
do_dr_register_info(struct gdbarch * gdbarch,struct ui_file * file,int dr_regnum)2468b725ae77Skettenis do_dr_register_info (struct gdbarch *gdbarch, struct ui_file *file,
2469b725ae77Skettenis 		     int dr_regnum)
2470b725ae77Skettenis {
2471b725ae77Skettenis   int first_fp_reg_num = dr_reg_base_num (dr_regnum);
2472b725ae77Skettenis 
2473b725ae77Skettenis   fprintf_filtered (file, "dr%d\t0x%08x%08x\n",
2474b725ae77Skettenis 		    dr_regnum - DR0_REGNUM,
2475b725ae77Skettenis 		    (int) read_register (first_fp_reg_num),
2476b725ae77Skettenis 		    (int) read_register (first_fp_reg_num + 1));
2477b725ae77Skettenis }
2478b725ae77Skettenis 
2479b725ae77Skettenis /* Double precision registers, compact mode.  */
2480b725ae77Skettenis static void
do_dr_c_register_info(int dr_regnum)2481b725ae77Skettenis do_dr_c_register_info (int dr_regnum)
2482b725ae77Skettenis {
2483b725ae77Skettenis  int first_fp_reg_num = sh64_compact_reg_base_num (dr_regnum);
2484b725ae77Skettenis 
2485b725ae77Skettenis  printf_filtered ("dr%d_c\t0x%08x%08x\n",
2486b725ae77Skettenis 		  dr_regnum - DR0_C_REGNUM,
2487b725ae77Skettenis 		  (int) read_register (first_fp_reg_num),
2488b725ae77Skettenis 		  (int) read_register (first_fp_reg_num +1));
2489b725ae77Skettenis }
2490b725ae77Skettenis 
2491b725ae77Skettenis /* General register in compact mode.  */
2492b725ae77Skettenis static void
do_r_c_register_info(int r_c_regnum)2493b725ae77Skettenis do_r_c_register_info (int r_c_regnum)
2494b725ae77Skettenis {
2495b725ae77Skettenis   int regnum =  sh64_compact_reg_base_num (r_c_regnum);
2496b725ae77Skettenis 
2497b725ae77Skettenis   printf_filtered ("r%d_c\t0x%08x\n",
2498b725ae77Skettenis 		    r_c_regnum - R0_C_REGNUM,
2499b725ae77Skettenis 		   /*FIXME!!!*/  (int) read_register (regnum));
2500b725ae77Skettenis }
2501b725ae77Skettenis 
2502b725ae77Skettenis /* FIXME:!! THIS SHOULD TAKE CARE OF GETTING THE RIGHT PORTION OF THE
2503b725ae77Skettenis    shmedia REGISTERS.  */
2504b725ae77Skettenis /* Control registers, compact mode.  */
2505b725ae77Skettenis static void
do_cr_c_register_info(int cr_c_regnum)2506b725ae77Skettenis do_cr_c_register_info (int cr_c_regnum)
2507b725ae77Skettenis {
2508b725ae77Skettenis   switch (cr_c_regnum)
2509b725ae77Skettenis     {
2510b725ae77Skettenis     case 237: printf_filtered ("pc_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2511b725ae77Skettenis       break;
2512b725ae77Skettenis     case 238: printf_filtered ("gbr_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2513b725ae77Skettenis       break;
2514b725ae77Skettenis     case 239: printf_filtered ("mach_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2515b725ae77Skettenis       break;
2516b725ae77Skettenis     case 240: printf_filtered ("macl_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2517b725ae77Skettenis       break;
2518b725ae77Skettenis     case 241: printf_filtered ("pr_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2519b725ae77Skettenis       break;
2520b725ae77Skettenis     case 242: printf_filtered ("t_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2521b725ae77Skettenis       break;
2522b725ae77Skettenis     case 243: printf_filtered ("fpscr_c\t0x%08x\n", (int) read_register (cr_c_regnum));
2523b725ae77Skettenis       break;
2524b725ae77Skettenis     case 244: printf_filtered ("fpul_c\t0x%08x\n", (int)read_register (cr_c_regnum));
2525b725ae77Skettenis       break;
2526b725ae77Skettenis     }
2527b725ae77Skettenis }
2528b725ae77Skettenis 
2529b725ae77Skettenis static void
sh_do_fp_register(struct gdbarch * gdbarch,struct ui_file * file,int regnum)2530b725ae77Skettenis sh_do_fp_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
2531b725ae77Skettenis {				/* do values for FP (float) regs */
2532b725ae77Skettenis   char *raw_buffer;
2533b725ae77Skettenis   double flt;	/* double extracted from raw hex data */
2534b725ae77Skettenis   int inv;
2535b725ae77Skettenis   int j;
2536b725ae77Skettenis 
2537b725ae77Skettenis   /* Allocate space for the float.  */
2538b725ae77Skettenis   raw_buffer = (char *) alloca (register_size (gdbarch, FP0_REGNUM));
2539b725ae77Skettenis 
2540b725ae77Skettenis   /* Get the data in raw format.  */
2541b725ae77Skettenis   if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
2542b725ae77Skettenis     error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
2543b725ae77Skettenis 
2544b725ae77Skettenis   /* Get the register as a number */
2545b725ae77Skettenis   flt = unpack_double (builtin_type_float, raw_buffer, &inv);
2546b725ae77Skettenis 
2547b725ae77Skettenis   /* Print the name and some spaces.  */
2548b725ae77Skettenis   fputs_filtered (REGISTER_NAME (regnum), file);
2549b725ae77Skettenis   print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
2550b725ae77Skettenis 
2551b725ae77Skettenis   /* Print the value.  */
2552b725ae77Skettenis   if (inv)
2553b725ae77Skettenis     fprintf_filtered (file, "<invalid float>");
2554b725ae77Skettenis   else
2555b725ae77Skettenis     fprintf_filtered (file, "%-10.9g", flt);
2556b725ae77Skettenis 
2557b725ae77Skettenis   /* Print the fp register as hex.  */
2558b725ae77Skettenis   fprintf_filtered (file, "\t(raw 0x");
2559b725ae77Skettenis   for (j = 0; j < register_size (gdbarch, regnum); j++)
2560b725ae77Skettenis     {
2561b725ae77Skettenis       int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
2562b725ae77Skettenis 	: register_size (gdbarch, regnum) - 1 - j;
2563b725ae77Skettenis       fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]);
2564b725ae77Skettenis     }
2565b725ae77Skettenis   fprintf_filtered (file, ")");
2566b725ae77Skettenis   fprintf_filtered (file, "\n");
2567b725ae77Skettenis }
2568b725ae77Skettenis 
2569b725ae77Skettenis static void
sh64_do_pseudo_register(int regnum)2570b725ae77Skettenis sh64_do_pseudo_register (int regnum)
2571b725ae77Skettenis {
2572b725ae77Skettenis   /* All the sh64-compact mode registers are pseudo registers.  */
2573b725ae77Skettenis 
2574b725ae77Skettenis   if (regnum < NUM_REGS
2575b725ae77Skettenis       || regnum >= NUM_REGS + NUM_PSEUDO_REGS_SH_MEDIA + NUM_PSEUDO_REGS_SH_COMPACT)
2576b725ae77Skettenis     internal_error (__FILE__, __LINE__,
2577b725ae77Skettenis 		    "Invalid pseudo register number %d\n", regnum);
2578b725ae77Skettenis 
2579b725ae77Skettenis   else if ((regnum >= DR0_REGNUM
2580b725ae77Skettenis 	    && regnum <= DR_LAST_REGNUM))
2581b725ae77Skettenis     do_dr_register_info (current_gdbarch, gdb_stdout, regnum);
2582b725ae77Skettenis 
2583b725ae77Skettenis   else if ((regnum >= DR0_C_REGNUM
2584b725ae77Skettenis 	    && regnum <= DR_LAST_C_REGNUM))
2585b725ae77Skettenis     do_dr_c_register_info (regnum);
2586b725ae77Skettenis 
2587b725ae77Skettenis   else if ((regnum >= FV0_REGNUM
2588b725ae77Skettenis 	    && regnum <= FV_LAST_REGNUM))
2589b725ae77Skettenis     do_fv_register_info (current_gdbarch, gdb_stdout, regnum);
2590b725ae77Skettenis 
2591b725ae77Skettenis   else if ((regnum >= FV0_C_REGNUM
2592b725ae77Skettenis 	    && regnum <= FV_LAST_C_REGNUM))
2593b725ae77Skettenis     do_fv_c_register_info (regnum);
2594b725ae77Skettenis 
2595b725ae77Skettenis   else if (regnum >= FPP0_REGNUM
2596b725ae77Skettenis 	   && regnum <= FPP_LAST_REGNUM)
2597b725ae77Skettenis     do_fpp_register_info (regnum);
2598b725ae77Skettenis 
2599b725ae77Skettenis   else if (regnum >= R0_C_REGNUM
2600b725ae77Skettenis 	   && regnum <= R_LAST_C_REGNUM)
2601b725ae77Skettenis     /* FIXME, this function will not print the right format.  */
2602b725ae77Skettenis     do_r_c_register_info (regnum);
2603b725ae77Skettenis   else if (regnum >= FP0_C_REGNUM
2604b725ae77Skettenis 	   && regnum <= FP_LAST_C_REGNUM)
2605b725ae77Skettenis     /* This should work also for pseudoregs.  */
2606b725ae77Skettenis     sh_do_fp_register (current_gdbarch, gdb_stdout, regnum);
2607b725ae77Skettenis   else if (regnum >= PC_C_REGNUM
2608b725ae77Skettenis 	   && regnum <= FPUL_C_REGNUM)
2609b725ae77Skettenis     do_cr_c_register_info (regnum);
2610b725ae77Skettenis }
2611b725ae77Skettenis 
2612b725ae77Skettenis static void
sh_do_register(struct gdbarch * gdbarch,struct ui_file * file,int regnum)2613b725ae77Skettenis sh_do_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
2614b725ae77Skettenis {
2615b725ae77Skettenis   char raw_buffer[MAX_REGISTER_SIZE];
2616b725ae77Skettenis 
2617b725ae77Skettenis   fputs_filtered (REGISTER_NAME (regnum), file);
2618b725ae77Skettenis   print_spaces_filtered (15 - strlen (REGISTER_NAME (regnum)), file);
2619b725ae77Skettenis 
2620b725ae77Skettenis   /* Get the data in raw format.  */
2621b725ae77Skettenis   if (!frame_register_read (get_selected_frame (), regnum, raw_buffer))
2622b725ae77Skettenis     fprintf_filtered (file, "*value not available*\n");
2623b725ae77Skettenis 
2624b725ae77Skettenis   val_print (gdbarch_register_type (gdbarch, regnum), raw_buffer, 0, 0,
2625b725ae77Skettenis 	     file, 'x', 1, 0, Val_pretty_default);
2626b725ae77Skettenis   fprintf_filtered (file, "\t");
2627b725ae77Skettenis   val_print (gdbarch_register_type (gdbarch, regnum), raw_buffer, 0, 0,
2628b725ae77Skettenis 	     file, 0, 1, 0, Val_pretty_default);
2629b725ae77Skettenis   fprintf_filtered (file, "\n");
2630b725ae77Skettenis }
2631b725ae77Skettenis 
2632b725ae77Skettenis static void
sh_print_register(struct gdbarch * gdbarch,struct ui_file * file,int regnum)2633b725ae77Skettenis sh_print_register (struct gdbarch *gdbarch, struct ui_file *file, int regnum)
2634b725ae77Skettenis {
2635b725ae77Skettenis   if (regnum < 0 || regnum >= NUM_REGS + NUM_PSEUDO_REGS)
2636b725ae77Skettenis     internal_error (__FILE__, __LINE__,
2637b725ae77Skettenis 		    "Invalid register number %d\n", regnum);
2638b725ae77Skettenis 
2639b725ae77Skettenis   else if (regnum >= 0 && regnum < NUM_REGS)
2640b725ae77Skettenis     {
2641b725ae77Skettenis       if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
2642b725ae77Skettenis 	sh_do_fp_register (gdbarch, file, regnum);	/* FP regs */
2643b725ae77Skettenis       else
2644b725ae77Skettenis 	sh_do_register (gdbarch, file, regnum);	/* All other regs */
2645b725ae77Skettenis     }
2646b725ae77Skettenis 
2647b725ae77Skettenis   else if (regnum < NUM_REGS + NUM_PSEUDO_REGS)
2648b725ae77Skettenis     sh64_do_pseudo_register (regnum);
2649b725ae77Skettenis }
2650b725ae77Skettenis 
2651b725ae77Skettenis static void
sh_print_registers_info(struct gdbarch * gdbarch,struct ui_file * file,struct frame_info * frame,int regnum,int fpregs)2652b725ae77Skettenis sh_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
2653b725ae77Skettenis 			 struct frame_info *frame, int regnum, int fpregs)
2654b725ae77Skettenis {
2655b725ae77Skettenis   if (regnum != -1)		/* do one specified register */
2656b725ae77Skettenis     {
2657b725ae77Skettenis       if (*(REGISTER_NAME (regnum)) == '\0')
2658b725ae77Skettenis 	error ("Not a valid register for the current processor type");
2659b725ae77Skettenis 
2660b725ae77Skettenis       sh_print_register (gdbarch, file, regnum);
2661b725ae77Skettenis     }
2662b725ae77Skettenis   else
2663b725ae77Skettenis     /* do all (or most) registers */
2664b725ae77Skettenis     {
2665b725ae77Skettenis       regnum = 0;
2666b725ae77Skettenis       while (regnum < NUM_REGS)
2667b725ae77Skettenis 	{
2668b725ae77Skettenis 	  /* If the register name is empty, it is undefined for this
2669b725ae77Skettenis 	     processor, so don't display anything.  */
2670b725ae77Skettenis 	  if (REGISTER_NAME (regnum) == NULL
2671b725ae77Skettenis 	      || *(REGISTER_NAME (regnum)) == '\0')
2672b725ae77Skettenis 	    {
2673b725ae77Skettenis 	      regnum++;
2674b725ae77Skettenis 	      continue;
2675b725ae77Skettenis 	    }
2676b725ae77Skettenis 
2677b725ae77Skettenis 	  if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
2678b725ae77Skettenis 	    {
2679b725ae77Skettenis 	      if (fpregs)
2680b725ae77Skettenis 		{
2681b725ae77Skettenis 		  /* true for "INFO ALL-REGISTERS" command */
2682b725ae77Skettenis 		  sh_do_fp_register (gdbarch, file, regnum);	/* FP regs */
2683b725ae77Skettenis 		  regnum ++;
2684b725ae77Skettenis 		}
2685b725ae77Skettenis 	      else
2686b725ae77Skettenis 		regnum += FP_LAST_REGNUM - FP0_REGNUM;	/* skip FP regs */
2687b725ae77Skettenis 	    }
2688b725ae77Skettenis 	  else
2689b725ae77Skettenis 	    {
2690b725ae77Skettenis 	      sh_do_register (gdbarch, file, regnum);	/* All other regs */
2691b725ae77Skettenis 	      regnum++;
2692b725ae77Skettenis 	    }
2693b725ae77Skettenis 	}
2694b725ae77Skettenis 
2695b725ae77Skettenis       if (fpregs)
2696b725ae77Skettenis 	while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
2697b725ae77Skettenis 	  {
2698b725ae77Skettenis 	    sh64_do_pseudo_register (regnum);
2699b725ae77Skettenis 	    regnum++;
2700b725ae77Skettenis 	  }
2701b725ae77Skettenis     }
2702b725ae77Skettenis }
2703b725ae77Skettenis 
2704b725ae77Skettenis static void
sh_compact_do_registers_info(int regnum,int fpregs)2705b725ae77Skettenis sh_compact_do_registers_info (int regnum, int fpregs)
2706b725ae77Skettenis {
2707b725ae77Skettenis   if (regnum != -1)		/* do one specified register */
2708b725ae77Skettenis     {
2709b725ae77Skettenis       if (*(REGISTER_NAME (regnum)) == '\0')
2710b725ae77Skettenis 	error ("Not a valid register for the current processor type");
2711b725ae77Skettenis 
2712b725ae77Skettenis       if (regnum >= 0 && regnum < R0_C_REGNUM)
2713b725ae77Skettenis         error ("Not a valid register for the current processor mode.");
2714b725ae77Skettenis 
2715b725ae77Skettenis       sh_print_register (current_gdbarch, gdb_stdout, regnum);
2716b725ae77Skettenis     }
2717b725ae77Skettenis   else
2718b725ae77Skettenis     /* do all compact registers */
2719b725ae77Skettenis     {
2720b725ae77Skettenis       regnum = R0_C_REGNUM;
2721b725ae77Skettenis       while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
2722b725ae77Skettenis         {
2723b725ae77Skettenis           sh64_do_pseudo_register (regnum);
2724b725ae77Skettenis           regnum++;
2725b725ae77Skettenis         }
2726b725ae77Skettenis     }
2727b725ae77Skettenis }
2728b725ae77Skettenis 
2729b725ae77Skettenis static void
sh64_do_registers_info(int regnum,int fpregs)2730b725ae77Skettenis sh64_do_registers_info (int regnum, int fpregs)
2731b725ae77Skettenis {
2732b725ae77Skettenis   if (pc_is_isa32 (get_frame_pc (deprecated_selected_frame)))
2733b725ae77Skettenis    sh_print_registers_info (current_gdbarch, gdb_stdout,
2734b725ae77Skettenis 			    deprecated_selected_frame, regnum, fpregs);
2735b725ae77Skettenis   else
2736b725ae77Skettenis    sh_compact_do_registers_info (regnum, fpregs);
2737b725ae77Skettenis }
2738b725ae77Skettenis 
2739b725ae77Skettenis /* Fetch (and possibly build) an appropriate link_map_offsets structure
2740b725ae77Skettenis    for native i386 linux targets using the struct offsets defined in
2741b725ae77Skettenis    link.h (but without actual reference to that file).
2742b725ae77Skettenis 
2743b725ae77Skettenis    This makes it possible to access i386-linux shared libraries from
2744b725ae77Skettenis    a gdb that was not built on an i386-linux host (for cross debugging).
2745b725ae77Skettenis    */
2746b725ae77Skettenis 
2747b725ae77Skettenis struct link_map_offsets *
sh_linux_svr4_fetch_link_map_offsets(void)2748b725ae77Skettenis sh_linux_svr4_fetch_link_map_offsets (void)
2749b725ae77Skettenis {
2750b725ae77Skettenis   static struct link_map_offsets lmo;
2751b725ae77Skettenis   static struct link_map_offsets *lmp = 0;
2752b725ae77Skettenis 
2753b725ae77Skettenis   if (lmp == 0)
2754b725ae77Skettenis     {
2755b725ae77Skettenis       lmp = &lmo;
2756b725ae77Skettenis 
2757b725ae77Skettenis       lmo.r_debug_size = 8;	/* 20 not actual size but all we need */
2758b725ae77Skettenis 
2759b725ae77Skettenis       lmo.r_map_offset = 4;
2760b725ae77Skettenis       lmo.r_map_size   = 4;
2761b725ae77Skettenis 
2762b725ae77Skettenis       lmo.link_map_size = 20;	/* 552 not actual size but all we need */
2763b725ae77Skettenis 
2764b725ae77Skettenis       lmo.l_addr_offset = 0;
2765b725ae77Skettenis       lmo.l_addr_size   = 4;
2766b725ae77Skettenis 
2767b725ae77Skettenis       lmo.l_name_offset = 4;
2768b725ae77Skettenis       lmo.l_name_size   = 4;
2769b725ae77Skettenis 
2770b725ae77Skettenis       lmo.l_next_offset = 12;
2771b725ae77Skettenis       lmo.l_next_size   = 4;
2772b725ae77Skettenis 
2773b725ae77Skettenis       lmo.l_prev_offset = 16;
2774b725ae77Skettenis       lmo.l_prev_size   = 4;
2775b725ae77Skettenis     }
2776b725ae77Skettenis 
2777b725ae77Skettenis     return lmp;
2778b725ae77Skettenis }
2779b725ae77Skettenis 
2780b725ae77Skettenis gdbarch_init_ftype sh64_gdbarch_init;
2781b725ae77Skettenis 
2782b725ae77Skettenis struct gdbarch *
sh64_gdbarch_init(struct gdbarch_info info,struct gdbarch_list * arches)2783b725ae77Skettenis sh64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
2784b725ae77Skettenis {
2785b725ae77Skettenis   struct gdbarch *gdbarch;
2786b725ae77Skettenis   struct gdbarch_tdep *tdep;
2787b725ae77Skettenis 
2788b725ae77Skettenis   /* If there is already a candidate, use it.  */
2789b725ae77Skettenis   arches = gdbarch_list_lookup_by_info (arches, &info);
2790b725ae77Skettenis   if (arches != NULL)
2791b725ae77Skettenis     return arches->gdbarch;
2792b725ae77Skettenis 
2793b725ae77Skettenis   /* None found, create a new architecture from the information
2794b725ae77Skettenis      provided.  */
2795b725ae77Skettenis   tdep = XMALLOC (struct gdbarch_tdep);
2796b725ae77Skettenis   gdbarch = gdbarch_alloc (&info, tdep);
2797b725ae77Skettenis 
2798b725ae77Skettenis   /* NOTE: cagney/2002-12-06: This can be deleted when this arch is
2799b725ae77Skettenis      ready to unwind the PC first (see frame.c:get_prev_frame()).  */
2800b725ae77Skettenis   set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
2801b725ae77Skettenis 
2802b725ae77Skettenis   /* Determine the ABI */
2803b725ae77Skettenis   if (info.abfd && bfd_get_arch_size (info.abfd) == 64)
2804b725ae77Skettenis     {
2805b725ae77Skettenis       /* If the ABI is the 64-bit one, it can only be sh-media.  */
2806b725ae77Skettenis       tdep->sh_abi = SH_ABI_64;
2807b725ae77Skettenis       set_gdbarch_ptr_bit (gdbarch, 8 * TARGET_CHAR_BIT);
2808b725ae77Skettenis       set_gdbarch_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
2809b725ae77Skettenis     }
2810b725ae77Skettenis   else
2811b725ae77Skettenis     {
2812b725ae77Skettenis       /* If the ABI is the 32-bit one it could be either media or
2813b725ae77Skettenis 	 compact.  */
2814b725ae77Skettenis       tdep->sh_abi = SH_ABI_32;
2815b725ae77Skettenis       set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
2816b725ae77Skettenis       set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
2817b725ae77Skettenis     }
2818b725ae77Skettenis 
2819b725ae77Skettenis   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
2820b725ae77Skettenis   set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
2821b725ae77Skettenis   set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
2822b725ae77Skettenis   set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
2823b725ae77Skettenis   set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
2824b725ae77Skettenis   set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
2825b725ae77Skettenis 
2826b725ae77Skettenis   set_gdbarch_sp_regnum (gdbarch, 15);
2827b725ae77Skettenis   set_gdbarch_deprecated_fp_regnum (gdbarch, 14);
2828b725ae77Skettenis 
2829b725ae77Skettenis   set_gdbarch_print_insn (gdbarch, gdb_print_insn_sh);
2830b725ae77Skettenis   set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
2831b725ae77Skettenis 
2832b725ae77Skettenis   set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
2833b725ae77Skettenis 
2834b725ae77Skettenis   set_gdbarch_skip_prologue (gdbarch, sh_skip_prologue);
2835b725ae77Skettenis   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
2836b725ae77Skettenis 
2837b725ae77Skettenis   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
2838b725ae77Skettenis 
2839b725ae77Skettenis   set_gdbarch_deprecated_frame_saved_pc (gdbarch, sh_frame_saved_pc);
2840b725ae77Skettenis   set_gdbarch_deprecated_saved_pc_after_call (gdbarch, sh_saved_pc_after_call);
2841b725ae77Skettenis   set_gdbarch_frame_align (gdbarch, sh_frame_align);
2842b725ae77Skettenis 
2843b725ae77Skettenis   set_gdbarch_num_pseudo_regs (gdbarch, NUM_PSEUDO_REGS_SH_MEDIA + NUM_PSEUDO_REGS_SH_COMPACT);
2844b725ae77Skettenis   set_gdbarch_fp0_regnum (gdbarch, SIM_SH64_FR0_REGNUM);
2845b725ae77Skettenis   set_gdbarch_pc_regnum (gdbarch, 64);
2846b725ae77Skettenis 
2847b725ae77Skettenis   /* The number of real registers is the same whether we are in
2848b725ae77Skettenis      ISA16(compact) or ISA32(media).  */
2849b725ae77Skettenis   set_gdbarch_num_regs (gdbarch, SIM_SH64_NR_REGS);
2850b725ae77Skettenis 
2851b725ae77Skettenis   set_gdbarch_register_name (gdbarch, sh64_register_name);
2852b725ae77Skettenis   set_gdbarch_register_type (gdbarch, sh64_register_type);
2853b725ae77Skettenis   set_gdbarch_deprecated_store_return_value (gdbarch, sh64_store_return_value);
2854b725ae77Skettenis   set_gdbarch_deprecated_register_byte (gdbarch, sh64_register_byte);
2855b725ae77Skettenis   set_gdbarch_pseudo_register_read (gdbarch, sh64_pseudo_register_read);
2856b725ae77Skettenis   set_gdbarch_pseudo_register_write (gdbarch, sh64_pseudo_register_write);
2857b725ae77Skettenis 
2858b725ae77Skettenis   set_gdbarch_deprecated_do_registers_info (gdbarch, sh64_do_registers_info);
2859b725ae77Skettenis   set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh64_nofp_frame_init_saved_regs);
2860b725ae77Skettenis   set_gdbarch_breakpoint_from_pc (gdbarch, sh64_breakpoint_from_pc);
2861b725ae77Skettenis 
2862b725ae77Skettenis   set_gdbarch_deprecated_init_extra_frame_info (gdbarch, sh64_init_extra_frame_info);
2863b725ae77Skettenis   set_gdbarch_deprecated_frame_chain (gdbarch, sh64_frame_chain);
2864b725ae77Skettenis   set_gdbarch_deprecated_get_saved_register (gdbarch, sh64_get_saved_register);
2865b725ae77Skettenis   set_gdbarch_deprecated_extract_return_value (gdbarch, sh64_extract_return_value);
2866b725ae77Skettenis   set_gdbarch_deprecated_push_arguments (gdbarch, sh64_push_arguments);
2867b725ae77Skettenis   set_gdbarch_deprecated_push_return_address (gdbarch, sh64_push_return_address);
2868b725ae77Skettenis   set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_write_sp);
2869b725ae77Skettenis   set_gdbarch_deprecated_store_struct_return (gdbarch, sh64_store_struct_return);
2870b725ae77Skettenis   set_gdbarch_deprecated_extract_struct_value_address (gdbarch, sh64_extract_struct_value_address);
2871*11efff7fSkettenis   set_gdbarch_deprecated_use_struct_convention (gdbarch, sh64_use_struct_convention);
2872b725ae77Skettenis   set_gdbarch_deprecated_pop_frame (gdbarch, sh64_pop_frame);
2873b725ae77Skettenis   set_gdbarch_elf_make_msymbol_special (gdbarch,
2874b725ae77Skettenis 					sh64_elf_make_msymbol_special);
2875b725ae77Skettenis 
2876b725ae77Skettenis   /* Hook in ABI-specific overrides, if they have been registered.  */
2877b725ae77Skettenis   gdbarch_init_osabi (info, gdbarch);
2878b725ae77Skettenis 
2879b725ae77Skettenis   return gdbarch;
2880b725ae77Skettenis }
2881