/* Type of operand */ #define OPERAND_GPR 0x1 /* Operand printed as %rx */ #define OPERAND_FPR 0x2 /* Operand printed as %fx */ #define OPERAND_AR 0x4 /* Operand printed as %ax */ #define OPERAND_CR 0x8 /* Operand printed as %cx */ #define OPERAND_VR 0x10 /* Operand printed as %vx */ #define OPERAND_DISP 0x20 /* Operand printed as displacement */ #define OPERAND_BASE 0x40 /* Operand printed as base register */ #define OPERAND_INDEX 0x80 /* Operand printed as index register */ #define OPERAND_PCREL 0x100 /* Operand printed as pc-relative symbol */ #define OPERAND_SIGNED 0x200 /* Operand printed as signed value */ #define OPERAND_LENGTH 0x400 /* Operand printed as length (+1) */
struct s390_operand { unsignedchar bits; /* The number of bits in the operand. */ unsignedchar shift; /* The number of bits to shift. */ unsignedshort flags; /* One bit syntax flags. */
};
enum {
UNUSED,
A_8, /* Access reg. starting at position 8 */
A_12, /* Access reg. starting at position 12 */
A_24, /* Access reg. starting at position 24 */
A_28, /* Access reg. starting at position 28 */
B_16, /* Base register starting at position 16 */
B_32, /* Base register starting at position 32 */
C_8, /* Control reg. starting at position 8 */
C_12, /* Control reg. starting at position 12 */
D20_20, /* 20 bit displacement starting at 20 */
D_20, /* Displacement starting at position 20 */
D_36, /* Displacement starting at position 36 */
F_8, /* FPR starting at position 8 */
F_12, /* FPR starting at position 12 */
F_16, /* FPR starting at position 16 */
F_24, /* FPR starting at position 24 */
F_28, /* FPR starting at position 28 */
F_32, /* FPR starting at position 32 */
I8_8, /* 8 bit signed value starting at 8 */
I8_32, /* 8 bit signed value starting at 32 */
I16_16, /* 16 bit signed value starting at 16 */
I16_32, /* 16 bit signed value starting at 32 */
I32_16, /* 32 bit signed value starting at 16 */
J12_12, /* 12 bit PC relative offset at 12 */
J16_16, /* 16 bit PC relative offset at 16 */
J16_32, /* 16 bit PC relative offset at 32 */
J24_24, /* 24 bit PC relative offset at 24 */
J32_16, /* 32 bit PC relative offset at 16 */
L4_8, /* 4 bit length starting at position 8 */
L4_12, /* 4 bit length starting at position 12 */
L8_8, /* 8 bit length starting at position 8 */
R_8, /* GPR starting at position 8 */
R_12, /* GPR starting at position 12 */
R_16, /* GPR starting at position 16 */
R_24, /* GPR starting at position 24 */
R_28, /* GPR starting at position 28 */
U4_8, /* 4 bit unsigned value starting at 8 */
U4_12, /* 4 bit unsigned value starting at 12 */
U4_16, /* 4 bit unsigned value starting at 16 */
U4_20, /* 4 bit unsigned value starting at 20 */
U4_24, /* 4 bit unsigned value starting at 24 */
U4_28, /* 4 bit unsigned value starting at 28 */
U4_32, /* 4 bit unsigned value starting at 32 */
U4_36, /* 4 bit unsigned value starting at 36 */
U8_8, /* 8 bit unsigned value starting at 8 */
U8_16, /* 8 bit unsigned value starting at 16 */
U8_24, /* 8 bit unsigned value starting at 24 */
U8_28, /* 8 bit unsigned value starting at 28 */
U8_32, /* 8 bit unsigned value starting at 32 */
U12_16, /* 12 bit unsigned value starting at 16 */
U16_16, /* 16 bit unsigned value starting at 16 */
U16_20, /* 16 bit unsigned value starting at 20 */
U16_32, /* 16 bit unsigned value starting at 32 */
U32_16, /* 32 bit unsigned value starting at 16 */
VX_12, /* Vector index register starting at position 12 */
V_8, /* Vector reg. starting at position 8 */
V_12, /* Vector reg. starting at position 12 */
V_16, /* Vector reg. starting at position 16 */
V_32, /* Vector reg. starting at position 32 */
X_12, /* Index register starting at position 12 */
};
/* Extracts an operand value from an instruction. */ staticunsignedint extract_operand(unsignedchar *code, conststruct s390_operand *operand)
{ unsignedchar *cp; unsignedint val; int bits;
/* Extract fragments of the operand byte for byte. */
cp = code + operand->shift / 8;
bits = (operand->shift & 7) + operand->bits;
val = 0; do {
val <<= 8;
val |= (unsignedint) *cp++;
bits -= 8;
} while (bits > 0);
val >>= -bits;
val &= ((1U << (operand->bits - 1)) << 1) - 1;
/* Check for special long displacement case. */ if (operand->bits == 20 && operand->shift == 20)
val = (val & 0xff) << 12 | (val & 0xfff00) >> 8;
/* Check for register extensions bits for vector registers. */ if (operand->flags & OPERAND_VR) { if (operand->shift == 8)
val |= (code[4] & 8) << 1; elseif (operand->shift == 12)
val |= (code[4] & 4) << 2; elseif (operand->shift == 16)
val |= (code[4] & 2) << 3; elseif (operand->shift == 32)
val |= (code[4] & 1) << 4;
}
/* Sign extend value if the operand is signed or pc relative. */ if ((operand->flags & (OPERAND_SIGNED | OPERAND_PCREL)) &&
(val & (1U << (operand->bits - 1))))
val |= (-1U << (operand->bits - 1)) << 1;
/* Double value if the operand is pc relative. */ if (operand->flags & OPERAND_PCREL)
val <<= 1;
/* Length x in an instructions has real length x + 1. */ if (operand->flags & OPERAND_LENGTH)
val++; return val;
}
/* Search the opcode offset table to find an entry which * matches the beginning of the opcode. If there is no match * the last entry will be used, which is the default entry for * unknown instructions as well as 1-byte opcode instructions.
*/ for (i = 0; i < ARRAY_SIZE(opcode_offset); i++) {
entry = &opcode_offset[i]; if (entry->opcode == code[0]) break;
}
opfrag = *(code + entry->byte) & entry->mask;
insn = &opcode[entry->offset]; for (i = 0; i < entry->count; i++) { if (insn->opfrag == opfrag) return insn;
insn++;
} return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.