Commit | Line | Data |
---|---|---|
abeeff98 LM |
1 | /* Target-dependent code for the ROCm amdgcn architecture. |
2 | ||
ca9af5a1 LM |
3 | Copyright (C) 2019-2020 Free Software Foundation, Inc. |
4 | Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved. | |
abeeff98 LM |
5 | |
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "defs.h" | |
22 | ||
23 | #include "amdgcn-rocm-tdep.h" | |
24 | #include "arch-utils.h" | |
25 | #include "dwarf2-frame.h" | |
26 | #include "frame-base.h" | |
27 | #include "frame-unwind.h" | |
28 | #include "gdbarch.h" | |
29 | #include "inferior.h" | |
30 | #include "osabi.h" | |
31 | #include "reggroups.h" | |
32 | #include "rocm-tdep.h" | |
33 | ||
34 | bool | |
35 | rocm_is_amdgcn_gdbarch (struct gdbarch *arch) | |
36 | { | |
37 | return (gdbarch_bfd_arch_info (arch)->arch == bfd_arch_amdgcn); | |
38 | } | |
39 | ||
40 | /* Return the name of register REGNUM. */ | |
41 | static const char * | |
42 | amdgcn_register_name (struct gdbarch *gdbarch, int regnum) | |
43 | { | |
44 | amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (); | |
45 | amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid); | |
46 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
47 | ||
48 | amd_dbgapi_size_t unused; | |
49 | if (amd_dbgapi_wave_register_get_info ( | |
50 | process_id, wave_id, tdep->register_ids[regnum], | |
51 | AMD_DBGAPI_REGISTER_INFO_SIZE, sizeof (unused), &unused) | |
52 | != AMD_DBGAPI_STATUS_SUCCESS) | |
53 | return ""; | |
54 | ||
55 | return tdep->register_names[regnum].c_str (); | |
56 | } | |
57 | ||
58 | static int | |
59 | amdgcn_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) | |
60 | { | |
61 | amd_dbgapi_architecture_id_t architecture_id; | |
62 | amd_dbgapi_register_id_t register_id; | |
63 | ||
64 | if (amd_dbgapi_get_architecture (gdbarch_bfd_arch_info (gdbarch)->mach, | |
65 | &architecture_id) | |
66 | != AMD_DBGAPI_STATUS_SUCCESS) | |
67 | return -1; | |
68 | ||
69 | if (amd_dbgapi_dwarf_register_to_register (architecture_id, reg, | |
70 | ®ister_id) | |
71 | != AMD_DBGAPI_STATUS_SUCCESS) | |
72 | return -1; | |
73 | ||
74 | return gdbarch_tdep (gdbarch)->regnum_map[register_id]; | |
75 | } | |
76 | ||
77 | static struct type * | |
78 | gdb_type_from_type_name (struct gdbarch *gdbarch, const std::string &type_name) | |
79 | { | |
80 | size_t pos; | |
81 | ||
82 | /* vector types. */ | |
83 | if ((pos = type_name.find_last_of ('[')) != std::string::npos) | |
84 | { | |
85 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
86 | ||
87 | auto it = tdep->vector_type_map.find (type_name); | |
88 | if (it != tdep->vector_type_map.end ()) | |
89 | return it->second; | |
90 | ||
91 | struct type *vector_type = init_vector_type ( | |
92 | gdb_type_from_type_name (gdbarch, type_name.substr (0, pos)), | |
93 | std::stoi (type_name.substr (pos + 1))); | |
94 | ||
2bcf29f7 LM |
95 | TYPE_NAME (vector_type) |
96 | = tdep->vector_type_map.emplace (type_name, vector_type) | |
97 | .first->first.c_str (); | |
98 | ||
abeeff98 LM |
99 | return vector_type; |
100 | } | |
101 | /* scalar types. */ | |
102 | else if (type_name == "int32_t") | |
103 | return builtin_type (gdbarch)->builtin_int32; | |
104 | else if (type_name == "uint32_t") | |
105 | return builtin_type (gdbarch)->builtin_uint32; | |
106 | else if (type_name == "int64_t") | |
107 | return builtin_type (gdbarch)->builtin_int64; | |
108 | else if (type_name == "uint64_t") | |
109 | return builtin_type (gdbarch)->builtin_uint64; | |
110 | else if (type_name == "float") | |
111 | return builtin_type (gdbarch)->builtin_float; | |
112 | else if (type_name == "double") | |
113 | return builtin_type (gdbarch)->builtin_double; | |
114 | else if (type_name == "void (*)()") | |
115 | return builtin_type (gdbarch)->builtin_func_ptr; | |
116 | ||
117 | return builtin_type (gdbarch)->builtin_void; | |
118 | } | |
119 | ||
120 | static struct type * | |
121 | amdgcn_register_type (struct gdbarch *gdbarch, int regnum) | |
122 | { | |
123 | amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (); | |
124 | amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid); | |
125 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
126 | ||
127 | char *bytes; | |
128 | if (amd_dbgapi_wave_register_get_info ( | |
129 | process_id, wave_id, tdep->register_ids[regnum], | |
130 | AMD_DBGAPI_REGISTER_INFO_TYPE, sizeof (bytes), &bytes) | |
131 | == AMD_DBGAPI_STATUS_SUCCESS) | |
132 | { | |
133 | std::string type_name (bytes); | |
134 | xfree (bytes); | |
135 | ||
136 | return gdb_type_from_type_name (gdbarch, type_name); | |
137 | } | |
138 | ||
139 | return builtin_type (gdbarch)->builtin_void; | |
140 | } | |
141 | ||
142 | static int | |
143 | amdgcn_register_reggroup_p (struct gdbarch *gdbarch, int regnum, | |
144 | struct reggroup *group) | |
145 | { | |
146 | struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | |
147 | const char *name = reggroup_name (group); | |
148 | ||
149 | auto it = tdep->register_class_map.find (name); | |
150 | if (it == tdep->register_class_map.end ()) | |
151 | return group == all_reggroup; | |
152 | ||
153 | amd_dbgapi_architecture_id_t architecture_id; | |
154 | ||
155 | if (amd_dbgapi_get_architecture (gdbarch_bfd_arch_info (gdbarch)->mach, | |
156 | &architecture_id) | |
157 | != AMD_DBGAPI_STATUS_SUCCESS) | |
158 | return group == all_reggroup; | |
159 | ||
160 | amd_dbgapi_register_class_state_t state; | |
161 | ||
162 | if (amd_dbgapi_register_is_in_register_class ( | |
163 | architecture_id, tdep->register_ids[regnum], it->second, &state) | |
164 | != AMD_DBGAPI_STATUS_SUCCESS) | |
165 | return group == all_reggroup; | |
166 | ||
167 | return state == AMD_DBGAPI_REGISTER_CLASS_STATE_MEMBER | |
168 | || group == all_reggroup; | |
169 | } | |
170 | ||
171 | static int | |
172 | amdgcn_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *) | |
173 | { | |
174 | return gdbarch_tdep (gdbarch)->breakpoint_instruction_size; | |
175 | } | |
176 | ||
177 | static const gdb_byte * | |
178 | amdgcn_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) | |
179 | { | |
180 | *size = kind; | |
181 | return gdbarch_tdep (gdbarch)->breakpoint_instruction_bytes.get (); | |
182 | } | |
183 | ||
184 | struct amdgcn_frame_cache | |
185 | { | |
186 | CORE_ADDR base; | |
187 | CORE_ADDR pc; | |
188 | }; | |
189 | ||
190 | static struct amdgcn_frame_cache * | |
191 | amdgcn_frame_cache (struct frame_info *this_frame, void **this_cache) | |
192 | { | |
193 | if (*this_cache) | |
194 | return (struct amdgcn_frame_cache *)*this_cache; | |
195 | ||
196 | struct amdgcn_frame_cache *cache | |
197 | = FRAME_OBSTACK_ZALLOC (struct amdgcn_frame_cache); | |
198 | (*this_cache) = cache; | |
199 | ||
200 | cache->pc = get_frame_func (this_frame); | |
201 | cache->base = 0; | |
202 | ||
203 | return cache; | |
204 | } | |
205 | ||
206 | static void | |
207 | amdgcn_frame_this_id (struct frame_info *this_frame, void **this_cache, | |
208 | struct frame_id *this_id) | |
209 | { | |
210 | struct amdgcn_frame_cache *cache | |
211 | = amdgcn_frame_cache (this_frame, this_cache); | |
212 | ||
213 | if (get_frame_type (this_frame) == INLINE_FRAME) | |
214 | (*this_id) = frame_id_build (cache->base, cache->pc); | |
215 | else | |
216 | (*this_id) = outer_frame_id; | |
217 | ||
218 | if (frame_debug) | |
219 | { | |
220 | fprintf_unfiltered ( | |
221 | gdb_stdlog, "{ amdgcn_frame_this_id (this_frame=%d) type=%d -> ", | |
222 | frame_relative_level (this_frame), get_frame_type (this_frame)); | |
223 | fprint_frame_id (gdb_stdlog, *this_id); | |
224 | fprintf_unfiltered (gdb_stdlog, "}\n"); | |
225 | } | |
226 | ||
227 | return; | |
228 | } | |
229 | ||
230 | static struct frame_id | |
231 | amdgcn_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) | |
232 | { | |
233 | return frame_id_build (0, get_frame_pc (this_frame)); | |
234 | } | |
235 | ||
236 | static struct value * | |
237 | amdgcn_frame_prev_register (struct frame_info *this_frame, void **this_cache, | |
238 | int regnum) | |
239 | { | |
240 | return frame_unwind_got_register (this_frame, regnum, regnum); | |
241 | } | |
242 | ||
243 | static const struct frame_unwind amdgcn_frame_unwind = { | |
244 | NORMAL_FRAME, | |
245 | default_frame_unwind_stop_reason, | |
246 | amdgcn_frame_this_id, | |
247 | amdgcn_frame_prev_register, | |
248 | NULL, | |
249 | default_frame_sniffer, | |
250 | NULL, | |
251 | NULL, | |
252 | }; | |
253 | ||
254 | struct rocm_displaced_step_closure : public displaced_step_closure | |
255 | { | |
256 | amd_dbgapi_process_id_t process_id; | |
257 | amd_dbgapi_wave_id_t wave_id; | |
258 | amd_dbgapi_displaced_stepping_id_t displaced_stepping_id; | |
259 | }; | |
260 | ||
261 | static CORE_ADDR | |
262 | amdgcn_rocm_displaced_step_location (struct gdbarch *gdbarch) | |
263 | { | |
264 | size_t size = gdbarch_tdep (gdbarch)->breakpoint_instruction_size; | |
265 | gdb::unique_xmalloc_ptr<gdb_byte> buffer ( | |
266 | static_cast<gdb_byte *> (xmalloc (size))); | |
267 | ||
268 | /* Read the bytes that were overwritten by the breakpoint instruction. */ | |
269 | if (target_read_memory (regcache_read_pc (get_current_regcache ()), | |
270 | buffer.get (), size)) | |
271 | return 0; | |
272 | ||
273 | amd_dbgapi_displaced_stepping_id_t stepping_id; | |
274 | if (amd_dbgapi_displaced_stepping_start ( | |
275 | get_amd_dbgapi_process_id (), get_amd_dbgapi_wave_id (inferior_ptid), | |
276 | buffer.get (), &stepping_id) | |
277 | != AMD_DBGAPI_STATUS_SUCCESS) | |
278 | return 0; | |
279 | ||
280 | return stepping_id.handle; | |
281 | } | |
282 | ||
283 | static struct displaced_step_closure * | |
284 | amdgcn_rocm_displaced_step_copy_insn (struct gdbarch *gdbarch, CORE_ADDR from, | |
285 | CORE_ADDR to, struct regcache *regcache) | |
286 | { | |
287 | rocm_displaced_step_closure *closure = new rocm_displaced_step_closure; | |
288 | ||
289 | closure->process_id = get_amd_dbgapi_process_id (); | |
290 | closure->wave_id = get_amd_dbgapi_wave_id (inferior_ptid); | |
291 | closure->displaced_stepping_id = { to }; | |
292 | ||
293 | return closure; | |
294 | } | |
295 | ||
296 | static void | |
297 | amdgcn_rocm_displaced_step_fixup (struct gdbarch *gdbarch, | |
298 | struct displaced_step_closure *closure_, | |
299 | CORE_ADDR from, CORE_ADDR to, | |
300 | struct regcache *regcache) | |
301 | { | |
302 | rocm_displaced_step_closure *closure | |
303 | = reinterpret_cast<rocm_displaced_step_closure *> (closure_); | |
304 | ||
305 | amd_dbgapi_status_t status = amd_dbgapi_displaced_stepping_complete ( | |
306 | closure->process_id, closure->wave_id, closure->displaced_stepping_id); | |
307 | ||
308 | if (status != AMD_DBGAPI_STATUS_SUCCESS) | |
45f0bbf1 LM |
309 | error (_ ("amd_dbgapi_displaced_stepping_complete failed (rc=%d)"), |
310 | status); | |
abeeff98 LM |
311 | |
312 | /* We may have written some registers, so flush the register cache. */ | |
313 | registers_changed_ptid (regcache->ptid ()); | |
314 | } | |
315 | ||
316 | static int | |
317 | print_insn_amdgcn (bfd_vma memaddr, struct disassemble_info *di) | |
318 | { | |
319 | gdb_disassembler *self | |
320 | = static_cast<gdb_disassembler *> (di->application_data); | |
321 | ||
322 | /* Try to read at most instruction_size bytes. */ | |
323 | ||
324 | amd_dbgapi_size_t instruction_size = gdbarch_max_insn_length (self->arch ()); | |
325 | gdb::unique_xmalloc_ptr<gdb_byte> buffer ( | |
326 | (gdb_byte *)xmalloc (instruction_size)); | |
327 | ||
328 | instruction_size | |
45f0bbf1 | 329 | = target_read (current_top_target (), TARGET_OBJECT_CODE_MEMORY, NULL, |
abeeff98 | 330 | buffer.get (), memaddr, instruction_size); |
45f0bbf1 | 331 | if (instruction_size == TARGET_XFER_E_IO || instruction_size == 0) |
abeeff98 LM |
332 | { |
333 | (*di->memory_error_func) (-1, memaddr, di); | |
334 | return -1; | |
335 | } | |
336 | ||
337 | amd_dbgapi_architecture_id_t architecture_id; | |
338 | if (amd_dbgapi_get_architecture (gdbarch_bfd_arch_info (self->arch ())->mach, | |
339 | &architecture_id) | |
340 | != AMD_DBGAPI_STATUS_SUCCESS) | |
341 | return -1; | |
342 | ||
343 | char *instruction_text = nullptr; | |
79803eff LM |
344 | |
345 | auto symbolizer | |
346 | = [] (amd_dbgapi_symbolizer_id_t id, amd_dbgapi_global_address_t address, | |
347 | char **symbol_text) -> amd_dbgapi_status_t { | |
348 | string_file string; | |
349 | print_address (reinterpret_cast<struct gdbarch *> (id), address, &string); | |
350 | *symbol_text = xstrdup (string.c_str ()); | |
351 | return AMD_DBGAPI_STATUS_SUCCESS; | |
352 | }; | |
abeeff98 LM |
353 | |
354 | if (amd_dbgapi_disassemble_instruction ( | |
355 | architecture_id, static_cast<amd_dbgapi_global_address_t> (memaddr), | |
79803eff LM |
356 | &instruction_size, buffer.get (), &instruction_text, |
357 | reinterpret_cast<amd_dbgapi_symbolizer_id_t> (self->arch ()), | |
358 | symbolizer) | |
abeeff98 LM |
359 | != AMD_DBGAPI_STATUS_SUCCESS) |
360 | { | |
361 | size_t alignment; | |
362 | if (amd_dbgapi_architecture_get_info ( | |
363 | architecture_id, | |
364 | AMD_DBGAPI_ARCHITECTURE_INFO_MINIMUM_INSTRUCTION_ALIGNMENT, | |
365 | sizeof (alignment), &alignment) | |
366 | != AMD_DBGAPI_STATUS_SUCCESS) | |
367 | error (_ ("amd_dbgapi_architecture_get_info failed")); | |
368 | ||
369 | (*di->fprintf_func) (di->stream, "<illegal instruction>"); | |
370 | /* Skip to the next valid instruction address. */ | |
371 | return align_up (memaddr + 1, alignment) - memaddr; | |
372 | } | |
373 | ||
374 | /* Print the instruction. */ | |
375 | (*di->fprintf_func) (di->stream, "%s", instruction_text); | |
376 | ||
abeeff98 LM |
377 | /* Free the memory allocated by the amd-dbgapi. */ |
378 | xfree (instruction_text); | |
abeeff98 LM |
379 | |
380 | return static_cast<int> (instruction_size); | |
381 | } | |
382 | ||
383 | static CORE_ADDR | |
384 | amdgcn_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) | |
385 | { | |
386 | CORE_ADDR func_addr; | |
387 | ||
388 | /* See if we can determine the end of the prologue via the symbol table. | |
389 | If so, then return either PC, or the PC after the prologue, whichever | |
390 | is greater. */ | |
391 | if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL)) | |
392 | { | |
393 | CORE_ADDR post_prologue_pc | |
394 | = skip_prologue_using_sal (gdbarch, func_addr); | |
395 | struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr); | |
396 | ||
397 | /* Clang always emits a line note before the prologue and another | |
398 | one after. We trust clang to emit usable line notes. */ | |
399 | if (post_prologue_pc | |
400 | && (cust != NULL && COMPUNIT_PRODUCER (cust) != NULL | |
401 | && startswith (COMPUNIT_PRODUCER (cust), "clang "))) | |
402 | return std::max (start_pc, post_prologue_pc); | |
403 | } | |
404 | ||
405 | /* Can't determine prologue from the symbol table, need to examine | |
406 | instructions. */ | |
407 | ||
408 | return start_pc; | |
409 | } | |
410 | ||
411 | static struct gdbarch * | |
412 | amdgcn_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | |
413 | { | |
414 | /* If there is already a candidate, use it. */ | |
415 | arches = gdbarch_list_lookup_by_info (arches, &info); | |
416 | if (arches != NULL) | |
417 | return arches->gdbarch; | |
418 | ||
419 | struct gdbarch_deleter | |
420 | { | |
421 | void | |
422 | operator() (struct gdbarch *gdbarch) const | |
423 | { | |
424 | gdbarch_free (gdbarch); | |
425 | } | |
426 | }; | |
427 | ||
428 | /* Allocate space for the new architecture. */ | |
429 | std::unique_ptr<struct gdbarch_tdep> tdep (new struct gdbarch_tdep); | |
430 | std::unique_ptr<struct gdbarch, gdbarch_deleter> gdbarch_u ( | |
431 | gdbarch_alloc (&info, tdep.get ())); | |
432 | ||
433 | struct gdbarch *gdbarch = gdbarch_u.get (); | |
434 | ||
435 | /* Data types. */ | |
436 | set_gdbarch_char_signed (gdbarch, 0); | |
437 | set_gdbarch_ptr_bit (gdbarch, 64); | |
438 | set_gdbarch_addr_bit (gdbarch, 64); | |
439 | set_gdbarch_short_bit (gdbarch, 16); | |
440 | set_gdbarch_int_bit (gdbarch, 32); | |
441 | set_gdbarch_long_bit (gdbarch, 64); | |
442 | set_gdbarch_long_long_bit (gdbarch, 64); | |
443 | set_gdbarch_float_bit (gdbarch, 32); | |
444 | set_gdbarch_double_bit (gdbarch, 64); | |
445 | set_gdbarch_long_double_bit (gdbarch, 128); | |
446 | set_gdbarch_float_format (gdbarch, floatformats_ieee_single); | |
447 | set_gdbarch_double_format (gdbarch, floatformats_ieee_double); | |
448 | set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); | |
449 | ||
450 | /* Frame Interpretation. */ | |
451 | set_gdbarch_skip_prologue (gdbarch, amdgcn_skip_prologue); | |
452 | set_gdbarch_inner_than (gdbarch, core_addr_lessthan); | |
453 | dwarf2_append_unwinders (gdbarch); | |
454 | frame_unwind_append_unwinder (gdbarch, &amdgcn_frame_unwind); | |
455 | set_gdbarch_dummy_id (gdbarch, amdgcn_dummy_id); | |
456 | ||
457 | /* Registers and Memory. */ | |
458 | amd_dbgapi_architecture_id_t architecture_id; | |
459 | if (amd_dbgapi_get_architecture (gdbarch_bfd_arch_info (gdbarch)->mach, | |
460 | &architecture_id) | |
461 | != AMD_DBGAPI_STATUS_SUCCESS) | |
462 | return nullptr; | |
463 | ||
464 | size_t register_class_count; | |
465 | amd_dbgapi_register_class_id_t *register_class_ids; | |
466 | ||
467 | if (amd_dbgapi_architecture_register_class_list ( | |
468 | architecture_id, ®ister_class_count, ®ister_class_ids) | |
469 | != AMD_DBGAPI_STATUS_SUCCESS) | |
470 | return nullptr; | |
471 | ||
472 | /* Add register groups. */ | |
473 | reggroup_add (gdbarch, all_reggroup); | |
474 | ||
475 | for (size_t i = 0; i < register_class_count; ++i) | |
476 | { | |
477 | char *bytes; | |
478 | if (amd_dbgapi_architecture_register_class_get_info ( | |
479 | architecture_id, register_class_ids[i], | |
480 | AMD_DBGAPI_REGISTER_CLASS_INFO_NAME, sizeof (bytes), &bytes) | |
481 | != AMD_DBGAPI_STATUS_SUCCESS) | |
482 | continue; | |
483 | ||
484 | gdb::unique_xmalloc_ptr<char> name (bytes); | |
485 | ||
486 | auto inserted = tdep->register_class_map.emplace (name.get (), | |
487 | register_class_ids[i]); | |
488 | ||
489 | if (!inserted.second) | |
490 | continue; | |
491 | ||
492 | /* Allocate the reggroup in the gdbarch. */ | |
493 | auto *group = reggroup_gdbarch_new (gdbarch, name.get (), USER_REGGROUP); | |
494 | if (!group) | |
495 | { | |
496 | tdep->register_class_map.erase (inserted.first); | |
497 | continue; | |
498 | } | |
499 | ||
500 | reggroup_add (gdbarch, group); | |
501 | } | |
502 | xfree (register_class_ids); | |
503 | ||
504 | /* Add registers. */ | |
505 | size_t register_count; | |
506 | amd_dbgapi_register_id_t *register_ids; | |
507 | ||
508 | if (amd_dbgapi_architecture_register_list (architecture_id, ®ister_count, | |
509 | ®ister_ids) | |
510 | != AMD_DBGAPI_STATUS_SUCCESS) | |
511 | return nullptr; | |
512 | ||
513 | tdep->register_ids.insert (tdep->register_ids.end (), ®ister_ids[0], | |
514 | ®ister_ids[register_count]); | |
515 | ||
516 | set_gdbarch_num_regs (gdbarch, register_count); | |
517 | set_gdbarch_num_pseudo_regs (gdbarch, 0); | |
518 | xfree (register_ids); | |
519 | ||
520 | tdep->register_names.resize (register_count); | |
521 | for (size_t i = 0; i < register_count; ++i) | |
522 | { | |
523 | if (!tdep->regnum_map.emplace (tdep->register_ids[i], i).second) | |
524 | return nullptr; | |
525 | ||
526 | char *bytes; | |
527 | if (amd_dbgapi_architecture_register_get_info ( | |
528 | architecture_id, tdep->register_ids[i], | |
529 | AMD_DBGAPI_REGISTER_INFO_NAME, sizeof (bytes), &bytes) | |
530 | != AMD_DBGAPI_STATUS_SUCCESS) | |
531 | continue; | |
532 | ||
533 | tdep->register_names[i] = bytes; | |
534 | xfree (bytes); | |
535 | } | |
536 | ||
537 | amd_dbgapi_register_id_t pc_register_id; | |
538 | if (amd_dbgapi_architecture_get_info ( | |
539 | architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_PC_REGISTER, | |
540 | sizeof (pc_register_id), &pc_register_id) | |
541 | != AMD_DBGAPI_STATUS_SUCCESS) | |
542 | return nullptr; | |
543 | ||
544 | set_gdbarch_pc_regnum (gdbarch, tdep->regnum_map[pc_register_id]); | |
545 | set_gdbarch_ps_regnum (gdbarch, -1); | |
546 | set_gdbarch_sp_regnum (gdbarch, -1); | |
547 | set_gdbarch_fp0_regnum (gdbarch, -1); | |
548 | ||
549 | set_gdbarch_dwarf2_reg_to_regnum (gdbarch, amdgcn_dwarf_reg_to_regnum); | |
550 | ||
551 | /* Register Representation. */ | |
552 | set_gdbarch_register_name (gdbarch, amdgcn_register_name); | |
553 | set_gdbarch_register_type (gdbarch, amdgcn_register_type); | |
554 | set_gdbarch_register_reggroup_p (gdbarch, amdgcn_register_reggroup_p); | |
555 | ||
556 | /* Disassembly. */ | |
557 | set_gdbarch_print_insn (gdbarch, print_insn_amdgcn); | |
558 | ||
559 | /* Displaced stepping. */ | |
560 | set_gdbarch_displaced_step_location (gdbarch, | |
561 | amdgcn_rocm_displaced_step_location); | |
562 | ||
563 | set_gdbarch_displaced_step_copy_insn (gdbarch, | |
564 | amdgcn_rocm_displaced_step_copy_insn); | |
565 | set_gdbarch_displaced_step_fixup (gdbarch, amdgcn_rocm_displaced_step_fixup); | |
566 | ||
567 | /* Instructions. */ | |
568 | amd_dbgapi_size_t max_insn_length = 0; | |
569 | if (amd_dbgapi_architecture_get_info ( | |
570 | architecture_id, | |
571 | AMD_DBGAPI_ARCHITECTURE_INFO_LARGEST_INSTRUCTION_SIZE, | |
572 | sizeof (max_insn_length), &max_insn_length) | |
573 | != AMD_DBGAPI_STATUS_SUCCESS) | |
574 | error (_ ("amd_dbgapi_architecture_get_info failed")); | |
575 | ||
576 | set_gdbarch_max_insn_length (gdbarch, max_insn_length); | |
577 | ||
578 | if (amd_dbgapi_architecture_get_info ( | |
579 | architecture_id, | |
580 | AMD_DBGAPI_ARCHITECTURE_INFO_BREAKPOINT_INSTRUCTION_SIZE, | |
581 | sizeof (tdep->breakpoint_instruction_size), | |
582 | &tdep->breakpoint_instruction_size) | |
583 | != AMD_DBGAPI_STATUS_SUCCESS) | |
584 | error (_ ("amd_dbgapi_architecture_get_info failed")); | |
585 | ||
586 | gdb_byte *breakpoint_instruction_bytes; | |
587 | if (amd_dbgapi_architecture_get_info ( | |
588 | architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_BREAKPOINT_INSTRUCTION, | |
45f0bbf1 | 589 | sizeof (breakpoint_instruction_bytes), &breakpoint_instruction_bytes) |
abeeff98 LM |
590 | != AMD_DBGAPI_STATUS_SUCCESS) |
591 | error (_ ("amd_dbgapi_architecture_get_info failed")); | |
592 | ||
593 | tdep->breakpoint_instruction_bytes.reset (breakpoint_instruction_bytes); | |
594 | ||
595 | set_gdbarch_breakpoint_kind_from_pc (gdbarch, | |
596 | amdgcn_breakpoint_kind_from_pc); | |
597 | set_gdbarch_sw_breakpoint_from_kind (gdbarch, | |
598 | amdgcn_sw_breakpoint_from_kind); | |
599 | ||
600 | tdep.release (); | |
601 | gdbarch_u.release (); | |
602 | ||
603 | return gdbarch; | |
604 | } | |
605 | ||
606 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
607 | extern initialize_file_ftype _initialize_amdgcn_rocm_tdep; | |
608 | ||
609 | void | |
610 | _initialize_amdgcn_rocm_tdep (void) | |
611 | { | |
612 | gdbarch_register (bfd_arch_amdgcn, amdgcn_gdbarch_init, NULL); | |
613 | } |