From 8e5eb8e1b0cb2a408008a3e40e571f193917dcc8 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 12 May 2022 10:32:11 +0300 Subject: [PATCH] ppc: extend opindex to 16 bits With the upcoming SVP64 extension[0] to PowerPC architecture, it became evident that PowerPC operand indices no longer fit 8 bits. This patch switches the underlying type to uint16_t, also introducing a special typedef so that any future extension goes even smoother. [0] https://libre-soc.org include/ * opcode/ppc.h (ppc_opindex_t): New typedef. (struct powerpc_opcode): Use it. (PPC_OPINDEX_MAX): Define. gas/ * write.h (struct fix): Increase size of fx_pcrel_adjust. Reorganise. * config/tc-ppc.c (insn_validate): Use ppc_opindex_t for operands. (md_assemble): Likewise. (md_apply_fix): Likewise. Mask fx_pcrel_adjust with PPC_OPINDEX_MAX. (ppc_setup_opcodes): Adjust opcode index assertion. opcodes/ * ppc-dis.c (skip_optional_operands): Use ppc_opindex_t for operand pointer. (lookup_powerpc, lookup_prefix, lookup_vle, lookup_spe2): Likewise. (print_insn_powerpc): Likewise. --- gas/config/tc-ppc.c | 12 ++++++------ gas/write.h | 18 +++++++++++------- include/opcode/ppc.h | 8 +++++++- opcodes/ppc-dis.c | 12 ++++++------ 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 72128af501b..4d789fd16a9 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1553,7 +1553,7 @@ ppc_target_format (void) static bool insn_validate (const struct powerpc_opcode *op) { - const unsigned char *o; + const ppc_opindex_t *o; uint64_t omask = op->mask; /* The mask had better not trim off opcode bits. */ @@ -1634,8 +1634,8 @@ ppc_setup_opcodes (void) unsigned int i; /* An index into powerpc_operands is stored in struct fix - fx_pcrel_adjust which is 8 bits wide. */ - gas_assert (num_powerpc_operands < 256); + fx_pcrel_adjust which is a 16 bit field. */ + gas_assert (num_powerpc_operands <= PPC_OPINDEX_MAX + 1); /* Check operand masks. Code here and in the disassembler assumes all the 1's in the mask are contiguous. */ @@ -3251,7 +3251,7 @@ md_assemble (char *str) char *s; const struct powerpc_opcode *opcode; uint64_t insn; - const unsigned char *opindex_ptr; + const ppc_opindex_t *opindex_ptr; int need_paren; int next_opindex; struct ppc_fixup fixups[MAX_INSN_FIXUPS]; @@ -3348,7 +3348,7 @@ md_assemble (char *str) { if (num_optional_operands == 0) { - const unsigned char *optr; + const ppc_opindex_t *optr; int total = 0; int provided = 0; int omitted; @@ -7011,7 +7011,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) if (fixP->fx_pcrel_adjust != 0) { /* This is a fixup on an instruction. */ - int opindex = fixP->fx_pcrel_adjust & 0xff; + ppc_opindex_t opindex = fixP->fx_pcrel_adjust & PPC_OPINDEX_MAX; operand = &powerpc_operands[opindex]; #ifdef OBJ_XCOFF diff --git a/gas/write.h b/gas/write.h index 501bdd828fc..3e31342cfc8 100644 --- a/gas/write.h +++ b/gas/write.h @@ -52,6 +52,16 @@ struct fix /* These small fields are grouped together for compactness of this structure, and efficiency of access on some architectures. */ + /* pc-relative offset adjust (only used by some CPU specific code). + A 4-bit field would be sufficient for most uses, except for ppc + which pokes an operand table index here. Bits may be stolen + from here should that be necessary, provided PPC_OPINDEX_MAX is + adjusted suitably. */ + int fx_pcrel_adjust : 16; + + /* How many bytes are involved? */ + unsigned fx_size : 8; + /* Is this a pc-relative relocation? */ unsigned fx_pcrel : 1; @@ -73,13 +83,7 @@ struct fix unsigned fx_tcbit2 : 1; /* Spare bits. */ - unsigned fx_unused : 10; - - /* pc-relative offset adjust (only used by some CPU specific code) */ - int fx_pcrel_adjust : 8; - - /* How many bytes are involved? */ - unsigned fx_size : 8; + unsigned fx_unused : 2; bfd_reloc_code_real_type fx_r_type; diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h index a9c25298311..7bc6ee216e1 100644 --- a/include/opcode/ppc.h +++ b/include/opcode/ppc.h @@ -29,6 +29,12 @@ extern "C" { #endif typedef uint64_t ppc_cpu_t; +typedef uint16_t ppc_opindex_t; + +/* Smaller of ppc_opindex_t and fx_pcrel_adjust maximum. Note that + values extracted from fx_pcrel_adjust are masked with this constant, + effectively making the field unsigned. */ +#define PPC_OPINDEX_MAX 0xffff /* The opcode table is an array of struct powerpc_opcode. */ @@ -60,7 +66,7 @@ struct powerpc_opcode /* An array of operand codes. Each code is an index into the operand table. They appear in the order which the operands must appear in assembly code, and are terminated by a zero. */ - unsigned char operands[8]; + ppc_opindex_t operands[8]; }; /* The table itself is sorted by major opcode number, and is otherwise diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index 38ddeca2623..45e8faeef5e 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -546,7 +546,7 @@ operand_value_powerpc (const struct powerpc_operand *operand, /* Determine whether the optional operand(s) should be printed. */ static bool -skip_optional_operands (const unsigned char *opindex, +skip_optional_operands (const ppc_opindex_t *opindex, uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel) { const struct powerpc_operand *operand; @@ -592,7 +592,7 @@ lookup_powerpc (uint64_t insn, ppc_cpu_t dialect) opcode < opcode_end; ++opcode) { - const unsigned char *opindex; + const ppc_opindex_t *opindex; const struct powerpc_operand *operand; int invalid; @@ -637,7 +637,7 @@ lookup_prefix (uint64_t insn, ppc_cpu_t dialect) opcode < opcode_end; ++opcode) { - const unsigned char *opindex; + const ppc_opindex_t *opindex; const struct powerpc_operand *operand; int invalid; @@ -691,7 +691,7 @@ lookup_vle (uint64_t insn, ppc_cpu_t dialect) uint64_t table_mask = opcode->mask; bool table_op_is_short = PPC_OP_SE_VLE(table_mask); uint64_t insn2; - const unsigned char *opindex; + const ppc_opindex_t *opindex; const struct powerpc_operand *operand; int invalid; @@ -746,7 +746,7 @@ lookup_spe2 (uint64_t insn, ppc_cpu_t dialect) uint64_t table_opcd = opcode->opcode; uint64_t table_mask = opcode->mask; uint64_t insn2; - const unsigned char *opindex; + const ppc_opindex_t *opindex; const struct powerpc_operand *operand; int invalid; @@ -925,7 +925,7 @@ print_insn_powerpc (bfd_vma memaddr, if (opcode != NULL) { - const unsigned char *opindex; + const ppc_opindex_t *opindex; const struct powerpc_operand *operand; enum { need_comma = 0, -- 2.30.2