xref: /openbsd-src/gnu/usr.bin/binutils/include/opcode/arm.h (revision 5f210c2af8ad7a823d98e333e3a6e3d7999783f5)
12159047fSniklas /* ARM opcode list.
2*5f210c2aSfgsch    Copyright 1989, 1991 Free Software Foundation, Inc.
32159047fSniklas 
42159047fSniklas This file is part of GDB and GAS.
52159047fSniklas 
62159047fSniklas GDB and GAS are free software; you can redistribute it and/or modify
72159047fSniklas it under the terms of the GNU General Public License as published by
82159047fSniklas the Free Software Foundation; either version 1, or (at your option)
92159047fSniklas any later version.
102159047fSniklas 
112159047fSniklas GDB and GAS are distributed in the hope that it will be useful,
122159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
132159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
142159047fSniklas GNU General Public License for more details.
152159047fSniklas 
162159047fSniklas You should have received a copy of the GNU General Public License
172159047fSniklas along with GDB or GAS; see the file COPYING.  If not, write to
182159047fSniklas the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
192159047fSniklas 
202159047fSniklas /* types of instruction (encoded in bits 26 and 27 of the instruction) */
212159047fSniklas 
222159047fSniklas #define TYPE_ARITHMETIC		0
232159047fSniklas #define TYPE_LDR_STR		1
242159047fSniklas #define TYPE_BLOCK_BRANCH	2
252159047fSniklas #define TYPE_SWI		3
262159047fSniklas 
272159047fSniklas /* bit 25 decides whether an instruction is a block move or a branch */
282159047fSniklas #define SUBTYPE_BLOCK		0
292159047fSniklas #define SUBTYPE_BRANCH		1
302159047fSniklas 
312159047fSniklas /* codes to distinguish the arithmetic instructions */
322159047fSniklas 
332159047fSniklas #define OPCODE_AND	0
342159047fSniklas #define OPCODE_EOR	1
352159047fSniklas #define OPCODE_SUB	2
362159047fSniklas #define OPCODE_RSB	3
372159047fSniklas #define OPCODE_ADD	4
382159047fSniklas #define OPCODE_ADC	5
392159047fSniklas #define OPCODE_SBC	6
402159047fSniklas #define OPCODE_RSC	7
412159047fSniklas #define OPCODE_TST	8
422159047fSniklas #define OPCODE_TEQ	9
432159047fSniklas #define OPCODE_CMP	10
442159047fSniklas #define OPCODE_CMN	11
452159047fSniklas #define OPCODE_ORR	12
462159047fSniklas #define OPCODE_MOV	13
472159047fSniklas #define OPCODE_BIC	14
482159047fSniklas #define OPCODE_MVN	15
492159047fSniklas 
502159047fSniklas /* condition codes */
512159047fSniklas 
522159047fSniklas #define COND_EQ		0
532159047fSniklas #define COND_NE		1
542159047fSniklas #define COND_CS		2
552159047fSniklas #define COND_CC		3
562159047fSniklas #define COND_MI		4
572159047fSniklas #define COND_PL		5
582159047fSniklas #define COND_VS		6
592159047fSniklas #define COND_VC		7
602159047fSniklas #define COND_HI		8
612159047fSniklas #define COND_LS		9
622159047fSniklas #define COND_GE		10
632159047fSniklas #define COND_LT		11
642159047fSniklas #define COND_GT		12
652159047fSniklas #define COND_LE		13
662159047fSniklas #define COND_AL		14
672159047fSniklas #define COND_NV		15
682159047fSniklas 
692159047fSniklas /* Describes the format of an ARM machine instruction */
702159047fSniklas 
712159047fSniklas struct generic_fmt {
722159047fSniklas     unsigned rest	:25;	/* the rest of the instruction */
732159047fSniklas     unsigned subtype	:1;	/* used to decide between block and branch */
742159047fSniklas     unsigned type	:2;	/* one of TYPE_* */
752159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
762159047fSniklas };
772159047fSniklas 
782159047fSniklas struct arith_fmt {
792159047fSniklas     unsigned operand2	:12;	/* #nn or rn or rn shift #m or rn shift rm */
802159047fSniklas     unsigned dest	:4;	/* place where the answer goes */
812159047fSniklas     unsigned operand1	:4;	/* first operand to instruction */
822159047fSniklas     unsigned set	:1;	/* == 1 means set processor flags */
832159047fSniklas     unsigned opcode	:4;	/* one of OPCODE_* defined above */
842159047fSniklas     unsigned immed	:1;	/* operand2 is an immediate value */
852159047fSniklas     unsigned type	:2;	/* == TYPE_ARITHMETIC */
862159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
872159047fSniklas };
882159047fSniklas 
892159047fSniklas struct ldr_str_fmt {
902159047fSniklas     unsigned offset	:12;	/* #nn or rn or rn shift #m */
912159047fSniklas     unsigned reg	:4;	/* destination for LDR, source for STR */
922159047fSniklas     unsigned base	:4;	/* base register */
932159047fSniklas     unsigned is_load	:1;	/* == 1 for LDR */
942159047fSniklas     unsigned writeback	:1;	/* == 1 means write back (base+offset) into base */
952159047fSniklas     unsigned byte	:1;	/* == 1 means byte access else word */
962159047fSniklas     unsigned up		:1;	/* == 1 means add offset else subtract it */
972159047fSniklas     unsigned pre_index	:1;	/* == 1 means [a,b] form else [a],b form */
982159047fSniklas     unsigned immed	:1;	/* == 0 means immediate offset */
992159047fSniklas     unsigned type	:2;	/* == TYPE_LDR_STR */
1002159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
1012159047fSniklas };
1022159047fSniklas 
1032159047fSniklas struct block_fmt {
1042159047fSniklas     unsigned mask	:16;	/* register mask */
1052159047fSniklas     unsigned base	:4;	/* register used as base of move */
1062159047fSniklas     unsigned is_load	:1;	/* == 1 for LDM */
1072159047fSniklas     unsigned writeback	:1;	/* == 1 means update base after move */
1082159047fSniklas     unsigned set	:1;	/* == 1 means set flags in pc if included in mask */
1092159047fSniklas     unsigned increment	:1;	/* == 1 means increment base register */
1102159047fSniklas     unsigned before	:1;	/* == 1 means inc/dec before each move */
1112159047fSniklas     unsigned is_block	:1;	/* == SUBTYPE_BLOCK */
1122159047fSniklas     unsigned type	:2;	/* == TYPE_BLOCK_BRANCH */
1132159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
1142159047fSniklas };
1152159047fSniklas 
1162159047fSniklas struct branch_fmt {
1172159047fSniklas     unsigned dest	:24;	/* destination of the branch */
1182159047fSniklas     unsigned link	:1;	/* branch with link (function call) */
1192159047fSniklas     unsigned is_branch	:1;	/* == SUBTYPE_BRANCH */
1202159047fSniklas     unsigned type	:2;	/* == TYPE_BLOCK_BRANCH */
1212159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
1222159047fSniklas };
1232159047fSniklas 
1242159047fSniklas #define ROUND_N		0
1252159047fSniklas #define ROUND_P		1
1262159047fSniklas #define ROUND_M		2
1272159047fSniklas #define ROUND_Z		3
1282159047fSniklas 
1292159047fSniklas #define FLOAT2_MVF	0
1302159047fSniklas #define FLOAT2_MNF	1
1312159047fSniklas #define FLOAT2_ABS	2
1322159047fSniklas #define FLOAT2_RND	3
1332159047fSniklas #define FLOAT2_SQT	4
1342159047fSniklas #define FLOAT2_LOG	5
1352159047fSniklas #define FLOAT2_LGN	6
1362159047fSniklas #define FLOAT2_EXP	7
1372159047fSniklas #define FLOAT2_SIN	8
1382159047fSniklas #define FLOAT2_COS	9
1392159047fSniklas #define FLOAT2_TAN	10
1402159047fSniklas #define FLOAT2_ASN	11
1412159047fSniklas #define FLOAT2_ACS	12
1422159047fSniklas #define FLOAT2_ATN	13
1432159047fSniklas 
1442159047fSniklas #define FLOAT3_ADF	0
1452159047fSniklas #define FLOAT3_MUF	1
1462159047fSniklas #define FLOAT3_SUF	2
1472159047fSniklas #define FLOAT3_RSF	3
1482159047fSniklas #define FLOAT3_DVF	4
1492159047fSniklas #define FLOAT3_RDF	5
1502159047fSniklas #define FLOAT3_POW	6
1512159047fSniklas #define FLOAT3_RPW	7
1522159047fSniklas #define FLOAT3_RMF	8
1532159047fSniklas #define FLOAT3_FML	9
1542159047fSniklas #define FLOAT3_FDV	10
1552159047fSniklas #define FLOAT3_FRD	11
1562159047fSniklas #define FLOAT3_POL	12
1572159047fSniklas 
1582159047fSniklas struct float2_fmt {
1592159047fSniklas     unsigned operand2	:3;	/* second operand */
1602159047fSniklas     unsigned immed	:1;	/* == 1 if second operand is a constant */
1612159047fSniklas     unsigned pad1	:1;	/* == 0 */
1622159047fSniklas     unsigned rounding	:2;	/* ROUND_* */
1632159047fSniklas     unsigned is_double	:1;	/* == 1 if precision is double (only if not extended) */
1642159047fSniklas     unsigned pad2	:4;	/* == 1 */
1652159047fSniklas     unsigned dest	:3;	/* destination */
1662159047fSniklas     unsigned is_2_op	:1;	/* == 1 if 2 operand ins */
1672159047fSniklas     unsigned operand1	:3;	/* first operand (only of is_2_op == 0) */
1682159047fSniklas     unsigned is_extended :1;	/* == 1 if precision is extended */
1692159047fSniklas     unsigned opcode	:4;	/* FLOAT2_* or FLOAT3_* depending on is_2_op */
1702159047fSniklas     unsigned must_be_2	:2;	/* == 2 */
1712159047fSniklas     unsigned type	:2;	/* == TYPE_SWI */
1722159047fSniklas     unsigned cond	:4;	/* COND_* */
1732159047fSniklas };
1742159047fSniklas 
1752159047fSniklas struct swi_fmt {
1762159047fSniklas     unsigned argument	:24;	/* argument to SWI (syscall number) */
1772159047fSniklas     unsigned must_be_3	:2;	/* == 3 */
1782159047fSniklas     unsigned type	:2;	/* == TYPE_SWI */
1792159047fSniklas     unsigned cond	:4;	/* one of COND_* defined above */
1802159047fSniklas };
1812159047fSniklas 
1822159047fSniklas union insn_fmt {
1832159047fSniklas     struct generic_fmt	generic;
1842159047fSniklas     struct arith_fmt	arith;
1852159047fSniklas     struct ldr_str_fmt	ldr_str;
1862159047fSniklas     struct block_fmt	block;
1872159047fSniklas     struct branch_fmt	branch;
1882159047fSniklas     struct swi_fmt	swi;
1892159047fSniklas     unsigned long	ins;
1902159047fSniklas };
1912159047fSniklas 
1922159047fSniklas struct opcode {
1932159047fSniklas     unsigned long value, mask;	/* recognise instruction if (op&mask)==value */
1942159047fSniklas     char *assembler;		/* how to disassemble this instruction */
1952159047fSniklas };
1962159047fSniklas 
1972159047fSniklas /* format of the assembler string :
1982159047fSniklas 
1992159047fSniklas    %%			%
2002159047fSniklas    %<bitfield>d		print the bitfield in decimal
2012159047fSniklas    %<bitfield>x		print the bitfield in hex
2022159047fSniklas    %<bitfield>r		print as an ARM register
2032159047fSniklas    %<bitfield>f		print a floating point constant if >7 else an fp register
2042159047fSniklas    %c			print condition code (always bits 28-31)
2052159047fSniklas    %P			print floating point precision in arithmetic insn
2062159047fSniklas    %Q			print floating point precision in ldf/stf insn
2072159047fSniklas    %R			print floating point rounding mode
2082159047fSniklas    %<bitnum>'c		print specified char iff bit is one
2092159047fSniklas    %<bitnum>`c		print specified char iff bit is zero
2102159047fSniklas    %<bitnum>?ab		print a if bit is one else print b
2112159047fSniklas    %p			print 'p' iff bits 12-15 are 15
2122159047fSniklas    %o			print operand2 (immediate or register + shift)
2132159047fSniklas    %a			print address for ldr/str instruction
2142159047fSniklas    %b			print branch destination
2152159047fSniklas    %A			print address for ldc/stc/ldf/stf instruction
2162159047fSniklas    %m			print register mask for ldm/stm instruction
2172159047fSniklas */
2182159047fSniklas 
2192159047fSniklas static struct opcode opcodes[] = {
2202159047fSniklas     /* ARM instructions */
2212159047fSniklas     0x00000090, 0x0fe000f0, "mul%20's %12-15r, %16-19r, %0-3r",
2222159047fSniklas     0x00200090, 0x0fe000f0, "mla%20's %12-15r, %16-19r, %0-3r, %8-11r",
2232159047fSniklas     0x00000000, 0x0de00000, "and%c%20's %12-15r, %16-19r, %o",
2242159047fSniklas     0x00200000, 0x0de00000, "eor%c%20's %12-15r, %16-19r, %o",
2252159047fSniklas     0x00400000, 0x0de00000, "sub%c%20's %12-15r, %16-19r, %o",
2262159047fSniklas     0x00600000, 0x0de00000, "rsb%c%20's %12-15r, %16-19r, %o",
2272159047fSniklas     0x00800000, 0x0de00000, "add%c%20's %12-15r, %16-19r, %o",
2282159047fSniklas     0x00a00000, 0x0de00000, "adc%c%20's %12-15r, %16-19r, %o",
2292159047fSniklas     0x00c00000, 0x0de00000, "sbc%c%20's %12-15r, %16-19r, %o",
2302159047fSniklas     0x00e00000, 0x0de00000, "rsc%c%20's %12-15r, %16-19r, %o",
2312159047fSniklas     0x01000000, 0x0de00000, "tst%c%p %16-19r, %o",
2322159047fSniklas     0x01200000, 0x0de00000, "teq%c%p %16-19r, %o",
2332159047fSniklas     0x01400000, 0x0de00000, "cmp%c%p %16-19r, %o",
2342159047fSniklas     0x01600000, 0x0de00000, "cmn%c%p %16-19r, %o",
2352159047fSniklas     0x01800000, 0x0de00000, "orr%c%20's %12-15r, %16-19r, %o",
2362159047fSniklas     0x01a00000, 0x0de00000, "mov%c%20's %12-15r, %o",
2372159047fSniklas     0x01c00000, 0x0de00000, "bic%c%20's %12-15r, %16-19r, %o",
2382159047fSniklas     0x01e00000, 0x0de00000, "mvn%c%20's %12-15r, %o",
2392159047fSniklas     0x04000000, 0x0c100000, "str%c%22'b %12-15r, %a",
2402159047fSniklas     0x04100000, 0x0c100000, "ldr%c%22'b %12-15r, %a",
2412159047fSniklas     0x08000000, 0x0e100000, "stm%c%23?id%24?ba %16-19r%22`!, %m",
2422159047fSniklas     0x08100000, 0x0e100000, "ldm%c%23?id%24?ba %16-19r%22`!, %m%22'^",
2432159047fSniklas     0x0a000000, 0x0e000000, "b%c%24'l %b",
2442159047fSniklas     0x0f000000, 0x0f000000, "swi%c %0-23x",
2452159047fSniklas     /* Floating point coprocessor instructions */
2462159047fSniklas     0x0e000100, 0x0ff08f10, "adf%c%P%R %12-14f, %16-18f, %0-3f",
2472159047fSniklas     0x0e100100, 0x0ff08f10, "muf%c%P%R %12-14f, %16-18f, %0-3f",
2482159047fSniklas     0x0e200100, 0x0ff08f10, "suf%c%P%R %12-14f, %16-18f, %0-3f",
2492159047fSniklas     0x0e300100, 0x0ff08f10, "rsf%c%P%R %12-14f, %16-18f, %0-3f",
2502159047fSniklas     0x0e400100, 0x0ff08f10, "dvf%c%P%R %12-14f, %16-18f, %0-3f",
2512159047fSniklas     0x0e500100, 0x0ff08f10, "rdf%c%P%R %12-14f, %16-18f, %0-3f",
2522159047fSniklas     0x0e600100, 0x0ff08f10, "pow%c%P%R %12-14f, %16-18f, %0-3f",
2532159047fSniklas     0x0e700100, 0x0ff08f10, "rpw%c%P%R %12-14f, %16-18f, %0-3f",
2542159047fSniklas     0x0e800100, 0x0ff08f10, "rmf%c%P%R %12-14f, %16-18f, %0-3f",
2552159047fSniklas     0x0e900100, 0x0ff08f10, "fml%c%P%R %12-14f, %16-18f, %0-3f",
2562159047fSniklas     0x0ea00100, 0x0ff08f10, "fdv%c%P%R %12-14f, %16-18f, %0-3f",
2572159047fSniklas     0x0eb00100, 0x0ff08f10, "frd%c%P%R %12-14f, %16-18f, %0-3f",
2582159047fSniklas     0x0ec00100, 0x0ff08f10, "pol%c%P%R %12-14f, %16-18f, %0-3f",
2592159047fSniklas     0x0e008100, 0x0ff08f10, "mvf%c%P%R %12-14f, %0-3f",
2602159047fSniklas     0x0e108100, 0x0ff08f10, "mnf%c%P%R %12-14f, %0-3f",
2612159047fSniklas     0x0e208100, 0x0ff08f10, "abs%c%P%R %12-14f, %0-3f",
2622159047fSniklas     0x0e308100, 0x0ff08f10, "rnd%c%P%R %12-14f, %0-3f",
2632159047fSniklas     0x0e408100, 0x0ff08f10, "sqt%c%P%R %12-14f, %0-3f",
2642159047fSniklas     0x0e508100, 0x0ff08f10, "log%c%P%R %12-14f, %0-3f",
2652159047fSniklas     0x0e608100, 0x0ff08f10, "lgn%c%P%R %12-14f, %0-3f",
2662159047fSniklas     0x0e708100, 0x0ff08f10, "exp%c%P%R %12-14f, %0-3f",
2672159047fSniklas     0x0e808100, 0x0ff08f10, "sin%c%P%R %12-14f, %0-3f",
2682159047fSniklas     0x0e908100, 0x0ff08f10, "cos%c%P%R %12-14f, %0-3f",
2692159047fSniklas     0x0ea08100, 0x0ff08f10, "tan%c%P%R %12-14f, %0-3f",
2702159047fSniklas     0x0eb08100, 0x0ff08f10, "asn%c%P%R %12-14f, %0-3f",
2712159047fSniklas     0x0ec08100, 0x0ff08f10, "acs%c%P%R %12-14f, %0-3f",
2722159047fSniklas     0x0ed08100, 0x0ff08f10, "atn%c%P%R %12-14f, %0-3f",
2732159047fSniklas     0x0e000110, 0x0ff00f1f, "flt%c%P%R %16-18f, %12-15r",
2742159047fSniklas     0x0e100110, 0x0fff0f98, "fix%c%R %12-15r, %0-2f",
2752159047fSniklas     0x0e200110, 0x0fff0fff, "wfs%c %12-15r",
2762159047fSniklas     0x0e300110, 0x0fff0fff, "rfs%c %12-15r",
2772159047fSniklas     0x0e400110, 0x0fff0fff, "wfc%c %12-15r",
2782159047fSniklas     0x0e500110, 0x0fff0fff, "rfc%c %12-15r",
2792159047fSniklas     0x0e90f110, 0x0ff8fff0, "cmf%c %16-18f, %0-3f",
2802159047fSniklas     0x0eb0f110, 0x0ff8fff0, "cnf%c %16-18f, %0-3f",
2812159047fSniklas     0x0ed0f110, 0x0ff8fff0, "cmfe%c %16-18f, %0-3f",
2822159047fSniklas     0x0ef0f110, 0x0ff8fff0, "cnfe%c %16-18f, %0-3f",
2832159047fSniklas     0x0c000100, 0x0e100f00, "stf%c%Q %12-14f, %A",
2842159047fSniklas     0x0c100100, 0x0e100f00, "ldf%c%Q %12-14f, %A",
2852159047fSniklas     /* Generic coprocessor instructions */
2862159047fSniklas     0x0e000000, 0x0f000010, "cdp%c %8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}",
2872159047fSniklas     0x0e000010, 0x0f100010, "mrc%c %8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}",
2882159047fSniklas     0x0e100010, 0x0f100010, "mcr%c %8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}",
2892159047fSniklas     0x0c000000, 0x0e100000, "stc%c%22`l %8-11d, cr%12-15d, %A",
2902159047fSniklas     0x0c100000, 0x0e100000, "ldc%c%22`l %8-11d, cr%12-15d, %A",
2912159047fSniklas     /* the rest */
2922159047fSniklas     0x00000000, 0x00000000, "undefined instruction %0-31x",
2932159047fSniklas };
2942159047fSniklas #define N_OPCODES	(sizeof opcodes / sizeof opcodes[0])
295