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