PRU BFD support

include/
	* elf/common.h: Add PRU ELF.
	* elf/pru.h: New file.
	* opcode/pru.h: New file.
	* dis-asm.h (print_insn_pru): Declare.
bfd/
	* archures.c: Add bfd_arch_pru.
	* Makefile.am: Add PRU target.
	* config.bfd: Ditto.
	* configure.ac: Ditto.
	* elf-bfd.h (enum elf_target_id): Add PRU_ELF_DATA.
	* targets.c: Add pru_elf32_vec.
	* reloc.c: Add PRU relocations.
	* cpu-pru.c: New file.
	* elf32-pru.c: New file.
	* Makefile.in: Regenerate.
	* configure: Regenerate.
	* po/SRC-POTFILES.in: Regenerate.
	* bfd-in2.h: Regenerate
	* libbfd.h: Regenerate.

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
This commit is contained in:
Dimitar Dimitrov 2016-12-30 12:39:46 +02:00 committed by Alan Modra
parent 4244d58a40
commit 889294f6ff
20 changed files with 2129 additions and 1 deletions

View File

@ -1,3 +1,20 @@
2016-12-31 Dimitar Dimitrov <dimitar@dinux.eu>
* archures.c: Add bfd_arch_pru.
* Makefile.am: Add PRU target.
* config.bfd: Ditto.
* configure.ac: Ditto.
* elf-bfd.h (enum elf_target_id): Add PRU_ELF_DATA.
* targets.c: Add pru_elf32_vec.
* reloc.c: Add PRU relocations.
* cpu-pru.c: New file.
* elf32-pru.c: New file.
* Makefile.in: Regenerate.
* configure: Regenerate.
* po/SRC-POTFILES.in: Regenerate.
* bfd-in2.h: Regenerate
* libbfd.h: Regenerate.
2016-12-29 Alan Modra <amodra@gmail.com>
* elflink.c (_bfd_elf_link_hash_copy_indirect): Only omit

View File

@ -147,6 +147,7 @@ ALL_MACHINES = \
cpu-pj.lo \
cpu-plugin.lo \
cpu-powerpc.lo \
cpu-pru.lo \
cpu-rs6000.lo \
cpu-riscv.lo \
cpu-rl78.lo \
@ -235,6 +236,7 @@ ALL_MACHINES_CFILES = \
cpu-pj.c \
cpu-plugin.c \
cpu-powerpc.c \
cpu-pru.c \
cpu-rs6000.c \
cpu-riscv.c \
cpu-rl78.c \
@ -365,6 +367,7 @@ BFD32_BACKENDS = \
elf32-or1k.lo \
elf32-pj.lo \
elf32-ppc.lo \
elf32-pru.lo \
elf32-rl78.lo \
elf32-rx.lo \
elf32-s390.lo \
@ -557,6 +560,7 @@ BFD32_BACKENDS_CFILES = \
elf32-or1k.c \
elf32-pj.c \
elf32-ppc.c \
elf32-pru.c \
elf32-rl78.c \
elf32-rx.c \
elf32-s390.c \

View File

@ -480,6 +480,7 @@ ALL_MACHINES = \
cpu-pj.lo \
cpu-plugin.lo \
cpu-powerpc.lo \
cpu-pru.lo \
cpu-rs6000.lo \
cpu-riscv.lo \
cpu-rl78.lo \
@ -568,6 +569,7 @@ ALL_MACHINES_CFILES = \
cpu-pj.c \
cpu-plugin.c \
cpu-powerpc.c \
cpu-pru.c \
cpu-rs6000.c \
cpu-riscv.c \
cpu-rl78.c \
@ -699,6 +701,7 @@ BFD32_BACKENDS = \
elf32-or1k.lo \
elf32-pj.lo \
elf32-ppc.lo \
elf32-pru.lo \
elf32-rl78.lo \
elf32-rx.lo \
elf32-s390.lo \
@ -891,6 +894,7 @@ BFD32_BACKENDS_CFILES = \
elf32-or1k.c \
elf32-pj.c \
elf32-ppc.c \
elf32-pru.c \
elf32-rl78.c \
elf32-rx.c \
elf32-s390.c \
@ -1420,6 +1424,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-pj.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-plugin.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-powerpc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-pru.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-riscv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-rl78.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-rs6000.Plo@am__quote@
@ -1510,6 +1515,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-or1k.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-pj.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-ppc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-pru.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-riscv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-rl78.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-rx.Plo@am__quote@

View File

@ -528,6 +528,8 @@ DESCRIPTION
.#define bfd_mach_nios2r2 2
. bfd_arch_visium, {* Visium *}
.#define bfd_mach_visium 1
. bfd_arch_pru, {* PRU *}
.#define bfd_mach_pru 0
. bfd_arch_last
. };
*/
@ -631,6 +633,7 @@ extern const bfd_arch_info_type bfd_pj_arch;
extern const bfd_arch_info_type bfd_plugin_arch;
extern const bfd_arch_info_type bfd_powerpc_archs[];
#define bfd_powerpc_arch bfd_powerpc_archs[0]
extern const bfd_arch_info_type bfd_pru_arch;
extern const bfd_arch_info_type bfd_riscv_arch;
extern const bfd_arch_info_type bfd_rs6000_arch;
extern const bfd_arch_info_type bfd_rl78_arch;
@ -721,6 +724,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
&bfd_or1k_arch,
&bfd_pdp11_arch,
&bfd_powerpc_arch,
&bfd_pru_arch,
&bfd_riscv_arch,
&bfd_rl78_arch,
&bfd_rs6000_arch,

View File

@ -2370,6 +2370,8 @@ enum bfd_architecture
#define bfd_mach_nios2r2 2
bfd_arch_visium, /* Visium */
#define bfd_mach_visium 1
bfd_arch_pru, /* PRU */
#define bfd_mach_pru 0
bfd_arch_last
};
@ -5562,6 +5564,41 @@ a matching LO8XG part. */
BFD_RELOC_NIOS2_R2_T1X1I6,
BFD_RELOC_NIOS2_R2_T1X1I6_2,
/* PRU LDI 16-bit unsigned data-memory relocation. */
BFD_RELOC_PRU_U16,
/* PRU LDI 16-bit unsigned instruction-memory relocation. */
BFD_RELOC_PRU_U16_PMEMIMM,
/* PRU relocation for two consecutive LDI load instructions that load a
32 bit value into a register. If the higher bits are all zero, then
the second instruction may be relaxed. */
BFD_RELOC_PRU_LDI32,
/* PRU QBBx 10-bit signed PC-relative relocation. */
BFD_RELOC_PRU_S10_PCREL,
/* PRU 8-bit unsigned relocation used for the LOOP instruction. */
BFD_RELOC_PRU_U8_PCREL,
/* PRU Program Memory relocations. Used to convert from byte addressing to
32-bit word addressing. */
BFD_RELOC_PRU_32_PMEM,
BFD_RELOC_PRU_16_PMEM,
/* PRU relocations to mark the difference of two local symbols.
These are only needed to support linker relaxation and can be ignored
when not relaxing. The field is set to the value of the difference
assuming no relaxation. The relocation encodes the position of the
second symbol so the linker can determine whether to adjust the field
value. The PMEM variants encode the word difference, instead of byte
difference between symbols. */
BFD_RELOC_PRU_GNU_DIFF8,
BFD_RELOC_PRU_GNU_DIFF16,
BFD_RELOC_PRU_GNU_DIFF32,
BFD_RELOC_PRU_GNU_DIFF16_PMEM,
BFD_RELOC_PRU_GNU_DIFF32_PMEM,
/* IQ2000 Relocations. */
BFD_RELOC_IQ2000_OFFSET_16,
BFD_RELOC_IQ2000_OFFSET_21,

View File

@ -189,6 +189,7 @@ or1k*|or1knd*) targ_archs=bfd_or1k_arch ;;
pdp11*) targ_archs=bfd_pdp11_arch ;;
pj*) targ_archs="bfd_pj_arch bfd_i386_arch";;
powerpc*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
pru*) targ_archs=bfd_pru_arch ;;
riscv*) targ_archs=bfd_riscv_arch ;;
rs6000) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
s390*) targ_archs=bfd_s390_arch ;;
@ -1436,6 +1437,11 @@ case "${targ}" in
targ_selvecs="powerpc_pei_le_vec powerpc_pei_vec powerpc_pe_le_vec powerpc_pe_vec"
;;
pru-*-*)
targ_defvec=pru_elf32_vec
targ_underscore=yes
;;
#ifdef BFD64
riscv32-*-*)
targ_defvec=riscv_elf32_vec

1
bfd/configure vendored
View File

@ -14475,6 +14475,7 @@ do
powerpc_pei_vec) tb="$tb pei-ppc.lo peigen.lo $coff" ;;
powerpc_pei_le_vec) tb="$tb pei-ppc.lo peigen.lo $coff" ;;
powerpc_xcoff_vec) tb="$tb coff-rs6000.lo $xcoff" ;;
pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;;
riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;;
riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;;
rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;;

View File

@ -606,6 +606,7 @@ do
powerpc_pei_vec) tb="$tb pei-ppc.lo peigen.lo $coff" ;;
powerpc_pei_le_vec) tb="$tb pei-ppc.lo peigen.lo $coff" ;;
powerpc_xcoff_vec) tb="$tb coff-rs6000.lo $xcoff" ;;
pru_elf32_vec) tb="$tb elf32-pru.lo elf32.lo $elf" ;;
riscv_elf32_vec) tb="$tb elf32-riscv.lo elfxx-riscv.lo elf32.lo $elf" ;;
riscv_elf64_vec) tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf32.lo $elf"; target_size=64 ;;
rl78_elf32_vec) tb="$tb elf32-rl78.lo elf32.lo $elf" ;;

43
bfd/cpu-pru.c Normal file
View File

@ -0,0 +1,43 @@
/* BFD support for the TI PRU microprocessor.
Copyright (C) 2014-2016 Free Software Foundation, Inc.
Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
{ \
BITS_WORD, /* bits in a word */ \
BITS_ADDR, /* bits in an address */ \
8, /* 8 bits in a byte */ \
bfd_arch_pru, \
NUMBER, \
"pru", \
PRINT, \
3, \
DEFAULT, \
bfd_default_compatible, \
bfd_default_scan, \
bfd_arch_default_fill, \
NEXT \
}
const bfd_arch_info_type bfd_pru_arch = N (32, 32, 0, "pru", TRUE, NULL);

View File

@ -467,6 +467,7 @@ enum elf_target_id
OR1K_ELF_DATA,
PPC32_ELF_DATA,
PPC64_ELF_DATA,
PRU_ELF_DATA,
S390_ELF_DATA,
SH_ELF_DATA,
SPARC_ELF_DATA,

1469
bfd/elf32-pru.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2741,6 +2741,18 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_NIOS2_R2_L5I4X1",
"BFD_RELOC_NIOS2_R2_T1X1I6",
"BFD_RELOC_NIOS2_R2_T1X1I6_2",
"BFD_RELOC_PRU_U16",
"BFD_RELOC_PRU_U16_PMEMIMM",
"BFD_RELOC_PRU_LDI32",
"BFD_RELOC_PRU_S10_PCREL",
"BFD_RELOC_PRU_U8_PCREL",
"BFD_RELOC_PRU_32_PMEM",
"BFD_RELOC_PRU_16_PMEM",
"BFD_RELOC_PRU_GNU_DIFF8",
"BFD_RELOC_PRU_GNU_DIFF16",
"BFD_RELOC_PRU_GNU_DIFF32",
"BFD_RELOC_PRU_GNU_DIFF16_PMEM",
"BFD_RELOC_PRU_GNU_DIFF32_PMEM",
"BFD_RELOC_IQ2000_OFFSET_16",
"BFD_RELOC_IQ2000_OFFSET_21",
"BFD_RELOC_IQ2000_UHI16",

View File

@ -119,6 +119,7 @@ cpu-pdp11.c
cpu-pj.c
cpu-plugin.c
cpu-powerpc.c
cpu-pru.c
cpu-riscv.c
cpu-rl78.c
cpu-rs6000.c
@ -212,6 +213,7 @@ elf32-nios2.c
elf32-or1k.c
elf32-pj.c
elf32-ppc.c
elf32-pru.c
elf32-rl78.c
elf32-rx.c
elf32-s390.c

View File

@ -6516,6 +6516,54 @@ ENUMX
ENUMDOC
Relocations used by the Altera Nios II core.
ENUM
BFD_RELOC_PRU_U16
ENUMDOC
PRU LDI 16-bit unsigned data-memory relocation.
ENUM
BFD_RELOC_PRU_U16_PMEMIMM
ENUMDOC
PRU LDI 16-bit unsigned instruction-memory relocation.
ENUM
BFD_RELOC_PRU_LDI32
ENUMDOC
PRU relocation for two consecutive LDI load instructions that load a
32 bit value into a register. If the higher bits are all zero, then
the second instruction may be relaxed.
ENUM
BFD_RELOC_PRU_S10_PCREL
ENUMDOC
PRU QBBx 10-bit signed PC-relative relocation.
ENUM
BFD_RELOC_PRU_U8_PCREL
ENUMDOC
PRU 8-bit unsigned relocation used for the LOOP instruction.
ENUM
BFD_RELOC_PRU_32_PMEM
ENUMX
BFD_RELOC_PRU_16_PMEM
ENUMDOC
PRU Program Memory relocations. Used to convert from byte addressing to
32-bit word addressing.
ENUM
BFD_RELOC_PRU_GNU_DIFF8
ENUMX
BFD_RELOC_PRU_GNU_DIFF16
ENUMX
BFD_RELOC_PRU_GNU_DIFF32
ENUMX
BFD_RELOC_PRU_GNU_DIFF16_PMEM
ENUMX
BFD_RELOC_PRU_GNU_DIFF32_PMEM
ENUMDOC
PRU relocations to mark the difference of two local symbols.
These are only needed to support linker relaxation and can be ignored
when not relaxing. The field is set to the value of the difference
assuming no relaxation. The relocation encodes the position of the
second symbol so the linker can determine whether to adjust the field
value. The PMEM variants encode the word difference, instead of byte
difference between symbols.
ENUM
BFD_RELOC_IQ2000_OFFSET_16
ENUMX

View File

@ -799,6 +799,7 @@ extern const bfd_target powerpc_pe_le_vec;
extern const bfd_target powerpc_pei_vec;
extern const bfd_target powerpc_pei_le_vec;
extern const bfd_target powerpc_xcoff_vec;
extern const bfd_target pru_elf32_vec;
extern const bfd_target riscv_elf32_vec;
extern const bfd_target riscv_elf64_vec;
extern const bfd_target rl78_elf32_vec;
@ -1305,6 +1306,8 @@ static const bfd_target * const _bfd_target_vector[] =
&powerpc_xcoff_vec,
#endif
&pru_elf32_vec,
#ifdef BFD64
&riscv_elf32_vec,
&riscv_elf64_vec,

View File

@ -1,3 +1,10 @@
2016-12-31 Dimitar Dimitrov <dimitar@dinux.eu>
* elf/common.h: Add PRU ELF.
* elf/pru.h: New file.
* opcode/pru.h: New file.
* dis-asm.h (print_insn_pru): Declare.
2016-12-23 Maciej W. Rozycki <macro@imgtec.com>
* opcode/mips.h: Document `0', `1', `2', `3', `4' and `s'

View File

@ -289,6 +289,7 @@ extern int print_insn_ns32k (bfd_vma, disassemble_info *);
extern int print_insn_or1k (bfd_vma, disassemble_info *);
extern int print_insn_pdp11 (bfd_vma, disassemble_info *);
extern int print_insn_pj (bfd_vma, disassemble_info *);
extern int print_insn_pru (bfd_vma, disassemble_info *);
extern int print_insn_rs6000 (bfd_vma, disassemble_info *);
extern int print_insn_s390 (bfd_vma, disassemble_info *);
extern int print_insn_sh (bfd_vma, disassemble_info *);

View File

@ -248,7 +248,7 @@
#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP family */
#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP family */
#define EM_res143 143 /* Reserved */
#define EM_res144 144 /* Reserved */
#define EM_TI_PRU 144 /* Texas Instruments Programmable Realtime Unit */
#define EM_res145 145 /* Reserved */
#define EM_res146 146 /* Reserved */
#define EM_res147 147 /* Reserved */

55
include/elf/pru.h Normal file
View File

@ -0,0 +1,55 @@
/* TI PRU ELF support for BFD.
Copyright (C) 2014-2016 Free Software Foundation, Inc.
Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
/* This file holds definitions specific to the TI PRU ELF ABI. Note
that most of this is not actually implemented by BFD. */
#ifndef _ELF_PRU_H
#define _ELF_PRU_H
#include "elf/reloc-macros.h"
START_RELOC_NUMBERS (elf_pru_reloc_type)
RELOC_NUMBER (R_PRU_NONE, 0)
RELOC_NUMBER (R_PRU_16_PMEM, 5)
RELOC_NUMBER (R_PRU_U16_PMEMIMM, 6)
RELOC_NUMBER (R_PRU_BFD_RELOC_16, 8)
RELOC_NUMBER (R_PRU_U16, 9)
RELOC_NUMBER (R_PRU_32_PMEM, 10)
RELOC_NUMBER (R_PRU_BFD_RELOC_32, 11)
RELOC_NUMBER (R_PRU_S10_PCREL, 14)
RELOC_NUMBER (R_PRU_U8_PCREL, 15)
RELOC_NUMBER (R_PRU_LDI32, 18)
/* Extensions required by GCC, or simply nice to have. */
RELOC_NUMBER (R_PRU_GNU_BFD_RELOC_8, 64)
RELOC_NUMBER (R_PRU_GNU_DIFF8, 65)
RELOC_NUMBER (R_PRU_GNU_DIFF16, 66)
RELOC_NUMBER (R_PRU_GNU_DIFF32, 67)
RELOC_NUMBER (R_PRU_GNU_DIFF16_PMEM, 68)
RELOC_NUMBER (R_PRU_GNU_DIFF32_PMEM, 69)
RELOC_NUMBER (R_PRU_ILLEGAL, 70)
END_RELOC_NUMBERS (R_PRU_maxext)
/* Processor-specific section flags. */
#endif /* _ELF_PRU_H */

411
include/opcode/pru.h Normal file
View File

@ -0,0 +1,411 @@
/* TI PRU opcode list for GAS, the GNU assembler.
Copyright (C) 2014-2016 Free Software Foundation, Inc.
Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
GAS/GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS/GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GAS or GDB; see the file COPYING3. If not, write to
the Free Software Foundation, 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
#ifndef _PRU_H_
#define _PRU_H_
#include "bfd.h"
/****************************************************************************
* This file contains structures, bit masks and shift counts used
* by the GNU toolchain to define the PRU instruction set and
* access various opcode fields.
****************************************************************************/
/* Identify different overflow situations for error messages. */
enum overflow_type
{
call_target_overflow = 0,
qbranch_target_overflow,
address_offset_overflow,
signed_immed16_overflow,
unsigned_immed32_overflow,
unsigned_immed16_overflow,
unsigned_immed8_overflow,
unsigned_immed5_overflow,
no_overflow
};
enum opcode_format_type {
opcode_format1,
opcode_format2ab,
opcode_format2abl,
opcode_format2c,
opcode_format2de,
opcode_format45,
opcode_format6
};
/* Opcode ID listing. Used for indexing by the simulator. */
enum pru_instr_type {
prui_add, prui_adc, prui_sub, prui_suc, prui_lsl, prui_lsr, prui_rsb,
prui_rsc, prui_and, prui_or, prui_xor, prui_min, prui_max, prui_clr,
prui_set, prui_not, prui_jmp, prui_jal, prui_ldi, prui_halt, prui_slp,
prui_xin, prui_xout, prui_xchg, prui_sxin, prui_sxout, prui_sxchg,
prui_loop, prui_iloop, prui_qbgt, prui_qbge, prui_qblt, prui_qble,
prui_qbeq, prui_qbne, prui_qba, prui_qbbs, prui_qbbc, prui_lbbo,
prui_sbbo, prui_lbco, prui_sbco
};
/* This structure holds information for a particular instruction.
The args field is a string describing the operands. The following
letters can appear in the args:
b - a 5.3-bit right source register index OR 8-bit unsigned immediate
B - same as 'b', but for LOOP instruction where IMM is decremented
c - a 5 bit unsigned immediate for constant table offset
d - a 5.3-bit destination register index
D - a 5.2-bit destination register index
E - for internal GAS self-tests only
i - a 32-bit immediate or label
j - a 5.3-bit right source register index OR 18-bit PC address
l - burst length (unsigned 7-bit immediate or r0.b[0-3]) for xLBCO
n - burst length (unsigned 7-bit immediate or r0.b[0-3]) for XFR
o - a 10-bit signed PC-relative offset
O - an 8-bit unsigned PC-relative offset for LOOP termination point
R - a 5-bit destination register index
s - a 5.3-bit left source register index
S - a 5-bit left source register index
w - a single bit for "WakeOnStatus"
W - a 16-bit unsigned immediate with IO=0 field (LDI)
x - an 8-bit XFR wide-bus address immediate
Literal ',' character may also appear in the args as delimiter.
Most of the macro names are from [1].
The pinfo field is INSN_MACRO for a macro. Otherwise, it is a collection
of bits describing the instruction, notably any relevant hazard
information.
When assembling, the match field contains the opcode template, which
is modified by the arguments to produce the actual opcode
that is emitted. If pinfo is INSN_MACRO, then this is 0.
If pinfo is INSN_MACRO, the mask field stores the macro identifier.
Otherwise this is a bit mask for the relevant portions of the opcode
when disassembling. If the actual opcode anded with the match field
equals the opcode field, then we have found the correct instruction.
[1] http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit */
struct pru_opcode
{
const char *name; /* The name of the instruction. */
enum pru_instr_type type; /* Instruction type. Used for fast indexing
by the simulator. */
const char *args; /* A string describing the arguments for this
instruction. */
unsigned long match; /* The basic opcode for the instruction. */
unsigned long mask; /* Mask for the opcode field of the
instruction. */
unsigned long pinfo; /* Is this a real instruction or instruction
macro? */
enum overflow_type overflow_msg; /* Used to generate informative
message when fixup overflows. */
};
/* This value is used in the pru_opcode.pinfo field to indicate that the
instruction is a macro or pseudo-op. This requires special treatment by
the assembler, and is used by the disassembler to determine whether to
check for a nop. */
#define PRU_INSN_MACRO 0x80000000
/* This macro is specially handled throughout the code because it is
the only insn to output 2 words (64 bits). */
#define PRU_INSN_LDI32 0x40000000
/* Associates a register name with a 5-bit index and 3-bit regsel. */
struct pru_reg
{
const char *name; /* Name, e.g. "r10". */
const unsigned int index; /* Index, e.g. 10. */
const unsigned int regsel; /* Register field selector, .e.g RSEL_31_0. */
};
/* Macros for getting and setting an instruction field. */
#define GET_INSN_FIELD(X, i) \
(((i) & OP_MASK_##X) >> OP_SH_##X)
#define SET_INSN_FIELD(X, i, v) \
((i) = (((i) & ~OP_MASK_##X) | (((v) << OP_SH_##X) & OP_MASK_##X)))
#define CHECK_INSN_FIELD(X, i) \
(((i) & OP_MASK_##X) == OP_MATCH_##X)
/* Masks, values, shifts and macros for accessing the various opcode fields. */
#define OP_SH_FMT1_OP 29
#define OP_MASK_FMT1_OP (0x7u << 29)
#define OP_MATCH_FMT1_OP (0x0u << 29)
#define OP_SH_FMT2_OP 29
#define OP_MASK_FMT2_OP (0x7u << 29)
#define OP_MATCH_FMT2_OP (0x1u << 29)
#define OP_SH_FMT4_OP 30
#define OP_MASK_FMT4_OP (0x3u << 30)
#define OP_MATCH_FMT4_OP (0x1u << 30)
#define OP_SH_FMT5_OP 29
#define OP_MASK_FMT5_OP (0x7u << 29)
#define OP_MATCH_FMT5_OP (0x6u << 29)
#define OP_SH_FMT6AB_OP 29
#define OP_MASK_FMT6AB_OP (0x7u << 29)
#define OP_MATCH_FMT6AB_OP (0x7u << 29)
#define OP_SH_FMT6CD_OP 29
#define OP_MASK_FMT6CD_OP (0x7u << 29)
#define OP_MATCH_FMT6CD_OP (0x4u << 29)
/* Generic fields. */
#define OP_SH_SUBOP 25
#define OP_MASK_SUBOP (0xfu << 25)
#define OP_SH_IO 24
#define OP_MASK_IO (0x1u << 24)
#define OP_SH_RS2SEL 21
#define OP_MASK_RS2SEL (0x7u << 21)
#define OP_SH_RS2 16
#define OP_MASK_RS2 (0x1fu << 16)
#define OP_SH_RS1SEL 13
#define OP_MASK_RS1SEL (0x7u << 13)
#define OP_SH_RS1 8
#define OP_MASK_RS1 (0x1fu << 8)
#define OP_SH_RDSEL 5
#define OP_MASK_RDSEL (0x7u << 5)
#define OP_SH_RD 0
#define OP_MASK_RD (0x1fu << 0)
#define OP_SH_IMM8 16
#define OP_MASK_IMM8 (0xffu << 16)
#define OP_SH_IMM16 8
#define OP_MASK_IMM16 (0xffffu << 8)
#define RSEL_7_0 0u
#define RSEL_15_8 1u
#define RSEL_23_16 2u
#define RSEL_31_24 3u
#define RSEL_15_0 4u
#define RSEL_23_8 5u
#define RSEL_31_16 6u
#define RSEL_31_0 7u
#define RSEL_NUM_ITEMS 8u
/* Format 1 specific fields. */
#define SUBOP_ADD 0u
#define SUBOP_ADC 1u
#define SUBOP_SUB 2u
#define SUBOP_SUC 3u
#define SUBOP_LSL 4u
#define SUBOP_LSR 5u
#define SUBOP_RSB 6u
#define SUBOP_RSC 7u
#define SUBOP_AND 8u
#define SUBOP_OR 9u
#define SUBOP_XOR 10u
#define SUBOP_NOT 11u
#define SUBOP_MIN 12u
#define SUBOP_MAX 13u
#define SUBOP_CLR 14u
#define SUBOP_SET 15u
/* Format 2 specific fields. */
#define SUBOP_JMP 0u
#define SUBOP_JAL 1u
#define SUBOP_LDI 2u
#define SUBOP_LMBD 3u
#define SUBOP_SCAN 4u
#define SUBOP_HALT 5u
#define SUBOP_RSVD_FOR_MVIx 6u
#define SUBOP_XFR 7u
#define SUBOP_LOOP 8u
#define SUBOP_RSVD_FOR_RFI 14u
#define SUBOP_SLP 15u
#define OP_SH_WAKEONSTATUS 23
#define OP_MASK_WAKEONSTATUS (0x1u << 23)
/* Format 2 XFR specific fields. */
#define OP_SH_SUBOP_XFR 23
#define OP_MASK_SUBOP_XFR (3u << 23)
#define OP_SH_XFR_WBA 15
#define OP_MASK_XFR_WBA (0xffu << 15)
#define OP_SH_XFR_S 14
#define OP_MASK_XFR_S (1u << 14)
#define OP_SH_XFR_LENGTH 7
#define OP_MASK_XFR_LENGTH (0x7fu << 7)
#define SUBOP_XFR_XIN 1u
#define SUBOP_XFR_XOUT 2u
#define SUBOP_XFR_XCHG 3u
/* Format 2 LOOP specific fields. */
#define OP_SH_LOOP_INTERRUPTIBLE 15
#define OP_MASK_LOOP_INTERRUPTIBLE (1u << 15)
#define OP_SH_LOOP_JMPOFFS 0
#define OP_MASK_LOOP_JMPOFFS (0xffu << 0)
/* Format 4 specific fields. */
#define OP_SH_BROFF98 25
#define OP_MASK_BROFF98 (0x3u << 25)
#define OP_SH_BROFF70 0
#define OP_MASK_BROFF70 (0xffu << 0)
#define OP_SH_GT 29
#define OP_MASK_GT (0x1u << 29)
#define OP_SH_EQ 28
#define OP_MASK_EQ (0x1u << 28)
#define OP_SH_LT 27
#define OP_MASK_LT (0x1u << 27)
#define OP_MASK_CMP (OP_MASK_GT | OP_MASK_EQ | OP_MASK_LT)
/* Format 5 specific fields. */
#define OP_SH_BS 28
#define OP_MASK_BS (0x1u << 28)
#define OP_SH_BC 27
#define OP_MASK_BC (0x1u << 27)
#define OP_MASK_BCMP (OP_MASK_BS | OP_MASK_BC)
/* Format 6 specific fields. */
#define OP_SH_LOADSTORE 28
#define OP_MASK_LOADSTORE (0x1u << 28)
#define OP_SH_BURSTLEN64 25
#define OP_MASK_BURSTLEN64 (0x7u << 25)
#define OP_SH_BURSTLEN31 13
#define OP_MASK_BURSTLEN31 (0x7u << 13)
#define OP_SH_CB 8
#define OP_MASK_CB (0x1fu << 8)
#define OP_SH_BURSTLEN0 7
#define OP_MASK_BURSTLEN0 (0x1u << 7)
#define OP_SH_RDB 5
#define OP_MASK_RDB (0x3u << 5)
#define LSSBBO_BYTECOUNT_R0_BITS7_0 124u
#define LSBBO_BYTECOUNT_R0_BITS15_8 125u
#define LSBBO_BYTECOUNT_R0_BITS23_16 126u
#define LSBBO_BYTECOUNT_R0_BITS31_24 127u
/* The following macros define the opcode matches for each
instruction code & OP_MASK_INST == OP_MATCH_INST. */
#define OP_MATCH_ADD (OP_MATCH_FMT1_OP | (SUBOP_ADD << OP_SH_SUBOP))
#define OP_MATCH_ADC (OP_MATCH_FMT1_OP | (SUBOP_ADC << OP_SH_SUBOP))
#define OP_MATCH_SUB (OP_MATCH_FMT1_OP | (SUBOP_SUB << OP_SH_SUBOP))
#define OP_MATCH_SUC (OP_MATCH_FMT1_OP | (SUBOP_SUC << OP_SH_SUBOP))
#define OP_MATCH_LSL (OP_MATCH_FMT1_OP | (SUBOP_LSL << OP_SH_SUBOP))
#define OP_MATCH_LSR (OP_MATCH_FMT1_OP | (SUBOP_LSR << OP_SH_SUBOP))
#define OP_MATCH_RSB (OP_MATCH_FMT1_OP | (SUBOP_RSB << OP_SH_SUBOP))
#define OP_MATCH_RSC (OP_MATCH_FMT1_OP | (SUBOP_RSC << OP_SH_SUBOP))
#define OP_MATCH_AND (OP_MATCH_FMT1_OP | (SUBOP_AND << OP_SH_SUBOP))
#define OP_MATCH_OR (OP_MATCH_FMT1_OP | (SUBOP_OR << OP_SH_SUBOP))
#define OP_MATCH_XOR (OP_MATCH_FMT1_OP | (SUBOP_XOR << OP_SH_SUBOP))
#define OP_MATCH_NOT (OP_MATCH_FMT1_OP | (SUBOP_NOT << OP_SH_SUBOP))
#define OP_MATCH_MIN (OP_MATCH_FMT1_OP | (SUBOP_MIN << OP_SH_SUBOP))
#define OP_MATCH_MAX (OP_MATCH_FMT1_OP | (SUBOP_MAX << OP_SH_SUBOP))
#define OP_MATCH_CLR (OP_MATCH_FMT1_OP | (SUBOP_CLR << OP_SH_SUBOP))
#define OP_MATCH_SET (OP_MATCH_FMT1_OP | (SUBOP_SET << OP_SH_SUBOP))
#define OP_MATCH_JMP (OP_MATCH_FMT2_OP | (SUBOP_JMP << OP_SH_SUBOP))
#define OP_MATCH_JAL (OP_MATCH_FMT2_OP | (SUBOP_JAL << OP_SH_SUBOP))
#define OP_MATCH_LDI (OP_MATCH_FMT2_OP | (SUBOP_LDI << OP_SH_SUBOP))
#define OP_MATCH_LMBD (OP_MATCH_FMT2_OP | (SUBOP_LMBD << OP_SH_SUBOP))
#define OP_MATCH_SCAN (OP_MATCH_FMT2_OP | (SUBOP_SCAN << OP_SH_SUBOP))
#define OP_MATCH_HALT (OP_MATCH_FMT2_OP | (SUBOP_HALT << OP_SH_SUBOP))
#define OP_MATCH_SLP (OP_MATCH_FMT2_OP | (SUBOP_SLP << OP_SH_SUBOP))
#define OP_MATCH_XFR (OP_MATCH_FMT2_OP | (SUBOP_XFR << OP_SH_SUBOP))
#define OP_MATCH_SXFR (OP_MATCH_XFR | OP_MASK_XFR_S)
#define OP_MATCH_XIN (OP_MATCH_XFR | (SUBOP_XFR_XIN << OP_SH_SUBOP_XFR))
#define OP_MATCH_XOUT (OP_MATCH_XFR | (SUBOP_XFR_XOUT << OP_SH_SUBOP_XFR))
#define OP_MATCH_XCHG (OP_MATCH_XFR | (SUBOP_XFR_XCHG << OP_SH_SUBOP_XFR))
#define OP_MATCH_SXIN (OP_MATCH_SXFR | (SUBOP_XFR_XIN << OP_SH_SUBOP_XFR))
#define OP_MATCH_SXOUT (OP_MATCH_SXFR | (SUBOP_XFR_XOUT << OP_SH_SUBOP_XFR))
#define OP_MATCH_SXCHG (OP_MATCH_SXFR | (SUBOP_XFR_XCHG << OP_SH_SUBOP_XFR))
#define OP_MATCH_LOOP (OP_MATCH_FMT2_OP | (SUBOP_LOOP << OP_SH_SUBOP))
#define OP_MATCH_ILOOP (OP_MATCH_FMT2_OP | (SUBOP_LOOP << OP_SH_SUBOP) \
| OP_MASK_LOOP_INTERRUPTIBLE)
#define OP_MATCH_QBGT (OP_MATCH_FMT4_OP | OP_MASK_GT)
#define OP_MATCH_QBGE (OP_MATCH_FMT4_OP | OP_MASK_GT | OP_MASK_EQ)
#define OP_MATCH_QBLT (OP_MATCH_FMT4_OP | OP_MASK_LT)
#define OP_MATCH_QBLE (OP_MATCH_FMT4_OP | OP_MASK_LT | OP_MASK_EQ)
#define OP_MATCH_QBEQ (OP_MATCH_FMT4_OP | OP_MASK_EQ)
#define OP_MATCH_QBNE (OP_MATCH_FMT4_OP | OP_MASK_GT | OP_MASK_LT)
#define OP_MATCH_QBA (OP_MATCH_FMT4_OP | OP_MASK_GT | OP_MASK_LT \
| OP_MASK_EQ)
#define OP_MATCH_QBBS (OP_MATCH_FMT5_OP | OP_MASK_BS)
#define OP_MATCH_QBBC (OP_MATCH_FMT5_OP | OP_MASK_BC)
#define OP_MATCH_LBBO (OP_MATCH_FMT6AB_OP | OP_MASK_LOADSTORE)
#define OP_MATCH_SBBO (OP_MATCH_FMT6AB_OP)
#define OP_MATCH_LBCO (OP_MATCH_FMT6CD_OP | OP_MASK_LOADSTORE)
#define OP_MATCH_SBCO (OP_MATCH_FMT6CD_OP)
/* Some special extractions. */
#define OP_MASK_BROFF (OP_MASK_BROFF98 | OP_MASK_BROFF70)
#define GET_BROFF_URAW(i) \
((GET_INSN_FIELD (BROFF98, i) << 8) | (GET_INSN_FIELD (BROFF70, i) << 0))
#define GET_BROFF_SIGNED(i) \
((long)(GET_BROFF_URAW (i) - (!!(GET_BROFF_URAW (i) & (1 << 9)) << 10)))
#define SET_BROFF_URAW(i, v) \
do { \
SET_INSN_FIELD (BROFF98, (i), (v) >> 8); \
SET_INSN_FIELD (BROFF70, (i), (v) & 0xff); \
} while (0)
#define GET_BURSTLEN(i) \
( (GET_INSN_FIELD (BURSTLEN64, (i)) << 4) | \
(GET_INSN_FIELD (BURSTLEN31, (i)) << 1) | \
(GET_INSN_FIELD (BURSTLEN0, (i)) << 0))
#define SET_BURSTLEN(i, v) \
do { \
SET_INSN_FIELD (BURSTLEN64, (i), (v) >> 4); \
SET_INSN_FIELD (BURSTLEN31, (i), (v) >> 1); \
SET_INSN_FIELD (BURSTLEN0, (i), (v) >> 0); \
} while (0)
/* Miscellaneous helpers. */
#define OP_MASK_XFR_OP (OP_MASK_FMT2_OP | OP_MASK_SUBOP \
| OP_MASK_SUBOP_XFR | OP_MASK_XFR_S)
#define OP_MASK_LOOP_OP (OP_MASK_FMT2_OP | OP_MASK_SUBOP \
| OP_MASK_LOOP_INTERRUPTIBLE)
/* These are the data structures we use to hold the instruction information. */
extern const struct pru_opcode pru_opcodes[];
extern const int bfd_pru_num_opcodes;
/* These are the data structures used to hold the register information. */
extern const struct pru_reg pru_regs[];
extern const int pru_num_regs;
/* Machine-independent macro for number of opcodes. */
#define NUMOPCODES bfd_pru_num_opcodes
#define NUMREGISTERS pru_num_regs;
/* This is made extern so that the assembler can use it to find out
what instruction caused an error. */
extern const struct pru_opcode *pru_find_opcode (unsigned long);
#endif /* _PRU_H */