1 /* Target dependent code for GDB on TI C6x systems.
3 Copyright (C) 2010, 2011
4 Free Software Foundation, Inc.
5 Contributed by Andrew Jenner <andrew@codesourcery.com>
6 Contributed by Yao Qi <yao@codesourcery.com>
8 This file is part of GDB.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 #include "linux-low.h"
26 #include <sys/ptrace.h>
29 #include "gdb_proc_service.h"
31 #ifndef PTRACE_GET_THREAD_AREA
32 #define PTRACE_GET_THREAD_AREA 25
35 /* There are at most 69 registers accessible in ptrace. */
36 #define TIC6X_NUM_REGS 69
38 #include <asm/ptrace.h>
40 /* Defined in auto-generated file tic6x-c64xp-linux.c. */
41 void init_registers_tic6x_c64xp_linux (void);
42 /* Defined in auto-generated file tic6x-c64x-linux.c. */
43 void init_registers_tic6x_c64x_linux (void);
44 /* Defined in auto-generated file tic62x-c6xp-linux.c. */
45 void init_registers_tic6x_c62x_linux (void);
54 /* Return the ptrace ``address'' of register REGNO. */
56 #if __BYTE_ORDER == __BIG_ENDIAN
57 static int tic6x_regmap_c64xp
[] = {
59 53, 52, 55, 54, 57, 56, 59, 58,
60 61, 60, 63, 62, 65, 64, 67, 66,
62 23, 22, 25, 24, 27, 26, 29, 28,
63 31, 30, 33, 32, 35, 34, 69, 68,
67 37, 36, 39, 38, 41, 40, 43, 42,
68 45, 44, 47, 46, 49, 48, 51, 50,
70 7, 6, 9, 8, 11, 10, 13, 12,
71 15, 14, 17, 16, 19, 18, 21, 20,
76 static int tic6x_regmap_c64x
[] = {
78 51, 50, 53, 52, 55, 54, 57, 56,
79 59, 58, 61, 60, 63, 62, 65, 64,
81 21, 20, 23, 22, 25, 24, 27, 26,
82 29, 28, 31, 30, 33, 32, 67, 66,
86 35, 34, 37, 36, 39, 38, 41, 40,
87 43, 42, 45, 44, 47, 46, 49, 48,
89 5, 4, 7, 6, 9, 8, 11, 10,
90 13, 12, 15, 14, 17, 16, 19, 18,
94 static int tic6x_regmap_c62x
[] = {
96 19, 18, 21, 20, 23, 22, 25, 24,
97 27, 26, 29, 28, 31, 30, 33, 32,
99 5, 4, 7, 6, 9, 8, 11, 10,
100 13, 12, 15, 14, 17, 16, 35, 34,
103 -1, -1, -1, -1, -1, -1, -1, -1,
104 -1, -1, -1, -1, -1, -1, -1, -1,
105 -1, -1, -1, -1, -1, -1, -1, -1,
106 -1, -1, -1, -1, -1, -1, -1, -1,
111 static int tic6x_regmap_c64xp
[] = {
113 52, 53, 54, 55, 56, 57, 58, 59,
114 60, 61, 62, 63, 64, 65, 66, 67,
116 22, 23, 24, 25, 26, 27, 28, 29,
117 30, 31, 32, 33, 34, 35, 68, 69,
121 36, 37, 38, 39, 40, 41, 42, 43,
122 44, 45, 46, 47, 48, 49, 50, 51,
124 6, 7, 8, 9, 10, 11, 12, 13,
125 14, 15, 16, 17, 18, 19, 20, 31,
130 static int tic6x_regmap_c64x
[] = {
132 50, 51, 52, 53, 54, 55, 56, 57,
133 58, 59, 60, 61, 62, 63, 64, 65,
135 20, 21, 22, 23, 24, 25, 26, 27,
136 28, 29, 30, 31, 32, 33, 66, 67,
140 34, 35, 36, 37, 38, 39, 40, 41,
141 42, 43, 44, 45, 46, 47, 48, 49,
143 4, 5, 6, 7, 8, 9, 10, 11,
144 12, 13, 14, 15, 16, 17, 18, 19,
148 static int tic6x_regmap_c62x
[] = {
150 18, 19, 20, 21, 22, 23, 24, 25,
151 26, 27, 28, 29, 30, 31, 32, 33,
153 4, 5, 6, 7, 8, 9, 10, 11,
154 12, 13, 14, 15, 16, 17, 34, 35,
157 -1, -1, -1, -1, -1, -1, -1, -1,
158 -1, -1, -1, -1, -1, -1, -1, -1,
159 -1, -1, -1, -1, -1, -1, -1, -1,
160 -1, -1, -1, -1, -1, -1, -1, -1,
166 extern struct linux_target_ops the_low_target
;
168 static int *tic6x_regmap
;
169 static unsigned int tic6x_breakpoint
;
172 tic6x_arch_setup (void)
174 register unsigned int csr
asm ("B2");
177 /* Determine the CPU we're running on to find the register order. */
178 __asm__ ("MVC .S2 CSR,%0" : "=r" (csr
) :);
182 case 0x00: /* C62x */
183 case 0x02: /* C67x */
184 tic6x_regmap
= tic6x_regmap_c62x
;
185 tic6x_breakpoint
= 0x0000a122; /* BNOP .S2 0,5 */
186 init_registers_tic6x_c62x_linux ();
188 case 0x03: /* C67x+ */
189 tic6x_regmap
= tic6x_regmap_c64x
;
190 tic6x_breakpoint
= 0x0000a122; /* BNOP .S2 0,5 */
191 init_registers_tic6x_c64x_linux ();
193 case 0x0c: /* C64x */
194 tic6x_regmap
= tic6x_regmap_c64x
;
195 tic6x_breakpoint
= 0x0000a122; /* BNOP .S2 0,5 */
196 init_registers_tic6x_c64x_linux ();
198 case 0x10: /* C64x+ */
199 case 0x14: /* C674x */
200 case 0x15: /* C66x */
201 tic6x_regmap
= tic6x_regmap_c64xp
;
202 tic6x_breakpoint
= 0x56454314; /* illegal opcode */
203 init_registers_tic6x_c64xp_linux ();
206 error ("Unknown CPU ID 0x%02x", cpuid
);
208 the_low_target
.regmap
= tic6x_regmap
;
212 tic6x_cannot_fetch_register (int regno
)
214 return (tic6x_regmap
[regno
] == -1);
218 tic6x_cannot_store_register (int regno
)
220 return (tic6x_regmap
[regno
] == -1);
224 tic6x_get_pc (struct regcache
*regcache
)
226 union tic6x_register pc
;
228 collect_register_by_name (regcache
, "PC", pc
.buf
);
233 tic6x_set_pc (struct regcache
*regcache
, CORE_ADDR pc
)
235 union tic6x_register newpc
;
238 supply_register_by_name (regcache
, "PC", newpc
.buf
);
241 #define tic6x_breakpoint_len 4
244 tic6x_breakpoint_at (CORE_ADDR where
)
248 (*the_target
->read_memory
) (where
, (unsigned char *) &insn
, 4);
249 if (insn
== tic6x_breakpoint
)
252 /* If necessary, recognize more trap instructions here. GDB only uses the
257 /* Fetch the thread-local storage pointer for libthread_db. */
260 ps_get_thread_area (const struct ps_prochandle
*ph
,
261 lwpid_t lwpid
, int idx
, void **base
)
263 if (ptrace (PTRACE_GET_THREAD_AREA
, lwpid
, NULL
, base
) != 0)
266 /* IDX is the bias from the thread pointer to the beginning of the
267 thread descriptor. It has to be subtracted due to implementation
268 quirks in libthread_db. */
269 *base
= (void *) ((char *) *base
- idx
);
275 tic6x_collect_register (struct regcache
*regcache
, int regno
,
276 union tic6x_register
*reg
)
278 union tic6x_register tmp_reg
;
280 collect_register (regcache
, regno
, &tmp_reg
.reg32
);
281 reg
->reg32
= tmp_reg
.reg32
;
285 tic6x_supply_register (struct regcache
*regcache
, int regno
,
286 const union tic6x_register
*reg
)
290 supply_register (regcache
, regno
, reg
->buf
+ offset
);
294 tic6x_fill_gregset (struct regcache
*regcache
, void *buf
)
296 union tic6x_register
*regset
= buf
;
299 for (i
= 0; i
< TIC6X_NUM_REGS
; i
++)
300 if (tic6x_regmap
[i
] != -1)
301 tic6x_collect_register (regcache
, i
, regset
+ tic6x_regmap
[i
]);
305 tic6x_store_gregset (struct regcache
*regcache
, const void *buf
)
307 const union tic6x_register
*regset
= buf
;
310 for (i
= 0; i
< TIC6X_NUM_REGS
; i
++)
311 if (tic6x_regmap
[i
] != -1)
312 tic6x_supply_register (regcache
, i
, regset
+ tic6x_regmap
[i
]);
315 struct regset_info target_regsets
[] = {
316 { PTRACE_GETREGS
, PTRACE_SETREGS
, 0, TIC6X_NUM_REGS
* 4, GENERAL_REGS
,
317 tic6x_fill_gregset
, tic6x_store_gregset
},
318 { 0, 0, 0, -1, -1, NULL
, NULL
}
321 struct linux_target_ops the_low_target
= {
325 tic6x_cannot_fetch_register
,
326 tic6x_cannot_store_register
,
329 (const unsigned char *) &tic6x_breakpoint
,
330 tic6x_breakpoint_len
,