+#if GDB_SELF_TEST
+namespace selftests {
+
+/* Provide both 16-bit and 32-bit thumb instructions. */
+
+class instruction_reader_thumb : public abstract_memory_reader
+{
+public:
+ template<size_t SIZE>
+ instruction_reader_thumb (enum bfd_endian endian,
+ const uint16_t (&insns)[SIZE])
+ : m_endian (endian), m_insns (insns), m_insns_size (SIZE)
+ {}
+
+ bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len) override
+ {
+ SELF_CHECK (len == 4 || len == 2);
+ SELF_CHECK (memaddr % 2 == 0);
+ SELF_CHECK ((memaddr / 2) < m_insns_size);
+
+ store_unsigned_integer (buf, 2, m_endian, m_insns[memaddr / 2]);
+ if (len == 4)
+ {
+ store_unsigned_integer (&buf[2], 2, m_endian,
+ m_insns[memaddr / 2 + 1]);
+ }
+ return true;
+ }
+
+private:
+ enum bfd_endian m_endian;
+ const uint16_t *m_insns;
+ size_t m_insns_size;
+};
+
+static void
+arm_record_test (void)
+{
+ struct gdbarch_info info;
+ gdbarch_info_init (&info);
+ info.bfd_arch_info = bfd_scan_arch ("arm");
+
+ struct gdbarch *gdbarch = gdbarch_find_by_info (info);
+
+ SELF_CHECK (gdbarch != NULL);
+
+ /* 16-bit Thumb instructions. */
+ {
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.gdbarch = gdbarch;
+
+ static const uint16_t insns[] = {
+ /* db b2 uxtb r3, r3 */
+ 0xb2db,
+ /* cd 58 ldr r5, [r1, r3] */
+ 0x58cd,
+ };
+
+ enum bfd_endian endian = gdbarch_byte_order_for_code (arm_record.gdbarch);
+ instruction_reader_thumb reader (endian, insns);
+ int ret = decode_insn (reader, &arm_record, THUMB_RECORD,
+ THUMB_INSN_SIZE_BYTES);
+
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 3);
+
+ arm_record.this_addr += 2;
+ ret = decode_insn (reader, &arm_record, THUMB_RECORD,
+ THUMB_INSN_SIZE_BYTES);
+
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 5);
+ }
+
+ /* 32-bit Thumb-2 instructions. */
+ {
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.gdbarch = gdbarch;
+
+ static const uint16_t insns[] = {
+ /* 1d ee 70 7f mrc 15, 0, r7, cr13, cr0, {3} */
+ 0xee1d, 0x7f70,
+ };
+
+ enum bfd_endian endian = gdbarch_byte_order_for_code (arm_record.gdbarch);
+ instruction_reader_thumb reader (endian, insns);
+ int ret = decode_insn (reader, &arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+
+ SELF_CHECK (ret == 0);
+ SELF_CHECK (arm_record.mem_rec_count == 0);
+ SELF_CHECK (arm_record.reg_rec_count == 1);
+ SELF_CHECK (arm_record.arm_regs[0] == 7);
+ }
+}
+} // namespace selftests
+#endif /* GDB_SELF_TEST */