include/opcode/
* mips.h (mips_operand_type, mips_reg_operand_type): New enums. (mips_operand, mips_int_operand, mips_mapped_int_operand) (mips_msb_operand, mips_reg_operand, mips_reg_pair_operand) (mips_pcrel_operand): New structures. (mips_insert_operand, mips_extract_operand, mips_signed_operand) (mips_decode_int_operand, mips_decode_pcrel_operand): New functions. (decode_mips_operand, decode_micromips_operand): Declare. opcodes/ * mips-formats.h: New file. * mips-opc.c: Include mips-formats.h. (reg_0_map): New static array. (decode_mips_operand): New function. * micromips-opc.c: Remove <stdio.h> include. Include mips-formats.h. (reg_0_map, reg_28_map, reg_29_map, reg_31_map, reg_m16_map) (reg_mn_map, reg_q_map, reg_h_map1, reg_h_map2, int_b_map) (int_c_map): New static arrays. (decode_micromips_operand): New function. * mips-dis.c (micromips_to_32_reg_b_map, micromips_to_32_reg_c_map) (micromips_to_32_reg_d_map, micromips_to_32_reg_e_map) (micromips_to_32_reg_f_map, micromips_to_32_reg_g_map) (micromips_to_32_reg_h_map1, micromips_to_32_reg_h_map2) (micromips_to_32_reg_l_map, micromips_to_32_reg_m_map) (micromips_to_32_reg_n_map, micromips_to_32_reg_q_map) (micromips_imm_b_map, micromips_imm_c_map): Delete. (print_reg): New function. (mips_print_arg_state): New structure. (init_print_arg_state, print_insn_arg): New functions. (print_insn_args): Change interface and use mips_operand structures. Delete GET_OP_S. Move GET_OP definition to... (print_insn_mips): ...here. Update the call to print_insn_args. (print_insn_micromips): Use print_insn_args. gas/ * config/tc-mips.c (validate_mips_insn): Move further up file. Add insn_bits and decode_operand arguments. Use the mips_operand fields to work out which bits an operand occupies. Detect double definitions. (validate_micromips_insn): Move further up file. Call into validate_mips_insn.
This commit is contained in:
parent
ca25afceea
commit
ac96b15958
|
@ -1,3 +1,13 @@
|
|||
2013-07-14 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* mips.h (mips_operand_type, mips_reg_operand_type): New enums.
|
||||
(mips_operand, mips_int_operand, mips_mapped_int_operand)
|
||||
(mips_msb_operand, mips_reg_operand, mips_reg_pair_operand)
|
||||
(mips_pcrel_operand): New structures.
|
||||
(mips_insert_operand, mips_extract_operand, mips_signed_operand)
|
||||
(mips_decode_int_operand, mips_decode_pcrel_operand): New functions.
|
||||
(decode_mips_operand, decode_micromips_operand): Declare.
|
||||
|
||||
2013-07-14 Richard Sandiford <rdsandiford@googlemail.com>
|
||||
|
||||
* mips.h: Document MIPS16 "I" opcode.
|
||||
|
|
|
@ -332,6 +332,292 @@
|
|||
#define OP_SH_EVAOFFSET 7
|
||||
#define OP_MASK_EVAOFFSET 0x1ff
|
||||
|
||||
/* Enumerates the various types of MIPS operand. */
|
||||
enum mips_operand_type {
|
||||
/* Described by mips_int_operand. */
|
||||
OP_INT,
|
||||
|
||||
/* Described by mips_mapped_int_operand. */
|
||||
OP_MAPPED_INT,
|
||||
|
||||
/* Described by mips_msb_operand. */
|
||||
OP_MSB,
|
||||
|
||||
/* Described by mips_reg_operand. */
|
||||
OP_REG,
|
||||
|
||||
/* Described by mips_reg_pair_operand. */
|
||||
OP_REG_PAIR,
|
||||
|
||||
/* Described by mips_pcrel_operand. */
|
||||
OP_PCREL,
|
||||
|
||||
/* A performance register. The field is 5 bits in size, but the supported
|
||||
values are much more restricted. */
|
||||
OP_PERF_REG,
|
||||
|
||||
/* The final operand in a microMIPS ADDIUSP instruction. It mostly acts
|
||||
as a normal 9-bit signed offset that is multiplied by four, but there
|
||||
are four special cases:
|
||||
|
||||
-2 * 4 => -258 * 4
|
||||
-1 * 4 => -257 * 4
|
||||
0 * 4 => 256 * 4
|
||||
1 * 4 => 257 * 4. */
|
||||
OP_ADDIUSP_INT,
|
||||
|
||||
/* The target of a (D)CLO or (D)CLZ instruction. The operand spans two
|
||||
5-bit register fields, both of which must be set to the destination
|
||||
register. */
|
||||
OP_CLO_CLZ_DEST,
|
||||
|
||||
/* A register list for a microMIPS LWM or SWM instruction. The operand
|
||||
size determines whether the 16-bit or 32-bit encoding is required. */
|
||||
OP_LWM_SWM_LIST,
|
||||
|
||||
/* A 10-bit field VVVVVNNNNN used for octobyte and quadhalf instructions:
|
||||
|
||||
V Meaning
|
||||
----- -------
|
||||
0EEE0 8 copies of $vN[E], OB format
|
||||
0EE01 4 copies of $vN[E], QH format
|
||||
10110 all 8 elements of $vN, OB format
|
||||
10101 all 4 elements of $vN, QH format
|
||||
11110 8 copies of immediate N, OB format
|
||||
11101 4 copies of immediate N, QH format. */
|
||||
OP_MDMX_IMM_REG,
|
||||
|
||||
/* A register operand that must match the destination register. */
|
||||
OP_REPEAT_DEST_REG,
|
||||
|
||||
/* A register operand that must match the previous register. */
|
||||
OP_REPEAT_PREV_REG,
|
||||
|
||||
/* $pc, which has no encoding in the architectural instruction. */
|
||||
OP_PC
|
||||
};
|
||||
|
||||
/* Enumerates the types of MIPS register. */
|
||||
enum mips_reg_operand_type {
|
||||
/* General registers $0-$31. Software names like $at can also be used. */
|
||||
OP_REG_GP,
|
||||
|
||||
/* Floating-point registers $f0-$f31. */
|
||||
OP_REG_FP,
|
||||
|
||||
/* Coprocessor condition code registers $cc0-$cc7. FPU condition codes
|
||||
can also be written $fcc0-$fcc7. */
|
||||
OP_REG_CCC,
|
||||
|
||||
/* FPRs used in a vector capacity. They can be written $f0-$f31
|
||||
or $v0-$v31, although the latter form is not used for the VR5400
|
||||
vector instructions. */
|
||||
OP_REG_VEC,
|
||||
|
||||
/* DSP accumulator registers $ac0-$ac3. */
|
||||
OP_REG_ACC,
|
||||
|
||||
/* Coprocessor registers $0-$31. Mnemonic names like c0_cause can
|
||||
also be used in some contexts. */
|
||||
OP_REG_COPRO,
|
||||
|
||||
/* Hardware registers $0-$31. Mnemonic names like hwr_cpunum can
|
||||
also be used in some contexts. */
|
||||
OP_REG_HW
|
||||
};
|
||||
|
||||
/* Base class for all operands. */
|
||||
struct mips_operand
|
||||
{
|
||||
/* The type of the operand. */
|
||||
enum mips_operand_type type;
|
||||
|
||||
/* The operand occupies SIZE bits of the instruction, starting at LSB. */
|
||||
unsigned short size;
|
||||
unsigned short lsb;
|
||||
};
|
||||
|
||||
/* Describes an integer operand with a regular encoding pattern. */
|
||||
struct mips_int_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* The low ROOT.SIZE bits of MAX_VAL encodes (MAX_VAL + BIAS) << SHIFT.
|
||||
The cyclically previous field value encodes 1 << SHIFT less than that,
|
||||
and so on. E.g.
|
||||
|
||||
- for { { T, 4, L }, 14, 0, 0 }, field values 0...14 encode themselves,
|
||||
but 15 encodes -1.
|
||||
|
||||
- { { T, 8, L }, 127, 0, 2 } is a normal signed 8-bit operand that is
|
||||
shifted left two places.
|
||||
|
||||
- { { T, 3, L }, 8, 0, 0 } is a normal unsigned 3-bit operand except
|
||||
that 0 encodes 8.
|
||||
|
||||
- { { ... }, 0, 1, 3 } means that N encodes (N + 1) << 3. */
|
||||
unsigned int max_val;
|
||||
int bias;
|
||||
unsigned int shift;
|
||||
|
||||
/* True if the operand should be printed as hex rather than decimal. */
|
||||
bfd_boolean print_hex;
|
||||
};
|
||||
|
||||
/* Uses a lookup table to describe a small integer operand. */
|
||||
struct mips_mapped_int_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* Maps each encoding value to the integer that it represents. */
|
||||
const int *int_map;
|
||||
|
||||
/* True if the operand should be printed as hex rather than decimal. */
|
||||
bfd_boolean print_hex;
|
||||
};
|
||||
|
||||
/* An operand that encodes the most significant bit position of a bitfield.
|
||||
Given a bitfield that spans bits [MSB, LSB], some operands of this type
|
||||
encode MSB directly while others encode MSB - LSB. Each operand of this
|
||||
type is preceded by an integer operand that specifies LSB.
|
||||
|
||||
The assembly form varies between instructions. For some instructions,
|
||||
such as EXT, the operand is written as the bitfield size. For others,
|
||||
such as EXTS, it is written in raw MSB - LSB form. */
|
||||
struct mips_msb_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* The assembly-level operand encoded by a field value of 0. */
|
||||
int bias;
|
||||
|
||||
/* True if the operand encodes MSB directly, false if it encodes
|
||||
MSB - LSB. */
|
||||
bfd_boolean add_lsb;
|
||||
|
||||
/* The maximum value of MSB + 1. */
|
||||
unsigned int opsize;
|
||||
};
|
||||
|
||||
/* Describes a single register operand. */
|
||||
struct mips_reg_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* The type of register. */
|
||||
enum mips_reg_operand_type reg_type;
|
||||
|
||||
/* If nonnull, REG_MAP[N] gives the register associated with encoding N,
|
||||
otherwise the encoding is the same as the register number. */
|
||||
const unsigned char *reg_map;
|
||||
};
|
||||
|
||||
/* Describes an operand that encodes a pair of registers. */
|
||||
struct mips_reg_pair_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* The type of register. */
|
||||
enum mips_reg_operand_type reg_type;
|
||||
|
||||
/* Encoding N represents REG1_MAP[N], REG2_MAP[N]. */
|
||||
unsigned char *reg1_map;
|
||||
unsigned char *reg2_map;
|
||||
};
|
||||
|
||||
/* Describes an operand that is calculated relative to a base PC.
|
||||
The base PC is usually the address of the following instruction,
|
||||
but the rules for MIPS16 instructions like ADDIUPC are more complicated. */
|
||||
struct mips_pcrel_operand
|
||||
{
|
||||
struct mips_operand root;
|
||||
|
||||
/* The low ALIGN_LOG2 bits of the base PC are cleared to give PC'. */
|
||||
unsigned int align_log2 : 8;
|
||||
|
||||
/* The operand is shifted left SHIFT places and added to PC'.
|
||||
The operand is signed if IS_SIGNED. */
|
||||
unsigned int shift : 8;
|
||||
unsigned int is_signed : 1;
|
||||
|
||||
/* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then
|
||||
reinstated. This is true for jumps and branches and false for
|
||||
PC-relative data instructions. */
|
||||
unsigned int include_isa_bit : 1;
|
||||
|
||||
/* If FLIP_ISA_BIT, the ISA bit of the result is inverted.
|
||||
This is true for JALX and false otherwise. */
|
||||
unsigned int flip_isa_bit : 1;
|
||||
};
|
||||
|
||||
/* Return a version of INSN in which the field specified by OPERAND
|
||||
has value UVAL. */
|
||||
|
||||
static inline unsigned int
|
||||
mips_insert_operand (const struct mips_operand *operand, unsigned int insn,
|
||||
unsigned int uval)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
mask = (1 << operand->size) - 1;
|
||||
insn &= ~(mask << operand->lsb);
|
||||
insn |= (uval & mask) << operand->lsb;
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Extract OPERAND from instruction INSN. */
|
||||
|
||||
static inline unsigned int
|
||||
mips_extract_operand (const struct mips_operand *operand, unsigned int insn)
|
||||
{
|
||||
return (insn >> operand->lsb) & ((1 << operand->size) - 1);
|
||||
}
|
||||
|
||||
/* UVAL is the value encoded by OPERAND. Return it in signed form. */
|
||||
|
||||
static inline int
|
||||
mips_signed_operand (const struct mips_operand *operand, unsigned int uval)
|
||||
{
|
||||
unsigned int sign_bit, mask;
|
||||
|
||||
mask = (1 << operand->size) - 1;
|
||||
sign_bit = 1 << (operand->size - 1);
|
||||
return ((uval + sign_bit) & mask) - sign_bit;
|
||||
}
|
||||
|
||||
/* Return the integer that OPERAND encodes as UVAL. */
|
||||
|
||||
static inline int
|
||||
mips_decode_int_operand (const struct mips_int_operand *operand,
|
||||
unsigned int uval)
|
||||
{
|
||||
uval |= (operand->max_val - uval) & -(1 << operand->root.size);
|
||||
uval += operand->bias;
|
||||
uval <<= operand->shift;
|
||||
return uval;
|
||||
}
|
||||
|
||||
/* PC-relative operand OPERAND has value UVAL and is relative to BASE_PC.
|
||||
Return the address that it encodes. */
|
||||
|
||||
static inline bfd_vma
|
||||
mips_decode_pcrel_operand (const struct mips_pcrel_operand *operand,
|
||||
bfd_vma base_pc, unsigned int uval)
|
||||
{
|
||||
bfd_vma addr;
|
||||
|
||||
addr = base_pc & -(1 << operand->align_log2);
|
||||
if (operand->is_signed)
|
||||
addr += mips_signed_operand (&operand->root, uval) * (1 << operand->shift);
|
||||
else
|
||||
addr += uval << operand->shift;
|
||||
if (operand->include_isa_bit)
|
||||
addr |= base_pc & 1;
|
||||
if (operand->flip_isa_bit)
|
||||
addr ^= 1;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* This structure holds information for a particular instruction. */
|
||||
|
||||
struct mips_opcode
|
||||
|
@ -1215,6 +1501,7 @@ enum
|
|||
Many instructions are short hand for other instructions (i.e., The
|
||||
jal <register> instruction is short for jalr <register>). */
|
||||
|
||||
extern const struct mips_operand *decode_mips_operand (const char *);
|
||||
extern const struct mips_opcode mips_builtin_opcodes[];
|
||||
extern const int bfd_mips_num_builtin_opcodes;
|
||||
extern struct mips_opcode *mips_opcodes;
|
||||
|
@ -1780,6 +2067,7 @@ extern const int bfd_mips16_num_opcodes;
|
|||
" bcdefghij lmn pq st xyz"
|
||||
*/
|
||||
|
||||
extern const struct mips_operand *decode_micromips_operand (const char *);
|
||||
extern const struct mips_opcode micromips_opcodes[];
|
||||
extern const int bfd_micromips_num_opcodes;
|
||||
|
||||
|
|
Loading…
Reference in New Issue