Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Disassemble s390 instructions.
0004  *
0005  * Copyright IBM Corp. 2007
0006  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
0007  */
0008 
0009 #include <linux/sched.h>
0010 #include <linux/kernel.h>
0011 #include <linux/string.h>
0012 #include <linux/errno.h>
0013 #include <linux/ptrace.h>
0014 #include <linux/timer.h>
0015 #include <linux/mm.h>
0016 #include <linux/smp.h>
0017 #include <linux/init.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/delay.h>
0020 #include <linux/export.h>
0021 #include <linux/kallsyms.h>
0022 #include <linux/reboot.h>
0023 #include <linux/kprobes.h>
0024 #include <linux/kdebug.h>
0025 #include <linux/uaccess.h>
0026 #include <linux/atomic.h>
0027 #include <asm/dis.h>
0028 #include <asm/io.h>
0029 #include <asm/cpcmd.h>
0030 #include <asm/lowcore.h>
0031 #include <asm/debug.h>
0032 #include <asm/irq.h>
0033 
0034 /* Type of operand */
0035 #define OPERAND_GPR 0x1 /* Operand printed as %rx */
0036 #define OPERAND_FPR 0x2 /* Operand printed as %fx */
0037 #define OPERAND_AR  0x4 /* Operand printed as %ax */
0038 #define OPERAND_CR  0x8 /* Operand printed as %cx */
0039 #define OPERAND_VR  0x10    /* Operand printed as %vx */
0040 #define OPERAND_DISP    0x20    /* Operand printed as displacement */
0041 #define OPERAND_BASE    0x40    /* Operand printed as base register */
0042 #define OPERAND_INDEX   0x80    /* Operand printed as index register */
0043 #define OPERAND_PCREL   0x100   /* Operand printed as pc-relative symbol */
0044 #define OPERAND_SIGNED  0x200   /* Operand printed as signed value */
0045 #define OPERAND_LENGTH  0x400   /* Operand printed as length (+1) */
0046 
0047 struct s390_operand {
0048     unsigned char bits; /* The number of bits in the operand. */
0049     unsigned char shift;    /* The number of bits to shift. */
0050     unsigned short flags;   /* One bit syntax flags. */
0051 };
0052 
0053 struct s390_insn {
0054     union {
0055         const char name[5];
0056         struct {
0057             unsigned char zero;
0058             unsigned int offset;
0059         } __packed;
0060     };
0061     unsigned char opfrag;
0062     unsigned char format;
0063 };
0064 
0065 struct s390_opcode_offset {
0066     unsigned char opcode;
0067     unsigned char mask;
0068     unsigned char byte;
0069     unsigned short offset;
0070     unsigned short count;
0071 } __packed;
0072 
0073 enum {
0074     UNUSED,
0075     A_8,    /* Access reg. starting at position 8 */
0076     A_12,   /* Access reg. starting at position 12 */
0077     A_24,   /* Access reg. starting at position 24 */
0078     A_28,   /* Access reg. starting at position 28 */
0079     B_16,   /* Base register starting at position 16 */
0080     B_32,   /* Base register starting at position 32 */
0081     C_8,    /* Control reg. starting at position 8 */
0082     C_12,   /* Control reg. starting at position 12 */
0083     D20_20, /* 20 bit displacement starting at 20 */
0084     D_20,   /* Displacement starting at position 20 */
0085     D_36,   /* Displacement starting at position 36 */
0086     F_8,    /* FPR starting at position 8 */
0087     F_12,   /* FPR starting at position 12 */
0088     F_16,   /* FPR starting at position 16 */
0089     F_24,   /* FPR starting at position 24 */
0090     F_28,   /* FPR starting at position 28 */
0091     F_32,   /* FPR starting at position 32 */
0092     I8_8,   /* 8 bit signed value starting at 8 */
0093     I8_32,  /* 8 bit signed value starting at 32 */
0094     I16_16, /* 16 bit signed value starting at 16 */
0095     I16_32, /* 16 bit signed value starting at 32 */
0096     I32_16, /* 32 bit signed value starting at 16 */
0097     J12_12, /* 12 bit PC relative offset at 12 */
0098     J16_16, /* 16 bit PC relative offset at 16 */
0099     J16_32, /* 16 bit PC relative offset at 32 */
0100     J24_24, /* 24 bit PC relative offset at 24 */
0101     J32_16, /* 32 bit PC relative offset at 16 */
0102     L4_8,   /* 4 bit length starting at position 8 */
0103     L4_12,  /* 4 bit length starting at position 12 */
0104     L8_8,   /* 8 bit length starting at position 8 */
0105     R_8,    /* GPR starting at position 8 */
0106     R_12,   /* GPR starting at position 12 */
0107     R_16,   /* GPR starting at position 16 */
0108     R_24,   /* GPR starting at position 24 */
0109     R_28,   /* GPR starting at position 28 */
0110     U4_8,   /* 4 bit unsigned value starting at 8 */
0111     U4_12,  /* 4 bit unsigned value starting at 12 */
0112     U4_16,  /* 4 bit unsigned value starting at 16 */
0113     U4_20,  /* 4 bit unsigned value starting at 20 */
0114     U4_24,  /* 4 bit unsigned value starting at 24 */
0115     U4_28,  /* 4 bit unsigned value starting at 28 */
0116     U4_32,  /* 4 bit unsigned value starting at 32 */
0117     U4_36,  /* 4 bit unsigned value starting at 36 */
0118     U8_8,   /* 8 bit unsigned value starting at 8 */
0119     U8_16,  /* 8 bit unsigned value starting at 16 */
0120     U8_24,  /* 8 bit unsigned value starting at 24 */
0121     U8_28,  /* 8 bit unsigned value starting at 28 */
0122     U8_32,  /* 8 bit unsigned value starting at 32 */
0123     U12_16, /* 12 bit unsigned value starting at 16 */
0124     U16_16, /* 16 bit unsigned value starting at 16 */
0125     U16_32, /* 16 bit unsigned value starting at 32 */
0126     U32_16, /* 32 bit unsigned value starting at 16 */
0127     VX_12,  /* Vector index register starting at position 12 */
0128     V_8,    /* Vector reg. starting at position 8 */
0129     V_12,   /* Vector reg. starting at position 12 */
0130     V_16,   /* Vector reg. starting at position 16 */
0131     V_32,   /* Vector reg. starting at position 32 */
0132     X_12,   /* Index register starting at position 12 */
0133 };
0134 
0135 static const struct s390_operand operands[] = {
0136     [UNUSED] = {  0,  0, 0 },
0137     [A_8]    = {  4,  8, OPERAND_AR },
0138     [A_12]   = {  4, 12, OPERAND_AR },
0139     [A_24]   = {  4, 24, OPERAND_AR },
0140     [A_28]   = {  4, 28, OPERAND_AR },
0141     [B_16]   = {  4, 16, OPERAND_BASE | OPERAND_GPR },
0142     [B_32]   = {  4, 32, OPERAND_BASE | OPERAND_GPR },
0143     [C_8]    = {  4,  8, OPERAND_CR },
0144     [C_12]   = {  4, 12, OPERAND_CR },
0145     [D20_20] = { 20, 20, OPERAND_DISP | OPERAND_SIGNED },
0146     [D_20]   = { 12, 20, OPERAND_DISP },
0147     [D_36]   = { 12, 36, OPERAND_DISP },
0148     [F_8]    = {  4,  8, OPERAND_FPR },
0149     [F_12]   = {  4, 12, OPERAND_FPR },
0150     [F_16]   = {  4, 16, OPERAND_FPR },
0151     [F_24]   = {  4, 24, OPERAND_FPR },
0152     [F_28]   = {  4, 28, OPERAND_FPR },
0153     [F_32]   = {  4, 32, OPERAND_FPR },
0154     [I8_8]   = {  8,  8, OPERAND_SIGNED },
0155     [I8_32]  = {  8, 32, OPERAND_SIGNED },
0156     [I16_16] = { 16, 16, OPERAND_SIGNED },
0157     [I16_32] = { 16, 32, OPERAND_SIGNED },
0158     [I32_16] = { 32, 16, OPERAND_SIGNED },
0159     [J12_12] = { 12, 12, OPERAND_PCREL },
0160     [J16_16] = { 16, 16, OPERAND_PCREL },
0161     [J16_32] = { 16, 32, OPERAND_PCREL },
0162     [J24_24] = { 24, 24, OPERAND_PCREL },
0163     [J32_16] = { 32, 16, OPERAND_PCREL },
0164     [L4_8]   = {  4,  8, OPERAND_LENGTH },
0165     [L4_12]  = {  4, 12, OPERAND_LENGTH },
0166     [L8_8]   = {  8,  8, OPERAND_LENGTH },
0167     [R_8]    = {  4,  8, OPERAND_GPR },
0168     [R_12]   = {  4, 12, OPERAND_GPR },
0169     [R_16]   = {  4, 16, OPERAND_GPR },
0170     [R_24]   = {  4, 24, OPERAND_GPR },
0171     [R_28]   = {  4, 28, OPERAND_GPR },
0172     [U4_8]   = {  4,  8, 0 },
0173     [U4_12]  = {  4, 12, 0 },
0174     [U4_16]  = {  4, 16, 0 },
0175     [U4_20]  = {  4, 20, 0 },
0176     [U4_24]  = {  4, 24, 0 },
0177     [U4_28]  = {  4, 28, 0 },
0178     [U4_32]  = {  4, 32, 0 },
0179     [U4_36]  = {  4, 36, 0 },
0180     [U8_8]   = {  8,  8, 0 },
0181     [U8_16]  = {  8, 16, 0 },
0182     [U8_24]  = {  8, 24, 0 },
0183     [U8_28]  = {  8, 28, 0 },
0184     [U8_32]  = {  8, 32, 0 },
0185     [U12_16] = { 12, 16, 0 },
0186     [U16_16] = { 16, 16, 0 },
0187     [U16_32] = { 16, 32, 0 },
0188     [U32_16] = { 32, 16, 0 },
0189     [VX_12]  = {  4, 12, OPERAND_INDEX | OPERAND_VR },
0190     [V_8]    = {  4,  8, OPERAND_VR },
0191     [V_12]   = {  4, 12, OPERAND_VR },
0192     [V_16]   = {  4, 16, OPERAND_VR },
0193     [V_32]   = {  4, 32, OPERAND_VR },
0194     [X_12]   = {  4, 12, OPERAND_INDEX | OPERAND_GPR },
0195 };
0196 
0197 static const unsigned char formats[][6] = {
0198     [INSTR_E]        = { 0, 0, 0, 0, 0, 0 },
0199     [INSTR_IE_UU]        = { U4_24, U4_28, 0, 0, 0, 0 },
0200     [INSTR_MII_UPP]      = { U4_8, J12_12, J24_24 },
0201     [INSTR_RIE_R0IU]     = { R_8, I16_16, U4_32, 0, 0, 0 },
0202     [INSTR_RIE_R0UU]     = { R_8, U16_16, U4_32, 0, 0, 0 },
0203     [INSTR_RIE_RRI0]     = { R_8, R_12, I16_16, 0, 0, 0 },
0204     [INSTR_RIE_RRP]      = { R_8, R_12, J16_16, 0, 0, 0 },
0205     [INSTR_RIE_RRPU]     = { R_8, R_12, U4_32, J16_16, 0, 0 },
0206     [INSTR_RIE_RRUUU]    = { R_8, R_12, U8_16, U8_24, U8_32, 0 },
0207     [INSTR_RIE_RUI0]     = { R_8, I16_16, U4_12, 0, 0, 0 },
0208     [INSTR_RIE_RUPI]     = { R_8, I8_32, U4_12, J16_16, 0, 0 },
0209     [INSTR_RIE_RUPU]     = { R_8, U8_32, U4_12, J16_16, 0, 0 },
0210     [INSTR_RIL_RI]       = { R_8, I32_16, 0, 0, 0, 0 },
0211     [INSTR_RIL_RP]       = { R_8, J32_16, 0, 0, 0, 0 },
0212     [INSTR_RIL_RU]       = { R_8, U32_16, 0, 0, 0, 0 },
0213     [INSTR_RIL_UP]       = { U4_8, J32_16, 0, 0, 0, 0 },
0214     [INSTR_RIS_RURDI]    = { R_8, I8_32, U4_12, D_20, B_16, 0 },
0215     [INSTR_RIS_RURDU]    = { R_8, U8_32, U4_12, D_20, B_16, 0 },
0216     [INSTR_RI_RI]        = { R_8, I16_16, 0, 0, 0, 0 },
0217     [INSTR_RI_RP]        = { R_8, J16_16, 0, 0, 0, 0 },
0218     [INSTR_RI_RU]        = { R_8, U16_16, 0, 0, 0, 0 },
0219     [INSTR_RI_UP]        = { U4_8, J16_16, 0, 0, 0, 0 },
0220     [INSTR_RRE_00]       = { 0, 0, 0, 0, 0, 0 },
0221     [INSTR_RRE_AA]       = { A_24, A_28, 0, 0, 0, 0 },
0222     [INSTR_RRE_AR]       = { A_24, R_28, 0, 0, 0, 0 },
0223     [INSTR_RRE_F0]       = { F_24, 0, 0, 0, 0, 0 },
0224     [INSTR_RRE_FF]       = { F_24, F_28, 0, 0, 0, 0 },
0225     [INSTR_RRE_FR]       = { F_24, R_28, 0, 0, 0, 0 },
0226     [INSTR_RRE_R0]       = { R_24, 0, 0, 0, 0, 0 },
0227     [INSTR_RRE_RA]       = { R_24, A_28, 0, 0, 0, 0 },
0228     [INSTR_RRE_RF]       = { R_24, F_28, 0, 0, 0, 0 },
0229     [INSTR_RRE_RR]       = { R_24, R_28, 0, 0, 0, 0 },
0230     [INSTR_RRF_0UFF]     = { F_24, F_28, U4_20, 0, 0, 0 },
0231     [INSTR_RRF_0URF]     = { R_24, F_28, U4_20, 0, 0, 0 },
0232     [INSTR_RRF_F0FF]     = { F_16, F_24, F_28, 0, 0, 0 },
0233     [INSTR_RRF_F0FF2]    = { F_24, F_16, F_28, 0, 0, 0 },
0234     [INSTR_RRF_F0FR]     = { F_24, F_16, R_28, 0, 0, 0 },
0235     [INSTR_RRF_FFRU]     = { F_24, F_16, R_28, U4_20, 0, 0 },
0236     [INSTR_RRF_FUFF]     = { F_24, F_16, F_28, U4_20, 0, 0 },
0237     [INSTR_RRF_FUFF2]    = { F_24, F_28, F_16, U4_20, 0, 0 },
0238     [INSTR_RRF_R0RR]     = { R_24, R_16, R_28, 0, 0, 0 },
0239     [INSTR_RRF_R0RR2]    = { R_24, R_28, R_16, 0, 0, 0 },
0240     [INSTR_RRF_RURR]     = { R_24, R_28, R_16, U4_20, 0, 0 },
0241     [INSTR_RRF_RURR2]    = { R_24, R_16, R_28, U4_20, 0, 0 },
0242     [INSTR_RRF_U0FF]     = { F_24, U4_16, F_28, 0, 0, 0 },
0243     [INSTR_RRF_U0RF]     = { R_24, U4_16, F_28, 0, 0, 0 },
0244     [INSTR_RRF_U0RR]     = { R_24, R_28, U4_16, 0, 0, 0 },
0245     [INSTR_RRF_URR]      = { R_24, R_28, U8_16, 0, 0, 0 },
0246     [INSTR_RRF_UUFF]     = { F_24, U4_16, F_28, U4_20, 0, 0 },
0247     [INSTR_RRF_UUFR]     = { F_24, U4_16, R_28, U4_20, 0, 0 },
0248     [INSTR_RRF_UURF]     = { R_24, U4_16, F_28, U4_20, 0, 0 },
0249     [INSTR_RRS_RRRDU]    = { R_8, R_12, U4_32, D_20, B_16 },
0250     [INSTR_RR_FF]        = { F_8, F_12, 0, 0, 0, 0 },
0251     [INSTR_RR_R0]        = { R_8,  0, 0, 0, 0, 0 },
0252     [INSTR_RR_RR]        = { R_8, R_12, 0, 0, 0, 0 },
0253     [INSTR_RR_U0]        = { U8_8,  0, 0, 0, 0, 0 },
0254     [INSTR_RR_UR]        = { U4_8, R_12, 0, 0, 0, 0 },
0255     [INSTR_RSI_RRP]      = { R_8, R_12, J16_16, 0, 0, 0 },
0256     [INSTR_RSL_LRDFU]    = { F_32, D_20, L8_8, B_16, U4_36, 0 },
0257     [INSTR_RSL_R0RD]     = { D_20, L4_8, B_16, 0, 0, 0 },
0258     [INSTR_RSY_AARD]     = { A_8, A_12, D20_20, B_16, 0, 0 },
0259     [INSTR_RSY_CCRD]     = { C_8, C_12, D20_20, B_16, 0, 0 },
0260     [INSTR_RSY_RDRU]     = { R_8, D20_20, B_16, U4_12, 0, 0 },
0261     [INSTR_RSY_RRRD]     = { R_8, R_12, D20_20, B_16, 0, 0 },
0262     [INSTR_RSY_RURD]     = { R_8, U4_12, D20_20, B_16, 0, 0 },
0263     [INSTR_RSY_RURD2]    = { R_8, D20_20, B_16, U4_12, 0, 0 },
0264     [INSTR_RS_AARD]      = { A_8, A_12, D_20, B_16, 0, 0 },
0265     [INSTR_RS_CCRD]      = { C_8, C_12, D_20, B_16, 0, 0 },
0266     [INSTR_RS_R0RD]      = { R_8, D_20, B_16, 0, 0, 0 },
0267     [INSTR_RS_RRRD]      = { R_8, R_12, D_20, B_16, 0, 0 },
0268     [INSTR_RS_RURD]      = { R_8, U4_12, D_20, B_16, 0, 0 },
0269     [INSTR_RXE_FRRD]     = { F_8, D_20, X_12, B_16, 0, 0 },
0270     [INSTR_RXE_RRRDU]    = { R_8, D_20, X_12, B_16, U4_32, 0 },
0271     [INSTR_RXF_FRRDF]    = { F_32, F_8, D_20, X_12, B_16, 0 },
0272     [INSTR_RXY_FRRD]     = { F_8, D20_20, X_12, B_16, 0, 0 },
0273     [INSTR_RXY_RRRD]     = { R_8, D20_20, X_12, B_16, 0, 0 },
0274     [INSTR_RXY_URRD]     = { U4_8, D20_20, X_12, B_16, 0, 0 },
0275     [INSTR_RX_FRRD]      = { F_8, D_20, X_12, B_16, 0, 0 },
0276     [INSTR_RX_RRRD]      = { R_8, D_20, X_12, B_16, 0, 0 },
0277     [INSTR_RX_URRD]      = { U4_8, D_20, X_12, B_16, 0, 0 },
0278     [INSTR_SIL_RDI]      = { D_20, B_16, I16_32, 0, 0, 0 },
0279     [INSTR_SIL_RDU]      = { D_20, B_16, U16_32, 0, 0, 0 },
0280     [INSTR_SIY_IRD]      = { D20_20, B_16, I8_8, 0, 0, 0 },
0281     [INSTR_SIY_RD]       = { D20_20, B_16, 0, 0, 0, 0 },
0282     [INSTR_SIY_URD]      = { D20_20, B_16, U8_8, 0, 0, 0 },
0283     [INSTR_SI_RD]        = { D_20, B_16, 0, 0, 0, 0 },
0284     [INSTR_SI_URD]       = { D_20, B_16, U8_8, 0, 0, 0 },
0285     [INSTR_SMI_U0RDP]    = { U4_8, J16_32, D_20, B_16, 0, 0 },
0286     [INSTR_SSE_RDRD]     = { D_20, B_16, D_36, B_32, 0, 0 },
0287     [INSTR_SSF_RRDRD]    = { D_20, B_16, D_36, B_32, R_8, 0 },
0288     [INSTR_SSF_RRDRD2]   = { R_8, D_20, B_16, D_36, B_32, 0 },
0289     [INSTR_SS_L0RDRD]    = { D_20, L8_8, B_16, D_36, B_32, 0 },
0290     [INSTR_SS_L2RDRD]    = { D_20, B_16, D_36, L8_8, B_32, 0 },
0291     [INSTR_SS_LIRDRD]    = { D_20, L4_8, B_16, D_36, B_32, U4_12 },
0292     [INSTR_SS_LLRDRD]    = { D_20, L4_8, B_16, D_36, L4_12, B_32 },
0293     [INSTR_SS_RRRDRD]    = { D_20, R_8, B_16, D_36, B_32, R_12 },
0294     [INSTR_SS_RRRDRD2]   = { R_8, D_20, B_16, R_12, D_36, B_32 },
0295     [INSTR_SS_RRRDRD3]   = { R_8, R_12, D_20, B_16, D_36, B_32 },
0296     [INSTR_S_00]         = { 0, 0, 0, 0, 0, 0 },
0297     [INSTR_S_RD]         = { D_20, B_16, 0, 0, 0, 0 },
0298     [INSTR_VRI_V0IU]     = { V_8, I16_16, U4_32, 0, 0, 0 },
0299     [INSTR_VRI_V0U]      = { V_8, U16_16, 0, 0, 0, 0 },
0300     [INSTR_VRI_V0UU2]    = { V_8, U16_16, U4_32, 0, 0, 0 },
0301     [INSTR_VRI_V0UUU]    = { V_8, U8_16, U8_24, U4_32, 0, 0 },
0302     [INSTR_VRI_VR0UU]    = { V_8, R_12, U8_28, U4_24, 0, 0 },
0303     [INSTR_VRI_VVUU]     = { V_8, V_12, U16_16, U4_32, 0, 0 },
0304     [INSTR_VRI_VVUUU]    = { V_8, V_12, U12_16, U4_32, U4_28, 0 },
0305     [INSTR_VRI_VVUUU2]   = { V_8, V_12, U8_28, U8_16, U4_24, 0 },
0306     [INSTR_VRI_VVV0U]    = { V_8, V_12, V_16, U8_24, 0, 0 },
0307     [INSTR_VRI_VVV0UU]   = { V_8, V_12, V_16, U8_24, U4_32, 0 },
0308     [INSTR_VRI_VVV0UU2]  = { V_8, V_12, V_16, U8_28, U4_24, 0 },
0309     [INSTR_VRR_0V]       = { V_12, 0, 0, 0, 0, 0 },
0310     [INSTR_VRR_0VV0U]    = { V_12, V_16, U4_24, 0, 0, 0 },
0311     [INSTR_VRR_RV0UU]    = { R_8, V_12, U4_24, U4_28, 0, 0 },
0312     [INSTR_VRR_VRR]      = { V_8, R_12, R_16, 0, 0, 0 },
0313     [INSTR_VRR_VV]       = { V_8, V_12, 0, 0, 0, 0 },
0314     [INSTR_VRR_VV0U]     = { V_8, V_12, U4_32, 0, 0, 0 },
0315     [INSTR_VRR_VV0U0U]   = { V_8, V_12, U4_32, U4_24, 0, 0 },
0316     [INSTR_VRR_VV0U2]    = { V_8, V_12, U4_24, 0, 0, 0 },
0317     [INSTR_VRR_VV0UU2]   = { V_8, V_12, U4_32, U4_28, 0, 0 },
0318     [INSTR_VRR_VV0UUU]   = { V_8, V_12, U4_32, U4_28, U4_24, 0 },
0319     [INSTR_VRR_VVV]      = { V_8, V_12, V_16, 0, 0, 0 },
0320     [INSTR_VRR_VVV0U]    = { V_8, V_12, V_16, U4_32, 0, 0 },
0321     [INSTR_VRR_VVV0U0]   = { V_8, V_12, V_16, U4_24, 0, 0 },
0322     [INSTR_VRR_VVV0U0U]  = { V_8, V_12, V_16, U4_32, U4_24, 0 },
0323     [INSTR_VRR_VVV0UU]   = { V_8, V_12, V_16, U4_32, U4_28, 0 },
0324     [INSTR_VRR_VVV0UUU]  = { V_8, V_12, V_16, U4_32, U4_28, U4_24 },
0325     [INSTR_VRR_VVV0V]    = { V_8, V_12, V_16, V_32, 0, 0 },
0326     [INSTR_VRR_VVVU0UV]  = { V_8, V_12, V_16, V_32, U4_28, U4_20 },
0327     [INSTR_VRR_VVVU0V]   = { V_8, V_12, V_16, V_32, U4_20, 0 },
0328     [INSTR_VRR_VVVUU0V]  = { V_8, V_12, V_16, V_32, U4_20, U4_24 },
0329     [INSTR_VRS_RRDV]     = { V_32, R_12, D_20, B_16, 0, 0 },
0330     [INSTR_VRS_RVRDU]    = { R_8, V_12, D_20, B_16, U4_32, 0 },
0331     [INSTR_VRS_VRRD]     = { V_8, R_12, D_20, B_16, 0, 0 },
0332     [INSTR_VRS_VRRDU]    = { V_8, R_12, D_20, B_16, U4_32, 0 },
0333     [INSTR_VRS_VVRDU]    = { V_8, V_12, D_20, B_16, U4_32, 0 },
0334     [INSTR_VRV_VVXRDU]   = { V_8, D_20, VX_12, B_16, U4_32, 0 },
0335     [INSTR_VRX_VRRDU]    = { V_8, D_20, X_12, B_16, U4_32, 0 },
0336     [INSTR_VRX_VV]       = { V_8, V_12, 0, 0, 0, 0 },
0337     [INSTR_VSI_URDV]     = { V_32, D_20, B_16, U8_8, 0, 0 },
0338 };
0339 
0340 static char long_insn_name[][7] = LONG_INSN_INITIALIZER;
0341 static struct s390_insn opcode[] = OPCODE_TABLE_INITIALIZER;
0342 static struct s390_opcode_offset opcode_offset[] = OPCODE_OFFSET_INITIALIZER;
0343 
0344 /* Extracts an operand value from an instruction.  */
0345 static unsigned int extract_operand(unsigned char *code,
0346                     const struct s390_operand *operand)
0347 {
0348     unsigned char *cp;
0349     unsigned int val;
0350     int bits;
0351 
0352     /* Extract fragments of the operand byte for byte.  */
0353     cp = code + operand->shift / 8;
0354     bits = (operand->shift & 7) + operand->bits;
0355     val = 0;
0356     do {
0357         val <<= 8;
0358         val |= (unsigned int) *cp++;
0359         bits -= 8;
0360     } while (bits > 0);
0361     val >>= -bits;
0362     val &= ((1U << (operand->bits - 1)) << 1) - 1;
0363 
0364     /* Check for special long displacement case.  */
0365     if (operand->bits == 20 && operand->shift == 20)
0366         val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
0367 
0368     /* Check for register extensions bits for vector registers. */
0369     if (operand->flags & OPERAND_VR) {
0370         if (operand->shift == 8)
0371             val |= (code[4] & 8) << 1;
0372         else if (operand->shift == 12)
0373             val |= (code[4] & 4) << 2;
0374         else if (operand->shift == 16)
0375             val |= (code[4] & 2) << 3;
0376         else if (operand->shift == 32)
0377             val |= (code[4] & 1) << 4;
0378     }
0379 
0380     /* Sign extend value if the operand is signed or pc relative.  */
0381     if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
0382         (val & (1U << (operand->bits - 1))))
0383         val |= (-1U << (operand->bits - 1)) << 1;
0384 
0385     /* Double value if the operand is pc relative.  */
0386     if (operand->flags & OPERAND_PCREL)
0387         val <<= 1;
0388 
0389     /* Length x in an instructions has real length x + 1.  */
0390     if (operand->flags & OPERAND_LENGTH)
0391         val++;
0392     return val;
0393 }
0394 
0395 struct s390_insn *find_insn(unsigned char *code)
0396 {
0397     struct s390_opcode_offset *entry;
0398     struct s390_insn *insn;
0399     unsigned char opfrag;
0400     int i;
0401 
0402     /* Search the opcode offset table to find an entry which
0403      * matches the beginning of the opcode. If there is no match
0404      * the last entry will be used, which is the default entry for
0405      * unknown instructions as well as 1-byte opcode instructions.
0406      */
0407     for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
0408         entry = &opcode_offset[i];
0409         if (entry->opcode == code[0])
0410             break;
0411     }
0412 
0413     opfrag = *(code + entry->byte) & entry->mask;
0414 
0415     insn = &opcode[entry->offset];
0416     for (i = 0; i < entry->count; i++) {
0417         if (insn->opfrag == opfrag)
0418             return insn;
0419         insn++;
0420     }
0421     return NULL;
0422 }
0423 
0424 static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
0425 {
0426     struct s390_insn *insn;
0427     const unsigned char *ops;
0428     const struct s390_operand *operand;
0429     unsigned int value;
0430     char separator;
0431     char *ptr;
0432     int i;
0433 
0434     ptr = buffer;
0435     insn = find_insn(code);
0436     if (insn) {
0437         if (insn->zero == 0)
0438             ptr += sprintf(ptr, "%.7s\t",
0439                        long_insn_name[insn->offset]);
0440         else
0441             ptr += sprintf(ptr, "%.5s\t", insn->name);
0442         /* Extract the operands. */
0443         separator = 0;
0444         for (ops = formats[insn->format], i = 0;
0445              *ops != 0 && i < 6; ops++, i++) {
0446             operand = operands + *ops;
0447             value = extract_operand(code, operand);
0448             if ((operand->flags & OPERAND_INDEX)  && value == 0)
0449                 continue;
0450             if ((operand->flags & OPERAND_BASE) &&
0451                 value == 0 && separator == '(') {
0452                 separator = ',';
0453                 continue;
0454             }
0455             if (separator)
0456                 ptr += sprintf(ptr, "%c", separator);
0457             if (operand->flags & OPERAND_GPR)
0458                 ptr += sprintf(ptr, "%%r%i", value);
0459             else if (operand->flags & OPERAND_FPR)
0460                 ptr += sprintf(ptr, "%%f%i", value);
0461             else if (operand->flags & OPERAND_AR)
0462                 ptr += sprintf(ptr, "%%a%i", value);
0463             else if (operand->flags & OPERAND_CR)
0464                 ptr += sprintf(ptr, "%%c%i", value);
0465             else if (operand->flags & OPERAND_VR)
0466                 ptr += sprintf(ptr, "%%v%i", value);
0467             else if (operand->flags & OPERAND_PCREL) {
0468                 void *pcrel = (void *)((int)value + addr);
0469 
0470                 ptr += sprintf(ptr, "%px", pcrel);
0471             } else if (operand->flags & OPERAND_SIGNED)
0472                 ptr += sprintf(ptr, "%i", value);
0473             else
0474                 ptr += sprintf(ptr, "%u", value);
0475             if (operand->flags & OPERAND_DISP)
0476                 separator = '(';
0477             else if (operand->flags & OPERAND_BASE) {
0478                 ptr += sprintf(ptr, ")");
0479                 separator = ',';
0480             } else
0481                 separator = ',';
0482         }
0483     } else
0484         ptr += sprintf(ptr, "unknown");
0485     return (int) (ptr - buffer);
0486 }
0487 
0488 static int copy_from_regs(struct pt_regs *regs, void *dst, void *src, int len)
0489 {
0490     if (user_mode(regs)) {
0491         if (copy_from_user(dst, (char __user *)src, len))
0492             return -EFAULT;
0493     } else {
0494         if (copy_from_kernel_nofault(dst, src, len))
0495             return -EFAULT;
0496     }
0497     return 0;
0498 }
0499 
0500 void show_code(struct pt_regs *regs)
0501 {
0502     char *mode = user_mode(regs) ? "User" : "Krnl";
0503     unsigned char code[64];
0504     char buffer[128], *ptr;
0505     unsigned long addr;
0506     int start, end, opsize, hops, i;
0507 
0508     /* Get a snapshot of the 64 bytes surrounding the fault address. */
0509     for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
0510         addr = regs->psw.addr - 34 + start;
0511         if (copy_from_regs(regs, code + start - 2, (void *)addr, 2))
0512             break;
0513     }
0514     for (end = 32; end < 64; end += 2) {
0515         addr = regs->psw.addr + end - 32;
0516         if (copy_from_regs(regs, code + end, (void *)addr, 2))
0517             break;
0518     }
0519     /* Code snapshot useable ? */
0520     if ((regs->psw.addr & 1) || start >= end) {
0521         printk("%s Code: Bad PSW.\n", mode);
0522         return;
0523     }
0524     /* Find a starting point for the disassembly. */
0525     while (start < 32) {
0526         for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
0527             if (!find_insn(code + start + i))
0528                 break;
0529             i += insn_length(code[start + i]);
0530         }
0531         if (start + i == 32)
0532             /* Looks good, sequence ends at PSW. */
0533             break;
0534         start += 2;
0535     }
0536     /* Decode the instructions. */
0537     ptr = buffer;
0538     ptr += sprintf(ptr, "%s Code:", mode);
0539     hops = 0;
0540     while (start < end && hops < 8) {
0541         opsize = insn_length(code[start]);
0542         if  (start + opsize == 32)
0543             *ptr++ = '#';
0544         else if (start == 32)
0545             *ptr++ = '>';
0546         else
0547             *ptr++ = ' ';
0548         addr = regs->psw.addr + start - 32;
0549         ptr += sprintf(ptr, "%px: ", (void *)addr);
0550         if (start + opsize >= end)
0551             break;
0552         for (i = 0; i < opsize; i++)
0553             ptr += sprintf(ptr, "%02x", code[start + i]);
0554         *ptr++ = '\t';
0555         if (i < 6)
0556             *ptr++ = '\t';
0557         ptr += print_insn(ptr, code + start, addr);
0558         start += opsize;
0559         pr_cont("%s", buffer);
0560         ptr = buffer;
0561         ptr += sprintf(ptr, "\n          ");
0562         hops++;
0563     }
0564     pr_cont("\n");
0565 }
0566 
0567 void print_fn_code(unsigned char *code, unsigned long len)
0568 {
0569     char buffer[128], *ptr;
0570     int opsize, i;
0571 
0572     while (len) {
0573         ptr = buffer;
0574         opsize = insn_length(*code);
0575         if (opsize > len)
0576             break;
0577         ptr += sprintf(ptr, "%px: ", code);
0578         for (i = 0; i < opsize; i++)
0579             ptr += sprintf(ptr, "%02x", code[i]);
0580         *ptr++ = '\t';
0581         if (i < 4)
0582             *ptr++ = '\t';
0583         ptr += print_insn(ptr, code, (unsigned long) code);
0584         *ptr++ = '\n';
0585         *ptr++ = 0;
0586         printk("%s", buffer);
0587         code += opsize;
0588         len -= opsize;
0589     }
0590 }