+/* Mapping between the registers in `struct pt_regs'
+ format and GDB's register array layout. */
+
+static int m32r_pt_regs_offset[] = {
+ 4 * 4, /* r0 */
+ 4 * 5, /* r1 */
+ 4 * 6, /* r2 */
+ 4 * 7, /* r3 */
+ 4 * 0, /* r4 */
+ 4 * 1, /* r5 */
+ 4 * 2, /* r6 */
+ 4 * 8, /* r7 */
+ 4 * 9, /* r8 */
+ 4 * 10, /* r9 */
+ 4 * 11, /* r10 */
+ 4 * 12, /* r11 */
+ 4 * 13, /* r12 */
+ 4 * 24, /* fp */
+ 4 * 25, /* lr */
+ 4 * 23, /* sp */
+ 4 * 19, /* psw */
+ 4 * 19, /* cbr */
+ 4 * 26, /* spi */
+ 4 * 23, /* spu */
+ 4 * 22, /* bpc */
+ 4 * 20, /* pc */
+ 4 * 16, /* accl */
+ 4 * 15 /* acch */
+};
+
+#define PSW_OFFSET (4 * 19)
+#define BBPSW_OFFSET (4 * 21)
+#define SPU_OFFSET (4 * 23)
+#define SPI_OFFSET (4 * 26)
+
+#define M32R_LINUX_GREGS_SIZE (4 * 28)
+
+static void
+m32r_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *gregs, size_t size)
+{
+ const gdb_byte *regs = gregs;
+ enum bfd_endian byte_order =
+ gdbarch_byte_order (get_regcache_arch (regcache));
+ ULONGEST psw, bbpsw;
+ gdb_byte buf[4];
+ const gdb_byte *p;
+ int i;
+
+ psw = extract_unsigned_integer (regs + PSW_OFFSET, 4, byte_order);
+ bbpsw = extract_unsigned_integer (regs + BBPSW_OFFSET, 4, byte_order);
+ psw = ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);
+
+ for (i = 0; i < ARRAY_SIZE (m32r_pt_regs_offset); i++)
+ {
+ if (regnum != -1 && regnum != i)
+ continue;
+
+ switch (i)
+ {
+ case PSW_REGNUM:
+ store_unsigned_integer (buf, 4, byte_order, psw);
+ p = buf;
+ break;
+ case CBR_REGNUM:
+ store_unsigned_integer (buf, 4, byte_order, psw & 1);
+ p = buf;
+ break;
+ case M32R_SP_REGNUM:
+ p = regs + ((psw & 0x80) ? SPU_OFFSET : SPI_OFFSET);
+ break;
+ default:
+ p = regs + m32r_pt_regs_offset[i];
+ }
+
+ regcache_raw_supply (regcache, i, p);
+ }
+}
+
+static void
+m32r_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t size)