root/arch/s390/kernel/dis.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. extract_operand
  2. find_insn
  3. print_insn
  4. show_code
  5. print_fn_code

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Disassemble s390 instructions.
   4  *
   5  * Copyright IBM Corp. 2007
   6  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
   7  */
   8 
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 #include <linux/string.h>
  12 #include <linux/errno.h>
  13 #include <linux/ptrace.h>
  14 #include <linux/timer.h>
  15 #include <linux/mm.h>
  16 #include <linux/smp.h>
  17 #include <linux/init.h>
  18 #include <linux/interrupt.h>
  19 #include <linux/delay.h>
  20 #include <linux/export.h>
  21 #include <linux/kallsyms.h>
  22 #include <linux/reboot.h>
  23 #include <linux/kprobes.h>
  24 #include <linux/kdebug.h>
  25 #include <linux/uaccess.h>
  26 #include <linux/atomic.h>
  27 #include <asm/dis.h>
  28 #include <asm/io.h>
  29 #include <asm/cpcmd.h>
  30 #include <asm/lowcore.h>
  31 #include <asm/debug.h>
  32 #include <asm/irq.h>
  33 
  34 /* Type of operand */
  35 #define OPERAND_GPR     0x1     /* Operand printed as %rx */
  36 #define OPERAND_FPR     0x2     /* Operand printed as %fx */
  37 #define OPERAND_AR      0x4     /* Operand printed as %ax */
  38 #define OPERAND_CR      0x8     /* Operand printed as %cx */
  39 #define OPERAND_VR      0x10    /* Operand printed as %vx */
  40 #define OPERAND_DISP    0x20    /* Operand printed as displacement */
  41 #define OPERAND_BASE    0x40    /* Operand printed as base register */
  42 #define OPERAND_INDEX   0x80    /* Operand printed as index register */
  43 #define OPERAND_PCREL   0x100   /* Operand printed as pc-relative symbol */
  44 #define OPERAND_SIGNED  0x200   /* Operand printed as signed value */
  45 #define OPERAND_LENGTH  0x400   /* Operand printed as length (+1) */
  46 
  47 struct s390_operand {
  48         unsigned char bits;     /* The number of bits in the operand. */
  49         unsigned char shift;    /* The number of bits to shift. */
  50         unsigned short flags;   /* One bit syntax flags. */
  51 };
  52 
  53 struct s390_insn {
  54         union {
  55                 const char name[5];
  56                 struct {
  57                         unsigned char zero;
  58                         unsigned int offset;
  59                 } __packed;
  60         };
  61         unsigned char opfrag;
  62         unsigned char format;
  63 };
  64 
  65 struct s390_opcode_offset {
  66         unsigned char opcode;
  67         unsigned char mask;
  68         unsigned char byte;
  69         unsigned short offset;
  70         unsigned short count;
  71 } __packed;
  72 
  73 enum {
  74         UNUSED,
  75         A_8,    /* Access reg. starting at position 8 */
  76         A_12,   /* Access reg. starting at position 12 */
  77         A_24,   /* Access reg. starting at position 24 */
  78         A_28,   /* Access reg. starting at position 28 */
  79         B_16,   /* Base register starting at position 16 */
  80         B_32,   /* Base register starting at position 32 */
  81         C_8,    /* Control reg. starting at position 8 */
  82         C_12,   /* Control reg. starting at position 12 */
  83         D20_20, /* 20 bit displacement starting at 20 */
  84         D_20,   /* Displacement starting at position 20 */
  85         D_36,   /* Displacement starting at position 36 */
  86         F_8,    /* FPR starting at position 8 */
  87         F_12,   /* FPR starting at position 12 */
  88         F_16,   /* FPR starting at position 16 */
  89         F_24,   /* FPR starting at position 24 */
  90         F_28,   /* FPR starting at position 28 */
  91         F_32,   /* FPR starting at position 32 */
  92         I8_8,   /* 8 bit signed value starting at 8 */
  93         I8_32,  /* 8 bit signed value starting at 32 */
  94         I16_16, /* 16 bit signed value starting at 16 */
  95         I16_32, /* 16 bit signed value starting at 32 */
  96         I32_16, /* 32 bit signed value starting at 16 */
  97         J12_12, /* 12 bit PC relative offset at 12 */
  98         J16_16, /* 16 bit PC relative offset at 16 */
  99         J16_32, /* 16 bit PC relative offset at 32 */
 100         J24_24, /* 24 bit PC relative offset at 24 */
 101         J32_16, /* 32 bit PC relative offset at 16 */
 102         L4_8,   /* 4 bit length starting at position 8 */
 103         L4_12,  /* 4 bit length starting at position 12 */
 104         L8_8,   /* 8 bit length starting at position 8 */
 105         R_8,    /* GPR starting at position 8 */
 106         R_12,   /* GPR starting at position 12 */
 107         R_16,   /* GPR starting at position 16 */
 108         R_24,   /* GPR starting at position 24 */
 109         R_28,   /* GPR starting at position 28 */
 110         U4_8,   /* 4 bit unsigned value starting at 8 */
 111         U4_12,  /* 4 bit unsigned value starting at 12 */
 112         U4_16,  /* 4 bit unsigned value starting at 16 */
 113         U4_20,  /* 4 bit unsigned value starting at 20 */
 114         U4_24,  /* 4 bit unsigned value starting at 24 */
 115         U4_28,  /* 4 bit unsigned value starting at 28 */
 116         U4_32,  /* 4 bit unsigned value starting at 32 */
 117         U4_36,  /* 4 bit unsigned value starting at 36 */
 118         U8_8,   /* 8 bit unsigned value starting at 8 */
 119         U8_16,  /* 8 bit unsigned value starting at 16 */
 120         U8_24,  /* 8 bit unsigned value starting at 24 */
 121         U8_28,  /* 8 bit unsigned value starting at 28 */
 122         U8_32,  /* 8 bit unsigned value starting at 32 */
 123         U12_16, /* 12 bit unsigned value starting at 16 */
 124         U16_16, /* 16 bit unsigned value starting at 16 */
 125         U16_32, /* 16 bit unsigned value starting at 32 */
 126         U32_16, /* 32 bit unsigned value starting at 16 */
 127         VX_12,  /* Vector index register starting at position 12 */
 128         V_8,    /* Vector reg. starting at position 8 */
 129         V_12,   /* Vector reg. starting at position 12 */
 130         V_16,   /* Vector reg. starting at position 16 */
 131         V_32,   /* Vector reg. starting at position 32 */
 132         X_12,   /* Index register starting at position 12 */
 133 };
 134 
 135 static const struct s390_operand operands[] = {
 136         [UNUSED] = {  0,  0, 0 },
 137         [A_8]    = {  4,  8, OPERAND_AR },
 138         [A_12]   = {  4, 12, OPERAND_AR },
 139         [A_24]   = {  4, 24, OPERAND_AR },
 140         [A_28]   = {  4, 28, OPERAND_AR },
 141         [B_16]   = {  4, 16, OPERAND_BASE | OPERAND_GPR },
 142         [B_32]   = {  4, 32, OPERAND_BASE | OPERAND_GPR },
 143         [C_8]    = {  4,  8, OPERAND_CR },
 144         [C_12]   = {  4, 12, OPERAND_CR },
 145         [D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED },
 146         [D_20]   = { 12, 20, OPERAND_DISP },
 147         [D_36]   = { 12, 36, OPERAND_DISP },
 148         [F_8]    = {  4,  8, OPERAND_FPR },
 149         [F_12]   = {  4, 12, OPERAND_FPR },
 150         [F_16]   = {  4, 16, OPERAND_FPR },
 151         [F_24]   = {  4, 24, OPERAND_FPR },
 152         [F_28]   = {  4, 28, OPERAND_FPR },
 153         [F_32]   = {  4, 32, OPERAND_FPR },
 154         [I8_8]   = {  8,  8, OPERAND_SIGNED },
 155         [I8_32]  = {  8, 32, OPERAND_SIGNED },
 156         [I16_16] = { 16, 16, OPERAND_SIGNED },
 157         [I16_32] = { 16, 32, OPERAND_SIGNED },
 158         [I32_16] = { 32, 16, OPERAND_SIGNED },
 159         [J12_12] = { 12, 12, OPERAND_PCREL },
 160         [J16_16] = { 16, 16, OPERAND_PCREL },
 161         [J16_32] = { 16, 32, OPERAND_PCREL },
 162         [J24_24] = { 24, 24, OPERAND_PCREL },
 163         [J32_16] = { 32, 16, OPERAND_PCREL },
 164         [L4_8]   = {  4,  8, OPERAND_LENGTH },
 165         [L4_12]  = {  4, 12, OPERAND_LENGTH },
 166         [L8_8]   = {  8,  8, OPERAND_LENGTH },
 167         [R_8]    = {  4,  8, OPERAND_GPR },
 168         [R_12]   = {  4, 12, OPERAND_GPR },
 169         [R_16]   = {  4, 16, OPERAND_GPR },
 170         [R_24]   = {  4, 24, OPERAND_GPR },
 171         [R_28]   = {  4, 28, OPERAND_GPR },
 172         [U4_8]   = {  4,  8, 0 },
 173         [U4_12]  = {  4, 12, 0 },
 174         [U4_16]  = {  4, 16, 0 },
 175         [U4_20]  = {  4, 20, 0 },
 176         [U4_24]  = {  4, 24, 0 },
 177         [U4_28]  = {  4, 28, 0 },
 178         [U4_32]  = {  4, 32, 0 },
 179         [U4_36]  = {  4, 36, 0 },
 180         [U8_8]   = {  8,  8, 0 },
 181         [U8_16]  = {  8, 16, 0 },
 182         [U8_24]  = {  8, 24, 0 },
 183         [U8_28]  = {  8, 28, 0 },
 184         [U8_32]  = {  8, 32, 0 },
 185         [U12_16] = { 12, 16, 0 },
 186         [U16_16] = { 16, 16, 0 },
 187         [U16_32] = { 16, 32, 0 },
 188         [U32_16] = { 32, 16, 0 },
 189         [VX_12]  = {  4, 12, OPERAND_INDEX | OPERAND_VR },
 190         [V_8]    = {  4,  8, OPERAND_VR },
 191         [V_12]   = {  4, 12, OPERAND_VR },
 192         [V_16]   = {  4, 16, OPERAND_VR },
 193         [V_32]   = {  4, 32, OPERAND_VR },
 194         [X_12]   = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
 195 };
 196 
 197 static const unsigned char formats[][6] = {
 198         [INSTR_E]            = { 0, 0, 0, 0, 0, 0 },
 199         [INSTR_IE_UU]        = { U4_24, U4_28, 0, 0, 0, 0 },
 200         [INSTR_MII_UPP]      = { U4_8, J12_12, J24_24 },
 201         [INSTR_RIE_R0IU]     = { R_8, I16_16, U4_32, 0, 0, 0 },
 202         [INSTR_RIE_R0UU]     = { R_8, U16_16, U4_32, 0, 0, 0 },
 203         [INSTR_RIE_RRI0]     = { R_8, R_12, I16_16, 0, 0, 0 },
 204         [INSTR_RIE_RRP]      = { R_8, R_12, J16_16, 0, 0, 0 },
 205         [INSTR_RIE_RRPU]     = { R_8, R_12, U4_32, J16_16, 0, 0 },
 206         [INSTR_RIE_RRUUU]    = { R_8, R_12, U8_16, U8_24, U8_32, 0 },
 207         [INSTR_RIE_RUI0]     = { R_8, I16_16, U4_12, 0, 0, 0 },
 208         [INSTR_RIE_RUPI]     = { R_8, I8_32, U4_12, J16_16, 0, 0 },
 209         [INSTR_RIE_RUPU]     = { R_8, U8_32, U4_12, J16_16, 0, 0 },
 210         [INSTR_RIL_RI]       = { R_8, I32_16, 0, 0, 0, 0 },
 211         [INSTR_RIL_RP]       = { R_8, J32_16, 0, 0, 0, 0 },
 212         [INSTR_RIL_RU]       = { R_8, U32_16, 0, 0, 0, 0 },
 213         [INSTR_RIL_UP]       = { U4_8, J32_16, 0, 0, 0, 0 },
 214         [INSTR_RIS_RURDI]    = { R_8, I8_32, U4_12, D_20, B_16, 0 },
 215         [INSTR_RIS_RURDU]    = { R_8, U8_32, U4_12, D_20, B_16, 0 },
 216         [INSTR_RI_RI]        = { R_8, I16_16, 0, 0, 0, 0 },
 217         [INSTR_RI_RP]        = { R_8, J16_16, 0, 0, 0, 0 },
 218         [INSTR_RI_RU]        = { R_8, U16_16, 0, 0, 0, 0 },
 219         [INSTR_RI_UP]        = { U4_8, J16_16, 0, 0, 0, 0 },
 220         [INSTR_RRE_00]       = { 0, 0, 0, 0, 0, 0 },
 221         [INSTR_RRE_AA]       = { A_24, A_28, 0, 0, 0, 0 },
 222         [INSTR_RRE_AR]       = { A_24, R_28, 0, 0, 0, 0 },
 223         [INSTR_RRE_F0]       = { F_24, 0, 0, 0, 0, 0 },
 224         [INSTR_RRE_FF]       = { F_24, F_28, 0, 0, 0, 0 },
 225         [INSTR_RRE_FR]       = { F_24, R_28, 0, 0, 0, 0 },
 226         [INSTR_RRE_R0]       = { R_24, 0, 0, 0, 0, 0 },
 227         [INSTR_RRE_RA]       = { R_24, A_28, 0, 0, 0, 0 },
 228         [INSTR_RRE_RF]       = { R_24, F_28, 0, 0, 0, 0 },
 229         [INSTR_RRE_RR]       = { R_24, R_28, 0, 0, 0, 0 },
 230         [INSTR_RRF_0UFF]     = { F_24, F_28, U4_20, 0, 0, 0 },
 231         [INSTR_RRF_0URF]     = { R_24, F_28, U4_20, 0, 0, 0 },
 232         [INSTR_RRF_F0FF]     = { F_16, F_24, F_28, 0, 0, 0 },
 233         [INSTR_RRF_F0FF2]    = { F_24, F_16, F_28, 0, 0, 0 },
 234         [INSTR_RRF_F0FR]     = { F_24, F_16, R_28, 0, 0, 0 },
 235         [INSTR_RRF_FFRU]     = { F_24, F_16, R_28, U4_20, 0, 0 },
 236         [INSTR_RRF_FUFF]     = { F_24, F_16, F_28, U4_20, 0, 0 },
 237         [INSTR_RRF_FUFF2]    = { F_24, F_28, F_16, U4_20, 0, 0 },
 238         [INSTR_RRF_R0RR]     = { R_24, R_16, R_28, 0, 0, 0 },
 239         [INSTR_RRF_R0RR2]    = { R_24, R_28, R_16, 0, 0, 0 },
 240         [INSTR_RRF_RURR]     = { R_24, R_28, R_16, U4_20, 0, 0 },
 241         [INSTR_RRF_RURR2]    = { R_24, R_16, R_28, U4_20, 0, 0 },
 242         [INSTR_RRF_U0FF]     = { F_24, U4_16, F_28, 0, 0, 0 },
 243         [INSTR_RRF_U0RF]     = { R_24, U4_16, F_28, 0, 0, 0 },
 244         [INSTR_RRF_U0RR]     = { R_24, R_28, U4_16, 0, 0, 0 },
 245         [INSTR_RRF_URR]      = { R_24, R_28, U8_16, 0, 0, 0 },
 246         [INSTR_RRF_UUFF]     = { F_24, U4_16, F_28, U4_20, 0, 0 },
 247         [INSTR_RRF_UUFR]     = { F_24, U4_16, R_28, U4_20, 0, 0 },
 248         [INSTR_RRF_UURF]     = { R_24, U4_16, F_28, U4_20, 0, 0 },
 249         [INSTR_RRS_RRRDU]    = { R_8, R_12, U4_32, D_20, B_16 },
 250         [INSTR_RR_FF]        = { F_8, F_12, 0, 0, 0, 0 },
 251         [INSTR_RR_R0]        = { R_8,  0, 0, 0, 0, 0 },
 252         [INSTR_RR_RR]        = { R_8, R_12, 0, 0, 0, 0 },
 253         [INSTR_RR_U0]        = { U8_8,  0, 0, 0, 0, 0 },
 254         [INSTR_RR_UR]        = { U4_8, R_12, 0, 0, 0, 0 },
 255         [INSTR_RSI_RRP]      = { R_8, R_12, J16_16, 0, 0, 0 },
 256         [INSTR_RSL_LRDFU]    = { F_32, D_20, L8_8, B_16, U4_36, 0 },
 257         [INSTR_RSL_R0RD]     = { D_20, L4_8, B_16, 0, 0, 0 },
 258         [INSTR_RSY_AARD]     = { A_8, A_12, D20_20, B_16, 0, 0 },
 259         [INSTR_RSY_CCRD]     = { C_8, C_12, D20_20, B_16, 0, 0 },
 260         [INSTR_RSY_RDRU]     = { R_8, D20_20, B_16, U4_12, 0, 0 },
 261         [INSTR_RSY_RRRD]     = { R_8, R_12, D20_20, B_16, 0, 0 },
 262         [INSTR_RSY_RURD]     = { R_8, U4_12, D20_20, B_16, 0, 0 },
 263         [INSTR_RSY_RURD2]    = { R_8, D20_20, B_16, U4_12, 0, 0 },
 264         [INSTR_RS_AARD]      = { A_8, A_12, D_20, B_16, 0, 0 },
 265         [INSTR_RS_CCRD]      = { C_8, C_12, D_20, B_16, 0, 0 },
 266         [INSTR_RS_R0RD]      = { R_8, D_20, B_16, 0, 0, 0 },
 267         [INSTR_RS_RRRD]      = { R_8, R_12, D_20, B_16, 0, 0 },
 268         [INSTR_RS_RURD]      = { R_8, U4_12, D_20, B_16, 0, 0 },
 269         [INSTR_RXE_FRRD]     = { F_8, D_20, X_12, B_16, 0, 0 },
 270         [INSTR_RXE_RRRDU]    = { R_8, D_20, X_12, B_16, U4_32, 0 },
 271         [INSTR_RXF_FRRDF]    = { F_32, F_8, D_20, X_12, B_16, 0 },
 272         [INSTR_RXY_FRRD]     = { F_8, D20_20, X_12, B_16, 0, 0 },
 273         [INSTR_RXY_RRRD]     = { R_8, D20_20, X_12, B_16, 0, 0 },
 274         [INSTR_RXY_URRD]     = { U4_8, D20_20, X_12, B_16, 0, 0 },
 275         [INSTR_RX_FRRD]      = { F_8, D_20, X_12, B_16, 0, 0 },
 276         [INSTR_RX_RRRD]      = { R_8, D_20, X_12, B_16, 0, 0 },
 277         [INSTR_RX_URRD]      = { U4_8, D_20, X_12, B_16, 0, 0 },
 278         [INSTR_SIL_RDI]      = { D_20, B_16, I16_32, 0, 0, 0 },
 279         [INSTR_SIL_RDU]      = { D_20, B_16, U16_32, 0, 0, 0 },
 280         [INSTR_SIY_IRD]      = { D20_20, B_16, I8_8, 0, 0, 0 },
 281         [INSTR_SIY_URD]      = { D20_20, B_16, U8_8, 0, 0, 0 },
 282         [INSTR_SI_RD]        = { D_20, B_16, 0, 0, 0, 0 },
 283         [INSTR_SI_URD]       = { D_20, B_16, U8_8, 0, 0, 0 },
 284         [INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
 285         [INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
 286         [INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
 287         [INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
 288         [INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
 289         [INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
 290         [INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
 291         [INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
 292         [INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
 293         [INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
 294         [INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
 295         [INSTR_S_00]         = { 0, 0, 0, 0, 0, 0 },
 296         [INSTR_S_RD]         = { D_20, B_16, 0, 0, 0, 0 },
 297         [INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
 298         [INSTR_VRI_V0U]      = { V_8, U16_16, 0, 0, 0, 0 },
 299         [INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
 300         [INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
 301         [INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
 302         [INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
 303         [INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
 304         [INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
 305         [INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
 306         [INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
 307         [INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
 308         [INSTR_VRR_0V]       = { V_12, 0, 0, 0, 0, 0 },
 309         [INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
 310         [INSTR_VRR_RV0UU]    = { R_8, V_12, U4_24, U4_28, 0, 0 },
 311         [INSTR_VRR_VRR]      = { V_8, R_12, R_16, 0, 0, 0 },
 312         [INSTR_VRR_VV]       = { V_8, V_12, 0, 0, 0, 0 },
 313         [INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
 314         [INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
 315         [INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
 316         [INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
 317         [INSTR_VRR_VVV]      = { V_8, V_12, V_16, 0, 0, 0 },
 318         [INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
 319         [INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
 320         [INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
 321         [INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
 322         [INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
 323         [INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
 324         [INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
 325         [INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
 326         [INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
 327         [INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
 328         [INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
 329         [INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
 330         [INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
 331         [INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
 332         [INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
 333         [INSTR_VRX_VV]       = { V_8, V_12, 0, 0, 0, 0 },
 334         [INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
 335 };
 336 
 337 static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
 338 static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
 339 static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
 340 
 341 /* Extracts an operand value from an instruction.  */
 342 static unsigned int extract_operand(unsigned char *code,
 343                                     const struct s390_operand *operand)
 344 {
 345         unsigned char *cp;
 346         unsigned int val;
 347         int bits;
 348 
 349         /* Extract fragments of the operand byte for byte.  */
 350         cp = code + operand->shift / 8;
 351         bits = (operand->shift & 7) + operand->bits;
 352         val = 0;
 353         do {
 354                 val <<= 8;
 355                 val |= (unsigned int) *cp++;
 356                 bits -= 8;
 357         } while (bits > 0);
 358         val >>= -bits;
 359         val &= ((1U << (operand->bits - 1)) << 1) - 1;
 360 
 361         /* Check for special long displacement case.  */
 362         if (operand->bits == 20 && operand->shift == 20)
 363                 val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
 364 
 365         /* Check for register extensions bits for vector registers. */
 366         if (operand->flags & OPERAND_VR) {
 367                 if (operand->shift == 8)
 368                         val |= (code[4] & 8) << 1;
 369                 else if (operand->shift == 12)
 370                         val |= (code[4] & 4) << 2;
 371                 else if (operand->shift == 16)
 372                         val |= (code[4] & 2) << 3;
 373                 else if (operand->shift == 32)
 374                         val |= (code[4] & 1) << 4;
 375         }
 376 
 377         /* Sign extend value if the operand is signed or pc relative.  */
 378         if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
 379             (val & (1U << (operand->bits - 1))))
 380                 val |= (-1U << (operand->bits - 1)) << 1;
 381 
 382         /* Double value if the operand is pc relative.  */
 383         if (operand->flags & OPERAND_PCREL)
 384                 val <<= 1;
 385 
 386         /* Length x in an instructions has real length x + 1.  */
 387         if (operand->flags & OPERAND_LENGTH)
 388                 val++;
 389         return val;
 390 }
 391 
 392 struct s390_insn *find_insn(unsigned char *code)
 393 {
 394         struct s390_opcode_offset *entry;
 395         struct s390_insn *insn;
 396         unsigned char opfrag;
 397         int i;
 398 
 399         /* Search the opcode offset table to find an entry which
 400          * matches the beginning of the opcode. If there is no match
 401          * the last entry will be used, which is the default entry for
 402          * unknown instructions as well as 1-byte opcode instructions.
 403          */
 404         for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
 405                 entry = &opcode_offset[i];
 406                 if (entry->opcode == code[0])
 407                         break;
 408         }
 409 
 410         opfrag = *(code + entry->byte) & entry->mask;
 411 
 412         insn = &opcode[entry->offset];
 413         for (i = 0; i < entry->count; i++) {
 414                 if (insn->opfrag == opfrag)
 415                         return insn;
 416                 insn++;
 417         }
 418         return NULL;
 419 }
 420 
 421 static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
 422 {
 423         struct s390_insn *insn;
 424         const unsigned char *ops;
 425         const struct s390_operand *operand;
 426         unsigned int value;
 427         char separator;
 428         char *ptr;
 429         int i;
 430 
 431         ptr = buffer;
 432         insn = find_insn(code);
 433         if (insn) {
 434                 if (insn->zero == 0)
 435                         ptr += sprintf(ptr, "%.7s\t",
 436                                        long_insn_name[insn->offset]);
 437                 else
 438                         ptr += sprintf(ptr, "%.5s\t", insn->name);
 439                 /* Extract the operands. */
 440                 separator = 0;
 441                 for (ops = formats[insn->format], i = 0;
 442                      *ops != 0 && i < 6; ops++, i++) {
 443                         operand = operands + *ops;
 444                         value = extract_operand(code, operand);
 445                         if ((operand->flags & OPERAND_INDEX)  && value == 0)
 446                                 continue;
 447                         if ((operand->flags & OPERAND_BASE) &&
 448                             value == 0 && separator == '(') {
 449                                 separator = ',';
 450                                 continue;
 451                         }
 452                         if (separator)
 453                                 ptr += sprintf(ptr, "%c", separator);
 454                         if (operand->flags & OPERAND_GPR)
 455                                 ptr += sprintf(ptr, "%%r%i", value);
 456                         else if (operand->flags & OPERAND_FPR)
 457                                 ptr += sprintf(ptr, "%%f%i", value);
 458                         else if (operand->flags & OPERAND_AR)
 459                                 ptr += sprintf(ptr, "%%a%i", value);
 460                         else if (operand->flags & OPERAND_CR)
 461                                 ptr += sprintf(ptr, "%%c%i", value);
 462                         else if (operand->flags & OPERAND_VR)
 463                                 ptr += sprintf(ptr, "%%v%i", value);
 464                         else if (operand->flags & OPERAND_PCREL) {
 465                                 void *pcrel = (void *)((int)value + addr);
 466 
 467                                 ptr += sprintf(ptr, "%px", pcrel);
 468                         } else if (operand->flags & OPERAND_SIGNED)
 469                                 ptr += sprintf(ptr, "%i", value);
 470                         else
 471                                 ptr += sprintf(ptr, "%u", value);
 472                         if (operand->flags & OPERAND_DISP)
 473                                 separator = '(';
 474                         else if (operand->flags & OPERAND_BASE) {
 475                                 ptr += sprintf(ptr, ")");
 476                                 separator = ',';
 477                         } else
 478                                 separator = ',';
 479                 }
 480         } else
 481                 ptr += sprintf(ptr, "unknown");
 482         return (int) (ptr - buffer);
 483 }
 484 
 485 void show_code(struct pt_regs *regs)
 486 {
 487         char *mode = user_mode(regs) ? "User" : "Krnl";
 488         unsigned char code[64];
 489         char buffer[128], *ptr;
 490         mm_segment_t old_fs;
 491         unsigned long addr;
 492         int start, end, opsize, hops, i;
 493 
 494         /* Get a snapshot of the 64 bytes surrounding the fault address. */
 495         old_fs = get_fs();
 496         set_fs(user_mode(regs) ? USER_DS : KERNEL_DS);
 497         for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
 498                 addr = regs->psw.addr - 34 + start;
 499                 if (__copy_from_user(code + start - 2,
 500                                      (char __user *) addr, 2))
 501                         break;
 502         }
 503         for (end = 32; end < 64; end += 2) {
 504                 addr = regs->psw.addr + end - 32;
 505                 if (__copy_from_user(code + end,
 506                                      (char __user *) addr, 2))
 507                         break;
 508         }
 509         set_fs(old_fs);
 510         /* Code snapshot useable ? */
 511         if ((regs->psw.addr & 1) || start >= end) {
 512                 printk("%s Code: Bad PSW.\n", mode);
 513                 return;
 514         }
 515         /* Find a starting point for the disassembly. */
 516         while (start < 32) {
 517                 for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
 518                         if (!find_insn(code + start + i))
 519                                 break;
 520                         i += insn_length(code[start + i]);
 521                 }
 522                 if (start + i == 32)
 523                         /* Looks good, sequence ends at PSW. */
 524                         break;
 525                 start += 2;
 526         }
 527         /* Decode the instructions. */
 528         ptr = buffer;
 529         ptr += sprintf(ptr, "%s Code:", mode);
 530         hops = 0;
 531         while (start < end && hops < 8) {
 532                 opsize = insn_length(code[start]);
 533                 if  (start + opsize == 32)
 534                         *ptr++ = '#';
 535                 else if (start == 32)
 536                         *ptr++ = '>';
 537                 else
 538                         *ptr++ = ' ';
 539                 addr = regs->psw.addr + start - 32;
 540                 ptr += sprintf(ptr, "%px: ", (void *)addr);
 541                 if (start + opsize >= end)
 542                         break;
 543                 for (i = 0; i < opsize; i++)
 544                         ptr += sprintf(ptr, "%02x", code[start + i]);
 545                 *ptr++ = '\t';
 546                 if (i < 6)
 547                         *ptr++ = '\t';
 548                 ptr += print_insn(ptr, code + start, addr);
 549                 start += opsize;
 550                 pr_cont("%s", buffer);
 551                 ptr = buffer;
 552                 ptr += sprintf(ptr, "\n          ");
 553                 hops++;
 554         }
 555         pr_cont("\n");
 556 }
 557 
 558 void print_fn_code(unsigned char *code, unsigned long len)
 559 {
 560         char buffer[64], *ptr;
 561         int opsize, i;
 562 
 563         while (len) {
 564                 ptr = buffer;
 565                 opsize = insn_length(*code);
 566                 if (opsize > len)
 567                         break;
 568                 ptr += sprintf(ptr, "%px: ", code);
 569                 for (i = 0; i < opsize; i++)
 570                         ptr += sprintf(ptr, "%02x", code[i]);
 571                 *ptr++ = '\t';
 572                 if (i < 4)
 573                         *ptr++ = '\t';
 574                 ptr += print_insn(ptr, code, (unsigned long) code);
 575                 *ptr++ = '\n';
 576                 *ptr++ = 0;
 577                 printk("%s", buffer);
 578                 code += opsize;
 579                 len -= opsize;
 580         }
 581 }

/* [<][>][^][v][top][bottom][index][help] */