diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3440e44..1ce071a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -644,7 +644,9 @@ TARGET_OBS = @TARGET_OBS@
# All target-dependent objects files that require 64-bit CORE_ADDR
# (used with --enable-targets=all --enable-64-bit-bfd).
ALL_64_TARGET_OBS = \
- aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o aarch64-insn.o \
+ aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o \
+ aarch64-insn.o \
+ arm-insn-utils.o \
alphabsd-tdep.o alphafbsd-tdep.o alpha-linux-tdep.o alpha-mdebug-tdep.o \
alphanbsd-tdep.o alphaobsd-tdep.o alpha-tdep.o \
amd64fbsd-tdep.o amd64-darwin-tdep.o amd64-dicos-tdep.o \
@@ -662,8 +664,9 @@ ALL_TARGET_OBS = \
arm-linux.o \
arm-linux-tdep.o \
arm-get-next-pcs.o \
- arm-symbian-tdep.o \
+ arm-insn-emit.o \
arm-insn-reloc.o \
+ arm-symbian-tdep.o \
armnbsd-tdep.o armobsd-tdep.o \
arm-tdep.o arm-wince-tdep.o \
avr-tdep.o \
@@ -993,7 +996,8 @@ common/common-exceptions.h target/target.h common/symbol.h \
common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h nat/amd64-linux-siginfo.h\
nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h \
-tid-parse.h ser-event.h arch/arm-insn-reloc.h
+tid-parse.h ser-event.h arch/arm-insn-emit.h arch/arm-insn-reloc.h \
+arch/arm-insn-utils.h
# Header files that already have srcdir in them, or which are in objdir.
@@ -2313,6 +2317,10 @@ arm-linux.o: ${srcdir}/arch/arm-linux.c
$(COMPILE) $(srcdir)/arch/arm-linux.c
$(POSTCOMPILE)
+arm-insn-emit.o: ${srcdir}/arch/arm-insn-emit.c
+ $(COMPILE) $(srcdir)/arch/arm-insn-emit.c
+ $(POSTCOMPILE)
+
arm-insn-reloc.o: ${srcdir}/arch/arm-insn-reloc.c
$(COMPILE) $(srcdir)/arch/arm-insn-reloc.c
$(POSTCOMPILE)
@@ -2395,6 +2403,10 @@ aarch64-insn.o: ${srcdir}/arch/aarch64-insn.c
$(COMPILE) $(srcdir)/arch/aarch64-insn.c
$(POSTCOMPILE)
+arm-insn-utils.o: ${srcdir}/arch/arm-insn-utils.c
+ $(COMPILE) $(srcdir)/arch/arm-insn-utils.c
+ $(POSTCOMPILE)
+
#
# gdb/tui/ dependencies
#
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 88fcf4b..dde9a4d 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -57,6 +57,7 @@
#include "features/aarch64.c"
+#include "arch/arm-insn-utils.h"
#include "arch/aarch64-insn.h"
#include "opcode/aarch64.h"
@@ -2471,7 +2472,7 @@ aarch64_displaced_step_ldr_literal (const int32_t offset, const int is_sw,
struct aarch64_displaced_step_data *dsd
= (struct aarch64_displaced_step_data *) data;
CORE_ADDR address = data->insn_addr + offset;
- struct aarch64_memory_operand zero = { MEMORY_OPERAND_OFFSET, 0 };
+ struct arm_memory_operand zero = { MEMORY_OPERAND_OFFSET, 0 };
regcache_cooked_write_unsigned (dsd->regs, AARCH64_X0_REGNUM + rt,
address);
diff --git a/gdb/arch/aarch64-insn.c b/gdb/arch/aarch64-insn.c
index 772512b..88fbffe 100644
--- a/gdb/arch/aarch64-insn.c
+++ b/gdb/arch/aarch64-insn.c
@@ -17,6 +17,7 @@
along with this program. If not, see . */
#include "common-defs.h"
+#include "arm-insn-utils.h"
#include "aarch64-insn.h"
/* Toggle this file's internal debugging dump. */
@@ -346,7 +347,7 @@ aarch64_emit_load_store (uint32_t *buf, uint32_t size,
enum aarch64_opcodes opcode,
struct aarch64_register rt,
struct aarch64_register rn,
- struct aarch64_memory_operand operand)
+ struct arm_memory_operand operand)
{
uint32_t op;
diff --git a/gdb/arch/aarch64-insn.h b/gdb/arch/aarch64-insn.h
index a799515..511a80c 100644
--- a/gdb/arch/aarch64-insn.h
+++ b/gdb/arch/aarch64-insn.h
@@ -117,36 +117,6 @@ struct aarch64_register
int is64;
};
-enum aarch64_memory_operand_type
-{
- MEMORY_OPERAND_OFFSET,
- MEMORY_OPERAND_PREINDEX,
- MEMORY_OPERAND_POSTINDEX,
-};
-
-/* Representation of a memory operand, used for load and store
- instructions.
-
- The types correspond to the following variants:
-
- MEMORY_OPERAND_OFFSET: LDR rt, [rn, #offset]
- MEMORY_OPERAND_PREINDEX: LDR rt, [rn, #index]!
- MEMORY_OPERAND_POSTINDEX: LDR rt, [rn], #index */
-
-struct aarch64_memory_operand
-{
- /* Type of the operand. */
- enum aarch64_memory_operand_type type;
-
- /* Index from the base register. */
- int32_t index;
-};
-
-/* Helper macro to mask and shift a value into a bitfield. */
-
-#define ENCODE(val, size, offset) \
- ((uint32_t) ((val & ((1ULL << size) - 1)) << offset))
-
int aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp,
unsigned *rd, int32_t *offset);
@@ -319,6 +289,6 @@ int aarch64_emit_load_store (uint32_t *buf, uint32_t size,
enum aarch64_opcodes opcode,
struct aarch64_register rt,
struct aarch64_register rn,
- struct aarch64_memory_operand operand);
+ struct arm_memory_operand operand);
#endif
diff --git a/gdb/arch/arm-insn-emit.c b/gdb/arch/arm-insn-emit.c
new file mode 100644
index 0000000..810172d
--- /dev/null
+++ b/gdb/arch/arm-insn-emit.c
@@ -0,0 +1,1550 @@
+/* Copyright (C) 2015-2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#include "common-defs.h"
+#include "arm.h"
+#include "arm-insn-utils.h"
+#include "arm-insn-emit.h"
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+/* Encode a bitfield with a repetition of BIT starting at from FROM for
+ LENGHT. Max 16 bits. */
+
+static uint16_t
+repeat_bit (uint8_t bit, uint8_t from, uint8_t length)
+{
+ uint16_t value = 0;
+ int i;
+
+ for (i = from; i - from < length; i++)
+ {
+ value |= ENCODE (bit & 1, 1, i);
+ }
+
+ return value;
+}
+
+/* See arm-insn-emit.h. */
+
+uint16_t
+encode_register_list (uint8_t from, uint8_t length, uint16_t initial)
+{
+ return repeat_bit (1, from, length) | initial;
+}
+
+/* See arm-insn-emit.h. */
+
+struct arm_operand
+immediate_operand (uint32_t imm)
+{
+ struct arm_operand operand;
+
+ operand.type = OPERAND_IMMEDIATE;
+ operand.imm = imm;
+
+ return operand;
+}
+
+/* Helper function to create a register operand, for instructions with
+ different types of operands.
+
+ For example:
+ p += emit_mov (p, x0, register_operand (x1)); */
+
+/* See arm-insn-emit.h. */
+
+struct arm_operand
+register_operand (uint8_t reg)
+{
+ struct arm_operand operand;
+
+ operand.type = OPERAND_REGISTER;
+ operand.reg = reg;
+
+ return operand;
+}
+
+/* See arm-insn-emit.h. */
+
+struct arm_operand
+memory_operand (struct arm_memory_operand mem)
+{
+ struct arm_operand operand;
+
+ operand.type = OPERAND_MEMORY;
+ operand.mem = mem;
+
+ return operand;
+}
+
+/* Write a 32-bit unsigned integer INSN info *BUF. Return the number of
+ instructions written (aka. 1). */
+
+static int
+arm_emit_arm_insn (uint32_t *buf, uint32_t insn)
+{
+ *buf = insn;
+ return 1;
+}
+
+/* Write a 16-bit unsigned integer INSN info *BUF. Return the number of
+ instructions written (aka. 1). */
+
+static int
+arm_emit_thumb_insn (uint16_t *buf, uint16_t insn)
+{
+ *buf = insn;
+ return 1;
+}
+
+/* Write a 32-bit unsigned integer INSN representing a Thumb-2 wide
+ instruction info *BUF. Return the number of instructions written
+ (aka. 2). */
+
+static int
+arm_emit_thumb_w_insn (uint16_t *buf, uint32_t insn)
+{
+ int res = arm_emit_thumb_insn (buf, bits (insn, 16, 31));
+ res += arm_emit_thumb_insn (buf + res, bits (insn, 0, 15));
+ return res;
+}
+
+/* See arm-insn-emit.h. */
+
+uint32_t
+arm_arm_branch_relative_distance (CORE_ADDR from, CORE_ADDR to)
+{
+ return arm_arm_branch_adjusted_offset ((uint32_t) to - (uint32_t) from);
+}
+
+/* See arm-insn-emit.h. */
+
+uint32_t
+arm_thumb_branch_relative_distance (CORE_ADDR from, CORE_ADDR to)
+{
+ uint32_t from_ = ((uint32_t) from) & ~1;
+ uint32_t to_ = ((uint32_t) to) & ~1;
+ return arm_thumb_branch_adjusted_offset (to_ - from_);
+}
+
+/* See arm-insn-emit.h. */
+
+uint32_t
+arm_thumb_to_arm_branch_relative_distance (CORE_ADDR from, CORE_ADDR to)
+{
+ uint32_t from_ = ((uint32_t) from) & ~3;
+ uint32_t to_ = ((uint32_t) to) & ~3;
+ return arm_thumb_branch_adjusted_offset (to_ - from_);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_arm_is_reachable (CORE_ADDR from, CORE_ADDR to)
+{
+ int32_t rel = arm_arm_branch_relative_distance (from, to);
+ rel >>= 25;
+ return !rel || !(rel + 1);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_thumb_is_reachable (CORE_ADDR from, CORE_ADDR to)
+{
+ int32_t rel = arm_thumb_branch_relative_distance (from, to);
+ rel >>= 24;
+ return !rel || !(rel + 1);
+}
+
+/* See arm-insn-emit.h. */
+
+uint32_t
+arm_arm_branch_adjusted_offset (uint32_t offset)
+{
+ return offset - 8;
+}
+
+/* See arm-insn-emit.h. */
+
+uint32_t
+arm_thumb_branch_adjusted_offset (uint32_t offset)
+{
+ return offset - 4;
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_mov_32 (uint16_t *mem, int reg, uint32_t val)
+{
+ uint16_t val_low = bits (val, 0, 15);
+ uint16_t val_high = bits (val, 16, 31);
+ int res = 0;
+
+ res += arm_emit_thumb_movw (mem, reg, immediate_operand (val_low));
+ res += arm_emit_thumb_movt (mem + res, reg, immediate_operand (val_high));
+
+ return res;
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_mov_32 (uint32_t *mem, int reg, uint32_t val)
+{
+ uint16_t val_low = bits (val, 0, 15);
+ uint16_t val_high = bits (val, 16, 31);
+ int res = 0;
+
+ res += arm_emit_arm_movw (mem, INST_AL, reg, immediate_operand (val_low));
+ res += arm_emit_arm_movt (mem + res, INST_AL, reg,
+ immediate_operand (val_high));
+
+ return res;
+}
+
+/* Write ARM branch instructions into *BUF.
+
+ This is a base function to write
+ B, BL and BLX instructions with immediate or register operands.
+
+ Proper encodings documentation is provided in the
+ arm_emit_arm_{b_,bl_,blx} helper functions.
+
+ L if set a bl instruction will be written.
+ X if set a blx instruction will be written. */
+
+static int
+arm_emit_arm_branch (uint32_t *buf, uint8_t cond,
+ struct arm_operand operand,
+ uint8_t l, uint8_t x)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ /* BLX */
+ if (l == 1 && x == 1)
+ {
+ cond = 0xF;
+ l = bit (operand.imm, 1);
+ }
+ /* Encode B, BL or BLX. */
+ return arm_emit_arm_insn (buf, (ARM_B
+ | ENCODE (l, 1, 24)
+ | ENCODE (cond, 4, 28)
+ | ENCODE (operand.imm >> 2, 24, 0)));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ if (l == 1 && x == 1)
+ {
+ return arm_emit_arm_insn (buf, (ARM_BLX
+ | ENCODE (cond, 4, 28)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ /* error. Only BLX has a register operand. */
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* Write Thumb branch instructions into *BUF.
+
+ This is a base function to write
+ BW, BL and BLX instructions with immediate or register operand.
+
+ Proper encodings documentation is provided in the
+ arm_emit_thumb_{bw_,bl_,blx} helper functions.
+
+ REL is the relative offset of the label.
+ L if set a bl instruction will be written.
+ X if set a blx instruction will be written. */
+
+int
+arm_emit_thumb_branch (uint16_t *buf, struct arm_operand operand,
+ uint8_t l, uint8_t x)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ uint32_t imm10, imm11;
+ uint32_t s, j1, j2;
+
+ if (x == 0)
+ imm11 = bits (operand.imm, 1, 11);
+ else
+ /* IMM10L:H. */
+ imm11 = bits (operand.imm, 2, 11) << 1;
+
+ imm10 = bits (operand.imm, 12, 21);
+ s = bit (operand.imm, 24);
+ j1 = s ^ !(bit (operand.imm, 23));
+ j2 = s ^ !(bit (operand.imm, 22));
+
+ return arm_emit_thumb_w_insn (buf, (THUMB_BW
+ | ENCODE (s, 1, 26)
+ | ENCODE (imm10, 10, 16)
+ | ENCODE (l, 1, 14)
+ | ENCODE (j1, 1, 13)
+ | ENCODE (x == 0 ? 1 : 0, 1, 12)
+ | ENCODE (j2, 1, 11)
+ | ENCODE (imm11, 11, 0)));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ if (l == 1 && x == 1)
+ return arm_emit_thumb_insn (buf, (THUMB_BLX
+ | ENCODE (operand.reg, 4, 3)));
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_b (uint32_t *buf, uint8_t cond, uint32_t rel)
+{
+ return arm_emit_arm_branch (buf, cond, immediate_operand (rel), 0, 0);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_bl (uint32_t *buf, uint8_t cond, uint32_t rel)
+{
+ return arm_emit_arm_branch (buf, cond, immediate_operand (rel), 1, 0);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_bl (uint16_t *buf, uint32_t rel)
+{
+ return arm_emit_thumb_branch (buf, immediate_operand (rel), 1, 0);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_b (uint16_t *buf, uint8_t cond, uint32_t rel)
+{
+ return arm_emit_thumb_insn (buf, (THUMB_B
+ | ENCODE (cond, 4, 8)
+ | ENCODE (rel >> 1, 8, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_bw (uint16_t *buf, uint32_t rel)
+{
+ return arm_emit_thumb_branch (buf, immediate_operand (rel), 0, 0);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_bw_cond (uint16_t *buf, uint8_t cond, uint32_t rel)
+{
+ uint32_t imm6, imm11;
+ uint32_t s, j1, j2;
+
+ imm11 = bits (rel, 1, 11);
+ imm6 = bits (rel, 12, 17);
+ s = bit (rel, 24);
+ j1 = s ^ !(bit (rel, 23));
+ j2 = s ^ !(bit (rel, 22));
+
+ return arm_emit_thumb_w_insn (buf, (THUMB_BW
+ | ENCODE (s, 1, 26)
+ | ENCODE (imm6, 6, 16)
+ | ENCODE (cond, 4, 22)
+ | ENCODE (j1, 1, 13)
+ | ENCODE (j2, 1, 11)
+ | ENCODE (imm11, 11, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_blx (uint16_t *buf, struct arm_operand operand)
+{
+ return arm_emit_thumb_branch (buf, operand, 1, 1);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_blx (uint32_t *buf, uint8_t cond, struct arm_operand operand)
+{
+ return arm_emit_arm_branch (buf, cond, operand, 1, 1);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_movw (uint32_t *buf, uint8_t cond, uint8_t rd,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_MOVW
+ | ENCODE (cond, 4, 28)
+ | ENCODE (bits (operand.imm, 12, 15), 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (bits (operand.imm, 0, 11), 12, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_mov (uint32_t *buf, uint8_t cond, uint8_t rd,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_MOV
+ | ENCODE (cond, 4, 28)
+ /* Immediate value opcode. */
+ | ENCODE (1, 1, 25)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (bits (operand.imm, 0, 11), 12, 0)));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_insn (buf, (ARM_MOV
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_movw (uint16_t *buf, uint8_t rd, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf,
+ (THUMB_MOVW
+ | ENCODE (bit (operand.imm, 11), 1, 26)
+ | ENCODE (bits (operand.imm, 12, 15),
+ 4, 16)
+ | ENCODE (bits (operand.imm, 8, 10), 3, 12)
+ | ENCODE (rd, 4, 8)
+ | ENCODE (bits (operand.imm, 0, 7),
+ 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_movt (uint32_t *buf, uint8_t cond, uint8_t rd,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_MOVT
+ | ENCODE (cond, 4, 28)
+ | ENCODE (bits (operand.imm, 12, 15), 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (bits (operand.imm, 0, 11), 12, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_movt (uint16_t *buf, uint8_t rd, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf,
+ (THUMB_MOVT
+ | ENCODE (bit (operand.imm, 11), 1, 26)
+ | ENCODE (bits (operand.imm, 12, 15),
+ 4, 16)
+ | ENCODE (bits (operand.imm, 8, 10), 3, 12)
+ | ENCODE (rd, 4, 8)
+ | ENCODE (bits (operand.imm, 0, 7),8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_vpush (uint32_t *buf, uint8_t cond, uint8_t rs, uint8_t len)
+{
+ return arm_emit_arm_insn (buf, (ARM_VPUSH
+ | ENCODE (cond, 4, 28)
+ | ENCODE (bit (rs, 4), 1, 22)
+ | ENCODE (bits (rs, 0, 3), 4, 12)
+ | ENCODE (2 * len, 8, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_vpush (uint16_t *buf, uint8_t rs, uint8_t len)
+{
+ return arm_emit_thumb_w_insn (buf, (THUMB_VPUSH
+ | ENCODE (bit (rs, 4), 1, 22)
+ | ENCODE (bits (rs, 0, 3), 4, 12)
+ | ENCODE (2 * len, 8, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_push_list (uint32_t *buf, uint8_t cond, uint16_t register_list)
+{
+ return arm_emit_arm_insn (buf, (ARM_PUSH_A1
+ | ENCODE (cond, 4, 28)
+ | ENCODE (register_list, 16, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_push_one (uint32_t *buf, uint8_t cond, uint8_t rt)
+{
+ return arm_emit_arm_insn (buf, (ARM_PUSH_A2
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rt, 4, 12)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_push_one (uint16_t *buf, uint8_t register_list, uint8_t lr)
+{
+ return arm_emit_thumb_insn (buf, (THUMB_PUSH_T1
+ | ENCODE (register_list, 8, 0)
+ | ENCODE (lr, 1, 8)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_push_list (uint16_t *buf,
+ uint16_t register_list,
+ uint8_t lr)
+{
+ return arm_emit_thumb_w_insn (buf, (THUMB_PUSH_T2
+ | ENCODE (bit (lr, 0), 1, 14)
+ | ENCODE (register_list, 13, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_mrs (uint32_t *buf,
+ uint8_t cond,
+ uint8_t rd)
+{
+ return arm_emit_arm_insn (buf, (ARM_MRS
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rd, 4, 12)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_mrs (uint16_t *buf, uint8_t rd)
+{
+ return arm_emit_thumb_w_insn (buf, THUMB_MRS | ENCODE (rd, 4, 12));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_mov (uint16_t *buf, uint8_t rd, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_thumb_insn (buf, (THUMB_MOV
+ | ENCODE (bit (rd, 3), 1, 7)
+ | ENCODE (bits (rd, 0, 2), 3, 0)
+ | ENCODE (operand.reg, 4, 3)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_dmb (uint32_t *buf)
+{
+ return arm_emit_arm_insn (buf, ARM_DMB | ENCODE (0xF, 4, 0));
+
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_dmb (uint16_t *buf)
+{
+ return arm_emit_thumb_w_insn (buf, THUMB_DMB | ENCODE (0xF, 4, 0));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_ldrex (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn)
+{
+ return arm_emit_arm_insn (buf, (ARM_LDREX
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_ldrex (uint16_t *buf, int8_t rt, uint8_t rn,
+ struct arm_operand operand)
+{
+
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf,
+ (THUMB_LDREX
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (bits (operand.imm, 0, 7),
+ 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_cmp (uint32_t *buf, uint8_t cond, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_CMP
+ | ENCODE (cond, 4, 28)
+ /* Immediate. */
+ | ENCODE (1, 1, 25)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (bits (operand.imm, 0, 11), 12, 0)));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_insn (buf, (ARM_CMP
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_cmp (uint16_t *buf, uint8_t rn, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_insn (buf,
+ (THUMB_CMP
+ | ENCODE (rn, 3, 8)
+ | ENCODE (bits (operand.imm, 0, 7), 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_cmpw (uint16_t *buf, uint8_t rn, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf,
+ (THUMB_CMPW
+ | ENCODE (rn, 4, 16)
+ | ENCODE (bit (operand.imm, 11), 1, 26)
+ | ENCODE (bits (operand.imm, 8, 10), 3, 12)
+ | ENCODE (bits (operand.imm, 0, 7),
+ 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_bic (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_BIC
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (bits (operand.imm, 0, 11), 12, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_bic (uint16_t *buf, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf,
+ (THUMB_BIC
+ | ENCODE (bit (operand.imm, 11), 1, 26)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 8)
+ | ENCODE (bits (operand.imm, 8, 10), 3, 12)
+ | ENCODE (bits (operand.imm, 0, 7),
+ 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_strex (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rt,
+ uint8_t rn)
+{
+ return arm_emit_arm_insn (buf, (ARM_STREX
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (rt, 4, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_strex (uint16_t *buf, uint8_t rd, uint8_t rt, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_w_insn (buf, (THUMB_STREX
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (rd, 4, 8)
+ | ENCODE (operand.imm, 8, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_str (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_MEMORY)
+ {
+ switch (operand.mem.type)
+ {
+ case MEMORY_OPERAND_OFFSET:
+ {
+ return arm_emit_arm_insn (buf,
+ (ARM_STR
+ | ENCODE (cond, 4, 28)
+ /* P. */
+ | ENCODE (1, 1, 24)
+ /* U. */
+ | ENCODE (operand.mem.index < 0 ? 0 : 1,
+ 1, 23)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (bits (ABS (operand.mem.index),
+ 0, 11), 12, 0)));
+
+ }
+ default:
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_str (uint16_t *buf, uint8_t rt, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_insn (buf, (THUMB_STR
+ | ENCODE (operand.imm, 5, 6)
+ | ENCODE (rn, 3, 3)
+ | ENCODE (rt, 3, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+
+}
+
+/* Helper function to emit data processing register instructions. */
+
+static int
+arm_emit_arm_data_processing_reg (uint32_t *buf, uint32_t opcode,
+ uint8_t cond, uint8_t flags,
+ uint32_t operands)
+{
+ return arm_emit_arm_insn (buf, (opcode
+ | ENCODE (cond, 4, 28)
+ | ENCODE (flags, 1, 20)
+ /* No shift. */
+ | ENCODE (0, 5, 7)
+ | ENCODE (0, 2, 5)
+ | operands));
+}
+
+/* Helper function to emit data processing immediate instructions. */
+
+static int
+arm_emit_arm_data_processing_imm (uint32_t *buf, uint32_t opcode, uint8_t cond,
+ uint8_t rn, uint32_t operands)
+{
+ return arm_emit_arm_insn (buf, (opcode
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rn, 4, 16)
+ | operands));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_add (uint32_t *buf, uint8_t cond, uint8_t flags, uint8_t rd,
+ uint8_t rn, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_insn (buf, (ARM_ADD
+ /* Immediate operand */
+ | ENCODE (1, 1, 25)
+ | ENCODE (cond, 4, 28)
+ | ENCODE (flags, 1, 20)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.imm, 8, 0)));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_ADD, cond, flags,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_adc (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ else if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_ADC, cond, 0,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_add_sp (uint16_t *buf, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_thumb_insn (buf, (THUMB_ADD_SP
+ | ENCODE (operand.imm >> 2, 7, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_pop_one (uint32_t *buf, uint8_t cond, uint8_t rt)
+{
+ return arm_emit_arm_insn (buf, (ARM_POP_A2
+ | ENCODE (cond, 4, 28)
+ | ENCODE (rt, 4, 12)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_pop_list (uint32_t *buf, uint8_t cond, uint16_t register_list)
+{
+ return arm_emit_arm_insn (buf, (ARM_POP_A1
+ | ENCODE (cond, 4, 28)
+ | ENCODE (register_list, 16, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_pop (uint16_t *buf, uint8_t register_list, uint8_t pc)
+{
+ return arm_emit_thumb_insn (buf, (THUMB_POP
+ | ENCODE (pc, 1, 8)
+ | ENCODE (register_list, 8, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_popw_list (uint16_t *buf, uint16_t register_list, uint8_t pc,
+ uint8_t lr)
+{
+ return arm_emit_thumb_w_insn (buf, (THUMB_POPW
+ | ENCODE (pc, 1, 15)
+ | ENCODE (lr, 1, 14)
+ | ENCODE (register_list, 13, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_msr (uint32_t *buf, uint8_t cond, uint8_t rn)
+{
+ return arm_emit_arm_insn (buf, (ARM_MSR
+ | ENCODE (cond, 4, 28)
+ /* Mask 0b11 */
+ | ENCODE (3, 2, 18)
+ | ENCODE (rn, 4, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_msr (uint16_t *buf, uint8_t rn)
+{
+ return arm_emit_thumb_w_insn (buf, (THUMB_MSR
+ | ENCODE (rn, 4, 16)
+ /* Mask 0b11 */
+ | ENCODE (3, 2, 10)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_vpop (uint32_t *buf, uint8_t cond, uint8_t rs, uint8_t len)
+{
+ return arm_emit_arm_insn (buf, (ARM_VPOP
+ | ENCODE (cond, 4, 28)
+ | ENCODE (bit (rs, 4), 1, 22)
+ | ENCODE (bits (rs, 0, 3), 4, 12)
+ | ENCODE (2 * len, 8, 0)));
+
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_thumb_vpop (uint16_t *buf, uint8_t rs, uint8_t len)
+{
+ return arm_emit_thumb_w_insn (buf, (THUMB_VPOP
+ | ENCODE (bit (rs, 4), 1, 22)
+ | ENCODE (bits (rs, 0, 3), 4, 12)
+ | ENCODE (2 * len, 8, 0)));
+}
+
+/* Helper function for LDR and LDRB instructions. */
+
+static int
+arm_emit_arm_ldr_ldrb (uint32_t *buf, uint32_t opcode, uint8_t cond, uint8_t rt,
+ uint8_t rn, struct arm_memory_operand operand)
+{
+ switch (operand.type)
+ {
+ case MEMORY_OPERAND_OFFSET:
+ {
+ /* Offset P 1 , W 0 */
+ /* Pre indexed P 1 W 1 */
+ /* Post indexed P 0 W1 */
+ /* U 1 if offset add */
+ /* U 0 if offset sub */
+
+ /* Offset P1 , W0. */
+ uint32_t offset_op = ENCODE (1, 1, 24) | ENCODE (0, 1, 21);
+
+ /* U1 if offset added or omitted, U0 if subtracted. */
+ if (operand.index >= 0)
+ offset_op |= ENCODE (1, 1, 23);
+
+ return arm_emit_arm_insn (buf, (opcode
+ | ENCODE (cond, 4, 28)
+ | offset_op
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (ABS (operand.index), 12, 0)));
+ }
+ default:
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+}
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_ldr (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn,
+ struct arm_memory_operand operand)
+{
+ return arm_emit_arm_ldr_ldrb (buf, ARM_LDR, cond, rt, rn, operand);
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_ldrb (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn,
+ struct arm_memory_operand operand)
+{
+ return arm_emit_arm_ldr_ldrb (buf, ARM_LDRB, cond, rt, rn, operand);
+}
+
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_ldrh (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn,
+ struct arm_memory_operand operand)
+{
+ switch (operand.type)
+ {
+ case MEMORY_OPERAND_OFFSET:
+ {
+ /* Offset P 1 , W 0 */
+ /* Pre indexed P 1 W 1 */
+ /* Post indexed P 0 W1 */
+ /* U 1 if offset add */
+ /* U 0 if offset sub */
+
+ /* Offset P1 , W0. */
+ uint32_t offset_op = ENCODE (1, 1, 24) | ENCODE (0, 1, 21);
+
+ /* U1 if offset added or omitted, U0 if subtracted. */
+ if (operand.index >= 0)
+ offset_op |= ENCODE (1, 1, 23);
+
+ return arm_emit_arm_insn (buf,
+ (ARM_LDRH
+ | ENCODE (cond, 4, 28)
+ | offset_op
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (bits(ABS (operand.index), 4, 7),
+ 4, 8)
+ | ENCODE (bits(ABS (operand.index), 0, 3),
+ 4, 0)));
+ }
+ default:
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_ldrd (uint32_t *buf, uint8_t cond, uint8_t rt, uint8_t rn,
+ struct arm_memory_operand operand)
+{
+ switch (operand.type)
+ {
+ case MEMORY_OPERAND_OFFSET:
+ {
+ /* Offset P 1 , W 0 */
+ /* Pre indexed P 1 W 1 */
+ /* Post indexed P 0 W1 */
+ /* U 1 if offset add */
+ /* U 0 if offset sub */
+
+ /* Offset P1 , W0. */
+ uint32_t offset_op = ENCODE (1, 1, 24) | ENCODE (0, 1, 21);
+
+ /* U1 if offset added or omitted, U0 if subtracted. */
+ if (operand.index >= 0)
+ offset_op |= ENCODE (1, 1, 23);
+
+ return arm_emit_arm_insn (buf,
+ (ARM_LDRD
+ | ENCODE (cond, 4, 28)
+ | offset_op
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rt, 4, 12)
+ | ENCODE (bits(ABS (operand.index), 4, 7),
+ 4, 8)
+ | ENCODE (bits(ABS (operand.index), 0, 3),
+ 4, 0)));
+ }
+ default:
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+ }
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_sbfx (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ uint32_t lsb, uint32_t width)
+{
+ return arm_emit_arm_insn (buf, (ARM_SBFX
+ | ENCODE (cond, 4, 28)
+ | ENCODE ((width - 1), 5, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (lsb, 5, 7)
+ | ENCODE (rn, 4, 0)));
+}
+
+/* See arm-insn-emit.h. */
+
+int
+arm_emit_arm_nop (uint32_t *buf, uint8_t cond)
+{
+ return arm_emit_arm_insn (buf, ARM_NOP | ENCODE (cond, 4, 28));
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_ubfx (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ uint8_t lsb, uint8_t width)
+{
+ return arm_emit_arm_insn (buf, (ARM_UBFX
+ | ENCODE (cond, 4, 28)
+ | ENCODE ((lsb + width - 1), 5, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (lsb, 5, 7)
+ | ENCODE (rn, 4, 0)));
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_sub (uint32_t *buf, uint8_t cond, uint8_t flags,
+ uint8_t rd, uint8_t rn, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_SUB, cond, flags,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_data_processing_imm (buf,
+ (ARM_SUB
+ /* Immediate. */
+ | ENCODE (1, 1, 25)
+ | ENCODE (flags, 1, 20)),
+ cond, rn,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.imm, 12, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_rsb (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_RSB, cond, 0,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_data_processing_imm (buf,
+ (ARM_RSB
+ /* Immediate. */
+ | ENCODE (1, 1, 25)
+ | ENCODE (0, 1, 20)),
+ cond, rn,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.imm, 12, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_sbc (uint32_t *buf, uint8_t cond, uint8_t flags, uint8_t rd,
+ uint8_t rn, struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_SBC, cond, flags,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int arm_emit_arm_mul (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_MUL, cond, 0,
+ (ENCODE (rd, 4, 16)
+ | ENCODE (operand.reg, 4, 8)
+ | ENCODE (rn, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_umull (uint32_t *buf, uint8_t cond, uint8_t rdlo, uint8_t rdhi,
+ uint8_t rn, uint8_t rm)
+{
+ return arm_emit_arm_data_processing_reg (buf, ARM_UMULL, cond, 0,
+ (ENCODE (rdhi, 4, 16)
+ | ENCODE (rdlo, 4, 12)
+ | ENCODE (rm, 4, 8)
+ | ENCODE (rn, 4, 0)));
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_lsl (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+
+ return arm_emit_arm_data_processing_reg (buf, ARM_LSL, cond, 0,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 8)
+ | ENCODE (rn, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_lsr (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+
+ return arm_emit_arm_data_processing_reg (buf, ARM_LSR, cond, 0,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 8)
+ | ENCODE (rn, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_asr (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_ASR, cond, 0,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 8)
+ /* Register op. */
+ | ENCODE (1, 1, 4)
+ | ENCODE (rn, 4, 0)));
+ }
+ else if (operand.type == OPERAND_IMMEDIATE)
+ {
+ return arm_emit_arm_data_processing_imm (buf,
+ (ARM_ASR
+ | ENCODE (0, 1, 20)
+ | ENCODE (rd, 4, 12)),
+ cond, 0,
+ (ENCODE (operand.imm, 5, 7)
+ | ENCODE (rn, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_and (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_AND, cond, 0,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_orr (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_ORR, cond, 0,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+int arm_emit_arm_orr_reg_shifted (uint32_t *buf, uint8_t cond, uint8_t rd,
+ uint8_t rn, uint8_t rm, uint8_t shift,
+ uint8_t rs)
+{
+ return arm_emit_arm_insn (buf, (ARM_ORR
+ | ENCODE (cond, 4, 28)
+ | ENCODE (0, 1, 20)
+ | ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (rs, 4, 8)
+ | ENCODE (shift, 2, 5)
+ | ENCODE (1, 1, 4)
+ | ENCODE (rm, 4, 0)));
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_eor (uint32_t *buf, uint8_t cond, uint8_t rd, uint8_t rn,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_EOR, cond, 0,
+ (ENCODE (rn, 4, 16)
+ | ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
+
+/* See arm-insn-emit.h */
+
+int
+arm_emit_arm_mvn (uint32_t *buf, uint8_t cond, uint8_t rd,
+ struct arm_operand operand)
+{
+ if (operand.type == OPERAND_REGISTER)
+ {
+ return arm_emit_arm_data_processing_reg (buf, ARM_MVN, cond, 0,
+ (ENCODE (rd, 4, 12)
+ | ENCODE (operand.reg, 4, 0)));
+ }
+ else
+ {
+ throw_error (NOT_SUPPORTED_ERROR,
+ _("Unimplemented instruction encoding."));
+ }
+}
diff --git a/gdb/arch/arm-insn-emit.h b/gdb/arch/arm-insn-emit.h
new file mode 100644
index 0000000..bcb216d
--- /dev/null
+++ b/gdb/arch/arm-insn-emit.h
@@ -0,0 +1,1087 @@
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#ifndef ARM_INSN_H
+#define ARM_INSN_H 1
+
+/* List of the ARM opcodes we need. */
+
+enum arm_opcodes
+ {
+ ARM_ADC = 0x00A00000,
+ ARM_ADD = 0x00800000,
+ ARM_AND = 0x00000000,
+ ARM_ASR = 0x01A00040,
+ ARM_B = 0x0A000000,
+ ARM_BIC = 0x03C00000,
+ ARM_BLX = 0x012FFF30,
+ ARM_CMP = 0x01500000,
+ ARM_DMB = 0xF57FF050,
+ ARM_EOR = 0x00200000,
+ ARM_LDR = 0x04100000,
+ ARM_LDRB = 0x04500000,
+ ARM_LDRH = 0x005000B0,
+ ARM_LDRD = 0x004000D0,
+ ARM_LDREX = 0x01900F9F,
+ ARM_LSL = 0x01A00010,
+ ARM_LSR = 0x01A00030,
+ ARM_MOV = 0x01A00000,
+ ARM_MOVT = 0x03400000,
+ ARM_MOVW = 0x03000000,
+ ARM_MRS = 0x010F0000,
+ ARM_MSR = 0x0120F000,
+ ARM_MUL = 0x00000090,
+ ARM_MVN = 0x01E00000,
+ ARM_NOP = 0x0320F000,
+ ARM_ORR = 0x01800000,
+ ARM_POP_A1 = 0x08BD0000,
+ ARM_POP_A2 = 0x049D0004,
+ ARM_PUSH_A1 = 0x092D0000,
+ ARM_PUSH_A2 = 0x052D0004,
+ ARM_RSB = 0x00600000,
+ ARM_SBC = 0x00C00000,
+ ARM_SBFX = 0x07A00050,
+ ARM_STR = 0x04000000,
+ ARM_STREX = 0x01800F90,
+ ARM_SUB = 0x00400000,
+ ARM_UBFX = 0x07E00050,
+ ARM_UMULL = 0x00800090,
+ ARM_VPOP = 0x0CBD0B00,
+ ARM_VPUSH = 0x0D2D0B00,
+ };
+
+/* List of the Thumb opcodes we need. */
+
+enum thumb_opcodes
+ {
+ THUMB_ADD_SP = 0xB000,
+ THUMB_BLX = 0x4780,
+ THUMB_B = 0xD000,
+ THUMB_BIC = 0xF0200000,
+ THUMB_BW = 0xF0008000,
+ THUMB_CMP = 0x2800,
+ THUMB_CMPW = 0xF1B00F00,
+ THUMB_DMB = 0xF3BF8F50,
+ THUMB_LDR = 0xF1A00000,
+ THUMB_LDREX = 0xE8500F00,
+ THUMB_MOVT = 0xF2C00000,
+ THUMB_MOVW = 0xF2400000,
+ THUMB_MOV = 0x4600,
+ THUMB_MRS = 0xF3EF8000,
+ THUMB_MSR = 0xF3808000,
+ THUMB_POP = 0xBC00,
+ THUMB_POPW = 0xE8BD0000,
+ THUMB_PUSH_T1 = 0xB400,
+ THUMB_PUSH_T2 = 0xE92D0000,
+ THUMB_SBFX = 0XF3400000,
+ THUMB_STR = 0x6000,
+ THUMB_STREX = 0xE8400000,
+ THUMB_VPOP = 0xECBD0B00,
+ THUMB_VPUSH = 0xED2D0B00,
+ };
+
+struct arm_operand
+{
+ /* Type of the operand. */
+ enum arm_operand_type type;
+
+ /* Value of the operand according to the type. */
+ union
+ {
+ uint32_t imm;
+ uint8_t reg;
+ struct arm_memory_operand mem;
+ };
+};
+
+enum arm_shifts
+ {
+ LSL = 0x0, /* Logical shift left. */
+ LSR = 0x1, /* Logical shift right. */
+ ASR = 0x2, /* Arithmetic shift right. */
+ };
+
+/* Helper function to create an immediate operand
+
+ Example:
+
+ p += emit_mov (p, r0, immediate_operand (12)); */
+
+struct arm_operand immediate_operand (uint32_t imm);
+
+/* Helper function to create a register operand.
+
+ Example:
+
+ p += emit_mov (p, r0, register_operand (r1)); */
+
+struct arm_operand register_operand (uint8_t reg);
+
+/* Helper function to create an memory operand.
+
+ Example:
+
+ p += emit_mov (p, r0, immediate_operand (12)); */
+
+struct arm_operand memory_operand (struct arm_memory_operand mem);
+
+/* Encode a register list bitfield, using a consecutive list of bits from
+ FROM with length LENGTH and using an inital value of INITIAL. Max 16
+ bits. */
+
+uint16_t encode_register_list (uint8_t from, uint8_t length, uint16_t initial);
+
+/* Return the distance in bytes from FROM to TO and adjusted for prefetch. */
+
+uint32_t arm_arm_branch_relative_distance (CORE_ADDR from, CORE_ADDR to);
+
+/* Return the distance in bytes from FROM to TO and adjusted for prefetch. */
+
+uint32_t arm_thumb_branch_relative_distance (CORE_ADDR from, CORE_ADDR to);
+
+/* Return the distance in bytes from FROM to TO , adjusted for prefetch
+ and for alignement when switching from ARM mode to Thumb mode. */
+
+uint32_t arm_thumb_to_arm_branch_relative_distance (CORE_ADDR from,
+ CORE_ADDR to);
+
+/* Return the offset is bytes adjusted for prefetch. */
+
+uint32_t arm_arm_branch_adjusted_offset (uint32_t offset);
+
+/* Return the offset in bytes adjusted for prefetch. */
+
+uint32_t arm_thumb_branch_adjusted_offset (uint32_t offset);
+
+/* Return whether it's possible to jump from FROM to TO using a relative
+ branch in arm mode. */
+
+int arm_arm_is_reachable (CORE_ADDR from, CORE_ADDR to);
+
+/* Return whether it's possible to jump from FROM to TO using a relative
+ branch in thumb mode. */
+
+int arm_thumb_is_reachable (CORE_ADDR from, CORE_ADDR to);
+
+/* Write arm instructions to move the 32bit value VAL into register REG. */
+
+int arm_emit_arm_mov_32 (uint32_t *mem, int reg, uint32_t val);
+
+/* Write thumb instructions to move the 32bit value VAL into register REG. */
+
+int arm_emit_thumb_mov_32 (uint16_t *mem, int reg, uint32_t val);
+
+/* Write an ARM B instruction into *BUF.
+
+ Encoding A1
+ ARMv4*, ARMv5T*, ARMv6*, ARMv7
+ B