diff mbox

[RFC,11/15] gdbserver: Add helper functions to create arm instructions

Message ID 2bdf7fa13db6d0b92a727eeff8d01b74bd200229.1444820235.git.henrik.wallin@windriver.com
State New
Headers show

Commit Message

henrik.wallin@windriver.com Oct. 14, 2015, 11:14 a.m. UTC
From: Henrik Wallin <henrik.wallin@windriver.com>

This adds the function. No users yet.

gdb/gdbserver/ChangeLog:

	* linux-arm-low.c : Add code generation helpers

Signed-off-by: Henrik Wallin <henrik.wallin@windriver.com>
---
 gdb/gdbserver/linux-arm-low.c | 135 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)
diff mbox

Patch

diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 81d23d953434..044e7527a3b0 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -20,6 +20,7 @@ 
 #include "linux-low.h"
 #include "arch/arm.h"
 #include "linux-aarch32-low.h"
+#include <inttypes.h>
 
 #include <sys/uio.h>
 /* Don't include elf.h if linux/elf.h got included by gdb_proc_service.h.
@@ -916,6 +917,140 @@  arm_regs_info (void)
     return &regs_info_arm;
 }
 
+static uint32_t
+mk_t_b_rel (CORE_ADDR from, CORE_ADDR to)
+{
+  uint32_t from_ = ((uint32_t) from) & ~1;
+  uint32_t to_   = ((uint32_t) to) & ~1;
+  return to_ - from_ - 4;
+}
+
+static int
+mk_t_b_isreachable (CORE_ADDR from, CORE_ADDR to)
+{
+  int32_t rel = mk_t_b_rel (from, to);
+  rel >>= 24;
+  return !rel || !(rel + 1);
+}
+
+static uint16_t *
+mk_t_b_instr (uint16_t *mem, CORE_ADDR from, CORE_ADDR to)
+{
+  uint32_t imm10, imm11;
+  uint32_t s, j1, j2;
+  uint32_t rel;
+
+  rel = mk_t_b_rel (from, to);
+  rel >>= 1;
+
+  imm11 = rel & 0x7ff;
+  rel >>= 11;
+  imm10 = rel & 0x3ff;
+  rel >>= 10;
+  s  = (rel > 3);
+  j1 = s ^ !(rel & 2);
+  j2 = s ^ !(rel & 1);
+
+  *mem++ = 0xF000 | (s << 10) | imm10;
+  *mem++ = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
+
+  return mem;
+}
+
+static uint16_t *
+mk_t_blx_instr (uint16_t *mem, int reg)
+{
+  reg &= 0xF;
+  *mem++ = 0x4780 | (reg << 3);
+  return mem;
+}
+
+static uint16_t *
+mk_t_load_instr (uint16_t *mem, int reg, uint32_t val)
+{
+  uint32_t imm4, imm3, imm8;
+  uint32_t i;
+
+  imm8 = val & 0x00FF;
+  val >>= 8;
+  imm3 = val & 0x0007;
+  val >>= 3;
+  i = val & 0x0001;
+  val >>= 1;
+  imm4 = val & 0x000F;
+  val >>= 4;
+
+  *mem++ = 0xF240 | (i << 10) | imm4;
+  *mem++ = 0x0000 | (imm3 << 12) | (reg << 8) | imm8;
+
+  imm8 = val & 0x00FF;
+  val >>= 8;
+  imm3 = val & 0x0007;
+  val >>= 3;
+  i = val & 0x0001;
+  val >>= 1;
+  imm4 = val & 0x000F;
+
+  *mem++ = 0xF2C0 | (i << 10) | imm4;
+  *mem++ = 0x0000 | (imm3 << 12) | (reg << 8) | imm8;
+
+  return mem;
+}
+
+static uint32_t
+mk_a_b_rel (CORE_ADDR from, CORE_ADDR to)
+{
+  return (uint32_t) to - (uint32_t) from - 8;
+}
+
+static int
+mk_a_b_isreachable (CORE_ADDR from, CORE_ADDR to)
+{
+  int32_t rel = mk_a_b_rel (from, to);
+  rel >>= 25;
+  return !rel || !(rel + 1);
+}
+
+static uint32_t *
+mk_a_b_instr (uint32_t *mem, CORE_ADDR from, CORE_ADDR to)
+{
+  uint32_t imm24 = mk_a_b_rel (from, to);
+
+  imm24 >>= 2;
+  imm24 &= 0x00FFFFFF;
+  *mem++ = 0xEA000000 | imm24;
+
+  return mem;
+}
+
+static uint32_t *
+mk_a_blx_instr (uint32_t *mem, int reg)
+{
+  *mem++ = 0xE12FFF30 | (reg & 0xF);
+  return mem;
+}
+
+static uint32_t *
+mk_a_load_instr (uint32_t *mem, int reg, uint32_t val)
+{
+  uint32_t imm4, imm12;
+
+  imm12 = val & 0x0FFF;
+  val >>= 12;
+  imm4 = val & 0xF;
+  val >>= 4;
+
+  *mem++ = 0xE3000000 | ((reg & 0xF) << 12) | (imm4 << 16) | imm12;
+
+  imm12 = val & 0x0FFF;
+  val >>= 12;
+  imm4 = val & 0xF;
+
+  *mem++ = 0xE3400000 | ((reg & 0xF) << 12) | (imm4 << 16) | imm12;
+
+  return mem;
+}
+
 struct linux_target_ops the_low_target = {
   arm_arch_setup,
   arm_regs_info,