riscv-ravenscar-thread.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* Ravenscar RISC-V target support.
  2. Copyright (C) 2019-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "defs.h"
  15. #include "gdbarch.h"
  16. #include "gdbcore.h"
  17. #include "regcache.h"
  18. #include "riscv-tdep.h"
  19. #include "inferior.h"
  20. #include "ravenscar-thread.h"
  21. #include "riscv-ravenscar-thread.h"
  22. struct riscv_ravenscar_ops : public ravenscar_arch_ops
  23. {
  24. void fetch_registers (struct regcache *regcache, int regnum) override;
  25. void store_registers (struct regcache *regcache, int regnum) override;
  26. private:
  27. /* Return the offset of the register in the context buffer. */
  28. int register_offset (struct gdbarch *arch, int regnum);
  29. };
  30. int
  31. riscv_ravenscar_ops::register_offset (struct gdbarch *arch, int regnum)
  32. {
  33. int offset;
  34. if (regnum == RISCV_RA_REGNUM || regnum == RISCV_PC_REGNUM)
  35. offset = 0;
  36. else if (regnum == RISCV_SP_REGNUM)
  37. offset = 1;
  38. else if (regnum == RISCV_ZERO_REGNUM + 8) /* S0 */
  39. offset = 2;
  40. else if (regnum == RISCV_ZERO_REGNUM + 9) /* S1 */
  41. offset = 3;
  42. else if (regnum >= RISCV_ZERO_REGNUM + 19
  43. && regnum <= RISCV_ZERO_REGNUM + 27) /* S2..S11 */
  44. offset = regnum - (RISCV_ZERO_REGNUM + 19) + 4;
  45. else if (regnum >= RISCV_FIRST_FP_REGNUM
  46. && regnum <= RISCV_FIRST_FP_REGNUM + 11)
  47. offset = regnum - RISCV_FIRST_FP_REGNUM + 14; /* FS0..FS11 */
  48. else
  49. {
  50. /* Not saved. */
  51. return -1;
  52. }
  53. int size = register_size (arch, regnum);
  54. return offset * size;
  55. }
  56. /* Supply register REGNUM, which has been saved on REGISTER_ADDR, to the
  57. regcache. */
  58. static void
  59. supply_register_at_address (struct regcache *regcache, int regnum,
  60. CORE_ADDR register_addr)
  61. {
  62. struct gdbarch *gdbarch = regcache->arch ();
  63. int buf_size = register_size (gdbarch, regnum);
  64. gdb_byte *buf;
  65. buf = (gdb_byte *) alloca (buf_size);
  66. read_memory (register_addr, buf, buf_size);
  67. regcache->raw_supply (regnum, buf);
  68. }
  69. void
  70. riscv_ravenscar_ops::fetch_registers (struct regcache *regcache, int regnum)
  71. {
  72. struct gdbarch *gdbarch = regcache->arch ();
  73. const int num_regs = gdbarch_num_regs (gdbarch);
  74. int current_regnum;
  75. CORE_ADDR current_address;
  76. CORE_ADDR thread_descriptor_address;
  77. /* The tid is the thread_id field, which is a pointer to the thread. */
  78. thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
  79. /* Read registers. */
  80. for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
  81. {
  82. int offset = register_offset (gdbarch, current_regnum);
  83. if (offset != -1)
  84. {
  85. current_address = thread_descriptor_address + offset;
  86. supply_register_at_address (regcache, current_regnum,
  87. current_address);
  88. }
  89. }
  90. }
  91. void
  92. riscv_ravenscar_ops::store_registers (struct regcache *regcache, int regnum)
  93. {
  94. struct gdbarch *gdbarch = regcache->arch ();
  95. int buf_size = register_size (gdbarch, regnum);
  96. gdb_byte buf[buf_size];
  97. CORE_ADDR register_address;
  98. int offset = register_offset (gdbarch, regnum);
  99. if (offset != -1)
  100. {
  101. register_address = inferior_ptid.tid () + offset;
  102. regcache->raw_collect (regnum, buf);
  103. write_memory (register_address,
  104. buf,
  105. buf_size);
  106. }
  107. }
  108. /* The ravenscar_arch_ops vector for most RISC-V targets. */
  109. static struct riscv_ravenscar_ops riscv_ravenscar_ops;
  110. /* Register riscv_ravenscar_ops in GDBARCH. */
  111. void
  112. register_riscv_ravenscar_ops (struct gdbarch *gdbarch)
  113. {
  114. set_gdbarch_ravenscar_ops (gdbarch, &riscv_ravenscar_ops);
  115. }