+ /* In frameless functions, there's no frame to destroy and thus
+ we don't care about the epilogue.
+
+ In functions with frame, the epilogue sequence is a pair of
+ a LM-type instruction that restores (amongst others) the
+ return register %r14 and the stack pointer %r15, followed
+ by a branch 'br %r14' --or equivalent-- that effects the
+ actual return.
+
+ In that situation, this function needs to return 'true' in
+ exactly one case: when pc points to that branch instruction.
+
+ Thus we try to disassemble the one instructions immediately
+ preceding pc and check whether it is an LM-type instruction
+ modifying the stack pointer.
+
+ Note that disassembling backwards is not reliable, so there
+ is a slight chance of false positives here ... */
+
+ bfd_byte insn[6];
+ unsigned int r1, r3, b2;
+ int d2;
+
+ if (word_size == 4
+ && !target_read_memory (pc - 4, insn, 4)
+ && is_rs (insn, op_lm, &r1, &r3, &d2, &b2)
+ && r3 == S390_SP_REGNUM - S390_R0_REGNUM)
+ return 1;
+
+ if (word_size == 4
+ && !target_read_memory (pc - 6, insn, 6)
+ && is_rsy (insn, op1_lmy, op2_lmy, &r1, &r3, &d2, &b2)
+ && r3 == S390_SP_REGNUM - S390_R0_REGNUM)
+ return 1;
+
+ if (word_size == 8
+ && !target_read_memory (pc - 6, insn, 6)
+ && is_rsy (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2)
+ && r3 == S390_SP_REGNUM - S390_R0_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+/* Implement unwind_pc gdbarch method. */
+
+static CORE_ADDR
+s390_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ULONGEST pc;
+ pc = frame_unwind_register_unsigned (next_frame, tdep->pc_regnum);
+ return gdbarch_addr_bits_remove (gdbarch, pc);
+}
+
+/* Implement unwind_sp gdbarch method. */
+
+static CORE_ADDR
+s390_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ ULONGEST sp;
+ sp = frame_unwind_register_unsigned (next_frame, S390_SP_REGNUM);
+ return gdbarch_addr_bits_remove (gdbarch, sp);
+}
+
+/* Helper routine to unwind pseudo registers. */
+
+static struct value *
+s390_unwind_pseudo_register (struct frame_info *this_frame, int regnum)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ struct type *type = register_type (gdbarch, regnum);
+
+ /* Unwind PC via PSW address. */
+ if (regnum == tdep->pc_regnum)
+ {
+ struct value *val;
+
+ val = frame_unwind_register_value (this_frame, S390_PSWA_REGNUM);
+ if (!value_optimized_out (val))
+ {
+ LONGEST pswa = value_as_long (val);
+
+ if (TYPE_LENGTH (type) == 4)
+ return value_from_pointer (type, pswa & 0x7fffffff);
+ else
+ return value_from_pointer (type, pswa);
+ }
+ }
+
+ /* Unwind CC via PSW mask. */
+ if (regnum == tdep->cc_regnum)
+ {
+ struct value *val;
+
+ val = frame_unwind_register_value (this_frame, S390_PSWM_REGNUM);
+ if (!value_optimized_out (val))
+ {
+ LONGEST pswm = value_as_long (val);
+
+ if (TYPE_LENGTH (type) == 4)
+ return value_from_longest (type, (pswm >> 12) & 3);
+ else
+ return value_from_longest (type, (pswm >> 44) & 3);
+ }
+ }
+
+ /* Unwind full GPRs to show at least the lower halves (as the
+ upper halves are undefined). */
+ if (regnum_is_gpr_full (tdep, regnum))
+ {
+ int reg = regnum - tdep->gpr_full_regnum;
+ struct value *val;
+
+ val = frame_unwind_register_value (this_frame, S390_R0_REGNUM + reg);
+ if (!value_optimized_out (val))
+ return value_cast (type, val);
+ }
+
+ return allocate_optimized_out_value (type);
+}
+
+/* Translate a .eh_frame register to DWARF register, or adjust a
+ .debug_frame register. */
+
+static int
+s390_adjust_frame_regnum (struct gdbarch *gdbarch, int num, int eh_frame_p)
+{
+ /* See s390_dwarf_reg_to_regnum for comments. */
+ return (num >= 0 && num < 16) ? num + s390_dwarf_reg_r0l : num;
+}
+
+/* DWARF-2 frame unwinding. */
+
+/* Function to unwind a pseudo-register in dwarf2_frame unwinder. Used by
+ s390_dwarf2_frame_init_reg. */
+
+static struct value *
+s390_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
+ int regnum)
+{
+ return s390_unwind_pseudo_register (this_frame, regnum);
+}
+
+/* Implement init_reg dwarf2_frame method. */
+
+static void
+s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ struct dwarf2_frame_state_reg *reg,
+ struct frame_info *this_frame)
+{
+ /* The condition code (and thus PSW mask) is call-clobbered. */
+ if (regnum == S390_PSWM_REGNUM)
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+
+ /* The PSW address unwinds to the return address. */
+ else if (regnum == S390_PSWA_REGNUM)
+ reg->how = DWARF2_FRAME_REG_RA;
+
+ /* Fixed registers are call-saved or call-clobbered
+ depending on the ABI in use. */
+ else if (regnum < S390_NUM_REGS)
+ {
+ if (s390_register_call_saved (gdbarch, regnum))
+ reg->how = DWARF2_FRAME_REG_SAME_VALUE;
+ else
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+ }
+
+ /* We install a special function to unwind pseudos. */
+ else
+ {
+ reg->how = DWARF2_FRAME_REG_FN;
+ reg->loc.fn = s390_dwarf2_prev_register;
+ }
+}
+
+/* Frame unwinding. */
+
+/* Wrapper for trad_frame_get_prev_register to allow for s390 pseudo
+ register translation. */
+
+struct value *
+s390_trad_frame_prev_register (struct frame_info *this_frame,
+ struct trad_frame_saved_reg saved_regs[],
+ int regnum)
+{
+ if (regnum < S390_NUM_REGS)
+ return trad_frame_get_prev_register (this_frame, saved_regs, regnum);
+ else
+ return s390_unwind_pseudo_register (this_frame, regnum);
+}
+
+/* Normal stack frames. */
+
+struct s390_unwind_cache {
+
+ CORE_ADDR func;
+ CORE_ADDR frame_base;
+ CORE_ADDR local_base;
+
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Unwind THIS_FRAME and write the information into unwind cache INFO using
+ prologue analysis. Helper for s390_frame_unwind_cache. */
+
+static int
+s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
+ struct s390_unwind_cache *info)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int word_size = gdbarch_ptr_bit (gdbarch) / 8;
+ struct s390_prologue_data data;
+ pv_t *fp = &data.gpr[S390_FRAME_REGNUM - S390_R0_REGNUM];
+ pv_t *sp = &data.gpr[S390_SP_REGNUM - S390_R0_REGNUM];
+ int i;
+ CORE_ADDR cfa;
+ CORE_ADDR func;
+ CORE_ADDR result;
+ ULONGEST reg;
+ CORE_ADDR prev_sp;
+ int frame_pointer;
+ int size;
+ struct frame_info *next_frame;
+
+ /* Try to find the function start address. If we can't find it, we don't
+ bother searching for it -- with modern compilers this would be mostly
+ pointless anyway. Trust that we'll either have valid DWARF-2 CFI data
+ or else a valid backchain ... */
+ if (!get_frame_func_if_available (this_frame, &info->func))
+ {
+ info->func = -1;
+ return 0;
+ }
+ func = info->func;
+
+ /* Try to analyze the prologue. */
+ result = s390_analyze_prologue (gdbarch, func,
+ get_frame_pc (this_frame), &data);
+ if (!result)
+ return 0;
+
+ /* If this was successful, we should have found the instruction that
+ sets the stack pointer register to the previous value of the stack
+ pointer minus the frame size. */
+ if (!pv_is_register (*sp, S390_SP_REGNUM))
+ return 0;
+
+ /* A frame size of zero at this point can mean either a real
+ frameless function, or else a failure to find the prologue.
+ Perform some sanity checks to verify we really have a
+ frameless function. */
+ if (sp->k == 0)
+ {
+ /* If the next frame is a NORMAL_FRAME, this frame *cannot* have frame
+ size zero. This is only possible if the next frame is a sentinel
+ frame, a dummy frame, or a signal trampoline frame. */
+ /* FIXME: cagney/2004-05-01: This sanity check shouldn't be
+ needed, instead the code should simpliy rely on its
+ analysis. */
+ next_frame = get_next_frame (this_frame);
+ while (next_frame && get_frame_type (next_frame) == INLINE_FRAME)
+ next_frame = get_next_frame (next_frame);
+ if (next_frame
+ && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
+ return 0;
+
+ /* If we really have a frameless function, %r14 must be valid
+ -- in particular, it must point to a different function. */
+ reg = get_frame_register_unsigned (this_frame, S390_RETADDR_REGNUM);
+ reg = gdbarch_addr_bits_remove (gdbarch, reg) - 1;
+ if (get_pc_function_start (reg) == func)
+ {
+ /* However, there is one case where it *is* valid for %r14
+ to point to the same function -- if this is a recursive
+ call, and we have stopped in the prologue *before* the
+ stack frame was allocated.
+
+ Recognize this case by looking ahead a bit ... */
+
+ struct s390_prologue_data data2;
+ pv_t *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM];
+
+ if (!(s390_analyze_prologue (gdbarch, func, (CORE_ADDR)-1, &data2)
+ && pv_is_register (*sp, S390_SP_REGNUM)
+ && sp->k != 0))
+ return 0;
+ }
+ }
+
+ /* OK, we've found valid prologue data. */
+ size = -sp->k;
+
+ /* If the frame pointer originally also holds the same value
+ as the stack pointer, we're probably using it. If it holds
+ some other value -- even a constant offset -- it is most
+ likely used as temp register. */
+ if (pv_is_identical (*sp, *fp))
+ frame_pointer = S390_FRAME_REGNUM;
+ else
+ frame_pointer = S390_SP_REGNUM;
+
+ /* If we've detected a function with stack frame, we'll still have to
+ treat it as frameless if we're currently within the function epilog
+ code at a point where the frame pointer has already been restored.
+ This can only happen in an innermost frame. */
+ /* FIXME: cagney/2004-05-01: This sanity check shouldn't be needed,
+ instead the code should simpliy rely on its analysis. */
+ next_frame = get_next_frame (this_frame);
+ while (next_frame && get_frame_type (next_frame) == INLINE_FRAME)
+ next_frame = get_next_frame (next_frame);
+ if (size > 0
+ && (next_frame == NULL
+ || get_frame_type (get_next_frame (this_frame)) != NORMAL_FRAME))
+ {
+ /* See the comment in s390_stack_frame_destroyed_p on why this is
+ not completely reliable ... */
+ if (s390_stack_frame_destroyed_p (gdbarch, get_frame_pc (this_frame)))
+ {
+ memset (&data, 0, sizeof (data));
+ size = 0;
+ frame_pointer = S390_SP_REGNUM;
+ }
+ }
+
+ /* Once we know the frame register and the frame size, we can unwind
+ the current value of the frame register from the next frame, and
+ add back the frame size to arrive that the previous frame's
+ stack pointer value. */
+ prev_sp = get_frame_register_unsigned (this_frame, frame_pointer) + size;
+ cfa = prev_sp + 16*word_size + 32;
+
+ /* Set up ABI call-saved/call-clobbered registers. */
+ for (i = 0; i < S390_NUM_REGS; i++)
+ if (!s390_register_call_saved (gdbarch, i))
+ trad_frame_set_unknown (info->saved_regs, i);
+
+ /* CC is always call-clobbered. */
+ trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
+
+ /* Record the addresses of all register spill slots the prologue parser
+ has recognized. Consider only registers defined as call-saved by the
+ ABI; for call-clobbered registers the parser may have recognized
+ spurious stores. */
+
+ for (i = 0; i < 16; i++)
+ if (s390_register_call_saved (gdbarch, S390_R0_REGNUM + i)
+ && data.gpr_slot[i] != 0)
+ info->saved_regs[S390_R0_REGNUM + i].addr = cfa - data.gpr_slot[i];
+
+ for (i = 0; i < 16; i++)
+ if (s390_register_call_saved (gdbarch, S390_F0_REGNUM + i)
+ && data.fpr_slot[i] != 0)
+ info->saved_regs[S390_F0_REGNUM + i].addr = cfa - data.fpr_slot[i];
+
+ /* Function return will set PC to %r14. */
+ info->saved_regs[S390_PSWA_REGNUM] = info->saved_regs[S390_RETADDR_REGNUM];
+
+ /* In frameless functions, we unwind simply by moving the return
+ address to the PC. However, if we actually stored to the
+ save area, use that -- we might only think the function frameless
+ because we're in the middle of the prologue ... */
+ if (size == 0
+ && !trad_frame_addr_p (info->saved_regs, S390_PSWA_REGNUM))
+ {
+ info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
+ }
+
+ /* Another sanity check: unless this is a frameless function,
+ we should have found spill slots for SP and PC.
+ If not, we cannot unwind further -- this happens e.g. in
+ libc's thread_start routine. */
+ if (size > 0)
+ {
+ if (!trad_frame_addr_p (info->saved_regs, S390_SP_REGNUM)
+ || !trad_frame_addr_p (info->saved_regs, S390_PSWA_REGNUM))
+ prev_sp = -1;
+ }
+
+ /* We use the current value of the frame register as local_base,
+ and the top of the register save area as frame_base. */
+ if (prev_sp != -1)
+ {
+ info->frame_base = prev_sp + 16*word_size + 32;
+ info->local_base = prev_sp - size;
+ }
+
+ return 1;
+}
+
+/* Unwind THIS_FRAME and write the information into unwind cache INFO using
+ back chain unwinding. Helper for s390_frame_unwind_cache. */
+
+static void
+s390_backchain_frame_unwind_cache (struct frame_info *this_frame,
+ struct s390_unwind_cache *info)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int word_size = gdbarch_ptr_bit (gdbarch) / 8;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ CORE_ADDR backchain;
+ ULONGEST reg;
+ LONGEST sp, tmp;
+ int i;
+
+ /* Set up ABI call-saved/call-clobbered registers. */
+ for (i = 0; i < S390_NUM_REGS; i++)
+ if (!s390_register_call_saved (gdbarch, i))
+ trad_frame_set_unknown (info->saved_regs, i);
+
+ /* CC is always call-clobbered. */
+ trad_frame_set_unknown (info->saved_regs, S390_PSWM_REGNUM);
+
+ /* Get the backchain. */
+ reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
+ if (!safe_read_memory_integer (reg, word_size, byte_order, &tmp))
+ tmp = 0;
+ backchain = (CORE_ADDR) tmp;
+
+ /* A zero backchain terminates the frame chain. As additional
+ sanity check, let's verify that the spill slot for SP in the
+ save area pointed to by the backchain in fact links back to
+ the save area. */
+ if (backchain != 0
+ && safe_read_memory_integer (backchain + 15*word_size,
+ word_size, byte_order, &sp)
+ && (CORE_ADDR)sp == backchain)
+ {
+ /* We don't know which registers were saved, but it will have
+ to be at least %r14 and %r15. This will allow us to continue
+ unwinding, but other prev-frame registers may be incorrect ... */
+ info->saved_regs[S390_SP_REGNUM].addr = backchain + 15*word_size;
+ info->saved_regs[S390_RETADDR_REGNUM].addr = backchain + 14*word_size;
+
+ /* Function return will set PC to %r14. */
+ info->saved_regs[S390_PSWA_REGNUM]
+ = info->saved_regs[S390_RETADDR_REGNUM];
+
+ /* We use the current value of the frame register as local_base,
+ and the top of the register save area as frame_base. */
+ info->frame_base = backchain + 16*word_size + 32;
+ info->local_base = reg;
+ }
+
+ info->func = get_frame_pc (this_frame);
+}
+
+/* Unwind THIS_FRAME and return the corresponding unwind cache for
+ s390_frame_unwind and s390_frame_base. */
+
+static struct s390_unwind_cache *
+s390_frame_unwind_cache (struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ struct s390_unwind_cache *info;
+
+ if (*this_prologue_cache)
+ return (struct s390_unwind_cache *) *this_prologue_cache;
+
+ info = FRAME_OBSTACK_ZALLOC (struct s390_unwind_cache);
+ *this_prologue_cache = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+ info->func = -1;
+ info->frame_base = -1;
+ info->local_base = -1;
+
+ TRY
+ {
+ /* Try to use prologue analysis to fill the unwind cache.
+ If this fails, fall back to reading the stack backchain. */
+ if (!s390_prologue_frame_unwind_cache (this_frame, info))
+ s390_backchain_frame_unwind_cache (this_frame, info);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ if (ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+ }
+ END_CATCH
+
+ return info;
+}
+
+/* Implement this_id frame_unwind method for s390_frame_unwind. */
+
+static void
+s390_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
+{
+ struct s390_unwind_cache *info
+ = s390_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ if (info->frame_base == -1)
+ {
+ if (info->func != -1)
+ *this_id = frame_id_build_unavailable_stack (info->func);
+ return;
+ }
+
+ *this_id = frame_id_build (info->frame_base, info->func);
+}
+
+/* Implement prev_register frame_unwind method for s390_frame_unwind. */
+
+static struct value *
+s390_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct s390_unwind_cache *info
+ = s390_frame_unwind_cache (this_frame, this_prologue_cache);
+
+ return s390_trad_frame_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+/* Default S390 frame unwinder. */
+
+static const struct frame_unwind s390_frame_unwind = {
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ s390_frame_this_id,
+ s390_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+/* Code stubs and their stack frames. For things like PLTs and NULL
+ function calls (where there is no true frame and the return address
+ is in the RETADDR register). */
+
+struct s390_stub_unwind_cache
+{
+ CORE_ADDR frame_base;
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Unwind THIS_FRAME and return the corresponding unwind cache for
+ s390_stub_frame_unwind. */
+
+static struct s390_stub_unwind_cache *
+s390_stub_frame_unwind_cache (struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int word_size = gdbarch_ptr_bit (gdbarch) / 8;
+ struct s390_stub_unwind_cache *info;
+ ULONGEST reg;
+
+ if (*this_prologue_cache)
+ return (struct s390_stub_unwind_cache *) *this_prologue_cache;
+
+ info = FRAME_OBSTACK_ZALLOC (struct s390_stub_unwind_cache);
+ *this_prologue_cache = info;
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ /* The return address is in register %r14. */
+ info->saved_regs[S390_PSWA_REGNUM].realreg = S390_RETADDR_REGNUM;
+
+ /* Retrieve stack pointer and determine our frame base. */
+ reg = get_frame_register_unsigned (this_frame, S390_SP_REGNUM);
+ info->frame_base = reg + 16*word_size + 32;
+
+ return info;
+}
+
+/* Implement this_id frame_unwind method for s390_stub_frame_unwind. */
+
+static void
+s390_stub_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
+{
+ struct s390_stub_unwind_cache *info
+ = s390_stub_frame_unwind_cache (this_frame, this_prologue_cache);
+ *this_id = frame_id_build (info->frame_base, get_frame_pc (this_frame));
+}
+
+/* Implement prev_register frame_unwind method for s390_stub_frame_unwind. */
+
+static struct value *
+s390_stub_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct s390_stub_unwind_cache *info
+ = s390_stub_frame_unwind_cache (this_frame, this_prologue_cache);
+ return s390_trad_frame_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+/* Implement sniffer frame_unwind method for s390_stub_frame_unwind. */
+
+static int
+s390_stub_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_prologue_cache)
+{
+ CORE_ADDR addr_in_block;
+ bfd_byte insn[S390_MAX_INSTR_SIZE];
+
+ /* If the current PC points to non-readable memory, we assume we
+ have trapped due to an invalid function pointer call. We handle
+ the non-existing current function like a PLT stub. */
+ addr_in_block = get_frame_address_in_block (this_frame);
+ if (in_plt_section (addr_in_block)
+ || s390_readinstruction (insn, get_frame_pc (this_frame)) < 0)
+ return 1;
+ return 0;
+}
+
+/* S390 stub frame unwinder. */
+
+static const struct frame_unwind s390_stub_frame_unwind = {
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ s390_stub_frame_this_id,
+ s390_stub_frame_prev_register,
+ NULL,
+ s390_stub_frame_sniffer
+};
+
+/* Frame base handling. */
+
+static CORE_ADDR
+s390_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct s390_unwind_cache *info
+ = s390_frame_unwind_cache (this_frame, this_cache);
+ return info->frame_base;
+}
+
+static CORE_ADDR
+s390_local_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct s390_unwind_cache *info
+ = s390_frame_unwind_cache (this_frame, this_cache);
+ return info->local_base;
+}
+
+static const struct frame_base s390_frame_base = {
+ &s390_frame_unwind,
+ s390_frame_base_address,
+ s390_local_base_address,
+ s390_local_base_address
+};
+
+/* Process record-replay */
+
+/* Takes the intermediate sum of address calculations and masks off upper
+ bits according to current addressing mode. */
+
+static CORE_ADDR
+s390_record_address_mask (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR val)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ULONGEST pswm, pswa;
+ int am;
+ if (tdep->abi == ABI_LINUX_S390)
+ {
+ regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &pswa);
+ am = pswa >> 31 & 1;
+ }
+ else
+ {
+ regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &pswm);
+ am = pswm >> 31 & 3;
+ }
+ switch (am)
+ {
+ case 0:
+ return val & 0xffffff;
+ case 1:
+ return val & 0x7fffffff;
+ case 3:
+ return val;
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Addressing mode %d used.", am);
+ return 0;
+ }
+}
+
+/* Calculates memory address using pre-calculated index, raw instruction word
+ with b and d/dl fields, and raw instruction byte with dh field. Index and
+ dh should be set to 0 if unused. */
+
+static CORE_ADDR
+s390_record_calc_disp_common (struct gdbarch *gdbarch, struct regcache *regcache,
+ ULONGEST x, uint16_t bd, int8_t dh)
+{
+ uint8_t rb = bd >> 12 & 0xf;
+ int32_t d = (bd & 0xfff) | ((int32_t)dh << 12);
+ ULONGEST b;
+ CORE_ADDR res = d + x;
+ if (rb)
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + rb, &b);
+ res += b;
+ }
+ return s390_record_address_mask (gdbarch, regcache, res);
+}
+
+/* Calculates memory address using raw x, b + d/dl, dh fields from
+ instruction. rx and dh should be set to 0 if unused. */
+
+static CORE_ADDR
+s390_record_calc_disp (struct gdbarch *gdbarch, struct regcache *regcache,
+ uint8_t rx, uint16_t bd, int8_t dh)
+{
+ ULONGEST x = 0;
+ if (rx)
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + rx, &x);
+ return s390_record_calc_disp_common (gdbarch, regcache, x, bd, dh);
+}
+
+/* Calculates memory address for VSCE[GF] instructions. */
+
+static int
+s390_record_calc_disp_vsce (struct gdbarch *gdbarch, struct regcache *regcache,
+ uint8_t vx, uint8_t el, uint8_t es, uint16_t bd,
+ int8_t dh, CORE_ADDR *res)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ ULONGEST x;
+ gdb_byte buf[16];
+ if (tdep->v0_full_regnum == -1 || el * es >= 16)
+ return -1;
+ if (vx < 16)
+ regcache->cooked_read (tdep->v0_full_regnum + vx, buf);
+ else
+ regcache->raw_read (S390_V16_REGNUM + vx - 16, buf);
+ x = extract_unsigned_integer (buf + el * es, es, byte_order);
+ *res = s390_record_calc_disp_common (gdbarch, regcache, x, bd, dh);
+ return 0;
+}
+
+/* Calculates memory address for instructions with relative long addressing. */
+
+static CORE_ADDR
+s390_record_calc_rl (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint16_t i1, uint16_t i2)
+{
+ int32_t ri = i1 << 16 | i2;
+ return s390_record_address_mask (gdbarch, regcache, addr + (LONGEST)ri * 2);
+}
+
+/* Population count helper. */
+
+static int s390_popcnt (unsigned int x) {
+ int res = 0;
+ while (x)
+ {
+ if (x & 1)
+ res++;
+ x >>= 1;
+ }
+ return res;
+}
+
+/* Record 64-bit register. */
+
+static int
+s390_record_gpr_g (struct gdbarch *gdbarch, struct regcache *regcache, int i)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + i))
+ return -1;
+ if (tdep->abi == ABI_LINUX_S390)
+ if (record_full_arch_list_add_reg (regcache, S390_R0_UPPER_REGNUM + i))
+ return -1;
+ return 0;
+}
+
+/* Record high 32 bits of a register. */
+
+static int
+s390_record_gpr_h (struct gdbarch *gdbarch, struct regcache *regcache, int i)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (tdep->abi == ABI_LINUX_S390)
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_R0_UPPER_REGNUM + i))
+ return -1;
+ }
+ else
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + i))
+ return -1;
+ }
+ return 0;
+}
+
+/* Record vector register. */
+
+static int
+s390_record_vr (struct gdbarch *gdbarch, struct regcache *regcache, int i)
+{
+ if (i < 16)
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + i))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_V0_LOWER_REGNUM + i))
+ return -1;
+ }
+ else
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_V16_REGNUM + i - 16))
+ return -1;
+ }
+ return 0;
+}
+
+/* Implement process_record gdbarch method. */
+
+static int
+s390_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ uint16_t insn[3] = {0};
+ /* Instruction as bytes. */
+ uint8_t ibyte[6];
+ /* Instruction as nibbles. */
+ uint8_t inib[12];
+ /* Instruction vector registers. */
+ uint8_t ivec[4];
+ CORE_ADDR oaddr, oaddr2, oaddr3;
+ ULONGEST tmp;
+ int i, n;
+ /* if EX/EXRL instruction used, here's the reg parameter */
+ int ex = -1;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+ /* Attempting to use EX or EXRL jumps back here */
+ex:
+
+ /* Read instruction. */
+ insn[0] = read_memory_unsigned_integer (addr, 2, byte_order);
+ /* If execute was involved, do the adjustment. */
+ if (ex != -1)
+ insn[0] |= ex & 0xff;
+ /* Two highest bits determine instruction size. */
+ if (insn[0] >= 0x4000)
+ insn[1] = read_memory_unsigned_integer (addr+2, 2, byte_order);
+ else
+ /* Not necessary, but avoids uninitialized variable warnings. */
+ insn[1] = 0;
+ if (insn[0] >= 0xc000)
+ insn[2] = read_memory_unsigned_integer (addr+4, 2, byte_order);
+ else
+ insn[2] = 0;
+ /* Split instruction into bytes and nibbles. */
+ for (i = 0; i < 3; i++)
+ {
+ ibyte[i*2] = insn[i] >> 8 & 0xff;
+ ibyte[i*2+1] = insn[i] & 0xff;
+ }
+ for (i = 0; i < 6; i++)
+ {
+ inib[i*2] = ibyte[i] >> 4 & 0xf;
+ inib[i*2+1] = ibyte[i] & 0xf;
+ }
+ /* Compute vector registers, if applicable. */
+ ivec[0] = (inib[9] >> 3 & 1) << 4 | inib[2];
+ ivec[1] = (inib[9] >> 2 & 1) << 4 | inib[3];
+ ivec[2] = (inib[9] >> 1 & 1) << 4 | inib[4];
+ ivec[3] = (inib[9] >> 0 & 1) << 4 | inib[8];
+
+ switch (ibyte[0])
+ {
+ /* 0x00 undefined */
+
+ case 0x01:
+ /* E-format instruction */
+ switch (ibyte[1])
+ {
+ /* 0x00 undefined */
+ /* 0x01 unsupported: PR - program return */
+ /* 0x02 unsupported: UPT */
+ /* 0x03 undefined */
+ /* 0x04 privileged: PTFF - perform timing facility function */
+ /* 0x05-0x06 undefined */
+ /* 0x07 privileged: SCKPF - set clock programmable field */
+ /* 0x08-0x09 undefined */
+
+ case 0x0a: /* PFPO - perform floating point operation */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ if (!(tmp & 0x80000000u))
+ {
+ uint8_t ofc = tmp >> 16 & 0xff;
+ switch (ofc)
+ {
+ case 0x00: /* HFP32 */
+ case 0x01: /* HFP64 */
+ case 0x05: /* BFP32 */
+ case 0x06: /* BFP64 */
+ case 0x08: /* DFP32 */
+ case 0x09: /* DFP64 */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM))
+ return -1;
+ break;
+ case 0x02: /* HFP128 */
+ case 0x07: /* BFP128 */
+ case 0x0a: /* DFP128 */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F2_REGNUM))
+ return -1;
+ break;
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown PFPO OFC %02x at %s.\n",
+ ofc, paddress (gdbarch, addr));
+ return -1;
+ }
+
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_R1_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x0b: /* TAM - test address mode */
+ case 0x0c: /* SAM24 - set address mode 24 */
+ case 0x0d: /* SAM31 - set address mode 31 */
+ case 0x0e: /* SAM64 - set address mode 64 */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0x0f-0xfe undefined */
+
+ /* 0xff unsupported: TRAP */
+
+ default:
+ goto UNKNOWN_OP;
+ }
+ break;
+
+ /* 0x02 undefined */
+ /* 0x03 undefined */
+
+ case 0x04: /* SPM - set program mask */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x05: /* BALR - branch and link */
+ case 0x45: /* BAL - branch and link */
+ case 0x06: /* BCTR - branch on count */
+ case 0x46: /* BCT - branch on count */
+ case 0x0d: /* BASR - branch and save */
+ case 0x4d: /* BAS - branch and save */
+ case 0x84: /* BRXH - branch relative on index high */
+ case 0x85: /* BRXLE - branch relative on index low or equal */
+ case 0x86: /* BXH - branch on index high */
+ case 0x87: /* BXLE - branch on index low or equal */
+ /* BA[SL]* use native-size destination for linkage info, BCT*, BRX*, BX*
+ use 32-bit destination as counter. */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ case 0x07: /* BCR - branch on condition */
+ case 0x47: /* BC - branch on condition */
+ /* No effect other than PC transfer. */
+ break;
+
+ /* 0x08 undefined */
+ /* 0x09 undefined */
+
+ case 0x0a:
+ /* SVC - supervisor call */
+ if (tdep->s390_syscall_record != NULL)
+ {
+ if (tdep->s390_syscall_record (regcache, ibyte[1]))
+ return -1;
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ break;
+
+ case 0x0b: /* BSM - branch and set mode */
+ if (inib[2])
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x0c: /* BASSM - branch and save and set mode */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x0e: /* MVCL - move long [interruptible] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[2], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[2] | 1), &tmp);
+ tmp &= 0xffffff;
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[3]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[3] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x0f: /* CLCL - compare logical long [interruptible] */
+ case 0xa9: /* CLCLE - compare logical long extended [partial] */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[3]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[3] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x10: /* LPR - load positive */
+ case 0x11: /* LNR - load negative */
+ case 0x12: /* LTR - load and test */
+ case 0x13: /* LCR - load complement */
+ case 0x14: /* NR - and */
+ case 0x16: /* OR - or */
+ case 0x17: /* XR - xor */
+ case 0x1a: /* AR - add */
+ case 0x1b: /* SR - subtract */
+ case 0x1e: /* ALR - add logical */
+ case 0x1f: /* SLR - subtract logical */
+ case 0x54: /* N - and */
+ case 0x56: /* O - or */
+ case 0x57: /* X - xor */
+ case 0x5a: /* A - add */
+ case 0x5b: /* S - subtract */
+ case 0x5e: /* AL - add logical */
+ case 0x5f: /* SL - subtract logical */
+ case 0x4a: /* AH - add halfword */
+ case 0x4b: /* SH - subtract halfword */
+ case 0x8a: /* SRA - shift right single */
+ case 0x8b: /* SLA - shift left single */
+ case 0xbf: /* ICM - insert characters under mask */
+ /* 32-bit destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x15: /* CLR - compare logical */
+ case 0x55: /* CL - compare logical */
+ case 0x19: /* CR - compare */
+ case 0x29: /* CDR - compare */
+ case 0x39: /* CER - compare */
+ case 0x49: /* CH - compare halfword */
+ case 0x59: /* C - compare */
+ case 0x69: /* CD - compare */
+ case 0x79: /* CE - compare */
+ case 0x91: /* TM - test under mask */
+ case 0x95: /* CLI - compare logical */
+ case 0xbd: /* CLM - compare logical under mask */
+ case 0xd5: /* CLC - compare logical */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x18: /* LR - load */
+ case 0x48: /* LH - load halfword */
+ case 0x58: /* L - load */
+ case 0x41: /* LA - load address */
+ case 0x43: /* IC - insert character */
+ case 0x4c: /* MH - multiply halfword */
+ case 0x71: /* MS - multiply single */
+ case 0x88: /* SRL - shift right single logical */
+ case 0x89: /* SLL - shift left single logical */
+ /* 32-bit, 8-bit (IC), or native width (LA) destination, no flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ case 0x1c: /* MR - multiply */
+ case 0x5c: /* M - multiply */
+ case 0x1d: /* DR - divide */
+ case 0x5d: /* D - divide */
+ case 0x8c: /* SRDL - shift right double logical */
+ case 0x8d: /* SLDL - shift left double logical */
+ /* 32-bit pair destination, no flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ break;
+
+ case 0x20: /* LPDR - load positive */
+ case 0x30: /* LPER - load positive */
+ case 0x21: /* LNDR - load negative */
+ case 0x31: /* LNER - load negative */
+ case 0x22: /* LTDR - load and test */
+ case 0x32: /* LTER - load and test */
+ case 0x23: /* LCDR - load complement */
+ case 0x33: /* LCER - load complement */
+ case 0x2a: /* ADR - add */
+ case 0x3a: /* AER - add */
+ case 0x6a: /* AD - add */
+ case 0x7a: /* AE - add */
+ case 0x2b: /* SDR - subtract */
+ case 0x3b: /* SER - subtract */
+ case 0x6b: /* SD - subtract */
+ case 0x7b: /* SE - subtract */
+ case 0x2e: /* AWR - add unnormalized */
+ case 0x3e: /* AUR - add unnormalized */
+ case 0x6e: /* AW - add unnormalized */
+ case 0x7e: /* AU - add unnormalized */
+ case 0x2f: /* SWR - subtract unnormalized */
+ case 0x3f: /* SUR - subtract unnormalized */
+ case 0x6f: /* SW - subtract unnormalized */
+ case 0x7f: /* SU - subtract unnormalized */
+ /* float destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x24: /* HDR - halve */
+ case 0x34: /* HER - halve */
+ case 0x25: /* LDXR - load rounded */
+ case 0x35: /* LEDR - load rounded */
+ case 0x28: /* LDR - load */
+ case 0x38: /* LER - load */
+ case 0x68: /* LD - load */
+ case 0x78: /* LE - load */
+ case 0x2c: /* MDR - multiply */
+ case 0x3c: /* MDER - multiply */
+ case 0x6c: /* MD - multiply */
+ case 0x7c: /* MDE - multiply */
+ case 0x2d: /* DDR - divide */
+ case 0x3d: /* DER - divide */
+ case 0x6d: /* DD - divide */
+ case 0x7d: /* DE - divide */
+ /* float destination, no flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ case 0x26: /* MXR - multiply */
+ case 0x27: /* MXDR - multiply */
+ case 0x67: /* MXD - multiply */
+ /* float pair destination, no flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[2] | 2)))
+ return -1;
+ break;
+
+ case 0x36: /* AXR - add */
+ case 0x37: /* SXR - subtract */
+ /* float pair destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[2] | 2)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x40: /* STH - store halfword */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 2))
+ return -1;
+ break;
+
+ case 0x42: /* STC - store character */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 1))
+ return -1;
+ break;
+
+ case 0x44: /* EX - execute */
+ if (ex != -1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Warning: Double execute at %s.\n",
+ paddress (gdbarch, addr));
+ return -1;
+ }
+ addr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
+ if (inib[2])
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[2], &tmp);
+ ex = tmp & 0xff;
+ }
+ else
+ {
+ ex = 0;
+ }
+ goto ex;
+
+ case 0x4e: /* CVD - convert to decimal */
+ case 0x60: /* STD - store */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
+ case 0x4f: /* CVB - convert to binary */
+ /* 32-bit gpr destination + FPC (DXC write) */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ case 0x50: /* ST - store */
+ case 0x70: /* STE - store */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ break;
+
+ case 0x51: /* LAE - load address extended */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_A0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ /* 0x52 undefined */
+ /* 0x53 undefined */
+
+ /* 0x61-0x66 undefined */
+
+ /* 0x72-0x77 undefined */
+
+ /* 0x80 privileged: SSM - set system mask */
+ /* 0x81 undefined */
+ /* 0x82 privileged: LPSW - load PSW */
+ /* 0x83 privileged: diagnose */
+
+ case 0x8e: /* SRDA - shift right double */
+ case 0x8f: /* SLDA - shift left double */
+ /* 32-bit pair destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x90: /* STM - store multiple */
+ case 0x9b: /* STAM - store access multiple */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (inib[2] <= inib[3])
+ n = inib[3] - inib[2] + 1;
+ else
+ n = inib[3] + 0x10 - inib[2] + 1;
+ if (record_full_arch_list_add_mem (oaddr, n * 4))
+ return -1;
+ break;
+
+ case 0x92: /* MVI - move */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 1))
+ return -1;
+ break;
+
+ case 0x93: /* TS - test and set */
+ case 0x94: /* NI - and */
+ case 0x96: /* OI - or */
+ case 0x97: /* XI - xor */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 1))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0x98: /* LM - load multiple */
+ for (i = inib[2]; i != inib[3]; i++, i &= 0xf)
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + i))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[3]))
+ return -1;
+ break;
+
+ /* 0x99 privileged: TRACE */
+
+ case 0x9a: /* LAM - load access multiple */
+ for (i = inib[2]; i != inib[3]; i++, i &= 0xf)
+ if (record_full_arch_list_add_reg (regcache, S390_A0_REGNUM + i))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_A0_REGNUM + inib[3]))
+ return -1;
+ break;
+
+ /* 0x9c-0x9f privileged and obsolete (old I/O) */
+ /* 0xa0-0xa4 undefined */
+
+ case 0xa5:
+ case 0xa7:
+ /* RI-format instruction */
+ switch (ibyte[0] << 4 | inib[3])
+ {
+ case 0xa50: /* IIHH - insert immediate */
+ case 0xa51: /* IIHL - insert immediate */
+ /* high 32-bit destination */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[2]))
+ return -1;
+ break;
+
+ case 0xa52: /* IILH - insert immediate */
+ case 0xa53: /* IILL - insert immediate */
+ case 0xa75: /* BRAS - branch relative and save */
+ case 0xa76: /* BRCT - branch relative on count */
+ case 0xa78: /* LHI - load halfword immediate */
+ case 0xa7c: /* MHI - multiply halfword immediate */
+ /* 32-bit or native destination */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ case 0xa54: /* NIHH - and immediate */
+ case 0xa55: /* NIHL - and immediate */
+ case 0xa58: /* OIHH - or immediate */
+ case 0xa59: /* OIHL - or immediate */
+ /* high 32-bit destination + flags */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xa56: /* NILH - and immediate */
+ case 0xa57: /* NILL - and immediate */
+ case 0xa5a: /* OILH - or immediate */
+ case 0xa5b: /* OILL - or immediate */
+ case 0xa7a: /* AHI - add halfword immediate */
+ /* 32-bit destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xa5c: /* LLIHH - load logical immediate */
+ case 0xa5d: /* LLIHL - load logical immediate */
+ case 0xa5e: /* LLILH - load logical immediate */
+ case 0xa5f: /* LLILL - load logical immediate */
+ case 0xa77: /* BRCTG - branch relative on count */
+ case 0xa79: /* LGHI - load halfword immediate */
+ case 0xa7d: /* MGHI - multiply halfword immediate */
+ /* 64-bit destination */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ break;
+
+ case 0xa70: /* TMLH - test under mask */
+ case 0xa71: /* TMLL - test under mask */
+ case 0xa72: /* TMHH - test under mask */
+ case 0xa73: /* TMHL - test under mask */
+ case 0xa7e: /* CHI - compare halfword immediate */
+ case 0xa7f: /* CGHI - compare halfword immediate */
+ /* flags only */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xa74: /* BRC - branch relative on condition */
+ /* no register change */
+ break;
+
+ case 0xa7b: /* AGHI - add halfword immediate */
+ /* 64-bit destination + flags */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ default:
+ goto UNKNOWN_OP;
+ }
+ break;
+
+ /* 0xa6 undefined */
+
+ case 0xa8: /* MVCLE - move long extended [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[2], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[2] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[3]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[3] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xaa-0xab undefined */
+ /* 0xac privileged: STNSM - store then and system mask */
+ /* 0xad privileged: STOSM - store then or system mask */
+ /* 0xae privileged: SIGP - signal processor */
+ /* 0xaf unsupported: MC - monitor call */
+ /* 0xb0 undefined */
+ /* 0xb1 privileged: LRA - load real address */
+
+ case 0xb2:
+ case 0xb3:
+ case 0xb9:
+ /* S/RRD/RRE/RRF/IE-format instruction */
+ switch (insn[0])
+ {
+ /* 0xb200-0xb204 undefined or privileged */
+
+ case 0xb205: /* STCK - store clock */
+ case 0xb27c: /* STCKF - store clock fast */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb206-0xb219 undefined, privileged, or unsupported */
+ /* 0xb21a unsupported: CFC */
+ /* 0xb21b-0xb221 undefined or privileged */
+
+ case 0xb222: /* IPM - insert program mask */
+ case 0xb24f: /* EAR - extract access */
+ case 0xb252: /* MSR - multiply single */
+ case 0xb2ec: /* ETND - extract transaction nesting depth */
+ case 0xb38c: /* EFPC - extract fpc */
+ case 0xb91f: /* LRVR - load reversed */
+ case 0xb926: /* LBR - load byte */
+ case 0xb927: /* LHR - load halfword */
+ case 0xb994: /* LLCR - load logical character */
+ case 0xb995: /* LLHR - load logical halfword */
+ case 0xb9f2: /* LOCR - load on condition */
+ /* 32-bit gpr destination */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ break;
+
+ /* 0xb223-0xb22c privileged or unsupported */
+
+ case 0xb22d: /* DXR - divide */
+ case 0xb325: /* LXDR - load lengthened */
+ case 0xb326: /* LXER - load lengthened */
+ case 0xb336: /* SQXR - square root */
+ case 0xb365: /* LXR - load */
+ case 0xb367: /* FIXR - load fp integer */
+ case 0xb376: /* LZXR - load zero */
+ case 0xb3b6: /* CXFR - convert from fixed */
+ case 0xb3c6: /* CXGR - convert from fixed */
+ case 0xb3fe: /* IEXTR - insert biased exponent */
+ /* float pair destination */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[6] | 2)))
+ return -1;
+ break;
+
+ /* 0xb22e-0xb240 undefined, privileged, or unsupported */
+
+ case 0xb241: /* CKSM - checksum [partial] */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb242-0xb243 undefined */
+
+ case 0xb244: /* SQDR - square root */
+ case 0xb245: /* SQER - square root */
+ case 0xb324: /* LDER - load lengthened */
+ case 0xb337: /* MEER - multiply */
+ case 0xb366: /* LEXR - load rounded */
+ case 0xb370: /* LPDFR - load positive */
+ case 0xb371: /* LNDFR - load negative */
+ case 0xb372: /* CSDFR - copy sign */
+ case 0xb373: /* LCDFR - load complement */
+ case 0xb374: /* LZER - load zero */
+ case 0xb375: /* LZDR - load zero */
+ case 0xb377: /* FIER - load fp integer */
+ case 0xb37f: /* FIDR - load fp integer */
+ case 0xb3b4: /* CEFR - convert from fixed */
+ case 0xb3b5: /* CDFR - convert from fixed */
+ case 0xb3c1: /* LDGR - load fpr from gr */
+ case 0xb3c4: /* CEGR - convert from fixed */
+ case 0xb3c5: /* CDGR - convert from fixed */
+ case 0xb3f6: /* IEDTR - insert biased exponent */
+ /* float destination */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ break;
+
+ /* 0xb246-0xb24c: privileged or unsupported */
+
+ case 0xb24d: /* CPYA - copy access */
+ case 0xb24e: /* SAR - set access */
+ if (record_full_arch_list_add_reg (regcache, S390_A0_REGNUM + inib[6]))
+ return -1;
+ break;
+
+ /* 0xb250-0xb251 undefined or privileged */
+ /* 0xb253-0xb254 undefined or privileged */
+
+ case 0xb255: /* MVST - move string [partial] */
+ {
+ uint8_t end;
+ gdb_byte cur;
+ ULONGEST num = 0;
+ /* Read ending byte. */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ end = tmp & 0xff;
+ /* Get address of second operand. */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[7], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ /* Search for ending byte and compute length. */
+ do {
+ num++;
+ if (target_read_memory (oaddr, &cur, 1))
+ return -1;
+ oaddr++;
+ } while (cur != end);
+ /* Get address of first operand and record it. */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ if (record_full_arch_list_add_mem (oaddr, num))
+ return -1;
+ /* Record the registers. */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ }
+ break;
+
+ /* 0xb256 undefined */
+
+ case 0xb257: /* CUSE - compare until substring equal [interruptible] */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb258-0xb25c undefined, privileged, or unsupported */
+
+ case 0xb25d: /* CLST - compare logical string [partial] */
+ case 0xb25e: /* SRST - search string [partial] */
+ case 0xb9be: /* SRSTU - search string unicode [partial] */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb25f-0xb262 undefined */
+
+ case 0xb263: /* CMPSC - compression call [interruptible] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[6] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R1_REGNUM))
+ return -1;
+ /* DXC may be written */
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb264-0xb277 undefined, privileged, or unsupported */
+
+ case 0xb278: /* STCKE - store clock extended */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb279-0xb27b undefined or unsupported */
+ /* 0xb27d-0xb298 undefined or privileged */
+
+ case 0xb299: /* SRNM - set rounding mode */
+ case 0xb2b8: /* SRNMB - set bfp rounding mode */
+ case 0xb2b9: /* SRNMT - set dfp rounding mode */
+ case 0xb29d: /* LFPC - load fpc */
+ case 0xb2bd: /* LFAS - load fpc and signal */
+ case 0xb384: /* SFPC - set fpc */
+ case 0xb385: /* SFASR - set fpc and signal */
+ case 0xb960: /* CGRT - compare and trap */
+ case 0xb961: /* CLGRT - compare logical and trap */
+ case 0xb972: /* CRT - compare and trap */
+ case 0xb973: /* CLRT - compare logical and trap */
+ /* fpc only - including possible DXC write for trapping insns */
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb29a-0xb29b undefined */
+
+ case 0xb29c: /* STFPC - store fpc */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ break;
+
+ /* 0xb29e-0xb2a4 undefined */
+
+ case 0xb2a5: /* TRE - translate extended [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[6] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb2a6: /* CU21 - convert UTF-16 to UTF-8 [partial] */
+ case 0xb2a7: /* CU12 - convert UTF-8 to UTF-16 [partial] */
+ case 0xb9b0: /* CU14 - convert UTF-8 to UTF-32 [partial] */
+ case 0xb9b1: /* CU24 - convert UTF-16 to UTF-32 [partial] */
+ case 0xb9b2: /* CU41 - convert UTF-32 to UTF-8 [partial] */
+ case 0xb9b3: /* CU42 - convert UTF-32 to UTF-16 [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[6] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb2a8-0xb2af undefined */
+
+ case 0xb2b0: /* STFLE - store facility list extended */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0xff;
+ if (record_full_arch_list_add_mem (oaddr, 8 * (tmp + 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb2b1-0xb2b7 undefined or privileged */
+ /* 0xb2ba-0xb2bc undefined */
+ /* 0xb2be-0xb2e7 undefined */
+ /* 0xb2e9-0xb2eb undefined */
+ /* 0xb2ed-0xb2f7 undefined */
+ /* 0xb2f8 unsupported: TEND */
+ /* 0xb2f9 undefined */
+
+ case 0xb2e8: /* PPA - perform processor assist */
+ case 0xb2fa: /* NIAI - next instruction access intent */
+ /* no visible effects */
+ break;
+
+ /* 0xb2fb undefined */
+ /* 0xb2fc unsupported: TABORT */
+ /* 0xb2fd-0xb2fe undefined */
+ /* 0xb2ff unsupported: TRAP */
+
+ case 0xb300: /* LPEBR - load positive */
+ case 0xb301: /* LNEBR - load negative */
+ case 0xb303: /* LCEBR - load complement */
+ case 0xb310: /* LPDBR - load positive */
+ case 0xb311: /* LNDBR - load negative */
+ case 0xb313: /* LCDBR - load complement */
+ case 0xb350: /* TBEDR - convert hfp to bfp */
+ case 0xb351: /* TBDR - convert hfp to bfp */
+ case 0xb358: /* THDER - convert bfp to hfp */
+ case 0xb359: /* THDR - convert bfp to hfp */
+ /* float destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb304: /* LDEBR - load lengthened */
+ case 0xb30c: /* MDEBR - multiply */
+ case 0xb30d: /* DEBR - divide */
+ case 0xb314: /* SQEBR - square root */
+ case 0xb315: /* SQDBR - square root */
+ case 0xb317: /* MEEBR - multiply */
+ case 0xb31c: /* MDBR - multiply */
+ case 0xb31d: /* DDBR - divide */
+ case 0xb344: /* LEDBRA - load rounded */
+ case 0xb345: /* LDXBRA - load rounded */
+ case 0xb346: /* LEXBRA - load rounded */
+ case 0xb357: /* FIEBRA - load fp integer */
+ case 0xb35f: /* FIDBRA - load fp integer */
+ case 0xb390: /* CELFBR - convert from logical */
+ case 0xb391: /* CDLFBR - convert from logical */
+ case 0xb394: /* CEFBR - convert from fixed */
+ case 0xb395: /* CDFBR - convert from fixed */
+ case 0xb3a0: /* CELGBR - convert from logical */
+ case 0xb3a1: /* CDLGBR - convert from logical */
+ case 0xb3a4: /* CEGBR - convert from fixed */
+ case 0xb3a5: /* CDGBR - convert from fixed */
+ case 0xb3d0: /* MDTR - multiply */
+ case 0xb3d1: /* DDTR - divide */
+ case 0xb3d4: /* LDETR - load lengthened */
+ case 0xb3d5: /* LEDTR - load lengthened */
+ case 0xb3d7: /* FIDTR - load fp integer */
+ case 0xb3dd: /* LDXTR - load lengthened */
+ case 0xb3f1: /* CDGTR - convert from fixed */
+ case 0xb3f2: /* CDUTR - convert from unsigned packed */
+ case 0xb3f3: /* CDSTR - convert from signed packed */
+ case 0xb3f5: /* QADTR - quantize */
+ case 0xb3f7: /* RRDTR - reround */
+ case 0xb951: /* CDFTR - convert from fixed */
+ case 0xb952: /* CDLGTR - convert from logical */
+ case 0xb953: /* CDLFTR - convert from logical */
+ /* float destination + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ case 0xb305: /* LXDBR - load lengthened */
+ case 0xb306: /* LXEBR - load lengthened */
+ case 0xb307: /* MXDBR - multiply */
+ case 0xb316: /* SQXBR - square root */
+ case 0xb34c: /* MXBR - multiply */
+ case 0xb34d: /* DXBR - divide */
+ case 0xb347: /* FIXBRA - load fp integer */
+ case 0xb392: /* CXLFBR - convert from logical */
+ case 0xb396: /* CXFBR - convert from fixed */
+ case 0xb3a2: /* CXLGBR - convert from logical */
+ case 0xb3a6: /* CXGBR - convert from fixed */
+ case 0xb3d8: /* MXTR - multiply */
+ case 0xb3d9: /* DXTR - divide */
+ case 0xb3dc: /* LXDTR - load lengthened */
+ case 0xb3df: /* FIXTR - load fp integer */
+ case 0xb3f9: /* CXGTR - convert from fixed */
+ case 0xb3fa: /* CXUTR - convert from unsigned packed */
+ case 0xb3fb: /* CXSTR - convert from signed packed */
+ case 0xb3fd: /* QAXTR - quantize */
+ case 0xb3ff: /* RRXTR - reround */
+ case 0xb959: /* CXFTR - convert from fixed */
+ case 0xb95a: /* CXLGTR - convert from logical */
+ case 0xb95b: /* CXLFTR - convert from logical */
+ /* float pair destination + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[6] | 2)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ case 0xb308: /* KEBR - compare and signal */
+ case 0xb309: /* CEBR - compare */
+ case 0xb318: /* KDBR - compare and signal */
+ case 0xb319: /* CDBR - compare */
+ case 0xb348: /* KXBR - compare and signal */
+ case 0xb349: /* CXBR - compare */
+ case 0xb3e0: /* KDTR - compare and signal */
+ case 0xb3e4: /* CDTR - compare */
+ case 0xb3e8: /* KXTR - compare and signal */
+ case 0xb3ec: /* CXTR - compare */
+ /* flags + fpc only */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ case 0xb302: /* LTEBR - load and test */
+ case 0xb312: /* LTDBR - load and test */
+ case 0xb30a: /* AEBR - add */
+ case 0xb30b: /* SEBR - subtract */
+ case 0xb31a: /* ADBR - add */
+ case 0xb31b: /* SDBR - subtract */
+ case 0xb3d2: /* ADTR - add */
+ case 0xb3d3: /* SDTR - subtract */
+ case 0xb3d6: /* LTDTR - load and test */
+ /* float destination + flags + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ case 0xb30e: /* MAEBR - multiply and add */
+ case 0xb30f: /* MSEBR - multiply and subtract */
+ case 0xb31e: /* MADBR - multiply and add */
+ case 0xb31f: /* MSDBR - multiply and subtract */
+ /* float destination [RRD] + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[4]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb320-0xb323 undefined */
+ /* 0xb327-0xb32d undefined */
+
+ case 0xb32e: /* MAER - multiply and add */
+ case 0xb32f: /* MSER - multiply and subtract */
+ case 0xb338: /* MAYLR - multiply and add unnormalized */
+ case 0xb339: /* MYLR - multiply unnormalized */
+ case 0xb33c: /* MAYHR - multiply and add unnormalized */
+ case 0xb33d: /* MYHR - multiply unnormalized */
+ case 0xb33e: /* MADR - multiply and add */
+ case 0xb33f: /* MSDR - multiply and subtract */
+ /* float destination [RRD] */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[4]))
+ return -1;
+ break;
+
+ /* 0xb330-0xb335 undefined */
+
+ case 0xb33a: /* MAYR - multiply and add unnormalized */
+ case 0xb33b: /* MYR - multiply unnormalized */
+ /* float pair destination [RRD] */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[4]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[4] | 2)))
+ return -1;
+ break;
+
+ case 0xb340: /* LPXBR - load positive */
+ case 0xb341: /* LNXBR - load negative */
+ case 0xb343: /* LCXBR - load complement */
+ case 0xb360: /* LPXR - load positive */
+ case 0xb361: /* LNXR - load negative */
+ case 0xb362: /* LTXR - load and test */
+ case 0xb363: /* LCXR - load complement */
+ /* float pair destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[6] | 2)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb342: /* LTXBR - load and test */
+ case 0xb34a: /* AXBR - add */
+ case 0xb34b: /* SXBR - subtract */
+ case 0xb3da: /* AXTR - add */
+ case 0xb3db: /* SXTR - subtract */
+ case 0xb3de: /* LTXTR - load and test */
+ /* float pair destination + flags + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + (inib[6] | 2)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb34e-0xb34f undefined */
+ /* 0xb352 undefined */
+
+ case 0xb353: /* DIEBR - divide to integer */
+ case 0xb35b: /* DIDBR - divide to integer */
+ /* two float destinations + flags + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[4]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_F0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb354-0xb356 undefined */
+ /* 0xb35a undefined */
+
+ /* 0xb35c-0xb35e undefined */
+ /* 0xb364 undefined */
+ /* 0xb368 undefined */
+
+ case 0xb369: /* CXR - compare */
+ case 0xb3f4: /* CEDTR - compare biased exponent */
+ case 0xb3fc: /* CEXTR - compare biased exponent */
+ case 0xb920: /* CGR - compare */
+ case 0xb921: /* CLGR - compare logical */
+ case 0xb930: /* CGFR - compare */
+ case 0xb931: /* CLGFR - compare logical */
+ case 0xb9cd: /* CHHR - compare high */
+ case 0xb9cf: /* CLHHR - compare logical high */
+ case 0xb9dd: /* CHLR - compare high */
+ case 0xb9df: /* CLHLR - compare logical high */
+ /* flags only */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb36a-0xb36f undefined */
+ /* 0xb377-0xb37e undefined */
+ /* 0xb380-0xb383 undefined */
+ /* 0xb386-0xb38b undefined */
+ /* 0xb38d-0xb38f undefined */
+ /* 0xb393 undefined */
+ /* 0xb397 undefined */
+
+ case 0xb398: /* CFEBR - convert to fixed */
+ case 0xb399: /* CFDBR - convert to fixed */
+ case 0xb39a: /* CFXBR - convert to fixed */
+ case 0xb39c: /* CLFEBR - convert to logical */
+ case 0xb39d: /* CLFDBR - convert to logical */
+ case 0xb39e: /* CLFXBR - convert to logical */
+ case 0xb941: /* CFDTR - convert to fixed */
+ case 0xb949: /* CFXTR - convert to fixed */
+ case 0xb943: /* CLFDTR - convert to logical */
+ case 0xb94b: /* CLFXTR - convert to logical */
+ /* 32-bit gpr destination + flags + fpc */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb39b undefined */
+ /* 0xb39f undefined */
+
+ /* 0xb3a3 undefined */
+ /* 0xb3a7 undefined */
+
+ case 0xb3a8: /* CGEBR - convert to fixed */
+ case 0xb3a9: /* CGDBR - convert to fixed */
+ case 0xb3aa: /* CGXBR - convert to fixed */
+ case 0xb3ac: /* CLGEBR - convert to logical */
+ case 0xb3ad: /* CLGDBR - convert to logical */
+ case 0xb3ae: /* CLGXBR - convert to logical */
+ case 0xb3e1: /* CGDTR - convert to fixed */
+ case 0xb3e9: /* CGXTR - convert to fixed */
+ case 0xb942: /* CLGDTR - convert to logical */
+ case 0xb94a: /* CLGXTR - convert to logical */
+ /* 64-bit gpr destination + flags + fpc */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb3ab undefined */
+ /* 0xb3af-0xb3b3 undefined */
+ /* 0xb3b7 undefined */
+
+ case 0xb3b8: /* CFER - convert to fixed */
+ case 0xb3b9: /* CFDR - convert to fixed */
+ case 0xb3ba: /* CFXR - convert to fixed */
+ case 0xb998: /* ALCR - add logical with carry */
+ case 0xb999: /* SLBR - subtract logical with borrow */
+ case 0xb9f4: /* NRK - and */
+ case 0xb9f6: /* ORK - or */
+ case 0xb9f7: /* XRK - xor */
+ case 0xb9f8: /* ARK - add */
+ case 0xb9f9: /* SRK - subtract */
+ case 0xb9fa: /* ALRK - add logical */
+ case 0xb9fb: /* SLRK - subtract logical */
+ /* 32-bit gpr destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb3c8: /* CGER - convert to fixed */
+ case 0xb3c9: /* CGDR - convert to fixed */
+ case 0xb3ca: /* CGXR - convert to fixed */
+ case 0xb900: /* LPGR - load positive */
+ case 0xb901: /* LNGR - load negative */
+ case 0xb902: /* LTGR - load and test */
+ case 0xb903: /* LCGR - load complement */
+ case 0xb908: /* AGR - add */
+ case 0xb909: /* SGR - subtract */
+ case 0xb90a: /* ALGR - add logical */
+ case 0xb90b: /* SLGR - subtract logical */
+ case 0xb910: /* LPGFR - load positive */
+ case 0xb911: /* LNGFR - load negative */
+ case 0xb912: /* LTGFR - load and test */
+ case 0xb913: /* LCGFR - load complement */
+ case 0xb918: /* AGFR - add */
+ case 0xb919: /* SGFR - subtract */
+ case 0xb91a: /* ALGFR - add logical */
+ case 0xb91b: /* SLGFR - subtract logical */
+ case 0xb980: /* NGR - and */
+ case 0xb981: /* OGR - or */
+ case 0xb982: /* XGR - xor */
+ case 0xb988: /* ALCGR - add logical with carry */
+ case 0xb989: /* SLBGR - subtract logical with borrow */
+ case 0xb9e1: /* POPCNT - population count */
+ case 0xb9e4: /* NGRK - and */
+ case 0xb9e6: /* OGRK - or */
+ case 0xb9e7: /* XGRK - xor */
+ case 0xb9e8: /* AGRK - add */
+ case 0xb9e9: /* SGRK - subtract */
+ case 0xb9ea: /* ALGRK - add logical */
+ case 0xb9eb: /* SLGRK - subtract logical */
+ case 0xb9ed: /* MSGRKC - multiply single 64x64 -> 64 */
+ case 0xb9fd: /* MSRKC - multiply single 32x32 -> 32 */
+ /* 64-bit gpr destination + flags */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb3bb-0xb3c0 undefined */
+ /* 0xb3c2-0xb3c3 undefined */
+ /* 0xb3c7 undefined */
+ /* 0xb3cb-0xb3cc undefined */
+
+ case 0xb3cd: /* LGDR - load gr from fpr */
+ case 0xb3e2: /* CUDTR - convert to unsigned packed */
+ case 0xb3e3: /* CSDTR - convert to signed packed */
+ case 0xb3e5: /* EEDTR - extract biased exponent */
+ case 0xb3e7: /* ESDTR - extract significance */
+ case 0xb3ed: /* EEXTR - extract biased exponent */
+ case 0xb3ef: /* ESXTR - extract significance */
+ case 0xb904: /* LGR - load */
+ case 0xb906: /* LGBR - load byte */
+ case 0xb907: /* LGHR - load halfword */
+ case 0xb90c: /* MSGR - multiply single */
+ case 0xb90f: /* LRVGR - load reversed */
+ case 0xb914: /* LGFR - load */
+ case 0xb916: /* LLGFR - load logical */
+ case 0xb917: /* LLGTR - load logical thirty one bits */
+ case 0xb91c: /* MSGFR - multiply single 64<32 */
+ case 0xb946: /* BCTGR - branch on count */
+ case 0xb984: /* LLGCR - load logical character */
+ case 0xb985: /* LLGHR - load logical halfword */
+ case 0xb9e2: /* LOCGR - load on condition */
+ /* 64-bit gpr destination */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
+ return -1;
+ break;
+
+ /* 0xb3ce-0xb3cf undefined */
+ /* 0xb3e6 undefined */
+
+ case 0xb3ea: /* CUXTR - convert to unsigned packed */
+ case 0xb3eb: /* CSXTR - convert to signed packed */
+ case 0xb90d: /* DSGR - divide single */
+ case 0xb91d: /* DSGFR - divide single */
+ case 0xb986: /* MLGR - multiply logical */
+ case 0xb987: /* DLGR - divide logical */
+ case 0xb9ec: /* MGRK - multiply 64x64 -> 128 */
+ /* 64-bit gpr pair destination */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
+ return -1;
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6] | 1))
+ return -1;
+ break;
+
+ /* 0xb3ee undefined */
+ /* 0xb3f0 undefined */
+ /* 0xb3f8 undefined */
+
+ /* 0xb905 privileged */
+
+ /* 0xb90e unsupported: EREGG */
+
+ /* 0xb915 undefined */
+
+ case 0xb91e: /* KMAC - compute message authentication code [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0xff;
+ switch (tmp)
+ {
+ case 0x00: /* KMAC-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* KMAC-DEA */
+ case 0x02: /* KMAC-TDEA-128 */
+ case 0x03: /* KMAC-TDEA-192 */
+ case 0x09: /* KMAC-Encrypted-DEA */
+ case 0x0a: /* KMAC-Encrypted-TDEA-128 */
+ case 0x0b: /* KMAC-Encrypted-TDEA-192 */
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
+ case 0x12: /* KMAC-AES-128 */
+ case 0x13: /* KMAC-AES-192 */
+ case 0x14: /* KMAC-AES-256 */
+ case 0x1a: /* KMAC-Encrypted-AES-128 */
+ case 0x1b: /* KMAC-Encrypted-AES-192 */
+ case 0x1c: /* KMAC-Encrypted-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KMAC function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (tmp != 0)
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb922-0xb924 undefined */
+ /* 0xb925 privileged */
+ /* 0xb928 privileged */
+
+ case 0xb929: /* KMA - cipher message with authentication */
+ case 0xb92a: /* KMF - cipher message with cipher feedback [partial] */
+ case 0xb92b: /* KMO - cipher message with output feedback [partial] */
+ case 0xb92f: /* KMC - cipher message with chaining [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0x7f;
+ switch (tmp)
+ {
+ case 0x00: /* KM*-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* KM*-DEA */
+ case 0x02: /* KM*-TDEA-128 */
+ case 0x03: /* KM*-TDEA-192 */
+ case 0x09: /* KM*-Encrypted-DEA */
+ case 0x0a: /* KM*-Encrypted-TDEA-128 */
+ case 0x0b: /* KM*-Encrypted-TDEA-192 */
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
+ case 0x12: /* KM*-AES-128 */
+ case 0x13: /* KM*-AES-192 */
+ case 0x14: /* KM*-AES-256 */
+ case 0x1a: /* KM*-Encrypted-AES-128 */
+ case 0x1b: /* KM*-Encrypted-AES-192 */
+ case 0x1c: /* KM*-Encrypted-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x43: /* KMC-PRNG */
+ /* Only valid for KMC. */
+ if (insn[0] == 0xb92f)
+ {
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+ }
+ /* For other instructions... */
+ /* Fall through. */
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KM* function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (tmp != 0)
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr2 = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[7] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr2, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ }
+ if (tmp != 0 && insn[0] == 0xb929)
+ {
+ if (record_full_arch_list_add_reg (regcache,
+ S390_R0_REGNUM + inib[4]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache,
+ S390_R0_REGNUM + (inib[4] | 1)))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb92c: /* PCC - perform cryptographic computation [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0x7f;
+ switch (tmp)
+ {
+ case 0x00: /* PCC-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* PCC-Compute-Last-Block-CMAC-Using-DEA */
+ case 0x02: /* PCC-Compute-Last-Block-CMAC-Using-TDEA-128 */
+ case 0x03: /* PCC-Compute-Last-Block-CMAC-Using-TDEA-192 */
+ case 0x09: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-DEA */
+ case 0x0a: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128 */
+ case 0x0b: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-TDEA-192 */
+ if (record_full_arch_list_add_mem (oaddr + 0x10, 8))
+ return -1;
+ break;
+
+ case 0x12: /* PCC-Compute-Last-Block-CMAC-Using-AES-128 */
+ case 0x13: /* PCC-Compute-Last-Block-CMAC-Using-AES-192 */
+ case 0x14: /* PCC-Compute-Last-Block-CMAC-Using-AES-256 */
+ case 0x1a: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-AES-128 */
+ case 0x1b: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-AES-192 */
+ case 0x1c: /* PCC-Compute-Last-Block-CMAC-Using-Encrypted-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr + 0x18, 16))
+ return -1;
+ break;
+
+ case 0x32: /* PCC-Compute-XTS-Parameter-Using-AES-128 */
+ if (record_full_arch_list_add_mem (oaddr + 0x30, 32))
+ return -1;
+ break;
+
+ case 0x34: /* PCC-Compute-XTS-Parameter-Using-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr + 0x40, 32))
+ return -1;
+ break;
+
+ case 0x3a: /* PCC-Compute-XTS-Parameter-Using-Encrypted-AES-128 */
+ if (record_full_arch_list_add_mem (oaddr + 0x50, 32))
+ return -1;
+ break;
+
+ case 0x3c: /* PCC-Compute-XTS-Parameter-Using-Encrypted-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr + 0x60, 32))
+ return -1;
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown PCC function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb92d: /* KMCTR - cipher message with counter [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0x7f;
+ switch (tmp)
+ {
+ case 0x00: /* KMCTR-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* KMCTR-DEA */
+ case 0x02: /* KMCTR-TDEA-128 */
+ case 0x03: /* KMCTR-TDEA-192 */
+ case 0x09: /* KMCTR-Encrypted-DEA */
+ case 0x0a: /* KMCTR-Encrypted-TDEA-128 */
+ case 0x0b: /* KMCTR-Encrypted-TDEA-192 */
+ case 0x12: /* KMCTR-AES-128 */
+ case 0x13: /* KMCTR-AES-192 */
+ case 0x14: /* KMCTR-AES-256 */
+ case 0x1a: /* KMCTR-Encrypted-AES-128 */
+ case 0x1b: /* KMCTR-Encrypted-AES-192 */
+ case 0x1c: /* KMCTR-Encrypted-AES-256 */
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KMCTR function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (tmp != 0)
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr2 = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[7] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr2, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[4]))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb92e: /* KM - cipher message [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0x7f;
+ switch (tmp)
+ {
+ case 0x00: /* KM-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* KM-DEA */
+ case 0x02: /* KM-TDEA-128 */
+ case 0x03: /* KM-TDEA-192 */
+ case 0x09: /* KM-Encrypted-DEA */
+ case 0x0a: /* KM-Encrypted-TDEA-128 */
+ case 0x0b: /* KM-Encrypted-TDEA-192 */
+ case 0x12: /* KM-AES-128 */
+ case 0x13: /* KM-AES-192 */
+ case 0x14: /* KM-AES-256 */
+ case 0x1a: /* KM-Encrypted-AES-128 */
+ case 0x1b: /* KM-Encrypted-AES-192 */
+ case 0x1c: /* KM-Encrypted-AES-256 */
+ break;
+
+ case 0x32: /* KM-XTS-AES-128 */
+ if (record_full_arch_list_add_mem (oaddr + 0x10, 16))
+ return -1;
+ break;
+
+ case 0x34: /* KM-XTS-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr + 0x20, 16))
+ return -1;
+ break;
+
+ case 0x3a: /* KM-XTS-Encrypted-AES-128 */
+ if (record_full_arch_list_add_mem (oaddr + 0x30, 16))
+ return -1;
+ break;
+
+ case 0x3c: /* KM-XTS-Encrypted-AES-256 */
+ if (record_full_arch_list_add_mem (oaddr + 0x40, 16))
+ return -1;
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KM function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (tmp != 0)
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr2 = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[7] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr2, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb932-0xb93b undefined */
+
+ case 0xb93c: /* PPNO - perform pseudorandom number operation [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0xff;
+ switch (tmp)
+ {
+ case 0x00: /* PPNO-Query */
+ case 0x80: /* PPNO-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x03: /* PPNO-SHA-512-DRNG - generate */
+ if (record_full_arch_list_add_mem (oaddr, 240))
+ return -1;
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr2 = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[6] | 1), &tmp);
+ if (record_full_arch_list_add_mem (oaddr2, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ break;
+
+ case 0x83: /* PPNO-SHA-512-DRNG - seed */
+ if (record_full_arch_list_add_mem (oaddr, 240))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown PPNO function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ /* DXC may be written */
+ if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb93d undefined */
+
+ case 0xb93e: /* KIMD - compute intermediate message digest [partial] */
+ case 0xb93f: /* KLMD - compute last message digest [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ tmp &= 0xff;
+ switch (tmp)
+ {
+ case 0x00: /* K*MD-Query */
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ case 0x01: /* K*MD-SHA-1 */
+ if (record_full_arch_list_add_mem (oaddr, 20))
+ return -1;
+ break;
+
+ case 0x02: /* K*MD-SHA-256 */
+ if (record_full_arch_list_add_mem (oaddr, 32))
+ return -1;
+ break;
+
+ case 0x03: /* K*MD-SHA-512 */
+ if (record_full_arch_list_add_mem (oaddr, 64))
+ return -1;
+ break;
+
+ case 0x41: /* KIMD-GHASH */
+ /* Only valid for KIMD. */
+ if (insn[0] == 0xb93e)
+ {
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+ }
+ /* For KLMD... */
+ /* Fall through. */
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KMAC function %02x at %s.\n",
+ (int)tmp, paddress (gdbarch, addr));
+ return -1;
+ }
+ if (tmp != 0)
+ {
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
+ return -1;
+ }
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb940 undefined */
+ /* 0xb944-0xb945 undefined */
+ /* 0xb947-0xb948 undefined */
+ /* 0xb94c-0xb950 undefined */
+ /* 0xb954-0xb958 undefined */
+ /* 0xb95c-0xb95f undefined */
+ /* 0xb962-0xb971 undefined */
+ /* 0xb974-0xb97f undefined */
+
+ case 0xb983: /* FLOGR - find leftmost one */
+ /* 64-bit gpr pair destination + flags */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
+ return -1;
+ if (s390_record_gpr_g (gdbarch, regcache, inib[6] | 1))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb98a privileged */
+ /* 0xb98b-0xb98c undefined */
+
+ case 0xb98d: /* EPSW - extract psw */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (inib[7])
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ break;
+
+ /* 0xb98e-0xb98f privileged */
+
+ case 0xb990: /* TRTT - translate two to two [partial] */
+ case 0xb991: /* TRTO - translate two to one [partial] */
+ case 0xb992: /* TROT - translate one to two [partial] */
+ case 0xb993: /* TROO - translate one to one [partial] */
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[6], &tmp);
+ oaddr = s390_record_address_mask (gdbarch, regcache, tmp);
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + (inib[6] | 1), &tmp);
+ /* tmp is source length, we want destination length. Adjust. */
+ if (insn[0] == 0xb991)
+ tmp >>= 1;
+ if (insn[0] == 0xb992)
+ tmp <<= 1;
+ if (record_full_arch_list_add_mem (oaddr, tmp))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xb996: /* MLR - multiply logical */
+ case 0xb997: /* DLR - divide logical */
+ /* 32-bit gpr pair destination */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ break;
+
+ /* 0xb99a-0xb9af unsupported, privileged, or undefined */
+ /* 0xb9b4-0xb9bc undefined */
+
+ case 0xb9bd: /* TRTRE - translate and test reverse extended [partial] */
+ case 0xb9bf: /* TRTE - translate and test extended [partial] */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[6] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[7]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb9c0-0xb9c7 undefined */
+
+ case 0xb9c8: /* AHHHR - add high */
+ case 0xb9c9: /* SHHHR - subtract high */
+ case 0xb9ca: /* ALHHHR - add logical high */
+ case 0xb9cb: /* SLHHHR - subtract logical high */
+ case 0xb9d8: /* AHHLR - add high */
+ case 0xb9d9: /* SHHLR - subtract high */
+ case 0xb9da: /* ALHHLR - add logical high */
+ case 0xb9db: /* SLHHLR - subtract logical high */
+ /* 32-bit high gpr destination + flags */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[6]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xb9cc undefined */
+ /* 0xb9ce undefined */
+ /* 0xb9d0-0xb9d7 undefined */
+ /* 0xb9dc undefined */
+ /* 0xb9de undefined */
+
+ case 0xb9e0: /* LOCFHR - load high on condition */
+ /* 32-bit high gpr destination */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[6]))
+ return -1;
+ break;
+
+ /* 0xb9e3 undefined */
+ /* 0xb9e5 undefined */
+ /* 0xb9ee-0xb9f1 undefined */
+ /* 0xb9f3 undefined */
+ /* 0xb9f5 undefined */
+ /* 0xb9fc undefined */
+ /* 0xb9fe -0xb9ff undefined */
+
+ default:
+ goto UNKNOWN_OP;
+ }
+ break;
+
+ /* 0xb4-0xb5 undefined */
+ /* 0xb6 privileged: STCTL - store control */
+ /* 0xb7 privileged: LCTL - load control */
+ /* 0xb8 undefined */
+
+ case 0xba: /* CS - compare and swap */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xbb: /* CDS - compare double and swap */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[2] | 1)))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xbc undefined */
+
+ case 0xbe: /* STCM - store characters under mask */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ if (record_full_arch_list_add_mem (oaddr, s390_popcnt (inib[3])))
+ return -1;
+ break;
+
+ case 0xc0:
+ case 0xc2:
+ case 0xc4:
+ case 0xc6:
+ case 0xcc:
+ /* RIL-format instruction */
+ switch (ibyte[0] << 4 | inib[3])
+ {
+ case 0xc00: /* LARL - load address relative long */
+ case 0xc05: /* BRASL - branch relative and save long */
+ case 0xc09: /* IILF - insert immediate */
+ case 0xc21: /* MSFI - multiply single immediate */
+ case 0xc42: /* LLHRL - load logical halfword relative long */
+ case 0xc45: /* LHRL - load halfword relative long */
+ case 0xc4d: /* LRL - load relative long */
+ /* 32-bit or native gpr destination */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ break;
+
+ case 0xc01: /* LGFI - load immediate */
+ case 0xc0e: /* LLIHF - load logical immediate */
+ case 0xc0f: /* LLILF - load logical immediate */
+ case 0xc20: /* MSGFI - multiply single immediate */
+ case 0xc44: /* LGHRL - load halfword relative long */
+ case 0xc46: /* LLGHRL - load logical halfword relative long */
+ case 0xc48: /* LGRL - load relative long */
+ case 0xc4c: /* LGFRL - load relative long */
+ case 0xc4e: /* LLGFRL - load logical relative long */
+ /* 64-bit gpr destination */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ break;
+
+ /* 0xc02-0xc03 undefined */
+
+ case 0xc04: /* BRCL - branch relative on condition long */
+ case 0xc62: /* PFDRL - prefetch data relative long */
+ break;
+
+ case 0xc06: /* XIHF - xor immediate */
+ case 0xc0a: /* NIHF - and immediate */
+ case 0xc0c: /* OIHF - or immediate */
+ case 0xcc8: /* AIH - add immediate high */
+ case 0xcca: /* ALSIH - add logical with signed immediate high */
+ /* 32-bit high gpr destination + flags */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xc07: /* XILF - xor immediate */
+ case 0xc0b: /* NILF - and immediate */
+ case 0xc0d: /* OILF - or immediate */
+ case 0xc25: /* SLFI - subtract logical immediate */
+ case 0xc29: /* AFI - add immediate */
+ case 0xc2b: /* ALFI - add logical immediate */
+ /* 32-bit gpr destination + flags */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ case 0xc08: /* IIHF - insert immediate */
+ case 0xcc6: /* BRCTH - branch relative on count high */
+ case 0xccb: /* ALSIHN - add logical with signed immediate high */
+ /* 32-bit high gpr destination */
+ if (s390_record_gpr_h (gdbarch, regcache, inib[2]))
+ return -1;
+ break;
+
+ /* 0xc22-0xc23 undefined */
+
+ case 0xc24: /* SLGFI - subtract logical immediate */
+ case 0xc28: /* AGFI - add immediate */
+ case 0xc2a: /* ALGFI - add logical immediate */
+ /* 64-bit gpr destination + flags */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xc26-0xc27 undefined */
+
+ case 0xc2c: /* CGFI - compare immediate */
+ case 0xc2d: /* CFI - compare immediate */
+ case 0xc2e: /* CLGFI - compare logical immediate */
+ case 0xc2f: /* CLFI - compare logical immediate */
+ case 0xc64: /* CGHRL - compare halfword relative long */
+ case 0xc65: /* CHRL - compare halfword relative long */
+ case 0xc66: /* CLGHRL - compare logical halfword relative long */
+ case 0xc67: /* CLHRL - compare logical halfword relative long */
+ case 0xc68: /* CGRL - compare relative long */
+ case 0xc6a: /* CLGRL - compare logical relative long */
+ case 0xc6c: /* CGFRL - compare relative long */
+ case 0xc6d: /* CRL - compare relative long */
+ case 0xc6e: /* CLGFRL - compare logical relative long */
+ case 0xc6f: /* CLRL - compare logical relative long */
+ case 0xccd: /* CIH - compare immediate high */
+ case 0xccf: /* CLIH - compare logical immediate high */
+ /* flags only */
+ if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+ return -1;
+ break;
+
+ /* 0xc40-0xc41 undefined */
+ /* 0xc43 undefined */
+
+ case 0xc47: /* STHRL - store halfword relative long */
+ oaddr = s390_record_calc_rl (gdbarch, regcache, addr, insn[1], insn[2]);
+ if (record_full_arch_list_add_mem (oaddr, 2))
+ return -1;
+ break;
+
+ /* 0xc49-0xc4a undefined */
+
+ case 0xc4b: /* STGRL - store relative long */
+ oaddr = s390_record_calc_rl (gdbarch, regcache, addr, insn[1], insn[2]);
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
+ case 0xc4f: /* STRL - store relative long */
+ oaddr = s390_record_calc_rl (gdbarch, regcache, addr, insn[1], insn[2]);
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ break;
+
+ case 0xc60: /* EXRL - execute relative long */
+ if (ex != -1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Warning: Double execute at %s.\n",
+ paddress (gdbarch, addr));
+ return -1;
+ }
+ addr = s390_record_calc_rl (gdbarch, regcache, addr, insn[1], insn[2]);
+ if (inib[2])
+ {
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[2], &tmp);
+ ex = tmp & 0xff;
+ }
+ else
+ {
+ ex = 0;
+ }
+ goto ex;
+
+ /* 0xc61 undefined */
+ /* 0xc63 undefined */
+ /* 0xc69 undefined */
+ /* 0xc6b undefined */
+ /* 0xcc0-0xcc5 undefined */
+ /* 0xcc7 undefined */
+ /* 0xcc9 undefined */
+ /* 0xccc undefined */
+ /* 0xcce undefined */
+
+ default:
+ goto UNKNOWN_OP;
+ }
+ break;
+
+ /* 0xc1 undefined */
+ /* 0xc3 undefined */
+
+ case 0xc5: /* BPRP - branch prediction relative preload */
+ case 0xc7: /* BPP - branch prediction preload */
+ /* no visible effect */
+ break;
+
+ case 0xc8:
+ /* SSF-format instruction */
+ switch (ibyte[0] << 4 | inib[3])
+ {
+ /* 0xc80 unsupported */
+
+ case 0xc81: /* ECTG - extract cpu time */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ if (s390_record_gpr_g (gdbarch, regcache, 0))
+ return -1;
+ if (s390_record_gpr_g (gdbarch, regcache, 1))
+ return -1;
+ break;
+
+ case 0xc82: /* CSST - compare and swap and store */
+ {
+ uint8_t fc, sc;
+ regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+ fc = tmp & 0xff;
+ sc = tmp >> 8 & 0xff;
+
+ /* First and third operands. */
+ oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+ switch (fc)
+ {
+ case 0x00: /* 32-bit */
+ if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
+ return -1;
+ if (record_full_arch_list_add_mem (oaddr, 4))
+ return -1;
+ break;
+
+ case 0x01: /* 64-bit */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ if (record_full_arch_list_add_mem (oaddr, 8))
+ return -1;
+ break;
+
+ case 0x02: /* 128-bit */
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
+ return -1;
+ if (s390_record_gpr_g (gdbarch, regcache, inib[2] | 1))
+ return -1;
+ if (record_full_arch_list_add_mem (oaddr, 16))
+ return -1;
+ break;
+
+ default:
+ fprintf_unfiltered (gdb_stdlog, "Warning: Unknown CSST FC %02x at %s.\n",
+ fc, paddress (gdbarch, addr));
+ return -1;
+ }