tc-arm.c revision 94536
1/* tc-arm.c -- Assemble for the ARM 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 3 Free Software Foundation, Inc. 4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) 5 Modified by David Taylor (dtaylor@armltd.co.uk) 6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com) 7 8 This file is part of GAS, the GNU Assembler. 9 10 GAS is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2, or (at your option) 13 any later version. 14 15 GAS is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with GAS; see the file COPYING. If not, write to the Free 22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 23 02111-1307, USA. */ 24 25#include <string.h> 26#define NO_RELOC 0 27#include "as.h" 28#include "safe-ctype.h" 29 30/* Need TARGET_CPU. */ 31#include "config.h" 32#include "subsegs.h" 33#include "obstack.h" 34#include "symbols.h" 35#include "listing.h" 36 37#ifdef OBJ_ELF 38#include "elf/arm.h" 39#include "dwarf2dbg.h" 40#endif 41 42/* XXX Set this to 1 after the next binutils release */ 43#define WARN_DEPRECATED 0 44 45/* The following bitmasks control CPU extensions: */ 46#define ARM_EXT_V1 0x00000001 /* All processors (core set). */ 47#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */ 48#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */ 49#define ARM_EXT_V3 0x00000008 /* MSR MRS. */ 50#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */ 51#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */ 52#define ARM_EXT_V4T 0x00000040 /* Thumb v1. */ 53#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */ 54#define ARM_EXT_V5T 0x00000100 /* Thumb v2. */ 55#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */ 56#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */ 57#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */ 58 59/* Co-processor space extensions. */ 60#define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */ 61#define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */ 62 63/* Architectures are the sum of the base and extensions. The ARM ARM (rev E) 64 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T, 65 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add 66 three more to cover cores prior to ARM6. Finally, there are cores which 67 implement further extensions in the co-processor space. */ 68#define ARM_ARCH_V1 ARM_EXT_V1 69#define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2) 70#define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S) 71#define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3) 72#define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M) 73#define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4) 74#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4) 75#define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T) 76#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T) 77#define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5) 78#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5) 79#define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T) 80#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T) 81#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP) 82#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E) 83#define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J) 84 85/* Processors with specific extensions in the co-processor space. */ 86#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE) 87 88/* Some useful combinations: */ 89#define ARM_ANY 0x0000ffff /* Any basic core. */ 90#define ARM_ALL 0x00ffffff /* Any core + co-processor */ 91#define CPROC_ANY 0x00ff0000 /* Any co-processor */ 92#define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */ 93 94 95#define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */ 96#define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */ 97#define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */ 98#define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */ 99#define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */ 100#define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */ 101#define FPU_NONE 0 102 103#define FPU_ARCH_FPE FPU_FPA_EXT_V1 104#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2) 105 106#define FPU_ARCH_VFP FPU_VFP_EXT_NONE 107#define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE) 108#define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1) 109#define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2) 110 111/* Types of processor to assemble for. */ 112#define ARM_1 ARM_ARCH_V1 113#define ARM_2 ARM_ARCH_V2 114#define ARM_3 ARM_ARCH_V2S 115#define ARM_250 ARM_ARCH_V2S 116#define ARM_6 ARM_ARCH_V3 117#define ARM_7 ARM_ARCH_V3 118#define ARM_8 ARM_ARCH_V4 119#define ARM_9 ARM_ARCH_V4T 120#define ARM_STRONG ARM_ARCH_V4 121#define ARM_CPU_MASK 0x0000000f /* XXX? */ 122 123#ifndef CPU_DEFAULT 124#if defined __XSCALE__ 125#define CPU_DEFAULT (ARM_ARCH_XSCALE) 126#else 127#if defined __thumb__ 128#define CPU_DEFAULT (ARM_ARCH_V5T) 129#else 130#define CPU_DEFAULT ARM_ANY 131#endif 132#endif 133#endif 134 135/* For backwards compatibility we default to the FPA. */ 136#ifndef FPU_DEFAULT 137#define FPU_DEFAULT FPU_ARCH_FPA 138#endif 139 140#define streq(a, b) (strcmp (a, b) == 0) 141#define skip_whitespace(str) while (*(str) == ' ') ++(str) 142 143static unsigned long cpu_variant; 144static int target_oabi = 0; 145 146/* Flags stored in private area of BFD structure. */ 147static int uses_apcs_26 = false; 148static int atpcs = false; 149static int support_interwork = false; 150static int uses_apcs_float = false; 151static int pic_code = false; 152 153/* Variables that we set while parsing command-line options. Once all 154 options have been read we re-process these values to set the real 155 assembly flags. */ 156static int legacy_cpu = -1; 157static int legacy_fpu = -1; 158 159static int mcpu_cpu_opt = -1; 160static int mcpu_fpu_opt = -1; 161static int march_cpu_opt = -1; 162static int march_fpu_opt = -1; 163static int mfpu_opt = -1; 164 165/* This array holds the chars that always start a comment. If the 166 pre-processor is disabled, these aren't very useful. */ 167const char comment_chars[] = "@"; 168 169/* This array holds the chars that only start a comment at the beginning of 170 a line. If the line seems to have the form '# 123 filename' 171 .line and .file directives will appear in the pre-processed output. */ 172/* Note that input_file.c hand checks for '#' at the beginning of the 173 first line of the input file. This is because the compiler outputs 174 #NO_APP at the beginning of its output. */ 175/* Also note that comments like this one will always work. */ 176const char line_comment_chars[] = "#"; 177 178const char line_separator_chars[] = ";"; 179 180/* Chars that can be used to separate mant 181 from exp in floating point numbers. */ 182const char EXP_CHARS[] = "eE"; 183 184/* Chars that mean this number is a floating point constant. */ 185/* As in 0f12.456 */ 186/* or 0d1.2345e12 */ 187 188const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; 189 190/* Prefix characters that indicate the start of an immediate 191 value. */ 192#define is_immediate_prefix(C) ((C) == '#' || (C) == '$') 193 194#ifdef OBJ_ELF 195/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ 196symbolS * GOT_symbol; 197#endif 198 199/* Size of relocation record. */ 200const int md_reloc_size = 8; 201 202/* 0: assemble for ARM, 203 1: assemble for Thumb, 204 2: assemble for Thumb even though target CPU does not support thumb 205 instructions. */ 206static int thumb_mode = 0; 207 208typedef struct arm_fix 209{ 210 int thumb_mode; 211} arm_fix_data; 212 213struct arm_it 214{ 215 const char * error; 216 unsigned long instruction; 217 int size; 218 struct 219 { 220 bfd_reloc_code_real_type type; 221 expressionS exp; 222 int pc_rel; 223 } reloc; 224}; 225 226struct arm_it inst; 227 228enum asm_shift_index 229{ 230 SHIFT_LSL = 0, 231 SHIFT_LSR, 232 SHIFT_ASR, 233 SHIFT_ROR, 234 SHIFT_RRX 235}; 236 237struct asm_shift_properties 238{ 239 enum asm_shift_index index; 240 unsigned long bit_field; 241 unsigned int allows_0 : 1; 242 unsigned int allows_32 : 1; 243}; 244 245static const struct asm_shift_properties shift_properties [] = 246{ 247 { SHIFT_LSL, 0, 1, 0}, 248 { SHIFT_LSR, 0x20, 0, 1}, 249 { SHIFT_ASR, 0x40, 0, 1}, 250 { SHIFT_ROR, 0x60, 0, 0}, 251 { SHIFT_RRX, 0x60, 0, 0} 252}; 253 254struct asm_shift_name 255{ 256 const char * name; 257 const struct asm_shift_properties * properties; 258}; 259 260static const struct asm_shift_name shift_names [] = 261{ 262 { "asl", shift_properties + SHIFT_LSL }, 263 { "lsl", shift_properties + SHIFT_LSL }, 264 { "lsr", shift_properties + SHIFT_LSR }, 265 { "asr", shift_properties + SHIFT_ASR }, 266 { "ror", shift_properties + SHIFT_ROR }, 267 { "rrx", shift_properties + SHIFT_RRX }, 268 { "ASL", shift_properties + SHIFT_LSL }, 269 { "LSL", shift_properties + SHIFT_LSL }, 270 { "LSR", shift_properties + SHIFT_LSR }, 271 { "ASR", shift_properties + SHIFT_ASR }, 272 { "ROR", shift_properties + SHIFT_ROR }, 273 { "RRX", shift_properties + SHIFT_RRX } 274}; 275 276#define NO_SHIFT_RESTRICT 1 277#define SHIFT_RESTRICT 0 278 279#define NUM_FLOAT_VALS 8 280 281const char * fp_const[] = 282{ 283 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0 284}; 285 286/* Number of littlenums required to hold an extended precision number. */ 287#define MAX_LITTLENUMS 6 288 289LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS]; 290 291#define FAIL (-1) 292#define SUCCESS (0) 293 294/* Whether a Co-processor load/store operation accepts write-back forms. */ 295#define CP_WB_OK 1 296#define CP_NO_WB 0 297 298#define SUFF_S 1 299#define SUFF_D 2 300#define SUFF_E 3 301#define SUFF_P 4 302 303#define CP_T_X 0x00008000 304#define CP_T_Y 0x00400000 305#define CP_T_Pre 0x01000000 306#define CP_T_UD 0x00800000 307#define CP_T_WB 0x00200000 308 309#define CONDS_BIT 0x00100000 310#define LOAD_BIT 0x00100000 311 312#define DOUBLE_LOAD_FLAG 0x00000001 313 314struct asm_cond 315{ 316 const char * template; 317 unsigned long value; 318}; 319 320#define COND_ALWAYS 0xe0000000 321#define COND_MASK 0xf0000000 322 323static const struct asm_cond conds[] = 324{ 325 {"eq", 0x00000000}, 326 {"ne", 0x10000000}, 327 {"cs", 0x20000000}, {"hs", 0x20000000}, 328 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000}, 329 {"mi", 0x40000000}, 330 {"pl", 0x50000000}, 331 {"vs", 0x60000000}, 332 {"vc", 0x70000000}, 333 {"hi", 0x80000000}, 334 {"ls", 0x90000000}, 335 {"ge", 0xa0000000}, 336 {"lt", 0xb0000000}, 337 {"gt", 0xc0000000}, 338 {"le", 0xd0000000}, 339 {"al", 0xe0000000}, 340 {"nv", 0xf0000000} 341}; 342 343struct asm_psr 344{ 345 const char * template; 346 boolean cpsr; 347 unsigned long field; 348}; 349 350/* The bit that distnguishes CPSR and SPSR. */ 351#define SPSR_BIT (1 << 22) 352 353/* How many bits to shift the PSR_xxx bits up by. */ 354#define PSR_SHIFT 16 355 356#define PSR_c (1 << 0) 357#define PSR_x (1 << 1) 358#define PSR_s (1 << 2) 359#define PSR_f (1 << 3) 360 361static const struct asm_psr psrs[] = 362{ 363 {"CPSR", true, PSR_c | PSR_f}, 364 {"CPSR_all", true, PSR_c | PSR_f}, 365 {"SPSR", false, PSR_c | PSR_f}, 366 {"SPSR_all", false, PSR_c | PSR_f}, 367 {"CPSR_flg", true, PSR_f}, 368 {"CPSR_f", true, PSR_f}, 369 {"SPSR_flg", false, PSR_f}, 370 {"SPSR_f", false, PSR_f}, 371 {"CPSR_c", true, PSR_c}, 372 {"CPSR_ctl", true, PSR_c}, 373 {"SPSR_c", false, PSR_c}, 374 {"SPSR_ctl", false, PSR_c}, 375 {"CPSR_x", true, PSR_x}, 376 {"CPSR_s", true, PSR_s}, 377 {"SPSR_x", false, PSR_x}, 378 {"SPSR_s", false, PSR_s}, 379 /* Combinations of flags. */ 380 {"CPSR_fs", true, PSR_f | PSR_s}, 381 {"CPSR_fx", true, PSR_f | PSR_x}, 382 {"CPSR_fc", true, PSR_f | PSR_c}, 383 {"CPSR_sf", true, PSR_s | PSR_f}, 384 {"CPSR_sx", true, PSR_s | PSR_x}, 385 {"CPSR_sc", true, PSR_s | PSR_c}, 386 {"CPSR_xf", true, PSR_x | PSR_f}, 387 {"CPSR_xs", true, PSR_x | PSR_s}, 388 {"CPSR_xc", true, PSR_x | PSR_c}, 389 {"CPSR_cf", true, PSR_c | PSR_f}, 390 {"CPSR_cs", true, PSR_c | PSR_s}, 391 {"CPSR_cx", true, PSR_c | PSR_x}, 392 {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x}, 393 {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c}, 394 {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s}, 395 {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c}, 396 {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s}, 397 {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x}, 398 {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x}, 399 {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c}, 400 {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f}, 401 {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c}, 402 {"CPSR_scf", true, PSR_s | PSR_c | PSR_f}, 403 {"CPSR_scx", true, PSR_s | PSR_c | PSR_x}, 404 {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s}, 405 {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c}, 406 {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f}, 407 {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c}, 408 {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f}, 409 {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s}, 410 {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s}, 411 {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x}, 412 {"CPSR_csf", true, PSR_c | PSR_s | PSR_f}, 413 {"CPSR_csx", true, PSR_c | PSR_s | PSR_x}, 414 {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f}, 415 {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s}, 416 {"CPSR_fsxc", true, PSR_f | PSR_s | PSR_x | PSR_c}, 417 {"CPSR_fscx", true, PSR_f | PSR_s | PSR_c | PSR_x}, 418 {"CPSR_fxsc", true, PSR_f | PSR_x | PSR_s | PSR_c}, 419 {"CPSR_fxcs", true, PSR_f | PSR_x | PSR_c | PSR_s}, 420 {"CPSR_fcsx", true, PSR_f | PSR_c | PSR_s | PSR_x}, 421 {"CPSR_fcxs", true, PSR_f | PSR_c | PSR_x | PSR_s}, 422 {"CPSR_sfxc", true, PSR_s | PSR_f | PSR_x | PSR_c}, 423 {"CPSR_sfcx", true, PSR_s | PSR_f | PSR_c | PSR_x}, 424 {"CPSR_sxfc", true, PSR_s | PSR_x | PSR_f | PSR_c}, 425 {"CPSR_sxcf", true, PSR_s | PSR_x | PSR_c | PSR_f}, 426 {"CPSR_scfx", true, PSR_s | PSR_c | PSR_f | PSR_x}, 427 {"CPSR_scxf", true, PSR_s | PSR_c | PSR_x | PSR_f}, 428 {"CPSR_xfsc", true, PSR_x | PSR_f | PSR_s | PSR_c}, 429 {"CPSR_xfcs", true, PSR_x | PSR_f | PSR_c | PSR_s}, 430 {"CPSR_xsfc", true, PSR_x | PSR_s | PSR_f | PSR_c}, 431 {"CPSR_xscf", true, PSR_x | PSR_s | PSR_c | PSR_f}, 432 {"CPSR_xcfs", true, PSR_x | PSR_c | PSR_f | PSR_s}, 433 {"CPSR_xcsf", true, PSR_x | PSR_c | PSR_s | PSR_f}, 434 {"CPSR_cfsx", true, PSR_c | PSR_f | PSR_s | PSR_x}, 435 {"CPSR_cfxs", true, PSR_c | PSR_f | PSR_x | PSR_s}, 436 {"CPSR_csfx", true, PSR_c | PSR_s | PSR_f | PSR_x}, 437 {"CPSR_csxf", true, PSR_c | PSR_s | PSR_x | PSR_f}, 438 {"CPSR_cxfs", true, PSR_c | PSR_x | PSR_f | PSR_s}, 439 {"CPSR_cxsf", true, PSR_c | PSR_x | PSR_s | PSR_f}, 440 {"SPSR_fs", false, PSR_f | PSR_s}, 441 {"SPSR_fx", false, PSR_f | PSR_x}, 442 {"SPSR_fc", false, PSR_f | PSR_c}, 443 {"SPSR_sf", false, PSR_s | PSR_f}, 444 {"SPSR_sx", false, PSR_s | PSR_x}, 445 {"SPSR_sc", false, PSR_s | PSR_c}, 446 {"SPSR_xf", false, PSR_x | PSR_f}, 447 {"SPSR_xs", false, PSR_x | PSR_s}, 448 {"SPSR_xc", false, PSR_x | PSR_c}, 449 {"SPSR_cf", false, PSR_c | PSR_f}, 450 {"SPSR_cs", false, PSR_c | PSR_s}, 451 {"SPSR_cx", false, PSR_c | PSR_x}, 452 {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x}, 453 {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c}, 454 {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s}, 455 {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c}, 456 {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s}, 457 {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x}, 458 {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x}, 459 {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c}, 460 {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f}, 461 {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c}, 462 {"SPSR_scf", false, PSR_s | PSR_c | PSR_f}, 463 {"SPSR_scx", false, PSR_s | PSR_c | PSR_x}, 464 {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s}, 465 {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c}, 466 {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f}, 467 {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c}, 468 {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f}, 469 {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s}, 470 {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s}, 471 {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x}, 472 {"SPSR_csf", false, PSR_c | PSR_s | PSR_f}, 473 {"SPSR_csx", false, PSR_c | PSR_s | PSR_x}, 474 {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f}, 475 {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s}, 476 {"SPSR_fsxc", false, PSR_f | PSR_s | PSR_x | PSR_c}, 477 {"SPSR_fscx", false, PSR_f | PSR_s | PSR_c | PSR_x}, 478 {"SPSR_fxsc", false, PSR_f | PSR_x | PSR_s | PSR_c}, 479 {"SPSR_fxcs", false, PSR_f | PSR_x | PSR_c | PSR_s}, 480 {"SPSR_fcsx", false, PSR_f | PSR_c | PSR_s | PSR_x}, 481 {"SPSR_fcxs", false, PSR_f | PSR_c | PSR_x | PSR_s}, 482 {"SPSR_sfxc", false, PSR_s | PSR_f | PSR_x | PSR_c}, 483 {"SPSR_sfcx", false, PSR_s | PSR_f | PSR_c | PSR_x}, 484 {"SPSR_sxfc", false, PSR_s | PSR_x | PSR_f | PSR_c}, 485 {"SPSR_sxcf", false, PSR_s | PSR_x | PSR_c | PSR_f}, 486 {"SPSR_scfx", false, PSR_s | PSR_c | PSR_f | PSR_x}, 487 {"SPSR_scxf", false, PSR_s | PSR_c | PSR_x | PSR_f}, 488 {"SPSR_xfsc", false, PSR_x | PSR_f | PSR_s | PSR_c}, 489 {"SPSR_xfcs", false, PSR_x | PSR_f | PSR_c | PSR_s}, 490 {"SPSR_xsfc", false, PSR_x | PSR_s | PSR_f | PSR_c}, 491 {"SPSR_xscf", false, PSR_x | PSR_s | PSR_c | PSR_f}, 492 {"SPSR_xcfs", false, PSR_x | PSR_c | PSR_f | PSR_s}, 493 {"SPSR_xcsf", false, PSR_x | PSR_c | PSR_s | PSR_f}, 494 {"SPSR_cfsx", false, PSR_c | PSR_f | PSR_s | PSR_x}, 495 {"SPSR_cfxs", false, PSR_c | PSR_f | PSR_x | PSR_s}, 496 {"SPSR_csfx", false, PSR_c | PSR_s | PSR_f | PSR_x}, 497 {"SPSR_csxf", false, PSR_c | PSR_s | PSR_x | PSR_f}, 498 {"SPSR_cxfs", false, PSR_c | PSR_x | PSR_f | PSR_s}, 499 {"SPSR_cxsf", false, PSR_c | PSR_x | PSR_s | PSR_f}, 500}; 501 502enum vfp_dp_reg_pos 503{ 504 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn 505}; 506 507enum vfp_sp_reg_pos 508{ 509 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn 510}; 511 512enum vfp_ldstm_type 513{ 514 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX 515}; 516 517/* VFP system registers. */ 518struct vfp_reg 519{ 520 const char *name; 521 unsigned long regno; 522}; 523 524static const struct vfp_reg vfp_regs[] = 525{ 526 {"fpsid", 0x00000000}, 527 {"FPSID", 0x00000000}, 528 {"fpscr", 0x00010000}, 529 {"FPSCR", 0x00010000}, 530 {"fpexc", 0x00080000}, 531 {"FPEXC", 0x00080000} 532}; 533 534/* Structure for a hash table entry for a register. */ 535struct reg_entry 536{ 537 const char * name; 538 int number; 539}; 540 541/* Some well known registers that we refer to directly elsewhere. */ 542#define REG_SP 13 543#define REG_LR 14 544#define REG_PC 15 545 546/* These are the standard names. Users can add aliases with .req. */ 547/* Integer Register Numbers. */ 548static const struct reg_entry rn_table[] = 549{ 550 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, 551 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, 552 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11}, 553 {"r12", 12}, {"r13", REG_SP}, {"r14", REG_LR}, {"r15", REG_PC}, 554 /* ATPCS Synonyms. */ 555 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3}, 556 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, 557 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11}, 558 /* Well-known aliases. */ 559 {"wr", 7}, 560 {"sb", 9}, {"sl", 10}, {"fp", 11}, 561 {"ip", 12}, {"sp", REG_SP}, {"lr", REG_LR}, {"pc", REG_PC}, 562 {NULL, 0} 563}; 564 565/* Co-processor Numbers. */ 566static const struct reg_entry cp_table[] = 567{ 568 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3}, 569 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7}, 570 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11}, 571 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15}, 572 {NULL, 0} 573}; 574 575/* Co-processor Register Numbers. */ 576static const struct reg_entry cn_table[] = 577{ 578 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3}, 579 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7}, 580 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11}, 581 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15}, 582 /* Not really valid, but kept for back-wards compatibility. */ 583 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3}, 584 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7}, 585 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11}, 586 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15}, 587 {NULL, 0} 588}; 589 590/* FPA Registers. */ 591static const struct reg_entry fn_table[] = 592{ 593 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3}, 594 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7}, 595 {NULL, 0} 596}; 597 598/* VFP SP Registers. */ 599static const struct reg_entry sn_table[] = 600{ 601 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3}, 602 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7}, 603 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11}, 604 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15}, 605 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19}, 606 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23}, 607 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27}, 608 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31}, 609 {NULL, 0} 610}; 611 612/* VFP DP Registers. */ 613static const struct reg_entry dn_table[] = 614{ 615 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3}, 616 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7}, 617 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11}, 618 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15}, 619 {NULL, 0} 620}; 621 622/* Maverick DSP coprocessor registers. */ 623static const struct reg_entry mav_mvf_table[] = 624{ 625 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3}, 626 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7}, 627 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11}, 628 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15}, 629 {NULL, 0} 630}; 631 632static const struct reg_entry mav_mvd_table[] = 633{ 634 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3}, 635 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7}, 636 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11}, 637 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15}, 638 {NULL, 0} 639}; 640 641static const struct reg_entry mav_mvfx_table[] = 642{ 643 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3}, 644 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7}, 645 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11}, 646 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15}, 647 {NULL, 0} 648}; 649 650static const struct reg_entry mav_mvdx_table[] = 651{ 652 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3}, 653 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7}, 654 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11}, 655 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15}, 656 {NULL, 0} 657}; 658 659static const struct reg_entry mav_mvax_table[] = 660{ 661 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3}, 662 {NULL, 0} 663}; 664 665static const struct reg_entry mav_dspsc_table[] = 666{ 667 {"dspsc", 0}, 668 {NULL, 0} 669}; 670 671struct reg_map 672{ 673 const struct reg_entry *names; 674 int max_regno; 675 struct hash_control *htab; 676 const char *expected; 677}; 678 679struct reg_map all_reg_maps[] = 680{ 681 {rn_table, 15, NULL, N_("ARM register expected")}, 682 {cp_table, 15, NULL, N_("bad or missing co-processor number")}, 683 {cn_table, 15, NULL, N_("co-processor register expected")}, 684 {fn_table, 7, NULL, N_("FPA register expected")}, 685 {sn_table, 31, NULL, N_("VFP single precision register expected")}, 686 {dn_table, 15, NULL, N_("VFP double precision register expected")}, 687 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")}, 688 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")}, 689 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")}, 690 {mav_mvdx_table, 15, NULL, N_("Maverick MVFX register expected")}, 691 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")}, 692 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")}, 693}; 694 695/* Enumeration matching entries in table above. */ 696enum arm_reg_type 697{ 698 REG_TYPE_RN = 0, 699#define REG_TYPE_FIRST REG_TYPE_RN 700 REG_TYPE_CP = 1, 701 REG_TYPE_CN = 2, 702 REG_TYPE_FN = 3, 703 REG_TYPE_SN = 4, 704 REG_TYPE_DN = 5, 705 REG_TYPE_MVF = 6, 706 REG_TYPE_MVD = 7, 707 REG_TYPE_MVFX = 8, 708 REG_TYPE_MVDX = 9, 709 REG_TYPE_MVAX = 10, 710 REG_TYPE_DSPSC = 11, 711 712 REG_TYPE_MAX = 12 713}; 714 715/* Functions called by parser. */ 716/* ARM instructions. */ 717static void do_arit PARAMS ((char *)); 718static void do_cmp PARAMS ((char *)); 719static void do_mov PARAMS ((char *)); 720static void do_ldst PARAMS ((char *)); 721static void do_ldstt PARAMS ((char *)); 722static void do_ldmstm PARAMS ((char *)); 723static void do_branch PARAMS ((char *)); 724static void do_swi PARAMS ((char *)); 725 726/* Pseudo Op codes. */ 727static void do_adr PARAMS ((char *)); 728static void do_adrl PARAMS ((char *)); 729static void do_empty PARAMS ((char *)); 730 731/* ARM v2. */ 732static void do_mul PARAMS ((char *)); 733static void do_mla PARAMS ((char *)); 734 735/* ARM v2S. */ 736static void do_swap PARAMS ((char *)); 737 738/* ARM v3. */ 739static void do_msr PARAMS ((char *)); 740static void do_mrs PARAMS ((char *)); 741 742/* ARM v3M. */ 743static void do_mull PARAMS ((char *)); 744 745/* ARM v4. */ 746static void do_ldstv4 PARAMS ((char *)); 747 748/* ARM v4T. */ 749static void do_bx PARAMS ((char *)); 750 751/* ARM v5T. */ 752static void do_blx PARAMS ((char *)); 753static void do_bkpt PARAMS ((char *)); 754static void do_clz PARAMS ((char *)); 755static void do_lstc2 PARAMS ((char *)); 756static void do_cdp2 PARAMS ((char *)); 757static void do_co_reg2 PARAMS ((char *)); 758 759/* ARM v5TExP. */ 760static void do_smla PARAMS ((char *)); 761static void do_smlal PARAMS ((char *)); 762static void do_smul PARAMS ((char *)); 763static void do_qadd PARAMS ((char *)); 764 765/* ARM v5TE. */ 766static void do_pld PARAMS ((char *)); 767static void do_ldrd PARAMS ((char *)); 768static void do_co_reg2c PARAMS ((char *)); 769 770/* ARM v5TEJ. */ 771static void do_bxj PARAMS ((char *)); 772 773/* Coprocessor Instructions. */ 774static void do_cdp PARAMS ((char *)); 775static void do_lstc PARAMS ((char *)); 776static void do_co_reg PARAMS ((char *)); 777 778/* FPA instructions. */ 779static void do_fpa_ctrl PARAMS ((char *)); 780static void do_fpa_ldst PARAMS ((char *)); 781static void do_fpa_ldmstm PARAMS ((char *)); 782static void do_fpa_dyadic PARAMS ((char *)); 783static void do_fpa_monadic PARAMS ((char *)); 784static void do_fpa_cmp PARAMS ((char *)); 785static void do_fpa_from_reg PARAMS ((char *)); 786static void do_fpa_to_reg PARAMS ((char *)); 787 788/* VFP instructions. */ 789static void do_vfp_sp_monadic PARAMS ((char *)); 790static void do_vfp_dp_monadic PARAMS ((char *)); 791static void do_vfp_sp_dyadic PARAMS ((char *)); 792static void do_vfp_dp_dyadic PARAMS ((char *)); 793static void do_vfp_reg_from_sp PARAMS ((char *)); 794static void do_vfp_sp_from_reg PARAMS ((char *)); 795static void do_vfp_sp_reg2 PARAMS ((char *)); 796static void do_vfp_reg_from_dp PARAMS ((char *)); 797static void do_vfp_reg2_from_dp PARAMS ((char *)); 798static void do_vfp_dp_from_reg PARAMS ((char *)); 799static void do_vfp_dp_from_reg2 PARAMS ((char *)); 800static void do_vfp_reg_from_ctrl PARAMS ((char *)); 801static void do_vfp_ctrl_from_reg PARAMS ((char *)); 802static void do_vfp_sp_ldst PARAMS ((char *)); 803static void do_vfp_dp_ldst PARAMS ((char *)); 804static void do_vfp_sp_ldstmia PARAMS ((char *)); 805static void do_vfp_sp_ldstmdb PARAMS ((char *)); 806static void do_vfp_dp_ldstmia PARAMS ((char *)); 807static void do_vfp_dp_ldstmdb PARAMS ((char *)); 808static void do_vfp_xp_ldstmia PARAMS ((char *)); 809static void do_vfp_xp_ldstmdb PARAMS ((char *)); 810static void do_vfp_sp_compare_z PARAMS ((char *)); 811static void do_vfp_dp_compare_z PARAMS ((char *)); 812static void do_vfp_dp_sp_cvt PARAMS ((char *)); 813static void do_vfp_sp_dp_cvt PARAMS ((char *)); 814 815/* XScale. */ 816static void do_xsc_mia PARAMS ((char *)); 817static void do_xsc_mar PARAMS ((char *)); 818static void do_xsc_mra PARAMS ((char *)); 819 820/* Maverick. */ 821static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type, 822 enum arm_reg_type)); 823static void do_mav_binops_1a PARAMS ((char *)); 824static void do_mav_binops_1b PARAMS ((char *)); 825static void do_mav_binops_1c PARAMS ((char *)); 826static void do_mav_binops_1d PARAMS ((char *)); 827static void do_mav_binops_1e PARAMS ((char *)); 828static void do_mav_binops_1f PARAMS ((char *)); 829static void do_mav_binops_1g PARAMS ((char *)); 830static void do_mav_binops_1h PARAMS ((char *)); 831static void do_mav_binops_1i PARAMS ((char *)); 832static void do_mav_binops_1j PARAMS ((char *)); 833static void do_mav_binops_1k PARAMS ((char *)); 834static void do_mav_binops_1l PARAMS ((char *)); 835static void do_mav_binops_1m PARAMS ((char *)); 836static void do_mav_binops_1n PARAMS ((char *)); 837static void do_mav_binops_1o PARAMS ((char *)); 838static void do_mav_binops_2a PARAMS ((char *)); 839static void do_mav_binops_2b PARAMS ((char *)); 840static void do_mav_binops_2c PARAMS ((char *)); 841static void do_mav_binops_3a PARAMS ((char *)); 842static void do_mav_binops_3b PARAMS ((char *)); 843static void do_mav_binops_3c PARAMS ((char *)); 844static void do_mav_binops_3d PARAMS ((char *)); 845static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type, 846 enum arm_reg_type, 847 enum arm_reg_type)); 848static void do_mav_triple_4a PARAMS ((char *)); 849static void do_mav_triple_4b PARAMS ((char *)); 850static void do_mav_triple_5a PARAMS ((char *)); 851static void do_mav_triple_5b PARAMS ((char *)); 852static void do_mav_triple_5c PARAMS ((char *)); 853static void do_mav_triple_5d PARAMS ((char *)); 854static void do_mav_triple_5e PARAMS ((char *)); 855static void do_mav_triple_5f PARAMS ((char *)); 856static void do_mav_triple_5g PARAMS ((char *)); 857static void do_mav_triple_5h PARAMS ((char *)); 858static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type, 859 enum arm_reg_type, 860 enum arm_reg_type, 861 enum arm_reg_type)); 862static void do_mav_quad_6a PARAMS ((char *)); 863static void do_mav_quad_6b PARAMS ((char *)); 864static void do_mav_dspsc_1 PARAMS ((char *)); 865static void do_mav_dspsc_2 PARAMS ((char *)); 866static void do_mav_shift PARAMS ((char *, enum arm_reg_type, 867 enum arm_reg_type)); 868static void do_mav_shift_1 PARAMS ((char *)); 869static void do_mav_shift_2 PARAMS ((char *)); 870static void do_mav_ldst PARAMS ((char *, enum arm_reg_type)); 871static void do_mav_ldst_1 PARAMS ((char *)); 872static void do_mav_ldst_2 PARAMS ((char *)); 873static void do_mav_ldst_3 PARAMS ((char *)); 874static void do_mav_ldst_4 PARAMS ((char *)); 875 876static int mav_reg_required_here PARAMS ((char **, int, 877 enum arm_reg_type)); 878static int mav_parse_offset PARAMS ((char **, int *)); 879 880static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *, 881 int, int)); 882static int arm_reg_parse PARAMS ((char **, struct hash_control *)); 883static enum arm_reg_type arm_reg_parse_any PARAMS ((char *)); 884static const struct asm_psr * arm_psr_parse PARAMS ((char **)); 885static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT, 886 fragS *)); 887static int add_to_lit_pool PARAMS ((void)); 888static unsigned validate_immediate PARAMS ((unsigned)); 889static unsigned validate_immediate_twopart PARAMS ((unsigned int, 890 unsigned int *)); 891static int validate_offset_imm PARAMS ((unsigned int, int)); 892static void opcode_select PARAMS ((int)); 893static void end_of_line PARAMS ((char *)); 894static int reg_required_here PARAMS ((char **, int)); 895static int psr_required_here PARAMS ((char **)); 896static int co_proc_number PARAMS ((char **)); 897static int cp_opc_expr PARAMS ((char **, int, int)); 898static int cp_reg_required_here PARAMS ((char **, int)); 899static int fp_reg_required_here PARAMS ((char **, int)); 900static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos)); 901static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos)); 902static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type)); 903static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type)); 904static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos)); 905static long vfp_dp_reg_list PARAMS ((char **)); 906static int vfp_psr_required_here PARAMS ((char **str)); 907static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str)); 908static int cp_address_offset PARAMS ((char **)); 909static int cp_address_required_here PARAMS ((char **, int)); 910static int my_get_float_expression PARAMS ((char **)); 911static int skip_past_comma PARAMS ((char **)); 912static int walk_no_bignums PARAMS ((symbolS *)); 913static int negate_data_op PARAMS ((unsigned long *, unsigned long)); 914static int data_op2 PARAMS ((char **)); 915static int fp_op2 PARAMS ((char **)); 916static long reg_list PARAMS ((char **)); 917static void thumb_load_store PARAMS ((char *, int, int)); 918static int decode_shift PARAMS ((char **, int)); 919static int ldst_extend PARAMS ((char **)); 920static int ldst_extend_v4 PARAMS ((char **)); 921static void thumb_add_sub PARAMS ((char *, int)); 922static void insert_reg PARAMS ((const struct reg_entry *, 923 struct hash_control *)); 924static void thumb_shift PARAMS ((char *, int)); 925static void thumb_mov_compare PARAMS ((char *, int)); 926static void build_arm_ops_hsh PARAMS ((void)); 927static void set_constant_flonums PARAMS ((void)); 928static valueT md_chars_to_number PARAMS ((char *, int)); 929static void build_reg_hsh PARAMS ((struct reg_map *)); 930static void insert_reg_alias PARAMS ((char *, int, struct hash_control *)); 931static int create_register_alias PARAMS ((char *, char *)); 932static void output_inst PARAMS ((const char *)); 933static int accum0_required_here PARAMS ((char **)); 934static int ld_mode_required_here PARAMS ((char **)); 935static void do_branch25 PARAMS ((char *)); 936static symbolS * find_real_start PARAMS ((symbolS *)); 937#ifdef OBJ_ELF 938static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void)); 939#endif 940 941/* ARM instructions take 4bytes in the object file, Thumb instructions 942 take 2: */ 943#define INSN_SIZE 4 944 945/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */ 946#define MAV_MODE1 0x100c 947 948/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */ 949#define MAV_MODE2 0x0c10 950 951/* "INSN<cond> X,Y" where X:0, Y:bit16. */ 952#define MAV_MODE3 0x1000 953 954/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */ 955#define MAV_MODE4 0x0c0010 956 957/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */ 958#define MAV_MODE5 0x00100c 959 960/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */ 961#define MAV_MODE6 0x00100c05 962 963struct asm_opcode 964{ 965 /* Basic string to match. */ 966 const char * template; 967 968 /* Basic instruction code. */ 969 unsigned long value; 970 971 /* Offset into the template where the condition code (if any) will be. 972 If zero, then the instruction is never conditional. */ 973 unsigned cond_offset; 974 975 /* Which architecture variant provides this instruction. */ 976 unsigned long variant; 977 978 /* Function to call to parse args. */ 979 void (* parms) PARAMS ((char *)); 980}; 981 982static const struct asm_opcode insns[] = 983{ 984 /* Core ARM Instructions. */ 985 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit}, 986 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit}, 987 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit}, 988 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit}, 989 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit}, 990 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit}, 991 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit}, 992 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit}, 993 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit}, 994 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit}, 995 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit}, 996 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit}, 997 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit}, 998 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit}, 999 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit}, 1000 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit}, 1001 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit}, 1002 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit}, 1003 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit}, 1004 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit}, 1005 1006 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp}, 1007 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp}, 1008 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp}, 1009 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp}, 1010 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp}, 1011 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp}, 1012 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp}, 1013 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp}, 1014 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp}, 1015 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp}, 1016 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp}, 1017 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp}, 1018 1019 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov}, 1020 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov}, 1021 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov}, 1022 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov}, 1023 1024 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst}, 1025 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst}, 1026 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt}, 1027 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt}, 1028 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst}, 1029 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst}, 1030 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt}, 1031 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt}, 1032 1033 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm}, 1034 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm}, 1035 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm}, 1036 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm}, 1037 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm}, 1038 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm}, 1039 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm}, 1040 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm}, 1041 1042 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm}, 1043 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm}, 1044 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm}, 1045 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm}, 1046 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm}, 1047 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm}, 1048 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm}, 1049 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm}, 1050 1051 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi}, 1052#ifdef TE_WINCE 1053 /* XXX This is the wrong place to do this. Think multi-arch. */ 1054 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch}, 1055 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch}, 1056#else 1057 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch}, 1058 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch}, 1059#endif 1060 1061 /* Pseudo ops. */ 1062 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr}, 1063 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl}, 1064 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty}, 1065 1066 /* ARM 2 multiplies. */ 1067 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul}, 1068 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul}, 1069 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla}, 1070 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla}, 1071 1072 /* Generic copressor instructions. */ 1073 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp}, 1074 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc}, 1075 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc}, 1076 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc}, 1077 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc}, 1078 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg}, 1079 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg}, 1080 1081 /* ARM 3 - swp instructions. */ 1082 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap}, 1083 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap}, 1084 1085 /* ARM 6 Status register instructions. */ 1086 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs}, 1087 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr}, 1088 /* ScottB: our code uses 0xe128f000 for msr. 1089 NickC: but this is wrong because the bits 16 through 19 are 1090 handled by the PSR_xxx defines above. */ 1091 1092 /* ARM 7M long multiplies. */ 1093 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull}, 1094 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull}, 1095 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull}, 1096 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull}, 1097 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull}, 1098 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull}, 1099 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull}, 1100 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull}, 1101 1102 /* ARM Architecture 4. */ 1103 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4}, 1104 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4}, 1105 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4}, 1106 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4}, 1107 1108 /* ARM Architecture 4T. */ 1109 /* Note: bx (and blx) are required on V5, even if the processor does 1110 not support Thumb. */ 1111 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx}, 1112 1113 /* ARM Architecture 5T. */ 1114 /* Note: blx has 2 variants, so the .value is set dynamically. 1115 Only one of the variants has conditional execution. */ 1116 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx}, 1117 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz}, 1118 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt}, 1119 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2}, 1120 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2}, 1121 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2}, 1122 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2}, 1123 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2}, 1124 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2}, 1125 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2}, 1126 1127 /* ARM Architecture 5TExP. */ 1128 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla}, 1129 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla}, 1130 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla}, 1131 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla}, 1132 1133 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla}, 1134 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla}, 1135 1136 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal}, 1137 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal}, 1138 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal}, 1139 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal}, 1140 1141 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul}, 1142 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul}, 1143 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul}, 1144 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul}, 1145 1146 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul}, 1147 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul}, 1148 1149 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd}, 1150 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd}, 1151 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd}, 1152 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd}, 1153 1154 /* ARM Architecture 5TE. */ 1155 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld}, 1156 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd}, 1157 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd}, 1158 1159 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c}, 1160 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c}, 1161 1162 /* ARM Architecture 5TEJ. */ 1163 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj}, 1164 1165 /* Core FPA instruction set (V1). */ 1166 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl}, 1167 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl}, 1168 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl}, 1169 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl}, 1170 1171 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1172 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1173 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1174 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1175 1176 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1177 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1178 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1179 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst}, 1180 1181 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1182 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1183 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1184 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1185 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1186 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1187 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1188 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1189 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1190 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1191 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1192 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1193 1194 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1195 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1196 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1197 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1198 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1199 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1200 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1201 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1202 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1203 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1204 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1205 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1206 1207 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1208 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1209 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1210 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1211 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1212 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1213 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1214 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1215 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1216 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1217 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1218 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1219 1220 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1221 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1222 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1223 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1224 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1225 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1226 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1227 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1228 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1229 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1230 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1231 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1232 1233 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1234 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1235 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1236 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1237 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1238 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1239 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1240 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1241 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1242 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1243 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1244 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1245 1246 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1247 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1248 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1249 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1250 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1251 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1252 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1253 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1254 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1255 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1256 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1257 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1258 1259 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1260 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1261 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1262 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1263 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1264 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1265 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1266 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1267 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1268 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1269 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1270 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1271 1272 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1273 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1274 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1275 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1276 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1277 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1278 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1279 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1280 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1281 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1282 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1283 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1284 1285 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1286 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1287 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1288 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1289 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1290 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1291 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1292 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1293 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1294 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1295 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1296 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1297 1298 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1299 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1300 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1301 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1302 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1303 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1304 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1305 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1306 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1307 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1308 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1309 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1310 1311 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1312 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1313 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1314 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1315 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1316 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1317 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1318 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1319 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1320 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1321 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1322 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1323 1324 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1325 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1326 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1327 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1328 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1329 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1330 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1331 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1332 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1333 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1334 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1335 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1336 1337 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1338 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1339 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1340 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1341 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1342 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1343 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1344 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1345 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1346 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1347 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1348 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1349 1350 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1351 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1352 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1353 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1354 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1355 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1356 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1357 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1358 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1359 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1360 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1361 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1362 1363 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1364 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1365 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1366 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1367 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1368 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1369 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1370 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1371 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1372 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1373 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1374 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1375 1376 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1377 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1378 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1379 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1380 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1381 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1382 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1383 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1384 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1385 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1386 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1387 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic}, 1388 1389 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1390 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1391 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1392 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1393 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1394 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1395 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1396 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1397 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1398 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1399 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1400 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1401 1402 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1403 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1404 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1405 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1406 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1407 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1408 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1409 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1410 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1411 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1412 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1413 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1414 1415 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1416 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1417 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1418 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1419 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1420 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1421 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1422 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1423 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1424 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1425 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1426 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1427 1428 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1429 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1430 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1431 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1432 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1433 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1434 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1435 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1436 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1437 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1438 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1439 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1440 1441 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1442 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1443 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1444 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1445 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1446 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1447 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1448 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1449 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1450 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1451 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1452 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1453 1454 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1455 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1456 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1457 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1458 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1459 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1460 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1461 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1462 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1463 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1464 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1465 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1466 1467 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1468 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1469 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1470 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1471 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1472 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1473 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1474 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1475 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1476 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1477 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1478 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1479 1480 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1481 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1482 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1483 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1484 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1485 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1486 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1487 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1488 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1489 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1490 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1491 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1492 1493 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1494 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1495 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1496 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1497 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1498 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1499 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1500 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1501 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1502 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1503 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1504 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1505 1506 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1507 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1508 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1509 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1510 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1511 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1512 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1513 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1514 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1515 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1516 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1517 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1518 1519 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1520 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1521 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1522 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1523 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1524 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1525 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1526 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1527 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1528 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1529 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1530 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1531 1532 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1533 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1534 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1535 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1536 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1537 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1538 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1539 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1540 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1541 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1542 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1543 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1544 1545 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1546 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1547 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1548 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1549 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1550 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1551 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1552 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1553 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1554 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1555 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1556 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic}, 1557 1558 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp}, 1559 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp}, 1560 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp}, 1561 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp}, 1562 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should 1563 not be an optional suffix, but part of the instruction. To be 1564 compatible, we accept either. */ 1565 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp}, 1566 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp}, 1567 1568 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1569 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1570 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1571 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1572 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1573 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1574 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1575 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1576 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1577 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1578 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1579 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg}, 1580 1581 /* The implementation of the FIX instruction is broken on some 1582 assemblers, in that it accepts a precision specifier as well as a 1583 rounding specifier, despite the fact that this is meaningless. 1584 To be more compatible, we accept it as well, though of course it 1585 does not set any bits. */ 1586 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1587 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1588 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1589 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1590 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1591 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1592 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1593 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1594 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1595 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1596 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1597 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1598 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg}, 1599 1600 /* Instructions that were new with the real FPA, call them V2. */ 1601 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1602 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1603 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1604 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1605 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1606 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm}, 1607 1608 /* VFP V1xD (single precision). */ 1609 /* Moves and type conversions. */ 1610 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1611 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp}, 1612 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg}, 1613 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty}, 1614 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1615 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1616 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1617 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1618 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1619 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1620 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl}, 1621 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg}, 1622 1623 /* Memory operations. */ 1624 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst}, 1625 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst}, 1626 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia}, 1627 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia}, 1628 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb}, 1629 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb}, 1630 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia}, 1631 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia}, 1632 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb}, 1633 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb}, 1634 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia}, 1635 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia}, 1636 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb}, 1637 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb}, 1638 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia}, 1639 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia}, 1640 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb}, 1641 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb}, 1642 1643 /* Monadic operations. */ 1644 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1645 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1646 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1647 1648 /* Dyadic operations. */ 1649 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1650 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1651 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1652 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1653 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1654 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1655 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1656 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1657 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic}, 1658 1659 /* Comparisons. */ 1660 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1661 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z}, 1662 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic}, 1663 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z}, 1664 1665 /* VFP V1 (Double precision). */ 1666 /* Moves and type conversions. */ 1667 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1668 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt}, 1669 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt}, 1670 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg}, 1671 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg}, 1672 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp}, 1673 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp}, 1674 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt}, 1675 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt}, 1676 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt}, 1677 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt}, 1678 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt}, 1679 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt}, 1680 1681 /* Memory operations. */ 1682 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst}, 1683 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst}, 1684 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia}, 1685 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia}, 1686 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb}, 1687 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb}, 1688 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia}, 1689 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia}, 1690 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb}, 1691 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb}, 1692 1693 /* Monadic operations. */ 1694 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1695 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1696 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1697 1698 /* Dyadic operations. */ 1699 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1700 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1701 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1702 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1703 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1704 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1705 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1706 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1707 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic}, 1708 1709 /* Comparisons. */ 1710 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1711 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z}, 1712 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic}, 1713 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z}, 1714 1715 /* VFP V2. */ 1716 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2}, 1717 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2}, 1718 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2}, 1719 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp}, 1720 1721 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */ 1722 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia}, 1723 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia}, 1724 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia}, 1725 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia}, 1726 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia}, 1727 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia}, 1728 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar}, 1729 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra}, 1730 1731 /* Cirrus Maverick instructions. */ 1732 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1}, 1733 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2}, 1734 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3}, 1735 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4}, 1736 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1}, 1737 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2}, 1738 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3}, 1739 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4}, 1740 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a}, 1741 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a}, 1742 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b}, 1743 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b}, 1744 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b}, 1745 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b}, 1746 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c}, 1747 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c}, 1748 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c}, 1749 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c}, 1750 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, 1751 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, 1752 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, 1753 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, 1754 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, 1755 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, 1756 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a}, 1757 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b}, 1758 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c}, 1759 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d}, 1760 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1}, 1761 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2}, 1762 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d}, 1763 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e}, 1764 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f}, 1765 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g}, 1766 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h}, 1767 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i}, 1768 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j}, 1769 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k}, 1770 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l}, 1771 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m}, 1772 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l}, 1773 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m}, 1774 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a}, 1775 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b}, 1776 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1}, 1777 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2}, 1778 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a}, 1779 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b}, 1780 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c}, 1781 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d}, 1782 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d}, 1783 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e}, 1784 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d}, 1785 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e}, 1786 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e}, 1787 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f}, 1788 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e}, 1789 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f}, 1790 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e}, 1791 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f}, 1792 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n}, 1793 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o}, 1794 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n}, 1795 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o}, 1796 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g}, 1797 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h}, 1798 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g}, 1799 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h}, 1800 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g}, 1801 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h}, 1802 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g}, 1803 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g}, 1804 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a}, 1805 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a}, 1806 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b}, 1807 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b}, 1808}; 1809 1810/* Defines for various bits that we will want to toggle. */ 1811#define INST_IMMEDIATE 0x02000000 1812#define OFFSET_REG 0x02000000 1813#define HWOFFSET_IMM 0x00400000 1814#define SHIFT_BY_REG 0x00000010 1815#define PRE_INDEX 0x01000000 1816#define INDEX_UP 0x00800000 1817#define WRITE_BACK 0x00200000 1818#define LDM_TYPE_2_OR_3 0x00400000 1819 1820#define LITERAL_MASK 0xf000f000 1821#define OPCODE_MASK 0xfe1fffff 1822#define V4_STR_BIT 0x00000020 1823 1824#define DATA_OP_SHIFT 21 1825 1826/* Codes to distinguish the arithmetic instructions. */ 1827#define OPCODE_AND 0 1828#define OPCODE_EOR 1 1829#define OPCODE_SUB 2 1830#define OPCODE_RSB 3 1831#define OPCODE_ADD 4 1832#define OPCODE_ADC 5 1833#define OPCODE_SBC 6 1834#define OPCODE_RSC 7 1835#define OPCODE_TST 8 1836#define OPCODE_TEQ 9 1837#define OPCODE_CMP 10 1838#define OPCODE_CMN 11 1839#define OPCODE_ORR 12 1840#define OPCODE_MOV 13 1841#define OPCODE_BIC 14 1842#define OPCODE_MVN 15 1843 1844/* Thumb v1 (ARMv4T). */ 1845static void do_t_nop PARAMS ((char *)); 1846static void do_t_arit PARAMS ((char *)); 1847static void do_t_add PARAMS ((char *)); 1848static void do_t_asr PARAMS ((char *)); 1849static void do_t_branch9 PARAMS ((char *)); 1850static void do_t_branch12 PARAMS ((char *)); 1851static void do_t_branch23 PARAMS ((char *)); 1852static void do_t_bx PARAMS ((char *)); 1853static void do_t_compare PARAMS ((char *)); 1854static void do_t_ldmstm PARAMS ((char *)); 1855static void do_t_ldr PARAMS ((char *)); 1856static void do_t_ldrb PARAMS ((char *)); 1857static void do_t_ldrh PARAMS ((char *)); 1858static void do_t_lds PARAMS ((char *)); 1859static void do_t_lsl PARAMS ((char *)); 1860static void do_t_lsr PARAMS ((char *)); 1861static void do_t_mov PARAMS ((char *)); 1862static void do_t_push_pop PARAMS ((char *)); 1863static void do_t_str PARAMS ((char *)); 1864static void do_t_strb PARAMS ((char *)); 1865static void do_t_strh PARAMS ((char *)); 1866static void do_t_sub PARAMS ((char *)); 1867static void do_t_swi PARAMS ((char *)); 1868static void do_t_adr PARAMS ((char *)); 1869 1870/* Thumb v2 (ARMv5T). */ 1871static void do_t_blx PARAMS ((char *)); 1872static void do_t_bkpt PARAMS ((char *)); 1873 1874#define T_OPCODE_MUL 0x4340 1875#define T_OPCODE_TST 0x4200 1876#define T_OPCODE_CMN 0x42c0 1877#define T_OPCODE_NEG 0x4240 1878#define T_OPCODE_MVN 0x43c0 1879 1880#define T_OPCODE_ADD_R3 0x1800 1881#define T_OPCODE_SUB_R3 0x1a00 1882#define T_OPCODE_ADD_HI 0x4400 1883#define T_OPCODE_ADD_ST 0xb000 1884#define T_OPCODE_SUB_ST 0xb080 1885#define T_OPCODE_ADD_SP 0xa800 1886#define T_OPCODE_ADD_PC 0xa000 1887#define T_OPCODE_ADD_I8 0x3000 1888#define T_OPCODE_SUB_I8 0x3800 1889#define T_OPCODE_ADD_I3 0x1c00 1890#define T_OPCODE_SUB_I3 0x1e00 1891 1892#define T_OPCODE_ASR_R 0x4100 1893#define T_OPCODE_LSL_R 0x4080 1894#define T_OPCODE_LSR_R 0x40c0 1895#define T_OPCODE_ASR_I 0x1000 1896#define T_OPCODE_LSL_I 0x0000 1897#define T_OPCODE_LSR_I 0x0800 1898 1899#define T_OPCODE_MOV_I8 0x2000 1900#define T_OPCODE_CMP_I8 0x2800 1901#define T_OPCODE_CMP_LR 0x4280 1902#define T_OPCODE_MOV_HR 0x4600 1903#define T_OPCODE_CMP_HR 0x4500 1904 1905#define T_OPCODE_LDR_PC 0x4800 1906#define T_OPCODE_LDR_SP 0x9800 1907#define T_OPCODE_STR_SP 0x9000 1908#define T_OPCODE_LDR_IW 0x6800 1909#define T_OPCODE_STR_IW 0x6000 1910#define T_OPCODE_LDR_IH 0x8800 1911#define T_OPCODE_STR_IH 0x8000 1912#define T_OPCODE_LDR_IB 0x7800 1913#define T_OPCODE_STR_IB 0x7000 1914#define T_OPCODE_LDR_RW 0x5800 1915#define T_OPCODE_STR_RW 0x5000 1916#define T_OPCODE_LDR_RH 0x5a00 1917#define T_OPCODE_STR_RH 0x5200 1918#define T_OPCODE_LDR_RB 0x5c00 1919#define T_OPCODE_STR_RB 0x5400 1920 1921#define T_OPCODE_PUSH 0xb400 1922#define T_OPCODE_POP 0xbc00 1923 1924#define T_OPCODE_BRANCH 0xe7fe 1925 1926static int thumb_reg PARAMS ((char ** str, int hi_lo)); 1927 1928#define THUMB_SIZE 2 /* Size of thumb instruction. */ 1929#define THUMB_REG_LO 0x1 1930#define THUMB_REG_HI 0x2 1931#define THUMB_REG_ANY 0x3 1932 1933#define THUMB_H1 0x0080 1934#define THUMB_H2 0x0040 1935 1936#define THUMB_ASR 0 1937#define THUMB_LSL 1 1938#define THUMB_LSR 2 1939 1940#define THUMB_MOVE 0 1941#define THUMB_COMPARE 1 1942 1943#define THUMB_LOAD 0 1944#define THUMB_STORE 1 1945 1946#define THUMB_PP_PC_LR 0x0100 1947 1948/* These three are used for immediate shifts, do not alter. */ 1949#define THUMB_WORD 2 1950#define THUMB_HALFWORD 1 1951#define THUMB_BYTE 0 1952 1953struct thumb_opcode 1954{ 1955 /* Basic string to match. */ 1956 const char * template; 1957 1958 /* Basic instruction code. */ 1959 unsigned long value; 1960 1961 int size; 1962 1963 /* Which CPU variants this exists for. */ 1964 unsigned long variant; 1965 1966 /* Function to call to parse args. */ 1967 void (* parms) PARAMS ((char *)); 1968}; 1969 1970static const struct thumb_opcode tinsns[] = 1971{ 1972 /* Thumb v1 (ARMv4T). */ 1973 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit}, 1974 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add}, 1975 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit}, 1976 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr}, 1977 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12}, 1978 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9}, 1979 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9}, 1980 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9}, 1981 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9}, 1982 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9}, 1983 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9}, 1984 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9}, 1985 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9}, 1986 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9}, 1987 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9}, 1988 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9}, 1989 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9}, 1990 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9}, 1991 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9}, 1992 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9}, 1993 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9}, 1994 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9}, 1995 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9}, 1996 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit}, 1997 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23}, 1998 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx}, 1999 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit}, 2000 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare}, 2001 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit}, 2002 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm}, 2003 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr}, 2004 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb}, 2005 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh}, 2006 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds}, 2007 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds}, 2008 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds}, 2009 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds}, 2010 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl}, 2011 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr}, 2012 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov}, 2013 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit}, 2014 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit}, 2015 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit}, 2016 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit}, 2017 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop}, 2018 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop}, 2019 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit}, 2020 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit}, 2021 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm}, 2022 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str}, 2023 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb}, 2024 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh}, 2025 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi}, 2026 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub}, 2027 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit}, 2028 /* Pseudo ops: */ 2029 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr}, 2030 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */ 2031 /* Thumb v2 (ARMv5T). */ 2032 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx}, 2033 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt}, 2034}; 2035 2036#define BAD_ARGS _("bad arguments to instruction") 2037#define BAD_PC _("r15 not allowed here") 2038#define BAD_COND _("instruction is not conditional") 2039#define ERR_NO_ACCUM _("acc0 expected") 2040 2041static struct hash_control * arm_ops_hsh = NULL; 2042static struct hash_control * arm_tops_hsh = NULL; 2043static struct hash_control * arm_cond_hsh = NULL; 2044static struct hash_control * arm_shift_hsh = NULL; 2045static struct hash_control * arm_psr_hsh = NULL; 2046 2047/* This table describes all the machine specific pseudo-ops the assembler 2048 has to support. The fields are: 2049 pseudo-op name without dot 2050 function to call to execute this pseudo-op 2051 Integer arg to pass to the function. */ 2052 2053static void s_req PARAMS ((int)); 2054static void s_align PARAMS ((int)); 2055static void s_bss PARAMS ((int)); 2056static void s_even PARAMS ((int)); 2057static void s_ltorg PARAMS ((int)); 2058static void s_arm PARAMS ((int)); 2059static void s_thumb PARAMS ((int)); 2060static void s_code PARAMS ((int)); 2061static void s_force_thumb PARAMS ((int)); 2062static void s_thumb_func PARAMS ((int)); 2063static void s_thumb_set PARAMS ((int)); 2064static void arm_s_text PARAMS ((int)); 2065static void arm_s_data PARAMS ((int)); 2066#ifdef OBJ_ELF 2067static void arm_s_section PARAMS ((int)); 2068static void s_arm_elf_cons PARAMS ((int)); 2069#endif 2070 2071static int my_get_expression PARAMS ((expressionS *, char **)); 2072 2073const pseudo_typeS md_pseudo_table[] = 2074{ 2075 /* Never called becasue '.req' does not start line. */ 2076 { "req", s_req, 0 }, 2077 { "bss", s_bss, 0 }, 2078 { "align", s_align, 0 }, 2079 { "arm", s_arm, 0 }, 2080 { "thumb", s_thumb, 0 }, 2081 { "code", s_code, 0 }, 2082 { "force_thumb", s_force_thumb, 0 }, 2083 { "thumb_func", s_thumb_func, 0 }, 2084 { "thumb_set", s_thumb_set, 0 }, 2085 { "even", s_even, 0 }, 2086 { "ltorg", s_ltorg, 0 }, 2087 { "pool", s_ltorg, 0 }, 2088 /* Allow for the effect of section changes. */ 2089 { "text", arm_s_text, 0 }, 2090 { "data", arm_s_data, 0 }, 2091#ifdef OBJ_ELF 2092 { "section", arm_s_section, 0 }, 2093 { "section.s", arm_s_section, 0 }, 2094 { "sect", arm_s_section, 0 }, 2095 { "sect.s", arm_s_section, 0 }, 2096 { "word", s_arm_elf_cons, 4 }, 2097 { "long", s_arm_elf_cons, 4 }, 2098 { "file", dwarf2_directive_file, 0 }, 2099 { "loc", dwarf2_directive_loc, 0 }, 2100#else 2101 { "word", cons, 4}, 2102#endif 2103 { "extend", float_cons, 'x' }, 2104 { "ldouble", float_cons, 'x' }, 2105 { "packed", float_cons, 'p' }, 2106 { 0, 0, 0 } 2107}; 2108 2109/* Other internal functions. */ 2110static int arm_parse_extension PARAMS ((char *, int *)); 2111static int arm_parse_cpu PARAMS ((char *)); 2112static int arm_parse_arch PARAMS ((char *)); 2113static int arm_parse_fpu PARAMS ((char *)); 2114 2115/* Stuff needed to resolve the label ambiguity 2116 As: 2117 ... 2118 label: <insn> 2119 may differ from: 2120 ... 2121 label: 2122 <insn> 2123*/ 2124 2125symbolS * last_label_seen; 2126static int label_is_thumb_function_name = false; 2127 2128/* Literal stuff. */ 2129 2130#define MAX_LITERAL_POOL_SIZE 1024 2131 2132typedef struct literalS 2133{ 2134 struct expressionS exp; 2135 struct arm_it * inst; 2136} literalT; 2137 2138literalT literals[MAX_LITERAL_POOL_SIZE]; 2139 2140/* Next free entry in the pool. */ 2141int next_literal_pool_place = 0; 2142 2143/* Next literal pool number. */ 2144int lit_pool_num = 1; 2145 2146symbolS * current_poolP = NULL; 2147 2148static int 2149add_to_lit_pool () 2150{ 2151 int lit_count = 0; 2152 2153 if (current_poolP == NULL) 2154 current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section, 2155 (valueT) 0, &zero_address_frag); 2156 2157 /* Check if this literal value is already in the pool: */ 2158 while (lit_count < next_literal_pool_place) 2159 { 2160 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op 2161 && inst.reloc.exp.X_op == O_constant 2162 && (literals[lit_count].exp.X_add_number 2163 == inst.reloc.exp.X_add_number) 2164 && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned) 2165 break; 2166 2167 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op 2168 && inst.reloc.exp.X_op == O_symbol 2169 && (literals[lit_count].exp.X_add_number 2170 == inst.reloc.exp.X_add_number) 2171 && (literals[lit_count].exp.X_add_symbol 2172 == inst.reloc.exp.X_add_symbol) 2173 && (literals[lit_count].exp.X_op_symbol 2174 == inst.reloc.exp.X_op_symbol)) 2175 break; 2176 2177 lit_count++; 2178 } 2179 2180 if (lit_count == next_literal_pool_place) /* New entry. */ 2181 { 2182 if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE) 2183 { 2184 inst.error = _("literal pool overflow"); 2185 return FAIL; 2186 } 2187 2188 literals[next_literal_pool_place].exp = inst.reloc.exp; 2189 lit_count = next_literal_pool_place++; 2190 } 2191 2192 inst.reloc.exp.X_op = O_symbol; 2193 inst.reloc.exp.X_add_number = (lit_count) * 4 - 8; 2194 inst.reloc.exp.X_add_symbol = current_poolP; 2195 2196 return SUCCESS; 2197} 2198 2199/* Can't use symbol_new here, so have to create a symbol and then at 2200 a later date assign it a value. Thats what these functions do. */ 2201 2202static void 2203symbol_locate (symbolP, name, segment, valu, frag) 2204 symbolS * symbolP; 2205 const char * name; /* It is copied, the caller can modify. */ 2206 segT segment; /* Segment identifier (SEG_<something>). */ 2207 valueT valu; /* Symbol value. */ 2208 fragS * frag; /* Associated fragment. */ 2209{ 2210 unsigned int name_length; 2211 char * preserved_copy_of_name; 2212 2213 name_length = strlen (name) + 1; /* +1 for \0. */ 2214 obstack_grow (¬es, name, name_length); 2215 preserved_copy_of_name = obstack_finish (¬es); 2216#ifdef STRIP_UNDERSCORE 2217 if (preserved_copy_of_name[0] == '_') 2218 preserved_copy_of_name++; 2219#endif 2220 2221#ifdef tc_canonicalize_symbol_name 2222 preserved_copy_of_name = 2223 tc_canonicalize_symbol_name (preserved_copy_of_name); 2224#endif 2225 2226 S_SET_NAME (symbolP, preserved_copy_of_name); 2227 2228 S_SET_SEGMENT (symbolP, segment); 2229 S_SET_VALUE (symbolP, valu); 2230 symbol_clear_list_pointers(symbolP); 2231 2232 symbol_set_frag (symbolP, frag); 2233 2234 /* Link to end of symbol chain. */ 2235 { 2236 extern int symbol_table_frozen; 2237 if (symbol_table_frozen) 2238 abort (); 2239 } 2240 2241 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP); 2242 2243 obj_symbol_new_hook (symbolP); 2244 2245#ifdef tc_symbol_new_hook 2246 tc_symbol_new_hook (symbolP); 2247#endif 2248 2249#ifdef DEBUG_SYMS 2250 verify_symbol_chain (symbol_rootP, symbol_lastP); 2251#endif /* DEBUG_SYMS */ 2252} 2253 2254/* Check that an immediate is valid. 2255 If so, convert it to the right format. */ 2256 2257static unsigned int 2258validate_immediate (val) 2259 unsigned int val; 2260{ 2261 unsigned int a; 2262 unsigned int i; 2263 2264#define rotate_left(v, n) (v << n | v >> (32 - n)) 2265 2266 for (i = 0; i < 32; i += 2) 2267 if ((a = rotate_left (val, i)) <= 0xff) 2268 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */ 2269 2270 return FAIL; 2271} 2272 2273/* Check to see if an immediate can be computed as two seperate immediate 2274 values, added together. We already know that this value cannot be 2275 computed by just one ARM instruction. */ 2276 2277static unsigned int 2278validate_immediate_twopart (val, highpart) 2279 unsigned int val; 2280 unsigned int * highpart; 2281{ 2282 unsigned int a; 2283 unsigned int i; 2284 2285 for (i = 0; i < 32; i += 2) 2286 if (((a = rotate_left (val, i)) & 0xff) != 0) 2287 { 2288 if (a & 0xff00) 2289 { 2290 if (a & ~ 0xffff) 2291 continue; 2292 * highpart = (a >> 8) | ((i + 24) << 7); 2293 } 2294 else if (a & 0xff0000) 2295 { 2296 if (a & 0xff000000) 2297 continue; 2298 * highpart = (a >> 16) | ((i + 16) << 7); 2299 } 2300 else 2301 { 2302 assert (a & 0xff000000); 2303 * highpart = (a >> 24) | ((i + 8) << 7); 2304 } 2305 2306 return (a & 0xff) | (i << 7); 2307 } 2308 2309 return FAIL; 2310} 2311 2312static int 2313validate_offset_imm (val, hwse) 2314 unsigned int val; 2315 int hwse; 2316{ 2317 if ((hwse && val > 255) || val > 4095) 2318 return FAIL; 2319 return val; 2320} 2321 2322static void 2323s_req (a) 2324 int a ATTRIBUTE_UNUSED; 2325{ 2326 as_bad (_("invalid syntax for .req directive")); 2327} 2328 2329static void 2330s_bss (ignore) 2331 int ignore ATTRIBUTE_UNUSED; 2332{ 2333 /* We don't support putting frags in the BSS segment, we fake it by 2334 marking in_bss, then looking at s_skip for clues. */ 2335 subseg_set (bss_section, 0); 2336 demand_empty_rest_of_line (); 2337} 2338 2339static void 2340s_even (ignore) 2341 int ignore ATTRIBUTE_UNUSED; 2342{ 2343 /* Never make frag if expect extra pass. */ 2344 if (!need_pass_2) 2345 frag_align (1, 0, 0); 2346 2347 record_alignment (now_seg, 1); 2348 2349 demand_empty_rest_of_line (); 2350} 2351 2352static void 2353s_ltorg (ignored) 2354 int ignored ATTRIBUTE_UNUSED; 2355{ 2356 int lit_count = 0; 2357 char sym_name[20]; 2358 2359 if (current_poolP == NULL) 2360 return; 2361 2362 /* Align pool as you have word accesses. 2363 Only make a frag if we have to. */ 2364 if (!need_pass_2) 2365 frag_align (2, 0, 0); 2366 2367 record_alignment (now_seg, 2); 2368 2369 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++); 2370 2371 symbol_locate (current_poolP, sym_name, now_seg, 2372 (valueT) frag_now_fix (), frag_now); 2373 symbol_table_insert (current_poolP); 2374 2375 ARM_SET_THUMB (current_poolP, thumb_mode); 2376 2377#if defined OBJ_COFF || defined OBJ_ELF 2378 ARM_SET_INTERWORK (current_poolP, support_interwork); 2379#endif 2380 2381 while (lit_count < next_literal_pool_place) 2382 /* First output the expression in the instruction to the pool. */ 2383 emit_expr (&(literals[lit_count++].exp), 4); /* .word */ 2384 2385 next_literal_pool_place = 0; 2386 current_poolP = NULL; 2387} 2388 2389/* Same as s_align_ptwo but align 0 => align 2. */ 2390 2391static void 2392s_align (unused) 2393 int unused ATTRIBUTE_UNUSED; 2394{ 2395 register int temp; 2396 register long temp_fill; 2397 long max_alignment = 15; 2398 2399 temp = get_absolute_expression (); 2400 if (temp > max_alignment) 2401 as_bad (_("alignment too large: %d assumed"), temp = max_alignment); 2402 else if (temp < 0) 2403 { 2404 as_bad (_("alignment negative. 0 assumed.")); 2405 temp = 0; 2406 } 2407 2408 if (*input_line_pointer == ',') 2409 { 2410 input_line_pointer++; 2411 temp_fill = get_absolute_expression (); 2412 } 2413 else 2414 temp_fill = 0; 2415 2416 if (!temp) 2417 temp = 2; 2418 2419 /* Only make a frag if we HAVE to. */ 2420 if (temp && !need_pass_2) 2421 frag_align (temp, (int) temp_fill, 0); 2422 demand_empty_rest_of_line (); 2423 2424 record_alignment (now_seg, temp); 2425} 2426 2427static void 2428s_force_thumb (ignore) 2429 int ignore ATTRIBUTE_UNUSED; 2430{ 2431 /* If we are not already in thumb mode go into it, EVEN if 2432 the target processor does not support thumb instructions. 2433 This is used by gcc/config/arm/lib1funcs.asm for example 2434 to compile interworking support functions even if the 2435 target processor should not support interworking. */ 2436 if (! thumb_mode) 2437 { 2438 thumb_mode = 2; 2439 2440 record_alignment (now_seg, 1); 2441 } 2442 2443 demand_empty_rest_of_line (); 2444} 2445 2446static void 2447s_thumb_func (ignore) 2448 int ignore ATTRIBUTE_UNUSED; 2449{ 2450 if (! thumb_mode) 2451 opcode_select (16); 2452 2453 /* The following label is the name/address of the start of a Thumb function. 2454 We need to know this for the interworking support. */ 2455 label_is_thumb_function_name = true; 2456 2457 demand_empty_rest_of_line (); 2458} 2459 2460/* Perform a .set directive, but also mark the alias as 2461 being a thumb function. */ 2462 2463static void 2464s_thumb_set (equiv) 2465 int equiv; 2466{ 2467 /* XXX the following is a duplicate of the code for s_set() in read.c 2468 We cannot just call that code as we need to get at the symbol that 2469 is created. */ 2470 register char * name; 2471 register char delim; 2472 register char * end_name; 2473 register symbolS * symbolP; 2474 2475 /* Especial apologies for the random logic: 2476 This just grew, and could be parsed much more simply! 2477 Dean - in haste. */ 2478 name = input_line_pointer; 2479 delim = get_symbol_end (); 2480 end_name = input_line_pointer; 2481 *end_name = delim; 2482 2483 SKIP_WHITESPACE (); 2484 2485 if (*input_line_pointer != ',') 2486 { 2487 *end_name = 0; 2488 as_bad (_("expected comma after name \"%s\""), name); 2489 *end_name = delim; 2490 ignore_rest_of_line (); 2491 return; 2492 } 2493 2494 input_line_pointer++; 2495 *end_name = 0; 2496 2497 if (name[0] == '.' && name[1] == '\0') 2498 { 2499 /* XXX - this should not happen to .thumb_set. */ 2500 abort (); 2501 } 2502 2503 if ((symbolP = symbol_find (name)) == NULL 2504 && (symbolP = md_undefined_symbol (name)) == NULL) 2505 { 2506#ifndef NO_LISTING 2507 /* When doing symbol listings, play games with dummy fragments living 2508 outside the normal fragment chain to record the file and line info 2509 for this symbol. */ 2510 if (listing & LISTING_SYMBOLS) 2511 { 2512 extern struct list_info_struct * listing_tail; 2513 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS)); 2514 2515 memset (dummy_frag, 0, sizeof (fragS)); 2516 dummy_frag->fr_type = rs_fill; 2517 dummy_frag->line = listing_tail; 2518 symbolP = symbol_new (name, undefined_section, 0, dummy_frag); 2519 dummy_frag->fr_symbol = symbolP; 2520 } 2521 else 2522#endif 2523 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); 2524 2525#ifdef OBJ_COFF 2526 /* "set" symbols are local unless otherwise specified. */ 2527 SF_SET_LOCAL (symbolP); 2528#endif /* OBJ_COFF */ 2529 } /* Make a new symbol. */ 2530 2531 symbol_table_insert (symbolP); 2532 2533 * end_name = delim; 2534 2535 if (equiv 2536 && S_IS_DEFINED (symbolP) 2537 && S_GET_SEGMENT (symbolP) != reg_section) 2538 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); 2539 2540 pseudo_set (symbolP); 2541 2542 demand_empty_rest_of_line (); 2543 2544 /* XXX Now we come to the Thumb specific bit of code. */ 2545 2546 THUMB_SET_FUNC (symbolP, 1); 2547 ARM_SET_THUMB (symbolP, 1); 2548#if defined OBJ_ELF || defined OBJ_COFF 2549 ARM_SET_INTERWORK (symbolP, support_interwork); 2550#endif 2551} 2552 2553/* If we change section we must dump the literal pool first. */ 2554 2555static void 2556arm_s_text (ignore) 2557 int ignore; 2558{ 2559 if (now_seg != text_section) 2560 s_ltorg (0); 2561 2562#ifdef OBJ_ELF 2563 obj_elf_text (ignore); 2564#else 2565 s_text (ignore); 2566#endif 2567} 2568 2569static void 2570arm_s_data (ignore) 2571 int ignore; 2572{ 2573 if (flag_readonly_data_in_text) 2574 { 2575 if (now_seg != text_section) 2576 s_ltorg (0); 2577 } 2578 else if (now_seg != data_section) 2579 s_ltorg (0); 2580 2581#ifdef OBJ_ELF 2582 obj_elf_data (ignore); 2583#else 2584 s_data (ignore); 2585#endif 2586} 2587 2588#ifdef OBJ_ELF 2589static void 2590arm_s_section (ignore) 2591 int ignore; 2592{ 2593 s_ltorg (0); 2594 2595 obj_elf_section (ignore); 2596} 2597#endif 2598 2599static void 2600opcode_select (width) 2601 int width; 2602{ 2603 switch (width) 2604 { 2605 case 16: 2606 if (! thumb_mode) 2607 { 2608 if (! (cpu_variant & ARM_EXT_V4T)) 2609 as_bad (_("selected processor does not support THUMB opcodes")); 2610 2611 thumb_mode = 1; 2612 /* No need to force the alignment, since we will have been 2613 coming from ARM mode, which is word-aligned. */ 2614 record_alignment (now_seg, 1); 2615 } 2616 break; 2617 2618 case 32: 2619 if (thumb_mode) 2620 { 2621 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T) 2622 as_bad (_("selected processor does not support ARM opcodes")); 2623 2624 thumb_mode = 0; 2625 2626 if (!need_pass_2) 2627 frag_align (2, 0, 0); 2628 2629 record_alignment (now_seg, 1); 2630 } 2631 break; 2632 2633 default: 2634 as_bad (_("invalid instruction size selected (%d)"), width); 2635 } 2636} 2637 2638static void 2639s_arm (ignore) 2640 int ignore ATTRIBUTE_UNUSED; 2641{ 2642 opcode_select (32); 2643 demand_empty_rest_of_line (); 2644} 2645 2646static void 2647s_thumb (ignore) 2648 int ignore ATTRIBUTE_UNUSED; 2649{ 2650 opcode_select (16); 2651 demand_empty_rest_of_line (); 2652} 2653 2654static void 2655s_code (unused) 2656 int unused ATTRIBUTE_UNUSED; 2657{ 2658 register int temp; 2659 2660 temp = get_absolute_expression (); 2661 switch (temp) 2662 { 2663 case 16: 2664 case 32: 2665 opcode_select (temp); 2666 break; 2667 2668 default: 2669 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp); 2670 } 2671} 2672 2673static void 2674end_of_line (str) 2675 char *str; 2676{ 2677 skip_whitespace (str); 2678 2679 if (*str != '\0' && !inst.error) 2680 inst.error = _("garbage following instruction"); 2681} 2682 2683static int 2684skip_past_comma (str) 2685 char ** str; 2686{ 2687 char * p = * str, c; 2688 int comma = 0; 2689 2690 while ((c = *p) == ' ' || c == ',') 2691 { 2692 p++; 2693 if (c == ',' && comma++) 2694 return FAIL; 2695 } 2696 2697 if (c == '\0') 2698 return FAIL; 2699 2700 *str = p; 2701 return comma ? SUCCESS : FAIL; 2702} 2703 2704/* A standard register must be given at this point. 2705 SHIFT is the place to put it in inst.instruction. 2706 Restores input start point on error. 2707 Returns the reg#, or FAIL. */ 2708 2709static int 2710reg_required_here (str, shift) 2711 char ** str; 2712 int shift; 2713{ 2714 static char buff [128]; /* XXX */ 2715 int reg; 2716 char * start = * str; 2717 2718 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL) 2719 { 2720 if (shift >= 0) 2721 inst.instruction |= reg << shift; 2722 return reg; 2723 } 2724 2725 /* Restore the start point, we may have got a reg of the wrong class. */ 2726 *str = start; 2727 2728 /* In the few cases where we might be able to accept something else 2729 this error can be overridden. */ 2730 sprintf (buff, _("register expected, not '%.100s'"), start); 2731 inst.error = buff; 2732 2733 return FAIL; 2734} 2735 2736static const struct asm_psr * 2737arm_psr_parse (ccp) 2738 register char ** ccp; 2739{ 2740 char * start = * ccp; 2741 char c; 2742 char * p; 2743 const struct asm_psr * psr; 2744 2745 p = start; 2746 2747 /* Skip to the end of the next word in the input stream. */ 2748 do 2749 { 2750 c = *p++; 2751 } 2752 while (ISALPHA (c) || c == '_'); 2753 2754 /* Terminate the word. */ 2755 *--p = 0; 2756 2757 /* CPSR's and SPSR's can now be lowercase. This is just a convenience 2758 feature for ease of use and backwards compatibility. */ 2759 if (!strncmp (start, "cpsr", 4)) 2760 strncpy (start, "CPSR", 4); 2761 else if (!strncmp (start, "spsr", 4)) 2762 strncpy (start, "SPSR", 4); 2763 2764 /* Now locate the word in the psr hash table. */ 2765 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start); 2766 2767 /* Restore the input stream. */ 2768 *p = c; 2769 2770 /* If we found a valid match, advance the 2771 stream pointer past the end of the word. */ 2772 *ccp = p; 2773 2774 return psr; 2775} 2776 2777/* Parse the input looking for a PSR flag. */ 2778 2779static int 2780psr_required_here (str) 2781 char ** str; 2782{ 2783 char * start = * str; 2784 const struct asm_psr * psr; 2785 2786 psr = arm_psr_parse (str); 2787 2788 if (psr) 2789 { 2790 /* If this is the SPSR that is being modified, set the R bit. */ 2791 if (! psr->cpsr) 2792 inst.instruction |= SPSR_BIT; 2793 2794 /* Set the psr flags in the MSR instruction. */ 2795 inst.instruction |= psr->field << PSR_SHIFT; 2796 2797 return SUCCESS; 2798 } 2799 2800 /* In the few cases where we might be able to accept 2801 something else this error can be overridden. */ 2802 inst.error = _("flag for {c}psr instruction expected"); 2803 2804 /* Restore the start point. */ 2805 *str = start; 2806 return FAIL; 2807} 2808 2809static int 2810co_proc_number (str) 2811 char **str; 2812{ 2813 int processor, pchar; 2814 char *start; 2815 2816 skip_whitespace (*str); 2817 start = *str; 2818 2819 /* The data sheet seems to imply that just a number on its own is valid 2820 here, but the RISC iX assembler seems to accept a prefix 'p'. We will 2821 accept either. */ 2822 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab)) 2823 == FAIL) 2824 { 2825 *str = start; 2826 2827 pchar = *(*str)++; 2828 if (pchar >= '0' && pchar <= '9') 2829 { 2830 processor = pchar - '0'; 2831 if (**str >= '0' && **str <= '9') 2832 { 2833 processor = processor * 10 + *(*str)++ - '0'; 2834 if (processor > 15) 2835 { 2836 inst.error = _("illegal co-processor number"); 2837 return FAIL; 2838 } 2839 } 2840 } 2841 else 2842 { 2843 inst.error = _("bad or missing co-processor number"); 2844 return FAIL; 2845 } 2846 } 2847 2848 inst.instruction |= processor << 8; 2849 return SUCCESS; 2850} 2851 2852static int 2853cp_opc_expr (str, where, length) 2854 char ** str; 2855 int where; 2856 int length; 2857{ 2858 expressionS expr; 2859 2860 skip_whitespace (* str); 2861 2862 memset (&expr, '\0', sizeof (expr)); 2863 2864 if (my_get_expression (&expr, str)) 2865 return FAIL; 2866 if (expr.X_op != O_constant) 2867 { 2868 inst.error = _("bad or missing expression"); 2869 return FAIL; 2870 } 2871 2872 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number) 2873 { 2874 inst.error = _("immediate co-processor expression too large"); 2875 return FAIL; 2876 } 2877 2878 inst.instruction |= expr.X_add_number << where; 2879 return SUCCESS; 2880} 2881 2882static int 2883cp_reg_required_here (str, where) 2884 char ** str; 2885 int where; 2886{ 2887 int reg; 2888 char * start = *str; 2889 2890 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL) 2891 { 2892 inst.instruction |= reg << where; 2893 return reg; 2894 } 2895 2896 /* In the few cases where we might be able to accept something else 2897 this error can be overridden. */ 2898 inst.error = _("co-processor register expected"); 2899 2900 /* Restore the start point. */ 2901 *str = start; 2902 return FAIL; 2903} 2904 2905static int 2906fp_reg_required_here (str, where) 2907 char ** str; 2908 int where; 2909{ 2910 int reg; 2911 char * start = * str; 2912 2913 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL) 2914 { 2915 inst.instruction |= reg << where; 2916 return reg; 2917 } 2918 2919 /* In the few cases where we might be able to accept something else 2920 this error can be overridden. */ 2921 inst.error = _("floating point register expected"); 2922 2923 /* Restore the start point. */ 2924 *str = start; 2925 return FAIL; 2926} 2927 2928static int 2929cp_address_offset (str) 2930 char ** str; 2931{ 2932 int offset; 2933 2934 skip_whitespace (* str); 2935 2936 if (! is_immediate_prefix (**str)) 2937 { 2938 inst.error = _("immediate expression expected"); 2939 return FAIL; 2940 } 2941 2942 (*str)++; 2943 2944 if (my_get_expression (& inst.reloc.exp, str)) 2945 return FAIL; 2946 2947 if (inst.reloc.exp.X_op == O_constant) 2948 { 2949 offset = inst.reloc.exp.X_add_number; 2950 2951 if (offset & 3) 2952 { 2953 inst.error = _("co-processor address must be word aligned"); 2954 return FAIL; 2955 } 2956 2957 if (offset > 1023 || offset < -1023) 2958 { 2959 inst.error = _("offset too large"); 2960 return FAIL; 2961 } 2962 2963 if (offset >= 0) 2964 inst.instruction |= INDEX_UP; 2965 else 2966 offset = -offset; 2967 2968 inst.instruction |= offset >> 2; 2969 } 2970 else 2971 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; 2972 2973 return SUCCESS; 2974} 2975 2976static int 2977cp_address_required_here (str, wb_ok) 2978 char ** str; 2979 int wb_ok; 2980{ 2981 char * p = * str; 2982 int pre_inc = 0; 2983 int write_back = 0; 2984 2985 if (*p == '[') 2986 { 2987 int reg; 2988 2989 p++; 2990 skip_whitespace (p); 2991 2992 if ((reg = reg_required_here (& p, 16)) == FAIL) 2993 return FAIL; 2994 2995 skip_whitespace (p); 2996 2997 if (*p == ']') 2998 { 2999 p++; 3000 3001 if (wb_ok && skip_past_comma (& p) == SUCCESS) 3002 { 3003 /* [Rn], #expr */ 3004 write_back = WRITE_BACK; 3005 3006 if (reg == REG_PC) 3007 { 3008 inst.error = _("pc may not be used in post-increment"); 3009 return FAIL; 3010 } 3011 3012 if (cp_address_offset (& p) == FAIL) 3013 return FAIL; 3014 } 3015 else 3016 pre_inc = PRE_INDEX | INDEX_UP; 3017 } 3018 else 3019 { 3020 /* '['Rn, #expr']'[!] */ 3021 3022 if (skip_past_comma (& p) == FAIL) 3023 { 3024 inst.error = _("pre-indexed expression expected"); 3025 return FAIL; 3026 } 3027 3028 pre_inc = PRE_INDEX; 3029 3030 if (cp_address_offset (& p) == FAIL) 3031 return FAIL; 3032 3033 skip_whitespace (p); 3034 3035 if (*p++ != ']') 3036 { 3037 inst.error = _("missing ]"); 3038 return FAIL; 3039 } 3040 3041 skip_whitespace (p); 3042 3043 if (wb_ok && *p == '!') 3044 { 3045 if (reg == REG_PC) 3046 { 3047 inst.error = _("pc may not be used with write-back"); 3048 return FAIL; 3049 } 3050 3051 p++; 3052 write_back = WRITE_BACK; 3053 } 3054 } 3055 } 3056 else 3057 { 3058 if (my_get_expression (&inst.reloc.exp, &p)) 3059 return FAIL; 3060 3061 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; 3062 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */ 3063 inst.reloc.pc_rel = 1; 3064 inst.instruction |= (REG_PC << 16); 3065 pre_inc = PRE_INDEX; 3066 } 3067 3068 inst.instruction |= write_back | pre_inc; 3069 *str = p; 3070 return SUCCESS; 3071} 3072 3073static void 3074do_empty (str) 3075 char * str; 3076{ 3077 /* Do nothing really. */ 3078 end_of_line (str); 3079 return; 3080} 3081 3082static void 3083do_mrs (str) 3084 char *str; 3085{ 3086 int skip = 0; 3087 3088 /* Only one syntax. */ 3089 skip_whitespace (str); 3090 3091 if (reg_required_here (&str, 12) == FAIL) 3092 { 3093 inst.error = BAD_ARGS; 3094 return; 3095 } 3096 3097 if (skip_past_comma (&str) == FAIL) 3098 { 3099 inst.error = _("comma expected after register name"); 3100 return; 3101 } 3102 3103 skip_whitespace (str); 3104 3105 if ( strcmp (str, "CPSR") == 0 3106 || strcmp (str, "SPSR") == 0 3107 /* Lower case versions for backwards compatability. */ 3108 || strcmp (str, "cpsr") == 0 3109 || strcmp (str, "spsr") == 0) 3110 skip = 4; 3111 3112 /* This is for backwards compatability with older toolchains. */ 3113 else if ( strcmp (str, "cpsr_all") == 0 3114 || strcmp (str, "spsr_all") == 0) 3115 skip = 8; 3116 else 3117 { 3118 inst.error = _("CPSR or SPSR expected"); 3119 return; 3120 } 3121 3122 if (* str == 's' || * str == 'S') 3123 inst.instruction |= SPSR_BIT; 3124 str += skip; 3125 3126 end_of_line (str); 3127} 3128 3129/* Two possible forms: 3130 "{C|S}PSR_<field>, Rm", 3131 "{C|S}PSR_f, #expression". */ 3132 3133static void 3134do_msr (str) 3135 char * str; 3136{ 3137 skip_whitespace (str); 3138 3139 if (psr_required_here (& str) == FAIL) 3140 return; 3141 3142 if (skip_past_comma (& str) == FAIL) 3143 { 3144 inst.error = _("comma missing after psr flags"); 3145 return; 3146 } 3147 3148 skip_whitespace (str); 3149 3150 if (reg_required_here (& str, 0) != FAIL) 3151 { 3152 inst.error = NULL; 3153 end_of_line (str); 3154 return; 3155 } 3156 3157 if (! is_immediate_prefix (* str)) 3158 { 3159 inst.error = 3160 _("only a register or immediate value can follow a psr flag"); 3161 return; 3162 } 3163 3164 str ++; 3165 inst.error = NULL; 3166 3167 if (my_get_expression (& inst.reloc.exp, & str)) 3168 { 3169 inst.error = 3170 _("only a register or immediate value can follow a psr flag"); 3171 return; 3172 } 3173 3174#if 0 /* The first edition of the ARM architecture manual stated that 3175 writing anything other than the flags with an immediate operation 3176 had UNPREDICTABLE effects. This constraint was removed in the 3177 second edition of the specification. */ 3178 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5 3179 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT)) 3180 { 3181 inst.error = _("immediate value cannot be used to set this field"); 3182 return; 3183 } 3184#endif 3185 3186 inst.instruction |= INST_IMMEDIATE; 3187 3188 if (inst.reloc.exp.X_add_symbol) 3189 { 3190 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; 3191 inst.reloc.pc_rel = 0; 3192 } 3193 else 3194 { 3195 unsigned value = validate_immediate (inst.reloc.exp.X_add_number); 3196 3197 if (value == (unsigned) FAIL) 3198 { 3199 inst.error = _("invalid constant"); 3200 return; 3201 } 3202 3203 inst.instruction |= value; 3204 } 3205 3206 inst.error = NULL; 3207 end_of_line (str); 3208} 3209 3210/* Long Multiply Parser 3211 UMULL RdLo, RdHi, Rm, Rs 3212 SMULL RdLo, RdHi, Rm, Rs 3213 UMLAL RdLo, RdHi, Rm, Rs 3214 SMLAL RdLo, RdHi, Rm, Rs. */ 3215 3216static void 3217do_mull (str) 3218 char * str; 3219{ 3220 int rdlo, rdhi, rm, rs; 3221 3222 /* Only one format "rdlo, rdhi, rm, rs". */ 3223 skip_whitespace (str); 3224 3225 if ((rdlo = reg_required_here (&str, 12)) == FAIL) 3226 { 3227 inst.error = BAD_ARGS; 3228 return; 3229 } 3230 3231 if (skip_past_comma (&str) == FAIL 3232 || (rdhi = reg_required_here (&str, 16)) == FAIL) 3233 { 3234 inst.error = BAD_ARGS; 3235 return; 3236 } 3237 3238 if (skip_past_comma (&str) == FAIL 3239 || (rm = reg_required_here (&str, 0)) == FAIL) 3240 { 3241 inst.error = BAD_ARGS; 3242 return; 3243 } 3244 3245 /* rdhi, rdlo and rm must all be different. */ 3246 if (rdlo == rdhi || rdlo == rm || rdhi == rm) 3247 as_tsktsk (_("rdhi, rdlo and rm must all be different")); 3248 3249 if (skip_past_comma (&str) == FAIL 3250 || (rs = reg_required_here (&str, 8)) == FAIL) 3251 { 3252 inst.error = BAD_ARGS; 3253 return; 3254 } 3255 3256 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC) 3257 { 3258 inst.error = BAD_PC; 3259 return; 3260 } 3261 3262 end_of_line (str); 3263 return; 3264} 3265 3266static void 3267do_mul (str) 3268 char * str; 3269{ 3270 int rd, rm; 3271 3272 /* Only one format "rd, rm, rs". */ 3273 skip_whitespace (str); 3274 3275 if ((rd = reg_required_here (&str, 16)) == FAIL) 3276 { 3277 inst.error = BAD_ARGS; 3278 return; 3279 } 3280 3281 if (rd == REG_PC) 3282 { 3283 inst.error = BAD_PC; 3284 return; 3285 } 3286 3287 if (skip_past_comma (&str) == FAIL 3288 || (rm = reg_required_here (&str, 0)) == FAIL) 3289 { 3290 inst.error = BAD_ARGS; 3291 return; 3292 } 3293 3294 if (rm == REG_PC) 3295 { 3296 inst.error = BAD_PC; 3297 return; 3298 } 3299 3300 if (rm == rd) 3301 as_tsktsk (_("rd and rm should be different in mul")); 3302 3303 if (skip_past_comma (&str) == FAIL 3304 || (rm = reg_required_here (&str, 8)) == FAIL) 3305 { 3306 inst.error = BAD_ARGS; 3307 return; 3308 } 3309 3310 if (rm == REG_PC) 3311 { 3312 inst.error = BAD_PC; 3313 return; 3314 } 3315 3316 end_of_line (str); 3317 return; 3318} 3319 3320static void 3321do_mla (str) 3322 char * str; 3323{ 3324 int rd, rm; 3325 3326 /* Only one format "rd, rm, rs, rn". */ 3327 skip_whitespace (str); 3328 3329 if ((rd = reg_required_here (&str, 16)) == FAIL) 3330 { 3331 inst.error = BAD_ARGS; 3332 return; 3333 } 3334 3335 if (rd == REG_PC) 3336 { 3337 inst.error = BAD_PC; 3338 return; 3339 } 3340 3341 if (skip_past_comma (&str) == FAIL 3342 || (rm = reg_required_here (&str, 0)) == FAIL) 3343 { 3344 inst.error = BAD_ARGS; 3345 return; 3346 } 3347 3348 if (rm == REG_PC) 3349 { 3350 inst.error = BAD_PC; 3351 return; 3352 } 3353 3354 if (rm == rd) 3355 as_tsktsk (_("rd and rm should be different in mla")); 3356 3357 if (skip_past_comma (&str) == FAIL 3358 || (rd = reg_required_here (&str, 8)) == FAIL 3359 || skip_past_comma (&str) == FAIL 3360 || (rm = reg_required_here (&str, 12)) == FAIL) 3361 { 3362 inst.error = BAD_ARGS; 3363 return; 3364 } 3365 3366 if (rd == REG_PC || rm == REG_PC) 3367 { 3368 inst.error = BAD_PC; 3369 return; 3370 } 3371 3372 end_of_line (str); 3373 return; 3374} 3375 3376/* Expects *str -> the characters "acc0", possibly with leading blanks. 3377 Advances *str to the next non-alphanumeric. 3378 Returns 0, or else FAIL (in which case sets inst.error). 3379 3380 (In a future XScale, there may be accumulators other than zero. 3381 At that time this routine and its callers can be upgraded to suit.) */ 3382 3383static int 3384accum0_required_here (str) 3385 char ** str; 3386{ 3387 static char buff [128]; /* Note the address is taken. Hence, static. */ 3388 char * p = * str; 3389 char c; 3390 int result = 0; /* The accum number. */ 3391 3392 skip_whitespace (p); 3393 3394 *str = p; /* Advance caller's string pointer too. */ 3395 c = *p++; 3396 while (ISALNUM (c)) 3397 c = *p++; 3398 3399 *--p = 0; /* Aap nul into input buffer at non-alnum. */ 3400 3401 if (! ( streq (*str, "acc0") || streq (*str, "ACC0"))) 3402 { 3403 sprintf (buff, _("acc0 expected, not '%.100s'"), *str); 3404 inst.error = buff; 3405 result = FAIL; 3406 } 3407 3408 *p = c; /* Unzap. */ 3409 *str = p; /* Caller's string pointer to after match. */ 3410 return result; 3411} 3412 3413/* Expects **str -> after a comma. May be leading blanks. 3414 Advances *str, recognizing a load mode, and setting inst.instruction. 3415 Returns rn, or else FAIL (in which case may set inst.error 3416 and not advance str) 3417 3418 Note: doesn't know Rd, so no err checks that require such knowledge. */ 3419 3420static int 3421ld_mode_required_here (string) 3422 char ** string; 3423{ 3424 char * str = * string; 3425 int rn; 3426 int pre_inc = 0; 3427 3428 skip_whitespace (str); 3429 3430 if (* str == '[') 3431 { 3432 str++; 3433 3434 skip_whitespace (str); 3435 3436 if ((rn = reg_required_here (& str, 16)) == FAIL) 3437 return FAIL; 3438 3439 skip_whitespace (str); 3440 3441 if (* str == ']') 3442 { 3443 str ++; 3444 3445 if (skip_past_comma (& str) == SUCCESS) 3446 { 3447 /* [Rn],... (post inc) */ 3448 if (ldst_extend_v4 (&str) == FAIL) 3449 return FAIL; 3450 } 3451 else /* [Rn] */ 3452 { 3453 skip_whitespace (str); 3454 3455 if (* str == '!') 3456 { 3457 str ++; 3458 inst.instruction |= WRITE_BACK; 3459 } 3460 3461 inst.instruction |= INDEX_UP | HWOFFSET_IMM; 3462 pre_inc = 1; 3463 } 3464 } 3465 else /* [Rn,...] */ 3466 { 3467 if (skip_past_comma (& str) == FAIL) 3468 { 3469 inst.error = _("pre-indexed expression expected"); 3470 return FAIL; 3471 } 3472 3473 pre_inc = 1; 3474 3475 if (ldst_extend_v4 (&str) == FAIL) 3476 return FAIL; 3477 3478 skip_whitespace (str); 3479 3480 if (* str ++ != ']') 3481 { 3482 inst.error = _("missing ]"); 3483 return FAIL; 3484 } 3485 3486 skip_whitespace (str); 3487 3488 if (* str == '!') 3489 { 3490 str ++; 3491 inst.instruction |= WRITE_BACK; 3492 } 3493 } 3494 } 3495 else if (* str == '=') /* ldr's "r,=label" syntax */ 3496 /* We should never reach here, because <text> = <expression> is 3497 caught gas/read.c read_a_source_file() as a .set operation. */ 3498 return FAIL; 3499 else /* PC +- 8 bit immediate offset. */ 3500 { 3501 if (my_get_expression (& inst.reloc.exp, & str)) 3502 return FAIL; 3503 3504 inst.instruction |= HWOFFSET_IMM; /* The I bit. */ 3505 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8; 3506 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */ 3507 inst.reloc.pc_rel = 1; 3508 inst.instruction |= (REG_PC << 16); 3509 3510 rn = REG_PC; 3511 pre_inc = 1; 3512 } 3513 3514 inst.instruction |= (pre_inc ? PRE_INDEX : 0); 3515 * string = str; 3516 3517 return rn; 3518} 3519 3520/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse) 3521 SMLAxy{cond} Rd,Rm,Rs,Rn 3522 SMLAWy{cond} Rd,Rm,Rs,Rn 3523 Error if any register is R15. */ 3524 3525static void 3526do_smla (str) 3527 char * str; 3528{ 3529 int rd, rm, rs, rn; 3530 3531 skip_whitespace (str); 3532 3533 if ((rd = reg_required_here (& str, 16)) == FAIL 3534 || skip_past_comma (& str) == FAIL 3535 || (rm = reg_required_here (& str, 0)) == FAIL 3536 || skip_past_comma (& str) == FAIL 3537 || (rs = reg_required_here (& str, 8)) == FAIL 3538 || skip_past_comma (& str) == FAIL 3539 || (rn = reg_required_here (& str, 12)) == FAIL) 3540 inst.error = BAD_ARGS; 3541 3542 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC) 3543 inst.error = BAD_PC; 3544 3545 else 3546 end_of_line (str); 3547} 3548 3549/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse) 3550 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs 3551 Error if any register is R15. 3552 Warning if Rdlo == Rdhi. */ 3553 3554static void 3555do_smlal (str) 3556 char * str; 3557{ 3558 int rdlo, rdhi, rm, rs; 3559 3560 skip_whitespace (str); 3561 3562 if ((rdlo = reg_required_here (& str, 12)) == FAIL 3563 || skip_past_comma (& str) == FAIL 3564 || (rdhi = reg_required_here (& str, 16)) == FAIL 3565 || skip_past_comma (& str) == FAIL 3566 || (rm = reg_required_here (& str, 0)) == FAIL 3567 || skip_past_comma (& str) == FAIL 3568 || (rs = reg_required_here (& str, 8)) == FAIL) 3569 { 3570 inst.error = BAD_ARGS; 3571 return; 3572 } 3573 3574 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC) 3575 { 3576 inst.error = BAD_PC; 3577 return; 3578 } 3579 3580 if (rdlo == rdhi) 3581 as_tsktsk (_("rdhi and rdlo must be different")); 3582 3583 end_of_line (str); 3584} 3585 3586/* ARM V5E (El Segundo) signed-multiply (argument parse) 3587 SMULxy{cond} Rd,Rm,Rs 3588 Error if any register is R15. */ 3589 3590static void 3591do_smul (str) 3592 char * str; 3593{ 3594 int rd, rm, rs; 3595 3596 skip_whitespace (str); 3597 3598 if ((rd = reg_required_here (& str, 16)) == FAIL 3599 || skip_past_comma (& str) == FAIL 3600 || (rm = reg_required_here (& str, 0)) == FAIL 3601 || skip_past_comma (& str) == FAIL 3602 || (rs = reg_required_here (& str, 8)) == FAIL) 3603 inst.error = BAD_ARGS; 3604 3605 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC) 3606 inst.error = BAD_PC; 3607 3608 else 3609 end_of_line (str); 3610} 3611 3612/* ARM V5E (El Segundo) saturating-add/subtract (argument parse) 3613 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn 3614 Error if any register is R15. */ 3615 3616static void 3617do_qadd (str) 3618 char * str; 3619{ 3620 int rd, rm, rn; 3621 3622 skip_whitespace (str); 3623 3624 if ((rd = reg_required_here (& str, 12)) == FAIL 3625 || skip_past_comma (& str) == FAIL 3626 || (rm = reg_required_here (& str, 0)) == FAIL 3627 || skip_past_comma (& str) == FAIL 3628 || (rn = reg_required_here (& str, 16)) == FAIL) 3629 inst.error = BAD_ARGS; 3630 3631 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC) 3632 inst.error = BAD_PC; 3633 3634 else 3635 end_of_line (str); 3636} 3637 3638/* ARM V5E (el Segundo) 3639 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>. 3640 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>. 3641 3642 These are equivalent to the XScale instructions MAR and MRA, 3643 respectively, when coproc == 0, opcode == 0, and CRm == 0. 3644 3645 Result unpredicatable if Rd or Rn is R15. */ 3646 3647static void 3648do_co_reg2c (str) 3649 char * str; 3650{ 3651 int rd, rn; 3652 3653 skip_whitespace (str); 3654 3655 if (co_proc_number (& str) == FAIL) 3656 { 3657 if (!inst.error) 3658 inst.error = BAD_ARGS; 3659 return; 3660 } 3661 3662 if (skip_past_comma (& str) == FAIL 3663 || cp_opc_expr (& str, 4, 4) == FAIL) 3664 { 3665 if (!inst.error) 3666 inst.error = BAD_ARGS; 3667 return; 3668 } 3669 3670 if (skip_past_comma (& str) == FAIL 3671 || (rd = reg_required_here (& str, 12)) == FAIL) 3672 { 3673 if (!inst.error) 3674 inst.error = BAD_ARGS; 3675 return; 3676 } 3677 3678 if (skip_past_comma (& str) == FAIL 3679 || (rn = reg_required_here (& str, 16)) == FAIL) 3680 { 3681 if (!inst.error) 3682 inst.error = BAD_ARGS; 3683 return; 3684 } 3685 3686 /* Unpredictable result if rd or rn is R15. */ 3687 if (rd == REG_PC || rn == REG_PC) 3688 as_tsktsk 3689 (_("Warning: instruction unpredictable when using r15")); 3690 3691 if (skip_past_comma (& str) == FAIL 3692 || cp_reg_required_here (& str, 0) == FAIL) 3693 { 3694 if (!inst.error) 3695 inst.error = BAD_ARGS; 3696 return; 3697 } 3698 3699 end_of_line (str); 3700} 3701 3702/* ARM V5 count-leading-zeroes instruction (argument parse) 3703 CLZ{<cond>} <Rd>, <Rm> 3704 Condition defaults to COND_ALWAYS. 3705 Error if Rd or Rm are R15. */ 3706 3707static void 3708do_clz (str) 3709 char * str; 3710{ 3711 int rd, rm; 3712 3713 skip_whitespace (str); 3714 3715 if (((rd = reg_required_here (& str, 12)) == FAIL) 3716 || (skip_past_comma (& str) == FAIL) 3717 || ((rm = reg_required_here (& str, 0)) == FAIL)) 3718 inst.error = BAD_ARGS; 3719 3720 else if (rd == REG_PC || rm == REG_PC ) 3721 inst.error = BAD_PC; 3722 3723 else 3724 end_of_line (str); 3725} 3726 3727/* ARM V5 (argument parse) 3728 LDC2{L} <coproc>, <CRd>, <addressing mode> 3729 STC2{L} <coproc>, <CRd>, <addressing mode> 3730 Instruction is not conditional, and has 0xf in the codition field. 3731 Otherwise, it's the same as LDC/STC. */ 3732 3733static void 3734do_lstc2 (str) 3735 char * str; 3736{ 3737 skip_whitespace (str); 3738 3739 if (co_proc_number (& str) == FAIL) 3740 { 3741 if (!inst.error) 3742 inst.error = BAD_ARGS; 3743 } 3744 else if (skip_past_comma (& str) == FAIL 3745 || cp_reg_required_here (& str, 12) == FAIL) 3746 { 3747 if (!inst.error) 3748 inst.error = BAD_ARGS; 3749 } 3750 else if (skip_past_comma (& str) == FAIL 3751 || cp_address_required_here (&str, CP_WB_OK) == FAIL) 3752 { 3753 if (! inst.error) 3754 inst.error = BAD_ARGS; 3755 } 3756 else 3757 end_of_line (str); 3758} 3759 3760/* ARM V5 (argument parse) 3761 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2> 3762 Instruction is not conditional, and has 0xf in the condition field. 3763 Otherwise, it's the same as CDP. */ 3764 3765static void 3766do_cdp2 (str) 3767 char * str; 3768{ 3769 skip_whitespace (str); 3770 3771 if (co_proc_number (& str) == FAIL) 3772 { 3773 if (!inst.error) 3774 inst.error = BAD_ARGS; 3775 return; 3776 } 3777 3778 if (skip_past_comma (& str) == FAIL 3779 || cp_opc_expr (& str, 20,4) == FAIL) 3780 { 3781 if (!inst.error) 3782 inst.error = BAD_ARGS; 3783 return; 3784 } 3785 3786 if (skip_past_comma (& str) == FAIL 3787 || cp_reg_required_here (& str, 12) == FAIL) 3788 { 3789 if (!inst.error) 3790 inst.error = BAD_ARGS; 3791 return; 3792 } 3793 3794 if (skip_past_comma (& str) == FAIL 3795 || cp_reg_required_here (& str, 16) == FAIL) 3796 { 3797 if (!inst.error) 3798 inst.error = BAD_ARGS; 3799 return; 3800 } 3801 3802 if (skip_past_comma (& str) == FAIL 3803 || cp_reg_required_here (& str, 0) == FAIL) 3804 { 3805 if (!inst.error) 3806 inst.error = BAD_ARGS; 3807 return; 3808 } 3809 3810 if (skip_past_comma (& str) == SUCCESS) 3811 { 3812 if (cp_opc_expr (& str, 5, 3) == FAIL) 3813 { 3814 if (!inst.error) 3815 inst.error = BAD_ARGS; 3816 return; 3817 } 3818 } 3819 3820 end_of_line (str); 3821} 3822 3823/* ARM V5 (argument parse) 3824 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2> 3825 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2> 3826 Instruction is not conditional, and has 0xf in the condition field. 3827 Otherwise, it's the same as MCR/MRC. */ 3828 3829static void 3830do_co_reg2 (str) 3831 char * str; 3832{ 3833 skip_whitespace (str); 3834 3835 if (co_proc_number (& str) == FAIL) 3836 { 3837 if (!inst.error) 3838 inst.error = BAD_ARGS; 3839 return; 3840 } 3841 3842 if (skip_past_comma (& str) == FAIL 3843 || cp_opc_expr (& str, 21, 3) == FAIL) 3844 { 3845 if (!inst.error) 3846 inst.error = BAD_ARGS; 3847 return; 3848 } 3849 3850 if (skip_past_comma (& str) == FAIL 3851 || reg_required_here (& str, 12) == FAIL) 3852 { 3853 if (!inst.error) 3854 inst.error = BAD_ARGS; 3855 return; 3856 } 3857 3858 if (skip_past_comma (& str) == FAIL 3859 || cp_reg_required_here (& str, 16) == FAIL) 3860 { 3861 if (!inst.error) 3862 inst.error = BAD_ARGS; 3863 return; 3864 } 3865 3866 if (skip_past_comma (& str) == FAIL 3867 || cp_reg_required_here (& str, 0) == FAIL) 3868 { 3869 if (!inst.error) 3870 inst.error = BAD_ARGS; 3871 return; 3872 } 3873 3874 if (skip_past_comma (& str) == SUCCESS) 3875 { 3876 if (cp_opc_expr (& str, 5, 3) == FAIL) 3877 { 3878 if (!inst.error) 3879 inst.error = BAD_ARGS; 3880 return; 3881 } 3882 } 3883 3884 end_of_line (str); 3885} 3886 3887/* ARM v5TEJ. Jump to Jazelle code. */ 3888static void 3889do_bxj (str) 3890 char * str; 3891{ 3892 int reg; 3893 3894 skip_whitespace (str); 3895 3896 if ((reg = reg_required_here (&str, 0)) == FAIL) 3897 { 3898 inst.error = BAD_ARGS; 3899 return; 3900 } 3901 3902 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */ 3903 if (reg == REG_PC) 3904 as_tsktsk (_("use of r15 in bxj is not really useful")); 3905 3906 end_of_line (str); 3907} 3908 3909/* THUMB V5 breakpoint instruction (argument parse) 3910 BKPT <immed_8>. */ 3911 3912static void 3913do_t_bkpt (str) 3914 char * str; 3915{ 3916 expressionS expr; 3917 unsigned long number; 3918 3919 skip_whitespace (str); 3920 3921 /* Allow optional leading '#'. */ 3922 if (is_immediate_prefix (*str)) 3923 str ++; 3924 3925 memset (& expr, '\0', sizeof (expr)); 3926 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant)) 3927 { 3928 inst.error = _("bad or missing expression"); 3929 return; 3930 } 3931 3932 number = expr.X_add_number; 3933 3934 /* Check it fits an 8 bit unsigned. */ 3935 if (number != (number & 0xff)) 3936 { 3937 inst.error = _("immediate value out of range"); 3938 return; 3939 } 3940 3941 inst.instruction |= number; 3942 3943 end_of_line (str); 3944} 3945 3946/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only. 3947 Expects inst.instruction is set for BLX(1). 3948 Note: this is cloned from do_branch, and the reloc changed to be a 3949 new one that can cope with setting one extra bit (the H bit). */ 3950 3951static void 3952do_branch25 (str) 3953 char * str; 3954{ 3955 if (my_get_expression (& inst.reloc.exp, & str)) 3956 return; 3957 3958#ifdef OBJ_ELF 3959 { 3960 char * save_in; 3961 3962 /* ScottB: February 5, 1998 */ 3963 /* Check to see of PLT32 reloc required for the instruction. */ 3964 3965 /* arm_parse_reloc() works on input_line_pointer. 3966 We actually want to parse the operands to the branch instruction 3967 passed in 'str'. Save the input pointer and restore it later. */ 3968 save_in = input_line_pointer; 3969 input_line_pointer = str; 3970 3971 if (inst.reloc.exp.X_op == O_symbol 3972 && *str == '(' 3973 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32) 3974 { 3975 inst.reloc.type = BFD_RELOC_ARM_PLT32; 3976 inst.reloc.pc_rel = 0; 3977 /* Modify str to point to after parsed operands, otherwise 3978 end_of_line() will complain about the (PLT) left in str. */ 3979 str = input_line_pointer; 3980 } 3981 else 3982 { 3983 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX; 3984 inst.reloc.pc_rel = 1; 3985 } 3986 3987 input_line_pointer = save_in; 3988 } 3989#else 3990 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX; 3991 inst.reloc.pc_rel = 1; 3992#endif /* OBJ_ELF */ 3993 3994 end_of_line (str); 3995} 3996 3997/* ARM V5 branch-link-exchange instruction (argument parse) 3998 BLX <target_addr> ie BLX(1) 3999 BLX{<condition>} <Rm> ie BLX(2) 4000 Unfortunately, there are two different opcodes for this mnemonic. 4001 So, the insns[].value is not used, and the code here zaps values 4002 into inst.instruction. 4003 Also, the <target_addr> can be 25 bits, hence has its own reloc. */ 4004 4005static void 4006do_blx (str) 4007 char * str; 4008{ 4009 char * mystr = str; 4010 int rm; 4011 4012 skip_whitespace (mystr); 4013 rm = reg_required_here (& mystr, 0); 4014 4015 /* The above may set inst.error. Ignore his opinion. */ 4016 inst.error = 0; 4017 4018 if (rm != FAIL) 4019 { 4020 /* Arg is a register. 4021 Use the condition code our caller put in inst.instruction. 4022 Pass ourselves off as a BX with a funny opcode. */ 4023 inst.instruction |= 0x012fff30; 4024 do_bx (str); 4025 } 4026 else 4027 { 4028 /* This must be is BLX <target address>, no condition allowed. */ 4029 if (inst.instruction != COND_ALWAYS) 4030 { 4031 inst.error = BAD_COND; 4032 return; 4033 } 4034 4035 inst.instruction = 0xfafffffe; 4036 4037 /* Process like a B/BL, but with a different reloc. 4038 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */ 4039 do_branch25 (str); 4040 } 4041} 4042 4043/* ARM V5 Thumb BLX (argument parse) 4044 BLX <target_addr> which is BLX(1) 4045 BLX <Rm> which is BLX(2) 4046 Unfortunately, there are two different opcodes for this mnemonic. 4047 So, the tinsns[].value is not used, and the code here zaps values 4048 into inst.instruction. */ 4049 4050static void 4051do_t_blx (str) 4052 char * str; 4053{ 4054 char * mystr = str; 4055 int rm; 4056 4057 skip_whitespace (mystr); 4058 inst.instruction = 0x4780; 4059 4060 /* Note that this call is to the ARM register recognizer. BLX(2) 4061 uses the ARM register space, not the Thumb one, so a call to 4062 thumb_reg() would be wrong. */ 4063 rm = reg_required_here (& mystr, 3); 4064 inst.error = 0; 4065 4066 if (rm != FAIL) 4067 { 4068 /* It's BLX(2). The .instruction was zapped with rm & is final. */ 4069 inst.size = 2; 4070 } 4071 else 4072 { 4073 /* No ARM register. This must be BLX(1). Change the .instruction. */ 4074 inst.instruction = 0xf7ffeffe; 4075 inst.size = 4; 4076 4077 if (my_get_expression (& inst.reloc.exp, & mystr)) 4078 return; 4079 4080 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX; 4081 inst.reloc.pc_rel = 1; 4082 } 4083 4084 end_of_line (mystr); 4085} 4086 4087/* ARM V5 breakpoint instruction (argument parse) 4088 BKPT <16 bit unsigned immediate> 4089 Instruction is not conditional. 4090 The bit pattern given in insns[] has the COND_ALWAYS condition, 4091 and it is an error if the caller tried to override that. */ 4092 4093static void 4094do_bkpt (str) 4095 char * str; 4096{ 4097 expressionS expr; 4098 unsigned long number; 4099 4100 skip_whitespace (str); 4101 4102 /* Allow optional leading '#'. */ 4103 if (is_immediate_prefix (* str)) 4104 str++; 4105 4106 memset (& expr, '\0', sizeof (expr)); 4107 4108 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant)) 4109 { 4110 inst.error = _("bad or missing expression"); 4111 return; 4112 } 4113 4114 number = expr.X_add_number; 4115 4116 /* Check it fits a 16 bit unsigned. */ 4117 if (number != (number & 0xffff)) 4118 { 4119 inst.error = _("immediate value out of range"); 4120 return; 4121 } 4122 4123 /* Top 12 of 16 bits to bits 19:8. */ 4124 inst.instruction |= (number & 0xfff0) << 4; 4125 4126 /* Bottom 4 of 16 bits to bits 3:0. */ 4127 inst.instruction |= number & 0xf; 4128 4129 end_of_line (str); 4130} 4131 4132/* Xscale multiply-accumulate (argument parse) 4133 MIAcc acc0,Rm,Rs 4134 MIAPHcc acc0,Rm,Rs 4135 MIAxycc acc0,Rm,Rs. */ 4136 4137static void 4138do_xsc_mia (str) 4139 char * str; 4140{ 4141 int rs; 4142 int rm; 4143 4144 if (accum0_required_here (& str) == FAIL) 4145 inst.error = ERR_NO_ACCUM; 4146 4147 else if (skip_past_comma (& str) == FAIL 4148 || (rm = reg_required_here (& str, 0)) == FAIL) 4149 inst.error = BAD_ARGS; 4150 4151 else if (skip_past_comma (& str) == FAIL 4152 || (rs = reg_required_here (& str, 12)) == FAIL) 4153 inst.error = BAD_ARGS; 4154 4155 /* inst.instruction has now been zapped with both rm and rs. */ 4156 else if (rm == REG_PC || rs == REG_PC) 4157 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */ 4158 4159 else 4160 end_of_line (str); 4161} 4162 4163/* Xscale move-accumulator-register (argument parse) 4164 4165 MARcc acc0,RdLo,RdHi. */ 4166 4167static void 4168do_xsc_mar (str) 4169 char * str; 4170{ 4171 int rdlo, rdhi; 4172 4173 if (accum0_required_here (& str) == FAIL) 4174 inst.error = ERR_NO_ACCUM; 4175 4176 else if (skip_past_comma (& str) == FAIL 4177 || (rdlo = reg_required_here (& str, 12)) == FAIL) 4178 inst.error = BAD_ARGS; 4179 4180 else if (skip_past_comma (& str) == FAIL 4181 || (rdhi = reg_required_here (& str, 16)) == FAIL) 4182 inst.error = BAD_ARGS; 4183 4184 /* inst.instruction has now been zapped with both rdlo and rdhi. */ 4185 else if (rdlo == REG_PC || rdhi == REG_PC) 4186 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */ 4187 4188 else 4189 end_of_line (str); 4190} 4191 4192/* Xscale move-register-accumulator (argument parse) 4193 4194 MRAcc RdLo,RdHi,acc0. */ 4195 4196static void 4197do_xsc_mra (str) 4198 char * str; 4199{ 4200 int rdlo; 4201 int rdhi; 4202 4203 skip_whitespace (str); 4204 4205 if ((rdlo = reg_required_here (& str, 12)) == FAIL) 4206 inst.error = BAD_ARGS; 4207 4208 else if (skip_past_comma (& str) == FAIL 4209 || (rdhi = reg_required_here (& str, 16)) == FAIL) 4210 inst.error = BAD_ARGS; 4211 4212 else if (skip_past_comma (& str) == FAIL 4213 || accum0_required_here (& str) == FAIL) 4214 inst.error = ERR_NO_ACCUM; 4215 4216 /* inst.instruction has now been zapped with both rdlo and rdhi. */ 4217 else if (rdlo == rdhi) 4218 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */ 4219 4220 else if (rdlo == REG_PC || rdhi == REG_PC) 4221 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */ 4222 else 4223 end_of_line (str); 4224} 4225 4226/* ARMv5TE: Preload-Cache 4227 4228 PLD <addr_mode> 4229 4230 Syntactically, like LDR with B=1, W=0, L=1. */ 4231 4232static void 4233do_pld (str) 4234 char * str; 4235{ 4236 int rd; 4237 4238 skip_whitespace (str); 4239 4240 if (* str != '[') 4241 { 4242 inst.error = _("'[' expected after PLD mnemonic"); 4243 return; 4244 } 4245 4246 ++str; 4247 skip_whitespace (str); 4248 4249 if ((rd = reg_required_here (& str, 16)) == FAIL) 4250 return; 4251 4252 skip_whitespace (str); 4253 4254 if (*str == ']') 4255 { 4256 /* [Rn], ... ? */ 4257 ++str; 4258 skip_whitespace (str); 4259 4260 /* Post-indexed addressing is not allowed with PLD. */ 4261 if (skip_past_comma (&str) == SUCCESS) 4262 { 4263 inst.error 4264 = _("post-indexed expression used in preload instruction"); 4265 return; 4266 } 4267 else if (*str == '!') /* [Rn]! */ 4268 { 4269 inst.error = _("writeback used in preload instruction"); 4270 ++str; 4271 } 4272 else /* [Rn] */ 4273 inst.instruction |= INDEX_UP | PRE_INDEX; 4274 } 4275 else /* [Rn, ...] */ 4276 { 4277 if (skip_past_comma (& str) == FAIL) 4278 { 4279 inst.error = _("pre-indexed expression expected"); 4280 return; 4281 } 4282 4283 if (ldst_extend (&str) == FAIL) 4284 return; 4285 4286 skip_whitespace (str); 4287 4288 if (* str != ']') 4289 { 4290 inst.error = _("missing ]"); 4291 return; 4292 } 4293 4294 ++ str; 4295 skip_whitespace (str); 4296 4297 if (* str == '!') /* [Rn]! */ 4298 { 4299 inst.error = _("writeback used in preload instruction"); 4300 ++ str; 4301 } 4302 4303 inst.instruction |= PRE_INDEX; 4304 } 4305 4306 end_of_line (str); 4307} 4308 4309/* ARMv5TE load-consecutive (argument parse) 4310 Mode is like LDRH. 4311 4312 LDRccD R, mode 4313 STRccD R, mode. */ 4314 4315static void 4316do_ldrd (str) 4317 char * str; 4318{ 4319 int rd; 4320 int rn; 4321 4322 skip_whitespace (str); 4323 4324 if ((rd = reg_required_here (& str, 12)) == FAIL) 4325 { 4326 inst.error = BAD_ARGS; 4327 return; 4328 } 4329 4330 if (skip_past_comma (& str) == FAIL 4331 || (rn = ld_mode_required_here (& str)) == FAIL) 4332 { 4333 if (!inst.error) 4334 inst.error = BAD_ARGS; 4335 return; 4336 } 4337 4338 /* inst.instruction has now been zapped with Rd and the addressing mode. */ 4339 if (rd & 1) /* Unpredictable result if Rd is odd. */ 4340 { 4341 inst.error = _("destination register must be even"); 4342 return; 4343 } 4344 4345 if (rd == REG_LR) 4346 { 4347 inst.error = _("r14 not allowed here"); 4348 return; 4349 } 4350 4351 if (((rd == rn) || (rd + 1 == rn)) 4352 && ((inst.instruction & WRITE_BACK) 4353 || (!(inst.instruction & PRE_INDEX)))) 4354 as_warn (_("pre/post-indexing used when modified address register is destination")); 4355 4356 /* For an index-register load, the index register must not overlap the 4357 destination (even if not write-back). */ 4358 if ((inst.instruction & V4_STR_BIT) == 0 4359 && (inst.instruction & HWOFFSET_IMM) == 0) 4360 { 4361 int rm = inst.instruction & 0x0000000f; 4362 4363 if (rm == rd || (rm == rd + 1)) 4364 as_warn (_("ldrd destination registers must not overlap index register")); 4365 } 4366 4367 end_of_line (str); 4368} 4369 4370/* Returns the index into fp_values of a floating point number, 4371 or -1 if not in the table. */ 4372 4373static int 4374my_get_float_expression (str) 4375 char ** str; 4376{ 4377 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 4378 char * save_in; 4379 expressionS exp; 4380 int i; 4381 int j; 4382 4383 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE)); 4384 4385 /* Look for a raw floating point number. */ 4386 if ((save_in = atof_ieee (*str, 'x', words)) != NULL 4387 && is_end_of_line[(unsigned char) *save_in]) 4388 { 4389 for (i = 0; i < NUM_FLOAT_VALS; i++) 4390 { 4391 for (j = 0; j < MAX_LITTLENUMS; j++) 4392 { 4393 if (words[j] != fp_values[i][j]) 4394 break; 4395 } 4396 4397 if (j == MAX_LITTLENUMS) 4398 { 4399 *str = save_in; 4400 return i; 4401 } 4402 } 4403 } 4404 4405 /* Try and parse a more complex expression, this will probably fail 4406 unless the code uses a floating point prefix (eg "0f"). */ 4407 save_in = input_line_pointer; 4408 input_line_pointer = *str; 4409 if (expression (&exp) == absolute_section 4410 && exp.X_op == O_big 4411 && exp.X_add_number < 0) 4412 { 4413 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it. 4414 Ditto for 15. */ 4415 if (gen_to_words (words, 5, (long) 15) == 0) 4416 { 4417 for (i = 0; i < NUM_FLOAT_VALS; i++) 4418 { 4419 for (j = 0; j < MAX_LITTLENUMS; j++) 4420 { 4421 if (words[j] != fp_values[i][j]) 4422 break; 4423 } 4424 4425 if (j == MAX_LITTLENUMS) 4426 { 4427 *str = input_line_pointer; 4428 input_line_pointer = save_in; 4429 return i; 4430 } 4431 } 4432 } 4433 } 4434 4435 *str = input_line_pointer; 4436 input_line_pointer = save_in; 4437 return -1; 4438} 4439 4440/* Return true if anything in the expression is a bignum. */ 4441 4442static int 4443walk_no_bignums (sp) 4444 symbolS * sp; 4445{ 4446 if (symbol_get_value_expression (sp)->X_op == O_big) 4447 return 1; 4448 4449 if (symbol_get_value_expression (sp)->X_add_symbol) 4450 { 4451 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) 4452 || (symbol_get_value_expression (sp)->X_op_symbol 4453 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); 4454 } 4455 4456 return 0; 4457} 4458 4459static int in_my_get_expression = 0; 4460 4461static int 4462my_get_expression (ep, str) 4463 expressionS * ep; 4464 char ** str; 4465{ 4466 char * save_in; 4467 segT seg; 4468 4469 save_in = input_line_pointer; 4470 input_line_pointer = *str; 4471 in_my_get_expression = 1; 4472 seg = expression (ep); 4473 in_my_get_expression = 0; 4474 4475 if (ep->X_op == O_illegal) 4476 { 4477 /* We found a bad expression in md_operand(). */ 4478 *str = input_line_pointer; 4479 input_line_pointer = save_in; 4480 return 1; 4481 } 4482 4483#ifdef OBJ_AOUT 4484 if (seg != absolute_section 4485 && seg != text_section 4486 && seg != data_section 4487 && seg != bss_section 4488 && seg != undefined_section) 4489 { 4490 inst.error = _("bad_segment"); 4491 *str = input_line_pointer; 4492 input_line_pointer = save_in; 4493 return 1; 4494 } 4495#endif 4496 4497 /* Get rid of any bignums now, so that we don't generate an error for which 4498 we can't establish a line number later on. Big numbers are never valid 4499 in instructions, which is where this routine is always called. */ 4500 if (ep->X_op == O_big 4501 || (ep->X_add_symbol 4502 && (walk_no_bignums (ep->X_add_symbol) 4503 || (ep->X_op_symbol 4504 && walk_no_bignums (ep->X_op_symbol))))) 4505 { 4506 inst.error = _("invalid constant"); 4507 *str = input_line_pointer; 4508 input_line_pointer = save_in; 4509 return 1; 4510 } 4511 4512 *str = input_line_pointer; 4513 input_line_pointer = save_in; 4514 return 0; 4515} 4516 4517/* We handle all bad expressions here, so that we can report the faulty 4518 instruction in the error message. */ 4519void 4520md_operand (expr) 4521 expressionS *expr; 4522{ 4523 if (in_my_get_expression) 4524 { 4525 expr->X_op = O_illegal; 4526 if (inst.error == NULL) 4527 inst.error = _("bad expression"); 4528 } 4529} 4530 4531/* UNRESTRICT should be one if <shift> <register> is permitted for this 4532 instruction. */ 4533 4534static int 4535decode_shift (str, unrestrict) 4536 char ** str; 4537 int unrestrict; 4538{ 4539 const struct asm_shift_name * shift; 4540 char * p; 4541 char c; 4542 4543 skip_whitespace (* str); 4544 4545 for (p = * str; ISALPHA (* p); p ++) 4546 ; 4547 4548 if (p == * str) 4549 { 4550 inst.error = _("shift expression expected"); 4551 return FAIL; 4552 } 4553 4554 c = * p; 4555 * p = '\0'; 4556 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str); 4557 * p = c; 4558 4559 if (shift == NULL) 4560 { 4561 inst.error = _("shift expression expected"); 4562 return FAIL; 4563 } 4564 4565 assert (shift->properties->index == shift_properties[shift->properties->index].index); 4566 4567 if (shift->properties->index == SHIFT_RRX) 4568 { 4569 * str = p; 4570 inst.instruction |= shift->properties->bit_field; 4571 return SUCCESS; 4572 } 4573 4574 skip_whitespace (p); 4575 4576 if (unrestrict && reg_required_here (& p, 8) != FAIL) 4577 { 4578 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG; 4579 * str = p; 4580 return SUCCESS; 4581 } 4582 else if (! is_immediate_prefix (* p)) 4583 { 4584 inst.error = (unrestrict 4585 ? _("shift requires register or #expression") 4586 : _("shift requires #expression")); 4587 * str = p; 4588 return FAIL; 4589 } 4590 4591 inst.error = NULL; 4592 p ++; 4593 4594 if (my_get_expression (& inst.reloc.exp, & p)) 4595 return FAIL; 4596 4597 /* Validate some simple #expressions. */ 4598 if (inst.reloc.exp.X_op == O_constant) 4599 { 4600 unsigned num = inst.reloc.exp.X_add_number; 4601 4602 /* Reject operations greater than 32. */ 4603 if (num > 32 4604 /* Reject a shift of 0 unless the mode allows it. */ 4605 || (num == 0 && shift->properties->allows_0 == 0) 4606 /* Reject a shift of 32 unless the mode allows it. */ 4607 || (num == 32 && shift->properties->allows_32 == 0) 4608 ) 4609 { 4610 /* As a special case we allow a shift of zero for 4611 modes that do not support it to be recoded as an 4612 logical shift left of zero (ie nothing). We warn 4613 about this though. */ 4614 if (num == 0) 4615 { 4616 as_warn (_("shift of 0 ignored.")); 4617 shift = & shift_names[0]; 4618 assert (shift->properties->index == SHIFT_LSL); 4619 } 4620 else 4621 { 4622 inst.error = _("invalid immediate shift"); 4623 return FAIL; 4624 } 4625 } 4626 4627 /* Shifts of 32 are encoded as 0, for those shifts that 4628 support it. */ 4629 if (num == 32) 4630 num = 0; 4631 4632 inst.instruction |= (num << 7) | shift->properties->bit_field; 4633 } 4634 else 4635 { 4636 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM; 4637 inst.reloc.pc_rel = 0; 4638 inst.instruction |= shift->properties->bit_field; 4639 } 4640 4641 * str = p; 4642 return SUCCESS; 4643} 4644 4645/* Do those data_ops which can take a negative immediate constant 4646 by altering the instuction. A bit of a hack really. 4647 MOV <-> MVN 4648 AND <-> BIC 4649 ADC <-> SBC 4650 by inverting the second operand, and 4651 ADD <-> SUB 4652 CMP <-> CMN 4653 by negating the second operand. */ 4654 4655static int 4656negate_data_op (instruction, value) 4657 unsigned long * instruction; 4658 unsigned long value; 4659{ 4660 int op, new_inst; 4661 unsigned long negated, inverted; 4662 4663 negated = validate_immediate (-value); 4664 inverted = validate_immediate (~value); 4665 4666 op = (*instruction >> DATA_OP_SHIFT) & 0xf; 4667 switch (op) 4668 { 4669 /* First negates. */ 4670 case OPCODE_SUB: /* ADD <-> SUB */ 4671 new_inst = OPCODE_ADD; 4672 value = negated; 4673 break; 4674 4675 case OPCODE_ADD: 4676 new_inst = OPCODE_SUB; 4677 value = negated; 4678 break; 4679 4680 case OPCODE_CMP: /* CMP <-> CMN */ 4681 new_inst = OPCODE_CMN; 4682 value = negated; 4683 break; 4684 4685 case OPCODE_CMN: 4686 new_inst = OPCODE_CMP; 4687 value = negated; 4688 break; 4689 4690 /* Now Inverted ops. */ 4691 case OPCODE_MOV: /* MOV <-> MVN */ 4692 new_inst = OPCODE_MVN; 4693 value = inverted; 4694 break; 4695 4696 case OPCODE_MVN: 4697 new_inst = OPCODE_MOV; 4698 value = inverted; 4699 break; 4700 4701 case OPCODE_AND: /* AND <-> BIC */ 4702 new_inst = OPCODE_BIC; 4703 value = inverted; 4704 break; 4705 4706 case OPCODE_BIC: 4707 new_inst = OPCODE_AND; 4708 value = inverted; 4709 break; 4710 4711 case OPCODE_ADC: /* ADC <-> SBC */ 4712 new_inst = OPCODE_SBC; 4713 value = inverted; 4714 break; 4715 4716 case OPCODE_SBC: 4717 new_inst = OPCODE_ADC; 4718 value = inverted; 4719 break; 4720 4721 /* We cannot do anything. */ 4722 default: 4723 return FAIL; 4724 } 4725 4726 if (value == (unsigned) FAIL) 4727 return FAIL; 4728 4729 *instruction &= OPCODE_MASK; 4730 *instruction |= new_inst << DATA_OP_SHIFT; 4731 return value; 4732} 4733 4734static int 4735data_op2 (str) 4736 char ** str; 4737{ 4738 int value; 4739 expressionS expr; 4740 4741 skip_whitespace (* str); 4742 4743 if (reg_required_here (str, 0) != FAIL) 4744 { 4745 if (skip_past_comma (str) == SUCCESS) 4746 /* Shift operation on register. */ 4747 return decode_shift (str, NO_SHIFT_RESTRICT); 4748 4749 return SUCCESS; 4750 } 4751 else 4752 { 4753 /* Immediate expression. */ 4754 if (is_immediate_prefix (**str)) 4755 { 4756 (*str)++; 4757 inst.error = NULL; 4758 4759 if (my_get_expression (&inst.reloc.exp, str)) 4760 return FAIL; 4761 4762 if (inst.reloc.exp.X_add_symbol) 4763 { 4764 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; 4765 inst.reloc.pc_rel = 0; 4766 } 4767 else 4768 { 4769 if (skip_past_comma (str) == SUCCESS) 4770 { 4771 /* #x, y -- ie explicit rotation by Y. */ 4772 if (my_get_expression (&expr, str)) 4773 return FAIL; 4774 4775 if (expr.X_op != O_constant) 4776 { 4777 inst.error = _("constant expression expected"); 4778 return FAIL; 4779 } 4780 4781 /* Rotate must be a multiple of 2. */ 4782 if (((unsigned) expr.X_add_number) > 30 4783 || (expr.X_add_number & 1) != 0 4784 || ((unsigned) inst.reloc.exp.X_add_number) > 255) 4785 { 4786 inst.error = _("invalid constant"); 4787 return FAIL; 4788 } 4789 inst.instruction |= INST_IMMEDIATE; 4790 inst.instruction |= inst.reloc.exp.X_add_number; 4791 inst.instruction |= expr.X_add_number << 7; 4792 return SUCCESS; 4793 } 4794 4795 /* Implicit rotation, select a suitable one. */ 4796 value = validate_immediate (inst.reloc.exp.X_add_number); 4797 4798 if (value == FAIL) 4799 { 4800 /* Can't be done. Perhaps the code reads something like 4801 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */ 4802 if ((value = negate_data_op (&inst.instruction, 4803 inst.reloc.exp.X_add_number)) 4804 == FAIL) 4805 { 4806 inst.error = _("invalid constant"); 4807 return FAIL; 4808 } 4809 } 4810 4811 inst.instruction |= value; 4812 } 4813 4814 inst.instruction |= INST_IMMEDIATE; 4815 return SUCCESS; 4816 } 4817 4818 (*str)++; 4819 inst.error = _("register or shift expression expected"); 4820 return FAIL; 4821 } 4822} 4823 4824static int 4825fp_op2 (str) 4826 char ** str; 4827{ 4828 skip_whitespace (* str); 4829 4830 if (fp_reg_required_here (str, 0) != FAIL) 4831 return SUCCESS; 4832 else 4833 { 4834 /* Immediate expression. */ 4835 if (*((*str)++) == '#') 4836 { 4837 int i; 4838 4839 inst.error = NULL; 4840 4841 skip_whitespace (* str); 4842 4843 /* First try and match exact strings, this is to guarantee 4844 that some formats will work even for cross assembly. */ 4845 4846 for (i = 0; fp_const[i]; i++) 4847 { 4848 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0) 4849 { 4850 char *start = *str; 4851 4852 *str += strlen (fp_const[i]); 4853 if (is_end_of_line[(unsigned char) **str]) 4854 { 4855 inst.instruction |= i + 8; 4856 return SUCCESS; 4857 } 4858 *str = start; 4859 } 4860 } 4861 4862 /* Just because we didn't get a match doesn't mean that the 4863 constant isn't valid, just that it is in a format that we 4864 don't automatically recognize. Try parsing it with 4865 the standard expression routines. */ 4866 if ((i = my_get_float_expression (str)) >= 0) 4867 { 4868 inst.instruction |= i + 8; 4869 return SUCCESS; 4870 } 4871 4872 inst.error = _("invalid floating point immediate expression"); 4873 return FAIL; 4874 } 4875 inst.error = 4876 _("floating point register or immediate expression expected"); 4877 return FAIL; 4878 } 4879} 4880 4881static void 4882do_arit (str) 4883 char * str; 4884{ 4885 skip_whitespace (str); 4886 4887 if (reg_required_here (&str, 12) == FAIL 4888 || skip_past_comma (&str) == FAIL 4889 || reg_required_here (&str, 16) == FAIL 4890 || skip_past_comma (&str) == FAIL 4891 || data_op2 (&str) == FAIL) 4892 { 4893 if (!inst.error) 4894 inst.error = BAD_ARGS; 4895 return; 4896 } 4897 4898 end_of_line (str); 4899 return; 4900} 4901 4902static void 4903do_adr (str) 4904 char * str; 4905{ 4906 /* This is a pseudo-op of the form "adr rd, label" to be converted 4907 into a relative address of the form "add rd, pc, #label-.-8". */ 4908 skip_whitespace (str); 4909 4910 if (reg_required_here (&str, 12) == FAIL 4911 || skip_past_comma (&str) == FAIL 4912 || my_get_expression (&inst.reloc.exp, &str)) 4913 { 4914 if (!inst.error) 4915 inst.error = BAD_ARGS; 4916 return; 4917 } 4918 4919 /* Frag hacking will turn this into a sub instruction if the offset turns 4920 out to be negative. */ 4921 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; 4922 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */ 4923 inst.reloc.pc_rel = 1; 4924 4925 end_of_line (str); 4926} 4927 4928static void 4929do_adrl (str) 4930 char * str; 4931{ 4932 /* This is a pseudo-op of the form "adrl rd, label" to be converted 4933 into a relative address of the form: 4934 add rd, pc, #low(label-.-8)" 4935 add rd, rd, #high(label-.-8)" */ 4936 4937 skip_whitespace (str); 4938 4939 if (reg_required_here (&str, 12) == FAIL 4940 || skip_past_comma (&str) == FAIL 4941 || my_get_expression (&inst.reloc.exp, &str)) 4942 { 4943 if (!inst.error) 4944 inst.error = BAD_ARGS; 4945 4946 return; 4947 } 4948 4949 end_of_line (str); 4950 /* Frag hacking will turn this into a sub instruction if the offset turns 4951 out to be negative. */ 4952 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE; 4953 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */ 4954 inst.reloc.pc_rel = 1; 4955 inst.size = INSN_SIZE * 2; 4956 4957 return; 4958} 4959 4960static void 4961do_cmp (str) 4962 char * str; 4963{ 4964 skip_whitespace (str); 4965 4966 if (reg_required_here (&str, 16) == FAIL) 4967 { 4968 if (!inst.error) 4969 inst.error = BAD_ARGS; 4970 return; 4971 } 4972 4973 if (skip_past_comma (&str) == FAIL 4974 || data_op2 (&str) == FAIL) 4975 { 4976 if (!inst.error) 4977 inst.error = BAD_ARGS; 4978 return; 4979 } 4980 4981 end_of_line (str); 4982 return; 4983} 4984 4985static void 4986do_mov (str) 4987 char * str; 4988{ 4989 skip_whitespace (str); 4990 4991 if (reg_required_here (&str, 12) == FAIL) 4992 { 4993 if (!inst.error) 4994 inst.error = BAD_ARGS; 4995 return; 4996 } 4997 4998 if (skip_past_comma (&str) == FAIL 4999 || data_op2 (&str) == FAIL) 5000 { 5001 if (!inst.error) 5002 inst.error = BAD_ARGS; 5003 return; 5004 } 5005 5006 end_of_line (str); 5007 return; 5008} 5009 5010static int 5011ldst_extend (str) 5012 char ** str; 5013{ 5014 int add = INDEX_UP; 5015 5016 switch (**str) 5017 { 5018 case '#': 5019 case '$': 5020 (*str)++; 5021 if (my_get_expression (& inst.reloc.exp, str)) 5022 return FAIL; 5023 5024 if (inst.reloc.exp.X_op == O_constant) 5025 { 5026 int value = inst.reloc.exp.X_add_number; 5027 5028 if (value < -4095 || value > 4095) 5029 { 5030 inst.error = _("address offset too large"); 5031 return FAIL; 5032 } 5033 5034 if (value < 0) 5035 { 5036 value = -value; 5037 add = 0; 5038 } 5039 5040 inst.instruction |= add | value; 5041 } 5042 else 5043 { 5044 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM; 5045 inst.reloc.pc_rel = 0; 5046 } 5047 return SUCCESS; 5048 5049 case '-': 5050 add = 0; 5051 /* Fall through. */ 5052 5053 case '+': 5054 (*str)++; 5055 /* Fall through. */ 5056 5057 default: 5058 if (reg_required_here (str, 0) == FAIL) 5059 return FAIL; 5060 5061 inst.instruction |= add | OFFSET_REG; 5062 if (skip_past_comma (str) == SUCCESS) 5063 return decode_shift (str, SHIFT_RESTRICT); 5064 5065 return SUCCESS; 5066 } 5067} 5068 5069static void 5070do_ldst (str) 5071 char * str; 5072{ 5073 int pre_inc = 0; 5074 int conflict_reg; 5075 int value; 5076 5077 skip_whitespace (str); 5078 5079 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL) 5080 { 5081 if (!inst.error) 5082 inst.error = BAD_ARGS; 5083 return; 5084 } 5085 5086 if (skip_past_comma (&str) == FAIL) 5087 { 5088 inst.error = _("address expected"); 5089 return; 5090 } 5091 5092 if (*str == '[') 5093 { 5094 int reg; 5095 5096 str++; 5097 5098 skip_whitespace (str); 5099 5100 if ((reg = reg_required_here (&str, 16)) == FAIL) 5101 return; 5102 5103 /* Conflicts can occur on stores as well as loads. */ 5104 conflict_reg = (conflict_reg == reg); 5105 5106 skip_whitespace (str); 5107 5108 if (*str == ']') 5109 { 5110 str ++; 5111 5112 if (skip_past_comma (&str) == SUCCESS) 5113 { 5114 /* [Rn],... (post inc) */ 5115 if (ldst_extend (&str) == FAIL) 5116 return; 5117 if (conflict_reg) 5118 as_warn (_("%s register same as write-back base"), 5119 ((inst.instruction & LOAD_BIT) 5120 ? _("destination") : _("source"))); 5121 } 5122 else 5123 { 5124 /* [Rn] */ 5125 skip_whitespace (str); 5126 5127 if (*str == '!') 5128 { 5129 if (conflict_reg) 5130 as_warn (_("%s register same as write-back base"), 5131 ((inst.instruction & LOAD_BIT) 5132 ? _("destination") : _("source"))); 5133 str++; 5134 inst.instruction |= WRITE_BACK; 5135 } 5136 5137 inst.instruction |= INDEX_UP; 5138 pre_inc = 1; 5139 } 5140 } 5141 else 5142 { 5143 /* [Rn,...] */ 5144 if (skip_past_comma (&str) == FAIL) 5145 { 5146 inst.error = _("pre-indexed expression expected"); 5147 return; 5148 } 5149 5150 pre_inc = 1; 5151 if (ldst_extend (&str) == FAIL) 5152 return; 5153 5154 skip_whitespace (str); 5155 5156 if (*str++ != ']') 5157 { 5158 inst.error = _("missing ]"); 5159 return; 5160 } 5161 5162 skip_whitespace (str); 5163 5164 if (*str == '!') 5165 { 5166 if (conflict_reg) 5167 as_warn (_("%s register same as write-back base"), 5168 ((inst.instruction & LOAD_BIT) 5169 ? _("destination") : _("source"))); 5170 str++; 5171 inst.instruction |= WRITE_BACK; 5172 } 5173 } 5174 } 5175 else if (*str == '=') 5176 { 5177 if ((inst.instruction & LOAD_BIT) == 0) 5178 { 5179 inst.error = _("invalid pseudo operation"); 5180 return; 5181 } 5182 5183 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */ 5184 str++; 5185 5186 skip_whitespace (str); 5187 5188 if (my_get_expression (&inst.reloc.exp, &str)) 5189 return; 5190 5191 if (inst.reloc.exp.X_op != O_constant 5192 && inst.reloc.exp.X_op != O_symbol) 5193 { 5194 inst.error = _("constant expression expected"); 5195 return; 5196 } 5197 5198 if (inst.reloc.exp.X_op == O_constant) 5199 { 5200 value = validate_immediate (inst.reloc.exp.X_add_number); 5201 5202 if (value != FAIL) 5203 { 5204 /* This can be done with a mov instruction. */ 5205 inst.instruction &= LITERAL_MASK; 5206 inst.instruction |= (INST_IMMEDIATE 5207 | (OPCODE_MOV << DATA_OP_SHIFT)); 5208 inst.instruction |= value & 0xfff; 5209 end_of_line (str); 5210 return; 5211 } 5212 5213 value = validate_immediate (~inst.reloc.exp.X_add_number); 5214 5215 if (value != FAIL) 5216 { 5217 /* This can be done with a mvn instruction. */ 5218 inst.instruction &= LITERAL_MASK; 5219 inst.instruction |= (INST_IMMEDIATE 5220 | (OPCODE_MVN << DATA_OP_SHIFT)); 5221 inst.instruction |= value & 0xfff; 5222 end_of_line (str); 5223 return; 5224 } 5225 } 5226 5227 /* Insert into literal pool. */ 5228 if (add_to_lit_pool () == FAIL) 5229 { 5230 if (!inst.error) 5231 inst.error = _("literal pool insertion failed"); 5232 return; 5233 } 5234 5235 /* Change the instruction exp to point to the pool. */ 5236 inst.reloc.type = BFD_RELOC_ARM_LITERAL; 5237 inst.reloc.pc_rel = 1; 5238 inst.instruction |= (REG_PC << 16); 5239 pre_inc = 1; 5240 } 5241 else 5242 { 5243 if (my_get_expression (&inst.reloc.exp, &str)) 5244 return; 5245 5246 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM; 5247#ifndef TE_WINCE 5248 /* PC rel adjust. */ 5249 inst.reloc.exp.X_add_number -= 8; 5250#endif 5251 inst.reloc.pc_rel = 1; 5252 inst.instruction |= (REG_PC << 16); 5253 pre_inc = 1; 5254 } 5255 5256 inst.instruction |= (pre_inc ? PRE_INDEX : 0); 5257 end_of_line (str); 5258 return; 5259} 5260 5261static void 5262do_ldstt (str) 5263 char * str; 5264{ 5265 int conflict_reg; 5266 5267 skip_whitespace (str); 5268 5269 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL) 5270 { 5271 if (!inst.error) 5272 inst.error = BAD_ARGS; 5273 return; 5274 } 5275 5276 if (skip_past_comma (& str) == FAIL) 5277 { 5278 inst.error = _("address expected"); 5279 return; 5280 } 5281 5282 if (*str == '[') 5283 { 5284 int reg; 5285 5286 str++; 5287 5288 skip_whitespace (str); 5289 5290 if ((reg = reg_required_here (&str, 16)) == FAIL) 5291 return; 5292 5293 /* ldrt/strt always use post-indexed addressing, so if the base is 5294 the same as Rd, we warn. */ 5295 if (conflict_reg == reg) 5296 as_warn (_("%s register same as write-back base"), 5297 ((inst.instruction & LOAD_BIT) 5298 ? _("destination") : _("source"))); 5299 5300 skip_whitespace (str); 5301 5302 if (*str == ']') 5303 { 5304 str ++; 5305 5306 if (skip_past_comma (&str) == SUCCESS) 5307 { 5308 /* [Rn],... (post inc) */ 5309 if (ldst_extend (&str) == FAIL) 5310 return; 5311 } 5312 else 5313 { 5314 /* [Rn] */ 5315 skip_whitespace (str); 5316 5317 /* Skip a write-back '!'. */ 5318 if (*str == '!') 5319 str++; 5320 5321 inst.instruction |= INDEX_UP; 5322 } 5323 } 5324 else 5325 { 5326 inst.error = _("post-indexed expression expected"); 5327 return; 5328 } 5329 } 5330 else 5331 { 5332 inst.error = _("post-indexed expression expected"); 5333 return; 5334 } 5335 5336 end_of_line (str); 5337 return; 5338} 5339 5340static int 5341ldst_extend_v4 (str) 5342 char ** str; 5343{ 5344 int add = INDEX_UP; 5345 5346 switch (**str) 5347 { 5348 case '#': 5349 case '$': 5350 (*str)++; 5351 if (my_get_expression (& inst.reloc.exp, str)) 5352 return FAIL; 5353 5354 if (inst.reloc.exp.X_op == O_constant) 5355 { 5356 int value = inst.reloc.exp.X_add_number; 5357 5358 if (value < -255 || value > 255) 5359 { 5360 inst.error = _("address offset too large"); 5361 return FAIL; 5362 } 5363 5364 if (value < 0) 5365 { 5366 value = -value; 5367 add = 0; 5368 } 5369 5370 /* Halfword and signextension instructions have the 5371 immediate value split across bits 11..8 and bits 3..0. */ 5372 inst.instruction |= (add | HWOFFSET_IMM 5373 | ((value >> 4) << 8) | (value & 0xF)); 5374 } 5375 else 5376 { 5377 inst.instruction |= HWOFFSET_IMM; 5378 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8; 5379 inst.reloc.pc_rel = 0; 5380 } 5381 return SUCCESS; 5382 5383 case '-': 5384 add = 0; 5385 /* Fall through. */ 5386 5387 case '+': 5388 (*str)++; 5389 /* Fall through. */ 5390 5391 default: 5392 if (reg_required_here (str, 0) == FAIL) 5393 return FAIL; 5394 5395 inst.instruction |= add; 5396 return SUCCESS; 5397 } 5398} 5399 5400/* Halfword and signed-byte load/store operations. */ 5401static void 5402do_ldstv4 (str) 5403 char * str; 5404{ 5405 int pre_inc = 0; 5406 int conflict_reg; 5407 int value; 5408 5409 skip_whitespace (str); 5410 5411 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL) 5412 { 5413 if (!inst.error) 5414 inst.error = BAD_ARGS; 5415 return; 5416 } 5417 5418 if (skip_past_comma (& str) == FAIL) 5419 { 5420 inst.error = _("address expected"); 5421 return; 5422 } 5423 5424 if (*str == '[') 5425 { 5426 int reg; 5427 5428 str++; 5429 5430 skip_whitespace (str); 5431 5432 if ((reg = reg_required_here (&str, 16)) == FAIL) 5433 return; 5434 5435 /* Conflicts can occur on stores as well as loads. */ 5436 conflict_reg = (conflict_reg == reg); 5437 5438 skip_whitespace (str); 5439 5440 if (*str == ']') 5441 { 5442 str ++; 5443 5444 if (skip_past_comma (&str) == SUCCESS) 5445 { 5446 /* [Rn],... (post inc) */ 5447 if (ldst_extend_v4 (&str) == FAIL) 5448 return; 5449 if (conflict_reg) 5450 as_warn (_("%s register same as write-back base"), 5451 ((inst.instruction & LOAD_BIT) 5452 ? _("destination") : _("source"))); 5453 } 5454 else 5455 { 5456 /* [Rn] */ 5457 inst.instruction |= HWOFFSET_IMM; 5458 5459 skip_whitespace (str); 5460 5461 if (*str == '!') 5462 { 5463 if (conflict_reg) 5464 as_warn (_("%s register same as write-back base"), 5465 ((inst.instruction & LOAD_BIT) 5466 ? _("destination") : _("source"))); 5467 str++; 5468 inst.instruction |= WRITE_BACK; 5469 } 5470 5471 inst.instruction |= INDEX_UP; 5472 pre_inc = 1; 5473 } 5474 } 5475 else 5476 { 5477 /* [Rn,...] */ 5478 if (skip_past_comma (&str) == FAIL) 5479 { 5480 inst.error = _("pre-indexed expression expected"); 5481 return; 5482 } 5483 5484 pre_inc = 1; 5485 if (ldst_extend_v4 (&str) == FAIL) 5486 return; 5487 5488 skip_whitespace (str); 5489 5490 if (*str++ != ']') 5491 { 5492 inst.error = _("missing ]"); 5493 return; 5494 } 5495 5496 skip_whitespace (str); 5497 5498 if (*str == '!') 5499 { 5500 if (conflict_reg) 5501 as_warn (_("%s register same as write-back base"), 5502 ((inst.instruction & LOAD_BIT) 5503 ? _("destination") : _("source"))); 5504 str++; 5505 inst.instruction |= WRITE_BACK; 5506 } 5507 } 5508 } 5509 else if (*str == '=') 5510 { 5511 if ((inst.instruction & LOAD_BIT) == 0) 5512 { 5513 inst.error = _("invalid pseudo operation"); 5514 return; 5515 } 5516 5517 /* XXX Does this work correctly for half-word/byte ops? */ 5518 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */ 5519 str++; 5520 5521 skip_whitespace (str); 5522 5523 if (my_get_expression (&inst.reloc.exp, &str)) 5524 return; 5525 5526 if (inst.reloc.exp.X_op != O_constant 5527 && inst.reloc.exp.X_op != O_symbol) 5528 { 5529 inst.error = _("constant expression expected"); 5530 return; 5531 } 5532 5533 if (inst.reloc.exp.X_op == O_constant) 5534 { 5535 value = validate_immediate (inst.reloc.exp.X_add_number); 5536 5537 if (value != FAIL) 5538 { 5539 /* This can be done with a mov instruction. */ 5540 inst.instruction &= LITERAL_MASK; 5541 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); 5542 inst.instruction |= value & 0xfff; 5543 end_of_line (str); 5544 return; 5545 } 5546 5547 value = validate_immediate (~ inst.reloc.exp.X_add_number); 5548 5549 if (value != FAIL) 5550 { 5551 /* This can be done with a mvn instruction. */ 5552 inst.instruction &= LITERAL_MASK; 5553 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT); 5554 inst.instruction |= value & 0xfff; 5555 end_of_line (str); 5556 return; 5557 } 5558 } 5559 5560 /* Insert into literal pool. */ 5561 if (add_to_lit_pool () == FAIL) 5562 { 5563 if (!inst.error) 5564 inst.error = _("literal pool insertion failed"); 5565 return; 5566 } 5567 5568 /* Change the instruction exp to point to the pool. */ 5569 inst.instruction |= HWOFFSET_IMM; 5570 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL; 5571 inst.reloc.pc_rel = 1; 5572 inst.instruction |= (REG_PC << 16); 5573 pre_inc = 1; 5574 } 5575 else 5576 { 5577 if (my_get_expression (&inst.reloc.exp, &str)) 5578 return; 5579 5580 inst.instruction |= HWOFFSET_IMM; 5581 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8; 5582#ifndef TE_WINCE 5583 /* PC rel adjust. */ 5584 inst.reloc.exp.X_add_number -= 8; 5585#endif 5586 inst.reloc.pc_rel = 1; 5587 inst.instruction |= (REG_PC << 16); 5588 pre_inc = 1; 5589 } 5590 5591 inst.instruction |= (pre_inc ? PRE_INDEX : 0); 5592 end_of_line (str); 5593 return; 5594} 5595 5596static long 5597reg_list (strp) 5598 char ** strp; 5599{ 5600 char * str = * strp; 5601 long range = 0; 5602 int another_range; 5603 5604 /* We come back here if we get ranges concatenated by '+' or '|'. */ 5605 do 5606 { 5607 another_range = 0; 5608 5609 if (*str == '{') 5610 { 5611 int in_range = 0; 5612 int cur_reg = -1; 5613 5614 str++; 5615 do 5616 { 5617 int reg; 5618 5619 skip_whitespace (str); 5620 5621 if ((reg = reg_required_here (& str, -1)) == FAIL) 5622 return FAIL; 5623 5624 if (in_range) 5625 { 5626 int i; 5627 5628 if (reg <= cur_reg) 5629 { 5630 inst.error = _("bad range in register list"); 5631 return FAIL; 5632 } 5633 5634 for (i = cur_reg + 1; i < reg; i++) 5635 { 5636 if (range & (1 << i)) 5637 as_tsktsk 5638 (_("Warning: duplicated register (r%d) in register list"), 5639 i); 5640 else 5641 range |= 1 << i; 5642 } 5643 in_range = 0; 5644 } 5645 5646 if (range & (1 << reg)) 5647 as_tsktsk (_("Warning: duplicated register (r%d) in register list"), 5648 reg); 5649 else if (reg <= cur_reg) 5650 as_tsktsk (_("Warning: register range not in ascending order")); 5651 5652 range |= 1 << reg; 5653 cur_reg = reg; 5654 } 5655 while (skip_past_comma (&str) != FAIL 5656 || (in_range = 1, *str++ == '-')); 5657 str--; 5658 skip_whitespace (str); 5659 5660 if (*str++ != '}') 5661 { 5662 inst.error = _("missing `}'"); 5663 return FAIL; 5664 } 5665 } 5666 else 5667 { 5668 expressionS expr; 5669 5670 if (my_get_expression (&expr, &str)) 5671 return FAIL; 5672 5673 if (expr.X_op == O_constant) 5674 { 5675 if (expr.X_add_number 5676 != (expr.X_add_number & 0x0000ffff)) 5677 { 5678 inst.error = _("invalid register mask"); 5679 return FAIL; 5680 } 5681 5682 if ((range & expr.X_add_number) != 0) 5683 { 5684 int regno = range & expr.X_add_number; 5685 5686 regno &= -regno; 5687 regno = (1 << regno) - 1; 5688 as_tsktsk 5689 (_("Warning: duplicated register (r%d) in register list"), 5690 regno); 5691 } 5692 5693 range |= expr.X_add_number; 5694 } 5695 else 5696 { 5697 if (inst.reloc.type != 0) 5698 { 5699 inst.error = _("expression too complex"); 5700 return FAIL; 5701 } 5702 5703 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS)); 5704 inst.reloc.type = BFD_RELOC_ARM_MULTI; 5705 inst.reloc.pc_rel = 0; 5706 } 5707 } 5708 5709 skip_whitespace (str); 5710 5711 if (*str == '|' || *str == '+') 5712 { 5713 str++; 5714 another_range = 1; 5715 } 5716 } 5717 while (another_range); 5718 5719 *strp = str; 5720 return range; 5721} 5722 5723static void 5724do_ldmstm (str) 5725 char * str; 5726{ 5727 int base_reg; 5728 long range; 5729 5730 skip_whitespace (str); 5731 5732 if ((base_reg = reg_required_here (&str, 16)) == FAIL) 5733 return; 5734 5735 if (base_reg == REG_PC) 5736 { 5737 inst.error = _("r15 not allowed as base register"); 5738 return; 5739 } 5740 5741 skip_whitespace (str); 5742 5743 if (*str == '!') 5744 { 5745 inst.instruction |= WRITE_BACK; 5746 str++; 5747 } 5748 5749 if (skip_past_comma (&str) == FAIL 5750 || (range = reg_list (&str)) == FAIL) 5751 { 5752 if (! inst.error) 5753 inst.error = BAD_ARGS; 5754 return; 5755 } 5756 5757 if (*str == '^') 5758 { 5759 str++; 5760 inst.instruction |= LDM_TYPE_2_OR_3; 5761 } 5762 5763 inst.instruction |= range; 5764 end_of_line (str); 5765 return; 5766} 5767 5768static void 5769do_swi (str) 5770 char * str; 5771{ 5772 skip_whitespace (str); 5773 5774 /* Allow optional leading '#'. */ 5775 if (is_immediate_prefix (*str)) 5776 str++; 5777 5778 if (my_get_expression (& inst.reloc.exp, & str)) 5779 return; 5780 5781 inst.reloc.type = BFD_RELOC_ARM_SWI; 5782 inst.reloc.pc_rel = 0; 5783 end_of_line (str); 5784 5785 return; 5786} 5787 5788static void 5789do_swap (str) 5790 char * str; 5791{ 5792 int reg; 5793 5794 skip_whitespace (str); 5795 5796 if ((reg = reg_required_here (&str, 12)) == FAIL) 5797 return; 5798 5799 if (reg == REG_PC) 5800 { 5801 inst.error = _("r15 not allowed in swap"); 5802 return; 5803 } 5804 5805 if (skip_past_comma (&str) == FAIL 5806 || (reg = reg_required_here (&str, 0)) == FAIL) 5807 { 5808 if (!inst.error) 5809 inst.error = BAD_ARGS; 5810 return; 5811 } 5812 5813 if (reg == REG_PC) 5814 { 5815 inst.error = _("r15 not allowed in swap"); 5816 return; 5817 } 5818 5819 if (skip_past_comma (&str) == FAIL 5820 || *str++ != '[') 5821 { 5822 inst.error = BAD_ARGS; 5823 return; 5824 } 5825 5826 skip_whitespace (str); 5827 5828 if ((reg = reg_required_here (&str, 16)) == FAIL) 5829 return; 5830 5831 if (reg == REG_PC) 5832 { 5833 inst.error = BAD_PC; 5834 return; 5835 } 5836 5837 skip_whitespace (str); 5838 5839 if (*str++ != ']') 5840 { 5841 inst.error = _("missing ]"); 5842 return; 5843 } 5844 5845 end_of_line (str); 5846 return; 5847} 5848 5849static void 5850do_branch (str) 5851 char * str; 5852{ 5853 if (my_get_expression (&inst.reloc.exp, &str)) 5854 return; 5855 5856#ifdef OBJ_ELF 5857 { 5858 char * save_in; 5859 5860 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc 5861 required for the instruction. */ 5862 5863 /* arm_parse_reloc () works on input_line_pointer. 5864 We actually want to parse the operands to the branch instruction 5865 passed in 'str'. Save the input pointer and restore it later. */ 5866 save_in = input_line_pointer; 5867 input_line_pointer = str; 5868 if (inst.reloc.exp.X_op == O_symbol 5869 && *str == '(' 5870 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32) 5871 { 5872 inst.reloc.type = BFD_RELOC_ARM_PLT32; 5873 inst.reloc.pc_rel = 0; 5874 /* Modify str to point to after parsed operands, otherwise 5875 end_of_line() will complain about the (PLT) left in str. */ 5876 str = input_line_pointer; 5877 } 5878 else 5879 { 5880 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH; 5881 inst.reloc.pc_rel = 1; 5882 } 5883 input_line_pointer = save_in; 5884 } 5885#else 5886 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH; 5887 inst.reloc.pc_rel = 1; 5888#endif /* OBJ_ELF */ 5889 5890 end_of_line (str); 5891 return; 5892} 5893 5894static void 5895do_bx (str) 5896 char * str; 5897{ 5898 int reg; 5899 5900 skip_whitespace (str); 5901 5902 if ((reg = reg_required_here (&str, 0)) == FAIL) 5903 { 5904 inst.error = BAD_ARGS; 5905 return; 5906 } 5907 5908 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */ 5909 if (reg == REG_PC) 5910 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful")); 5911 5912 end_of_line (str); 5913} 5914 5915static void 5916do_cdp (str) 5917 char * str; 5918{ 5919 /* Co-processor data operation. 5920 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */ 5921 skip_whitespace (str); 5922 5923 if (co_proc_number (&str) == FAIL) 5924 { 5925 if (!inst.error) 5926 inst.error = BAD_ARGS; 5927 return; 5928 } 5929 5930 if (skip_past_comma (&str) == FAIL 5931 || cp_opc_expr (&str, 20,4) == FAIL) 5932 { 5933 if (!inst.error) 5934 inst.error = BAD_ARGS; 5935 return; 5936 } 5937 5938 if (skip_past_comma (&str) == FAIL 5939 || cp_reg_required_here (&str, 12) == FAIL) 5940 { 5941 if (!inst.error) 5942 inst.error = BAD_ARGS; 5943 return; 5944 } 5945 5946 if (skip_past_comma (&str) == FAIL 5947 || cp_reg_required_here (&str, 16) == FAIL) 5948 { 5949 if (!inst.error) 5950 inst.error = BAD_ARGS; 5951 return; 5952 } 5953 5954 if (skip_past_comma (&str) == FAIL 5955 || cp_reg_required_here (&str, 0) == FAIL) 5956 { 5957 if (!inst.error) 5958 inst.error = BAD_ARGS; 5959 return; 5960 } 5961 5962 if (skip_past_comma (&str) == SUCCESS) 5963 { 5964 if (cp_opc_expr (&str, 5, 3) == FAIL) 5965 { 5966 if (!inst.error) 5967 inst.error = BAD_ARGS; 5968 return; 5969 } 5970 } 5971 5972 end_of_line (str); 5973 return; 5974} 5975 5976static void 5977do_lstc (str) 5978 char * str; 5979{ 5980 /* Co-processor register load/store. 5981 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */ 5982 5983 skip_whitespace (str); 5984 5985 if (co_proc_number (&str) == FAIL) 5986 { 5987 if (!inst.error) 5988 inst.error = BAD_ARGS; 5989 return; 5990 } 5991 5992 if (skip_past_comma (&str) == FAIL 5993 || cp_reg_required_here (&str, 12) == FAIL) 5994 { 5995 if (!inst.error) 5996 inst.error = BAD_ARGS; 5997 return; 5998 } 5999 6000 if (skip_past_comma (&str) == FAIL 6001 || cp_address_required_here (&str, CP_WB_OK) == FAIL) 6002 { 6003 if (! inst.error) 6004 inst.error = BAD_ARGS; 6005 return; 6006 } 6007 6008 end_of_line (str); 6009 return; 6010} 6011 6012static void 6013do_co_reg (str) 6014 char * str; 6015{ 6016 /* Co-processor register transfer. 6017 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */ 6018 6019 skip_whitespace (str); 6020 6021 if (co_proc_number (&str) == FAIL) 6022 { 6023 if (!inst.error) 6024 inst.error = BAD_ARGS; 6025 return; 6026 } 6027 6028 if (skip_past_comma (&str) == FAIL 6029 || cp_opc_expr (&str, 21, 3) == FAIL) 6030 { 6031 if (!inst.error) 6032 inst.error = BAD_ARGS; 6033 return; 6034 } 6035 6036 if (skip_past_comma (&str) == FAIL 6037 || reg_required_here (&str, 12) == FAIL) 6038 { 6039 if (!inst.error) 6040 inst.error = BAD_ARGS; 6041 return; 6042 } 6043 6044 if (skip_past_comma (&str) == FAIL 6045 || cp_reg_required_here (&str, 16) == FAIL) 6046 { 6047 if (!inst.error) 6048 inst.error = BAD_ARGS; 6049 return; 6050 } 6051 6052 if (skip_past_comma (&str) == FAIL 6053 || cp_reg_required_here (&str, 0) == FAIL) 6054 { 6055 if (!inst.error) 6056 inst.error = BAD_ARGS; 6057 return; 6058 } 6059 6060 if (skip_past_comma (&str) == SUCCESS) 6061 { 6062 if (cp_opc_expr (&str, 5, 3) == FAIL) 6063 { 6064 if (!inst.error) 6065 inst.error = BAD_ARGS; 6066 return; 6067 } 6068 } 6069 6070 end_of_line (str); 6071 return; 6072} 6073 6074static void 6075do_fpa_ctrl (str) 6076 char * str; 6077{ 6078 /* FP control registers. 6079 Format: <WFS|RFS|WFC|RFC>{cond} Rn */ 6080 6081 skip_whitespace (str); 6082 6083 if (reg_required_here (&str, 12) == FAIL) 6084 { 6085 if (!inst.error) 6086 inst.error = BAD_ARGS; 6087 return; 6088 } 6089 6090 end_of_line (str); 6091 return; 6092} 6093 6094static void 6095do_fpa_ldst (str) 6096 char * str; 6097{ 6098 skip_whitespace (str); 6099 6100 if (fp_reg_required_here (&str, 12) == FAIL) 6101 { 6102 if (!inst.error) 6103 inst.error = BAD_ARGS; 6104 return; 6105 } 6106 6107 if (skip_past_comma (&str) == FAIL 6108 || cp_address_required_here (&str, CP_WB_OK) == FAIL) 6109 { 6110 if (!inst.error) 6111 inst.error = BAD_ARGS; 6112 return; 6113 } 6114 6115 end_of_line (str); 6116} 6117 6118static void 6119do_fpa_ldmstm (str) 6120 char * str; 6121{ 6122 int num_regs; 6123 6124 skip_whitespace (str); 6125 6126 if (fp_reg_required_here (&str, 12) == FAIL) 6127 { 6128 if (! inst.error) 6129 inst.error = BAD_ARGS; 6130 return; 6131 } 6132 6133 /* Get Number of registers to transfer. */ 6134 if (skip_past_comma (&str) == FAIL 6135 || my_get_expression (&inst.reloc.exp, &str)) 6136 { 6137 if (! inst.error) 6138 inst.error = _("constant expression expected"); 6139 return; 6140 } 6141 6142 if (inst.reloc.exp.X_op != O_constant) 6143 { 6144 inst.error = _("constant value required for number of registers"); 6145 return; 6146 } 6147 6148 num_regs = inst.reloc.exp.X_add_number; 6149 6150 if (num_regs < 1 || num_regs > 4) 6151 { 6152 inst.error = _("number of registers must be in the range [1:4]"); 6153 return; 6154 } 6155 6156 switch (num_regs) 6157 { 6158 case 1: 6159 inst.instruction |= CP_T_X; 6160 break; 6161 case 2: 6162 inst.instruction |= CP_T_Y; 6163 break; 6164 case 3: 6165 inst.instruction |= CP_T_Y | CP_T_X; 6166 break; 6167 case 4: 6168 break; 6169 default: 6170 abort (); 6171 } 6172 6173 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */ 6174 { 6175 int reg; 6176 int write_back; 6177 int offset; 6178 6179 /* The instruction specified "ea" or "fd", so we can only accept 6180 [Rn]{!}. The instruction does not really support stacking or 6181 unstacking, so we have to emulate these by setting appropriate 6182 bits and offsets. */ 6183 if (skip_past_comma (&str) == FAIL 6184 || *str != '[') 6185 { 6186 if (! inst.error) 6187 inst.error = BAD_ARGS; 6188 return; 6189 } 6190 6191 str++; 6192 skip_whitespace (str); 6193 6194 if ((reg = reg_required_here (&str, 16)) == FAIL) 6195 return; 6196 6197 skip_whitespace (str); 6198 6199 if (*str != ']') 6200 { 6201 inst.error = BAD_ARGS; 6202 return; 6203 } 6204 6205 str++; 6206 if (*str == '!') 6207 { 6208 write_back = 1; 6209 str++; 6210 if (reg == REG_PC) 6211 { 6212 inst.error = 6213 _("r15 not allowed as base register with write-back"); 6214 return; 6215 } 6216 } 6217 else 6218 write_back = 0; 6219 6220 if (inst.instruction & CP_T_Pre) 6221 { 6222 /* Pre-decrement. */ 6223 offset = 3 * num_regs; 6224 if (write_back) 6225 inst.instruction |= CP_T_WB; 6226 } 6227 else 6228 { 6229 /* Post-increment. */ 6230 if (write_back) 6231 { 6232 inst.instruction |= CP_T_WB; 6233 offset = 3 * num_regs; 6234 } 6235 else 6236 { 6237 /* No write-back, so convert this into a standard pre-increment 6238 instruction -- aesthetically more pleasing. */ 6239 inst.instruction |= CP_T_Pre | CP_T_UD; 6240 offset = 0; 6241 } 6242 } 6243 6244 inst.instruction |= offset; 6245 } 6246 else if (skip_past_comma (&str) == FAIL 6247 || cp_address_required_here (&str, CP_WB_OK) == FAIL) 6248 { 6249 if (! inst.error) 6250 inst.error = BAD_ARGS; 6251 return; 6252 } 6253 6254 end_of_line (str); 6255} 6256 6257static void 6258do_fpa_dyadic (str) 6259 char * str; 6260{ 6261 skip_whitespace (str); 6262 6263 if (fp_reg_required_here (&str, 12) == FAIL) 6264 { 6265 if (! inst.error) 6266 inst.error = BAD_ARGS; 6267 return; 6268 } 6269 6270 if (skip_past_comma (&str) == FAIL 6271 || fp_reg_required_here (&str, 16) == FAIL) 6272 { 6273 if (! inst.error) 6274 inst.error = BAD_ARGS; 6275 return; 6276 } 6277 6278 if (skip_past_comma (&str) == FAIL 6279 || fp_op2 (&str) == FAIL) 6280 { 6281 if (! inst.error) 6282 inst.error = BAD_ARGS; 6283 return; 6284 } 6285 6286 end_of_line (str); 6287 return; 6288} 6289 6290static void 6291do_fpa_monadic (str) 6292 char * str; 6293{ 6294 skip_whitespace (str); 6295 6296 if (fp_reg_required_here (&str, 12) == FAIL) 6297 { 6298 if (! inst.error) 6299 inst.error = BAD_ARGS; 6300 return; 6301 } 6302 6303 if (skip_past_comma (&str) == FAIL 6304 || fp_op2 (&str) == FAIL) 6305 { 6306 if (! inst.error) 6307 inst.error = BAD_ARGS; 6308 return; 6309 } 6310 6311 end_of_line (str); 6312 return; 6313} 6314 6315static void 6316do_fpa_cmp (str) 6317 char * str; 6318{ 6319 skip_whitespace (str); 6320 6321 if (fp_reg_required_here (&str, 16) == FAIL) 6322 { 6323 if (! inst.error) 6324 inst.error = BAD_ARGS; 6325 return; 6326 } 6327 6328 if (skip_past_comma (&str) == FAIL 6329 || fp_op2 (&str) == FAIL) 6330 { 6331 if (! inst.error) 6332 inst.error = BAD_ARGS; 6333 return; 6334 } 6335 6336 end_of_line (str); 6337 return; 6338} 6339 6340static void 6341do_fpa_from_reg (str) 6342 char * str; 6343{ 6344 skip_whitespace (str); 6345 6346 if (fp_reg_required_here (&str, 16) == FAIL) 6347 { 6348 if (! inst.error) 6349 inst.error = BAD_ARGS; 6350 return; 6351 } 6352 6353 if (skip_past_comma (&str) == FAIL 6354 || reg_required_here (&str, 12) == FAIL) 6355 { 6356 if (! inst.error) 6357 inst.error = BAD_ARGS; 6358 return; 6359 } 6360 6361 end_of_line (str); 6362 return; 6363} 6364 6365static void 6366do_fpa_to_reg (str) 6367 char * str; 6368{ 6369 skip_whitespace (str); 6370 6371 if (reg_required_here (&str, 12) == FAIL) 6372 return; 6373 6374 if (skip_past_comma (&str) == FAIL 6375 || fp_reg_required_here (&str, 0) == FAIL) 6376 { 6377 if (! inst.error) 6378 inst.error = BAD_ARGS; 6379 return; 6380 } 6381 6382 end_of_line (str); 6383 return; 6384} 6385 6386static int 6387vfp_sp_reg_required_here (str, pos) 6388 char **str; 6389 enum vfp_sp_reg_pos pos; 6390{ 6391 int reg; 6392 char *start = *str; 6393 6394 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL) 6395 { 6396 switch (pos) 6397 { 6398 case VFP_REG_Sd: 6399 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22); 6400 break; 6401 6402 case VFP_REG_Sn: 6403 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7); 6404 break; 6405 6406 case VFP_REG_Sm: 6407 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5); 6408 break; 6409 6410 default: 6411 abort (); 6412 } 6413 return reg; 6414 } 6415 6416 /* In the few cases where we might be able to accept something else 6417 this error can be overridden. */ 6418 inst.error = _(all_reg_maps[REG_TYPE_SN].expected); 6419 6420 /* Restore the start point. */ 6421 *str = start; 6422 return FAIL; 6423} 6424 6425static int 6426vfp_dp_reg_required_here (str, pos) 6427 char **str; 6428 enum vfp_dp_reg_pos pos; 6429{ 6430 int reg; 6431 char *start = *str; 6432 6433 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL) 6434 { 6435 switch (pos) 6436 { 6437 case VFP_REG_Dd: 6438 inst.instruction |= reg << 12; 6439 break; 6440 6441 case VFP_REG_Dn: 6442 inst.instruction |= reg << 16; 6443 break; 6444 6445 case VFP_REG_Dm: 6446 inst.instruction |= reg << 0; 6447 break; 6448 6449 default: 6450 abort (); 6451 } 6452 return reg; 6453 } 6454 6455 /* In the few cases where we might be able to accept something else 6456 this error can be overridden. */ 6457 inst.error = _(all_reg_maps[REG_TYPE_DN].expected); 6458 6459 /* Restore the start point. */ 6460 *str = start; 6461 return FAIL; 6462} 6463 6464static void 6465do_vfp_sp_monadic (str) 6466 char *str; 6467{ 6468 skip_whitespace (str); 6469 6470 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL) 6471 return; 6472 6473 if (skip_past_comma (&str) == FAIL 6474 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL) 6475 { 6476 if (! inst.error) 6477 inst.error = BAD_ARGS; 6478 return; 6479 } 6480 6481 end_of_line (str); 6482 return; 6483} 6484 6485static void 6486do_vfp_dp_monadic (str) 6487 char *str; 6488{ 6489 skip_whitespace (str); 6490 6491 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL) 6492 return; 6493 6494 if (skip_past_comma (&str) == FAIL 6495 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL) 6496 { 6497 if (! inst.error) 6498 inst.error = BAD_ARGS; 6499 return; 6500 } 6501 6502 end_of_line (str); 6503 return; 6504} 6505 6506static void 6507do_vfp_sp_dyadic (str) 6508 char *str; 6509{ 6510 skip_whitespace (str); 6511 6512 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL) 6513 return; 6514 6515 if (skip_past_comma (&str) == FAIL 6516 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL 6517 || skip_past_comma (&str) == FAIL 6518 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL) 6519 { 6520 if (! inst.error) 6521 inst.error = BAD_ARGS; 6522 return; 6523 } 6524 6525 end_of_line (str); 6526 return; 6527} 6528 6529static void 6530do_vfp_dp_dyadic (str) 6531 char *str; 6532{ 6533 skip_whitespace (str); 6534 6535 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL) 6536 return; 6537 6538 if (skip_past_comma (&str) == FAIL 6539 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL 6540 || skip_past_comma (&str) == FAIL 6541 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL) 6542 { 6543 if (! inst.error) 6544 inst.error = BAD_ARGS; 6545 return; 6546 } 6547 6548 end_of_line (str); 6549 return; 6550} 6551 6552static void 6553do_vfp_reg_from_sp (str) 6554 char *str; 6555{ 6556 skip_whitespace (str); 6557 6558 if (reg_required_here (&str, 12) == FAIL) 6559 return; 6560 6561 if (skip_past_comma (&str) == FAIL 6562 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL) 6563 { 6564 if (! inst.error) 6565 inst.error = BAD_ARGS; 6566 return; 6567 } 6568 6569 end_of_line (str); 6570 return; 6571} 6572 6573static void 6574do_vfp_sp_reg2 (str) 6575 char *str; 6576{ 6577 skip_whitespace (str); 6578 6579 if (reg_required_here (&str, 12) == FAIL) 6580 return; 6581 6582 if (skip_past_comma (&str) == FAIL 6583 || reg_required_here (&str, 16) == FAIL 6584 || skip_past_comma (&str) == FAIL) 6585 { 6586 if (! inst.error) 6587 inst.error = BAD_ARGS; 6588 return; 6589 } 6590 6591 /* We require exactly two consecutive SP registers. */ 6592 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2) 6593 { 6594 if (! inst.error) 6595 inst.error = _("only two consecutive VFP SP registers allowed here"); 6596 } 6597 6598 end_of_line (str); 6599 return; 6600} 6601 6602static void 6603do_vfp_sp_from_reg (str) 6604 char *str; 6605{ 6606 skip_whitespace (str); 6607 6608 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL) 6609 return; 6610 6611 if (skip_past_comma (&str) == FAIL 6612 || reg_required_here (&str, 12) == FAIL) 6613 { 6614 if (! inst.error) 6615 inst.error = BAD_ARGS; 6616 return; 6617 } 6618 6619 end_of_line (str); 6620 return; 6621} 6622 6623static void 6624do_vfp_reg_from_dp (str) 6625 char *str; 6626{ 6627 skip_whitespace (str); 6628 6629 if (reg_required_here (&str, 12) == FAIL) 6630 return; 6631 6632 if (skip_past_comma (&str) == FAIL 6633 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL) 6634 { 6635 if (! inst.error) 6636 inst.error = BAD_ARGS; 6637 return; 6638 } 6639 6640 end_of_line (str); 6641 return; 6642} 6643 6644static void 6645do_vfp_reg2_from_dp (str) 6646 char *str; 6647{ 6648 skip_whitespace (str); 6649 6650 if (reg_required_here (&str, 12) == FAIL) 6651 return; 6652 6653 if (skip_past_comma (&str) == FAIL 6654 || reg_required_here (&str, 16) == FAIL 6655 || skip_past_comma (&str) == FAIL 6656 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL) 6657 { 6658 if (! inst.error) 6659 inst.error = BAD_ARGS; 6660 return; 6661 } 6662 6663 end_of_line (str); 6664 return; 6665} 6666 6667static void 6668do_vfp_dp_from_reg (str) 6669 char *str; 6670{ 6671 skip_whitespace (str); 6672 6673 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL) 6674 return; 6675 6676 if (skip_past_comma (&str) == FAIL 6677 || reg_required_here (&str, 12) == FAIL) 6678 { 6679 if (! inst.error) 6680 inst.error = BAD_ARGS; 6681 return; 6682 } 6683 6684 end_of_line (str); 6685 return; 6686} 6687 6688static void 6689do_vfp_dp_from_reg2 (str) 6690 char *str; 6691{ 6692 skip_whitespace (str); 6693 6694 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL) 6695 return; 6696 6697 if (skip_past_comma (&str) == FAIL 6698 || reg_required_here (&str, 12) == FAIL 6699 || skip_past_comma (&str) == FAIL 6700 || reg_required_here (&str, 16)) 6701 { 6702 if (! inst.error) 6703 inst.error = BAD_ARGS; 6704 return; 6705 } 6706 6707 end_of_line (str); 6708 return; 6709} 6710 6711static const struct vfp_reg * 6712vfp_psr_parse (str) 6713 char **str; 6714{ 6715 char *start = *str; 6716 char c; 6717 char *p; 6718 const struct vfp_reg *vreg; 6719 6720 p = start; 6721 6722 /* Find the end of the current token. */ 6723 do 6724 { 6725 c = *p++; 6726 } 6727 while (ISALPHA (c)); 6728 6729 /* Mark it. */ 6730 *--p = 0; 6731 6732 for (vreg = vfp_regs + 0; 6733 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg); 6734 vreg++) 6735 { 6736 if (strcmp (start, vreg->name) == 0) 6737 { 6738 *p = c; 6739 *str = p; 6740 return vreg; 6741 } 6742 } 6743 6744 *p = c; 6745 return NULL; 6746} 6747 6748static int 6749vfp_psr_required_here (str) 6750 char **str; 6751{ 6752 char *start = *str; 6753 const struct vfp_reg *vreg; 6754 6755 vreg = vfp_psr_parse (str); 6756 6757 if (vreg) 6758 { 6759 inst.instruction |= vreg->regno; 6760 return SUCCESS; 6761 } 6762 6763 inst.error = _("VFP system register expected"); 6764 6765 *str = start; 6766 return FAIL; 6767} 6768 6769static void 6770do_vfp_reg_from_ctrl (str) 6771 char *str; 6772{ 6773 skip_whitespace (str); 6774 6775 if (reg_required_here (&str, 12) == FAIL) 6776 return; 6777 6778 if (skip_past_comma (&str) == FAIL 6779 || vfp_psr_required_here (&str) == FAIL) 6780 { 6781 if (! inst.error) 6782 inst.error = BAD_ARGS; 6783 return; 6784 } 6785 6786 end_of_line (str); 6787 return; 6788} 6789 6790static void 6791do_vfp_ctrl_from_reg (str) 6792 char *str; 6793{ 6794 skip_whitespace (str); 6795 6796 if (vfp_psr_required_here (&str) == FAIL) 6797 return; 6798 6799 if (skip_past_comma (&str) == FAIL 6800 || reg_required_here (&str, 12) == FAIL) 6801 { 6802 if (! inst.error) 6803 inst.error = BAD_ARGS; 6804 return; 6805 } 6806 6807 end_of_line (str); 6808 return; 6809} 6810 6811static void 6812do_vfp_sp_ldst (str) 6813 char *str; 6814{ 6815 skip_whitespace (str); 6816 6817 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL) 6818 { 6819 if (!inst.error) 6820 inst.error = BAD_ARGS; 6821 return; 6822 } 6823 6824 if (skip_past_comma (&str) == FAIL 6825 || cp_address_required_here (&str, CP_NO_WB) == FAIL) 6826 { 6827 if (!inst.error) 6828 inst.error = BAD_ARGS; 6829 return; 6830 } 6831 6832 end_of_line (str); 6833 return; 6834} 6835 6836static void 6837do_vfp_dp_ldst (str) 6838 char *str; 6839{ 6840 skip_whitespace (str); 6841 6842 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL) 6843 { 6844 if (!inst.error) 6845 inst.error = BAD_ARGS; 6846 return; 6847 } 6848 6849 if (skip_past_comma (&str) == FAIL 6850 || cp_address_required_here (&str, CP_NO_WB) == FAIL) 6851 { 6852 if (!inst.error) 6853 inst.error = BAD_ARGS; 6854 return; 6855 } 6856 6857 end_of_line (str); 6858 return; 6859} 6860 6861/* Parse and encode a VFP SP register list, storing the initial 6862 register in position POS and returning the range as the result. If 6863 the string is invalid return FAIL (an invalid range). */ 6864static long 6865vfp_sp_reg_list (str, pos) 6866 char **str; 6867 enum vfp_sp_reg_pos pos; 6868{ 6869 long range = 0; 6870 int base_reg = 0; 6871 int new_base; 6872 long base_bits = 0; 6873 int count = 0; 6874 long tempinst; 6875 unsigned long mask = 0; 6876 int warned = 0; 6877 6878 if (**str != '{') 6879 return FAIL; 6880 6881 (*str)++; 6882 skip_whitespace (*str); 6883 6884 tempinst = inst.instruction; 6885 6886 do 6887 { 6888 inst.instruction = 0; 6889 6890 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL) 6891 return FAIL; 6892 6893 if (count == 0 || base_reg > new_base) 6894 { 6895 base_reg = new_base; 6896 base_bits = inst.instruction; 6897 } 6898 6899 if (mask & (1 << new_base)) 6900 { 6901 inst.error = _("invalid register list"); 6902 return FAIL; 6903 } 6904 6905 if ((mask >> new_base) != 0 && ! warned) 6906 { 6907 as_tsktsk (_("register list not in ascending order")); 6908 warned = 1; 6909 } 6910 6911 mask |= 1 << new_base; 6912 count++; 6913 6914 skip_whitespace (*str); 6915 6916 if (**str == '-') /* We have the start of a range expression */ 6917 { 6918 int high_range; 6919 6920 (*str)++; 6921 6922 if ((high_range 6923 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) 6924 == FAIL) 6925 { 6926 inst.error = _(all_reg_maps[REG_TYPE_SN].expected); 6927 return FAIL; 6928 } 6929 6930 if (high_range <= new_base) 6931 { 6932 inst.error = _("register range not in ascending order"); 6933 return FAIL; 6934 } 6935 6936 for (new_base++; new_base <= high_range; new_base++) 6937 { 6938 if (mask & (1 << new_base)) 6939 { 6940 inst.error = _("invalid register list"); 6941 return FAIL; 6942 } 6943 6944 mask |= 1 << new_base; 6945 count++; 6946 } 6947 } 6948 } 6949 while (skip_past_comma (str) != FAIL); 6950 6951 if (**str != '}') 6952 { 6953 inst.error = _("invalid register list"); 6954 return FAIL; 6955 } 6956 6957 (*str)++; 6958 6959 range = count; 6960 6961 /* Sanity check -- should have raised a parse error above. */ 6962 if (count == 0 || count > 32) 6963 abort(); 6964 6965 /* Final test -- the registers must be consecutive. */ 6966 while (count--) 6967 { 6968 if ((mask & (1 << base_reg++)) == 0) 6969 { 6970 inst.error = _("non-contiguous register range"); 6971 return FAIL; 6972 } 6973 } 6974 6975 inst.instruction = tempinst | base_bits; 6976 return range; 6977} 6978 6979static long 6980vfp_dp_reg_list (str) 6981 char **str; 6982{ 6983 long range = 0; 6984 int base_reg = 0; 6985 int new_base; 6986 int count = 0; 6987 long tempinst; 6988 unsigned long mask = 0; 6989 int warned = 0; 6990 6991 if (**str != '{') 6992 return FAIL; 6993 6994 (*str)++; 6995 skip_whitespace (*str); 6996 6997 tempinst = inst.instruction; 6998 6999 do 7000 { 7001 inst.instruction = 0; 7002 7003 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL) 7004 return FAIL; 7005 7006 if (count == 0 || base_reg > new_base) 7007 { 7008 base_reg = new_base; 7009 range = inst.instruction; 7010 } 7011 7012 if (mask & (1 << new_base)) 7013 { 7014 inst.error = _("invalid register list"); 7015 return FAIL; 7016 } 7017 7018 if ((mask >> new_base) != 0 && ! warned) 7019 { 7020 as_tsktsk (_("register list not in ascending order")); 7021 warned = 1; 7022 } 7023 7024 mask |= 1 << new_base; 7025 count++; 7026 7027 skip_whitespace (*str); 7028 7029 if (**str == '-') /* We have the start of a range expression */ 7030 { 7031 int high_range; 7032 7033 (*str)++; 7034 7035 if ((high_range 7036 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) 7037 == FAIL) 7038 { 7039 inst.error = _(all_reg_maps[REG_TYPE_DN].expected); 7040 return FAIL; 7041 } 7042 7043 if (high_range <= new_base) 7044 { 7045 inst.error = _("register range not in ascending order"); 7046 return FAIL; 7047 } 7048 7049 for (new_base++; new_base <= high_range; new_base++) 7050 { 7051 if (mask & (1 << new_base)) 7052 { 7053 inst.error = _("invalid register list"); 7054 return FAIL; 7055 } 7056 7057 mask |= 1 << new_base; 7058 count++; 7059 } 7060 } 7061 } 7062 while (skip_past_comma (str) != FAIL); 7063 7064 if (**str != '}') 7065 { 7066 inst.error = _("invalid register list"); 7067 return FAIL; 7068 } 7069 7070 (*str)++; 7071 7072 range |= 2 * count; 7073 7074 /* Sanity check -- should have raised a parse error above. */ 7075 if (count == 0 || count > 16) 7076 abort(); 7077 7078 /* Final test -- the registers must be consecutive. */ 7079 while (count--) 7080 { 7081 if ((mask & (1 << base_reg++)) == 0) 7082 { 7083 inst.error = _("non-contiguous register range"); 7084 return FAIL; 7085 } 7086 } 7087 7088 inst.instruction = tempinst; 7089 return range; 7090} 7091 7092static void 7093vfp_sp_ldstm(str, ldstm_type) 7094 char *str; 7095 enum vfp_ldstm_type ldstm_type; 7096{ 7097 long range; 7098 7099 skip_whitespace (str); 7100 7101 if (reg_required_here (&str, 16) == FAIL) 7102 return; 7103 7104 skip_whitespace (str); 7105 7106 if (*str == '!') 7107 { 7108 inst.instruction |= WRITE_BACK; 7109 str++; 7110 } 7111 else if (ldstm_type != VFP_LDSTMIA) 7112 { 7113 inst.error = _("this addressing mode requires base-register writeback"); 7114 return; 7115 } 7116 7117 if (skip_past_comma (&str) == FAIL 7118 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL) 7119 { 7120 if (!inst.error) 7121 inst.error = BAD_ARGS; 7122 return; 7123 } 7124 7125 inst.instruction |= range; 7126 end_of_line (str); 7127} 7128 7129static void 7130vfp_dp_ldstm(str, ldstm_type) 7131 char *str; 7132 enum vfp_ldstm_type ldstm_type; 7133{ 7134 long range; 7135 7136 skip_whitespace (str); 7137 7138 if (reg_required_here (&str, 16) == FAIL) 7139 return; 7140 7141 skip_whitespace (str); 7142 7143 if (*str == '!') 7144 { 7145 inst.instruction |= WRITE_BACK; 7146 str++; 7147 } 7148 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX) 7149 { 7150 inst.error = _("this addressing mode requires base-register writeback"); 7151 return; 7152 } 7153 7154 if (skip_past_comma (&str) == FAIL 7155 || (range = vfp_dp_reg_list (&str)) == FAIL) 7156 { 7157 if (!inst.error) 7158 inst.error = BAD_ARGS; 7159 return; 7160 } 7161 7162 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX) 7163 range += 1; 7164 7165 inst.instruction |= range; 7166 end_of_line (str); 7167} 7168 7169static void 7170do_vfp_sp_ldstmia (str) 7171 char *str; 7172{ 7173 vfp_sp_ldstm (str, VFP_LDSTMIA); 7174} 7175 7176static void 7177do_vfp_sp_ldstmdb (str) 7178 char *str; 7179{ 7180 vfp_sp_ldstm (str, VFP_LDSTMDB); 7181} 7182 7183static void 7184do_vfp_dp_ldstmia (str) 7185 char *str; 7186{ 7187 vfp_dp_ldstm (str, VFP_LDSTMIA); 7188} 7189 7190static void 7191do_vfp_dp_ldstmdb (str) 7192 char *str; 7193{ 7194 vfp_dp_ldstm (str, VFP_LDSTMDB); 7195} 7196 7197static void 7198do_vfp_xp_ldstmia (str) 7199 char *str; 7200{ 7201 vfp_dp_ldstm (str, VFP_LDSTMIAX); 7202} 7203 7204static void 7205do_vfp_xp_ldstmdb (str) 7206 char *str; 7207{ 7208 vfp_dp_ldstm (str, VFP_LDSTMDBX); 7209} 7210 7211static void 7212do_vfp_sp_compare_z (str) 7213 char *str; 7214{ 7215 skip_whitespace (str); 7216 7217 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL) 7218 { 7219 if (!inst.error) 7220 inst.error = BAD_ARGS; 7221 return; 7222 } 7223 7224 end_of_line (str); 7225 return; 7226} 7227 7228static void 7229do_vfp_dp_compare_z (str) 7230 char *str; 7231{ 7232 skip_whitespace (str); 7233 7234 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL) 7235 { 7236 if (!inst.error) 7237 inst.error = BAD_ARGS; 7238 return; 7239 } 7240 7241 end_of_line (str); 7242 return; 7243} 7244 7245static void 7246do_vfp_dp_sp_cvt (str) 7247 char *str; 7248{ 7249 skip_whitespace (str); 7250 7251 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL) 7252 return; 7253 7254 if (skip_past_comma (&str) == FAIL 7255 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL) 7256 { 7257 if (! inst.error) 7258 inst.error = BAD_ARGS; 7259 return; 7260 } 7261 7262 end_of_line (str); 7263 return; 7264} 7265 7266static void 7267do_vfp_sp_dp_cvt (str) 7268 char *str; 7269{ 7270 skip_whitespace (str); 7271 7272 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL) 7273 return; 7274 7275 if (skip_past_comma (&str) == FAIL 7276 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL) 7277 { 7278 if (! inst.error) 7279 inst.error = BAD_ARGS; 7280 return; 7281 } 7282 7283 end_of_line (str); 7284 return; 7285} 7286 7287/* Thumb specific routines. */ 7288 7289/* Parse and validate that a register is of the right form, this saves 7290 repeated checking of this information in many similar cases. 7291 Unlike the 32-bit case we do not insert the register into the opcode 7292 here, since the position is often unknown until the full instruction 7293 has been parsed. */ 7294 7295static int 7296thumb_reg (strp, hi_lo) 7297 char ** strp; 7298 int hi_lo; 7299{ 7300 int reg; 7301 7302 if ((reg = reg_required_here (strp, -1)) == FAIL) 7303 return FAIL; 7304 7305 switch (hi_lo) 7306 { 7307 case THUMB_REG_LO: 7308 if (reg > 7) 7309 { 7310 inst.error = _("lo register required"); 7311 return FAIL; 7312 } 7313 break; 7314 7315 case THUMB_REG_HI: 7316 if (reg < 8) 7317 { 7318 inst.error = _("hi register required"); 7319 return FAIL; 7320 } 7321 break; 7322 7323 default: 7324 break; 7325 } 7326 7327 return reg; 7328} 7329 7330/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode 7331 was SUB. */ 7332 7333static void 7334thumb_add_sub (str, subtract) 7335 char * str; 7336 int subtract; 7337{ 7338 int Rd, Rs, Rn = FAIL; 7339 7340 skip_whitespace (str); 7341 7342 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL 7343 || skip_past_comma (&str) == FAIL) 7344 { 7345 if (! inst.error) 7346 inst.error = BAD_ARGS; 7347 return; 7348 } 7349 7350 if (is_immediate_prefix (*str)) 7351 { 7352 Rs = Rd; 7353 str++; 7354 if (my_get_expression (&inst.reloc.exp, &str)) 7355 return; 7356 } 7357 else 7358 { 7359 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL) 7360 return; 7361 7362 if (skip_past_comma (&str) == FAIL) 7363 { 7364 /* Two operand format, shuffle the registers 7365 and pretend there are 3. */ 7366 Rn = Rs; 7367 Rs = Rd; 7368 } 7369 else if (is_immediate_prefix (*str)) 7370 { 7371 str++; 7372 if (my_get_expression (&inst.reloc.exp, &str)) 7373 return; 7374 } 7375 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL) 7376 return; 7377 } 7378 7379 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL; 7380 for the latter case, EXPR contains the immediate that was found. */ 7381 if (Rn != FAIL) 7382 { 7383 /* All register format. */ 7384 if (Rd > 7 || Rs > 7 || Rn > 7) 7385 { 7386 if (Rs != Rd) 7387 { 7388 inst.error = _("dest and source1 must be the same register"); 7389 return; 7390 } 7391 7392 /* Can't do this for SUB. */ 7393 if (subtract) 7394 { 7395 inst.error = _("subtract valid only on lo regs"); 7396 return; 7397 } 7398 7399 inst.instruction = (T_OPCODE_ADD_HI 7400 | (Rd > 7 ? THUMB_H1 : 0) 7401 | (Rn > 7 ? THUMB_H2 : 0)); 7402 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3); 7403 } 7404 else 7405 { 7406 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3; 7407 inst.instruction |= Rd | (Rs << 3) | (Rn << 6); 7408 } 7409 } 7410 else 7411 { 7412 /* Immediate expression, now things start to get nasty. */ 7413 7414 /* First deal with HI regs, only very restricted cases allowed: 7415 Adjusting SP, and using PC or SP to get an address. */ 7416 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP)) 7417 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC)) 7418 { 7419 inst.error = _("invalid Hi register with immediate"); 7420 return; 7421 } 7422 7423 if (inst.reloc.exp.X_op != O_constant) 7424 { 7425 /* Value isn't known yet, all we can do is store all the fragments 7426 we know about in the instruction and let the reloc hacking 7427 work it all out. */ 7428 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs; 7429 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD; 7430 } 7431 else 7432 { 7433 int offset = inst.reloc.exp.X_add_number; 7434 7435 if (subtract) 7436 offset = -offset; 7437 7438 if (offset < 0) 7439 { 7440 offset = -offset; 7441 subtract = 1; 7442 7443 /* Quick check, in case offset is MIN_INT. */ 7444 if (offset < 0) 7445 { 7446 inst.error = _("immediate value out of range"); 7447 return; 7448 } 7449 } 7450 else 7451 subtract = 0; 7452 7453 if (Rd == REG_SP) 7454 { 7455 if (offset & ~0x1fc) 7456 { 7457 inst.error = _("invalid immediate value for stack adjust"); 7458 return; 7459 } 7460 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST; 7461 inst.instruction |= offset >> 2; 7462 } 7463 else if (Rs == REG_PC || Rs == REG_SP) 7464 { 7465 if (subtract 7466 || (offset & ~0x3fc)) 7467 { 7468 inst.error = _("invalid immediate for address calculation"); 7469 return; 7470 } 7471 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC 7472 : T_OPCODE_ADD_SP); 7473 inst.instruction |= (Rd << 8) | (offset >> 2); 7474 } 7475 else if (Rs == Rd) 7476 { 7477 if (offset & ~0xff) 7478 { 7479 inst.error = _("immediate value out of range"); 7480 return; 7481 } 7482 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8; 7483 inst.instruction |= (Rd << 8) | offset; 7484 } 7485 else 7486 { 7487 if (offset & ~0x7) 7488 { 7489 inst.error = _("immediate value out of range"); 7490 return; 7491 } 7492 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3; 7493 inst.instruction |= Rd | (Rs << 3) | (offset << 6); 7494 } 7495 } 7496 } 7497 7498 end_of_line (str); 7499} 7500 7501static void 7502thumb_shift (str, shift) 7503 char * str; 7504 int shift; 7505{ 7506 int Rd, Rs, Rn = FAIL; 7507 7508 skip_whitespace (str); 7509 7510 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL 7511 || skip_past_comma (&str) == FAIL) 7512 { 7513 if (! inst.error) 7514 inst.error = BAD_ARGS; 7515 return; 7516 } 7517 7518 if (is_immediate_prefix (*str)) 7519 { 7520 /* Two operand immediate format, set Rs to Rd. */ 7521 Rs = Rd; 7522 str ++; 7523 if (my_get_expression (&inst.reloc.exp, &str)) 7524 return; 7525 } 7526 else 7527 { 7528 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 7529 return; 7530 7531 if (skip_past_comma (&str) == FAIL) 7532 { 7533 /* Two operand format, shuffle the registers 7534 and pretend there are 3. */ 7535 Rn = Rs; 7536 Rs = Rd; 7537 } 7538 else if (is_immediate_prefix (*str)) 7539 { 7540 str++; 7541 if (my_get_expression (&inst.reloc.exp, &str)) 7542 return; 7543 } 7544 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 7545 return; 7546 } 7547 7548 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL; 7549 for the latter case, EXPR contains the immediate that was found. */ 7550 7551 if (Rn != FAIL) 7552 { 7553 if (Rs != Rd) 7554 { 7555 inst.error = _("source1 and dest must be same register"); 7556 return; 7557 } 7558 7559 switch (shift) 7560 { 7561 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break; 7562 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break; 7563 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break; 7564 } 7565 7566 inst.instruction |= Rd | (Rn << 3); 7567 } 7568 else 7569 { 7570 switch (shift) 7571 { 7572 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break; 7573 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break; 7574 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break; 7575 } 7576 7577 if (inst.reloc.exp.X_op != O_constant) 7578 { 7579 /* Value isn't known yet, create a dummy reloc and let reloc 7580 hacking fix it up. */ 7581 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT; 7582 } 7583 else 7584 { 7585 unsigned shift_value = inst.reloc.exp.X_add_number; 7586 7587 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL)) 7588 { 7589 inst.error = _("invalid immediate for shift"); 7590 return; 7591 } 7592 7593 /* Shifts of zero are handled by converting to LSL. */ 7594 if (shift_value == 0) 7595 inst.instruction = T_OPCODE_LSL_I; 7596 7597 /* Shifts of 32 are encoded as a shift of zero. */ 7598 if (shift_value == 32) 7599 shift_value = 0; 7600 7601 inst.instruction |= shift_value << 6; 7602 } 7603 7604 inst.instruction |= Rd | (Rs << 3); 7605 } 7606 7607 end_of_line (str); 7608} 7609 7610static void 7611thumb_mov_compare (str, move) 7612 char * str; 7613 int move; 7614{ 7615 int Rd, Rs = FAIL; 7616 7617 skip_whitespace (str); 7618 7619 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL 7620 || skip_past_comma (&str) == FAIL) 7621 { 7622 if (! inst.error) 7623 inst.error = BAD_ARGS; 7624 return; 7625 } 7626 7627 if (is_immediate_prefix (*str)) 7628 { 7629 str++; 7630 if (my_get_expression (&inst.reloc.exp, &str)) 7631 return; 7632 } 7633 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL) 7634 return; 7635 7636 if (Rs != FAIL) 7637 { 7638 if (Rs < 8 && Rd < 8) 7639 { 7640 if (move == THUMB_MOVE) 7641 /* A move of two lowregs is encoded as ADD Rd, Rs, #0 7642 since a MOV instruction produces unpredictable results. */ 7643 inst.instruction = T_OPCODE_ADD_I3; 7644 else 7645 inst.instruction = T_OPCODE_CMP_LR; 7646 inst.instruction |= Rd | (Rs << 3); 7647 } 7648 else 7649 { 7650 if (move == THUMB_MOVE) 7651 inst.instruction = T_OPCODE_MOV_HR; 7652 else 7653 inst.instruction = T_OPCODE_CMP_HR; 7654 7655 if (Rd > 7) 7656 inst.instruction |= THUMB_H1; 7657 7658 if (Rs > 7) 7659 inst.instruction |= THUMB_H2; 7660 7661 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3); 7662 } 7663 } 7664 else 7665 { 7666 if (Rd > 7) 7667 { 7668 inst.error = _("only lo regs allowed with immediate"); 7669 return; 7670 } 7671 7672 if (move == THUMB_MOVE) 7673 inst.instruction = T_OPCODE_MOV_I8; 7674 else 7675 inst.instruction = T_OPCODE_CMP_I8; 7676 7677 inst.instruction |= Rd << 8; 7678 7679 if (inst.reloc.exp.X_op != O_constant) 7680 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM; 7681 else 7682 { 7683 unsigned value = inst.reloc.exp.X_add_number; 7684 7685 if (value > 255) 7686 { 7687 inst.error = _("invalid immediate"); 7688 return; 7689 } 7690 7691 inst.instruction |= value; 7692 } 7693 } 7694 7695 end_of_line (str); 7696} 7697 7698static void 7699thumb_load_store (str, load_store, size) 7700 char * str; 7701 int load_store; 7702 int size; 7703{ 7704 int Rd, Rb, Ro = FAIL; 7705 7706 skip_whitespace (str); 7707 7708 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL 7709 || skip_past_comma (&str) == FAIL) 7710 { 7711 if (! inst.error) 7712 inst.error = BAD_ARGS; 7713 return; 7714 } 7715 7716 if (*str == '[') 7717 { 7718 str++; 7719 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL) 7720 return; 7721 7722 if (skip_past_comma (&str) != FAIL) 7723 { 7724 if (is_immediate_prefix (*str)) 7725 { 7726 str++; 7727 if (my_get_expression (&inst.reloc.exp, &str)) 7728 return; 7729 } 7730 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 7731 return; 7732 } 7733 else 7734 { 7735 inst.reloc.exp.X_op = O_constant; 7736 inst.reloc.exp.X_add_number = 0; 7737 } 7738 7739 if (*str != ']') 7740 { 7741 inst.error = _("expected ']'"); 7742 return; 7743 } 7744 str++; 7745 } 7746 else if (*str == '=') 7747 { 7748 if (load_store != THUMB_LOAD) 7749 { 7750 inst.error = _("invalid pseudo operation"); 7751 return; 7752 } 7753 7754 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */ 7755 str++; 7756 7757 skip_whitespace (str); 7758 7759 if (my_get_expression (& inst.reloc.exp, & str)) 7760 return; 7761 7762 end_of_line (str); 7763 7764 if ( inst.reloc.exp.X_op != O_constant 7765 && inst.reloc.exp.X_op != O_symbol) 7766 { 7767 inst.error = "Constant expression expected"; 7768 return; 7769 } 7770 7771 if (inst.reloc.exp.X_op == O_constant 7772 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0)) 7773 { 7774 /* This can be done with a mov instruction. */ 7775 7776 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8); 7777 inst.instruction |= inst.reloc.exp.X_add_number; 7778 return; 7779 } 7780 7781 /* Insert into literal pool. */ 7782 if (add_to_lit_pool () == FAIL) 7783 { 7784 if (!inst.error) 7785 inst.error = "literal pool insertion failed"; 7786 return; 7787 } 7788 7789 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET; 7790 inst.reloc.pc_rel = 1; 7791 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8); 7792 /* Adjust ARM pipeline offset to Thumb. */ 7793 inst.reloc.exp.X_add_number += 4; 7794 7795 return; 7796 } 7797 else 7798 { 7799 if (my_get_expression (&inst.reloc.exp, &str)) 7800 return; 7801 7802 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8); 7803 inst.reloc.pc_rel = 1; 7804 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */ 7805 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET; 7806 end_of_line (str); 7807 return; 7808 } 7809 7810 if (Rb == REG_PC || Rb == REG_SP) 7811 { 7812 if (size != THUMB_WORD) 7813 { 7814 inst.error = _("byte or halfword not valid for base register"); 7815 return; 7816 } 7817 else if (Rb == REG_PC && load_store != THUMB_LOAD) 7818 { 7819 inst.error = _("r15 based store not allowed"); 7820 return; 7821 } 7822 else if (Ro != FAIL) 7823 { 7824 inst.error = _("invalid base register for register offset"); 7825 return; 7826 } 7827 7828 if (Rb == REG_PC) 7829 inst.instruction = T_OPCODE_LDR_PC; 7830 else if (load_store == THUMB_LOAD) 7831 inst.instruction = T_OPCODE_LDR_SP; 7832 else 7833 inst.instruction = T_OPCODE_STR_SP; 7834 7835 inst.instruction |= Rd << 8; 7836 if (inst.reloc.exp.X_op == O_constant) 7837 { 7838 unsigned offset = inst.reloc.exp.X_add_number; 7839 7840 if (offset & ~0x3fc) 7841 { 7842 inst.error = _("invalid offset"); 7843 return; 7844 } 7845 7846 inst.instruction |= offset >> 2; 7847 } 7848 else 7849 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET; 7850 } 7851 else if (Rb > 7) 7852 { 7853 inst.error = _("invalid base register in load/store"); 7854 return; 7855 } 7856 else if (Ro == FAIL) 7857 { 7858 /* Immediate offset. */ 7859 if (size == THUMB_WORD) 7860 inst.instruction = (load_store == THUMB_LOAD 7861 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW); 7862 else if (size == THUMB_HALFWORD) 7863 inst.instruction = (load_store == THUMB_LOAD 7864 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH); 7865 else 7866 inst.instruction = (load_store == THUMB_LOAD 7867 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB); 7868 7869 inst.instruction |= Rd | (Rb << 3); 7870 7871 if (inst.reloc.exp.X_op == O_constant) 7872 { 7873 unsigned offset = inst.reloc.exp.X_add_number; 7874 7875 if (offset & ~(0x1f << size)) 7876 { 7877 inst.error = _("invalid offset"); 7878 return; 7879 } 7880 inst.instruction |= (offset >> size) << 6; 7881 } 7882 else 7883 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET; 7884 } 7885 else 7886 { 7887 /* Register offset. */ 7888 if (size == THUMB_WORD) 7889 inst.instruction = (load_store == THUMB_LOAD 7890 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW); 7891 else if (size == THUMB_HALFWORD) 7892 inst.instruction = (load_store == THUMB_LOAD 7893 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH); 7894 else 7895 inst.instruction = (load_store == THUMB_LOAD 7896 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB); 7897 7898 inst.instruction |= Rd | (Rb << 3) | (Ro << 6); 7899 } 7900 7901 end_of_line (str); 7902} 7903 7904/* A register must be given at this point. 7905 7906 Shift is the place to put it in inst.instruction. 7907 7908 Restores input start point on err. 7909 Returns the reg#, or FAIL. */ 7910 7911static int 7912mav_reg_required_here (str, shift, regtype) 7913 char ** str; 7914 int shift; 7915 enum arm_reg_type regtype; 7916{ 7917 int reg; 7918 char *start = *str; 7919 7920 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL) 7921 { 7922 if (shift >= 0) 7923 inst.instruction |= reg << shift; 7924 7925 return reg; 7926 } 7927 7928 /* Restore the start point. */ 7929 *str = start; 7930 7931 /* In the few cases where we might be able to accept something else 7932 this error can be overridden. */ 7933 inst.error = _(all_reg_maps[regtype].expected); 7934 7935 return FAIL; 7936} 7937 7938/* Cirrus Maverick Instructions. */ 7939 7940/* Wrapper functions. */ 7941 7942static void 7943do_mav_binops_1a (str) 7944 char * str; 7945{ 7946 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF); 7947} 7948 7949static void 7950do_mav_binops_1b (str) 7951 char * str; 7952{ 7953 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD); 7954} 7955 7956static void 7957do_mav_binops_1c (str) 7958 char * str; 7959{ 7960 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX); 7961} 7962 7963static void 7964do_mav_binops_1d (str) 7965 char * str; 7966{ 7967 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF); 7968} 7969 7970static void 7971do_mav_binops_1e (str) 7972 char * str; 7973{ 7974 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD); 7975} 7976 7977static void 7978do_mav_binops_1f (str) 7979 char * str; 7980{ 7981 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF); 7982} 7983 7984static void 7985do_mav_binops_1g (str) 7986 char * str; 7987{ 7988 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD); 7989} 7990 7991static void 7992do_mav_binops_1h (str) 7993 char * str; 7994{ 7995 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX); 7996} 7997 7998static void 7999do_mav_binops_1i (str) 8000 char * str; 8001{ 8002 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX); 8003} 8004 8005static void 8006do_mav_binops_1j (str) 8007 char * str; 8008{ 8009 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX); 8010} 8011 8012static void 8013do_mav_binops_1k (str) 8014 char * str; 8015{ 8016 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX); 8017} 8018 8019static void 8020do_mav_binops_1l (str) 8021 char * str; 8022{ 8023 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF); 8024} 8025 8026static void 8027do_mav_binops_1m (str) 8028 char * str; 8029{ 8030 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD); 8031} 8032 8033static void 8034do_mav_binops_1n (str) 8035 char * str; 8036{ 8037 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX); 8038} 8039 8040static void 8041do_mav_binops_1o (str) 8042 char * str; 8043{ 8044 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX); 8045} 8046 8047static void 8048do_mav_binops_2a (str) 8049 char * str; 8050{ 8051 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN); 8052} 8053 8054static void 8055do_mav_binops_2b (str) 8056 char * str; 8057{ 8058 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN); 8059} 8060 8061static void 8062do_mav_binops_2c (str) 8063 char * str; 8064{ 8065 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN); 8066} 8067 8068static void 8069do_mav_binops_3a (str) 8070 char * str; 8071{ 8072 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX); 8073} 8074 8075static void 8076do_mav_binops_3b (str) 8077 char * str; 8078{ 8079 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX); 8080} 8081 8082static void 8083do_mav_binops_3c (str) 8084 char * str; 8085{ 8086 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX); 8087} 8088 8089static void 8090do_mav_binops_3d (str) 8091 char * str; 8092{ 8093 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX); 8094} 8095 8096static void 8097do_mav_triple_4a (str) 8098 char * str; 8099{ 8100 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN); 8101} 8102 8103static void 8104do_mav_triple_4b (str) 8105 char * str; 8106{ 8107 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN); 8108} 8109 8110static void 8111do_mav_triple_5a (str) 8112 char * str; 8113{ 8114 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF); 8115} 8116 8117static void 8118do_mav_triple_5b (str) 8119 char * str; 8120{ 8121 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD); 8122} 8123 8124static void 8125do_mav_triple_5c (str) 8126 char * str; 8127{ 8128 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX); 8129} 8130 8131static void 8132do_mav_triple_5d (str) 8133 char * str; 8134{ 8135 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX); 8136} 8137 8138static void 8139do_mav_triple_5e (str) 8140 char * str; 8141{ 8142 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF); 8143} 8144 8145static void 8146do_mav_triple_5f (str) 8147 char * str; 8148{ 8149 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD); 8150} 8151 8152static void 8153do_mav_triple_5g (str) 8154 char * str; 8155{ 8156 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX); 8157} 8158 8159static void 8160do_mav_triple_5h (str) 8161 char * str; 8162{ 8163 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX); 8164} 8165 8166static void 8167do_mav_quad_6a (str) 8168 char * str; 8169{ 8170 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX, 8171 REG_TYPE_MVFX); 8172} 8173 8174static void 8175do_mav_quad_6b (str) 8176 char * str; 8177{ 8178 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX, 8179 REG_TYPE_MVFX); 8180} 8181 8182/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */ 8183static void 8184do_mav_dspsc_1 (str) 8185 char * str; 8186{ 8187 skip_whitespace (str); 8188 8189 /* cfmvsc32. */ 8190 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL 8191 || skip_past_comma (&str) == FAIL 8192 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL) 8193 { 8194 if (!inst.error) 8195 inst.error = BAD_ARGS; 8196 8197 return; 8198 } 8199 8200 end_of_line (str); 8201} 8202 8203/* cfmv32sc<cond> MVFX[15:0],DSPSC. */ 8204static void 8205do_mav_dspsc_2 (str) 8206 char * str; 8207{ 8208 skip_whitespace (str); 8209 8210 /* cfmv32sc. */ 8211 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL 8212 || skip_past_comma (&str) == FAIL 8213 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL) 8214 { 8215 if (!inst.error) 8216 inst.error = BAD_ARGS; 8217 8218 return; 8219 } 8220 8221 end_of_line (str); 8222} 8223 8224static void 8225do_mav_shift_1 (str) 8226 char * str; 8227{ 8228 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX); 8229} 8230 8231static void 8232do_mav_shift_2 (str) 8233 char * str; 8234{ 8235 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX); 8236} 8237 8238static void 8239do_mav_ldst_1 (str) 8240 char * str; 8241{ 8242 do_mav_ldst (str, REG_TYPE_MVF); 8243} 8244 8245static void 8246do_mav_ldst_2 (str) 8247 char * str; 8248{ 8249 do_mav_ldst (str, REG_TYPE_MVD); 8250} 8251 8252static void 8253do_mav_ldst_3 (str) 8254 char * str; 8255{ 8256 do_mav_ldst (str, REG_TYPE_MVFX); 8257} 8258 8259static void 8260do_mav_ldst_4 (str) 8261 char * str; 8262{ 8263 do_mav_ldst (str, REG_TYPE_MVDX); 8264} 8265 8266/* Isnsn like "foo X,Y". */ 8267 8268static void 8269do_mav_binops (str, mode, reg0, reg1) 8270 char * str; 8271 int mode; 8272 enum arm_reg_type reg0; 8273 enum arm_reg_type reg1; 8274{ 8275 int shift0, shift1; 8276 8277 shift0 = mode & 0xff; 8278 shift1 = (mode >> 8) & 0xff; 8279 8280 skip_whitespace (str); 8281 8282 if (mav_reg_required_here (&str, shift0, reg0) == FAIL 8283 || skip_past_comma (&str) == FAIL 8284 || mav_reg_required_here (&str, shift1, reg1) == FAIL) 8285 { 8286 if (!inst.error) 8287 inst.error = BAD_ARGS; 8288 } 8289 else 8290 end_of_line (str); 8291} 8292 8293/* Isnsn like "foo X,Y,Z". */ 8294 8295static void 8296do_mav_triple (str, mode, reg0, reg1, reg2) 8297 char * str; 8298 int mode; 8299 enum arm_reg_type reg0; 8300 enum arm_reg_type reg1; 8301 enum arm_reg_type reg2; 8302{ 8303 int shift0, shift1, shift2; 8304 8305 shift0 = mode & 0xff; 8306 shift1 = (mode >> 8) & 0xff; 8307 shift2 = (mode >> 16) & 0xff; 8308 8309 skip_whitespace (str); 8310 8311 if (mav_reg_required_here (&str, shift0, reg0) == FAIL 8312 || skip_past_comma (&str) == FAIL 8313 || mav_reg_required_here (&str, shift1, reg1) == FAIL 8314 || skip_past_comma (&str) == FAIL 8315 || mav_reg_required_here (&str, shift2, reg2) == FAIL) 8316 { 8317 if (!inst.error) 8318 inst.error = BAD_ARGS; 8319 } 8320 else 8321 end_of_line (str); 8322} 8323 8324/* Isnsn like "foo W,X,Y,Z". 8325 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */ 8326 8327static void 8328do_mav_quad (str, mode, reg0, reg1, reg2, reg3) 8329 char * str; 8330 int mode; 8331 enum arm_reg_type reg0; 8332 enum arm_reg_type reg1; 8333 enum arm_reg_type reg2; 8334 enum arm_reg_type reg3; 8335{ 8336 int shift0, shift1, shift2, shift3; 8337 8338 shift0= mode & 0xff; 8339 shift1 = (mode >> 8) & 0xff; 8340 shift2 = (mode >> 16) & 0xff; 8341 shift3 = (mode >> 24) & 0xff; 8342 8343 skip_whitespace (str); 8344 8345 if (mav_reg_required_here (&str, shift0, reg0) == FAIL 8346 || skip_past_comma (&str) == FAIL 8347 || mav_reg_required_here (&str, shift1, reg1) == FAIL 8348 || skip_past_comma (&str) == FAIL 8349 || mav_reg_required_here (&str, shift2, reg2) == FAIL 8350 || skip_past_comma (&str) == FAIL 8351 || mav_reg_required_here (&str, shift3, reg3) == FAIL) 8352 { 8353 if (!inst.error) 8354 inst.error = BAD_ARGS; 8355 } 8356 else 8357 end_of_line (str); 8358} 8359 8360/* Maverick shift immediate instructions. 8361 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0]. 8362 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */ 8363 8364static void 8365do_mav_shift (str, reg0, reg1) 8366 char * str; 8367 enum arm_reg_type reg0; 8368 enum arm_reg_type reg1; 8369{ 8370 int error; 8371 int imm, neg = 0; 8372 8373 skip_whitespace (str); 8374 8375 error = 0; 8376 8377 if (mav_reg_required_here (&str, 12, reg0) == FAIL 8378 || skip_past_comma (&str) == FAIL 8379 || mav_reg_required_here (&str, 16, reg1) == FAIL 8380 || skip_past_comma (&str) == FAIL) 8381 { 8382 if (!inst.error) 8383 inst.error = BAD_ARGS; 8384 return; 8385 } 8386 8387 /* Calculate the immediate operand. 8388 The operand is a 7bit signed number. */ 8389 skip_whitespace (str); 8390 8391 if (*str == '#') 8392 ++str; 8393 8394 if (!ISDIGIT (*str) && *str != '-') 8395 { 8396 inst.error = _("expecting immediate, 7bit operand"); 8397 return; 8398 } 8399 8400 if (*str == '-') 8401 { 8402 neg = 1; 8403 ++str; 8404 } 8405 8406 for (imm = 0; *str && ISDIGIT (*str); ++str) 8407 imm = imm * 10 + *str - '0'; 8408 8409 if (imm > 64) 8410 { 8411 inst.error = _("immediate out of range"); 8412 return; 8413 } 8414 8415 /* Make negative imm's into 7bit signed numbers. */ 8416 if (neg) 8417 { 8418 imm = -imm; 8419 imm &= 0x0000007f; 8420 } 8421 8422 /* Bits 0-3 of the insn should have bits 0-3 of the immediate. 8423 Bits 5-7 of the insn should have bits 4-6 of the immediate. 8424 Bit 4 should be 0. */ 8425 imm = (imm & 0xf) | ((imm & 0x70) << 1); 8426 8427 inst.instruction |= imm; 8428 end_of_line (str); 8429} 8430 8431static int 8432mav_parse_offset (str, negative) 8433 char ** str; 8434 int *negative; 8435{ 8436 char * p = *str; 8437 int offset; 8438 8439 *negative = 0; 8440 8441 skip_whitespace (p); 8442 8443 if (*p == '#') 8444 ++p; 8445 8446 if (*p == '-') 8447 { 8448 *negative = 1; 8449 ++p; 8450 } 8451 8452 if (!ISDIGIT (*p)) 8453 { 8454 inst.error = _("offset expected"); 8455 return 0; 8456 } 8457 8458 for (offset = 0; *p && ISDIGIT (*p); ++p) 8459 offset = offset * 10 + *p - '0'; 8460 8461 if (offset > 0xff) 8462 { 8463 inst.error = _("offset out of range"); 8464 return 0; 8465 } 8466 8467 *str = p; 8468 8469 return *negative ? -offset : offset; 8470} 8471 8472/* Maverick load/store instructions. 8473 <insn><cond> CRd,[Rn,<offset>]{!}. 8474 <insn><cond> CRd,[Rn],<offset>. */ 8475 8476static void 8477do_mav_ldst (str, reg0) 8478 char * str; 8479 enum arm_reg_type reg0; 8480{ 8481 int offset, negative; 8482 8483 skip_whitespace (str); 8484 8485 if (mav_reg_required_here (&str, 12, reg0) == FAIL 8486 || skip_past_comma (&str) == FAIL 8487 || *str++ != '[' 8488 || reg_required_here (&str, 16) == FAIL) 8489 goto fail_ldst; 8490 8491 if (skip_past_comma (&str) == SUCCESS) 8492 { 8493 /* You are here: "<offset>]{!}". */ 8494 inst.instruction |= PRE_INDEX; 8495 8496 offset = mav_parse_offset (&str, &negative); 8497 8498 if (inst.error) 8499 return; 8500 8501 if (*str++ != ']') 8502 { 8503 inst.error = _("missing ]"); 8504 return; 8505 } 8506 8507 if (*str == '!') 8508 { 8509 inst.instruction |= WRITE_BACK; 8510 ++str; 8511 } 8512 } 8513 else 8514 { 8515 /* You are here: "], <offset>". */ 8516 if (*str++ != ']') 8517 { 8518 inst.error = _("missing ]"); 8519 return; 8520 } 8521 8522 if (skip_past_comma (&str) == FAIL 8523 || (offset = mav_parse_offset (&str, &negative), inst.error)) 8524 goto fail_ldst; 8525 8526 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */ 8527 } 8528 8529 if (negative) 8530 offset = -offset; 8531 else 8532 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */ 8533 8534 inst.instruction |= offset >> 2; 8535 end_of_line (str); 8536 return; 8537 8538fail_ldst: 8539 if (!inst.error) 8540 inst.error = BAD_ARGS; 8541 return; 8542} 8543 8544static void 8545do_t_nop (str) 8546 char * str; 8547{ 8548 /* Do nothing. */ 8549 end_of_line (str); 8550 return; 8551} 8552 8553/* Handle the Format 4 instructions that do not have equivalents in other 8554 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL, 8555 BIC and MVN. */ 8556 8557static void 8558do_t_arit (str) 8559 char * str; 8560{ 8561 int Rd, Rs, Rn; 8562 8563 skip_whitespace (str); 8564 8565 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL 8566 || skip_past_comma (&str) == FAIL 8567 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 8568 { 8569 inst.error = BAD_ARGS; 8570 return; 8571 } 8572 8573 if (skip_past_comma (&str) != FAIL) 8574 { 8575 /* Three operand format not allowed for TST, CMN, NEG and MVN. 8576 (It isn't allowed for CMP either, but that isn't handled by this 8577 function.) */ 8578 if (inst.instruction == T_OPCODE_TST 8579 || inst.instruction == T_OPCODE_CMN 8580 || inst.instruction == T_OPCODE_NEG 8581 || inst.instruction == T_OPCODE_MVN) 8582 { 8583 inst.error = BAD_ARGS; 8584 return; 8585 } 8586 8587 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 8588 return; 8589 8590 if (Rs != Rd) 8591 { 8592 inst.error = _("dest and source1 must be the same register"); 8593 return; 8594 } 8595 Rs = Rn; 8596 } 8597 8598 if (inst.instruction == T_OPCODE_MUL 8599 && Rs == Rd) 8600 as_tsktsk (_("Rs and Rd must be different in MUL")); 8601 8602 inst.instruction |= Rd | (Rs << 3); 8603 end_of_line (str); 8604} 8605 8606static void 8607do_t_add (str) 8608 char * str; 8609{ 8610 thumb_add_sub (str, 0); 8611} 8612 8613static void 8614do_t_asr (str) 8615 char * str; 8616{ 8617 thumb_shift (str, THUMB_ASR); 8618} 8619 8620static void 8621do_t_branch9 (str) 8622 char * str; 8623{ 8624 if (my_get_expression (&inst.reloc.exp, &str)) 8625 return; 8626 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9; 8627 inst.reloc.pc_rel = 1; 8628 end_of_line (str); 8629} 8630 8631static void 8632do_t_branch12 (str) 8633 char * str; 8634{ 8635 if (my_get_expression (&inst.reloc.exp, &str)) 8636 return; 8637 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12; 8638 inst.reloc.pc_rel = 1; 8639 end_of_line (str); 8640} 8641 8642/* Find the real, Thumb encoded start of a Thumb function. */ 8643 8644static symbolS * 8645find_real_start (symbolP) 8646 symbolS * symbolP; 8647{ 8648 char * real_start; 8649 const char * name = S_GET_NAME (symbolP); 8650 symbolS * new_target; 8651 8652 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */ 8653#define STUB_NAME ".real_start_of" 8654 8655 if (name == NULL) 8656 abort (); 8657 8658 /* Names that start with '.' are local labels, not function entry points. 8659 The compiler may generate BL instructions to these labels because it 8660 needs to perform a branch to a far away location. */ 8661 if (name[0] == '.') 8662 return symbolP; 8663 8664 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1); 8665 sprintf (real_start, "%s%s", STUB_NAME, name); 8666 8667 new_target = symbol_find (real_start); 8668 8669 if (new_target == NULL) 8670 { 8671 as_warn ("Failed to find real start of function: %s\n", name); 8672 new_target = symbolP; 8673 } 8674 8675 free (real_start); 8676 8677 return new_target; 8678} 8679 8680static void 8681do_t_branch23 (str) 8682 char * str; 8683{ 8684 if (my_get_expression (& inst.reloc.exp, & str)) 8685 return; 8686 8687 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23; 8688 inst.reloc.pc_rel = 1; 8689 end_of_line (str); 8690 8691 /* If the destination of the branch is a defined symbol which does not have 8692 the THUMB_FUNC attribute, then we must be calling a function which has 8693 the (interfacearm) attribute. We look for the Thumb entry point to that 8694 function and change the branch to refer to that function instead. */ 8695 if ( inst.reloc.exp.X_op == O_symbol 8696 && inst.reloc.exp.X_add_symbol != NULL 8697 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol) 8698 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol)) 8699 inst.reloc.exp.X_add_symbol = 8700 find_real_start (inst.reloc.exp.X_add_symbol); 8701} 8702 8703static void 8704do_t_bx (str) 8705 char * str; 8706{ 8707 int reg; 8708 8709 skip_whitespace (str); 8710 8711 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL) 8712 return; 8713 8714 /* This sets THUMB_H2 from the top bit of reg. */ 8715 inst.instruction |= reg << 3; 8716 8717 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc 8718 should cause the alignment to be checked once it is known. This is 8719 because BX PC only works if the instruction is word aligned. */ 8720 8721 end_of_line (str); 8722} 8723 8724static void 8725do_t_compare (str) 8726 char * str; 8727{ 8728 thumb_mov_compare (str, THUMB_COMPARE); 8729} 8730 8731static void 8732do_t_ldmstm (str) 8733 char * str; 8734{ 8735 int Rb; 8736 long range; 8737 8738 skip_whitespace (str); 8739 8740 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL) 8741 return; 8742 8743 if (*str != '!') 8744 as_warn (_("inserted missing '!': load/store multiple always writes back base register")); 8745 else 8746 str++; 8747 8748 if (skip_past_comma (&str) == FAIL 8749 || (range = reg_list (&str)) == FAIL) 8750 { 8751 if (! inst.error) 8752 inst.error = BAD_ARGS; 8753 return; 8754 } 8755 8756 if (inst.reloc.type != BFD_RELOC_NONE) 8757 { 8758 /* This really doesn't seem worth it. */ 8759 inst.reloc.type = BFD_RELOC_NONE; 8760 inst.error = _("expression too complex"); 8761 return; 8762 } 8763 8764 if (range & ~0xff) 8765 { 8766 inst.error = _("only lo-regs valid in load/store multiple"); 8767 return; 8768 } 8769 8770 inst.instruction |= (Rb << 8) | range; 8771 end_of_line (str); 8772} 8773 8774static void 8775do_t_ldr (str) 8776 char * str; 8777{ 8778 thumb_load_store (str, THUMB_LOAD, THUMB_WORD); 8779} 8780 8781static void 8782do_t_ldrb (str) 8783 char * str; 8784{ 8785 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE); 8786} 8787 8788static void 8789do_t_ldrh (str) 8790 char * str; 8791{ 8792 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD); 8793} 8794 8795static void 8796do_t_lds (str) 8797 char * str; 8798{ 8799 int Rd, Rb, Ro; 8800 8801 skip_whitespace (str); 8802 8803 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL 8804 || skip_past_comma (&str) == FAIL 8805 || *str++ != '[' 8806 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL 8807 || skip_past_comma (&str) == FAIL 8808 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL 8809 || *str++ != ']') 8810 { 8811 if (! inst.error) 8812 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]"); 8813 return; 8814 } 8815 8816 inst.instruction |= Rd | (Rb << 3) | (Ro << 6); 8817 end_of_line (str); 8818} 8819 8820static void 8821do_t_lsl (str) 8822 char * str; 8823{ 8824 thumb_shift (str, THUMB_LSL); 8825} 8826 8827static void 8828do_t_lsr (str) 8829 char * str; 8830{ 8831 thumb_shift (str, THUMB_LSR); 8832} 8833 8834static void 8835do_t_mov (str) 8836 char * str; 8837{ 8838 thumb_mov_compare (str, THUMB_MOVE); 8839} 8840 8841static void 8842do_t_push_pop (str) 8843 char * str; 8844{ 8845 long range; 8846 8847 skip_whitespace (str); 8848 8849 if ((range = reg_list (&str)) == FAIL) 8850 { 8851 if (! inst.error) 8852 inst.error = BAD_ARGS; 8853 return; 8854 } 8855 8856 if (inst.reloc.type != BFD_RELOC_NONE) 8857 { 8858 /* This really doesn't seem worth it. */ 8859 inst.reloc.type = BFD_RELOC_NONE; 8860 inst.error = _("expression too complex"); 8861 return; 8862 } 8863 8864 if (range & ~0xff) 8865 { 8866 if ((inst.instruction == T_OPCODE_PUSH 8867 && (range & ~0xff) == 1 << REG_LR) 8868 || (inst.instruction == T_OPCODE_POP 8869 && (range & ~0xff) == 1 << REG_PC)) 8870 { 8871 inst.instruction |= THUMB_PP_PC_LR; 8872 range &= 0xff; 8873 } 8874 else 8875 { 8876 inst.error = _("invalid register list to push/pop instruction"); 8877 return; 8878 } 8879 } 8880 8881 inst.instruction |= range; 8882 end_of_line (str); 8883} 8884 8885static void 8886do_t_str (str) 8887 char * str; 8888{ 8889 thumb_load_store (str, THUMB_STORE, THUMB_WORD); 8890} 8891 8892static void 8893do_t_strb (str) 8894 char * str; 8895{ 8896 thumb_load_store (str, THUMB_STORE, THUMB_BYTE); 8897} 8898 8899static void 8900do_t_strh (str) 8901 char * str; 8902{ 8903 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD); 8904} 8905 8906static void 8907do_t_sub (str) 8908 char * str; 8909{ 8910 thumb_add_sub (str, 1); 8911} 8912 8913static void 8914do_t_swi (str) 8915 char * str; 8916{ 8917 skip_whitespace (str); 8918 8919 if (my_get_expression (&inst.reloc.exp, &str)) 8920 return; 8921 8922 inst.reloc.type = BFD_RELOC_ARM_SWI; 8923 end_of_line (str); 8924 return; 8925} 8926 8927static void 8928do_t_adr (str) 8929 char * str; 8930{ 8931 int reg; 8932 8933 /* This is a pseudo-op of the form "adr rd, label" to be converted 8934 into a relative address of the form "add rd, pc, #label-.-4". */ 8935 skip_whitespace (str); 8936 8937 /* Store Rd in temporary location inside instruction. */ 8938 if ((reg = reg_required_here (&str, 4)) == FAIL 8939 || (reg > 7) /* For Thumb reg must be r0..r7. */ 8940 || skip_past_comma (&str) == FAIL 8941 || my_get_expression (&inst.reloc.exp, &str)) 8942 { 8943 if (!inst.error) 8944 inst.error = BAD_ARGS; 8945 return; 8946 } 8947 8948 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD; 8949 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */ 8950 inst.reloc.pc_rel = 1; 8951 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */ 8952 8953 end_of_line (str); 8954} 8955 8956static void 8957insert_reg (r, htab) 8958 const struct reg_entry *r; 8959 struct hash_control *htab; 8960{ 8961 int len = strlen (r->name) + 2; 8962 char * buf = (char *) xmalloc (len); 8963 char * buf2 = (char *) xmalloc (len); 8964 int i = 0; 8965 8966#ifdef REGISTER_PREFIX 8967 buf[i++] = REGISTER_PREFIX; 8968#endif 8969 8970 strcpy (buf + i, r->name); 8971 8972 for (i = 0; buf[i]; i++) 8973 buf2[i] = TOUPPER (buf[i]); 8974 8975 buf2[i] = '\0'; 8976 8977 hash_insert (htab, buf, (PTR) r); 8978 hash_insert (htab, buf2, (PTR) r); 8979} 8980 8981static void 8982build_reg_hsh (map) 8983 struct reg_map *map; 8984{ 8985 const struct reg_entry *r; 8986 8987 if ((map->htab = hash_new ()) == NULL) 8988 as_fatal (_("virtual memory exhausted")); 8989 8990 for (r = map->names; r->name != NULL; r++) 8991 insert_reg (r, map->htab); 8992} 8993 8994static void 8995insert_reg_alias (str, regnum, htab) 8996 char *str; 8997 int regnum; 8998 struct hash_control *htab; 8999{ 9000 struct reg_entry *new = 9001 (struct reg_entry *) xmalloc (sizeof (struct reg_entry)); 9002 char *name = xmalloc (strlen (str) + 1); 9003 strcpy (name, str); 9004 9005 new->name = name; 9006 new->number = regnum; 9007 9008 hash_insert (htab, name, (PTR) new); 9009} 9010 9011/* Look for the .req directive. This is of the form: 9012 9013 newname .req existing_name 9014 9015 If we find one, or if it looks sufficiently like one that we want to 9016 handle any error here, return non-zero. Otherwise return zero. */ 9017static int 9018create_register_alias (newname, p) 9019 char *newname; 9020 char *p; 9021{ 9022 char *q; 9023 char c; 9024 9025 q = p; 9026 skip_whitespace (q); 9027 9028 c = *p; 9029 *p = '\0'; 9030 9031 if (*q && !strncmp (q, ".req ", 5)) 9032 { 9033 char *copy_of_str; 9034 char *r; 9035 9036#ifdef IGNORE_OPCODE_CASE 9037 newname = original_case_string; 9038#endif 9039 copy_of_str = newname; 9040 9041 q += 4; 9042 skip_whitespace (q); 9043 9044 for (r = q; *r != '\0'; r++) 9045 if (*r == ' ') 9046 break; 9047 9048 if (r != q) 9049 { 9050 enum arm_reg_type new_type, old_type; 9051 int old_regno; 9052 char d = *r; 9053 9054 *r = '\0'; 9055 old_type = arm_reg_parse_any (q); 9056 *r = d; 9057 9058 new_type = arm_reg_parse_any (newname); 9059 9060 if (new_type == REG_TYPE_MAX) 9061 { 9062 if (old_type != REG_TYPE_MAX) 9063 { 9064 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab); 9065 insert_reg_alias (newname, old_regno, 9066 all_reg_maps[old_type].htab); 9067 } 9068 else 9069 as_warn (_("register '%s' does not exist\n"), q); 9070 } 9071 else if (old_type == REG_TYPE_MAX) 9072 { 9073 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"), 9074 copy_of_str, q); 9075 } 9076 else 9077 { 9078 /* Do not warn about redefinitions to the same alias. */ 9079 if (new_type != old_type 9080 || (arm_reg_parse (&q, all_reg_maps[old_type].htab) 9081 != arm_reg_parse (&q, all_reg_maps[new_type].htab))) 9082 as_warn (_("ignoring redefinition of register alias '%s'"), 9083 copy_of_str); 9084 9085 } 9086 } 9087 else 9088 as_warn (_("ignoring incomplete .req pseuso op")); 9089 9090 *p = c; 9091 return 1; 9092 } 9093 *p = c; 9094 return 0; 9095} 9096 9097static void 9098set_constant_flonums () 9099{ 9100 int i; 9101 9102 for (i = 0; i < NUM_FLOAT_VALS; i++) 9103 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL) 9104 abort (); 9105} 9106 9107/* Iterate over the base tables to create the instruction patterns. */ 9108static void 9109build_arm_ops_hsh () 9110{ 9111 unsigned int i; 9112 unsigned int j; 9113 static struct obstack insn_obstack; 9114 9115 obstack_begin (&insn_obstack, 4000); 9116 9117 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++) 9118 { 9119 const struct asm_opcode *insn = insns + i; 9120 9121 if (insn->cond_offset != 0) 9122 { 9123 /* Insn supports conditional execution. Build the varaints 9124 and insert them in the hash table. */ 9125 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++) 9126 { 9127 unsigned len = strlen (insn->template); 9128 struct asm_opcode *new; 9129 char *template; 9130 9131 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode)); 9132 /* All condition codes are two characters. */ 9133 template = obstack_alloc (&insn_obstack, len + 3); 9134 9135 strncpy (template, insn->template, insn->cond_offset); 9136 strcpy (template + insn->cond_offset, conds[j].template); 9137 if (len > insn->cond_offset) 9138 strcpy (template + insn->cond_offset + 2, 9139 insn->template + insn->cond_offset); 9140 new->template = template; 9141 new->cond_offset = 0; 9142 new->variant = insn->variant; 9143 new->parms = insn->parms; 9144 new->value = (insn->value & ~COND_MASK) | conds[j].value; 9145 9146 hash_insert (arm_ops_hsh, new->template, (PTR) new); 9147 } 9148 } 9149 /* Finally, insert the unconditional insn in the table directly; 9150 no need to build a copy. */ 9151 hash_insert (arm_ops_hsh, insn->template, (PTR) insn); 9152 } 9153} 9154 9155void 9156md_begin () 9157{ 9158 unsigned mach; 9159 unsigned int i; 9160 9161 if ( (arm_ops_hsh = hash_new ()) == NULL 9162 || (arm_tops_hsh = hash_new ()) == NULL 9163 || (arm_cond_hsh = hash_new ()) == NULL 9164 || (arm_shift_hsh = hash_new ()) == NULL 9165 || (arm_psr_hsh = hash_new ()) == NULL) 9166 as_fatal (_("virtual memory exhausted")); 9167 9168 build_arm_ops_hsh (); 9169 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++) 9170 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i)); 9171 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++) 9172 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i)); 9173 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++) 9174 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i)); 9175 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++) 9176 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i)); 9177 9178 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++) 9179 build_reg_hsh (all_reg_maps + i); 9180 9181 set_constant_flonums (); 9182 9183 /* Set the cpu variant based on the command-line options. We prefer 9184 -mcpu= over -march= if both are set (as for GCC); and we prefer 9185 -mfpu= over any other way of setting the floating point unit. 9186 Use of legacy options with new options are faulted. */ 9187 if (legacy_cpu != -1) 9188 { 9189 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1) 9190 as_bad (_("use of old and new-style options to set CPU type")); 9191 9192 mcpu_cpu_opt = legacy_cpu; 9193 } 9194 else if (mcpu_cpu_opt == -1) 9195 mcpu_cpu_opt = march_cpu_opt; 9196 9197 if (legacy_fpu != -1) 9198 { 9199 if (mfpu_opt != -1) 9200 as_bad (_("use of old and new-style options to set FPU type")); 9201 9202 mfpu_opt = legacy_fpu; 9203 } 9204 else if (mfpu_opt == -1) 9205 { 9206 if (mcpu_fpu_opt != -1) 9207 mfpu_opt = mcpu_fpu_opt; 9208 else 9209 mfpu_opt = march_fpu_opt; 9210 } 9211 9212 if (mfpu_opt == -1) 9213 { 9214 if (mcpu_cpu_opt == -1) 9215 mfpu_opt = FPU_DEFAULT; 9216 else if (mcpu_cpu_opt & ARM_EXT_V5) 9217 mfpu_opt = FPU_ARCH_VFP_V2; 9218 else 9219 mfpu_opt = FPU_ARCH_FPA; 9220 } 9221 9222 if (mcpu_cpu_opt == -1) 9223 mcpu_cpu_opt = CPU_DEFAULT; 9224 9225 cpu_variant = mcpu_cpu_opt | mfpu_opt; 9226 9227#if defined OBJ_COFF || defined OBJ_ELF 9228 { 9229 unsigned int flags = 0; 9230 9231 /* Set the flags in the private structure. */ 9232 if (uses_apcs_26) flags |= F_APCS26; 9233 if (support_interwork) flags |= F_INTERWORK; 9234 if (uses_apcs_float) flags |= F_APCS_FLOAT; 9235 if (pic_code) flags |= F_PIC; 9236 if ((cpu_variant & FPU_ANY) == FPU_NONE 9237 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */ 9238 flags |= F_SOFT_FLOAT; 9239 /* Using VFP conventions (even if soft-float). */ 9240 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT; 9241 9242 9243 bfd_set_private_flags (stdoutput, flags); 9244 9245 /* We have run out flags in the COFF header to encode the 9246 status of ATPCS support, so instead we create a dummy, 9247 empty, debug section called .arm.atpcs. */ 9248 if (atpcs) 9249 { 9250 asection * sec; 9251 9252 sec = bfd_make_section (stdoutput, ".arm.atpcs"); 9253 9254 if (sec != NULL) 9255 { 9256 bfd_set_section_flags 9257 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */); 9258 bfd_set_section_size (stdoutput, sec, 0); 9259 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0); 9260 } 9261 } 9262 } 9263#endif 9264 9265 /* Record the CPU type as well. */ 9266 switch (cpu_variant & ARM_CPU_MASK) 9267 { 9268 case ARM_2: 9269 mach = bfd_mach_arm_2; 9270 break; 9271 9272 case ARM_3: /* Also ARM_250. */ 9273 mach = bfd_mach_arm_2a; 9274 break; 9275 9276 case ARM_6: /* Also ARM_7. */ 9277 mach = bfd_mach_arm_3; 9278 break; 9279 9280 default: 9281 mach = bfd_mach_arm_4; 9282 break; 9283 } 9284 9285 /* Catch special cases. */ 9286 if (cpu_variant & ARM_CEXT_XSCALE) 9287 mach = bfd_mach_arm_XScale; 9288 else if (cpu_variant & ARM_EXT_V5E) 9289 mach = bfd_mach_arm_5TE; 9290 else if (cpu_variant & ARM_EXT_V5) 9291 { 9292 if (cpu_variant & ARM_EXT_V4T) 9293 mach = bfd_mach_arm_5T; 9294 else 9295 mach = bfd_mach_arm_5; 9296 } 9297 else if (cpu_variant & ARM_EXT_V4) 9298 { 9299 if (cpu_variant & ARM_EXT_V4T) 9300 mach = bfd_mach_arm_4T; 9301 else 9302 mach = bfd_mach_arm_4; 9303 } 9304 else if (cpu_variant & ARM_EXT_V3M) 9305 mach = bfd_mach_arm_3M; 9306 9307 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach); 9308} 9309 9310/* Turn an integer of n bytes (in val) into a stream of bytes appropriate 9311 for use in the a.out file, and stores them in the array pointed to by buf. 9312 This knows about the endian-ness of the target machine and does 9313 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) 9314 2 (short) and 4 (long) Floating numbers are put out as a series of 9315 LITTLENUMS (shorts, here at least). */ 9316 9317void 9318md_number_to_chars (buf, val, n) 9319 char * buf; 9320 valueT val; 9321 int n; 9322{ 9323 if (target_big_endian) 9324 number_to_chars_bigendian (buf, val, n); 9325 else 9326 number_to_chars_littleendian (buf, val, n); 9327} 9328 9329static valueT 9330md_chars_to_number (buf, n) 9331 char * buf; 9332 int n; 9333{ 9334 valueT result = 0; 9335 unsigned char * where = (unsigned char *) buf; 9336 9337 if (target_big_endian) 9338 { 9339 while (n--) 9340 { 9341 result <<= 8; 9342 result |= (*where++ & 255); 9343 } 9344 } 9345 else 9346 { 9347 while (n--) 9348 { 9349 result <<= 8; 9350 result |= (where[n] & 255); 9351 } 9352 } 9353 9354 return result; 9355} 9356 9357/* Turn a string in input_line_pointer into a floating point constant 9358 of type TYPE, and store the appropriate bytes in *LITP. The number 9359 of LITTLENUMS emitted is stored in *SIZEP. An error message is 9360 returned, or NULL on OK. 9361 9362 Note that fp constants aren't represent in the normal way on the ARM. 9363 In big endian mode, things are as expected. However, in little endian 9364 mode fp constants are big-endian word-wise, and little-endian byte-wise 9365 within the words. For example, (double) 1.1 in big endian mode is 9366 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is 9367 the byte sequence 99 99 f1 3f 9a 99 99 99. 9368 9369 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */ 9370 9371char * 9372md_atof (type, litP, sizeP) 9373 char type; 9374 char * litP; 9375 int * sizeP; 9376{ 9377 int prec; 9378 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 9379 char *t; 9380 int i; 9381 9382 switch (type) 9383 { 9384 case 'f': 9385 case 'F': 9386 case 's': 9387 case 'S': 9388 prec = 2; 9389 break; 9390 9391 case 'd': 9392 case 'D': 9393 case 'r': 9394 case 'R': 9395 prec = 4; 9396 break; 9397 9398 case 'x': 9399 case 'X': 9400 prec = 6; 9401 break; 9402 9403 case 'p': 9404 case 'P': 9405 prec = 6; 9406 break; 9407 9408 default: 9409 *sizeP = 0; 9410 return _("bad call to MD_ATOF()"); 9411 } 9412 9413 t = atof_ieee (input_line_pointer, type, words); 9414 if (t) 9415 input_line_pointer = t; 9416 *sizeP = prec * 2; 9417 9418 if (target_big_endian) 9419 { 9420 for (i = 0; i < prec; i++) 9421 { 9422 md_number_to_chars (litP, (valueT) words[i], 2); 9423 litP += 2; 9424 } 9425 } 9426 else 9427 { 9428 if (cpu_variant & FPU_ARCH_VFP) 9429 for (i = prec - 1; i >= 0; i--) 9430 { 9431 md_number_to_chars (litP, (valueT) words[i], 2); 9432 litP += 2; 9433 } 9434 else 9435 /* For a 4 byte float the order of elements in `words' is 1 0. 9436 For an 8 byte float the order is 1 0 3 2. */ 9437 for (i = 0; i < prec; i += 2) 9438 { 9439 md_number_to_chars (litP, (valueT) words[i + 1], 2); 9440 md_number_to_chars (litP + 2, (valueT) words[i], 2); 9441 litP += 4; 9442 } 9443 } 9444 9445 return 0; 9446} 9447 9448/* The knowledge of the PC's pipeline offset is built into the insns 9449 themselves. */ 9450 9451long 9452md_pcrel_from (fixP) 9453 fixS * fixP; 9454{ 9455 if (fixP->fx_addsy 9456 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section 9457 && fixP->fx_subsy == NULL) 9458 return 0; 9459 9460 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD)) 9461 { 9462 /* PC relative addressing on the Thumb is slightly odd 9463 as the bottom two bits of the PC are forced to zero 9464 for the calculation. */ 9465 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3; 9466 } 9467 9468#ifdef TE_WINCE 9469 /* The pattern was adjusted to accomodate CE's off-by-one fixups, 9470 so we un-adjust here to compensate for the accomodation. */ 9471 return fixP->fx_where + fixP->fx_frag->fr_address + 8; 9472#else 9473 return fixP->fx_where + fixP->fx_frag->fr_address; 9474#endif 9475} 9476 9477/* Round up a section size to the appropriate boundary. */ 9478 9479valueT 9480md_section_align (segment, size) 9481 segT segment ATTRIBUTE_UNUSED; 9482 valueT size; 9483{ 9484#ifdef OBJ_ELF 9485 return size; 9486#else 9487 /* Round all sects to multiple of 4. */ 9488 return (size + 3) & ~3; 9489#endif 9490} 9491 9492/* Under ELF we need to default _GLOBAL_OFFSET_TABLE. 9493 Otherwise we have no need to default values of symbols. */ 9494 9495symbolS * 9496md_undefined_symbol (name) 9497 char * name ATTRIBUTE_UNUSED; 9498{ 9499#ifdef OBJ_ELF 9500 if (name[0] == '_' && name[1] == 'G' 9501 && streq (name, GLOBAL_OFFSET_TABLE_NAME)) 9502 { 9503 if (!GOT_symbol) 9504 { 9505 if (symbol_find (name)) 9506 as_bad ("GOT already in the symbol table"); 9507 9508 GOT_symbol = symbol_new (name, undefined_section, 9509 (valueT) 0, & zero_address_frag); 9510 } 9511 9512 return GOT_symbol; 9513 } 9514#endif 9515 9516 return 0; 9517} 9518 9519/* arm_reg_parse () := if it looks like a register, return its token and 9520 advance the pointer. */ 9521 9522static int 9523arm_reg_parse (ccp, htab) 9524 register char ** ccp; 9525 struct hash_control *htab; 9526{ 9527 char * start = * ccp; 9528 char c; 9529 char * p; 9530 struct reg_entry * reg; 9531 9532#ifdef REGISTER_PREFIX 9533 if (*start != REGISTER_PREFIX) 9534 return FAIL; 9535 p = start + 1; 9536#else 9537 p = start; 9538#ifdef OPTIONAL_REGISTER_PREFIX 9539 if (*p == OPTIONAL_REGISTER_PREFIX) 9540 p++, start++; 9541#endif 9542#endif 9543 if (!ISALPHA (*p) || !is_name_beginner (*p)) 9544 return FAIL; 9545 9546 c = *p++; 9547 while (ISALPHA (c) || ISDIGIT (c) || c == '_') 9548 c = *p++; 9549 9550 *--p = 0; 9551 reg = (struct reg_entry *) hash_find (htab, start); 9552 *p = c; 9553 9554 if (reg) 9555 { 9556 *ccp = p; 9557 return reg->number; 9558 } 9559 9560 return FAIL; 9561} 9562 9563/* Search for the following register name in each of the possible reg name 9564 tables. Return the classification if found, or REG_TYPE_MAX if not 9565 present. */ 9566static enum arm_reg_type 9567arm_reg_parse_any (cp) 9568 char *cp; 9569{ 9570 int i; 9571 9572 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++) 9573 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL) 9574 return (enum arm_reg_type) i; 9575 9576 return REG_TYPE_MAX; 9577} 9578 9579void 9580md_apply_fix3 (fixP, valP, seg) 9581 fixS * fixP; 9582 valueT * valP; 9583 segT seg; 9584{ 9585 offsetT value = * valP; 9586 offsetT newval; 9587 unsigned int newimm; 9588 unsigned long temp; 9589 int sign; 9590 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal; 9591 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data; 9592 9593 assert (fixP->fx_r_type < BFD_RELOC_UNUSED); 9594 9595 /* Note whether this will delete the relocation. */ 9596#if 0 9597 /* Patch from REarnshaw to JDavis (disabled for the moment, since it 9598 doesn't work fully.) */ 9599 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy)) 9600 && !fixP->fx_pcrel) 9601#else 9602 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) 9603#endif 9604 fixP->fx_done = 1; 9605 9606 /* If this symbol is in a different section then we need to leave it for 9607 the linker to deal with. Unfortunately, md_pcrel_from can't tell, 9608 so we have to undo it's effects here. */ 9609 if (fixP->fx_pcrel) 9610 { 9611 if (fixP->fx_addsy != NULL 9612 && S_IS_DEFINED (fixP->fx_addsy) 9613 && S_GET_SEGMENT (fixP->fx_addsy) != seg) 9614 { 9615 if (target_oabi 9616 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH 9617 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX 9618 )) 9619 value = 0; 9620 else 9621 value += md_pcrel_from (fixP); 9622 } 9623 } 9624 9625 /* Remember value for emit_reloc. */ 9626 fixP->fx_addnumber = value; 9627 9628 switch (fixP->fx_r_type) 9629 { 9630 case BFD_RELOC_ARM_IMMEDIATE: 9631 newimm = validate_immediate (value); 9632 temp = md_chars_to_number (buf, INSN_SIZE); 9633 9634 /* If the instruction will fail, see if we can fix things up by 9635 changing the opcode. */ 9636 if (newimm == (unsigned int) FAIL 9637 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL) 9638 { 9639 as_bad_where (fixP->fx_file, fixP->fx_line, 9640 _("invalid constant (%lx) after fixup"), 9641 (unsigned long) value); 9642 break; 9643 } 9644 9645 newimm |= (temp & 0xfffff000); 9646 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE); 9647 break; 9648 9649 case BFD_RELOC_ARM_ADRL_IMMEDIATE: 9650 { 9651 unsigned int highpart = 0; 9652 unsigned int newinsn = 0xe1a00000; /* nop. */ 9653 newimm = validate_immediate (value); 9654 temp = md_chars_to_number (buf, INSN_SIZE); 9655 9656 /* If the instruction will fail, see if we can fix things up by 9657 changing the opcode. */ 9658 if (newimm == (unsigned int) FAIL 9659 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL) 9660 { 9661 /* No ? OK - try using two ADD instructions to generate 9662 the value. */ 9663 newimm = validate_immediate_twopart (value, & highpart); 9664 9665 /* Yes - then make sure that the second instruction is 9666 also an add. */ 9667 if (newimm != (unsigned int) FAIL) 9668 newinsn = temp; 9669 /* Still No ? Try using a negated value. */ 9670 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL) 9671 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT; 9672 /* Otherwise - give up. */ 9673 else 9674 { 9675 as_bad_where (fixP->fx_file, fixP->fx_line, 9676 _("unable to compute ADRL instructions for PC offset of 0x%lx"), 9677 value); 9678 break; 9679 } 9680 9681 /* Replace the first operand in the 2nd instruction (which 9682 is the PC) with the destination register. We have 9683 already added in the PC in the first instruction and we 9684 do not want to do it again. */ 9685 newinsn &= ~ 0xf0000; 9686 newinsn |= ((newinsn & 0x0f000) << 4); 9687 } 9688 9689 newimm |= (temp & 0xfffff000); 9690 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE); 9691 9692 highpart |= (newinsn & 0xfffff000); 9693 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE); 9694 } 9695 break; 9696 9697 case BFD_RELOC_ARM_OFFSET_IMM: 9698 sign = value >= 0; 9699 9700 if (value < 0) 9701 value = - value; 9702 9703 if (validate_offset_imm (value, 0) == FAIL) 9704 { 9705 as_bad_where (fixP->fx_file, fixP->fx_line, 9706 _("bad immediate value for offset (%ld)"), 9707 (long) value); 9708 break; 9709 } 9710 9711 newval = md_chars_to_number (buf, INSN_SIZE); 9712 newval &= 0xff7ff000; 9713 newval |= value | (sign ? INDEX_UP : 0); 9714 md_number_to_chars (buf, newval, INSN_SIZE); 9715 break; 9716 9717 case BFD_RELOC_ARM_OFFSET_IMM8: 9718 case BFD_RELOC_ARM_HWLITERAL: 9719 sign = value >= 0; 9720 9721 if (value < 0) 9722 value = - value; 9723 9724 if (validate_offset_imm (value, 1) == FAIL) 9725 { 9726 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL) 9727 as_bad_where (fixP->fx_file, fixP->fx_line, 9728 _("invalid literal constant: pool needs to be closer")); 9729 else 9730 as_bad (_("bad immediate value for half-word offset (%ld)"), 9731 (long) value); 9732 break; 9733 } 9734 9735 newval = md_chars_to_number (buf, INSN_SIZE); 9736 newval &= 0xff7ff0f0; 9737 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0); 9738 md_number_to_chars (buf, newval, INSN_SIZE); 9739 break; 9740 9741 case BFD_RELOC_ARM_LITERAL: 9742 sign = value >= 0; 9743 9744 if (value < 0) 9745 value = - value; 9746 9747 if (validate_offset_imm (value, 0) == FAIL) 9748 { 9749 as_bad_where (fixP->fx_file, fixP->fx_line, 9750 _("invalid literal constant: pool needs to be closer")); 9751 break; 9752 } 9753 9754 newval = md_chars_to_number (buf, INSN_SIZE); 9755 newval &= 0xff7ff000; 9756 newval |= value | (sign ? INDEX_UP : 0); 9757 md_number_to_chars (buf, newval, INSN_SIZE); 9758 break; 9759 9760 case BFD_RELOC_ARM_SHIFT_IMM: 9761 newval = md_chars_to_number (buf, INSN_SIZE); 9762 if (((unsigned long) value) > 32 9763 || (value == 32 9764 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60))) 9765 { 9766 as_bad_where (fixP->fx_file, fixP->fx_line, 9767 _("shift expression is too large")); 9768 break; 9769 } 9770 9771 if (value == 0) 9772 /* Shifts of zero must be done as lsl. */ 9773 newval &= ~0x60; 9774 else if (value == 32) 9775 value = 0; 9776 newval &= 0xfffff07f; 9777 newval |= (value & 0x1f) << 7; 9778 md_number_to_chars (buf, newval, INSN_SIZE); 9779 break; 9780 9781 case BFD_RELOC_ARM_SWI: 9782 if (arm_data->thumb_mode) 9783 { 9784 if (((unsigned long) value) > 0xff) 9785 as_bad_where (fixP->fx_file, fixP->fx_line, 9786 _("invalid swi expression")); 9787 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00; 9788 newval |= value; 9789 md_number_to_chars (buf, newval, THUMB_SIZE); 9790 } 9791 else 9792 { 9793 if (((unsigned long) value) > 0x00ffffff) 9794 as_bad_where (fixP->fx_file, fixP->fx_line, 9795 _("invalid swi expression")); 9796 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000; 9797 newval |= value; 9798 md_number_to_chars (buf, newval, INSN_SIZE); 9799 } 9800 break; 9801 9802 case BFD_RELOC_ARM_MULTI: 9803 if (((unsigned long) value) > 0xffff) 9804 as_bad_where (fixP->fx_file, fixP->fx_line, 9805 _("invalid expression in load/store multiple")); 9806 newval = value | md_chars_to_number (buf, INSN_SIZE); 9807 md_number_to_chars (buf, newval, INSN_SIZE); 9808 break; 9809 9810 case BFD_RELOC_ARM_PCREL_BRANCH: 9811 newval = md_chars_to_number (buf, INSN_SIZE); 9812 9813 /* Sign-extend a 24-bit number. */ 9814#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000) 9815 9816#ifdef OBJ_ELF 9817 if (! target_oabi) 9818 value = fixP->fx_offset; 9819#endif 9820 9821 /* We are going to store value (shifted right by two) in the 9822 instruction, in a 24 bit, signed field. Thus we need to check 9823 that none of the top 8 bits of the shifted value (top 7 bits of 9824 the unshifted, unsigned value) are set, or that they are all set. */ 9825 if ((value & ~ ((offsetT) 0x1ffffff)) != 0 9826 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff))) 9827 { 9828#ifdef OBJ_ELF 9829 /* Normally we would be stuck at this point, since we cannot store 9830 the absolute address that is the destination of the branch in the 9831 24 bits of the branch instruction. If however, we happen to know 9832 that the destination of the branch is in the same section as the 9833 branch instruciton itself, then we can compute the relocation for 9834 ourselves and not have to bother the linker with it. 9835 9836 FIXME: The tests for OBJ_ELF and ! target_oabi are only here 9837 because I have not worked out how to do this for OBJ_COFF or 9838 target_oabi. */ 9839 if (! target_oabi 9840 && fixP->fx_addsy != NULL 9841 && S_IS_DEFINED (fixP->fx_addsy) 9842 && S_GET_SEGMENT (fixP->fx_addsy) == seg) 9843 { 9844 /* Get pc relative value to go into the branch. */ 9845 value = * valP; 9846 9847 /* Permit a backward branch provided that enough bits 9848 are set. Allow a forwards branch, provided that 9849 enough bits are clear. */ 9850 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff) 9851 || (value & ~ ((offsetT) 0x1ffffff)) == 0) 9852 fixP->fx_done = 1; 9853 } 9854 9855 if (! fixP->fx_done) 9856#endif 9857 as_bad_where (fixP->fx_file, fixP->fx_line, 9858 _("GAS can't handle same-section branch dest >= 0x04000000")); 9859 } 9860 9861 value >>= 2; 9862 value += SEXT24 (newval); 9863 9864 if ( (value & ~ ((offsetT) 0xffffff)) != 0 9865 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff))) 9866 as_bad_where (fixP->fx_file, fixP->fx_line, 9867 _("out of range branch")); 9868 9869 newval = (value & 0x00ffffff) | (newval & 0xff000000); 9870 md_number_to_chars (buf, newval, INSN_SIZE); 9871 break; 9872 9873 case BFD_RELOC_ARM_PCREL_BLX: 9874 { 9875 offsetT hbit; 9876 newval = md_chars_to_number (buf, INSN_SIZE); 9877 9878#ifdef OBJ_ELF 9879 if (! target_oabi) 9880 value = fixP->fx_offset; 9881#endif 9882 hbit = (value >> 1) & 1; 9883 value = (value >> 2) & 0x00ffffff; 9884 value = (value + (newval & 0x00ffffff)) & 0x00ffffff; 9885 newval = value | (newval & 0xfe000000) | (hbit << 24); 9886 md_number_to_chars (buf, newval, INSN_SIZE); 9887 } 9888 break; 9889 9890 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */ 9891 newval = md_chars_to_number (buf, THUMB_SIZE); 9892 { 9893 addressT diff = (newval & 0xff) << 1; 9894 if (diff & 0x100) 9895 diff |= ~0xff; 9896 9897 value += diff; 9898 if ((value & ~0xff) && ((value & ~0xff) != ~0xff)) 9899 as_bad_where (fixP->fx_file, fixP->fx_line, 9900 _("branch out of range")); 9901 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1); 9902 } 9903 md_number_to_chars (buf, newval, THUMB_SIZE); 9904 break; 9905 9906 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */ 9907 newval = md_chars_to_number (buf, THUMB_SIZE); 9908 { 9909 addressT diff = (newval & 0x7ff) << 1; 9910 if (diff & 0x800) 9911 diff |= ~0x7ff; 9912 9913 value += diff; 9914 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff)) 9915 as_bad_where (fixP->fx_file, fixP->fx_line, 9916 _("branch out of range")); 9917 newval = (newval & 0xf800) | ((value & 0xfff) >> 1); 9918 } 9919 md_number_to_chars (buf, newval, THUMB_SIZE); 9920 break; 9921 9922 case BFD_RELOC_THUMB_PCREL_BLX: 9923 case BFD_RELOC_THUMB_PCREL_BRANCH23: 9924 { 9925 offsetT newval2; 9926 addressT diff; 9927 9928 newval = md_chars_to_number (buf, THUMB_SIZE); 9929 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE); 9930 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1); 9931 if (diff & 0x400000) 9932 diff |= ~0x3fffff; 9933#ifdef OBJ_ELF 9934 value = fixP->fx_offset; 9935#endif 9936 value += diff; 9937 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff)) 9938 as_bad_where (fixP->fx_file, fixP->fx_line, 9939 _("branch with link out of range")); 9940 9941 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12); 9942 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1); 9943 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) 9944 /* Remove bit zero of the adjusted offset. Bit zero can only be 9945 set if the upper insn is at a half-word boundary, since the 9946 destination address, an ARM instruction, must always be on a 9947 word boundary. The semantics of the BLX (1) instruction, however, 9948 are that bit zero in the offset must always be zero, and the 9949 corresponding bit one in the target address will be set from bit 9950 one of the source address. */ 9951 newval2 &= ~1; 9952 md_number_to_chars (buf, newval, THUMB_SIZE); 9953 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE); 9954 } 9955 break; 9956 9957 case BFD_RELOC_8: 9958 if (fixP->fx_done || fixP->fx_pcrel) 9959 md_number_to_chars (buf, value, 1); 9960#ifdef OBJ_ELF 9961 else if (!target_oabi) 9962 { 9963 value = fixP->fx_offset; 9964 md_number_to_chars (buf, value, 1); 9965 } 9966#endif 9967 break; 9968 9969 case BFD_RELOC_16: 9970 if (fixP->fx_done || fixP->fx_pcrel) 9971 md_number_to_chars (buf, value, 2); 9972#ifdef OBJ_ELF 9973 else if (!target_oabi) 9974 { 9975 value = fixP->fx_offset; 9976 md_number_to_chars (buf, value, 2); 9977 } 9978#endif 9979 break; 9980 9981#ifdef OBJ_ELF 9982 case BFD_RELOC_ARM_GOT32: 9983 case BFD_RELOC_ARM_GOTOFF: 9984 md_number_to_chars (buf, 0, 4); 9985 break; 9986#endif 9987 9988 case BFD_RELOC_RVA: 9989 case BFD_RELOC_32: 9990 if (fixP->fx_done || fixP->fx_pcrel) 9991 md_number_to_chars (buf, value, 4); 9992#ifdef OBJ_ELF 9993 else if (!target_oabi) 9994 { 9995 value = fixP->fx_offset; 9996 md_number_to_chars (buf, value, 4); 9997 } 9998#endif 9999 break; 10000 10001#ifdef OBJ_ELF 10002 case BFD_RELOC_ARM_PLT32: 10003 /* It appears the instruction is fully prepared at this point. */ 10004 break; 10005#endif 10006 10007 case BFD_RELOC_ARM_GOTPC: 10008 md_number_to_chars (buf, value, 4); 10009 break; 10010 10011 case BFD_RELOC_ARM_CP_OFF_IMM: 10012 sign = value >= 0; 10013 if (value < -1023 || value > 1023 || (value & 3)) 10014 as_bad_where (fixP->fx_file, fixP->fx_line, 10015 _("illegal value for co-processor offset")); 10016 if (value < 0) 10017 value = -value; 10018 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00; 10019 newval |= (value >> 2) | (sign ? INDEX_UP : 0); 10020 md_number_to_chars (buf, newval, INSN_SIZE); 10021 break; 10022 10023 case BFD_RELOC_ARM_THUMB_OFFSET: 10024 newval = md_chars_to_number (buf, THUMB_SIZE); 10025 /* Exactly what ranges, and where the offset is inserted depends 10026 on the type of instruction, we can establish this from the 10027 top 4 bits. */ 10028 switch (newval >> 12) 10029 { 10030 case 4: /* PC load. */ 10031 /* Thumb PC loads are somewhat odd, bit 1 of the PC is 10032 forced to zero for these loads, so we will need to round 10033 up the offset if the instruction address is not word 10034 aligned (since the final address produced must be, and 10035 we can only describe word-aligned immediate offsets). */ 10036 10037 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3) 10038 as_bad_where (fixP->fx_file, fixP->fx_line, 10039 _("invalid offset, target not word aligned (0x%08X)"), 10040 (unsigned int) (fixP->fx_frag->fr_address 10041 + fixP->fx_where + value)); 10042 10043 if ((value + 2) & ~0x3fe) 10044 as_bad_where (fixP->fx_file, fixP->fx_line, 10045 _("invalid offset, value too big (0x%08lX)"), value); 10046 10047 /* Round up, since pc will be rounded down. */ 10048 newval |= (value + 2) >> 2; 10049 break; 10050 10051 case 9: /* SP load/store. */ 10052 if (value & ~0x3fc) 10053 as_bad_where (fixP->fx_file, fixP->fx_line, 10054 _("invalid offset, value too big (0x%08lX)"), value); 10055 newval |= value >> 2; 10056 break; 10057 10058 case 6: /* Word load/store. */ 10059 if (value & ~0x7c) 10060 as_bad_where (fixP->fx_file, fixP->fx_line, 10061 _("invalid offset, value too big (0x%08lX)"), value); 10062 newval |= value << 4; /* 6 - 2. */ 10063 break; 10064 10065 case 7: /* Byte load/store. */ 10066 if (value & ~0x1f) 10067 as_bad_where (fixP->fx_file, fixP->fx_line, 10068 _("invalid offset, value too big (0x%08lX)"), value); 10069 newval |= value << 6; 10070 break; 10071 10072 case 8: /* Halfword load/store. */ 10073 if (value & ~0x3e) 10074 as_bad_where (fixP->fx_file, fixP->fx_line, 10075 _("invalid offset, value too big (0x%08lX)"), value); 10076 newval |= value << 5; /* 6 - 1. */ 10077 break; 10078 10079 default: 10080 as_bad_where (fixP->fx_file, fixP->fx_line, 10081 "Unable to process relocation for thumb opcode: %lx", 10082 (unsigned long) newval); 10083 break; 10084 } 10085 md_number_to_chars (buf, newval, THUMB_SIZE); 10086 break; 10087 10088 case BFD_RELOC_ARM_THUMB_ADD: 10089 /* This is a complicated relocation, since we use it for all of 10090 the following immediate relocations: 10091 10092 3bit ADD/SUB 10093 8bit ADD/SUB 10094 9bit ADD/SUB SP word-aligned 10095 10bit ADD PC/SP word-aligned 10096 10097 The type of instruction being processed is encoded in the 10098 instruction field: 10099 10100 0x8000 SUB 10101 0x00F0 Rd 10102 0x000F Rs 10103 */ 10104 newval = md_chars_to_number (buf, THUMB_SIZE); 10105 { 10106 int rd = (newval >> 4) & 0xf; 10107 int rs = newval & 0xf; 10108 int subtract = newval & 0x8000; 10109 10110 if (rd == REG_SP) 10111 { 10112 if (value & ~0x1fc) 10113 as_bad_where (fixP->fx_file, fixP->fx_line, 10114 _("invalid immediate for stack address calculation")); 10115 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST; 10116 newval |= value >> 2; 10117 } 10118 else if (rs == REG_PC || rs == REG_SP) 10119 { 10120 if (subtract || 10121 value & ~0x3fc) 10122 as_bad_where (fixP->fx_file, fixP->fx_line, 10123 _("invalid immediate for address calculation (value = 0x%08lX)"), 10124 (unsigned long) value); 10125 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP); 10126 newval |= rd << 8; 10127 newval |= value >> 2; 10128 } 10129 else if (rs == rd) 10130 { 10131 if (value & ~0xff) 10132 as_bad_where (fixP->fx_file, fixP->fx_line, 10133 _("invalid 8bit immediate")); 10134 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8; 10135 newval |= (rd << 8) | value; 10136 } 10137 else 10138 { 10139 if (value & ~0x7) 10140 as_bad_where (fixP->fx_file, fixP->fx_line, 10141 _("invalid 3bit immediate")); 10142 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3; 10143 newval |= rd | (rs << 3) | (value << 6); 10144 } 10145 } 10146 md_number_to_chars (buf, newval, THUMB_SIZE); 10147 break; 10148 10149 case BFD_RELOC_ARM_THUMB_IMM: 10150 newval = md_chars_to_number (buf, THUMB_SIZE); 10151 switch (newval >> 11) 10152 { 10153 case 0x04: /* 8bit immediate MOV. */ 10154 case 0x05: /* 8bit immediate CMP. */ 10155 if (value < 0 || value > 255) 10156 as_bad_where (fixP->fx_file, fixP->fx_line, 10157 _("invalid immediate: %ld is too large"), 10158 (long) value); 10159 newval |= value; 10160 break; 10161 10162 default: 10163 abort (); 10164 } 10165 md_number_to_chars (buf, newval, THUMB_SIZE); 10166 break; 10167 10168 case BFD_RELOC_ARM_THUMB_SHIFT: 10169 /* 5bit shift value (0..31). */ 10170 if (value < 0 || value > 31) 10171 as_bad_where (fixP->fx_file, fixP->fx_line, 10172 _("illegal Thumb shift value: %ld"), (long) value); 10173 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f; 10174 newval |= value << 6; 10175 md_number_to_chars (buf, newval, THUMB_SIZE); 10176 break; 10177 10178 case BFD_RELOC_VTABLE_INHERIT: 10179 case BFD_RELOC_VTABLE_ENTRY: 10180 fixP->fx_done = 0; 10181 return; 10182 10183 case BFD_RELOC_NONE: 10184 default: 10185 as_bad_where (fixP->fx_file, fixP->fx_line, 10186 _("bad relocation fixup type (%d)"), fixP->fx_r_type); 10187 } 10188} 10189 10190/* Translate internal representation of relocation info to BFD target 10191 format. */ 10192 10193arelent * 10194tc_gen_reloc (section, fixp) 10195 asection * section ATTRIBUTE_UNUSED; 10196 fixS * fixp; 10197{ 10198 arelent * reloc; 10199 bfd_reloc_code_real_type code; 10200 10201 reloc = (arelent *) xmalloc (sizeof (arelent)); 10202 10203 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 10204 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 10205 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 10206 10207 /* @@ Why fx_addnumber sometimes and fx_offset other times? */ 10208#ifndef OBJ_ELF 10209 if (fixp->fx_pcrel == 0) 10210 reloc->addend = fixp->fx_offset; 10211 else 10212 reloc->addend = fixp->fx_offset = reloc->address; 10213#else /* OBJ_ELF */ 10214 reloc->addend = fixp->fx_offset; 10215#endif 10216 10217 switch (fixp->fx_r_type) 10218 { 10219 case BFD_RELOC_8: 10220 if (fixp->fx_pcrel) 10221 { 10222 code = BFD_RELOC_8_PCREL; 10223 break; 10224 } 10225 10226 case BFD_RELOC_16: 10227 if (fixp->fx_pcrel) 10228 { 10229 code = BFD_RELOC_16_PCREL; 10230 break; 10231 } 10232 10233 case BFD_RELOC_32: 10234 if (fixp->fx_pcrel) 10235 { 10236 code = BFD_RELOC_32_PCREL; 10237 break; 10238 } 10239 10240 case BFD_RELOC_ARM_PCREL_BRANCH: 10241 case BFD_RELOC_ARM_PCREL_BLX: 10242 case BFD_RELOC_RVA: 10243 case BFD_RELOC_THUMB_PCREL_BRANCH9: 10244 case BFD_RELOC_THUMB_PCREL_BRANCH12: 10245 case BFD_RELOC_THUMB_PCREL_BRANCH23: 10246 case BFD_RELOC_THUMB_PCREL_BLX: 10247 case BFD_RELOC_VTABLE_ENTRY: 10248 case BFD_RELOC_VTABLE_INHERIT: 10249 code = fixp->fx_r_type; 10250 break; 10251 10252 case BFD_RELOC_ARM_LITERAL: 10253 case BFD_RELOC_ARM_HWLITERAL: 10254 /* If this is called then the a literal has been referenced across 10255 a section boundary - possibly due to an implicit dump. */ 10256 as_bad_where (fixp->fx_file, fixp->fx_line, 10257 _("literal referenced across section boundary (Implicit dump?)")); 10258 return NULL; 10259 10260#ifdef OBJ_ELF 10261 case BFD_RELOC_ARM_GOT32: 10262 case BFD_RELOC_ARM_GOTOFF: 10263 case BFD_RELOC_ARM_PLT32: 10264 code = fixp->fx_r_type; 10265 break; 10266#endif 10267 10268 case BFD_RELOC_ARM_IMMEDIATE: 10269 as_bad_where (fixp->fx_file, fixp->fx_line, 10270 _("internal relocation (type %d) not fixed up (IMMEDIATE)"), 10271 fixp->fx_r_type); 10272 return NULL; 10273 10274 case BFD_RELOC_ARM_ADRL_IMMEDIATE: 10275 as_bad_where (fixp->fx_file, fixp->fx_line, 10276 _("ADRL used for a symbol not defined in the same file")); 10277 return NULL; 10278 10279 case BFD_RELOC_ARM_OFFSET_IMM: 10280 as_bad_where (fixp->fx_file, fixp->fx_line, 10281 _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"), 10282 fixp->fx_r_type); 10283 return NULL; 10284 10285 default: 10286 { 10287 char * type; 10288 10289 switch (fixp->fx_r_type) 10290 { 10291 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break; 10292 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break; 10293 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break; 10294 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break; 10295 case BFD_RELOC_ARM_SWI: type = "SWI"; break; 10296 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break; 10297 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break; 10298 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break; 10299 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break; 10300 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break; 10301 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break; 10302 default: type = _("<unknown>"); break; 10303 } 10304 as_bad_where (fixp->fx_file, fixp->fx_line, 10305 _("cannot represent %s relocation in this object file format"), 10306 type); 10307 return NULL; 10308 } 10309 } 10310 10311#ifdef OBJ_ELF 10312 if (code == BFD_RELOC_32_PCREL 10313 && GOT_symbol 10314 && fixp->fx_addsy == GOT_symbol) 10315 { 10316 code = BFD_RELOC_ARM_GOTPC; 10317 reloc->addend = fixp->fx_offset = reloc->address; 10318 } 10319#endif 10320 10321 reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 10322 10323 if (reloc->howto == NULL) 10324 { 10325 as_bad_where (fixp->fx_file, fixp->fx_line, 10326 _("cannot represent %s relocation in this object file format"), 10327 bfd_get_reloc_code_name (code)); 10328 return NULL; 10329 } 10330 10331 /* HACK: Since arm ELF uses Rel instead of Rela, encode the 10332 vtable entry to be used in the relocation's section offset. */ 10333 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 10334 reloc->address = fixp->fx_offset; 10335 10336 return reloc; 10337} 10338 10339int 10340md_estimate_size_before_relax (fragP, segtype) 10341 fragS * fragP ATTRIBUTE_UNUSED; 10342 segT segtype ATTRIBUTE_UNUSED; 10343{ 10344 as_fatal (_("md_estimate_size_before_relax\n")); 10345 return 1; 10346} 10347 10348static void 10349output_inst (str) 10350 const char *str; 10351{ 10352 char * to = NULL; 10353 10354 if (inst.error) 10355 { 10356 as_bad ("%s -- `%s'", inst.error, str); 10357 return; 10358 } 10359 10360 to = frag_more (inst.size); 10361 10362 if (thumb_mode && (inst.size > THUMB_SIZE)) 10363 { 10364 assert (inst.size == (2 * THUMB_SIZE)); 10365 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE); 10366 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE); 10367 } 10368 else if (inst.size > INSN_SIZE) 10369 { 10370 assert (inst.size == (2 * INSN_SIZE)); 10371 md_number_to_chars (to, inst.instruction, INSN_SIZE); 10372 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE); 10373 } 10374 else 10375 md_number_to_chars (to, inst.instruction, inst.size); 10376 10377 if (inst.reloc.type != BFD_RELOC_NONE) 10378 fix_new_arm (frag_now, to - frag_now->fr_literal, 10379 inst.size, & inst.reloc.exp, inst.reloc.pc_rel, 10380 inst.reloc.type); 10381 10382#ifdef OBJ_ELF 10383 dwarf2_emit_insn (inst.size); 10384#endif 10385} 10386 10387void 10388md_assemble (str) 10389 char * str; 10390{ 10391 char c; 10392 char *p; 10393 char *start; 10394 10395 /* Align the instruction. 10396 This may not be the right thing to do but ... */ 10397#if 0 10398 arm_align (2, 0); 10399#endif 10400 listing_prev_line (); /* Defined in listing.h. */ 10401 10402 /* Align the previous label if needed. */ 10403 if (last_label_seen != NULL) 10404 { 10405 symbol_set_frag (last_label_seen, frag_now); 10406 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ()); 10407 S_SET_SEGMENT (last_label_seen, now_seg); 10408 } 10409 10410 memset (&inst, '\0', sizeof (inst)); 10411 inst.reloc.type = BFD_RELOC_NONE; 10412 10413 skip_whitespace (str); 10414 10415 /* Scan up to the end of the op-code, which must end in white space or 10416 end of string. */ 10417 for (start = p = str; *p != '\0'; p++) 10418 if (*p == ' ') 10419 break; 10420 10421 if (p == str) 10422 { 10423 as_bad (_("no operator -- statement `%s'\n"), str); 10424 return; 10425 } 10426 10427 if (thumb_mode) 10428 { 10429 const struct thumb_opcode * opcode; 10430 10431 c = *p; 10432 *p = '\0'; 10433 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str); 10434 *p = c; 10435 10436 if (opcode) 10437 { 10438 /* Check that this instruction is supported for this CPU. */ 10439 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0) 10440 { 10441 as_bad (_("selected processor does not support `%s'"), str); 10442 return; 10443 } 10444 10445 inst.instruction = opcode->value; 10446 inst.size = opcode->size; 10447 (*opcode->parms) (p); 10448 output_inst (str); 10449 return; 10450 } 10451 } 10452 else 10453 { 10454 const struct asm_opcode * opcode; 10455 10456 c = *p; 10457 *p = '\0'; 10458 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str); 10459 *p = c; 10460 10461 if (opcode) 10462 { 10463 /* Check that this instruction is supported for this CPU. */ 10464 if ((opcode->variant & cpu_variant) == 0) 10465 { 10466 as_bad (_("selected processor does not support `%s'"), str); 10467 return; 10468 } 10469 10470 inst.instruction = opcode->value; 10471 inst.size = INSN_SIZE; 10472 (*opcode->parms) (p); 10473 output_inst (str); 10474 return; 10475 } 10476 } 10477 10478 /* It wasn't an instruction, but it might be a register alias of the form 10479 alias .req reg. */ 10480 if (create_register_alias (str, p)) 10481 return; 10482 10483 as_bad (_("bad instruction `%s'"), start); 10484} 10485 10486/* md_parse_option 10487 Invocation line includes a switch not recognized by the base assembler. 10488 See if it's a processor-specific option. 10489 10490 This routine is somewhat complicated by the need for backwards 10491 compatibility (since older releases of gcc can't be changed). 10492 The new options try to make the interface as compatible as 10493 possible with GCC. 10494 10495 New options (supported) are: 10496 10497 -mcpu=<cpu name> Assemble for selected processor 10498 -march=<architecture name> Assemble for selected architecture 10499 -mfpu=<fpu architecture> Assemble for selected FPU. 10500 -EB/-mbig-endian Big-endian 10501 -EL/-mlittle-endian Little-endian 10502 -k Generate PIC code 10503 -mthumb Start in Thumb mode 10504 -mthumb-interwork Code supports ARM/Thumb interworking 10505 10506 For now we will also provide support for 10507 10508 -mapcs-32 32-bit Program counter 10509 -mapcs-26 26-bit Program counter 10510 -macps-float Floats passed in FP registers 10511 -mapcs-reentrant Reentrant code 10512 -matpcs 10513 (sometime these will probably be replaced with -mapcs=<list of options> 10514 and -matpcs=<list of options>) 10515 10516 The remaining options are only supported for back-wards compatibility. 10517 Cpu variants, the arm part is optional: 10518 -m[arm]1 Currently not supported. 10519 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor 10520 -m[arm]3 Arm 3 processor 10521 -m[arm]6[xx], Arm 6 processors 10522 -m[arm]7[xx][t][[d]m] Arm 7 processors 10523 -m[arm]8[10] Arm 8 processors 10524 -m[arm]9[20][tdmi] Arm 9 processors 10525 -mstrongarm[110[0]] StrongARM processors 10526 -mxscale XScale processors 10527 -m[arm]v[2345[t[e]]] Arm architectures 10528 -mall All (except the ARM1) 10529 FP variants: 10530 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions 10531 -mfpe-old (No float load/store multiples) 10532 -mvfpxd VFP Single precision 10533 -mvfp All VFP 10534 -mno-fpu Disable all floating point instructions 10535 10536 The following CPU names are recognized: 10537 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620, 10538 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700, 10539 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c, 10540 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9, 10541 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e, 10542 arm10t arm10e, arm1020t, arm1020e, arm10200e, 10543 strongarm, strongarm110, strongarm1100, strongarm1110, xscale. 10544 10545 */ 10546 10547CONST char * md_shortopts = "m:k"; 10548 10549#ifdef ARM_BI_ENDIAN 10550#define OPTION_EB (OPTION_MD_BASE + 0) 10551#define OPTION_EL (OPTION_MD_BASE + 1) 10552#else 10553#if TARGET_BYTES_BIG_ENDIAN 10554#define OPTION_EB (OPTION_MD_BASE + 0) 10555#else 10556#define OPTION_EL (OPTION_MD_BASE + 1) 10557#endif 10558#endif 10559 10560struct option md_longopts[] = 10561{ 10562#ifdef OPTION_EB 10563 {"EB", no_argument, NULL, OPTION_EB}, 10564#endif 10565#ifdef OPTION_EL 10566 {"EL", no_argument, NULL, OPTION_EL}, 10567#endif 10568 {NULL, no_argument, NULL, 0} 10569}; 10570 10571size_t md_longopts_size = sizeof (md_longopts); 10572 10573struct arm_option_table 10574{ 10575 char *option; /* Option name to match. */ 10576 char *help; /* Help information. */ 10577 int *var; /* Variable to change. */ 10578 int value; /* What to change it to. */ 10579 char *deprecated; /* If non-null, print this message. */ 10580}; 10581 10582struct arm_option_table arm_opts[] = 10583{ 10584 {"k", N_("generate PIC code"), &pic_code, 1, NULL}, 10585 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL}, 10586 {"mthumb-interwork", N_("support ARM/Thumb interworking"), 10587 &support_interwork, 1, NULL}, 10588 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL}, 10589 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL}, 10590 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL}, 10591 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float, 10592 1, NULL}, 10593 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL}, 10594 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL}, 10595 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL}, 10596 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1, 10597 NULL}, 10598 10599 /* These are recognized by the assembler, but have no affect on code. */ 10600 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL}, 10601 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL}, 10602 10603 /* DON'T add any new processors to this list -- we want the whole list 10604 to go away... Add them to the processors table instead. */ 10605 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")}, 10606 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")}, 10607 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")}, 10608 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")}, 10609 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")}, 10610 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")}, 10611 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")}, 10612 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")}, 10613 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")}, 10614 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")}, 10615 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")}, 10616 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")}, 10617 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")}, 10618 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")}, 10619 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")}, 10620 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")}, 10621 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")}, 10622 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")}, 10623 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")}, 10624 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")}, 10625 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")}, 10626 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")}, 10627 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")}, 10628 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")}, 10629 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")}, 10630 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")}, 10631 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")}, 10632 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")}, 10633 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")}, 10634 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")}, 10635 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")}, 10636 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")}, 10637 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")}, 10638 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")}, 10639 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")}, 10640 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")}, 10641 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")}, 10642 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")}, 10643 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")}, 10644 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")}, 10645 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")}, 10646 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")}, 10647 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")}, 10648 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")}, 10649 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")}, 10650 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")}, 10651 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")}, 10652 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")}, 10653 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")}, 10654 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")}, 10655 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")}, 10656 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")}, 10657 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")}, 10658 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")}, 10659 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")}, 10660 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")}, 10661 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")}, 10662 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")}, 10663 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")}, 10664 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")}, 10665 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")}, 10666 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")}, 10667 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")}, 10668 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")}, 10669 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")}, 10670 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")}, 10671 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")}, 10672 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")}, 10673 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")}, 10674 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4, 10675 N_("use -mcpu=strongarm110")}, 10676 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4, 10677 N_("use -mcpu=strongarm1100")}, 10678 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4, 10679 N_("use -mcpu=strongarm1110")}, 10680 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")}, 10681 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")}, 10682 10683 /* Architecture variants -- don't add any more to this list either. */ 10684 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")}, 10685 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")}, 10686 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")}, 10687 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")}, 10688 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")}, 10689 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")}, 10690 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")}, 10691 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")}, 10692 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")}, 10693 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")}, 10694 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")}, 10695 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")}, 10696 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")}, 10697 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")}, 10698 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")}, 10699 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")}, 10700 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")}, 10701 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")}, 10702 10703 /* Floating point variants -- don't add any more to this list either. */ 10704 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")}, 10705 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")}, 10706 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")}, 10707 {"mno-fpu", NULL, &legacy_fpu, 0, 10708 N_("use either -mfpu=softfpa or -mfpu=softvfp")}, 10709 10710 {NULL, NULL, NULL, 0, NULL} 10711}; 10712 10713struct arm_cpu_option_table 10714{ 10715 char *name; 10716 int value; 10717 /* For some CPUs we assume an FPU unless the user explicitly sets 10718 -mfpu=... */ 10719 int default_fpu; 10720}; 10721 10722/* This list should, at a minimum, contain all the cpu names 10723 recognized by GCC. */ 10724static struct arm_cpu_option_table arm_cpus[] = 10725{ 10726 {"all", ARM_ANY, FPU_ARCH_FPA}, 10727 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA}, 10728 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA}, 10729 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA}, 10730 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA}, 10731 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA}, 10732 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA}, 10733 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA}, 10734 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA}, 10735 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA}, 10736 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA}, 10737 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA}, 10738 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA}, 10739 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA}, 10740 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA}, 10741 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA}, 10742 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA}, 10743 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA}, 10744 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA}, 10745 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA}, 10746 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10747 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA}, 10748 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10749 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10750 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA}, 10751 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA}, 10752 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA}, 10753 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA}, 10754 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10755 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10756 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA}, 10757 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA}, 10758 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA}, 10759 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA}, 10760 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA}, 10761 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA}, 10762 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA}, 10763 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10764 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10765 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10766 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10767 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10768 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10769 /* For V5 or later processors we default to using VFP; but the user 10770 should really set the FPU type explicitly. */ 10771 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, 10772 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10773 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2}, 10774 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, 10775 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10776 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, 10777 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10778 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1}, 10779 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10780 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10781 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1}, 10782 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, 10783 /* ??? XSCALE is really an architecture. */ 10784 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2}, 10785 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2}, 10786 /* Maverick */ 10787 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE}, 10788 {NULL, 0, 0} 10789}; 10790 10791struct arm_arch_option_table 10792{ 10793 char *name; 10794 int value; 10795 int default_fpu; 10796}; 10797 10798/* This list should, at a minimum, contain all the architecture names 10799 recognized by GCC. */ 10800static struct arm_arch_option_table arm_archs[] = 10801{ 10802 {"all", ARM_ANY, FPU_ARCH_FPA}, 10803 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA}, 10804 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA}, 10805 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA}, 10806 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA}, 10807 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA}, 10808 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA}, 10809 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA}, 10810 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA}, 10811 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA}, 10812 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA}, 10813 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP}, 10814 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP}, 10815 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP}, 10816 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP}, 10817 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP}, 10818 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP}, 10819 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP}, 10820 {NULL, 0, 0} 10821}; 10822 10823/* ISA extensions in the co-processor space. */ 10824struct arm_arch_extension_table 10825{ 10826 char *name; 10827 int value; 10828}; 10829 10830static struct arm_arch_extension_table arm_extensions[] = 10831{ 10832 {"maverick", ARM_CEXT_MAVERICK}, 10833 {"xscale", ARM_CEXT_XSCALE}, 10834 {NULL, 0} 10835}; 10836 10837struct arm_fpu_option_table 10838{ 10839 char *name; 10840 int value; 10841}; 10842 10843/* This list should, at a minimum, contain all the fpu names 10844 recognized by GCC. */ 10845static struct arm_fpu_option_table arm_fpus[] = 10846{ 10847 {"softfpa", FPU_NONE}, 10848 {"fpe", FPU_ARCH_FPE}, 10849 {"fpe2", FPU_ARCH_FPE}, 10850 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */ 10851 {"fpa", FPU_ARCH_FPA}, 10852 {"fpa10", FPU_ARCH_FPA}, 10853 {"fpa11", FPU_ARCH_FPA}, 10854 {"arm7500fe", FPU_ARCH_FPA}, 10855 {"softvfp", FPU_ARCH_VFP}, 10856 {"softvfp+vfp", FPU_ARCH_VFP_V2}, 10857 {"vfp", FPU_ARCH_VFP_V2}, 10858 {"vfp9", FPU_ARCH_VFP_V2}, 10859 {"vfp10", FPU_ARCH_VFP_V2}, 10860 {"vfp10-r0", FPU_ARCH_VFP_V1}, 10861 {"vfpxd", FPU_ARCH_VFP_V1xD}, 10862 {"arm1020t", FPU_ARCH_VFP_V1}, 10863 {"arm1020e", FPU_ARCH_VFP_V2}, 10864 {NULL, 0} 10865}; 10866 10867struct arm_long_option_table 10868{ 10869 char *option; /* Substring to match. */ 10870 char *help; /* Help information. */ 10871 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */ 10872 char *deprecated; /* If non-null, print this message. */ 10873}; 10874 10875static int 10876arm_parse_extension (str, opt_p) 10877 char *str; 10878 int *opt_p; 10879{ 10880 while (str != NULL && *str != 0) 10881 { 10882 struct arm_arch_extension_table *opt; 10883 char *ext; 10884 int optlen; 10885 10886 if (*str != '+') 10887 { 10888 as_bad (_("invalid architectural extension")); 10889 return 0; 10890 } 10891 10892 str++; 10893 ext = strchr (str, '+'); 10894 10895 if (ext != NULL) 10896 optlen = ext - str; 10897 else 10898 optlen = strlen (str); 10899 10900 if (optlen == 0) 10901 { 10902 as_bad (_("missing architectural extension")); 10903 return 0; 10904 } 10905 10906 for (opt = arm_extensions; opt->name != NULL; opt++) 10907 if (strncmp (opt->name, str, optlen) == 0) 10908 { 10909 *opt_p |= opt->value; 10910 break; 10911 } 10912 10913 if (opt->name == NULL) 10914 { 10915 as_bad (_("unknown architectural extnsion `%s'"), str); 10916 return 0; 10917 } 10918 10919 str = ext; 10920 }; 10921 10922 return 1; 10923} 10924 10925static int 10926arm_parse_cpu (str) 10927 char *str; 10928{ 10929 struct arm_cpu_option_table *opt; 10930 char *ext = strchr (str, '+'); 10931 int optlen; 10932 10933 if (ext != NULL) 10934 optlen = ext - str; 10935 else 10936 optlen = strlen (str); 10937 10938 if (optlen == 0) 10939 { 10940 as_bad (_("missing cpu name `%s'"), str); 10941 return 0; 10942 } 10943 10944 for (opt = arm_cpus; opt->name != NULL; opt++) 10945 if (strncmp (opt->name, str, optlen) == 0) 10946 { 10947 mcpu_cpu_opt = opt->value; 10948 mcpu_fpu_opt = opt->default_fpu; 10949 10950 if (ext != NULL) 10951 return arm_parse_extension (ext, &mcpu_cpu_opt); 10952 10953 return 1; 10954 } 10955 10956 as_bad (_("unknown cpu `%s'"), str); 10957 return 0; 10958} 10959 10960static int 10961arm_parse_arch (str) 10962 char *str; 10963{ 10964 struct arm_arch_option_table *opt; 10965 char *ext = strchr (str, '+'); 10966 int optlen; 10967 10968 if (ext != NULL) 10969 optlen = ext - str; 10970 else 10971 optlen = strlen (str); 10972 10973 if (optlen == 0) 10974 { 10975 as_bad (_("missing architecture name `%s'"), str); 10976 return 0; 10977 } 10978 10979 10980 for (opt = arm_archs; opt->name != NULL; opt++) 10981 if (strcmp (opt->name, str) == 0) 10982 { 10983 march_cpu_opt = opt->value; 10984 march_fpu_opt = opt->default_fpu; 10985 10986 if (ext != NULL) 10987 return arm_parse_extension (ext, &march_cpu_opt); 10988 10989 return 1; 10990 } 10991 10992 as_bad (_("unknown architecture `%s'\n"), str); 10993 return 0; 10994} 10995 10996static int 10997arm_parse_fpu (str) 10998 char *str; 10999{ 11000 struct arm_fpu_option_table *opt; 11001 11002 for (opt = arm_fpus; opt->name != NULL; opt++) 11003 if (strcmp (opt->name, str) == 0) 11004 { 11005 mfpu_opt = opt->value; 11006 return 1; 11007 } 11008 11009 as_bad (_("unknown floating point format `%s'\n"), str); 11010 return 0; 11011} 11012 11013struct arm_long_option_table arm_long_opts[] = 11014{ 11015 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"), 11016 arm_parse_cpu, NULL}, 11017 {"march=", N_("<arch name>\t assemble for architecture <arch name>"), 11018 arm_parse_arch, NULL}, 11019 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"), 11020 arm_parse_fpu, NULL}, 11021 {NULL, NULL, 0, NULL} 11022}; 11023 11024int 11025md_parse_option (c, arg) 11026 int c; 11027 char * arg; 11028{ 11029 struct arm_option_table *opt; 11030 struct arm_long_option_table *lopt; 11031 11032 switch (c) 11033 { 11034#ifdef OPTION_EB 11035 case OPTION_EB: 11036 target_big_endian = 1; 11037 break; 11038#endif 11039 11040#ifdef OPTION_EL 11041 case OPTION_EL: 11042 target_big_endian = 0; 11043 break; 11044#endif 11045 11046 case 'a': 11047 /* Listing option. Just ignore these, we don't support additional 11048 ones. */ 11049 return 0; 11050 11051 default: 11052 for (opt = arm_opts; opt->option != NULL; opt++) 11053 { 11054 if (c == opt->option[0] 11055 && ((arg == NULL && opt->option[1] == 0) 11056 || strcmp (arg, opt->option + 1) == 0)) 11057 { 11058#if WARN_DEPRECATED 11059 /* If the option is deprecated, tell the user. */ 11060 if (opt->deprecated != NULL) 11061 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, 11062 arg ? arg : "", _(opt->deprecated)); 11063#endif 11064 11065 if (opt->var != NULL) 11066 *opt->var = opt->value; 11067 11068 return 1; 11069 } 11070 } 11071 11072 for (lopt = arm_long_opts; lopt->option != NULL; lopt++) 11073 { 11074 /* These options are expected to have an argument. */ 11075 if (c == lopt->option[0] 11076 && arg != NULL 11077 && strncmp (arg, lopt->option + 1, 11078 strlen (lopt->option + 1)) == 0) 11079 { 11080#if WARN_DEPRECATED 11081 /* If the option is deprecated, tell the user. */ 11082 if (lopt->deprecated != NULL) 11083 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg, 11084 _(lopt->deprecated)); 11085#endif 11086 11087 /* Call the sup-option parser. */ 11088 return (*lopt->func)(arg + strlen (lopt->option) - 1); 11089 } 11090 } 11091 11092 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); 11093 return 0; 11094 } 11095 11096 return 1; 11097} 11098 11099void 11100md_show_usage (fp) 11101 FILE * fp; 11102{ 11103 struct arm_option_table *opt; 11104 struct arm_long_option_table *lopt; 11105 11106 fprintf (fp, _(" ARM-specific assembler options:\n")); 11107 11108 for (opt = arm_opts; opt->option != NULL; opt++) 11109 if (opt->help != NULL) 11110 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help)); 11111 11112 for (lopt = arm_long_opts; lopt->option != NULL; lopt++) 11113 if (lopt->help != NULL) 11114 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help)); 11115 11116#ifdef OPTION_EB 11117 fprintf (fp, _("\ 11118 -EB assemble code for a big-endian cpu\n")); 11119#endif 11120 11121#ifdef OPTION_EL 11122 fprintf (fp, _("\ 11123 -EL assemble code for a little-endian cpu\n")); 11124#endif 11125} 11126 11127/* We need to be able to fix up arbitrary expressions in some statements. 11128 This is so that we can handle symbols that are an arbitrary distance from 11129 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask), 11130 which returns part of an address in a form which will be valid for 11131 a data instruction. We do this by pushing the expression into a symbol 11132 in the expr_section, and creating a fix for that. */ 11133 11134static void 11135fix_new_arm (frag, where, size, exp, pc_rel, reloc) 11136 fragS * frag; 11137 int where; 11138 short int size; 11139 expressionS * exp; 11140 int pc_rel; 11141 int reloc; 11142{ 11143 fixS * new_fix; 11144 arm_fix_data * arm_data; 11145 11146 switch (exp->X_op) 11147 { 11148 case O_constant: 11149 case O_symbol: 11150 case O_add: 11151 case O_subtract: 11152 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc); 11153 break; 11154 11155 default: 11156 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, 11157 pc_rel, reloc); 11158 break; 11159 } 11160 11161 /* Mark whether the fix is to a THUMB instruction, or an ARM 11162 instruction. */ 11163 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data)); 11164 new_fix->tc_fix_data = (PTR) arm_data; 11165 arm_data->thumb_mode = thumb_mode; 11166 11167 return; 11168} 11169 11170/* This fix_new is called by cons via TC_CONS_FIX_NEW. */ 11171 11172void 11173cons_fix_new_arm (frag, where, size, exp) 11174 fragS * frag; 11175 int where; 11176 int size; 11177 expressionS * exp; 11178{ 11179 bfd_reloc_code_real_type type; 11180 int pcrel = 0; 11181 11182 /* Pick a reloc. 11183 FIXME: @@ Should look at CPU word size. */ 11184 switch (size) 11185 { 11186 case 1: 11187 type = BFD_RELOC_8; 11188 break; 11189 case 2: 11190 type = BFD_RELOC_16; 11191 break; 11192 case 4: 11193 default: 11194 type = BFD_RELOC_32; 11195 break; 11196 case 8: 11197 type = BFD_RELOC_64; 11198 break; 11199 } 11200 11201 fix_new_exp (frag, where, (int) size, exp, pcrel, type); 11202} 11203 11204/* A good place to do this, although this was probably not intended 11205 for this kind of use. We need to dump the literal pool before 11206 references are made to a null symbol pointer. */ 11207 11208void 11209arm_cleanup () 11210{ 11211 if (current_poolP == NULL) 11212 return; 11213 11214 /* Put it at the end of text section. */ 11215 subseg_set (text_section, 0); 11216 s_ltorg (0); 11217 listing_prev_line (); 11218} 11219 11220void 11221arm_start_line_hook () 11222{ 11223 last_label_seen = NULL; 11224} 11225 11226void 11227arm_frob_label (sym) 11228 symbolS * sym; 11229{ 11230 last_label_seen = sym; 11231 11232 ARM_SET_THUMB (sym, thumb_mode); 11233 11234#if defined OBJ_COFF || defined OBJ_ELF 11235 ARM_SET_INTERWORK (sym, support_interwork); 11236#endif 11237 11238 /* Note - do not allow local symbols (.Lxxx) to be labeled 11239 as Thumb functions. This is because these labels, whilst 11240 they exist inside Thumb code, are not the entry points for 11241 possible ARM->Thumb calls. Also, these labels can be used 11242 as part of a computed goto or switch statement. eg gcc 11243 can generate code that looks like this: 11244 11245 ldr r2, [pc, .Laaa] 11246 lsl r3, r3, #2 11247 ldr r2, [r3, r2] 11248 mov pc, r2 11249 11250 .Lbbb: .word .Lxxx 11251 .Lccc: .word .Lyyy 11252 ..etc... 11253 .Laaa: .word Lbbb 11254 11255 The first instruction loads the address of the jump table. 11256 The second instruction converts a table index into a byte offset. 11257 The third instruction gets the jump address out of the table. 11258 The fourth instruction performs the jump. 11259 11260 If the address stored at .Laaa is that of a symbol which has the 11261 Thumb_Func bit set, then the linker will arrange for this address 11262 to have the bottom bit set, which in turn would mean that the 11263 address computation performed by the third instruction would end 11264 up with the bottom bit set. Since the ARM is capable of unaligned 11265 word loads, the instruction would then load the incorrect address 11266 out of the jump table, and chaos would ensue. */ 11267 if (label_is_thumb_function_name 11268 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L') 11269 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) 11270 { 11271 /* When the address of a Thumb function is taken the bottom 11272 bit of that address should be set. This will allow 11273 interworking between Arm and Thumb functions to work 11274 correctly. */ 11275 11276 THUMB_SET_FUNC (sym, 1); 11277 11278 label_is_thumb_function_name = false; 11279 } 11280} 11281 11282/* Adjust the symbol table. This marks Thumb symbols as distinct from 11283 ARM ones. */ 11284 11285void 11286arm_adjust_symtab () 11287{ 11288#ifdef OBJ_COFF 11289 symbolS * sym; 11290 11291 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym)) 11292 { 11293 if (ARM_IS_THUMB (sym)) 11294 { 11295 if (THUMB_IS_FUNC (sym)) 11296 { 11297 /* Mark the symbol as a Thumb function. */ 11298 if ( S_GET_STORAGE_CLASS (sym) == C_STAT 11299 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */ 11300 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC); 11301 11302 else if (S_GET_STORAGE_CLASS (sym) == C_EXT) 11303 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC); 11304 else 11305 as_bad (_("%s: unexpected function type: %d"), 11306 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym)); 11307 } 11308 else switch (S_GET_STORAGE_CLASS (sym)) 11309 { 11310 case C_EXT: 11311 S_SET_STORAGE_CLASS (sym, C_THUMBEXT); 11312 break; 11313 case C_STAT: 11314 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT); 11315 break; 11316 case C_LABEL: 11317 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL); 11318 break; 11319 default: 11320 /* Do nothing. */ 11321 break; 11322 } 11323 } 11324 11325 if (ARM_IS_INTERWORK (sym)) 11326 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF; 11327 } 11328#endif 11329#ifdef OBJ_ELF 11330 symbolS * sym; 11331 char bind; 11332 11333 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym)) 11334 { 11335 if (ARM_IS_THUMB (sym)) 11336 { 11337 elf_symbol_type * elf_sym; 11338 11339 elf_sym = elf_symbol (symbol_get_bfdsym (sym)); 11340 bind = ELF_ST_BIND (elf_sym); 11341 11342 /* If it's a .thumb_func, declare it as so, 11343 otherwise tag label as .code 16. */ 11344 if (THUMB_IS_FUNC (sym)) 11345 elf_sym->internal_elf_sym.st_info = 11346 ELF_ST_INFO (bind, STT_ARM_TFUNC); 11347 else 11348 elf_sym->internal_elf_sym.st_info = 11349 ELF_ST_INFO (bind, STT_ARM_16BIT); 11350 } 11351 } 11352#endif 11353} 11354 11355int 11356arm_data_in_code () 11357{ 11358 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5)) 11359 { 11360 *input_line_pointer = '/'; 11361 input_line_pointer += 5; 11362 *input_line_pointer = 0; 11363 return 1; 11364 } 11365 11366 return 0; 11367} 11368 11369char * 11370arm_canonicalize_symbol_name (name) 11371 char * name; 11372{ 11373 int len; 11374 11375 if (thumb_mode && (len = strlen (name)) > 5 11376 && streq (name + len - 5, "/data")) 11377 *(name + len - 5) = 0; 11378 11379 return name; 11380} 11381 11382boolean 11383arm_validate_fix (fixP) 11384 fixS * fixP; 11385{ 11386 /* If the destination of the branch is a defined symbol which does not have 11387 the THUMB_FUNC attribute, then we must be calling a function which has 11388 the (interfacearm) attribute. We look for the Thumb entry point to that 11389 function and change the branch to refer to that function instead. */ 11390 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23 11391 && fixP->fx_addsy != NULL 11392 && S_IS_DEFINED (fixP->fx_addsy) 11393 && ! THUMB_IS_FUNC (fixP->fx_addsy)) 11394 { 11395 fixP->fx_addsy = find_real_start (fixP->fx_addsy); 11396 return true; 11397 } 11398 11399 return false; 11400} 11401 11402#ifdef OBJ_COFF 11403/* This is a little hack to help the gas/arm/adrl.s test. It prevents 11404 local labels from being added to the output symbol table when they 11405 are used with the ADRL pseudo op. The ADRL relocation should always 11406 be resolved before the binbary is emitted, so it is safe to say that 11407 it is adjustable. */ 11408 11409boolean 11410arm_fix_adjustable (fixP) 11411 fixS * fixP; 11412{ 11413 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE) 11414 return 1; 11415 return 0; 11416} 11417#endif 11418#ifdef OBJ_ELF 11419/* Relocations against Thumb function names must be left unadjusted, 11420 so that the linker can use this information to correctly set the 11421 bottom bit of their addresses. The MIPS version of this function 11422 also prevents relocations that are mips-16 specific, but I do not 11423 know why it does this. 11424 11425 FIXME: 11426 There is one other problem that ought to be addressed here, but 11427 which currently is not: Taking the address of a label (rather 11428 than a function) and then later jumping to that address. Such 11429 addresses also ought to have their bottom bit set (assuming that 11430 they reside in Thumb code), but at the moment they will not. */ 11431 11432boolean 11433arm_fix_adjustable (fixP) 11434 fixS * fixP; 11435{ 11436 if (fixP->fx_addsy == NULL) 11437 return 1; 11438 11439 /* Prevent all adjustments to global symbols. */ 11440 if (S_IS_EXTERN (fixP->fx_addsy)) 11441 return 0; 11442 11443 if (S_IS_WEAK (fixP->fx_addsy)) 11444 return 0; 11445 11446 if (THUMB_IS_FUNC (fixP->fx_addsy) 11447 && fixP->fx_subsy == NULL) 11448 return 0; 11449 11450 /* We need the symbol name for the VTABLE entries. */ 11451 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 11452 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 11453 return 0; 11454 11455 return 1; 11456} 11457 11458const char * 11459elf32_arm_target_format () 11460{ 11461 if (target_big_endian) 11462 { 11463 if (target_oabi) 11464 return "elf32-bigarm-oabi"; 11465 else 11466 return "elf32-bigarm"; 11467 } 11468 else 11469 { 11470 if (target_oabi) 11471 return "elf32-littlearm-oabi"; 11472 else 11473 return "elf32-littlearm"; 11474 } 11475} 11476 11477void 11478armelf_frob_symbol (symp, puntp) 11479 symbolS * symp; 11480 int * puntp; 11481{ 11482 elf_frob_symbol (symp, puntp); 11483} 11484 11485int 11486arm_force_relocation (fixp) 11487 struct fix * fixp; 11488{ 11489 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 11490 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY 11491 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH 11492 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX 11493 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX 11494 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23) 11495 return 1; 11496 11497 return 0; 11498} 11499 11500static bfd_reloc_code_real_type 11501arm_parse_reloc () 11502{ 11503 char id [16]; 11504 char * ip; 11505 unsigned int i; 11506 static struct 11507 { 11508 char * str; 11509 int len; 11510 bfd_reloc_code_real_type reloc; 11511 } 11512 reloc_map[] = 11513 { 11514#define MAP(str,reloc) { str, sizeof (str) - 1, reloc } 11515 MAP ("(got)", BFD_RELOC_ARM_GOT32), 11516 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF), 11517 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)" 11518 branch instructions generated by GCC for PLT relocs. */ 11519 MAP ("(plt)", BFD_RELOC_ARM_PLT32), 11520 { NULL, 0, BFD_RELOC_UNUSED } 11521#undef MAP 11522 }; 11523 11524 for (i = 0, ip = input_line_pointer; 11525 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip)); 11526 i++, ip++) 11527 id[i] = TOLOWER (*ip); 11528 11529 for (i = 0; reloc_map[i].str; i++) 11530 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0) 11531 break; 11532 11533 input_line_pointer += reloc_map[i].len; 11534 11535 return reloc_map[i].reloc; 11536} 11537 11538static void 11539s_arm_elf_cons (nbytes) 11540 int nbytes; 11541{ 11542 expressionS exp; 11543 11544#ifdef md_flush_pending_output 11545 md_flush_pending_output (); 11546#endif 11547 11548 if (is_it_end_of_statement ()) 11549 { 11550 demand_empty_rest_of_line (); 11551 return; 11552 } 11553 11554#ifdef md_cons_align 11555 md_cons_align (nbytes); 11556#endif 11557 11558 do 11559 { 11560 bfd_reloc_code_real_type reloc; 11561 11562 expression (& exp); 11563 11564 if (exp.X_op == O_symbol 11565 && * input_line_pointer == '(' 11566 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED) 11567 { 11568 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc); 11569 int size = bfd_get_reloc_size (howto); 11570 11571 if (size > nbytes) 11572 as_bad ("%s relocations do not fit in %d bytes", 11573 howto->name, nbytes); 11574 else 11575 { 11576 register char *p = frag_more ((int) nbytes); 11577 int offset = nbytes - size; 11578 11579 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size, 11580 &exp, 0, reloc); 11581 } 11582 } 11583 else 11584 emit_expr (&exp, (unsigned int) nbytes); 11585 } 11586 while (*input_line_pointer++ == ','); 11587 11588 /* Put terminator back into stream. */ 11589 input_line_pointer --; 11590 demand_empty_rest_of_line (); 11591} 11592 11593#endif /* OBJ_ELF */ 11594 11595/* This is called from HANDLE_ALIGN in write.c. Fill in the contents 11596 of an rs_align_code fragment. */ 11597 11598void 11599arm_handle_align (fragP) 11600 fragS *fragP; 11601{ 11602 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 }; 11603 static char const thumb_noop[2] = { 0xc0, 0x46 }; 11604 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 }; 11605 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 }; 11606 11607 int bytes, fix, noop_size; 11608 char * p; 11609 const char * noop; 11610 11611 if (fragP->fr_type != rs_align_code) 11612 return; 11613 11614 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; 11615 p = fragP->fr_literal + fragP->fr_fix; 11616 fix = 0; 11617 11618 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE) 11619 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE; 11620 11621 if (fragP->tc_frag_data) 11622 { 11623 if (target_big_endian) 11624 noop = thumb_bigend_noop; 11625 else 11626 noop = thumb_noop; 11627 noop_size = sizeof (thumb_noop); 11628 } 11629 else 11630 { 11631 if (target_big_endian) 11632 noop = arm_bigend_noop; 11633 else 11634 noop = arm_noop; 11635 noop_size = sizeof (arm_noop); 11636 } 11637 11638 if (bytes & (noop_size - 1)) 11639 { 11640 fix = bytes & (noop_size - 1); 11641 memset (p, 0, fix); 11642 p += fix; 11643 bytes -= fix; 11644 } 11645 11646 while (bytes >= noop_size) 11647 { 11648 memcpy (p, noop, noop_size); 11649 p += noop_size; 11650 bytes -= noop_size; 11651 fix += noop_size; 11652 } 11653 11654 fragP->fr_fix += fix; 11655 fragP->fr_var = noop_size; 11656} 11657 11658/* Called from md_do_align. Used to create an alignment 11659 frag in a code section. */ 11660 11661void 11662arm_frag_align_code (n, max) 11663 int n; 11664 int max; 11665{ 11666 char * p; 11667 11668 /* We assume that there will never be a requirment 11669 to support alignments greater than 32 bytes. */ 11670 if (max > MAX_MEM_FOR_RS_ALIGN_CODE) 11671 as_fatal (_("alignments greater than 32 bytes not supported in .text sections.")); 11672 11673 p = frag_var (rs_align_code, 11674 MAX_MEM_FOR_RS_ALIGN_CODE, 11675 1, 11676 (relax_substateT) max, 11677 (symbolS *) NULL, 11678 (offsetT) n, 11679 (char *) NULL); 11680 *p = 0; 11681 11682} 11683 11684/* Perform target specific initialisation of a frag. */ 11685 11686void 11687arm_init_frag (fragP) 11688 fragS *fragP; 11689{ 11690 /* Record whether this frag is in an ARM or a THUMB area. */ 11691 fragP->tc_frag_data = thumb_mode; 11692} 11693