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