1/* tc-score.c -- Assembler for Score 2 Copyright (C) 2006-2022 Free Software Foundation, Inc. 3 Contributed by: 4 Brain.lin (brain.lin@sunplusct.com) 5 Mei Ligang (ligang@sunnorth.com.cn) 6 Pei-Lin Tsai (pltsai@sunplus.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 3, 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, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 23 02110-1301, USA. */ 24 25#include "tc-score7.c" 26 27static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED); 28static void s3_s_score_text (int ignore); 29static void s3_score_s_section (int ignore); 30static void s3_s_change_sec (int sec); 31static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED); 32static void s3_s_score_ent (int aent); 33static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED); 34static void s3_s_score_end (int x ATTRIBUTE_UNUSED); 35static void s3_s_score_set (int x ATTRIBUTE_UNUSED); 36static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED); 37static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED); 38static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED); 39static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED); 40static void s3_s_score_lcomm (int bytes_p); 41 42static void s_score_bss (int ignore ATTRIBUTE_UNUSED); 43static void s_score_text (int ignore); 44static void s_section (int ignore); 45static void s_change_sec (int sec); 46static void s_score_mask (int reg_type ATTRIBUTE_UNUSED); 47static void s_score_ent (int aent); 48static void s_score_frame (int ignore ATTRIBUTE_UNUSED); 49static void s_score_end (int x ATTRIBUTE_UNUSED); 50static void s_score_set (int x ATTRIBUTE_UNUSED); 51static void s_score_cpload (int ignore ATTRIBUTE_UNUSED); 52static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED); 53static void s_score_gpword (int ignore ATTRIBUTE_UNUSED); 54static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED); 55static void s_score_lcomm (int bytes_p); 56 57/* s3: hooks. */ 58static void s3_md_number_to_chars (char *buf, valueT val, int n); 59static valueT s3_md_chars_to_number (char *buf, int n); 60static void s3_assemble (char *str); 61static void s3_operand (expressionS *); 62static void s3_begin (void); 63static void s3_number_to_chars (char *buf, valueT val, int n); 64static const char *s3_atof (int type, char *litP, int *sizeP); 65static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED); 66static void s3_validate_fix (fixS *fixP); 67static int s3_force_relocation (struct fix *fixp); 68static bool s3_fix_adjustable (fixS * fixP); 69static void s3_elf_final_processing (void); 70static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED); 71static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED); 72static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp); 73static long s3_pcrel_from (fixS * fixP); 74static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size); 75static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg); 76static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp); 77 78/* s3: utils. */ 79static void s3_do_ldst_insn (char *); 80static void s3_do_crdcrscrsimm5 (char *); 81static void s3_do_ldst_unalign (char *); 82static void s3_do_ldst_atomic (char *); 83static void s3_do_ldst_cop (char *); 84static void s3_do_macro_li_rdi32 (char *); 85static void s3_do_macro_la_rdi32 (char *); 86static void s3_do_macro_rdi32hi (char *); 87static void s3_do_macro_rdi32lo (char *); 88static void s3_do_macro_mul_rdrsrs (char *); 89static void s3_do_macro_bcmp (char *); 90static void s3_do_macro_bcmpz (char *); 91static void s3_do_macro_ldst_label (char *); 92static void s3_do_branch (char *); 93static void s3_do_jump (char *); 94static void s3_do_empty (char *); 95static void s3_do16_int (char *); 96static void s3_do_rdrsrs (char *); 97static void s3_do_rdsi16 (char *); 98static void s3_do_rdrssi14 (char *); 99static void s3_do_sub_rdsi16 (char *); 100static void s3_do_sub_rdi16 (char *); 101static void s3_do_sub_rdrssi14 (char *); 102static void s3_do_rdrsi5 (char *); 103static void s3_do_rdrsi14 (char *); 104static void s3_do_rdi16 (char *); 105static void s3_do_ldis (char *); 106static void s3_do_xrsi5 (char *); 107static void s3_do_rdrs (char *); 108static void s3_do_rdxrs (char *); 109static void s3_do_rsrs (char *); 110static void s3_do_rdcrs (char *); 111static void s3_do_rdsrs (char *); 112static void s3_do_rd (char *); 113static void s3_do16_dsp (char *); 114static void s3_do16_dsp2 (char *); 115static void s3_do_dsp (char *); 116static void s3_do_dsp2 (char *); 117static void s3_do_dsp3 (char *); 118static void s3_do_rs (char *); 119static void s3_do_i15 (char *); 120static void s3_do_xi5x (char *); 121static void s3_do_ceinst (char *); 122static void s3_do_cache (char *); 123static void s3_do16_rdrs2 (char *); 124static void s3_do16_br (char *); 125static void s3_do16_brr (char *); 126static void s3_do_ltb (char *); 127static void s3_do16_mv_cmp (char *); 128static void s3_do16_addi (char *); 129static void s3_do16_cmpi (char *); 130static void s3_do16_rdi5 (char *); 131static void s3_do16_xi5 (char *); 132static void s3_do16_ldst_insn (char *); 133static void s3_do16_slli_srli (char *); 134static void s3_do16_ldiu (char *); 135static void s3_do16_push_pop (char *); 136static void s3_do16_rpush (char *); 137static void s3_do16_rpop (char *); 138static void s3_do16_branch (char *); 139static void s3_do_lw48 (char *); 140static void s3_do_sw48 (char *); 141static void s3_do_ldi48 (char *); 142static void s3_do_sdbbp48 (char *); 143static void s3_do_and48 (char *); 144static void s3_do_or48 (char *); 145static void s3_do_mbitclr (char *); 146static void s3_do_mbitset (char *); 147static void s3_do_rdi16_pic (char *); 148static void s3_do_addi_s_pic (char *); 149static void s3_do_addi_u_pic (char *); 150static void s3_do_lw_pic (char *); 151 152#define MARCH_SCORE3 "score3" 153#define MARCH_SCORE3D "score3d" 154#define MARCH_SCORE7 "score7" 155#define MARCH_SCORE7D "score7d" 156#define MARCH_SCORE5 "score5" 157#define MARCH_SCORE5U "score5u" 158 159#define SCORE_BI_ENDIAN 160 161#ifdef SCORE_BI_ENDIAN 162#define OPTION_EB (OPTION_MD_BASE + 0) 163#define OPTION_EL (OPTION_MD_BASE + 1) 164#else 165#if TARGET_BYTES_BIG_ENDIAN 166#define OPTION_EB (OPTION_MD_BASE + 0) 167#else 168#define OPTION_EL (OPTION_MD_BASE + 1) 169#endif 170#endif 171#define OPTION_FIXDD (OPTION_MD_BASE + 2) 172#define OPTION_NWARN (OPTION_MD_BASE + 3) 173#define OPTION_SCORE5 (OPTION_MD_BASE + 4) 174#define OPTION_SCORE5U (OPTION_MD_BASE + 5) 175#define OPTION_SCORE7 (OPTION_MD_BASE + 6) 176#define OPTION_R1 (OPTION_MD_BASE + 7) 177#define OPTION_O0 (OPTION_MD_BASE + 8) 178#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9) 179#define OPTION_PIC (OPTION_MD_BASE + 10) 180#define OPTION_MARCH (OPTION_MD_BASE + 11) 181#define OPTION_SCORE3 (OPTION_MD_BASE + 12) 182 183/* This array holds the chars that always start a comment. If the 184 pre-processor is disabled, these aren't very useful. */ 185const char comment_chars[] = "#"; 186const char line_comment_chars[] = "#"; 187const char line_separator_chars[] = ";"; 188/* Chars that can be used to separate mant from exp in floating point numbers. */ 189const char EXP_CHARS[] = "eE"; 190const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; 191 192#ifdef OBJ_ELF 193/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ 194symbolS *GOT_symbol; 195#endif 196 197const pseudo_typeS md_pseudo_table[] = 198{ 199 {"bss", s_score_bss, 0}, 200 {"text", s_score_text, 0}, 201 {"word", cons, 4}, 202 {"long", cons, 4}, 203 {"extend", float_cons, 'x'}, 204 {"ldouble", float_cons, 'x'}, 205 {"packed", float_cons, 'p'}, 206 {"end", s_score_end, 0}, 207 {"ent", s_score_ent, 0}, 208 {"frame", s_score_frame, 0}, 209 {"rdata", s_change_sec, 'r'}, 210 {"sdata", s_change_sec, 's'}, 211 {"set", s_score_set, 0}, 212 {"mask", s_score_mask, 'R'}, 213 {"dword", cons, 8}, 214 {"lcomm", s_score_lcomm, 1}, 215 {"section", s_section, 0}, 216 {"cpload", s_score_cpload, 0}, 217 {"cprestore", s_score_cprestore, 0}, 218 {"gpword", s_score_gpword, 0}, 219 {"cpadd", s_score_cpadd, 0}, 220 {0, 0, 0} 221}; 222 223const char *md_shortopts = "nO::g::G:"; 224struct option md_longopts[] = 225{ 226#ifdef OPTION_EB 227 {"EB" , no_argument, NULL, OPTION_EB}, 228#endif 229#ifdef OPTION_EL 230 {"EL" , no_argument, NULL, OPTION_EL}, 231#endif 232 {"FIXDD" , no_argument, NULL, OPTION_FIXDD}, 233 {"NWARN" , no_argument, NULL, OPTION_NWARN}, 234 {"SCORE5" , no_argument, NULL, OPTION_SCORE5}, 235 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U}, 236 {"SCORE7" , no_argument, NULL, OPTION_SCORE7}, 237 {"USE_R1" , no_argument, NULL, OPTION_R1}, 238 {"O0" , no_argument, NULL, OPTION_O0}, 239 {"V" , no_argument, NULL, OPTION_SCORE_VERSION}, 240 {"KPIC" , no_argument, NULL, OPTION_PIC}, 241 {"march=" , required_argument, NULL, OPTION_MARCH}, 242 {"SCORE3" , no_argument, NULL, OPTION_SCORE3}, 243 {NULL , no_argument, NULL, 0} 244}; 245 246size_t md_longopts_size = sizeof (md_longopts); 247 248#define s3_GP 28 249#define s3_PIC_CALL_REG 29 250#define s3_MAX_LITERAL_POOL_SIZE 1024 251#define s3_FAIL 0x80000000 252#define s3_SUCCESS 0 253#define s3_INSN48_SIZE 6 254#define s3_INSN_SIZE 4 255#define s3_INSN16_SIZE 2 256#define s3_RELAX_INST_NUM 3 257 258/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */ 259#define s3_BAD_ARGS _("bad arguments to instruction") 260#define s3_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions") 261#define s3_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu") 262#define s3_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction") 263#define s3_BAD_SKIP_COMMA s3_BAD_ARGS 264#define s3_BAD_GARBAGE _("garbage following instruction"); 265 266#define s3_skip_whitespace(str) while (*(str) == ' ') ++(str) 267 268/* The name of the readonly data section. */ 269#define s3_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ 270 ? ".data" \ 271 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ 272 ? ".rdata" \ 273 : OUTPUT_FLAVOR == bfd_target_coff_flavour \ 274 ? ".rdata" \ 275 : OUTPUT_FLAVOR == bfd_target_elf_flavour \ 276 ? ".rodata" \ 277 : (abort (), "")) 278 279#define s3_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \ 280 ((relax_substateT) \ 281 (((old) << 23) \ 282 | ((new) << 16) \ 283 | ((type) << 9) \ 284 | ((reloc1) << 5) \ 285 | ((reloc2) << 1) \ 286 | ((opt) ? 1 : 0))) 287 288#define s3_RELAX_OLD(i) (((i) >> 23) & 0x7f) 289#define s3_RELAX_NEW(i) (((i) >> 16) & 0x7f) 290#define s3_RELAX_TYPE(i) (((i) >> 9) & 0x7f) 291#define s3_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf) 292#define s3_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf) 293#define s3_RELAX_OPT(i) ((i) & 1) 294 295#define s3_SET_INSN_ERROR(s) (s3_inst.error = (s)) 296#define s3_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL) 297#define s3_INSN_IS_48_P(s) (strstr (str, "48") != NULL) 298#define s3_GET_INSN_CLASS(type) (s3_get_insn_class_from_type (type)) 299#define s3_GET_INSN_SIZE(type) ((s3_GET_INSN_CLASS (type) == INSN_CLASS_16) \ 300 ? s3_INSN16_SIZE : (s3_GET_INSN_CLASS (type) == INSN_CLASS_48) \ 301 ? s3_INSN48_SIZE : s3_INSN_SIZE) 302 303#define s3_INSN_NAME_LEN 16 304 305/* Relax will need some padding for alignment. */ 306#define s3_RELAX_PAD_BYTE 3 307 308 309#define s3_USE_GLOBAL_POINTER_OPT 1 310 311/* Enumeration matching entries in table above. */ 312enum s3_score_reg_type 313{ 314 s3_REG_TYPE_SCORE = 0, 315#define s3_REG_TYPE_FIRST s3_REG_TYPE_SCORE 316 s3_REG_TYPE_SCORE_SR = 1, 317 s3_REG_TYPE_SCORE_CR = 2, 318 s3_REG_TYPE_MAX = 3 319}; 320 321enum s3_score_pic_level 322{ 323 s3_NO_PIC, 324 s3_PIC 325}; 326static enum s3_score_pic_level s3_score_pic = s3_NO_PIC; 327 328enum s3_insn_type_for_dependency 329{ 330 s3_D_mtcr, 331 s3_D_all_insn 332}; 333 334struct s3_insn_to_dependency 335{ 336 const char *insn_name; 337 enum s3_insn_type_for_dependency type; 338}; 339 340struct s3_data_dependency 341{ 342 enum s3_insn_type_for_dependency pre_insn_type; 343 char pre_reg[6]; 344 enum s3_insn_type_for_dependency cur_insn_type; 345 char cur_reg[6]; 346 int bubblenum_7; 347 int bubblenum_3; 348 int warn_or_error; /* warning - 0; error - 1 */ 349}; 350 351static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] = 352{ 353 /* move special instruction. */ 354 {"mtcr", s3_D_mtcr}, 355}; 356 357static const struct s3_data_dependency s3_data_dependency_table[] = 358{ 359 /* Status register. */ 360 {s3_D_mtcr, "cr0", s3_D_all_insn, "", 5, 1, 0}, 361}; 362 363/* Used to contain constructed error messages. */ 364static char s3_err_msg[255]; 365 366static int s3_fix_data_dependency = 0; 367static int s3_warn_fix_data_dependency = 1; 368 369static int s3_in_my_get_expression = 0; 370 371/* Default, pop warning message when using r1. */ 372static int s3_nor1 = 1; 373 374/* Default will do instruction relax, -O0 will set s3_g_opt = 0. */ 375static unsigned int s3_g_opt = 1; 376 377/* The size of the small data section. */ 378static unsigned int s3_g_switch_value = 8; 379 380static segT s3_pdr_seg; 381 382struct s3_score_it 383{ 384 char name[s3_INSN_NAME_LEN]; 385 bfd_vma instruction; 386 bfd_vma relax_inst; 387 int size; 388 int relax_size; 389 enum score_insn_type type; 390 char str[s3_MAX_LITERAL_POOL_SIZE]; 391 const char *error; 392 int bwarn; 393 char reg[s3_INSN_NAME_LEN]; 394 struct 395 { 396 bfd_reloc_code_real_type type; 397 expressionS exp; 398 int pc_rel; 399 }reloc; 400}; 401static struct s3_score_it s3_inst; 402 403typedef struct s3_proc 404{ 405 symbolS *isym; 406 unsigned long reg_mask; 407 unsigned long reg_offset; 408 unsigned long fpreg_mask; 409 unsigned long leaf; 410 unsigned long frame_offset; 411 unsigned long frame_reg; 412 unsigned long pc_reg; 413} s3_procS; 414static s3_procS s3_cur_proc; 415static s3_procS *s3_cur_proc_ptr; 416static int s3_numprocs; 417 418 419/* Structure for a hash table entry for a register. */ 420struct s3_reg_entry 421{ 422 const char *name; 423 int number; 424}; 425 426static const struct s3_reg_entry s3_score_rn_table[] = 427{ 428 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, 429 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, 430 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11}, 431 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15}, 432 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19}, 433 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23}, 434 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27}, 435 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31}, 436 {NULL, 0} 437}; 438 439static const struct s3_reg_entry s3_score_srn_table[] = 440{ 441 {"sr0", 0}, {"sr1", 1}, {"sr2", 2}, 442 {NULL, 0} 443}; 444 445static const struct s3_reg_entry s3_score_crn_table[] = 446{ 447 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3}, 448 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7}, 449 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11}, 450 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15}, 451 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19}, 452 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23}, 453 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27}, 454 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31}, 455 {NULL, 0} 456}; 457 458struct s3_reg_map 459{ 460 const struct s3_reg_entry *names; 461 int max_regno; 462 htab_t htab; 463 const char *expected; 464}; 465 466static struct s3_reg_map s3_all_reg_maps[] = 467{ 468 {s3_score_rn_table, 31, NULL, N_("S+core register expected")}, 469 {s3_score_srn_table, 2, NULL, N_("S+core special-register expected")}, 470 {s3_score_crn_table, 31, NULL, N_("S+core co-processor register expected")}, 471}; 472 473static htab_t s3_score_ops_hsh = NULL; 474static htab_t s3_dependency_insn_hsh = NULL; 475 476 477struct s3_datafield_range 478{ 479 int data_type; 480 int bits; 481 int range[2]; 482}; 483 484static struct s3_datafield_range s3_score_df_range[] = 485{ 486 {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */ 487 {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */ 488 {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */ 489 {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */ 490 {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ 491 {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ 492 {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */ 493 {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */ 494 {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */ 495 {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */ 496 {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ 497 {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */ 498 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */ 499 {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ 500 {_IMM20, 20, {0, (1 << 20) - 1}}, 501 {_IMM25, 25, {0, (1 << 25) - 1}}, 502 {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */ 503 {_DISP11div2, 11, {0, 0}}, 504 {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */ 505 {_DISP24div2, 24, {0, 0}}, 506 {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}}, 507 {_VALUE_HI16, 16, {0, (1 << 16) - 1}}, 508 {_VALUE_LO16, 16, {0, (1 << 16) - 1}}, 509 {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}}, 510 {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ 511 {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */ 512 {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */ 513 {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ 514 {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */ 515 {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */ 516 {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */ 517 {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */ 518 {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */ 519 {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */ 520 {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */ 521 {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */ 522 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ 523 {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ 524 {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */ 525 {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */ 526 {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */ 527 {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */ 528 {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ 529 {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ 530 {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ 531 {_SIMM5, 5, {-(1 << 4), (1 << 4) - 1}}, /* ( -16 ~ 15 ) */ 532 {_SIMM6, 6, {-(1 << 5), (1 << 5) - 1}}, /* ( -32 ~ 31 ) */ 533 {_IMM32, 32, {0, 0xfffffff}}, 534 {_SIMM32, 32, {-0x80000000, 0x7fffffff}}, 535 {_IMM11, 11, {0, (1 << 11) - 1}}, 536}; 537 538struct s3_asm_opcode 539{ 540 /* Instruction name. */ 541 const char *template_name; 542 543 /* Instruction Opcode. */ 544 bfd_vma value; 545 546 /* Instruction bit mask. */ 547 bfd_vma bitmask; 548 549 /* Relax instruction opcode. 0x8000 imply no relaxation. */ 550 bfd_vma relax_value; 551 552 /* Instruction type. */ 553 enum score_insn_type type; 554 555 /* Function to call to parse args. */ 556 void (*parms) (char *); 557}; 558 559static const struct s3_asm_opcode s3_score_ldst_insns[] = 560{ 561 {"lw", 0x20000000, 0x3e000000, 0x1000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, 562 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, 563 {"lw", 0x0e000000, 0x3e000007, 0x0040, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, 564 {"lh", 0x22000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, 565 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, 566 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, 567 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, 568 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, 569 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, 570 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, 571 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, 572 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, 573 {"sw", 0x28000000, 0x3e000000, 0x2000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, 574 {"sw", 0x06000004, 0x3e000007, 0x0060, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, 575 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, 576 {"sh", 0x2a000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, 577 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, 578 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, 579 {"lbu", 0x2c000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, 580 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, 581 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, 582 {"sb", 0x2e000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, 583 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, 584 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, 585}; 586 587static const struct s3_asm_opcode s3_score_insns[] = 588{ 589 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3}, 590 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3}, 591 {"add", 0x00000010, 0x3e0003ff, 0x4800, Rd_Rs_Rs, s3_do_rdrsrs}, 592 {"add.c", 0x00000011, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 593 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 594 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 595 {"addc.c", 0x00000013, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 596 {"addi", 0x02000000, 0x3e0e0001, 0x5c00, Rd_SI16, s3_do_rdsi16}, 597 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdsi16}, 598 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16}, 599 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16}, 600 {"addi!", 0x5c00, 0x7c00, 0x8000, Rd_SI6, s3_do16_addi}, 601 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14}, 602 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14}, 603 604 /* add.c <-> add!. */ 605 {"add!", 0x4800, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, 606 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16}, 607 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16}, 608 {"subis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16}, 609 {"subis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16}, 610 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14}, 611 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14}, 612 {"and", 0x00000020, 0x3e0003ff, 0x4b00, Rd_Rs_Rs, s3_do_rdrsrs}, 613 {"and.c", 0x00000021, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 614 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 615 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 616 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 617 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 618 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, 619 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, 620 621 /* and.c <-> and!. */ 622 {"and!", 0x4b00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, 623 {"bcs", 0x08000000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 624 {"bcc", 0x08000400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 625 {"bcnz", 0x08003800, 0x3e007c01, 0x3200, PC_DISP19div2, s3_do_branch}, 626 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 627 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 628 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 629 {"bcnz!", 0x3200, 0x7f00, 0x08003800, PC_DISP8div2, s3_do16_branch}, 630 {"beq", 0x08001000, 0x3e007c01, 0x3800, PC_DISP19div2, s3_do_branch}, 631 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 632 {"beq!", 0x3800, 0x7e00, 0x08001000, PC_DISP8div2, s3_do16_branch}, 633 {"bgtu", 0x08000800, 0x3e007c01, 0x3400, PC_DISP19div2, s3_do_branch}, 634 {"bgt", 0x08001800, 0x3e007c01, 0x3c00, PC_DISP19div2, s3_do_branch}, 635 {"bge", 0x08002000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 636 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 637 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 638 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 639 {"bgtu!", 0x3400, 0x7e00, 0x08000800, PC_DISP8div2, s3_do16_branch}, 640 {"bgt!", 0x3c00, 0x7e00, 0x08001800, PC_DISP8div2, s3_do16_branch}, 641 {"bitclr", 0x00000028, 0x3e0003ff, 0x5000, Rd_Rs_I5, s3_do_rdrsi5}, 642 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 643 644 {"mbitclr", 0x00000064, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitclr}, 645 {"mbitset", 0x0000006c, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitset}, 646 647 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 648 {"bitset", 0x0000002a, 0x3e0003ff, 0x5200, Rd_Rs_I5, s3_do_rdrsi5}, 649 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 650 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x5400, x_Rs_I5, s3_do_xrsi5}, 651 {"bittgl", 0x0000002e, 0x3e0003ff, 0x5600, Rd_Rs_I5, s3_do_rdrsi5}, 652 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 653 {"bitclr!", 0x5000, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, 654 {"bitset!", 0x5200, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, 655 {"bittst!", 0x5400, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, 656 {"bittgl!", 0x5600, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, 657 {"bleu", 0x08000c00, 0x3e007c01, 0x3600, PC_DISP19div2, s3_do_branch}, 658 {"ble", 0x08001c00, 0x3e007c01, 0x3e00, PC_DISP19div2, s3_do_branch}, 659 {"blt", 0x08002400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 660 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 661 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 662 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 663 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 664 {"bleu!", 0x3600, 0x7e00, 0x08000c00, PC_DISP8div2, s3_do16_branch}, 665 {"ble!", 0x3e00, 0x7e00, 0x08001c00, PC_DISP8div2, s3_do16_branch}, 666 {"bmi", 0x08002800, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 667 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 668 {"bne", 0x08001400, 0x3e007c01, 0x3a00, PC_DISP19div2, s3_do_branch}, 669 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 670 {"bne!", 0x3a00, 0x7e00, 0x08001400, PC_DISP8div2, s3_do16_branch}, 671 {"bpl", 0x08002c00, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 672 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 673 {"brcs", 0x00000008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 674 {"brcc", 0x00000408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 675 {"brgtu", 0x00000808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 676 {"brleu", 0x00000c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 677 {"breq", 0x00001008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 678 {"brne", 0x00001408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 679 {"brgt", 0x00001808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 680 {"brle", 0x00001c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 681 {"brge", 0x00002008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 682 {"brlt", 0x00002408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 683 {"brmi", 0x00002808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 684 {"brpl", 0x00002c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 685 {"brvs", 0x00003008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 686 {"brvc", 0x00003408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 687 {"brcnz", 0x00003808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 688 {"br", 0x00003c08, 0x3e007fff, 0x0080, x_Rs_x, s3_do_rs}, 689 {"brcsl", 0x00000009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 690 {"brccl", 0x00000409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 691 {"brgtul", 0x00000809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 692 {"brleul", 0x00000c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 693 {"breql", 0x00001009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 694 {"brnel", 0x00001409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 695 {"brgtl", 0x00001809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 696 {"brlel", 0x00001c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 697 {"brgel", 0x00002009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 698 {"brltl", 0x00002409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 699 {"brmil", 0x00002809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 700 {"brpll", 0x00002c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 701 {"brvsl", 0x00003009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 702 {"brvcl", 0x00003409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 703 {"brcnzl", 0x00003809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, 704 {"brl", 0x00003c09, 0x3e007fff, 0x00a0, x_Rs_x, s3_do_rs}, 705 {"br!", 0x0080, 0x7fe0, 0x8000, x_Rs, s3_do16_br}, 706 {"brl!", 0x00a0, 0x7fe0, 0x8000, x_Rs, s3_do16_br}, 707 {"brr!", 0x00c0, 0x7fe0, 0x8000, x_Rs, s3_do16_brr}, 708 {"bvs", 0x08003000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 709 {"bvc", 0x08003400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 710 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 711 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, 712 {"b!", 0x3000, 0x7e00, 0x08003c00, PC_DISP8div2, s3_do16_branch}, 713 {"b", 0x08003c00, 0x3e007c01, 0x3000, PC_DISP19div2, s3_do_branch}, 714 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s3_do_cache}, 715 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s3_do_ceinst}, 716 {"clz", 0x0000001c, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 717 {"cmp.c", 0x00300019, 0x3ff003ff, 0x4400, x_Rs_Rs, s3_do_rsrs}, 718 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s3_do_rs}, 719 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x6000, Rd_SI16, s3_do_rdsi16}, 720 721 /* cmp.c <-> cmp!. */ 722 {"cmp!", 0x4400, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp}, 723 {"cmpi!", 0x6000, 0x7c00, 0x8000, Rd_SI5, s3_do16_cmpi}, 724 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, 725 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, 726 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, 727 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, 728 {"disint!", 0x00e0, 0xffe1, 0x8000, NO16_OPD, s3_do16_int}, 729 {"enint!", 0x00e1, 0xffe1, 0x8000, NO16_OPD, s3_do16_int}, 730 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 731 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 732 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 733 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 734 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 735 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 736 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 737 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 738 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump}, 739 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump}, 740 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s3_do_ldst_atomic}, 741 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s3_do_ldst_unalign}, 742 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign}, 743 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign}, 744 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, 745 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, 746 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, 747 748 /* s3_inst.relax */ 749 {"ldi", 0x020c0000, 0x3e0e0000, 0x6400, Rd_SI16, s3_do_rdsi16}, 750 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s3_do_ldis}, 751 752 /* ldi <-> ldiu!. */ 753 {"ldiu!", 0x6400, 0x7c00, 0x8000, Rd_I5, s3_do16_ldiu}, 754 755 /*ltbb! , ltbh! ltbw! */ 756 {"ltbw", 0x00000032, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, 757 {"ltbh", 0x00000132, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, 758 {"ltbb", 0x00000332, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, 759 {"lw!", 0x1000, 0x7000, 0x8000, Rd_rvalueRs, s3_do16_ldst_insn}, 760 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, 761 {"mfcel!", 0x7100, 0x7ff0, 0x00000448, x_Rs, s3_do16_dsp}, 762 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 763 {"mad.f!", 0x7400, 0x7f00, 0x38000080, Rd_Rs, s3_do16_dsp2}, 764 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 765 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 766 {"madh.fs!", 0x7b00, 0x7f00, 0x380002c3, Rd_Rs, s3_do16_dsp2}, 767 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 768 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 769 {"madl.fs!", 0x7a00, 0x7f00, 0x380000c2, Rd_Rs, s3_do16_dsp2}, 770 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 771 {"madu!", 0x7500, 0x7f00, 0x38000020, Rd_Rs, s3_do16_dsp2}, 772 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 773 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 774 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 775 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 776 {"mazh.f!", 0x7900, 0x7f00, 0x3800038c, Rd_Rs, s3_do16_dsp2}, 777 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 778 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 779 {"mazl.f!", 0x7800, 0x7f00, 0x38000182, Rd_Rs, s3_do16_dsp2}, 780 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, 781 {"mfceh!", 0x7110, 0x7ff0, 0x00000848, x_Rs, s3_do16_dsp}, 782 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 783 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s3_do_rdsrs}, 784 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 785 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 786 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 787 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 788 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 789 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 790 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 791 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 792 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 793 {"msb.f!", 0x7600, 0x7f00, 0x38000081, Rd_Rs, s3_do16_dsp2}, 794 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 795 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 796 {"msbh.fs!", 0x7f00, 0x7f00, 0x380002c5, Rd_Rs, s3_do16_dsp2}, 797 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 798 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 799 {"msbl.fs!", 0x7e00, 0x7f00, 0x380000c4, Rd_Rs, s3_do16_dsp2}, 800 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 801 {"msbu!", 0x7700, 0x7f00, 0x38000021, Rd_Rs, s3_do16_dsp2}, 802 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 803 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 804 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 805 {"mszh.f!", 0x7d00, 0x7f00, 0x38000385, Rd_Rs, s3_do16_dsp2}, 806 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 807 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, 808 {"mszl.f!", 0x7c00, 0x7f00, 0x38000184, Rd_Rs, s3_do16_dsp2}, 809 {"mtcel!", 0x7000, 0x7ff0, 0x0000044a, x_Rs, s3_do16_dsp}, 810 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, 811 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, 812 {"mtceh!", 0x7010, 0x7ff0, 0x0000084a, x_Rs, s3_do16_dsp}, 813 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 814 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s3_do_rdsrs}, 815 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 816 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 817 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 818 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 819 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 820 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 821 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, 822 {"mul.f!", 0x7200, 0x7f00, 0x00000041, Rd_Rs, s3_do16_dsp2}, 823 {"mulu!", 0x7300, 0x7f00, 0x00000042, Rd_Rs, s3_do16_dsp2}, 824 {"mulr.l", 0x00000140, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 825 {"mulr.h", 0x00000240, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 826 {"mulr", 0x00000340, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 827 {"mulr.lf", 0x00000141, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 828 {"mulr.hf", 0x00000241, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 829 {"mulr.f", 0x00000341, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 830 {"mulur.l", 0x00000142, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 831 {"mulur.h", 0x00000242, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 832 {"mulur", 0x00000342, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 833 {"divr.q", 0x00000144, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 834 {"divr.r", 0x00000244, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 835 {"divr", 0x00000344, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 836 {"divur.q", 0x00000146, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 837 {"divur.r", 0x00000246, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 838 {"divur", 0x00000346, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, 839 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 840 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 841 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 842 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 843 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 844 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 845 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 846 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 847 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 848 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 849 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 850 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 851 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 852 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 853 854 /* mv <-> mv!. */ 855 {"mv", 0x00003c56, 0x3e007fff, 0x4000, Rd_Rs_x, s3_do_rdrs}, 856 {"mv!", 0x4000, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp}, 857 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs}, 858 {"neg.c", 0x0000001f, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs}, 859 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s3_do_empty}, 860 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 861 {"not.c", 0x00000025, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, 862 {"nop!", 0x0000, 0x7fff, 0x8000, NO16_OPD, s3_do_empty}, 863 {"or", 0x00000022, 0x3e0003ff, 0x4a00, Rd_Rs_Rs, s3_do_rdrsrs}, 864 {"or.c", 0x00000023, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 865 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 866 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 867 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 868 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, 869 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, 870 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, 871 872 /* or.c <-> or!. */ 873 {"or!", 0x4a00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, 874 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, 875 {"pop!", 0x0040, 0x7fe0, 0x8000, Rd_rvalueRs, s3_do16_push_pop}, 876 {"push!", 0x0060, 0x7fe0, 0x8000, Rd_lvalueRs, s3_do16_push_pop}, 877 878 {"rpop!", 0x6800, 0x7c00, 0x8000, Rd_I5, s3_do16_rpop}, 879 {"rpush!", 0x6c00, 0x7c00, 0x8000, Rd_I5, s3_do16_rpush}, 880 881 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 882 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 883 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 884 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 885 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 886 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 887 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 888 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 889 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 890 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 891 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 892 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 893 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, 894 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s3_do_ldst_atomic}, 895 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign}, 896 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign}, 897 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s3_do_ldst_unalign}, 898 {"sdbbp", 0x00000006, 0x3e0003ff, 0x0020, x_I5_x, s3_do_xi5x}, 899 {"sdbbp!", 0x0020, 0x7fe0, 0x8000, Rd_I5, s3_do16_xi5}, 900 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, 901 {"rti", 0x0c0000e4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, 902 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 903 {"sll.c", 0x00000031, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 904 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 905 {"slli", 0x00000070, 0x3e0003ff, 0x5800, Rd_Rs_I5, s3_do_rdrsi5}, 906 {"slli.c", 0x00000071, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 907 908 /* slli.c <-> slli!. */ 909 {"slli!", 0x5800, 0x7e00, 0x8000, Rd_I5, s3_do16_slli_srli}, 910 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 911 {"srl.c", 0x00000035, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 912 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 913 {"sra.c", 0x00000037, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 914 {"srli", 0x00000074, 0x3e0003ff, 0x5a00, Rd_Rs_I5, s3_do_rdrsi5}, 915 {"srli.c", 0x00000075, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 916 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 917 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, 918 919 /* srli.c <-> srli!. */ 920 {"srli!", 0x5a00, 0x7e00, 0x8000, Rd_Rs, s3_do16_slli_srli}, 921 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, 922 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, 923 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, 924 {"sub", 0x00000014, 0x3e0003ff, 0x4900, Rd_Rs_Rs, s3_do_rdrsrs}, 925 {"sub.c", 0x00000015, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 926 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, 927 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 928 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 929 930 /* sub.c <-> sub!. */ 931 {"sub!", 0x4900, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, 932 {"sw!", 0x2000, 0x7000, 0x8000, Rd_lvalueRs, s3_do16_ldst_insn}, 933 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s3_do_i15}, 934 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 935 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 936 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 937 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 938 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 939 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 940 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 941 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 942 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 943 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 944 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 945 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 946 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 947 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 948 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, 949 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 950 {"xor.c", 0x00000027, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, 951 952 /* Macro instruction. */ 953 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_li_rdi32}, 954 955 /* la reg, imm32 -->(1) ldi reg, simm16 956 (2) ldis reg, %HI(imm32) 957 ori reg, %LO(imm32) 958 959 la reg, symbol -->(1) lis reg, %HI(imm32) 960 ori reg, %LO(imm32) */ 961 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_la_rdi32}, 962 {"bcmpeqz", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz}, 963 {"bcmpeq", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp}, 964 {"bcmpnez", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz}, 965 {"bcmpne", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp}, 966 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 967 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 968 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 969 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 970 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 971 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 972 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 973 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 974 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 975 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, 976 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 977 {"lbu", INSN_LBU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 978 {"lh", INSN_LH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 979 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 980 {"lw", INSN_LW, 0x00000000, 0x1000, Insn_Type_SYN, s3_do_macro_ldst_label}, 981 {"sb", INSN_SB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 982 {"sh", INSN_SH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, 983 {"sw", INSN_SW, 0x00000000, 0x2000, Insn_Type_SYN, s3_do_macro_ldst_label}, 984 985 /* Assembler use internal. */ 986 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_macro_rdi32hi}, 987 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_macro_rdi32lo}, 988 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_rdi16_pic}, 989 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_s_pic}, 990 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_u_pic}, 991 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s3_do_lw_pic}, 992 993 /* 48-bit instructions. */ 994 {"sdbbp48", 0x000000000000LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_sdbbp48}, 995 {"ldi48", 0x000000000001LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_ldi48}, 996 {"lw48", 0x000000000002LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_lw48}, 997 {"sw48", 0x000000000003LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_sw48}, 998 {"andri48", 0x040000000000LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48}, 999 {"andri48.c", 0x040000000001LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48}, 1000 {"orri48", 0x040000000002LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48}, 1001 {"orri48.c", 0x040000000003LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48}, 1002}; 1003 1004#define s3_SCORE3_PIPELINE 3 1005 1006static int s3_university_version = 0; 1007static int s3_vector_size = s3_SCORE3_PIPELINE; 1008static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE]; 1009 1010static int s3_score3d = 1; 1011 1012static int 1013s3_end_of_line (char *str) 1014{ 1015 int retval = s3_SUCCESS; 1016 1017 s3_skip_whitespace (str); 1018 if (*str != '\0') 1019 { 1020 retval = (int) s3_FAIL; 1021 1022 if (!s3_inst.error) 1023 s3_inst.error = s3_BAD_GARBAGE; 1024 } 1025 1026 return retval; 1027} 1028 1029static int 1030s3_score_reg_parse (char **ccp, htab_t htab) 1031{ 1032 char *start = *ccp; 1033 char c; 1034 char *p; 1035 struct s3_reg_entry *reg; 1036 1037 p = start; 1038 if (!ISALPHA (*p) || !is_name_beginner (*p)) 1039 return (int) s3_FAIL; 1040 1041 c = *p++; 1042 1043 while (ISALPHA (c) || ISDIGIT (c) || c == '_') 1044 c = *p++; 1045 1046 *--p = 0; 1047 reg = (struct s3_reg_entry *) str_hash_find (htab, start); 1048 *p = c; 1049 1050 if (reg) 1051 { 1052 *ccp = p; 1053 return reg->number; 1054 } 1055 return (int) s3_FAIL; 1056} 1057 1058/* If shift <= 0, only return reg. */ 1059 1060static int 1061s3_reg_required_here (char **str, int shift, enum s3_score_reg_type reg_type) 1062{ 1063 static char buff[s3_MAX_LITERAL_POOL_SIZE]; 1064 int reg = (int) s3_FAIL; 1065 char *start = *str; 1066 1067 if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[reg_type].htab)) != (int) s3_FAIL) 1068 { 1069 if (reg_type == s3_REG_TYPE_SCORE) 1070 { 1071 if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0)) 1072 { 1073 as_warn (_("Using temp register (r1)")); 1074 s3_inst.bwarn = 1; 1075 } 1076 } 1077 if (shift >= 0) 1078 { 1079 if (reg_type == s3_REG_TYPE_SCORE_CR) 1080 strcpy (s3_inst.reg, s3_score_crn_table[reg].name); 1081 else if (reg_type == s3_REG_TYPE_SCORE_SR) 1082 strcpy (s3_inst.reg, s3_score_srn_table[reg].name); 1083 else 1084 strcpy (s3_inst.reg, ""); 1085 1086 s3_inst.instruction |= (bfd_vma) reg << shift; 1087 } 1088 } 1089 else 1090 { 1091 *str = start; 1092 sprintf (buff, _("register expected, not '%.100s'"), start); 1093 s3_inst.error = buff; 1094 } 1095 1096 return reg; 1097} 1098 1099static int 1100s3_skip_past_comma (char **str) 1101{ 1102 char *p = *str; 1103 char c; 1104 int comma = 0; 1105 1106 while ((c = *p) == ' ' || c == ',') 1107 { 1108 p++; 1109 if (c == ',' && comma++) 1110 { 1111 s3_inst.error = s3_BAD_SKIP_COMMA; 1112 return (int) s3_FAIL; 1113 } 1114 } 1115 1116 if ((c == '\0') || (comma == 0)) 1117 { 1118 s3_inst.error = s3_BAD_SKIP_COMMA; 1119 return (int) s3_FAIL; 1120 } 1121 1122 *str = p; 1123 return comma ? s3_SUCCESS : (int) s3_FAIL; 1124} 1125 1126static void 1127s3_do_rdrsrs (char *str) 1128{ 1129 int reg; 1130 s3_skip_whitespace (str); 1131 1132 if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 1133 || s3_skip_past_comma (&str) == (int) s3_FAIL 1134 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1135 || s3_skip_past_comma (&str) == (int) s3_FAIL 1136 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1137 || s3_end_of_line (str) == (int) s3_FAIL) 1138 { 1139 return; 1140 } 1141 else 1142 { 1143 /* Check mulr, mulur rd is even number. */ 1144 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340 1145 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342) 1146 && (reg % 2)) 1147 { 1148 s3_inst.error = _("rd must be even number."); 1149 return; 1150 } 1151 1152 if ((((s3_inst.instruction >> 15) & 0x10) == 0) 1153 && (((s3_inst.instruction >> 10) & 0x10) == 0) 1154 && (((s3_inst.instruction >> 20) & 0x10) == 0) 1155 && (s3_inst.relax_inst != 0x8000) 1156 && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf))) 1157 { 1158 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) ) 1159 | (((s3_inst.instruction >> 15) & 0xf) << 4); 1160 s3_inst.relax_size = 2; 1161 } 1162 else 1163 { 1164 s3_inst.relax_inst = 0x8000; 1165 } 1166 } 1167} 1168 1169static int 1170s3_walk_no_bignums (symbolS * sp) 1171{ 1172 if (symbol_get_value_expression (sp)->X_op == O_big) 1173 return 1; 1174 1175 if (symbol_get_value_expression (sp)->X_add_symbol) 1176 return (s3_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) 1177 || (symbol_get_value_expression (sp)->X_op_symbol 1178 && s3_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); 1179 1180 return 0; 1181} 1182 1183static int 1184s3_my_get_expression (expressionS * ep, char **str) 1185{ 1186 char *save_in; 1187 1188 save_in = input_line_pointer; 1189 input_line_pointer = *str; 1190 s3_in_my_get_expression = 1; 1191 (void) expression (ep); 1192 s3_in_my_get_expression = 0; 1193 1194 if (ep->X_op == O_illegal) 1195 { 1196 *str = input_line_pointer; 1197 input_line_pointer = save_in; 1198 s3_inst.error = _("illegal expression"); 1199 return (int) s3_FAIL; 1200 } 1201 /* Get rid of any bignums now, so that we don't generate an error for which 1202 we can't establish a line number later on. Big numbers are never valid 1203 in instructions, which is where this routine is always called. */ 1204 if (ep->X_op == O_big 1205 || (ep->X_add_symbol 1206 && (s3_walk_no_bignums (ep->X_add_symbol) 1207 || (ep->X_op_symbol && s3_walk_no_bignums (ep->X_op_symbol))))) 1208 { 1209 s3_inst.error = _("invalid constant"); 1210 *str = input_line_pointer; 1211 input_line_pointer = save_in; 1212 return (int) s3_FAIL; 1213 } 1214 1215 if ((ep->X_add_symbol != NULL) 1216 && (s3_inst.type != PC_DISP19div2) 1217 && (s3_inst.type != PC_DISP8div2) 1218 && (s3_inst.type != PC_DISP24div2) 1219 && (s3_inst.type != PC_DISP11div2) 1220 && (s3_inst.type != Insn_Type_SYN) 1221 && (s3_inst.type != Rd_rvalueRs_SI15) 1222 && (s3_inst.type != Rd_lvalueRs_SI15) 1223 && (s3_inst.type != Insn_internal) 1224 && (s3_inst.type != Rd_I30) 1225 && (s3_inst.type != Rd_I32) 1226 && (s3_inst.type != Insn_BCMP)) 1227 { 1228 s3_inst.error = s3_BAD_ARGS; 1229 *str = input_line_pointer; 1230 input_line_pointer = save_in; 1231 return (int) s3_FAIL; 1232 } 1233 1234 *str = input_line_pointer; 1235 input_line_pointer = save_in; 1236 return s3_SUCCESS; 1237} 1238 1239/* Check if an immediate is valid. If so, convert it to the right format. */ 1240static bfd_signed_vma 1241s3_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p) 1242{ 1243 switch (data_type) 1244 { 1245 case _VALUE_HI16: 1246 { 1247 bfd_signed_vma val_hi = ((val & 0xffff0000) >> 16); 1248 1249 if (s3_score_df_range[data_type].range[0] <= val_hi 1250 && val_hi <= s3_score_df_range[data_type].range[1]) 1251 return val_hi; 1252 } 1253 break; 1254 1255 case _VALUE_LO16: 1256 { 1257 bfd_signed_vma val_lo = (val & 0xffff); 1258 1259 if (s3_score_df_range[data_type].range[0] <= val_lo 1260 && val_lo <= s3_score_df_range[data_type].range[1]) 1261 return val_lo; 1262 } 1263 break; 1264 1265 case _SIMM14: 1266 if (hex_p == 1) 1267 { 1268 if (!(val >= -0x2000 && val <= 0x3fff)) 1269 { 1270 return (int) s3_FAIL; 1271 } 1272 } 1273 else 1274 { 1275 if (!(val >= -8192 && val <= 8191)) 1276 { 1277 return (int) s3_FAIL; 1278 } 1279 } 1280 1281 return val; 1282 break; 1283 1284 case _SIMM16_NEG: 1285 if (hex_p == 1) 1286 { 1287 if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000)) 1288 { 1289 return (int) s3_FAIL; 1290 } 1291 } 1292 else 1293 { 1294 if (!(val >= -32767 && val <= 32768)) 1295 { 1296 return (int) s3_FAIL; 1297 } 1298 } 1299 1300 val = -val; 1301 return val; 1302 break; 1303 1304 case _IMM5_MULTI_LOAD: 1305 if (val >= 2 && val <= 32) 1306 { 1307 if (val == 32) 1308 val = 0; 1309 return val; 1310 } 1311 return (int) s3_FAIL; 1312 1313 case _IMM32: 1314 if (val >= 0 && val <= 0xffffffff) 1315 { 1316 return val; 1317 } 1318 else 1319 { 1320 return (int) s3_FAIL; 1321 } 1322 1323 default: 1324 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG) 1325 val = -val; 1326 1327 if (s3_score_df_range[data_type].range[0] <= val 1328 && val <= s3_score_df_range[data_type].range[1]) 1329 return val; 1330 1331 break; 1332 } 1333 1334 return (int) s3_FAIL; 1335} 1336 1337static int 1338s3_data_op2 (char **str, int shift, enum score_data_type data_type) 1339{ 1340 bfd_signed_vma value; 1341 char data_exp[s3_MAX_LITERAL_POOL_SIZE]; 1342 char *dataptr; 1343 int cnt = 0; 1344 char *pp = NULL; 1345 1346 s3_skip_whitespace (*str); 1347 s3_inst.error = NULL; 1348 dataptr = * str; 1349 1350 /* Set hex_p to zero. */ 1351 int hex_p = 0; 1352 1353 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s3_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */ 1354 { 1355 data_exp[cnt] = *dataptr; 1356 dataptr++; 1357 cnt++; 1358 } 1359 1360 data_exp[cnt] = '\0'; 1361 pp = (char *)&data_exp; 1362 1363 if (*dataptr == '|') /* process PCE */ 1364 { 1365 if (s3_my_get_expression (&s3_inst.reloc.exp, &pp) == (int) s3_FAIL) 1366 return (int) s3_FAIL; 1367 s3_end_of_line (pp); 1368 if (s3_inst.error != 0) 1369 return (int) s3_FAIL; /* to ouptut_inst to printf out the error */ 1370 *str = dataptr; 1371 } 1372 else /* process 16 bit */ 1373 { 1374 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL) 1375 { 1376 return (int) s3_FAIL; 1377 } 1378 1379 dataptr = (char *)data_exp; 1380 for (; *dataptr != '\0'; dataptr++) 1381 { 1382 *dataptr = TOLOWER (*dataptr); 1383 if (*dataptr == '!' || *dataptr == ' ') 1384 break; 1385 } 1386 dataptr = (char *)data_exp; 1387 1388 if ((dataptr != NULL) 1389 && (((strstr (dataptr, "0x")) != NULL) 1390 || ((strstr (dataptr, "0X")) != NULL))) 1391 { 1392 hex_p = 1; 1393 if ((data_type != _SIMM16_LA) 1394 && (data_type != _VALUE_HI16) 1395 && (data_type != _VALUE_LO16) 1396 && (data_type != _IMM16) 1397 && (data_type != _IMM15) 1398 && (data_type != _IMM14) 1399 && (data_type != _IMM4) 1400 && (data_type != _IMM5) 1401 && (data_type != _IMM5_MULTI_LOAD) 1402 && (data_type != _IMM11) 1403 && (data_type != _IMM8) 1404 && (data_type != _IMM5_RSHIFT_1) 1405 && (data_type != _IMM5_RSHIFT_2) 1406 && (data_type != _SIMM14) 1407 && (data_type != _SIMM14_NEG) 1408 && (data_type != _SIMM16_NEG) 1409 && (data_type != _IMM10_RSHIFT_2) 1410 && (data_type != _GP_IMM15) 1411 && (data_type != _SIMM5) 1412 && (data_type != _SIMM6) 1413 && (data_type != _IMM32) 1414 && (data_type != _SIMM32)) 1415 { 1416 data_type += 24; 1417 } 1418 } 1419 1420 if ((s3_inst.reloc.exp.X_add_number == 0) 1421 && (s3_inst.type != Insn_Type_SYN) 1422 && (s3_inst.type != Rd_rvalueRs_SI15) 1423 && (s3_inst.type != Rd_lvalueRs_SI15) 1424 && (s3_inst.type != Insn_internal) 1425 && (((*dataptr >= 'a') && (*dataptr <= 'z')) 1426 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0')) 1427 || ((*dataptr == '+') && (*(dataptr + 1) != '0')) 1428 || ((*dataptr == '-') && (*(dataptr + 1) != '0')))) 1429 { 1430 s3_inst.error = s3_BAD_ARGS; 1431 return (int) s3_FAIL; 1432 } 1433 } 1434 1435 if ((s3_inst.reloc.exp.X_add_symbol) 1436 && ((data_type == _SIMM16) 1437 || (data_type == _SIMM16_NEG) 1438 || (data_type == _IMM16_NEG) 1439 || (data_type == _SIMM14) 1440 || (data_type == _SIMM14_NEG) 1441 || (data_type == _IMM5) 1442 || (data_type == _IMM5_MULTI_LOAD) 1443 || (data_type == _IMM11) 1444 || (data_type == _IMM14) 1445 || (data_type == _IMM20) 1446 || (data_type == _IMM16) 1447 || (data_type == _IMM15) 1448 || (data_type == _IMM4))) 1449 { 1450 s3_inst.error = s3_BAD_ARGS; 1451 return (int) s3_FAIL; 1452 } 1453 1454 if (s3_inst.reloc.exp.X_add_symbol) 1455 { 1456 switch (data_type) 1457 { 1458 case _SIMM16_LA: 1459 return (int) s3_FAIL; 1460 case _VALUE_HI16: 1461 s3_inst.reloc.type = BFD_RELOC_HI16_S; 1462 s3_inst.reloc.pc_rel = 0; 1463 break; 1464 case _VALUE_LO16: 1465 s3_inst.reloc.type = BFD_RELOC_LO16; 1466 s3_inst.reloc.pc_rel = 0; 1467 break; 1468 case _GP_IMM15: 1469 s3_inst.reloc.type = BFD_RELOC_SCORE_GPREL15; 1470 s3_inst.reloc.pc_rel = 0; 1471 break; 1472 case _SIMM16_pic: 1473 case _IMM16_LO16_pic: 1474 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16; 1475 s3_inst.reloc.pc_rel = 0; 1476 break; 1477 default: 1478 s3_inst.reloc.type = BFD_RELOC_32; 1479 s3_inst.reloc.pc_rel = 0; 1480 break; 1481 } 1482 } 1483 else 1484 { 1485 if (data_type == _IMM16_pic) 1486 { 1487 s3_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16; 1488 s3_inst.reloc.pc_rel = 0; 1489 } 1490 1491 if (data_type == _SIMM16_LA && s3_inst.reloc.exp.X_unsigned == 1) 1492 { 1493 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p); 1494 if (value == (int) s3_FAIL) /* for advance to check if this is ldis */ 1495 if ((s3_inst.reloc.exp.X_add_number & 0xffff) == 0) 1496 { 1497 s3_inst.instruction |= 0x8000000; 1498 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe; 1499 return s3_SUCCESS; 1500 } 1501 } 1502 else 1503 { 1504 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, hex_p); 1505 } 1506 1507 if (value == (int) s3_FAIL) 1508 { 1509 if (data_type == _IMM32) 1510 { 1511 sprintf (s3_err_msg, 1512 _("invalid constant: %d bit expression not in range %u..%u"), 1513 s3_score_df_range[data_type].bits, 1514 0, (unsigned)0xffffffff); 1515 } 1516 else if (data_type == _IMM5_MULTI_LOAD) 1517 { 1518 sprintf (s3_err_msg, 1519 _("invalid constant: %d bit expression not in range %u..%u"), 1520 5, 2, 32); 1521 } 1522 else if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG)) 1523 { 1524 sprintf (s3_err_msg, 1525 _("invalid constant: %d bit expression not in range %d..%d"), 1526 s3_score_df_range[data_type].bits, 1527 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 1528 } 1529 else 1530 { 1531 sprintf (s3_err_msg, 1532 _("invalid constant: %d bit expression not in range %d..%d"), 1533 s3_score_df_range[data_type].bits, 1534 -s3_score_df_range[data_type].range[1], -s3_score_df_range[data_type].range[0]); 1535 } 1536 1537 s3_inst.error = s3_err_msg; 1538 return (int) s3_FAIL; 1539 } 1540 1541 if (((s3_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31)) 1542 && data_type != _IMM5_MULTI_LOAD) 1543 { 1544 value &= (1 << s3_score_df_range[data_type].bits) - 1; 1545 } 1546 1547 s3_inst.instruction |= value << shift; 1548 } 1549 1550 if ((s3_inst.instruction & 0x3e000000) == 0x30000000) 1551 { 1552 if ((((s3_inst.instruction >> 20) & 0x1F) != 0) 1553 && (((s3_inst.instruction >> 20) & 0x1F) != 1) 1554 && (((s3_inst.instruction >> 20) & 0x1F) != 2) 1555 && (((s3_inst.instruction >> 20) & 0x1F) != 0x10)) 1556 { 1557 s3_inst.error = _("invalid constant: bit expression not defined"); 1558 return (int) s3_FAIL; 1559 } 1560 } 1561 1562 return s3_SUCCESS; 1563} 1564 1565/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */ 1566static void 1567s3_do_rdsi16 (char *str) 1568{ 1569 s3_skip_whitespace (str); 1570 1571 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1572 || s3_skip_past_comma (&str) == (int) s3_FAIL 1573 || s3_data_op2 (&str, 1, _SIMM16) == (int) s3_FAIL 1574 || s3_end_of_line (str) == (int) s3_FAIL) 1575 return; 1576 1577 /* ldi.->ldiu! only for imm5 */ 1578 if ((s3_inst.instruction & 0x20c0000) == 0x20c0000) 1579 { 1580 if ((s3_inst.instruction & 0x1ffc0) != 0) 1581 { 1582 s3_inst.relax_inst = 0x8000; 1583 } 1584 else 1585 { 1586 s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; 1587 s3_inst.relax_inst |= (((s3_inst.instruction >> 20)& 0x1f) <<5); 1588 s3_inst.relax_size = 2; 1589 } 1590 } 1591 /*cmpi.c */ 1592 else if ((s3_inst.instruction & 0x02040001) == 0x02040001) 1593 { 1594 /* imm <=0x3f (5 bit<<1)*/ 1595 if (((s3_inst.instruction & 0x1ffe0) == 0) 1596 || (((s3_inst.instruction & 0x1ffe0) == 0x1ffe0) 1597 && (s3_inst.instruction & 0x003e) != 0)) 1598 { 1599 s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; 1600 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5); 1601 s3_inst.relax_size = 2; 1602 } 1603 else 1604 { 1605 s3_inst.relax_inst =0x8000; 1606 1607 } 1608 } 1609 /* addi */ 1610 else if (((s3_inst.instruction & 0x2000000) == 0x02000000) && (s3_inst.relax_inst!=0x8000)) 1611 { 1612 /* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/ 1613 if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) 1614 && (((s3_inst.instruction & 0x1ffc0) == 0) 1615 || (((s3_inst.instruction & 0x1ffc0) == 0x1ffc0) 1616 && (s3_inst.instruction & 0x007e) != 0))) 1617 { 1618 s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f; 1619 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6); 1620 s3_inst.relax_size = 2; 1621 } 1622 else 1623 { 1624 s3_inst.relax_inst =0x8000; 1625 } 1626 } 1627 1628 else if (((s3_inst.instruction >> 20) & 0x10) == 0x10) 1629 { 1630 s3_inst.relax_inst = 0x8000; 1631 } 1632} 1633 1634static void 1635s3_do_ldis (char *str) 1636{ 1637 s3_skip_whitespace (str); 1638 1639 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1640 || s3_skip_past_comma (&str) == (int) s3_FAIL 1641 || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL 1642 || s3_end_of_line (str) == (int) s3_FAIL) 1643 return; 1644} 1645 1646/* Handle subi/subi.c. */ 1647static void 1648s3_do_sub_rdsi16 (char *str) 1649{ 1650 s3_skip_whitespace (str); 1651 1652 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1653 && s3_skip_past_comma (&str) != (int) s3_FAIL 1654 && s3_data_op2 (&str, 1, _SIMM16_NEG) != (int) s3_FAIL) 1655 s3_end_of_line (str); 1656} 1657 1658/* Handle subis/subis.c. */ 1659static void 1660s3_do_sub_rdi16 (char *str) 1661{ 1662 s3_skip_whitespace (str); 1663 1664 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1665 && s3_skip_past_comma (&str) != (int) s3_FAIL 1666 && s3_data_op2 (&str, 1, _IMM16_NEG) != (int) s3_FAIL) 1667 s3_end_of_line (str); 1668} 1669 1670/* Handle addri/addri.c. */ 1671static void 1672s3_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ 1673{ 1674 s3_skip_whitespace (str); 1675 1676 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1677 && s3_skip_past_comma (&str) != (int) s3_FAIL 1678 && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1679 && s3_skip_past_comma (&str) != (int) s3_FAIL) 1680 s3_data_op2 (&str, 1, _SIMM14); 1681} 1682 1683/* Handle subri.c/subri. */ 1684static void 1685s3_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ 1686{ 1687 s3_skip_whitespace (str); 1688 1689 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1690 && s3_skip_past_comma (&str) != (int) s3_FAIL 1691 && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1692 && s3_skip_past_comma (&str) != (int) s3_FAIL 1693 && s3_data_op2 (&str, 1, _SIMM14_NEG) != (int) s3_FAIL) 1694 s3_end_of_line (str); 1695} 1696 1697/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. 1698 0~((2^14)-1) */ 1699static void 1700s3_do_rdrsi5 (char *str) 1701{ 1702 s3_skip_whitespace (str); 1703 1704 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1705 || s3_skip_past_comma (&str) == (int) s3_FAIL 1706 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1707 || s3_skip_past_comma (&str) == (int) s3_FAIL 1708 || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL 1709 || s3_end_of_line (str) == (int) s3_FAIL) 1710 return; 1711 1712 if ((((s3_inst.instruction >> 20) & 0x1f) == ((s3_inst.instruction >> 15) & 0x1f)) 1713 && (s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0)) 1714 { 1715 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f) ) | (((s3_inst.instruction >> 15) & 0xf) << 5); 1716 s3_inst.relax_size = 2; 1717 } 1718 else 1719 s3_inst.relax_inst = 0x8000; 1720} 1721 1722/* Handle andri/orri/andri.c/orri.c. 1723 0 ~ ((2^14)-1) */ 1724static void 1725s3_do_rdrsi14 (char *str) 1726{ 1727 s3_skip_whitespace (str); 1728 1729 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1730 && s3_skip_past_comma (&str) != (int) s3_FAIL 1731 && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1732 && s3_skip_past_comma (&str) != (int) s3_FAIL 1733 && s3_data_op2 (&str, 1, _IMM14) != (int) s3_FAIL) 1734 s3_end_of_line (str); 1735} 1736 1737/* Handle bittst.c. */ 1738static void 1739s3_do_xrsi5 (char *str) 1740{ 1741 s3_skip_whitespace (str); 1742 1743 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1744 || s3_skip_past_comma (&str) == (int) s3_FAIL 1745 || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL 1746 || s3_end_of_line (str) == (int) s3_FAIL) 1747 return; 1748 1749 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0)) 1750 { 1751 s3_inst.relax_inst |= ((s3_inst.instruction >> 10) & 0x1f) | (((s3_inst.instruction >> 15) & 0xf) << 5); 1752 s3_inst.relax_size = 2; 1753 } 1754 else 1755 s3_inst.relax_inst = 0x8000; 1756} 1757 1758/* Handle addis/andi/ori/andis/oris/ldis. */ 1759static void 1760s3_do_rdi16 (char *str) 1761{ 1762 s3_skip_whitespace (str); 1763 1764 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1765 || s3_skip_past_comma (&str) == (int) s3_FAIL 1766 || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL 1767 || s3_end_of_line (str) == (int) s3_FAIL) 1768 return; 1769 1770 /* ldis */ 1771 if ((s3_inst.instruction & 0x3e0e0000) == 0x0a0c0000) 1772 { 1773 /* rd : 0-16 ;imm =0 -> can transform to addi!*/ 1774 if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0)) 1775 { 1776 s3_inst.relax_inst =0x5400; /* ldiu! */ 1777 s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; 1778 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 5); 1779 s3_inst.relax_size = 2; 1780 } 1781 else 1782 { 1783 s3_inst.relax_inst =0x8000; 1784 1785 } 1786 } 1787 1788 /* addis */ 1789 else if ((s3_inst.instruction & 0x3e0e0001) == 0x0a000000) 1790 { 1791 /* rd : 0-16 ;imm =0 -> can transform to addi!*/ 1792 if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0)) 1793 { 1794 s3_inst.relax_inst =0x5c00; /* addi! */ 1795 s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f; 1796 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6); 1797 s3_inst.relax_size = 2; 1798 } 1799 else 1800 { 1801 s3_inst.relax_inst =0x8000; 1802 1803 } 1804 } 1805} 1806 1807static void 1808s3_do_macro_rdi32hi (char *str) 1809{ 1810 s3_skip_whitespace (str); 1811 1812 /* Do not handle s3_end_of_line(). */ 1813 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1814 && s3_skip_past_comma (&str) != (int) s3_FAIL) 1815 s3_data_op2 (&str, 1, _VALUE_HI16); 1816} 1817 1818static void 1819s3_do_macro_rdi32lo (char *str) 1820{ 1821 s3_skip_whitespace (str); 1822 1823 /* Do not handle s3_end_of_line(). */ 1824 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1825 && s3_skip_past_comma (&str) != (int) s3_FAIL) 1826 s3_data_op2 (&str, 1, _VALUE_LO16); 1827} 1828 1829/* Handle ldis_pic. */ 1830static void 1831s3_do_rdi16_pic (char *str) 1832{ 1833 s3_skip_whitespace (str); 1834 1835 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1836 && s3_skip_past_comma (&str) != (int) s3_FAIL 1837 && s3_data_op2 (&str, 1, _IMM16_pic) != (int) s3_FAIL) 1838 s3_end_of_line (str); 1839} 1840 1841/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */ 1842static void 1843s3_do_addi_s_pic (char *str) 1844{ 1845 s3_skip_whitespace (str); 1846 1847 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1848 && s3_skip_past_comma (&str) != (int) s3_FAIL 1849 && s3_data_op2 (&str, 1, _SIMM16_pic) != (int) s3_FAIL) 1850 s3_end_of_line (str); 1851} 1852 1853/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */ 1854static void 1855s3_do_addi_u_pic (char *str) 1856{ 1857 s3_skip_whitespace (str); 1858 1859 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1860 && s3_skip_past_comma (&str) != (int) s3_FAIL 1861 && s3_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s3_FAIL) 1862 s3_end_of_line (str); 1863} 1864 1865/* Handle mfceh/mfcel/mtceh/mtchl. */ 1866static void 1867s3_do_rd (char *str) 1868{ 1869 s3_skip_whitespace (str); 1870 1871 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL) 1872 s3_end_of_line (str); 1873} 1874 1875/* Handle br{cond},cmpzteq.c ,cmpztmi.c ,cmpz.c */ 1876static void 1877s3_do_rs (char *str) 1878{ 1879 s3_skip_whitespace (str); 1880 1881 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1882 || s3_end_of_line (str) == (int) s3_FAIL) 1883 return; 1884 1885 if ((s3_inst.relax_inst != 0x8000) ) 1886 { 1887 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) &0x1f); 1888 s3_inst.relax_size = 2; 1889 } 1890 else 1891 s3_inst.relax_inst = 0x8000; 1892} 1893 1894static void 1895s3_do_i15 (char *str) 1896{ 1897 s3_skip_whitespace (str); 1898 1899 if (s3_data_op2 (&str, 10, _IMM15) != (int) s3_FAIL) 1900 s3_end_of_line (str); 1901} 1902 1903static void 1904s3_do_xi5x (char *str) 1905{ 1906 s3_skip_whitespace (str); 1907 1908 if (s3_data_op2 (&str, 15, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) 1909 return; 1910 1911 if (s3_inst.relax_inst != 0x8000) 1912 { 1913 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f); 1914 s3_inst.relax_size = 2; 1915 } 1916} 1917 1918static void 1919s3_do_rdrs (char *str) 1920{ 1921 s3_skip_whitespace (str); 1922 1923 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1924 || s3_skip_past_comma (&str) == (int) s3_FAIL 1925 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1926 || s3_end_of_line (str) == (int) s3_FAIL) 1927 return; 1928 1929 if (s3_inst.relax_inst != 0x8000) 1930 { 1931 if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/ 1932 { 1933 /* mv! rd : 5bit , ra : 5bit */ 1934 s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5); 1935 s3_inst.relax_size = 2; 1936 } 1937 else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) 1938 { 1939 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4) 1940 | (((s3_inst.instruction >> 20) & 0xf) << 8); 1941 s3_inst.relax_size = 2; 1942 } 1943 else 1944 { 1945 s3_inst.relax_inst = 0x8000; 1946 } 1947 } 1948} 1949 1950/* Handle mfcr/mtcr. */ 1951static void 1952s3_do_rdcrs (char *str) 1953{ 1954 s3_skip_whitespace (str); 1955 1956 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1957 && s3_skip_past_comma (&str) != (int) s3_FAIL 1958 && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) != (int) s3_FAIL) 1959 s3_end_of_line (str); 1960} 1961 1962/* Handle mfsr/mtsr. */ 1963static void 1964s3_do_rdsrs (char *str) 1965{ 1966 s3_skip_whitespace (str); 1967 1968 /* mfsr */ 1969 if ((s3_inst.instruction & 0xff) == 0x50) 1970 { 1971 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1972 && s3_skip_past_comma (&str) != (int) s3_FAIL 1973 && s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR) != (int) s3_FAIL) 1974 s3_end_of_line (str); 1975 } 1976 else 1977 { 1978 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL 1979 && s3_skip_past_comma (&str) != (int) s3_FAIL) 1980 s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR); 1981 } 1982} 1983 1984/* Handle neg. */ 1985static void 1986s3_do_rdxrs (char *str) 1987{ 1988 s3_skip_whitespace (str); 1989 1990 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1991 || s3_skip_past_comma (&str) == (int) s3_FAIL 1992 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 1993 || s3_end_of_line (str) == (int) s3_FAIL) 1994 return; 1995 1996 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 10) & 0x10) == 0) 1997 && (((s3_inst.instruction >> 20) & 0x10) == 0)) 1998 { 1999 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) << 4) | (((s3_inst.instruction >> 20) & 0xf) << 8); 2000 s3_inst.relax_size = 2; 2001 } 2002 else 2003 s3_inst.relax_inst = 0x8000; 2004} 2005 2006/* Handle cmp.c/cmp<cond>. */ 2007static void 2008s3_do_rsrs (char *str) 2009{ 2010 s3_skip_whitespace (str); 2011 2012 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2013 || s3_skip_past_comma (&str) == (int) s3_FAIL 2014 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2015 || s3_end_of_line (str) == (int) s3_FAIL) 2016 return; 2017 2018 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) 2019 { 2020 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); 2021 s3_inst.relax_size = 2; 2022 } 2023 else 2024 s3_inst.relax_inst = 0x8000; 2025} 2026 2027static void 2028s3_do_ceinst (char *str) 2029{ 2030 char *strbak; 2031 2032 strbak = str; 2033 s3_skip_whitespace (str); 2034 2035 if (s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL 2036 || s3_skip_past_comma (&str) == (int) s3_FAIL 2037 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2038 || s3_skip_past_comma (&str) == (int) s3_FAIL 2039 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2040 || s3_skip_past_comma (&str) == (int) s3_FAIL 2041 || s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL 2042 || s3_skip_past_comma (&str) == (int) s3_FAIL 2043 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 2044 || s3_end_of_line (str) == (int) s3_FAIL) 2045 { 2046 return; 2047 } 2048 else 2049 { 2050 str = strbak; 2051 if (s3_data_op2 (&str, 0, _IMM25) == (int) s3_FAIL) 2052 return; 2053 } 2054} 2055 2056static int 2057s3_reglow_required_here (char **str, int shift) 2058{ 2059 static char buff[s3_MAX_LITERAL_POOL_SIZE]; 2060 int reg; 2061 char *start = *str; 2062 2063 if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[s3_REG_TYPE_SCORE].htab)) != (int) s3_FAIL) 2064 { 2065 if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0)) 2066 { 2067 as_warn (_("Using temp register(r1)")); 2068 s3_inst.bwarn = 1; 2069 } 2070 if (reg < 16) 2071 { 2072 if (shift >= 0) 2073 s3_inst.instruction |= (bfd_vma) reg << shift; 2074 2075 return reg; 2076 } 2077 } 2078 2079 /* Restore the start point, we may have got a reg of the wrong class. */ 2080 *str = start; 2081 sprintf (buff, _("low register (r0-r15) expected, not '%.100s'"), start); 2082 s3_inst.error = buff; 2083 return (int) s3_FAIL; 2084} 2085 2086/* Handle add!/and!/or!/sub!. */ 2087static void 2088s3_do16_rdrs2 (char *str) 2089{ 2090 s3_skip_whitespace (str); 2091 2092 if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL 2093 || s3_skip_past_comma (&str) == (int) s3_FAIL 2094 || s3_reglow_required_here (&str, 0) == (int) s3_FAIL 2095 || s3_end_of_line (str) == (int) s3_FAIL) 2096 { 2097 return; 2098 } 2099} 2100 2101/* Handle br!/brl!. */ 2102static void 2103s3_do16_br (char *str) 2104{ 2105 s3_skip_whitespace (str); 2106 2107 if (s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2108 || s3_end_of_line (str) == (int) s3_FAIL) 2109 { 2110 return; 2111 } 2112} 2113 2114/* Handle brr!. */ 2115static void 2116s3_do16_brr (char *str) 2117{ 2118 int rd = 0; 2119 2120 s3_skip_whitespace (str); 2121 2122 if ((rd = s3_reg_required_here (&str, 0,s3_REG_TYPE_SCORE)) == (int) s3_FAIL 2123 || s3_end_of_line (str) == (int) s3_FAIL) 2124 { 2125 return; 2126 } 2127} 2128 2129/*Handle ltbw / ltbh / ltbb */ 2130static void 2131s3_do_ltb (char *str) 2132{ 2133 s3_skip_whitespace (str); 2134 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2135 || s3_skip_past_comma (&str) == (int) s3_FAIL) 2136 { 2137 return; 2138 } 2139 2140 s3_skip_whitespace (str); 2141 if (*str++ != '[') 2142 { 2143 s3_inst.error = _("missing ["); 2144 return; 2145 } 2146 2147 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2148 || s3_skip_past_comma (&str) == (int) s3_FAIL 2149 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 2150 { 2151 return; 2152 } 2153 2154 s3_skip_whitespace (str); 2155 if (*str++ != ']') 2156 { 2157 s3_inst.error = _("missing ]"); 2158 return; 2159 } 2160} 2161 2162/* We need to be able to fix up arbitrary expressions in some statements. 2163 This is so that we can handle symbols that are an arbitrary distance from 2164 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask), 2165 which returns part of an address in a form which will be valid for 2166 a data instruction. We do this by pushing the expression into a symbol 2167 in the expr_section, and creating a fix for that. */ 2168static fixS * 2169s3_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc) 2170{ 2171 fixS *new_fix; 2172 2173 switch (exp->X_op) 2174 { 2175 case O_constant: 2176 case O_symbol: 2177 case O_add: 2178 case O_subtract: 2179 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc); 2180 break; 2181 default: 2182 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc); 2183 break; 2184 } 2185 return new_fix; 2186} 2187 2188static void 2189s3_init_dependency_vector (void) 2190{ 2191 int i; 2192 2193 for (i = 0; i < s3_vector_size; i++) 2194 memset (&s3_dependency_vector[i], '\0', sizeof (s3_dependency_vector[i])); 2195 2196 return; 2197} 2198 2199static enum s3_insn_type_for_dependency 2200s3_dependency_type_from_insn (char *insn_name) 2201{ 2202 char name[s3_INSN_NAME_LEN]; 2203 const struct s3_insn_to_dependency *tmp; 2204 2205 strcpy (name, insn_name); 2206 tmp = (const struct s3_insn_to_dependency *) 2207 str_hash_find (s3_dependency_insn_hsh, name); 2208 2209 if (tmp) 2210 return tmp->type; 2211 2212 return s3_D_all_insn; 2213} 2214 2215static int 2216s3_check_dependency (char *pre_insn, char *pre_reg, 2217 char *cur_insn, char *cur_reg, int *warn_or_error) 2218{ 2219 int bubbles = 0; 2220 unsigned int i; 2221 enum s3_insn_type_for_dependency pre_insn_type; 2222 enum s3_insn_type_for_dependency cur_insn_type; 2223 2224 pre_insn_type = s3_dependency_type_from_insn (pre_insn); 2225 cur_insn_type = s3_dependency_type_from_insn (cur_insn); 2226 2227 for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++) 2228 { 2229 if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type) 2230 && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type 2231 || cur_insn_type == s3_data_dependency_table[i].cur_insn_type) 2232 && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0 2233 || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0) 2234 && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0 2235 || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0)) 2236 { 2237 bubbles = s3_data_dependency_table[i].bubblenum_3; 2238 *warn_or_error = s3_data_dependency_table[i].warn_or_error; 2239 break; 2240 } 2241 } 2242 2243 return bubbles; 2244} 2245 2246static void 2247s3_build_one_frag (struct s3_score_it one_inst) 2248{ 2249 char *p; 2250 int relaxable_p = s3_g_opt; 2251 int relax_size = 0; 2252 2253 /* Start a new frag if frag_now is not empty. */ 2254 if (frag_now_fix () != 0) 2255 { 2256 if (!frag_now->tc_frag_data.is_insn) 2257 frag_wane (frag_now); 2258 2259 frag_new (0); 2260 } 2261 frag_grow (20); 2262 2263 p = frag_more (one_inst.size); 2264 s3_md_number_to_chars (p, one_inst.instruction, one_inst.size); 2265 2266#ifdef OBJ_ELF 2267 dwarf2_emit_insn (one_inst.size); 2268#endif 2269 2270 relaxable_p &= (one_inst.relax_size != 0); 2271 relax_size = relaxable_p ? one_inst.relax_size : 0; 2272 2273 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, 2274 s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size, 2275 one_inst.type, 0, 0, relaxable_p), 2276 NULL, 0, NULL); 2277 2278 if (relaxable_p) 2279 s3_md_number_to_chars (p, one_inst.relax_inst, relax_size); 2280} 2281 2282static void 2283s3_handle_dependency (struct s3_score_it *theinst) 2284{ 2285 int i; 2286 int warn_or_error = 0; /* warn - 0; error - 1 */ 2287 int bubbles = 0; 2288 int remainder_bubbles = 0; 2289 char cur_insn[s3_INSN_NAME_LEN]; 2290 char pre_insn[s3_INSN_NAME_LEN]; 2291 struct s3_score_it nop_inst; 2292 struct s3_score_it pflush_inst; 2293 2294 nop_inst.instruction = 0x0000; 2295 nop_inst.size = 2; 2296 nop_inst.relax_inst = 0x80008000; 2297 nop_inst.relax_size = 4; 2298 nop_inst.type = NO16_OPD; 2299 2300 pflush_inst.instruction = 0x8000800a; 2301 pflush_inst.size = 4; 2302 pflush_inst.relax_inst = 0x8000; 2303 pflush_inst.relax_size = 0; 2304 pflush_inst.type = NO_OPD; 2305 2306 /* pflush will clear all data dependency. */ 2307 if (strcmp (theinst->name, "pflush") == 0) 2308 { 2309 s3_init_dependency_vector (); 2310 return; 2311 } 2312 2313 /* Push current instruction to s3_dependency_vector[0]. */ 2314 for (i = s3_vector_size - 1; i > 0; i--) 2315 memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i])); 2316 2317 memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i])); 2318 2319 /* There is no dependency between nop and any instruction. */ 2320 if (strcmp (s3_dependency_vector[0].name, "nop") == 0 2321 || strcmp (s3_dependency_vector[0].name, "nop!") == 0) 2322 return; 2323 2324 strcpy (cur_insn, s3_dependency_vector[0].name); 2325 2326 for (i = 1; i < s3_vector_size; i++) 2327 { 2328 /* The element of s3_dependency_vector is NULL. */ 2329 if (s3_dependency_vector[i].name[0] == '\0') 2330 continue; 2331 2332 strcpy (pre_insn, s3_dependency_vector[i].name); 2333 2334 bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg, 2335 cur_insn, s3_dependency_vector[0].reg, &warn_or_error); 2336 remainder_bubbles = bubbles - i + 1; 2337 2338 if (remainder_bubbles > 0) 2339 { 2340 int j; 2341 2342 if (s3_fix_data_dependency == 1) 2343 { 2344 if (remainder_bubbles <= 2) 2345 { 2346 if (s3_warn_fix_data_dependency) 2347 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"), 2348 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2349 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2350 remainder_bubbles, bubbles); 2351 2352 for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--) 2353 memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles], 2354 sizeof (s3_dependency_vector[j])); 2355 2356 for (j = 1; j <= remainder_bubbles; j++) 2357 { 2358 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); 2359 /* Insert nop!. */ 2360 s3_build_one_frag (nop_inst); 2361 } 2362 } 2363 else 2364 { 2365 if (s3_warn_fix_data_dependency) 2366 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"), 2367 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2368 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2369 bubbles); 2370 2371 for (j = 1; j < s3_vector_size; j++) 2372 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); 2373 2374 /* Insert pflush. */ 2375 s3_build_one_frag (pflush_inst); 2376 } 2377 } 2378 else 2379 { 2380 if (warn_or_error) 2381 { 2382 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2383 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2384 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2385 remainder_bubbles, bubbles); 2386 } 2387 else 2388 { 2389 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2390 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2391 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2392 remainder_bubbles, bubbles); 2393 } 2394 } 2395 } 2396 } 2397} 2398 2399static enum insn_class 2400s3_get_insn_class_from_type (enum score_insn_type type) 2401{ 2402 enum insn_class retval = (int) s3_FAIL; 2403 2404 switch (type) 2405 { 2406 case Rd_I4: 2407 case Rd_I5: 2408 case Rd_rvalueBP_I5: 2409 case Rd_lvalueBP_I5: 2410 case Rd_I8: 2411 case PC_DISP8div2: 2412 case PC_DISP11div2: 2413 case Rd_Rs: 2414 case Rd_HighRs: 2415 case Rd_lvalueRs: 2416 case Rd_rvalueRs: 2417 case x_Rs: 2418 case Rd_LowRs: 2419 case NO16_OPD: 2420 case Rd_SI5: 2421 case Rd_SI6: 2422 retval = INSN_CLASS_16; 2423 break; 2424 case Rd_Rs_I5: 2425 case x_Rs_I5: 2426 case x_I5_x: 2427 case Rd_Rs_I14: 2428 case I15: 2429 case Rd_I16: 2430 case Rd_SI16: 2431 case Rd_rvalueRs_SI10: 2432 case Rd_lvalueRs_SI10: 2433 case Rd_rvalueRs_preSI12: 2434 case Rd_rvalueRs_postSI12: 2435 case Rd_lvalueRs_preSI12: 2436 case Rd_lvalueRs_postSI12: 2437 case Rd_Rs_SI14: 2438 case Rd_rvalueRs_SI15: 2439 case Rd_lvalueRs_SI15: 2440 case PC_DISP19div2: 2441 case PC_DISP24div2: 2442 case Rd_Rs_Rs: 2443 case x_Rs_x: 2444 case x_Rs_Rs: 2445 case Rd_Rs_x: 2446 case Rd_x_Rs: 2447 case Rd_x_x: 2448 case OP5_rvalueRs_SI15: 2449 case I5_Rs_Rs_I5_OP5: 2450 case x_rvalueRs_post4: 2451 case Rd_rvalueRs_post4: 2452 case Rd_x_I5: 2453 case Rd_lvalueRs_post4: 2454 case x_lvalueRs_post4: 2455 case Rd_Rs_Rs_imm: 2456 case NO_OPD: 2457 case Rd_lvalue32Rs: 2458 case Rd_rvalue32Rs: 2459 case Insn_GP: 2460 case Insn_PIC: 2461 case Insn_internal: 2462 case Insn_BCMP: 2463 case Ra_I9_I5: 2464 retval = INSN_CLASS_32; 2465 break; 2466 case Insn_Type_PCE: 2467 retval = INSN_CLASS_PCE; 2468 break; 2469 case Insn_Type_SYN: 2470 retval = INSN_CLASS_SYN; 2471 break; 2472 case Rd_I30: 2473 case Rd_I32: 2474 retval = INSN_CLASS_48; 2475 break; 2476 default: 2477 abort (); 2478 break; 2479 } 2480 return retval; 2481} 2482 2483/* Type of p-bits: 2484 48-bit instruction: 1, 1, 0. 2485 32-bit instruction: 1, 0. 2486 16-bit instruction: 0. */ 2487static bfd_vma 2488s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class) 2489{ 2490 bfd_vma result = 0; 2491 bfd_vma m_code_high = 0; 2492 unsigned long m_code_middle = 0; 2493 unsigned long m_code_low = 0; 2494 bfd_vma pb_high = 0; 2495 unsigned long pb_middle = 0; 2496 unsigned long pb_low = 0; 2497 2498 if (i_class == INSN_CLASS_48) 2499 { 2500 pb_high = 0x800000000000LL; 2501 pb_middle = 0x80000000; 2502 pb_low = 0x00000000; 2503 m_code_high = m_code & 0x1fffc0000000LL; 2504 m_code_middle = m_code & 0x3fff8000; 2505 m_code_low = m_code & 0x00007fff; 2506 result = pb_high | (m_code_high << 2) | 2507 pb_middle | (m_code_middle << 1) | 2508 pb_low | m_code_low; 2509 } 2510 else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN) 2511 { 2512 pb_high = 0x80000000; 2513 pb_low = 0x00000000; 2514 m_code_high = m_code & 0x3fff8000; 2515 m_code_low = m_code & 0x00007fff; 2516 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2517 } 2518 else if (i_class == INSN_CLASS_16) 2519 { 2520 pb_high = 0; 2521 pb_low = 0; 2522 m_code_high = m_code & 0x3fff8000; 2523 m_code_low = m_code & 0x00007fff; 2524 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2525 } 2526 else if (i_class == INSN_CLASS_PCE) 2527 { 2528 /* Keep original. */ 2529 pb_high = 0; 2530 pb_low = 0x00008000; 2531 m_code_high = m_code & 0x3fff8000; 2532 m_code_low = m_code & 0x00007fff; 2533 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2534 } 2535 else 2536 { 2537 abort (); 2538 } 2539 2540 return result; 2541} 2542 2543static void 2544s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2) 2545{ 2546 char *p; 2547 bool pce_p = false; 2548 int relaxable_p = s3_g_opt; 2549 int relax_size = 0; 2550 struct s3_score_it *inst1 = part_1; 2551 struct s3_score_it *inst2 = part_2; 2552 struct s3_score_it backup_inst1; 2553 2554 pce_p = inst2 != NULL; 2555 memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it)); 2556 2557 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 2558 if (pce_p) 2559 { 2560 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15) 2561 | (inst2->instruction & 0x7FFF); 2562 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); 2563 backup_inst1.relax_inst = 0x8000; 2564 backup_inst1.size = s3_INSN_SIZE; 2565 backup_inst1.relax_size = 0; 2566 backup_inst1.type = Insn_Type_PCE; 2567 } 2568 else 2569 { 2570 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, 2571 s3_GET_INSN_CLASS (backup_inst1.type)); 2572 } 2573 2574 if (backup_inst1.relax_size != 0) 2575 { 2576 enum insn_class tmp; 2577 2578 tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; 2579 backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp); 2580 } 2581 2582 /* Check data dependency. */ 2583 s3_handle_dependency (&backup_inst1); 2584 2585 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains 2586 data produced by .ascii etc. Doing this is to make one instruction per frag. */ 2587 if (frag_now_fix () != 0) 2588 { 2589 if (!frag_now->tc_frag_data.is_insn) 2590 frag_wane (frag_now); 2591 2592 frag_new (0); 2593 } 2594 2595 /* Here, we must call frag_grow in order to keep the instruction frag type is 2596 rs_machine_dependent. 2597 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which 2598 actually will call frag_wane. 2599 Calling frag_grow first will create a new frag_now which free size is 20 that is enough 2600 for frag_var. */ 2601 frag_grow (20); 2602 2603 p = frag_more (backup_inst1.size); 2604 s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); 2605 2606#ifdef OBJ_ELF 2607 dwarf2_emit_insn (backup_inst1.size); 2608#endif 2609 2610 /* Generate fixup structure. */ 2611 if (pce_p) 2612 { 2613 if (inst1->reloc.type != BFD_RELOC_NONE) 2614 s3_fix_new_score (frag_now, p - frag_now->fr_literal, 2615 inst1->size, &inst1->reloc.exp, 2616 inst1->reloc.pc_rel, inst1->reloc.type); 2617 2618 if (inst2->reloc.type != BFD_RELOC_NONE) 2619 s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2, 2620 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type); 2621 } 2622 else 2623 { 2624 if (backup_inst1.reloc.type != BFD_RELOC_NONE) 2625 s3_fix_new_score (frag_now, p - frag_now->fr_literal, 2626 backup_inst1.size, &backup_inst1.reloc.exp, 2627 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type); 2628 } 2629 2630 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */ 2631 relaxable_p &= (backup_inst1.relax_size != 0); 2632 relax_size = relaxable_p ? backup_inst1.relax_size : 0; 2633 2634 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, 2635 s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, 2636 backup_inst1.type, 0, 0, relaxable_p), 2637 backup_inst1.reloc.exp.X_add_symbol, 0, NULL); 2638 2639 if (relaxable_p) 2640 s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size); 2641 2642 memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it)); 2643} 2644 2645static void 2646s3_parse_16_32_inst (char *insnstr, bool gen_frag_p) 2647{ 2648 char c; 2649 char *p; 2650 char *operator = insnstr; 2651 const struct s3_asm_opcode *opcode; 2652 2653 /* Parse operator and operands. */ 2654 s3_skip_whitespace (operator); 2655 2656 for (p = operator; *p != '\0'; p++) 2657 if ((*p == ' ') || (*p == '!')) 2658 break; 2659 2660 if (*p == '!') 2661 p++; 2662 2663 c = *p; 2664 *p = '\0'; 2665 2666 opcode = (const struct s3_asm_opcode *) str_hash_find (s3_score_ops_hsh, 2667 operator); 2668 *p = c; 2669 2670 memset (&s3_inst, '\0', sizeof (s3_inst)); 2671 sprintf (s3_inst.str, "%s", insnstr); 2672 if (opcode) 2673 { 2674 s3_inst.instruction = opcode->value; 2675 s3_inst.relax_inst = opcode->relax_value; 2676 s3_inst.type = opcode->type; 2677 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); 2678 s3_inst.relax_size = 0; 2679 s3_inst.bwarn = 0; 2680 sprintf (s3_inst.name, "%s", opcode->template_name); 2681 strcpy (s3_inst.reg, ""); 2682 s3_inst.error = NULL; 2683 s3_inst.reloc.type = BFD_RELOC_NONE; 2684 2685 (*opcode->parms) (p); 2686 2687 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ 2688 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) 2689 s3_gen_insn_frag (&s3_inst, NULL); 2690 } 2691 else 2692 s3_inst.error = _("unrecognized opcode"); 2693} 2694 2695static void 2696s3_parse_48_inst (char *insnstr, bool gen_frag_p) 2697{ 2698 char c; 2699 char *p; 2700 char *operator = insnstr; 2701 const struct s3_asm_opcode *opcode; 2702 2703 /* Parse operator and operands. */ 2704 s3_skip_whitespace (operator); 2705 2706 for (p = operator; *p != '\0'; p++) 2707 if (*p == ' ') 2708 break; 2709 2710 c = *p; 2711 *p = '\0'; 2712 2713 opcode = (const struct s3_asm_opcode *) str_hash_find (s3_score_ops_hsh, 2714 operator); 2715 *p = c; 2716 2717 memset (&s3_inst, '\0', sizeof (s3_inst)); 2718 sprintf (s3_inst.str, "%s", insnstr); 2719 if (opcode) 2720 { 2721 s3_inst.instruction = opcode->value; 2722 s3_inst.relax_inst = opcode->relax_value; 2723 s3_inst.type = opcode->type; 2724 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); 2725 s3_inst.relax_size = 0; 2726 s3_inst.bwarn = 0; 2727 sprintf (s3_inst.name, "%s", opcode->template_name); 2728 strcpy (s3_inst.reg, ""); 2729 s3_inst.error = NULL; 2730 s3_inst.reloc.type = BFD_RELOC_NONE; 2731 2732 (*opcode->parms) (p); 2733 2734 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ 2735 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) 2736 s3_gen_insn_frag (&s3_inst, NULL); 2737 } 2738 else 2739 s3_inst.error = _("unrecognized opcode"); 2740} 2741 2742static int 2743s3_append_insn (char *str, bool gen_frag_p) 2744{ 2745 int retval = s3_SUCCESS; 2746 2747 s3_parse_16_32_inst (str, gen_frag_p); 2748 2749 if (s3_inst.error) 2750 { 2751 retval = (int) s3_FAIL; 2752 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); 2753 s3_inst.error = NULL; 2754 } 2755 2756 return retval; 2757} 2758 2759static void 2760s3_do16_mv_cmp (char *str) 2761{ 2762 s3_skip_whitespace (str); 2763 2764 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2765 || s3_skip_past_comma (&str) == (int) s3_FAIL 2766 || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2767 || s3_end_of_line (str) == (int) s3_FAIL) 2768 { 2769 return; 2770 } 2771} 2772 2773static void 2774s3_do16_cmpi (char *str) 2775{ 2776 s3_skip_whitespace (str); 2777 2778 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2779 || s3_skip_past_comma (&str) == (int) s3_FAIL 2780 || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL 2781 || s3_end_of_line (str) == (int) s3_FAIL) 2782 { 2783 return; 2784 } 2785} 2786 2787static void 2788s3_do16_addi (char *str) 2789{ 2790 s3_skip_whitespace (str); 2791 2792 if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL 2793 || s3_skip_past_comma (&str) == (int) s3_FAIL 2794 || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL 2795 || s3_end_of_line (str) == (int) s3_FAIL) 2796 { 2797 return; 2798 } 2799} 2800 2801/* Handle bitclr! / bitset! / bittst! / bittgl! */ 2802static void 2803s3_do16_rdi5 (char *str) 2804{ 2805 s3_skip_whitespace (str); 2806 2807 if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL 2808 || s3_skip_past_comma (&str) == (int) s3_FAIL 2809 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 2810 || s3_end_of_line (str) == (int) s3_FAIL) 2811 return; 2812 else 2813 { 2814 s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20) 2815 | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10); 2816 s3_inst.relax_size = 4; 2817 } 2818} 2819 2820 2821/* Handle sdbbp!. */ 2822static void 2823s3_do16_xi5 (char *str) 2824{ 2825 s3_skip_whitespace (str); 2826 2827 if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) 2828 return; 2829} 2830 2831/* Check that an immediate is word alignment or half word alignment. 2832 If so, convert it to the right format. */ 2833static int 2834s3_validate_immediate_align (int val, unsigned int data_type) 2835{ 2836 if (data_type == _IMM5_RSHIFT_1) 2837 { 2838 if (val % 2) 2839 { 2840 s3_inst.error = _("address offset must be half word alignment"); 2841 return (int) s3_FAIL; 2842 } 2843 } 2844 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2845 { 2846 if (val % 4) 2847 { 2848 s3_inst.error = _("address offset must be word alignment"); 2849 return (int) s3_FAIL; 2850 } 2851 } 2852 2853 return s3_SUCCESS; 2854} 2855 2856static int 2857s3_exp_ldst_offset (char **str, int shift, unsigned int data_type) 2858{ 2859 char *dataptr; 2860 2861 dataptr = * str; 2862 2863 if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 2864 && (data_type != _SIMM16_LA) 2865 && (data_type != _VALUE_HI16) 2866 && (data_type != _VALUE_LO16) 2867 && (data_type != _IMM16) 2868 && (data_type != _IMM15) 2869 && (data_type != _IMM14) 2870 && (data_type != _IMM4) 2871 && (data_type != _IMM5) 2872 && (data_type != _IMM8) 2873 && (data_type != _IMM5_RSHIFT_1) 2874 && (data_type != _IMM5_RSHIFT_2) 2875 && (data_type != _SIMM14_NEG) 2876 && (data_type != _IMM10_RSHIFT_2)) 2877 { 2878 data_type += 24; 2879 } 2880 2881 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL) 2882 return (int) s3_FAIL; 2883 2884 if (s3_inst.reloc.exp.X_op == O_constant) 2885 { 2886 /* Need to check the immediate align. */ 2887 int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type); 2888 2889 if (value == (int) s3_FAIL) 2890 return (int) s3_FAIL; 2891 2892 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 2893 if (value == (int) s3_FAIL) 2894 { 2895 if (data_type < 30) 2896 sprintf (s3_err_msg, 2897 _("invalid constant: %d bit expression not in range %d..%d"), 2898 s3_score_df_range[data_type].bits, 2899 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 2900 else 2901 sprintf (s3_err_msg, 2902 _("invalid constant: %d bit expression not in range %d..%d"), 2903 s3_score_df_range[data_type - 24].bits, 2904 s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]); 2905 s3_inst.error = s3_err_msg; 2906 return (int) s3_FAIL; 2907 } 2908 2909 if (data_type == _IMM5_RSHIFT_1) 2910 { 2911 value >>= 1; 2912 } 2913 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2914 { 2915 value >>= 2; 2916 } 2917 2918 if (s3_score_df_range[data_type].range[0] != 0) 2919 { 2920 value &= (1 << s3_score_df_range[data_type].bits) - 1; 2921 } 2922 2923 s3_inst.instruction |= value << shift; 2924 } 2925 else 2926 { 2927 s3_inst.reloc.pc_rel = 0; 2928 } 2929 2930 return s3_SUCCESS; 2931} 2932 2933static void 2934s3_do_ldst_insn (char *str) 2935{ 2936 int pre_inc = 0; 2937 int conflict_reg; 2938 int value; 2939 char * temp; 2940 char *dataptr; 2941 int reg; 2942 int ldst_idx = 0; 2943 2944 s3_skip_whitespace (str); 2945 2946 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 2947 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 2948 return; 2949 2950 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */ 2951 if (*str == '[') 2952 { 2953 str++; 2954 s3_skip_whitespace (str); 2955 2956 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 2957 return; 2958 2959 /* Conflicts can occur on stores as well as loads. */ 2960 conflict_reg = (conflict_reg == reg); 2961 s3_skip_whitespace (str); 2962 temp = str + 1; /* The latter will process decimal/hex expression. */ 2963 2964 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */ 2965 if (*str == ']') 2966 { 2967 str++; 2968 if (*str == '+') 2969 { 2970 str++; 2971 /* ld/sw rD, [rA]+, simm12. */ 2972 if (s3_skip_past_comma (&str) == s3_SUCCESS) 2973 { 2974 if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL) 2975 || (s3_end_of_line (str) == (int) s3_FAIL)) 2976 return; 2977 2978 if (conflict_reg) 2979 { 2980 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 2981 2982 if ((ldst_func == INSN_LH) 2983 || (ldst_func == INSN_LHU) 2984 || (ldst_func == INSN_LW) 2985 || (ldst_func == INSN_LB) 2986 || (ldst_func == INSN_LBU)) 2987 { 2988 s3_inst.error = _("register same as write-back base"); 2989 return; 2990 } 2991 } 2992 2993 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 2994 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2995 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value; 2996 2997 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */ 2998 if ((s3_inst.instruction & 0x3e000007) == 0x0e000000) 2999 { 3000 /* rs = r0, offset = 4 */ 3001 if ((((s3_inst.instruction >> 15) & 0x1f) == 0) 3002 && (((s3_inst.instruction >> 3) & 0xfff) == 4)) 3003 { 3004 /* Relax to pop!. */ 3005 s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f); 3006 s3_inst.relax_size = 2; 3007 } 3008 } 3009 return; 3010 } 3011 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */ 3012 else 3013 { 3014 s3_SET_INSN_ERROR (NULL); 3015 if (s3_end_of_line (str) == (int) s3_FAIL) 3016 { 3017 return; 3018 } 3019 3020 pre_inc = 1; 3021 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0); 3022 value &= (1 << s3_score_df_range[_SIMM12].bits) - 1; 3023 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3024 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3025 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; 3026 s3_inst.instruction |= value << 3; 3027 s3_inst.relax_inst = 0x8000; 3028 return; 3029 } 3030 } 3031 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */ 3032 else 3033 { 3034 if (s3_end_of_line (str) == (int) s3_FAIL) 3035 return; 3036 3037 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3038 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3039 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; 3040 3041 /* lbu rd, [rs] -> lbu! rd, [rs] */ 3042 if (ldst_idx == INSN_LBU) 3043 { 3044 s3_inst.relax_inst = INSN16_LBU; 3045 } 3046 else if (ldst_idx == INSN_LH) 3047 { 3048 s3_inst.relax_inst = INSN16_LH; 3049 } 3050 else if (ldst_idx == INSN_LW) 3051 { 3052 s3_inst.relax_inst = INSN16_LW; 3053 } 3054 else if (ldst_idx == INSN_SB) 3055 { 3056 s3_inst.relax_inst = INSN16_SB; 3057 } 3058 else if (ldst_idx == INSN_SH) 3059 { 3060 s3_inst.relax_inst = INSN16_SH; 3061 } 3062 else if (ldst_idx == INSN_SW) 3063 { 3064 s3_inst.relax_inst = INSN16_SW; 3065 } 3066 else 3067 { 3068 s3_inst.relax_inst = 0x8000; 3069 } 3070 3071 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */ 3072 /* if ((ldst_idx == INSN_LBU) 3073 || (ldst_idx == INSN_LH) 3074 || (ldst_idx == INSN_LW) 3075 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/ 3076 if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW)) 3077 { 3078 /* ra only 3 bit , rd only 4 bit for lw! and sw! */ 3079 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3080 { 3081 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) | 3082 (((s3_inst.instruction >> 15) & 0x7) << 5); 3083 s3_inst.relax_size = 2; 3084 } 3085 } 3086 3087 return; 3088 } 3089 } 3090 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */ 3091 else 3092 { 3093 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3094 { 3095 s3_inst.error = _("pre-indexed expression expected"); 3096 return; 3097 } 3098 3099 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 3100 return; 3101 3102 s3_skip_whitespace (str); 3103 if (*str++ != ']') 3104 { 3105 s3_inst.error = _("missing ]"); 3106 return; 3107 } 3108 3109 s3_skip_whitespace (str); 3110 /* ld/sw rD, [rA, simm12]+. */ 3111 if (*str == '+') 3112 { 3113 str++; 3114 pre_inc = 1; 3115 if (conflict_reg) 3116 { 3117 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3118 3119 if ((ldst_func == INSN_LH) 3120 || (ldst_func == INSN_LHU) 3121 || (ldst_func == INSN_LW) 3122 || (ldst_func == INSN_LB) 3123 || (ldst_func == INSN_LBU)) 3124 { 3125 s3_inst.error = _("register same as write-back base"); 3126 return; 3127 } 3128 } 3129 } 3130 3131 if (s3_end_of_line (str) == (int) s3_FAIL) 3132 return; 3133 3134 if (s3_inst.reloc.exp.X_op == O_constant) 3135 { 3136 unsigned int data_type; 3137 3138 if (pre_inc == 1) 3139 data_type = _SIMM12; 3140 else 3141 data_type = _SIMM15; 3142 dataptr = temp; 3143 3144 if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 3145 && (data_type != _SIMM16_LA) 3146 && (data_type != _VALUE_HI16) 3147 && (data_type != _VALUE_LO16) 3148 && (data_type != _IMM16) 3149 && (data_type != _IMM15) 3150 && (data_type != _IMM14) 3151 && (data_type != _IMM4) 3152 && (data_type != _IMM5) 3153 && (data_type != _IMM8) 3154 && (data_type != _IMM5_RSHIFT_1) 3155 && (data_type != _IMM5_RSHIFT_2) 3156 && (data_type != _SIMM14_NEG) 3157 && (data_type != _IMM10_RSHIFT_2)) 3158 { 3159 data_type += 24; 3160 } 3161 3162 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 3163 if (value == (int) s3_FAIL) 3164 { 3165 if (data_type < 30) 3166 sprintf (s3_err_msg, 3167 _("invalid constant: %d bit expression not in range %d..%d"), 3168 s3_score_df_range[data_type].bits, 3169 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 3170 else 3171 sprintf (s3_err_msg, 3172 _("invalid constant: %d bit expression not in range %d..%d"), 3173 s3_score_df_range[data_type - 24].bits, 3174 s3_score_df_range[data_type - 24].range[0], 3175 s3_score_df_range[data_type - 24].range[1]); 3176 s3_inst.error = s3_err_msg; 3177 return; 3178 } 3179 3180 value &= (1 << s3_score_df_range[data_type].bits) - 1; 3181 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3182 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3183 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; 3184 if (pre_inc == 1) 3185 s3_inst.instruction |= value << 3; 3186 else 3187 s3_inst.instruction |= value; 3188 3189 /* lw rD, [rA, simm15] */ 3190 if ((s3_inst.instruction & 0x3e000000) == 0x20000000) 3191 { 3192 /* rD in [r0 - r15]. , ra in [r0-r7] */ 3193 if ((((s3_inst.instruction >> 15) & 0x18) == 0) 3194 && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3195 { 3196 /* simm = [bit 7], lw -> lw!. */ 3197 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) 3198 { 3199 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5) 3200 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); 3201 s3_inst.relax_size = 2; 3202 } 3203 else 3204 { 3205 s3_inst.relax_inst = 0x8000; 3206 } 3207 } 3208 else 3209 { 3210 s3_inst.relax_inst = 0x8000; 3211 } 3212 } 3213 /* sw rD, [rA, simm15] */ 3214 else if ((s3_inst.instruction & 0x3e000000) == 0x28000000) 3215 { 3216 /* rD is in [r0 - r15] and ra in [r0-r7] */ 3217 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3218 { 3219 /* simm15 =7 bit , sw -> sw!. */ 3220 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) 3221 { 3222 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5) 3223 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); 3224 s3_inst.relax_size = 2; 3225 } 3226 /* rA = r2, sw -> swp!. */ 3227 else 3228 { 3229 s3_inst.relax_inst = 0x8000; 3230 } 3231 } 3232 else 3233 { 3234 s3_inst.relax_inst = 0x8000; 3235 } 3236 } 3237 /* sw rD, [rA, simm15]+ sw pre. */ 3238 else if ((s3_inst.instruction & 0x3e000007) == 0x06000004) 3239 { 3240 /* simm15 = -4. and ra==r0 */ 3241 if ((((s3_inst.instruction >> 15) & 0x1f) == 0) 3242 && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc)) 3243 { 3244 /* sw -> push!. */ 3245 s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f); 3246 s3_inst.relax_size = 2; 3247 } 3248 else 3249 { 3250 s3_inst.relax_inst = 0x8000; 3251 } 3252 } 3253 else 3254 { 3255 s3_inst.relax_inst = 0x8000; 3256 } 3257 3258 return; 3259 } 3260 else 3261 { 3262 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */ 3263 s3_inst.reloc.pc_rel = 0; 3264 } 3265 } 3266 } 3267 else 3268 { 3269 s3_inst.error = s3_BAD_ARGS; 3270 } 3271} 3272 3273/* Handle cache. */ 3274static void 3275s3_do_cache (char *str) 3276{ 3277 s3_skip_whitespace (str); 3278 3279 if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3280 { 3281 return; 3282 } 3283 else 3284 { 3285 int cache_op; 3286 3287 cache_op = (s3_inst.instruction >> 20) & 0x1F; 3288 sprintf (s3_inst.name, "cache %d", cache_op); 3289 } 3290 3291 if (*str == '[') 3292 { 3293 str++; 3294 s3_skip_whitespace (str); 3295 3296 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3297 return; 3298 3299 s3_skip_whitespace (str); 3300 3301 /* cache op, [rA] */ 3302 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3303 { 3304 s3_SET_INSN_ERROR (NULL); 3305 if (*str != ']') 3306 { 3307 s3_inst.error = _("missing ]"); 3308 return; 3309 } 3310 str++; 3311 } 3312 /* cache op, [rA, simm15] */ 3313 else 3314 { 3315 if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL) 3316 { 3317 return; 3318 } 3319 3320 s3_skip_whitespace (str); 3321 if (*str++ != ']') 3322 { 3323 s3_inst.error = _("missing ]"); 3324 return; 3325 } 3326 } 3327 3328 if (s3_end_of_line (str) == (int) s3_FAIL) 3329 return; 3330 } 3331 else 3332 { 3333 s3_inst.error = s3_BAD_ARGS; 3334 } 3335} 3336 3337static void 3338s3_do_crdcrscrsimm5 (char *str) 3339{ 3340 char *strbak; 3341 3342 strbak = str; 3343 s3_skip_whitespace (str); 3344 3345 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3346 || s3_skip_past_comma (&str) == (int) s3_FAIL 3347 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3348 || s3_skip_past_comma (&str) == (int) s3_FAIL 3349 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3350 || s3_skip_past_comma (&str) == (int) s3_FAIL) 3351 { 3352 str = strbak; 3353 /* cop1 cop_code20. */ 3354 if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL) 3355 return; 3356 } 3357 else 3358 { 3359 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL) 3360 return; 3361 } 3362 3363 s3_end_of_line (str); 3364} 3365 3366/* Handle ldc/stc. */ 3367static void 3368s3_do_ldst_cop (char *str) 3369{ 3370 s3_skip_whitespace (str); 3371 3372 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL) 3373 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3374 return; 3375 3376 if (*str == '[') 3377 { 3378 str++; 3379 s3_skip_whitespace (str); 3380 3381 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3382 return; 3383 3384 s3_skip_whitespace (str); 3385 3386 if (*str++ != ']') 3387 { 3388 if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL) 3389 return; 3390 3391 s3_skip_whitespace (str); 3392 if (*str++ != ']') 3393 { 3394 s3_inst.error = _("missing ]"); 3395 return; 3396 } 3397 } 3398 3399 s3_end_of_line (str); 3400 } 3401 else 3402 s3_inst.error = s3_BAD_ARGS; 3403} 3404 3405static void 3406s3_do16_ldst_insn (char *str) 3407{ 3408 int conflict_reg = 0; 3409 s3_skip_whitespace (str); 3410 3411 if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3412 return; 3413 3414 if (*str == '[') 3415 { 3416 3417 str++; 3418 s3_skip_whitespace (str); 3419 3420 if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL) 3421 return; 3422 if (conflict_reg&0x8) 3423 { 3424 sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg); 3425 s3_inst.error = s3_err_msg; 3426 return; 3427 } 3428 3429 s3_skip_whitespace (str); 3430 3431 if (*str == ']') 3432 { 3433 str++; 3434 if (s3_end_of_line (str) == (int) s3_FAIL) 3435 return; 3436 } 3437 else 3438 { 3439 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3440 { 3441 s3_inst.error = _("comma is expected"); 3442 return; 3443 } 3444 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 3445 return; 3446 s3_skip_whitespace (str); 3447 if (*str++ != ']') 3448 { 3449 s3_inst.error = _("missing ]"); 3450 return; 3451 } 3452 if (s3_end_of_line (str) == (int) s3_FAIL) 3453 return; 3454 if (s3_inst.reloc.exp.X_op == O_constant) 3455 { 3456 int value; 3457 unsigned int data_type; 3458 data_type = _IMM5_RSHIFT_2; 3459 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 3460 if (value == (int) s3_FAIL) 3461 { 3462 if (data_type < 30) 3463 sprintf (s3_err_msg, 3464 _("invalid constant: %d bit expression not in range %d..%d"), 3465 s3_score_df_range[data_type].bits, 3466 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 3467 s3_inst.error = s3_err_msg; 3468 return; 3469 } 3470 if (value & 0x3) 3471 { 3472 sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value); 3473 s3_inst.error = s3_err_msg; 3474 return; 3475 } 3476 3477 value >>= 2; 3478 s3_inst.instruction |= value; 3479 } 3480 } 3481 } 3482 else 3483 { 3484 sprintf (s3_err_msg, _("missing [")); 3485 s3_inst.error = s3_err_msg; 3486 return; 3487 } 3488} 3489 3490static void 3491s3_do_lw48 (char *str) 3492{ 3493 bfd_signed_vma val = 0; 3494 3495 s3_skip_whitespace (str); 3496 3497 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3498 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3499 return; 3500 3501 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3502 || s3_end_of_line (str) == (int) s3_FAIL) 3503 { 3504 return; 3505 } 3506 3507 /* Check word align for lw48 rd, value. */ 3508 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3509 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) 3510 { 3511 s3_inst.error = _("invalid constant: 32 bit expression not word align"); 3512 return; 3513 } 3514 3515 /* Check and set offset. */ 3516 val = s3_inst.reloc.exp.X_add_number; 3517 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3518 && (!(val >= 0 && val <= 0xffffffffLL))) 3519 { 3520 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); 3521 return; 3522 } 3523 3524 val &= 0xffffffff; 3525 val >>= 2; 3526 s3_inst.instruction |= (val << 7); 3527 3528 /* Set reloc type. */ 3529 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; 3530 3531} 3532 3533static void 3534s3_do_sw48 (char *str) 3535{ 3536 bfd_signed_vma val = 0; 3537 3538 s3_skip_whitespace (str); 3539 3540 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3541 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3542 return; 3543 3544 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3545 || s3_end_of_line (str) == (int) s3_FAIL) 3546 { 3547 return; 3548 } 3549 3550 /* Check word align for lw48 rd, value. */ 3551 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3552 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) 3553 { 3554 s3_inst.error = _("invalid constant: 32 bit expression not word align"); 3555 return; 3556 } 3557 3558 /* Check and set offset. */ 3559 val = s3_inst.reloc.exp.X_add_number; 3560 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3561 && (!(val >= 0 && val <= 0xffffffffLL))) 3562 { 3563 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); 3564 return; 3565 } 3566 3567 val &= 0xffffffff; 3568 val >>= 2; 3569 s3_inst.instruction |= (val << 7); 3570 3571 /* Set reloc type. */ 3572 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; 3573} 3574 3575static void 3576s3_do_ldi48 (char *str) 3577{ 3578 bfd_signed_vma val; 3579 3580 s3_skip_whitespace (str); 3581 3582 if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL 3583 || s3_skip_past_comma (&str) == (int) s3_FAIL) 3584 return; 3585 3586 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3587 || s3_end_of_line (str) == (int) s3_FAIL) 3588 { 3589 return; 3590 } 3591 3592 /* Check and set offset. */ 3593 val = s3_inst.reloc.exp.X_add_number; 3594 if (!(val >= -0xffffffffLL && val <= 0xffffffffLL)) 3595 { 3596 s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]"); 3597 return; 3598 } 3599 3600 val &= 0xffffffff; 3601 s3_inst.instruction |= (val << 5); 3602 3603 /* Set reloc type. */ 3604 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32; 3605} 3606 3607static void 3608s3_do_sdbbp48 (char *str) 3609{ 3610 s3_skip_whitespace (str); 3611 3612 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) 3613 return; 3614} 3615 3616static void 3617s3_do_and48 (char *str) 3618{ 3619 s3_skip_whitespace (str); 3620 3621 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL 3622 || s3_skip_past_comma (&str) == (int) s3_FAIL 3623 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL 3624 || s3_skip_past_comma (&str) == (int) s3_FAIL 3625 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL 3626 || s3_end_of_line (str) == (int) s3_FAIL) 3627 return; 3628} 3629 3630static void 3631s3_do_or48 (char *str) 3632{ 3633 s3_skip_whitespace (str); 3634 3635 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL 3636 || s3_skip_past_comma (&str) == (int) s3_FAIL 3637 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL 3638 || s3_skip_past_comma (&str) == (int) s3_FAIL 3639 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL 3640 || s3_end_of_line (str) == (int) s3_FAIL) 3641 return; 3642} 3643 3644static void 3645s3_do_mbitclr (char *str) 3646{ 3647 int val; 3648 s3_skip_whitespace (str); 3649 3650 if (*str != '[') 3651 { 3652 sprintf (s3_err_msg, _("missing [")); 3653 s3_inst.error = s3_err_msg; 3654 return; 3655 } 3656 str++; 3657 3658 s3_inst.instruction &= 0x0; 3659 3660 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3661 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3662 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) 3663 return; 3664 3665 /* Get imm11 and refill opcode. */ 3666 val = s3_inst.instruction & 0x7ff; 3667 val >>= 2; 3668 s3_inst.instruction &= 0x000f8000; 3669 s3_inst.instruction |= 0x00000064; 3670 3671 if (*str != ']') 3672 { 3673 sprintf (s3_err_msg, _("missing ]")); 3674 s3_inst.error = s3_err_msg; 3675 return; 3676 } 3677 str++; 3678 3679 if ((s3_skip_past_comma (&str) == (int) s3_FAIL) 3680 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) 3681 return; 3682 3683 /* Set imm11 to opcode. */ 3684 s3_inst.instruction |= (val & 0x1) 3685 | (((val >> 1 ) & 0x7) << 7) 3686 | (((val >> 4 ) & 0x1f) << 20); 3687} 3688 3689static void 3690s3_do_mbitset (char *str) 3691{ 3692 int val; 3693 s3_skip_whitespace (str); 3694 3695 if (*str != '[') 3696 { 3697 sprintf (s3_err_msg, _("missing [")); 3698 s3_inst.error = s3_err_msg; 3699 return; 3700 } 3701 str++; 3702 3703 s3_inst.instruction &= 0x0; 3704 3705 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3706 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3707 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) 3708 return; 3709 3710 /* Get imm11 and refill opcode. */ 3711 val = s3_inst.instruction & 0x7ff; 3712 val >>= 2; 3713 s3_inst.instruction &= 0x000f8000; 3714 s3_inst.instruction |= 0x0000006c; 3715 3716 if (*str != ']') 3717 { 3718 sprintf (s3_err_msg, _("missing ]")); 3719 s3_inst.error = s3_err_msg; 3720 return; 3721 } 3722 str++; 3723 3724 if ((s3_skip_past_comma (&str) == (int) s3_FAIL) 3725 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) 3726 return; 3727 3728 /* Set imm11 to opcode. */ 3729 s3_inst.instruction |= (val & 0x1) 3730 | (((val >> 1 ) & 0x7) << 7) 3731 | (((val >> 4 ) & 0x1f) << 20); 3732} 3733 3734static void 3735s3_do16_slli_srli (char *str) 3736{ 3737 s3_skip_whitespace (str); 3738 3739 if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL) 3740 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3741 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 3742 || s3_end_of_line (str) == (int) s3_FAIL) 3743 return; 3744} 3745 3746static void 3747s3_do16_ldiu (char *str) 3748{ 3749 s3_skip_whitespace (str); 3750 3751 if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3752 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3753 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 3754 || s3_end_of_line (str) == (int) s3_FAIL) 3755 return; 3756} 3757 3758static void 3759s3_do16_push_pop (char *str) 3760{ 3761 s3_skip_whitespace (str); 3762 if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 3763 || s3_end_of_line (str) == (int) s3_FAIL) 3764 return; 3765} 3766 3767static void 3768s3_do16_rpush (char *str) 3769{ 3770 int reg; 3771 int val; 3772 s3_skip_whitespace (str); 3773 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL 3774 || s3_skip_past_comma (&str) == (int) s3_FAIL 3775 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL 3776 || s3_end_of_line (str) == (int) s3_FAIL) 3777 return; 3778 3779 /* 0: indicate 32. 3780 1: invalid value. 3781 2: to 31: normal value. */ 3782 val = s3_inst.instruction & 0x1f; 3783 if (val == 1) 3784 { 3785 s3_inst.error = _("imm5 should >= 2"); 3786 return; 3787 } 3788 if (reg >= 32) 3789 { 3790 s3_inst.error = _("reg should <= 31"); 3791 return; 3792 } 3793} 3794 3795static void 3796s3_do16_rpop (char *str) 3797{ 3798 int reg; 3799 int val; 3800 s3_skip_whitespace (str); 3801 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL 3802 || s3_skip_past_comma (&str) == (int) s3_FAIL 3803 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL 3804 || s3_end_of_line (str) == (int) s3_FAIL) 3805 return; 3806 3807 /* 0: indicate 32. 3808 1: invalid value. 3809 2: to 31: normal value. */ 3810 val = s3_inst.instruction & 0x1f; 3811 if (val == 1) 3812 { 3813 s3_inst.error = _("imm5 should >= 2"); 3814 return; 3815 } 3816 3817 if (reg >= 32) 3818 { 3819 s3_inst.error = _("reg should <= 31"); 3820 return; 3821 } 3822 else 3823 { 3824 if ((reg + val) <= 32) 3825 reg = reg + val - 1; 3826 else 3827 reg = reg + val - 33; 3828 s3_inst.instruction &= 0x7c1f; 3829 s3_inst.instruction |= (reg << 5); 3830 return; 3831 } 3832} 3833 3834/* Handle lcb/lcw/lce/scb/scw/sce. */ 3835static void 3836s3_do_ldst_unalign (char *str) 3837{ 3838 int conflict_reg; 3839 3840 if (s3_university_version == 1) 3841 { 3842 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; 3843 return; 3844 } 3845 3846 s3_skip_whitespace (str); 3847 3848 /* lcb/scb [rA]+. */ 3849 if (*str == '[') 3850 { 3851 str++; 3852 s3_skip_whitespace (str); 3853 3854 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3855 return; 3856 3857 if (*str++ == ']') 3858 { 3859 if (*str++ != '+') 3860 { 3861 s3_inst.error = _("missing +"); 3862 return; 3863 } 3864 } 3865 else 3866 { 3867 s3_inst.error = _("missing ]"); 3868 return; 3869 } 3870 3871 if (s3_end_of_line (str) == (int) s3_FAIL) 3872 return; 3873 } 3874 /* lcw/lce/scb/sce rD, [rA]+. */ 3875 else 3876 { 3877 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3878 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3879 { 3880 return; 3881 } 3882 3883 s3_skip_whitespace (str); 3884 if (*str++ == '[') 3885 { 3886 int reg; 3887 3888 s3_skip_whitespace (str); 3889 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3890 { 3891 return; 3892 } 3893 3894 /* Conflicts can occur on stores as well as loads. */ 3895 conflict_reg = (conflict_reg == reg); 3896 s3_skip_whitespace (str); 3897 if (*str++ == ']') 3898 { 3899 unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK; 3900 3901 if (*str++ == '+') 3902 { 3903 if (conflict_reg) 3904 { 3905 as_warn (_("%s register same as write-back base"), 3906 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW) 3907 ? _("destination") : _("source"))); 3908 } 3909 } 3910 else 3911 { 3912 s3_inst.error = _("missing +"); 3913 return; 3914 } 3915 3916 if (s3_end_of_line (str) == (int) s3_FAIL) 3917 return; 3918 } 3919 else 3920 { 3921 s3_inst.error = _("missing ]"); 3922 return; 3923 } 3924 } 3925 else 3926 { 3927 s3_inst.error = s3_BAD_ARGS; 3928 return; 3929 } 3930 } 3931} 3932 3933/* Handle alw/asw. */ 3934static void 3935s3_do_ldst_atomic (char *str) 3936{ 3937 if (s3_university_version == 1) 3938 { 3939 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; 3940 return; 3941 } 3942 3943 s3_skip_whitespace (str); 3944 3945 if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3946 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3947 { 3948 return; 3949 } 3950 else 3951 { 3952 3953 s3_skip_whitespace (str); 3954 if (*str++ == '[') 3955 { 3956 int reg; 3957 3958 s3_skip_whitespace (str); 3959 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3960 { 3961 return; 3962 } 3963 3964 s3_skip_whitespace (str); 3965 if (*str++ != ']') 3966 { 3967 s3_inst.error = _("missing ]"); 3968 return; 3969 } 3970 3971 s3_end_of_line (str); 3972 } 3973 else 3974 s3_inst.error = s3_BAD_ARGS; 3975 } 3976} 3977 3978static void 3979s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED, 3980 struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num, 3981 symbolS *add_symbol) 3982{ 3983 int i; 3984 char *p; 3985 fixS *fixp = NULL; 3986 fixS *cur_fixp = NULL; 3987 long where; 3988 struct s3_score_it inst_main; 3989 3990 memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it)); 3991 3992 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 3993 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 3994 inst_main.type = Insn_PIC; 3995 3996 for (i = 0; i < var_num; i++) 3997 { 3998 inst_main.relax_size += var_insts[i].size; 3999 var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction, 4000 s3_GET_INSN_CLASS (var_insts[i].type)); 4001 } 4002 4003 /* Check data dependency. */ 4004 s3_handle_dependency (&inst_main); 4005 4006 /* Start a new frag if frag_now is not empty. */ 4007 if (frag_now_fix () != 0) 4008 { 4009 if (!frag_now->tc_frag_data.is_insn) 4010 { 4011 frag_wane (frag_now); 4012 } 4013 frag_new (0); 4014 } 4015 frag_grow (20); 4016 4017 /* Write fr_fix part. */ 4018 p = frag_more (inst_main.size); 4019 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4020 4021 if (inst_main.reloc.type != BFD_RELOC_NONE) 4022 fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4023 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4024 4025 frag_now->tc_frag_data.fixp = fixp; 4026 cur_fixp = frag_now->tc_frag_data.fixp; 4027 4028#ifdef OBJ_ELF 4029 dwarf2_emit_insn (inst_main.size); 4030#endif 4031 4032 where = p - frag_now->fr_literal + inst_main.size; 4033 for (i = 0; i < var_num; i++) 4034 { 4035 if (i > 0) 4036 where += var_insts[i - 1].size; 4037 4038 if (var_insts[i].reloc.type != BFD_RELOC_NONE) 4039 { 4040 fixp = s3_fix_new_score (frag_now, where, var_insts[i].size, 4041 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel, 4042 var_insts[i].reloc.type); 4043 if (fixp) 4044 { 4045 if (cur_fixp) 4046 { 4047 cur_fixp->fx_next = fixp; 4048 cur_fixp = cur_fixp->fx_next; 4049 } 4050 else 4051 { 4052 frag_now->tc_frag_data.fixp = fixp; 4053 cur_fixp = frag_now->tc_frag_data.fixp; 4054 } 4055 } 4056 } 4057 } 4058 4059 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4060 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 4061 0, inst_main.size, 0), add_symbol, 0, NULL); 4062 4063 /* Write fr_var part. 4064 no calling s3_gen_insn_frag, no fixS will be generated. */ 4065 for (i = 0; i < var_num; i++) 4066 { 4067 s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); 4068 p += var_insts[i].size; 4069 } 4070 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4071 s3_inst.bwarn = -1; 4072} 4073 4074/* Build a relax frag for la instruction when generating s3_PIC, 4075 external symbol first and local symbol second. */ 4076static void 4077s3_build_la_pic (int reg_rd, expressionS exp) 4078{ 4079 symbolS *add_symbol = exp.X_add_symbol; 4080 offsetT add_number = exp.X_add_number; 4081 struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; 4082 struct s3_score_it var_insts[s3_RELAX_INST_NUM]; 4083 int fix_num = 0; 4084 int var_num = 0; 4085 char tmp[s3_MAX_LITERAL_POOL_SIZE]; 4086 int r1_bak; 4087 4088 r1_bak = s3_nor1; 4089 s3_nor1 = 0; 4090 4091 if (add_number == 0) 4092 { 4093 fix_num = 1; 4094 var_num = 2; 4095 4096 /* For an external symbol, only one insn is generated; 4097 For a local symbol, two insns are generated. */ 4098 /* Fix part 4099 For an external symbol: lw rD, <sym>($gp) 4100 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */ 4101 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4102 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4103 return; 4104 4105 if (reg_rd == s3_PIC_CALL_REG) 4106 s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15; 4107 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4108 4109 /* Var part 4110 For a local symbol : 4111 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 4112 addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 4113 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4114 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4115 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4116 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4117 return; 4118 4119 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); 4120 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4121 } 4122 else if (add_number >= -0x8000 && add_number <= 0x7fff) 4123 { 4124 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 4125 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4126 if (s3_append_insn (tmp, true) == (int) s3_FAIL) 4127 return; 4128 4129 /* Insn 2 */ 4130 fix_num = 1; 4131 var_num = 1; 4132 /* Fix part 4133 For an external symbol: addi rD, <constant> */ 4134 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number); 4135 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4136 return; 4137 4138 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4139 4140 /* Var part 4141 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */ 4142 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, 4143 S_GET_NAME (add_symbol), (int) add_number); 4144 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4145 return; 4146 4147 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4148 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4149 } 4150 else 4151 { 4152 int hi = (add_number >> 16) & 0x0000FFFF; 4153 int lo = add_number & 0x0000FFFF; 4154 4155 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 4156 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4157 if (s3_append_insn (tmp, true) == (int) s3_FAIL) 4158 return; 4159 4160 /* Insn 2 */ 4161 fix_num = 1; 4162 var_num = 1; 4163 /* Fix part 4164 For an external symbol: ldis r1, HI%<constant> */ 4165 sprintf (tmp, "ldis r1, %d", hi); 4166 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4167 return; 4168 4169 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4170 4171 /* Var part 4172 For a local symbol: ldis r1, HI%<constant> 4173 but, if lo is out of 16 bit, make hi plus 1 */ 4174 if ((lo < -0x8000) || (lo > 0x7fff)) 4175 { 4176 hi += 1; 4177 } 4178 sprintf (tmp, "ldis_pic r1, %d", hi); 4179 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4180 return; 4181 4182 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4183 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4184 4185 /* Insn 3 */ 4186 fix_num = 1; 4187 var_num = 1; 4188 /* Fix part 4189 For an external symbol: ori r1, LO%<constant> */ 4190 sprintf (tmp, "ori r1, %d", lo); 4191 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4192 return; 4193 4194 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4195 4196 /* Var part 4197 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */ 4198 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo); 4199 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4200 return; 4201 4202 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4203 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4204 4205 /* Insn 4: add rD, rD, r1 */ 4206 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd); 4207 if (s3_append_insn (tmp, true) == (int) s3_FAIL) 4208 return; 4209 4210 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4211 s3_inst.bwarn = -1; 4212 } 4213 4214 s3_nor1 = r1_bak; 4215} 4216 4217/* Handle la. */ 4218static void 4219s3_do_macro_la_rdi32 (char *str) 4220{ 4221 int reg_rd; 4222 4223 s3_skip_whitespace (str); 4224 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4225 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4226 { 4227 return; 4228 } 4229 else 4230 { 4231 /* Save str. */ 4232 char *keep_data = str; 4233 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4234 4235 /* Check immediate value. */ 4236 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 4237 { 4238 s3_inst.error = _("expression error"); 4239 return; 4240 } 4241 else if ((s3_inst.reloc.exp.X_add_symbol == NULL) 4242 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL)) 4243 { 4244 s3_inst.error = _("value not in range [0, 0xffffffff]"); 4245 return; 4246 } 4247 4248 /* Reset str. */ 4249 str = keep_data; 4250 4251 /* la rd, simm16. */ 4252 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) 4253 { 4254 s3_end_of_line (str); 4255 return; 4256 } 4257 /* la rd, imm32 or la rd, label. */ 4258 else 4259 { 4260 s3_SET_INSN_ERROR (NULL); 4261 /* Reset str. */ 4262 str = keep_data; 4263 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) 4264 || (s3_end_of_line (str) == (int) s3_FAIL)) 4265 { 4266 return; 4267 } 4268 else 4269 { 4270 if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol)) 4271 { 4272 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 4273 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4274 return; 4275 4276 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 4277 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4278 return; 4279 } 4280 else 4281 { 4282 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4283 s3_build_la_pic (reg_rd, s3_inst.reloc.exp); 4284 } 4285 4286 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4287 s3_inst.bwarn = -1; 4288 } 4289 } 4290 } 4291} 4292 4293/* Handle li. */ 4294static void 4295s3_do_macro_li_rdi32 (char *str) 4296{ 4297 4298 int reg_rd; 4299 4300 s3_skip_whitespace (str); 4301 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4302 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4303 { 4304 return; 4305 } 4306 else 4307 { 4308 /* Save str. */ 4309 char *keep_data = str; 4310 4311 /* Check immediate value. */ 4312 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 4313 { 4314 s3_inst.error = _("expression error"); 4315 return; 4316 } 4317 else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL 4318 && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL)) 4319 { 4320 s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]"); 4321 return; 4322 } 4323 4324 /* Reset str. */ 4325 str = keep_data; 4326 4327 /* li rd, simm16. */ 4328 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) 4329 { 4330 s3_end_of_line (str); 4331 return; 4332 } 4333 /* li rd, imm32. */ 4334 else 4335 { 4336 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4337 4338 /* Reset str. */ 4339 str = keep_data; 4340 4341 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) 4342 || (s3_end_of_line (str) == (int) s3_FAIL)) 4343 { 4344 return; 4345 } 4346 else if (s3_inst.reloc.exp.X_add_symbol) 4347 { 4348 s3_inst.error = _("li rd label isn't correct instruction form"); 4349 return; 4350 } 4351 else 4352 { 4353 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 4354 4355 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4356 return; 4357 else 4358 { 4359 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 4360 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4361 return; 4362 4363 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4364 s3_inst.bwarn = -1; 4365 } 4366 } 4367 } 4368 } 4369} 4370 4371/* Handle mul/mulu/div/divu/rem/remu. */ 4372static void 4373s3_do_macro_mul_rdrsrs (char *str) 4374{ 4375 int reg_rd; 4376 int reg_rs1; 4377 int reg_rs2; 4378 char *backupstr; 4379 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4380 4381 if (s3_university_version == 1) 4382 as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV); 4383 4384 strcpy (append_str, str); 4385 backupstr = append_str; 4386 s3_skip_whitespace (backupstr); 4387 if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4388 || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4389 || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)) 4390 { 4391 s3_inst.error = s3_BAD_ARGS; 4392 return; 4393 } 4394 4395 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4396 { 4397 /* rem/remu rA, rB is error format. */ 4398 if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0) 4399 { 4400 s3_SET_INSN_ERROR (s3_BAD_ARGS); 4401 } 4402 else 4403 { 4404 s3_SET_INSN_ERROR (NULL); 4405 s3_do_rsrs (str); 4406 } 4407 return; 4408 } 4409 else 4410 { 4411 s3_SET_INSN_ERROR (NULL); 4412 if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4413 || (s3_end_of_line (backupstr) == (int) s3_FAIL)) 4414 { 4415 return; 4416 } 4417 else 4418 { 4419 char append_str1[s3_MAX_LITERAL_POOL_SIZE]; 4420 4421 if (strcmp (s3_inst.name, "rem") == 0) 4422 { 4423 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2); 4424 sprintf (append_str1, "mfceh r%d", reg_rd); 4425 } 4426 else if (strcmp (s3_inst.name, "remu") == 0) 4427 { 4428 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2); 4429 sprintf (append_str1, "mfceh r%d", reg_rd); 4430 } 4431 else 4432 { 4433 sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2); 4434 sprintf (append_str1, "mfcel r%d", reg_rd); 4435 } 4436 4437 /* Output mul/mulu or div/divu or rem/remu. */ 4438 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4439 return; 4440 4441 /* Output mfcel or mfceh. */ 4442 if (s3_append_insn (append_str1, true) == (int) s3_FAIL) 4443 return; 4444 4445 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4446 s3_inst.bwarn = -1; 4447 } 4448 } 4449} 4450 4451static void 4452s3_exp_macro_ldst_abs (char *str) 4453{ 4454 int reg_rd; 4455 char *backupstr, *tmp; 4456 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4457 char verifystr[s3_MAX_LITERAL_POOL_SIZE]; 4458 struct s3_score_it inst_backup; 4459 int r1_bak = 0; 4460 4461 r1_bak = s3_nor1; 4462 s3_nor1 = 0; 4463 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); 4464 4465 strcpy (verifystr, str); 4466 backupstr = verifystr; 4467 s3_skip_whitespace (backupstr); 4468 if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4469 return; 4470 4471 tmp = backupstr; 4472 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4473 return; 4474 4475 backupstr = tmp; 4476 sprintf (append_str, "li r1 %s", backupstr); 4477 s3_append_insn (append_str, true); 4478 4479 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); 4480 sprintf (append_str, " r%d, [r1,0]", reg_rd); 4481 s3_do_ldst_insn (append_str); 4482 4483 s3_nor1 = r1_bak; 4484} 4485 4486/* Handle bcmpeq / bcmpne */ 4487static void 4488s3_do_macro_bcmp (char *str) 4489{ 4490 int reg_a , reg_b; 4491 char *keep_data; 4492 size_t keep_data_size; 4493 int i; 4494 struct s3_score_it inst_expand[2]; 4495 struct s3_score_it inst_main; 4496 4497 memset (inst_expand, 0, sizeof inst_expand); 4498 s3_skip_whitespace (str); 4499 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4500 || s3_skip_past_comma (&str) == (int) s3_FAIL 4501 ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4502 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4503 return; 4504 4505 keep_data_size = strlen (str) + 1; 4506 keep_data = xmalloc (keep_data_size * 2 + 14); 4507 memcpy (keep_data, str, keep_data_size); 4508 4509 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 4510 ||reg_b == 0 4511 || s3_end_of_line (str) == (int) s3_FAIL) 4512 goto out; 4513 else if (s3_inst.reloc.exp.X_add_symbol == 0) 4514 { 4515 s3_inst.error = _("lacking label "); 4516 goto out; 4517 } 4518 else 4519 { 4520 char *append_str = keep_data + keep_data_size; 4521 s3_SET_INSN_ERROR (NULL); 4522 4523 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; 4524 s3_inst.reloc.pc_rel = 1; 4525 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; 4526 4527 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 4528 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1) 4529 | ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7 4530 | ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20; 4531 4532 /* Check and set offset. */ 4533 if (((val & 0xfffffe00) != 0) 4534 && ((val & 0xfffffe00) != 0xfffffe00)) 4535 { 4536 /* support bcmp --> cmp!+beq (bne) */ 4537 if (s3_score_pic == s3_NO_PIC) 4538 { 4539 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b); 4540 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4541 goto out; 4542 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4543 memcpy (append_str, "beq ", 4); 4544 else 4545 memcpy (append_str, "bne ", 4); 4546 memmove (append_str + 4, keep_data, strlen (keep_data) + 1); 4547 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4548 goto out; 4549 } 4550 else 4551 { 4552 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4553 } 4554 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4555 s3_inst.bwarn = -1; 4556 goto out; 4557 } 4558 else 4559 { 4560 val >>= 1; 4561 s3_inst.instruction |= (val & 0x1) 4562 | (((val >> 1) & 0x7) << 7) 4563 | (((val >> 4) & 0x1f) << 20); 4564 } 4565 4566 /* Backup s3_inst. */ 4567 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 4568 4569 if (s3_score_pic == s3_NO_PIC) 4570 { 4571 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b); 4572 if (s3_append_insn (append_str, false) == (int) s3_FAIL) 4573 goto out; 4574 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); 4575 4576 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4577 memcpy (append_str, "beq ", 4); 4578 else 4579 memcpy (append_str, "bne ", 4); 4580 memmove (append_str + 4, keep_data, strlen (keep_data) + 1); 4581 if (s3_append_insn (append_str, false) == (int) s3_FAIL) 4582 goto out; 4583 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); 4584 } 4585 else 4586 { 4587 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4588 } 4589 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; 4590 inst_main.type = Insn_BCMP; 4591 4592 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 4593 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 4594 4595 for (i = 0; i < 2; i++) 4596 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, 4597 s3_GET_INSN_CLASS (inst_expand[i].type)); 4598 /* Check data dependency. */ 4599 s3_handle_dependency (&inst_main); 4600 /* Start a new frag if frag_now is not empty. */ 4601 if (frag_now_fix () != 0) 4602 { 4603 if (!frag_now->tc_frag_data.is_insn) 4604 frag_wane (frag_now); 4605 frag_new (0); 4606 } 4607 frag_grow (20); 4608 4609 /* Write fr_fix part. */ 4610 char *p; 4611 p = frag_more (inst_main.size); 4612 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4613 4614 if (inst_main.reloc.type != BFD_RELOC_NONE) 4615 { 4616 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4617 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4618 } 4619#ifdef OBJ_ELF 4620 dwarf2_emit_insn (inst_main.size); 4621#endif 4622 4623 /* s3_GP instruction can not do optimization, only can do relax between 4624 1 instruction and 3 instructions. */ 4625 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4626 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), 4627 inst_main.reloc.exp.X_add_symbol, 0, NULL); 4628 4629 /* Write fr_var part. 4630 no calling s3_gen_insn_frag, no fixS will be generated. */ 4631 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 4632 p += inst_expand[0].size; 4633 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 4634 p += inst_expand[1].size; 4635 4636 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4637 s3_inst.bwarn = -1; 4638 } 4639 out: 4640 free (keep_data); 4641} 4642 4643/* Handle bcmpeqz / bcmpnez */ 4644static void 4645s3_do_macro_bcmpz (char *str) 4646{ 4647 int reg_a; 4648 char *keep_data; 4649 size_t keep_data_size; 4650 int i; 4651 struct s3_score_it inst_expand[2]; 4652 struct s3_score_it inst_main; 4653 4654 memset (inst_expand, 0, sizeof inst_expand); 4655 s3_skip_whitespace (str); 4656 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4657 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4658 return; 4659 4660 keep_data_size = strlen (str) + 1; 4661 keep_data = xmalloc (keep_data_size * 2 + 13); 4662 memcpy (keep_data, str, keep_data_size); 4663 4664 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 4665 || s3_end_of_line (str) == (int) s3_FAIL) 4666 goto out; 4667 else if (s3_inst.reloc.exp.X_add_symbol == 0) 4668 { 4669 s3_inst.error = _("lacking label "); 4670 goto out; 4671 } 4672 else 4673 { 4674 char *append_str = keep_data + keep_data_size; 4675 s3_SET_INSN_ERROR (NULL); 4676 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; 4677 s3_inst.reloc.pc_rel = 1; 4678 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; 4679 4680 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 4681 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number>>1) & 0x1) | ((s3_inst.reloc.exp.X_add_number>>2) & 0x7)<<7 |((s3_inst.reloc.exp.X_add_number>>5) & 0x1f)<<20; 4682 4683 /* Check and set offset. */ 4684 if (((val & 0xfffffe00) != 0) 4685 && ((val & 0xfffffe00) != 0xfffffe00)) 4686 { 4687 if (s3_score_pic == s3_NO_PIC) 4688 { 4689 sprintf (append_str, "cmpi! r%d, 0", reg_a); 4690 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4691 goto out; 4692 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4693 memcpy (append_str, "beq ", 4); 4694 else 4695 memcpy (append_str, "bne ", 4); 4696 memmove (append_str + 4, keep_data, strlen (keep_data) + 1); 4697 if (s3_append_insn (append_str, true) == (int) s3_FAIL) 4698 goto out; 4699 } 4700 else 4701 { 4702 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4703 } 4704 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4705 s3_inst.bwarn = -1; 4706 goto out; 4707 } 4708 else 4709 { 4710 val >>= 1; 4711 s3_inst.instruction |= (val & 0x1) 4712 | (((val >> 1) & 0x7) << 7) 4713 | (((val >> 4) & 0x1f) << 20); 4714 } 4715 4716 /* Backup s3_inst. */ 4717 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 4718 4719 if (s3_score_pic == s3_NO_PIC) 4720 { 4721 sprintf (append_str, "cmpi! r%d, 0", reg_a); 4722 if (s3_append_insn (append_str, false) == (int) s3_FAIL) 4723 goto out; 4724 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); 4725 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4726 memcpy (append_str, "beq ", 4); 4727 else 4728 memcpy (append_str, "bne ", 4); 4729 memmove (append_str + 4, keep_data, strlen (keep_data) + 1); 4730 if (s3_append_insn (append_str, false) == (int) s3_FAIL) 4731 goto out; 4732 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); 4733 } 4734 else 4735 { 4736 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4737 } 4738 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; 4739 inst_main.type = Insn_BCMP; 4740 4741 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 4742 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 4743 4744 for (i = 0; i < 2; i++) 4745 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction , 4746 s3_GET_INSN_CLASS (inst_expand[i].type)); 4747 /* Check data dependency. */ 4748 s3_handle_dependency (&inst_main); 4749 /* Start a new frag if frag_now is not empty. */ 4750 if (frag_now_fix () != 0) 4751 { 4752 if (!frag_now->tc_frag_data.is_insn) 4753 frag_wane (frag_now); 4754 frag_new (0); 4755 } 4756 frag_grow (20); 4757 4758 /* Write fr_fix part. */ 4759 char *p; 4760 p = frag_more (inst_main.size); 4761 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4762 4763 if (inst_main.reloc.type != BFD_RELOC_NONE) 4764 { 4765 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4766 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4767 } 4768#ifdef OBJ_ELF 4769 dwarf2_emit_insn (inst_main.size); 4770#endif 4771 4772 /* s3_GP instruction can not do optimization, only can do relax between 4773 1 instruction and 3 instructions. */ 4774 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4775 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), 4776 inst_main.reloc.exp.X_add_symbol, 0, NULL); 4777 4778 /* Write fr_var part. 4779 no calling s3_gen_insn_frag, no fixS will be generated. */ 4780 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 4781 p += inst_expand[0].size; 4782 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 4783 p += inst_expand[1].size; 4784 4785 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4786 s3_inst.bwarn = -1; 4787 } 4788 out: 4789 free (keep_data); 4790} 4791 4792static int 4793s3_nopic_need_relax (symbolS * sym, int before_relaxing) 4794{ 4795 if (sym == NULL) 4796 return 0; 4797 else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0) 4798 { 4799 const char *symname; 4800 const char *segname; 4801 4802 /* Find out whether this symbol can be referenced off the $gp 4803 register. It can be if it is smaller than the -G size or if 4804 it is in the .sdata or .sbss section. Certain symbols can 4805 not be referenced off the $gp, although it appears as though 4806 they can. */ 4807 symname = S_GET_NAME (sym); 4808 if (symname != (const char *)NULL 4809 && (strcmp (symname, "eprol") == 0 4810 || strcmp (symname, "etext") == 0 4811 || strcmp (symname, "_gp") == 0 4812 || strcmp (symname, "edata") == 0 4813 || strcmp (symname, "_fbss") == 0 4814 || strcmp (symname, "_fdata") == 0 4815 || strcmp (symname, "_ftext") == 0 4816 || strcmp (symname, "end") == 0 4817 || strcmp (symname, GP_DISP_LABEL) == 0)) 4818 { 4819 return 1; 4820 } 4821 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 4822 /* We must defer this decision until after the whole file has been read, 4823 since there might be a .extern after the first use of this symbol. */ 4824 || (before_relaxing 4825 && S_GET_VALUE (sym) == 0) 4826 || (S_GET_VALUE (sym) != 0 4827 && S_GET_VALUE (sym) <= s3_g_switch_value))) 4828 { 4829 return 0; 4830 } 4831 4832 segname = segment_name (S_GET_SEGMENT (sym)); 4833 return (strcmp (segname, ".sdata") != 0 4834 && strcmp (segname, ".sbss") != 0 4835 && !startswith (segname, ".sdata.") 4836 && !startswith (segname, ".gnu.linkonce.s.")); 4837 } 4838 /* We are not optimizing for the $gp register. */ 4839 else 4840 return 1; 4841} 4842 4843/* Build a relax frag for lw/st instruction when generating s3_PIC, 4844 external symbol first and local symbol second. */ 4845static void 4846s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) 4847{ 4848 symbolS *add_symbol = exp.X_add_symbol; 4849 int add_number = exp.X_add_number; 4850 struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; 4851 struct s3_score_it var_insts[s3_RELAX_INST_NUM]; 4852 int fix_num = 0; 4853 int var_num = 0; 4854 char tmp[s3_MAX_LITERAL_POOL_SIZE]; 4855 int r1_bak; 4856 4857 r1_bak = s3_nor1; 4858 s3_nor1 = 0; 4859 4860 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) 4861 { 4862 fix_num = 1; 4863 var_num = 2; 4864 4865 /* For an external symbol, two insns are generated; 4866 For a local symbol, three insns are generated. */ 4867 /* Fix part 4868 For an external symbol: lw rD, <sym>($gp) 4869 (BFD_RELOC_SCORE_GOT15) */ 4870 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol)); 4871 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4872 return; 4873 4874 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4875 4876 /* Var part 4877 For a local symbol : 4878 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 4879 addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 4880 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4881 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4882 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol)); 4883 if (s3_append_insn (tmp, false) == (int) s3_FAIL) 4884 return; 4885 4886 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); 4887 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4888 4889 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ 4890 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); 4891 if (s3_append_insn (tmp, true) == (int) s3_FAIL) 4892 return; 4893 4894 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4895 s3_inst.bwarn = -1; 4896 } 4897 else 4898 { 4899 s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)"); 4900 return; 4901 } 4902 4903 s3_nor1 = r1_bak; 4904} 4905 4906static void 4907s3_do_macro_ldst_label (char *str) 4908{ 4909 int i; 4910 int ldst_gp_p = 0; 4911 int reg_rd; 4912 int r1_bak; 4913 char *backup_str; 4914 char *label_str; 4915 char *absolute_value; 4916 char append_str[3][s3_MAX_LITERAL_POOL_SIZE]; 4917 char verifystr[s3_MAX_LITERAL_POOL_SIZE]; 4918 struct s3_score_it inst_backup; 4919 struct s3_score_it inst_expand[3]; 4920 struct s3_score_it inst_main; 4921 4922 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); 4923 strcpy (verifystr, str); 4924 backup_str = verifystr; 4925 4926 s3_skip_whitespace (backup_str); 4927 if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4928 return; 4929 4930 if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL) 4931 return; 4932 4933 label_str = backup_str; 4934 4935 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */ 4936 if (*backup_str == '[') 4937 { 4938 s3_inst.type = Rd_rvalueRs_preSI12; 4939 s3_do_ldst_insn (str); 4940 return; 4941 } 4942 4943 /* Ld/st rD, imm. */ 4944 absolute_value = backup_str; 4945 s3_inst.type = Rd_rvalueRs_SI15; 4946 4947 if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL) 4948 { 4949 s3_inst.error = _("expression error"); 4950 return; 4951 } 4952 else if ((s3_inst.reloc.exp.X_add_symbol == NULL) 4953 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL)) 4954 { 4955 s3_inst.error = _("value not in range [0, 0x7fffffff]"); 4956 return; 4957 } 4958 else if (s3_end_of_line (backup_str) == (int) s3_FAIL) 4959 { 4960 s3_inst.error = _("end on line error"); 4961 return; 4962 } 4963 else 4964 { 4965 if (s3_inst.reloc.exp.X_add_symbol == 0) 4966 { 4967 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); 4968 s3_exp_macro_ldst_abs (str); 4969 return; 4970 } 4971 } 4972 4973 /* Ld/st rD, label. */ 4974 s3_inst.type = Rd_rvalueRs_SI15; 4975 backup_str = absolute_value; 4976 if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL) 4977 || (s3_end_of_line (backup_str) == (int) s3_FAIL)) 4978 { 4979 return; 4980 } 4981 else 4982 { 4983 if (s3_inst.reloc.exp.X_add_symbol == 0) 4984 { 4985 if (!s3_inst.error) 4986 s3_inst.error = s3_BAD_ARGS; 4987 4988 return; 4989 } 4990 4991 if (s3_score_pic == s3_PIC) 4992 { 4993 int ldst_idx = 0; 4994 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 4995 s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp, 4996 s3_score_ldst_insns[ldst_idx * 3 + 0].template_name); 4997 return; 4998 } 4999 else 5000 { 5001 if ((s3_inst.reloc.exp.X_add_number <= 0x3fff) 5002 && (s3_inst.reloc.exp.X_add_number >= -0x4000) 5003 && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1))) 5004 { 5005 int ldst_idx = 0; 5006 5007 /* Assign the real opcode. */ 5008 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 5009 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 5010 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value; 5011 s3_inst.instruction |= reg_rd << 20; 5012 s3_inst.instruction |= s3_GP << 15; 5013 s3_inst.relax_inst = 0x8000; 5014 s3_inst.relax_size = 0; 5015 ldst_gp_p = 1; 5016 } 5017 } 5018 } 5019 5020 /* Backup s3_inst. */ 5021 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 5022 r1_bak = s3_nor1; 5023 s3_nor1 = 0; 5024 5025 /* Determine which instructions should be output. */ 5026 sprintf (append_str[0], "ld_i32hi r1, %s", label_str); 5027 sprintf (append_str[1], "ld_i32lo r1, %s", label_str); 5028 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd); 5029 5030 /* Generate three instructions. 5031 la r1, label 5032 ld/st rd, [r1, 0] */ 5033 for (i = 0; i < 3; i++) 5034 { 5035 if (s3_append_insn (append_str[i], false) == (int) s3_FAIL) 5036 return; 5037 5038 memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it)); 5039 } 5040 5041 if (ldst_gp_p) 5042 { 5043 char *p; 5044 5045 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 5046 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 5047 5048 /* relax lw rd, label -> ldis rs, imm16 5049 ori rd, imm16 5050 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ 5051 if (inst_expand[2].relax_size == 0) 5052 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; 5053 else 5054 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size; 5055 5056 inst_main.type = Insn_GP; 5057 5058 for (i = 0; i < 3; i++) 5059 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, 5060 s3_GET_INSN_CLASS (inst_expand[i].type)); 5061 5062 /* Check data dependency. */ 5063 s3_handle_dependency (&inst_main); 5064 5065 /* Start a new frag if frag_now is not empty. */ 5066 if (frag_now_fix () != 0) 5067 { 5068 if (!frag_now->tc_frag_data.is_insn) 5069 frag_wane (frag_now); 5070 5071 frag_new (0); 5072 } 5073 frag_grow (20); 5074 5075 /* Write fr_fix part. */ 5076 p = frag_more (inst_main.size); 5077 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 5078 5079 if (inst_main.reloc.type != BFD_RELOC_NONE) 5080 { 5081 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 5082 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 5083 } 5084 5085#ifdef OBJ_ELF 5086 dwarf2_emit_insn (inst_main.size); 5087#endif 5088 5089 /* s3_GP instruction can not do optimization, only can do relax between 5090 1 instruction and 3 instructions. */ 5091 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 5092 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), 5093 inst_main.reloc.exp.X_add_symbol, 0, NULL); 5094 5095 /* Write fr_var part. 5096 no calling s3_gen_insn_frag, no fixS will be generated. */ 5097 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 5098 p += inst_expand[0].size; 5099 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 5100 p += inst_expand[1].size; 5101 5102 /* relax lw rd, label -> ldis rs, imm16 5103 ori rd, imm16 5104 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ 5105 if (inst_expand[2].relax_size == 0) 5106 s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); 5107 else 5108 s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size); 5109 } 5110 else 5111 { 5112 s3_gen_insn_frag (&inst_expand[0], NULL); 5113 s3_gen_insn_frag (&inst_expand[1], NULL); 5114 s3_gen_insn_frag (&inst_expand[2], NULL); 5115 } 5116 s3_nor1 = r1_bak; 5117 5118 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 5119 s3_inst.bwarn = -1; 5120} 5121 5122static void 5123s3_do_lw_pic (char *str) 5124{ 5125 int reg_rd; 5126 5127 s3_skip_whitespace (str); 5128 if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 5129 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 5130 || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 5131 || (s3_end_of_line (str) == (int) s3_FAIL)) 5132 { 5133 return; 5134 } 5135 else 5136 { 5137 if (s3_inst.reloc.exp.X_add_symbol == 0) 5138 { 5139 if (!s3_inst.error) 5140 s3_inst.error = s3_BAD_ARGS; 5141 5142 return; 5143 } 5144 5145 s3_inst.instruction |= s3_GP << 15; 5146 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 5147 } 5148} 5149 5150static void 5151s3_do_empty (char *str) 5152{ 5153 str = str; 5154 if (s3_university_version == 1) 5155 { 5156 if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004) 5157 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024) 5158 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044) 5159 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064)) 5160 { 5161 s3_inst.error = s3_ERR_FOR_SCORE5U_MMU; 5162 return; 5163 } 5164 } 5165 if (s3_end_of_line (str) == (int) s3_FAIL) 5166 return; 5167 5168 if (s3_inst.relax_inst != 0x8000) 5169 { 5170 if (s3_inst.type == NO_OPD) 5171 { 5172 s3_inst.relax_size = 2; 5173 } 5174 else 5175 { 5176 s3_inst.relax_size = 4; 5177 } 5178 } 5179} 5180 5181static void 5182s3_do16_int (char *str) 5183{ 5184 s3_skip_whitespace (str); 5185 return; 5186} 5187 5188static void 5189s3_do_jump (char *str) 5190{ 5191 char *save_in; 5192 5193 s3_skip_whitespace (str); 5194 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5195 || s3_end_of_line (str) == (int) s3_FAIL) 5196 return; 5197 5198 if (s3_inst.reloc.exp.X_add_symbol == 0) 5199 { 5200 s3_inst.error = _("lacking label "); 5201 return; 5202 } 5203 5204 if (!(s3_inst.reloc.exp.X_add_number >= -16777216 5205 && s3_inst.reloc.exp.X_add_number <= 16777215)) 5206 { 5207 s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]"); 5208 return; 5209 } 5210 5211 save_in = input_line_pointer; 5212 input_line_pointer = str; 5213 s3_inst.reloc.type = BFD_RELOC_SCORE_JMP; 5214 s3_inst.reloc.pc_rel = 1; 5215 input_line_pointer = save_in; 5216} 5217 5218static void 5219s3_do_branch (char *str) 5220{ 5221 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5222 || s3_end_of_line (str) == (int) s3_FAIL) 5223 { 5224 return; 5225 } 5226 else if (s3_inst.reloc.exp.X_add_symbol == 0) 5227 { 5228 s3_inst.error = _("lacking label "); 5229 return; 5230 } 5231 else if (!(s3_inst.reloc.exp.X_add_number >= -524288 5232 && s3_inst.reloc.exp.X_add_number <= 524287)) 5233 { 5234 s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19-1"); 5235 return; 5236 } 5237 5238 s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH; 5239 s3_inst.reloc.pc_rel = 1; 5240 5241 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 5242 s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5); 5243 5244 /* Compute 16 bit branch instruction. */ 5245 if ((s3_inst.relax_inst != 0x8000) 5246 && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511)) 5247 { 5248 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */ 5249 s3_inst.relax_size = 2; 5250 } 5251 else 5252 { 5253 s3_inst.relax_inst = 0x8000; 5254 } 5255} 5256 5257static void 5258s3_do16_branch (char *str) 5259{ 5260 if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5261 || s3_end_of_line (str) == (int) s3_FAIL)) 5262 { 5263 ; 5264 } 5265 else if (s3_inst.reloc.exp.X_add_symbol == 0) 5266 { 5267 s3_inst.error = _("lacking label"); 5268 } 5269 else if (!(s3_inst.reloc.exp.X_add_number >= -512 5270 && s3_inst.reloc.exp.X_add_number <= 511)) 5271 { 5272 s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]"); 5273 } 5274 else 5275 { 5276 s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; 5277 s3_inst.reloc.pc_rel = 1; 5278 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff); 5279 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff); 5280 s3_inst.relax_size = 4; 5281 } 5282} 5283 5284/* Return true if the given symbol should be considered local for s3_PIC. */ 5285static bool 5286s3_pic_need_relax (symbolS *sym, asection *segtype) 5287{ 5288 asection *symsec; 5289 bool linkonce; 5290 5291 /* Handle the case of a symbol equated to another symbol. */ 5292 while (symbol_equated_reloc_p (sym)) 5293 { 5294 symbolS *n; 5295 5296 /* It's possible to get a loop here in a badly written 5297 program. */ 5298 n = symbol_get_value_expression (sym)->X_add_symbol; 5299 if (n == sym) 5300 break; 5301 sym = n; 5302 } 5303 5304 symsec = S_GET_SEGMENT (sym); 5305 5306 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ 5307 linkonce = false; 5308 if (symsec != segtype && ! S_IS_LOCAL (sym)) 5309 { 5310 if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0) 5311 linkonce = true; 5312 5313 /* The GNU toolchain uses an extension for ELF: a section 5314 beginning with the magic string .gnu.linkonce is a linkonce 5315 section. */ 5316 if (startswith (segment_name (symsec), ".gnu.linkonce")) 5317 linkonce = true; 5318 } 5319 5320 /* This must duplicate the test in adjust_reloc_syms. */ 5321 return (!bfd_is_und_section (symsec) 5322 && !bfd_is_abs_section (symsec) 5323 && !bfd_is_com_section (symsec) 5324 && !linkonce 5325#ifdef OBJ_ELF 5326 /* A global or weak symbol is treated as external. */ 5327 && (OUTPUT_FLAVOR != bfd_target_elf_flavour 5328 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) 5329#endif 5330 ); 5331} 5332 5333static void 5334s3_parse_pce_inst (char *insnstr) 5335{ 5336 char c; 5337 char *p; 5338 char first[s3_MAX_LITERAL_POOL_SIZE]; 5339 char second[s3_MAX_LITERAL_POOL_SIZE]; 5340 struct s3_score_it pec_part_1; 5341 5342 /* Get first part string of PCE. */ 5343 p = strstr (insnstr, "||"); 5344 c = *p; 5345 *p = '\0'; 5346 sprintf (first, "%s", insnstr); 5347 5348 /* Get second part string of PCE. */ 5349 *p = c; 5350 p += 2; 5351 sprintf (second, "%s", p); 5352 5353 s3_parse_16_32_inst (first, false); 5354 if (s3_inst.error) 5355 return; 5356 5357 memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst)); 5358 5359 s3_parse_16_32_inst (second, false); 5360 if (s3_inst.error) 5361 return; 5362 5363 if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE)) 5364 || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE)) 5365 || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE))) 5366 { 5367 s3_inst.error = _("pce instruction error (16 bit || 16 bit)."); 5368 sprintf (s3_inst.str, "%s", insnstr); 5369 return; 5370 } 5371 5372 if (!s3_inst.error) 5373 s3_gen_insn_frag (&pec_part_1, &s3_inst); 5374} 5375 5376/* s3: dsp. */ 5377static void 5378s3_do16_dsp (char *str) 5379{ 5380 int rd = 0; 5381 5382 /* Check 3d. */ 5383 if (s3_score3d == 0) 5384 { 5385 s3_inst.error = _("score3d instruction."); 5386 return; 5387 } 5388 5389 s3_skip_whitespace (str); 5390 5391 if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL 5392 || s3_end_of_line (str) == (int) s3_FAIL) 5393 { 5394 return; 5395 } 5396 else 5397 { 5398 s3_inst.relax_inst |= rd << 20; 5399 s3_inst.relax_size = 4; 5400 } 5401} 5402 5403static void 5404s3_do16_dsp2 (char *str) 5405{ 5406 /* Check 3d. */ 5407 if (s3_score3d == 0) 5408 { 5409 s3_inst.error = _("score3d instruction."); 5410 return; 5411 } 5412 5413 s3_skip_whitespace (str); 5414 5415 if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL 5416 || s3_skip_past_comma (&str) == (int) s3_FAIL 5417 || s3_reglow_required_here (&str, 0) == (int) s3_FAIL 5418 || s3_end_of_line (str) == (int) s3_FAIL) 5419 { 5420 return; 5421 } 5422 else 5423 { 5424 s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20) 5425 | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10); 5426 s3_inst.relax_size = 4; 5427 } 5428} 5429 5430static void 5431s3_do_dsp (char *str) 5432{ 5433 /* Check 3d. */ 5434 if (s3_score3d == 0) 5435 { 5436 s3_inst.error = _("score3d instruction."); 5437 return; 5438 } 5439 5440 s3_skip_whitespace (str); 5441 5442 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5443 || s3_skip_past_comma (&str) == (int) s3_FAIL 5444 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5445 || s3_end_of_line (str) == (int) s3_FAIL) 5446 return; 5447 5448 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) 5449 { 5450 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); 5451 s3_inst.relax_size = 2; 5452 } 5453 else 5454 s3_inst.relax_inst = 0x8000; 5455} 5456 5457static void 5458s3_do_dsp2 (char *str) 5459{ 5460 int reg; 5461 5462 /* Check 3d. */ 5463 if (s3_score3d == 0) 5464 { 5465 s3_inst.error = _("score3d instruction."); 5466 return; 5467 } 5468 5469 s3_skip_whitespace (str); 5470 5471 if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 5472 || s3_skip_past_comma (&str) == (int) s3_FAIL 5473 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5474 || s3_skip_past_comma (&str) == (int) s3_FAIL 5475 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5476 || s3_end_of_line (str) == (int) s3_FAIL) 5477 { 5478 return; 5479 } 5480 else 5481 { 5482 /* Check mulr, mulur rd is even number. */ 5483 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340 5484 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342) 5485 && (reg % 2)) 5486 { 5487 s3_inst.error = _("rd must be even number."); 5488 return; 5489 } 5490 5491 if ((((s3_inst.instruction >> 15) & 0x10) == 0) 5492 && (((s3_inst.instruction >> 10) & 0x10) == 0) 5493 && (((s3_inst.instruction >> 20) & 0x10) == 0) 5494 && (s3_inst.relax_inst != 0x8000) 5495 && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf))) 5496 { 5497 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) ) 5498 | (((s3_inst.instruction >> 15) & 0xf) << 4); 5499 s3_inst.relax_size = 2; 5500 } 5501 else 5502 { 5503 s3_inst.relax_inst = 0x8000; 5504 } 5505 } 5506} 5507 5508static void 5509s3_do_dsp3 (char *str) 5510{ 5511 /* Check 3d. */ 5512 if (s3_score3d == 0) 5513 { 5514 s3_inst.error = _("score3d instruction."); 5515 return; 5516 } 5517 5518 s3_skip_whitespace (str); 5519 5520 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5521 || s3_skip_past_comma (&str) == (int) s3_FAIL 5522 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5523 || s3_end_of_line (str) == (int) s3_FAIL) 5524 return; 5525 5526 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) 5527 { 5528 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); 5529 s3_inst.relax_size = 2; 5530 } 5531 else 5532 s3_inst.relax_inst = 0x8000; 5533} 5534 5535 5536/* If we change section we must dump the literal pool first. */ 5537static void 5538s3_s_score_bss (int ignore ATTRIBUTE_UNUSED) 5539{ 5540 subseg_set (bss_section, (subsegT) get_absolute_expression ()); 5541 demand_empty_rest_of_line (); 5542} 5543 5544static void 5545s3_s_score_text (int ignore) 5546{ 5547 obj_elf_text (ignore); 5548 record_alignment (now_seg, 2); 5549} 5550 5551static void 5552s3_score_s_section (int ignore) 5553{ 5554 obj_elf_section (ignore); 5555 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5556 record_alignment (now_seg, 2); 5557 5558} 5559 5560static void 5561s3_s_change_sec (int sec) 5562{ 5563 segT seg; 5564 5565#ifdef OBJ_ELF 5566 /* The ELF backend needs to know that we are changing sections, so 5567 that .previous works correctly. We could do something like check 5568 for an obj_section_change_hook macro, but that might be confusing 5569 as it would not be appropriate to use it in the section changing 5570 functions in read.c, since obj-elf.c intercepts those. FIXME: 5571 This should be cleaner, somehow. */ 5572 obj_elf_section_change_hook (); 5573#endif 5574 switch (sec) 5575 { 5576 case 'r': 5577 seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); 5578 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY 5579 | SEC_RELOC | SEC_DATA)); 5580 if (strcmp (TARGET_OS, "elf") != 0) 5581 record_alignment (seg, 4); 5582 demand_empty_rest_of_line (); 5583 break; 5584 case 's': 5585 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); 5586 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_RELOC 5587 | SEC_DATA | SEC_SMALL_DATA)); 5588 if (strcmp (TARGET_OS, "elf") != 0) 5589 record_alignment (seg, 4); 5590 demand_empty_rest_of_line (); 5591 break; 5592 } 5593} 5594 5595static void 5596s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED) 5597{ 5598 long mask, off; 5599 5600 if (s3_cur_proc_ptr == (s3_procS *) NULL) 5601 { 5602 as_warn (_(".mask outside of .ent")); 5603 demand_empty_rest_of_line (); 5604 return; 5605 } 5606 if (get_absolute_expression_and_terminator (&mask) != ',') 5607 { 5608 as_warn (_("Bad .mask directive")); 5609 --input_line_pointer; 5610 demand_empty_rest_of_line (); 5611 return; 5612 } 5613 off = get_absolute_expression (); 5614 s3_cur_proc_ptr->reg_mask = mask; 5615 s3_cur_proc_ptr->reg_offset = off; 5616 demand_empty_rest_of_line (); 5617} 5618 5619static symbolS * 5620s3_get_symbol (void) 5621{ 5622 int c; 5623 char *name; 5624 symbolS *p; 5625 5626 c = get_symbol_name (&name); 5627 p = (symbolS *) symbol_find_or_make (name); 5628 (void) restore_line_pointer (c); 5629 return p; 5630} 5631 5632static long 5633s3_get_number (void) 5634{ 5635 int negative = 0; 5636 long val = 0; 5637 5638 if (*input_line_pointer == '-') 5639 { 5640 ++input_line_pointer; 5641 negative = 1; 5642 } 5643 if (!ISDIGIT (*input_line_pointer)) 5644 as_bad (_("expected simple number")); 5645 if (input_line_pointer[0] == '0') 5646 { 5647 if (input_line_pointer[1] == 'x') 5648 { 5649 input_line_pointer += 2; 5650 while (ISXDIGIT (*input_line_pointer)) 5651 { 5652 val <<= 4; 5653 val |= hex_value (*input_line_pointer++); 5654 } 5655 return negative ? -val : val; 5656 } 5657 else 5658 { 5659 ++input_line_pointer; 5660 while (ISDIGIT (*input_line_pointer)) 5661 { 5662 val <<= 3; 5663 val |= *input_line_pointer++ - '0'; 5664 } 5665 return negative ? -val : val; 5666 } 5667 } 5668 if (!ISDIGIT (*input_line_pointer)) 5669 { 5670 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); 5671 as_warn (_("invalid number")); 5672 return -1; 5673 } 5674 while (ISDIGIT (*input_line_pointer)) 5675 { 5676 val *= 10; 5677 val += *input_line_pointer++ - '0'; 5678 } 5679 return negative ? -val : val; 5680} 5681 5682/* The .aent and .ent directives. */ 5683static void 5684s3_s_score_ent (int aent) 5685{ 5686 symbolS *symbolP; 5687 int maybe_text; 5688 5689 symbolP = s3_get_symbol (); 5690 if (*input_line_pointer == ',') 5691 ++input_line_pointer; 5692 SKIP_WHITESPACE (); 5693 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') 5694 s3_get_number (); 5695 5696 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5697 maybe_text = 1; 5698 else 5699 maybe_text = 0; 5700 if (!maybe_text) 5701 as_warn (_(".ent or .aent not in text section.")); 5702 if (!aent && s3_cur_proc_ptr) 5703 as_warn (_("missing .end")); 5704 if (!aent) 5705 { 5706 s3_cur_proc_ptr = &s3_cur_proc; 5707 s3_cur_proc_ptr->reg_mask = 0xdeadbeaf; 5708 s3_cur_proc_ptr->reg_offset = 0xdeadbeaf; 5709 s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf; 5710 s3_cur_proc_ptr->leaf = 0xdeafbeaf; 5711 s3_cur_proc_ptr->frame_offset = 0xdeafbeaf; 5712 s3_cur_proc_ptr->frame_reg = 0xdeafbeaf; 5713 s3_cur_proc_ptr->pc_reg = 0xdeafbeaf; 5714 s3_cur_proc_ptr->isym = symbolP; 5715 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; 5716 ++s3_numprocs; 5717 if (debug_type == DEBUG_STABS) 5718 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); 5719 } 5720 demand_empty_rest_of_line (); 5721} 5722 5723static void 5724s3_s_score_frame (int ignore ATTRIBUTE_UNUSED) 5725{ 5726 char *backupstr; 5727 char str[30]; 5728 long val; 5729 int i = 0; 5730 5731 backupstr = input_line_pointer; 5732 5733#ifdef OBJ_ELF 5734 if (s3_cur_proc_ptr == (s3_procS *) NULL) 5735 { 5736 as_warn (_(".frame outside of .ent")); 5737 demand_empty_rest_of_line (); 5738 return; 5739 } 5740 s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); 5741 SKIP_WHITESPACE (); 5742 s3_skip_past_comma (&backupstr); 5743 while (*backupstr != ',') 5744 { 5745 str[i] = *backupstr; 5746 i++; 5747 backupstr++; 5748 } 5749 str[i] = '\0'; 5750 val = atoi (str); 5751 5752 SKIP_WHITESPACE (); 5753 s3_skip_past_comma (&backupstr); 5754 s3_cur_proc_ptr->frame_offset = val; 5755 s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); 5756 5757 SKIP_WHITESPACE (); 5758 s3_skip_past_comma (&backupstr); 5759 i = 0; 5760 while (*backupstr != '\n') 5761 { 5762 str[i] = *backupstr; 5763 i++; 5764 backupstr++; 5765 } 5766 str[i] = '\0'; 5767 val = atoi (str); 5768 s3_cur_proc_ptr->leaf = val; 5769 SKIP_WHITESPACE (); 5770 s3_skip_past_comma (&backupstr); 5771 5772#endif /* OBJ_ELF */ 5773 while (input_line_pointer != backupstr) 5774 input_line_pointer++; 5775} 5776 5777/* The .end directive. */ 5778static void 5779s3_s_score_end (int x ATTRIBUTE_UNUSED) 5780{ 5781 symbolS *p; 5782 int maybe_text; 5783 5784 /* Generate a .pdr section. */ 5785 segT saved_seg = now_seg; 5786 subsegT saved_subseg = now_subseg; 5787 expressionS exp; 5788 char *fragp; 5789 5790 if (!is_end_of_line[(unsigned char)*input_line_pointer]) 5791 { 5792 p = s3_get_symbol (); 5793 demand_empty_rest_of_line (); 5794 } 5795 else 5796 p = NULL; 5797 5798 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5799 maybe_text = 1; 5800 else 5801 maybe_text = 0; 5802 5803 if (!maybe_text) 5804 as_warn (_(".end not in text section")); 5805 if (!s3_cur_proc_ptr) 5806 { 5807 as_warn (_(".end directive without a preceding .ent directive.")); 5808 demand_empty_rest_of_line (); 5809 return; 5810 } 5811 if (p != NULL) 5812 { 5813 gas_assert (S_GET_NAME (p)); 5814 if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym))) 5815 as_warn (_(".end symbol does not match .ent symbol.")); 5816 if (debug_type == DEBUG_STABS) 5817 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); 5818 } 5819 else 5820 as_warn (_(".end directive missing or unknown symbol")); 5821 5822 if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) || 5823 (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) || 5824 (s3_cur_proc_ptr->leaf == 0xdeafbeaf) || 5825 (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) || 5826 (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf)); 5827 5828 else 5829 { 5830 (void) frag_now_fix (); 5831 gas_assert (s3_pdr_seg); 5832 subseg_set (s3_pdr_seg, 0); 5833 /* Write the symbol. */ 5834 exp.X_op = O_symbol; 5835 exp.X_add_symbol = p; 5836 exp.X_add_number = 0; 5837 emit_expr (&exp, 4); 5838 fragp = frag_more (7 * 4); 5839 md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4); 5840 md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4); 5841 md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4); 5842 md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4); 5843 md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4); 5844 md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4); 5845 md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4); 5846 subseg_set (saved_seg, saved_subseg); 5847 5848 } 5849 s3_cur_proc_ptr = NULL; 5850} 5851 5852/* Handle the .set pseudo-op. */ 5853static void 5854s3_s_score_set (int x ATTRIBUTE_UNUSED) 5855{ 5856 int i = 0; 5857 char name[s3_MAX_LITERAL_POOL_SIZE]; 5858 char * orig_ilp = input_line_pointer; 5859 5860 while (!is_end_of_line[(unsigned char)*input_line_pointer]) 5861 { 5862 name[i] = (char) * input_line_pointer; 5863 i++; 5864 ++input_line_pointer; 5865 } 5866 5867 name[i] = '\0'; 5868 5869 if (strcmp (name, "nwarn") == 0) 5870 { 5871 s3_warn_fix_data_dependency = 0; 5872 } 5873 else if (strcmp (name, "fixdd") == 0) 5874 { 5875 s3_fix_data_dependency = 1; 5876 } 5877 else if (strcmp (name, "nofixdd") == 0) 5878 { 5879 s3_fix_data_dependency = 0; 5880 } 5881 else if (strcmp (name, "r1") == 0) 5882 { 5883 s3_nor1 = 0; 5884 } 5885 else if (strcmp (name, "nor1") == 0) 5886 { 5887 s3_nor1 = 1; 5888 } 5889 else if (strcmp (name, "optimize") == 0) 5890 { 5891 s3_g_opt = 1; 5892 } 5893 else if (strcmp (name, "volatile") == 0) 5894 { 5895 s3_g_opt = 0; 5896 } 5897 else if (strcmp (name, "pic") == 0) 5898 { 5899 s3_score_pic = s3_PIC; 5900 } 5901 else 5902 { 5903 input_line_pointer = orig_ilp; 5904 s_set (0); 5905 } 5906} 5907 5908/* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the 5909 $gp register for the function based on the function address, which is in the register 5910 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled 5911 specially by the linker. The result is: 5912 ldis gp, %hi(GP_DISP_LABEL) 5913 ori gp, %low(GP_DISP_LABEL) 5914 add gp, gp, .cpload argument 5915 The .cpload argument is normally r29. */ 5916static void 5917s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED) 5918{ 5919 int reg; 5920 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 5921 5922 /* If we are not generating s3_PIC code, .cpload is ignored. */ 5923 if (s3_score_pic == s3_NO_PIC) 5924 { 5925 s_ignore (0); 5926 return; 5927 } 5928 5929 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 5930 return; 5931 5932 demand_empty_rest_of_line (); 5933 5934 sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL); 5935 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5936 return; 5937 5938 sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL); 5939 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5940 return; 5941 5942 sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg); 5943 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5944 return; 5945} 5946 5947/* Handle the .cprestore pseudo-op. This stores $gp into a given 5948 offset from $sp. The offset is remembered, and after making a s3_PIC 5949 call $gp is restored from that location. */ 5950static void 5951s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED) 5952{ 5953 int reg; 5954 int cprestore_offset; 5955 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 5956 5957 /* If we are not generating s3_PIC code, .cprestore is ignored. */ 5958 if (s3_score_pic == s3_NO_PIC) 5959 { 5960 s_ignore (0); 5961 return; 5962 } 5963 5964 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 5965 || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL) 5966 { 5967 return; 5968 } 5969 5970 cprestore_offset = get_absolute_expression (); 5971 5972 if (cprestore_offset <= 0x3fff) 5973 { 5974 sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset); 5975 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5976 return; 5977 } 5978 else 5979 { 5980 int r1_bak; 5981 5982 r1_bak = s3_nor1; 5983 s3_nor1 = 0; 5984 5985 sprintf (insn_str, "li r1, %d", cprestore_offset); 5986 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5987 return; 5988 5989 sprintf (insn_str, "add r1, r1, r%d", reg); 5990 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5991 return; 5992 5993 sprintf (insn_str, "sw r%d, [r1]", s3_GP); 5994 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 5995 return; 5996 5997 s3_nor1 = r1_bak; 5998 } 5999 6000 demand_empty_rest_of_line (); 6001} 6002 6003/* Handle the .gpword pseudo-op. This is used when generating s3_PIC 6004 code. It generates a 32 bit s3_GP relative reloc. */ 6005static void 6006s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED) 6007{ 6008 expressionS ex; 6009 char *p; 6010 6011 /* When not generating s3_PIC code, this is treated as .word. */ 6012 if (s3_score_pic == s3_NO_PIC) 6013 { 6014 cons (4); 6015 return; 6016 } 6017 expression (&ex); 6018 if (ex.X_op != O_symbol || ex.X_add_number != 0) 6019 { 6020 as_bad (_("Unsupported use of .gpword")); 6021 ignore_rest_of_line (); 6022 } 6023 p = frag_more (4); 6024 s3_md_number_to_chars (p, (valueT) 0, 4); 6025 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, false, BFD_RELOC_GPREL32); 6026 demand_empty_rest_of_line (); 6027} 6028 6029/* Handle the .cpadd pseudo-op. This is used when dealing with switch 6030 tables in s3_PIC code. */ 6031static void 6032s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED) 6033{ 6034 int reg; 6035 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 6036 6037 /* If we are not generating s3_PIC code, .cpload is ignored. */ 6038 if (s3_score_pic == s3_NO_PIC) 6039 { 6040 s_ignore (0); 6041 return; 6042 } 6043 6044 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 6045 { 6046 return; 6047 } 6048 demand_empty_rest_of_line (); 6049 6050 /* Add $gp to the register named as an argument. */ 6051 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP); 6052 if (s3_append_insn (insn_str, true) == (int) s3_FAIL) 6053 return; 6054} 6055 6056#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 6057#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 6058 do \ 6059 { \ 6060 if ((SIZE) >= 8) \ 6061 (P2VAR) = 3; \ 6062 else if ((SIZE) >= 4) \ 6063 (P2VAR) = 2; \ 6064 else if ((SIZE) >= 2) \ 6065 (P2VAR) = 1; \ 6066 else \ 6067 (P2VAR) = 0; \ 6068 } \ 6069 while (0) 6070#endif 6071 6072static void 6073s3_s_score_lcomm (int bytes_p) 6074{ 6075 char *name; 6076 char c; 6077 char *p; 6078 int temp; 6079 symbolS *symbolP; 6080 segT current_seg = now_seg; 6081 subsegT current_subseg = now_subseg; 6082 const int max_alignment = 15; 6083 int align = 0; 6084 segT bss_seg = bss_section; 6085 int needs_align = 0; 6086 6087 c = get_symbol_name (&name); 6088 p = input_line_pointer; 6089 (void) restore_line_pointer (c); 6090 6091 if (name == p) 6092 { 6093 as_bad (_("expected symbol name")); 6094 discard_rest_of_line (); 6095 return; 6096 } 6097 6098 SKIP_WHITESPACE (); 6099 6100 /* Accept an optional comma after the name. The comma used to be 6101 required, but Irix 5 cc does not generate it. */ 6102 if (*input_line_pointer == ',') 6103 { 6104 ++input_line_pointer; 6105 SKIP_WHITESPACE (); 6106 } 6107 6108 if (is_end_of_line[(unsigned char)*input_line_pointer]) 6109 { 6110 as_bad (_("missing size expression")); 6111 return; 6112 } 6113 6114 if ((temp = get_absolute_expression ()) < 0) 6115 { 6116 as_warn (_("BSS length (%d) < 0 ignored"), temp); 6117 ignore_rest_of_line (); 6118 return; 6119 } 6120 6121#if defined (TC_SCORE) 6122 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) 6123 { 6124 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ 6125 if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) 6126 { 6127 bss_seg = subseg_new (".sbss", 1); 6128 seg_info (bss_seg)->bss = 1; 6129 if (!bfd_set_section_flags (bss_seg, SEC_ALLOC | SEC_SMALL_DATA)) 6130 as_warn (_("error setting flags for \".sbss\": %s"), 6131 bfd_errmsg (bfd_get_error ())); 6132 } 6133 } 6134#endif 6135 6136 SKIP_WHITESPACE (); 6137 if (*input_line_pointer == ',') 6138 { 6139 ++input_line_pointer; 6140 SKIP_WHITESPACE (); 6141 6142 if (is_end_of_line[(unsigned char)*input_line_pointer]) 6143 { 6144 as_bad (_("missing alignment")); 6145 return; 6146 } 6147 else 6148 { 6149 align = get_absolute_expression (); 6150 needs_align = 1; 6151 } 6152 } 6153 6154 if (!needs_align) 6155 { 6156 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); 6157 6158 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ 6159 if (align) 6160 record_alignment (bss_seg, align); 6161 } 6162 6163 if (needs_align) 6164 { 6165 if (bytes_p) 6166 { 6167 /* Convert to a power of 2. */ 6168 if (align != 0) 6169 { 6170 unsigned int i; 6171 6172 for (i = 0; align != 0; align >>= 1, ++i) 6173 ; 6174 align = i - 1; 6175 } 6176 } 6177 6178 if (align > max_alignment) 6179 { 6180 align = max_alignment; 6181 as_warn (_("alignment too large; %d assumed"), align); 6182 } 6183 else if (align < 0) 6184 { 6185 align = 0; 6186 as_warn (_("alignment negative; 0 assumed")); 6187 } 6188 6189 record_alignment (bss_seg, align); 6190 } 6191 else 6192 { 6193 /* Assume some objects may require alignment on some systems. */ 6194#if defined (TC_ALPHA) && ! defined (VMS) 6195 if (temp > 1) 6196 { 6197 align = ffs (temp) - 1; 6198 if (temp % (1 << align)) 6199 abort (); 6200 } 6201#endif 6202 } 6203 6204 *p = 0; 6205 symbolP = symbol_find_or_make (name); 6206 *p = c; 6207 6208 if ( 6209#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 6210 (OUTPUT_FLAVOR != bfd_target_aout_flavour 6211 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && 6212#endif 6213 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) 6214 { 6215 char *pfrag; 6216 6217 subseg_set (bss_seg, 1); 6218 6219 if (align) 6220 frag_align (align, 0, 0); 6221 6222 /* Detach from old frag. */ 6223 if (S_GET_SEGMENT (symbolP) == bss_seg) 6224 symbol_get_frag (symbolP)->fr_symbol = NULL; 6225 6226 symbol_set_frag (symbolP, frag_now); 6227 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); 6228 *pfrag = 0; 6229 6230 6231 S_SET_SEGMENT (symbolP, bss_seg); 6232 6233#ifdef OBJ_COFF 6234 /* The symbol may already have been created with a preceding 6235 ".globl" directive -- be careful not to step on storage class 6236 in that case. Otherwise, set it to static. */ 6237 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 6238 { 6239 S_SET_STORAGE_CLASS (symbolP, C_STAT); 6240 } 6241#endif /* OBJ_COFF */ 6242 6243#ifdef S_SET_SIZE 6244 S_SET_SIZE (symbolP, temp); 6245#endif 6246 } 6247 else 6248 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 6249 6250 subseg_set (current_seg, current_subseg); 6251 6252 demand_empty_rest_of_line (); 6253} 6254 6255static void 6256s3_insert_reg (const struct s3_reg_entry *r, htab_t htab) 6257{ 6258 int i = 0; 6259 int len = strlen (r->name) + 2; 6260 char *buf = XNEWVEC (char, len); 6261 char *buf2 = XNEWVEC (char, len); 6262 6263 strcpy (buf + i, r->name); 6264 for (i = 0; buf[i]; i++) 6265 { 6266 buf2[i] = TOUPPER (buf[i]); 6267 } 6268 buf2[i] = '\0'; 6269 6270 str_hash_insert (htab, buf, r, 0); 6271 str_hash_insert (htab, buf2, r, 0); 6272} 6273 6274static void 6275s3_build_reg_hsh (struct s3_reg_map *map) 6276{ 6277 const struct s3_reg_entry *r; 6278 6279 map->htab = str_htab_create (); 6280 for (r = map->names; r->name != NULL; r++) 6281 s3_insert_reg (r, map->htab); 6282} 6283 6284/* Iterate over the base tables to create the instruction patterns. */ 6285static void 6286s3_build_score_ops_hsh (void) 6287{ 6288 unsigned int i; 6289 static struct obstack insn_obstack; 6290 6291 obstack_begin (&insn_obstack, 4000); 6292 for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++) 6293 { 6294 const struct s3_asm_opcode *insn = s3_score_insns + i; 6295 size_t len = strlen (insn->template_name); 6296 struct s3_asm_opcode *new_opcode; 6297 char *template_name; 6298 new_opcode = (struct s3_asm_opcode *) 6299 obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode)); 6300 template_name = (char *) obstack_alloc (& insn_obstack, len + 1); 6301 6302 strcpy (template_name, insn->template_name); 6303 new_opcode->template_name = template_name; 6304 new_opcode->parms = insn->parms; 6305 new_opcode->value = insn->value; 6306 new_opcode->relax_value = insn->relax_value; 6307 new_opcode->type = insn->type; 6308 new_opcode->bitmask = insn->bitmask; 6309 str_hash_insert (s3_score_ops_hsh, new_opcode->template_name, 6310 new_opcode, 0); 6311 } 6312} 6313 6314static void 6315s3_build_dependency_insn_hsh (void) 6316{ 6317 unsigned int i; 6318 static struct obstack dependency_obstack; 6319 6320 obstack_begin (&dependency_obstack, 4000); 6321 for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++) 6322 { 6323 const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i; 6324 size_t len = strlen (tmp->insn_name); 6325 struct s3_insn_to_dependency *new_i2n; 6326 char *buf; 6327 6328 new_i2n = (struct s3_insn_to_dependency *) 6329 obstack_alloc (&dependency_obstack, 6330 sizeof (struct s3_insn_to_dependency)); 6331 buf = (char *) obstack_alloc (&dependency_obstack, len + 1); 6332 6333 strcpy (buf, tmp->insn_name); 6334 new_i2n->insn_name = buf; 6335 new_i2n->type = tmp->type; 6336 str_hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name, new_i2n, 0); 6337 } 6338} 6339 6340static void 6341s_score_bss (int ignore ATTRIBUTE_UNUSED) 6342{ 6343 if (score3) 6344 return s3_s_score_bss (ignore); 6345 else 6346 return s7_s_score_bss (ignore); 6347} 6348 6349static void 6350s_score_text (int ignore) 6351{ 6352 if (score3) 6353 return s3_s_score_text (ignore); 6354 else 6355 return s7_s_score_text (ignore); 6356} 6357 6358static void 6359s_section (int ignore) 6360{ 6361 if (score3) 6362 return s3_score_s_section (ignore); 6363 else 6364 return s7_s_section (ignore); 6365} 6366 6367static void 6368s_change_sec (int sec) 6369{ 6370 if (score3) 6371 return s3_s_change_sec (sec); 6372 else 6373 return s7_s_change_sec (sec); 6374} 6375 6376static void 6377s_score_mask (int reg_type ATTRIBUTE_UNUSED) 6378{ 6379 if (score3) 6380 return s3_s_score_mask (reg_type); 6381 else 6382 return s7_s_score_mask (reg_type); 6383} 6384 6385static void 6386s_score_ent (int aent) 6387{ 6388 if (score3) 6389 return s3_s_score_ent (aent); 6390 else 6391 return s7_s_score_ent (aent); 6392} 6393 6394static void 6395s_score_frame (int ignore ATTRIBUTE_UNUSED) 6396{ 6397 if (score3) 6398 return s3_s_score_frame (ignore); 6399 else 6400 return s7_s_score_frame (ignore); 6401} 6402 6403static void 6404s_score_end (int x ATTRIBUTE_UNUSED) 6405{ 6406 if (score3) 6407 return s3_s_score_end (x); 6408 else 6409 return s7_s_score_end (x); 6410} 6411 6412static void 6413s_score_set (int x ATTRIBUTE_UNUSED) 6414{ 6415 if (score3) 6416 return s3_s_score_set (x); 6417 else 6418 return s7_s_score_set (x); 6419} 6420 6421static void 6422s_score_cpload (int ignore ATTRIBUTE_UNUSED) 6423{ 6424 if (score3) 6425 return s3_s_score_cpload (ignore); 6426 else 6427 return s7_s_score_cpload (ignore); 6428} 6429 6430static void 6431s_score_cprestore (int ignore ATTRIBUTE_UNUSED) 6432{ 6433 if (score3) 6434 return s3_s_score_cprestore (ignore); 6435 else 6436 return s7_s_score_cprestore (ignore); 6437} 6438 6439static void 6440s_score_gpword (int ignore ATTRIBUTE_UNUSED) 6441{ 6442 if (score3) 6443 return s3_s_score_gpword (ignore); 6444 else 6445 return s7_s_score_gpword (ignore); 6446} 6447 6448static void 6449s_score_cpadd (int ignore ATTRIBUTE_UNUSED) 6450{ 6451 if (score3) 6452 return s3_s_score_cpadd (ignore); 6453 else 6454 return s7_s_score_cpadd (ignore); 6455} 6456 6457static void 6458s_score_lcomm (int bytes_p) 6459{ 6460 if (score3) 6461 return s3_s_score_lcomm (bytes_p); 6462 else 6463 return s7_s_score_lcomm (bytes_p); 6464} 6465 6466static void 6467s3_assemble (char *str) 6468{ 6469 know (str); 6470 know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE); 6471 6472 memset (&s3_inst, '\0', sizeof (s3_inst)); 6473 if (s3_INSN_IS_PCE_P (str)) 6474 s3_parse_pce_inst (str); 6475 else if (s3_INSN_IS_48_P (str)) 6476 s3_parse_48_inst (str, true); 6477 else 6478 s3_parse_16_32_inst (str, true); 6479 6480 if (s3_inst.error) 6481 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); 6482} 6483 6484static void 6485s3_operand (expressionS * exp) 6486{ 6487 if (s3_in_my_get_expression) 6488 { 6489 exp->X_op = O_illegal; 6490 if (s3_inst.error == NULL) 6491 { 6492 s3_inst.error = _("bad expression"); 6493 } 6494 } 6495} 6496 6497static void 6498s3_begin (void) 6499{ 6500 unsigned int i; 6501 segT seg; 6502 subsegT subseg; 6503 6504 s3_score_ops_hsh = str_htab_create (); 6505 6506 s3_build_score_ops_hsh (); 6507 6508 s3_dependency_insn_hsh = str_htab_create (); 6509 6510 s3_build_dependency_insn_hsh (); 6511 6512 for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++) 6513 s3_build_reg_hsh (s3_all_reg_maps + i); 6514 6515 /* Initialize dependency vector. */ 6516 s3_init_dependency_vector (); 6517 6518 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 6519 seg = now_seg; 6520 subseg = now_subseg; 6521 s3_pdr_seg = subseg_new (".pdr", (subsegT) 0); 6522 bfd_set_section_flags (s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); 6523 bfd_set_section_alignment (s3_pdr_seg, 2); 6524 subseg_set (seg, subseg); 6525 6526 if (s3_USE_GLOBAL_POINTER_OPT) 6527 bfd_set_gp_size (stdoutput, s3_g_switch_value); 6528} 6529 6530static void 6531s3_number_to_chars (char *buf, valueT val, int n) 6532{ 6533 if (target_big_endian) 6534 number_to_chars_bigendian (buf, val, n); 6535 else 6536 number_to_chars_littleendian (buf, val, n); 6537} 6538 6539static valueT 6540s3_normal_chars_to_number (char *buf, int n) 6541{ 6542 valueT result = 0; 6543 unsigned char *where = (unsigned char *)buf; 6544 6545 if (target_big_endian) 6546 { 6547 while (n--) 6548 { 6549 result <<= 8; 6550 result |= (*where++ & 255); 6551 } 6552 } 6553 else 6554 { 6555 while (n--) 6556 { 6557 result <<= 8; 6558 result |= (where[n] & 255); 6559 } 6560 } 6561 6562 return result; 6563} 6564 6565static void 6566s3_number_to_chars_littleendian (void *p, valueT data, int n) 6567{ 6568 char *buf = (char *) p; 6569 6570 switch (n) 6571 { 6572 case 4: 6573 md_number_to_chars (buf, data >> 16, 2); 6574 md_number_to_chars (buf + 2, data, 2); 6575 break; 6576 case 6: 6577 md_number_to_chars (buf, data >> 32, 2); 6578 md_number_to_chars (buf + 2, data >> 16, 2); 6579 md_number_to_chars (buf + 4, data, 2); 6580 break; 6581 default: 6582 /* Error routine. */ 6583 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); 6584 break; 6585 } 6586} 6587 6588static valueT 6589s3_chars_to_number_littleendian (const void *p, int n) 6590{ 6591 char *buf = (char *) p; 6592 valueT result = 0; 6593 6594 switch (n) 6595 { 6596 case 4: 6597 result = s3_normal_chars_to_number (buf, 2) << 16; 6598 result |= s3_normal_chars_to_number (buf + 2, 2); 6599 break; 6600 case 6: 6601 result = s3_normal_chars_to_number (buf, 2) << 32; 6602 result |= s3_normal_chars_to_number (buf + 2, 2) << 16; 6603 result |= s3_normal_chars_to_number (buf + 4, 2); 6604 break; 6605 default: 6606 /* Error routine. */ 6607 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); 6608 break; 6609 } 6610 6611 return result; 6612} 6613 6614static void 6615s3_md_number_to_chars (char *buf, valueT val, int n) 6616{ 6617 if (!target_big_endian && n >= 4) 6618 s3_number_to_chars_littleendian (buf, val, n); 6619 else 6620 md_number_to_chars (buf, val, n); 6621} 6622 6623static valueT 6624s3_md_chars_to_number (char *buf, int n) 6625{ 6626 valueT result = 0; 6627 6628 if (!target_big_endian && n >= 4) 6629 result = s3_chars_to_number_littleendian (buf, n); 6630 else 6631 result = s3_normal_chars_to_number (buf, n); 6632 6633 return result; 6634} 6635 6636static const char * 6637s3_atof (int type, char *litP, int *sizeP) 6638{ 6639 int prec; 6640 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 6641 char *t; 6642 int i; 6643 6644 switch (type) 6645 { 6646 case 'f': 6647 case 'F': 6648 case 's': 6649 case 'S': 6650 prec = 2; 6651 break; 6652 case 'd': 6653 case 'D': 6654 case 'r': 6655 case 'R': 6656 prec = 4; 6657 break; 6658 case 'x': 6659 case 'X': 6660 case 'p': 6661 case 'P': 6662 prec = 6; 6663 break; 6664 default: 6665 *sizeP = 0; 6666 return _("bad call to MD_ATOF()"); 6667 } 6668 6669 t = atof_ieee (input_line_pointer, type, words); 6670 if (t) 6671 input_line_pointer = t; 6672 *sizeP = prec * 2; 6673 6674 if (target_big_endian) 6675 { 6676 for (i = 0; i < prec; i++) 6677 { 6678 s3_md_number_to_chars (litP, (valueT) words[i], 2); 6679 litP += 2; 6680 } 6681 } 6682 else 6683 { 6684 for (i = 0; i < prec; i += 2) 6685 { 6686 s3_md_number_to_chars (litP, (valueT) words[i + 1], 2); 6687 s3_md_number_to_chars (litP + 2, (valueT) words[i], 2); 6688 litP += 4; 6689 } 6690 } 6691 6692 return 0; 6693} 6694 6695static void 6696s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED) 6697{ 6698 know (fragp->insn_addr <= s3_RELAX_PAD_BYTE); 6699} 6700 6701static void 6702s3_validate_fix (fixS *fixP) 6703{ 6704 fixP->fx_where += fixP->fx_frag->insn_addr; 6705} 6706 6707static int 6708s3_force_relocation (struct fix *fixp) 6709{ 6710 int retval = 0; 6711 6712 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 6713 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY 6714 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP 6715 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH 6716 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP 6717 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH 6718 || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP) 6719 { 6720 retval = 1; 6721 } 6722 return retval; 6723} 6724 6725static bool 6726s3_fix_adjustable (fixS * fixP) 6727{ 6728 if (fixP->fx_addsy == NULL) 6729 { 6730 return 1; 6731 } 6732 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour 6733 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) 6734 { 6735 return 0; 6736 } 6737 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 6738 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY 6739 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP 6740 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP) 6741 { 6742 return 0; 6743 } 6744 6745 return 1; 6746} 6747 6748static void 6749s3_elf_final_processing (void) 6750{ 6751 unsigned long val = 0; 6752 6753 if (score3) 6754 val = E_SCORE_MACH_SCORE3; 6755 else if (score7) 6756 val = E_SCORE_MACH_SCORE7; 6757 6758 elf_elfheader (stdoutput)->e_machine = EM_SCORE; 6759 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH; 6760 elf_elfheader (stdoutput)->e_flags |= val; 6761 6762 if (s3_fix_data_dependency == 1) 6763 { 6764 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; 6765 } 6766 if (s3_score_pic == s3_PIC) 6767 { 6768 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; 6769 } 6770} 6771 6772static int 6773s3_judge_size_before_relax (fragS * fragp, asection *sec) 6774{ 6775 int change = 0; 6776 6777 if (s3_score_pic == s3_NO_PIC) 6778 change = s3_nopic_need_relax (fragp->fr_symbol, 0); 6779 else 6780 change = s3_pic_need_relax (fragp->fr_symbol, sec); 6781 6782 if (change == 1) 6783 { 6784 /* Only at the first time determining whether s3_GP instruction relax should be done, 6785 return the difference between instruction size and instruction relax size. */ 6786 if (fragp->fr_opcode == NULL) 6787 { 6788 fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype); 6789 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6790 return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype); 6791 } 6792 } 6793 6794 return 0; 6795} 6796 6797static int 6798s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) 6799{ 6800 if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP) 6801 || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) 6802 return s3_judge_size_before_relax (fragp, sec); 6803 6804 return 0; 6805} 6806 6807static int 6808s3_relax_branch_inst32 (fragS * fragp) 6809{ 6810 fragp->fr_opcode = NULL; 6811 return 0; 6812} 6813 6814static int 6815s3_relax_branch_inst16 (fragS * fragp) 6816{ 6817 int relaxable_p = 0; 6818 int frag_addr = fragp->fr_address + fragp->insn_addr; 6819 addressT symbol_address = 0; 6820 symbolS *s; 6821 offsetT offset; 6822 long value; 6823 unsigned long inst_value; 6824 6825 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6826 6827 s = fragp->fr_symbol; 6828 if (s == NULL) 6829 frag_addr = 0; 6830 else 6831 symbol_address = (addressT) symbol_get_frag (s)->fr_address; 6832 6833 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE); 6834 offset = (inst_value & 0x1ff) << 1; 6835 if ((offset & 0x200) == 0x200) 6836 offset |= 0xfffffc00; 6837 6838 value = offset + symbol_address - frag_addr; 6839 6840 if (relaxable_p 6841 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) 6842 && fragp->fr_fix == 2 6843 && (S_IS_DEFINED (s) 6844 && !S_IS_COMMON (s) 6845 && !S_IS_EXTERNAL (s))) 6846 { 6847 /* Relax branch 32 to branch 16. */ 6848 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6849 fragp->fr_fix = 4; 6850 return 2; 6851 } 6852 else 6853 return 0; 6854} 6855 6856static int 6857s3_relax_cmpbranch_inst32 (fragS * fragp) 6858{ 6859 int relaxable_p = 0; 6860 symbolS *s; 6861 /* For sign bit. */ 6862 long offset; 6863 long frag_addr = fragp->fr_address + fragp->insn_addr; 6864 long symbol_address = 0; 6865 long value; 6866 unsigned long inst_value; 6867 6868 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6869 6870 s = fragp->fr_symbol; 6871 if (s == NULL) 6872 frag_addr = 0; 6873 else 6874 symbol_address = (addressT) symbol_get_frag (s)->fr_address; 6875 6876 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE); 6877 offset = (inst_value & 0x1) 6878 | (((inst_value >> 7) & 0x7) << 1) 6879 | (((inst_value >> 21) & 0x1f) << 4); 6880 offset <<= 1; 6881 if ((offset & 0x200) == 0x200) 6882 offset |= 0xfffffe00; 6883 6884 value = offset + symbol_address - frag_addr; 6885 /* change the order of judging rule is because 6886 1.not defined symbol or common symbol or external symbol will change 6887 bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode 6888 2.if the flow is as before : it will results to recursive loop 6889 */ 6890 if (fragp->fr_fix == 6) 6891 { 6892 /* Have already relaxed! Just return 0 to terminate the loop. */ 6893 return 0; 6894 } 6895 /* need to translate when extern or not defined or common symbol */ 6896 else if ((relaxable_p 6897 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) 6898 && fragp->fr_fix == 4) 6899 || !S_IS_DEFINED (s) 6900 ||S_IS_COMMON (s) 6901 ||S_IS_EXTERNAL (s)) 6902 { 6903 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6904 fragp->fr_fix = 6; 6905 return 2; 6906 } 6907 else 6908 { 6909 /* Never relax. Modify fr_opcode to NULL to verify it's value in 6910 md_apply_fix. */ 6911 fragp->fr_opcode = NULL; 6912 return 0; 6913 } 6914} 6915 6916 6917static int 6918s3_relax_other_inst32 (fragS * fragp) 6919{ 6920 int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6921 6922 if (relaxable_p 6923 && fragp->fr_fix == 4) 6924 { 6925 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6926 fragp->fr_fix = 2; 6927 return -2; 6928 } 6929 else 6930 return 0; 6931} 6932 6933static int 6934s3_relax_gp_and_pic_inst32 (void) 6935{ 6936 /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC 6937 instructions. We don't change relax size here. */ 6938 return 0; 6939} 6940 6941static int 6942s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) 6943{ 6944 int grows = 0; 6945 int adjust_align_p = 0; 6946 6947 /* If the instruction address is odd, make it half word align first. */ 6948 if ((fragp->fr_address) % 2 != 0) 6949 { 6950 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) 6951 { 6952 fragp->insn_addr = 1; 6953 grows += 1; 6954 adjust_align_p = 1; 6955 } 6956 } 6957 6958 switch (s3_RELAX_TYPE (fragp->fr_subtype)) 6959 { 6960 case PC_DISP19div2: 6961 grows += s3_relax_branch_inst32 (fragp); 6962 break; 6963 6964 case PC_DISP8div2: 6965 grows += s3_relax_branch_inst16 (fragp); 6966 break; 6967 6968 case Insn_BCMP : 6969 grows += s3_relax_cmpbranch_inst32 (fragp); 6970 break; 6971 6972 case Insn_GP: 6973 case Insn_PIC: 6974 grows += s3_relax_gp_and_pic_inst32 (); 6975 break; 6976 6977 default: 6978 grows += s3_relax_other_inst32 (fragp); 6979 break; 6980 } 6981 6982 /* newly added */ 6983 if (adjust_align_p && fragp->insn_addr) 6984 { 6985 fragp->fr_fix += fragp->insn_addr; 6986 } 6987 6988 return grows; 6989} 6990 6991static void 6992s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) 6993{ 6994 unsigned int r_old; 6995 unsigned int r_new; 6996 char backup[20]; 6997 fixS *fixp; 6998 6999 r_old = s3_RELAX_OLD (fragp->fr_subtype); 7000 r_new = s3_RELAX_NEW (fragp->fr_subtype); 7001 7002 /* fragp->fr_opcode indicates whether this frag should be relaxed. */ 7003 if (fragp->fr_opcode == NULL) 7004 { 7005 memcpy (backup, fragp->fr_literal, r_old); 7006 fragp->fr_fix = r_old; 7007 } 7008 else 7009 { 7010 memcpy (backup, fragp->fr_literal + r_old, r_new); 7011 fragp->fr_fix = r_new; 7012 } 7013 7014 fixp = fragp->tc_frag_data.fixp; 7015 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old) 7016 { 7017 if (fragp->fr_opcode) 7018 fixp->fx_done = 1; 7019 fixp = fixp->fx_next; 7020 } 7021 while (fixp && fixp->fx_frag == fragp) 7022 { 7023 if (fragp->fr_opcode) 7024 fixp->fx_where -= r_old + fragp->insn_addr; 7025 else 7026 fixp->fx_done = 1; 7027 fixp = fixp->fx_next; 7028 } 7029 7030 if (fragp->insn_addr) 7031 { 7032 s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); 7033 } 7034 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); 7035 fragp->fr_fix += fragp->insn_addr; 7036} 7037 7038static long 7039s3_pcrel_from (fixS * fixP) 7040{ 7041 long retval = 0; 7042 7043 if (fixP->fx_addsy 7044 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) 7045 && (fixP->fx_subsy == NULL)) 7046 { 7047 retval = 0; 7048 } 7049 else 7050 { 7051 retval = fixP->fx_where + fixP->fx_frag->fr_address; 7052 } 7053 7054 return retval; 7055} 7056 7057static valueT 7058s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 7059{ 7060 int align = bfd_section_alignment (segment); 7061 return ((size + (1 << align) - 1) & -(1 << align)); 7062} 7063 7064static void 7065s3_apply_fix (fixS *fixP, valueT *valP, segT seg) 7066{ 7067 valueT value = *valP; 7068 valueT newval; 7069 valueT content; 7070 valueT HI, LO; 7071 7072 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; 7073 7074 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED); 7075 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) 7076 { 7077 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) 7078 fixP->fx_done = 1; 7079 } 7080 7081 /* If this symbol is in a different section then we need to leave it for 7082 the linker to deal with. Unfortunately, md_pcrel_from can't tell, 7083 so we have to undo it's effects here. */ 7084 if (fixP->fx_pcrel) 7085 { 7086 if (fixP->fx_addsy != NULL 7087 && S_IS_DEFINED (fixP->fx_addsy) 7088 && S_GET_SEGMENT (fixP->fx_addsy) != seg) 7089 value += md_pcrel_from (fixP); 7090 } 7091 7092 /* Remember value for emit_reloc. */ 7093 fixP->fx_addnumber = value; 7094 7095 switch (fixP->fx_r_type) 7096 { 7097 case BFD_RELOC_HI16_S: 7098 if (fixP->fx_done) /* For la rd, imm32. */ 7099 { 7100 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7101 HI = value >> 16; /* mul to 2, then take the hi 16 bit. */ 7102 newval |= (HI & 0x3fff) << 1; 7103 newval |= ((HI >> 14) & 0x3) << 16; 7104 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7105 } 7106 break; 7107 case BFD_RELOC_LO16: 7108 if (fixP->fx_done) /* For la rd, imm32. */ 7109 { 7110 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7111 LO = value & 0xffff; 7112 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ 7113 newval |= ((LO >> 14) & 0x3) << 16; 7114 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7115 } 7116 break; 7117 case BFD_RELOC_SCORE_JMP: 7118 { 7119 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7120 value = fixP->fx_offset; 7121 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); 7122 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7123 } 7124 break; 7125 7126 case BFD_RELOC_SCORE_IMM30: 7127 { 7128 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); 7129 value = fixP->fx_offset; 7130 value >>= 2; 7131 content = (content & ~0x7f7fff7f80LL) 7132 | (((value & 0xff) >> 0) << 7) 7133 | (((value & 0x7fff00) >> 8) << 16) 7134 | (((value & 0x3f800000) >> 23) << 32); 7135 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); 7136 break; 7137 } 7138 7139 case BFD_RELOC_SCORE_IMM32: 7140 { 7141 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); 7142 value = fixP->fx_offset; 7143 content = (content & ~0x7f7fff7fe0LL) 7144 | ((value & 0x3ff) << 5) 7145 | (((value >> 10) & 0x7fff) << 16) 7146 | (((value >> 25) & 0x7f) << 32); 7147 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); 7148 break; 7149 } 7150 7151 case BFD_RELOC_SCORE_BRANCH: 7152 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7153 value = fixP->fx_offset; 7154 else 7155 fixP->fx_done = 1; 7156 7157 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7158 7159 /* Don't check c-bit. */ 7160 if (fixP->fx_frag->fr_opcode != 0) 7161 { 7162 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7163 { 7164 as_bad_where (fixP->fx_file, fixP->fx_line, 7165 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7166 return; 7167 } 7168 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7169 content &= 0xfe00; 7170 content = (content & 0xfe00) | ((value >> 1) & 0x1ff); 7171 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7172 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; 7173 fixP->fx_size = 2; 7174 } 7175 else 7176 { 7177 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7178 { 7179 as_bad_where (fixP->fx_file, fixP->fx_line, 7180 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7181 return; 7182 } 7183 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7184 content &= 0xfc00fc01; 7185 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7186 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7187 } 7188 break; 7189 case BFD_RELOC_SCORE16_JMP: 7190 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7191 content &= 0xf001; 7192 value = fixP->fx_offset & 0xfff; 7193 content = (content & 0xfc01) | (value & 0xffe); 7194 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7195 break; 7196 case BFD_RELOC_SCORE16_BRANCH: 7197 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7198 /* Don't check c-bit. */ 7199 if (fixP->fx_frag->fr_opcode != 0) 7200 { 7201 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 7202 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7203 value = fixP->fx_offset; 7204 else 7205 fixP->fx_done = 1; 7206 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7207 { 7208 as_bad_where (fixP->fx_file, fixP->fx_line, 7209 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7210 return; 7211 } 7212 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7213 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7214 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7215 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; 7216 fixP->fx_size = 4; 7217 break; 7218 } 7219 else 7220 { 7221 /* In different section. */ 7222 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 7223 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7224 value = fixP->fx_offset; 7225 else 7226 fixP->fx_done = 1; 7227 7228 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7229 { 7230 as_bad_where (fixP->fx_file, fixP->fx_line, 7231 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7232 return; 7233 } 7234 7235 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7236 content = (content & 0xfe00) | ((value >> 1) & 0x1ff); 7237 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7238 break; 7239 } 7240 7241 break; 7242 7243 case BFD_RELOC_SCORE_BCMP: 7244 if (fixP->fx_frag->fr_opcode != 0) 7245 { 7246 char *buf_ptr = buf; 7247 buf_ptr += 2; 7248 7249 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7250 value = fixP->fx_offset; 7251 else 7252 fixP->fx_done = 1; 7253 7254 /* NOTE!!! 7255 bcmp -> cmp! and branch, so value -= 2. */ 7256 value -= 2; 7257 7258 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7259 { 7260 as_bad_where (fixP->fx_file, fixP->fx_line, 7261 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7262 return; 7263 } 7264 7265 content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE); 7266 content &= 0xfc00fc01; 7267 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7268 s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE); 7269 /* change relocation type to BFD_RELOC_SCORE_BRANCH */ 7270 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; 7271 fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */ 7272 break; 7273 } 7274 else 7275 { 7276 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7277 value = fixP->fx_offset; 7278 else 7279 fixP->fx_done = 1; 7280 7281 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7282 7283 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7284 { 7285 as_bad_where (fixP->fx_file, fixP->fx_line, 7286 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7287 return; 7288 } 7289 7290 value >>= 1; 7291 content &= ~0x03e00381; 7292 content = content 7293 | (value & 0x1) 7294 | (((value & 0xe) >> 1) << 7) 7295 | (((value & 0x1f0) >> 4) << 21); 7296 7297 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7298 break; 7299 } 7300 7301 case BFD_RELOC_8: 7302 if (fixP->fx_done || fixP->fx_pcrel) 7303 s3_md_number_to_chars (buf, value, 1); 7304#ifdef OBJ_ELF 7305 else 7306 { 7307 value = fixP->fx_offset; 7308 s3_md_number_to_chars (buf, value, 1); 7309 } 7310#endif 7311 break; 7312 7313 case BFD_RELOC_16: 7314 if (fixP->fx_done || fixP->fx_pcrel) 7315 s3_md_number_to_chars (buf, value, 2); 7316#ifdef OBJ_ELF 7317 else 7318 { 7319 value = fixP->fx_offset; 7320 s3_md_number_to_chars (buf, value, 2); 7321 } 7322#endif 7323 break; 7324 case BFD_RELOC_RVA: 7325 case BFD_RELOC_32: 7326 if (fixP->fx_done || fixP->fx_pcrel) 7327 md_number_to_chars (buf, value, 4); 7328#ifdef OBJ_ELF 7329 else 7330 { 7331 value = fixP->fx_offset; 7332 md_number_to_chars (buf, value, 4); 7333 } 7334#endif 7335 break; 7336 case BFD_RELOC_VTABLE_INHERIT: 7337 fixP->fx_done = 0; 7338 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) 7339 S_SET_WEAK (fixP->fx_addsy); 7340 break; 7341 case BFD_RELOC_VTABLE_ENTRY: 7342 fixP->fx_done = 0; 7343 break; 7344 case BFD_RELOC_SCORE_GPREL15: 7345 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7346 /* c-bit. */ 7347 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000)) 7348 fixP->fx_r_type = BFD_RELOC_NONE; 7349 fixP->fx_done = 0; 7350 break; 7351 case BFD_RELOC_SCORE_GOT15: 7352 case BFD_RELOC_SCORE_DUMMY_HI16: 7353 case BFD_RELOC_SCORE_GOT_LO16: 7354 case BFD_RELOC_SCORE_CALL15: 7355 case BFD_RELOC_GPREL32: 7356 break; 7357 case BFD_RELOC_NONE: 7358 default: 7359 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); 7360 } 7361} 7362 7363static arelent ** 7364s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 7365{ 7366 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ 7367 arelent *reloc; 7368 bfd_reloc_code_real_type code; 7369 const char *type; 7370 7371 reloc = retval[0] = XNEW (arelent); 7372 retval[1] = NULL; 7373 7374 reloc->sym_ptr_ptr = XNEW (asymbol *); 7375 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 7376 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 7377 reloc->addend = fixp->fx_offset; 7378 7379 /* If this is a variant frag, we may need to adjust the existing 7380 reloc and generate a new one. */ 7381 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) 7382 { 7383 /* Update instruction imm bit. */ 7384 offsetT newval; 7385 unsigned short off; 7386 char *buf; 7387 7388 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; 7389 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7390 off = fixp->fx_offset >> 16; 7391 newval |= (off & 0x3fff) << 1; 7392 newval |= ((off >> 14) & 0x3) << 16; 7393 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7394 7395 buf += s3_INSN_SIZE; 7396 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7397 off = fixp->fx_offset & 0xffff; 7398 newval |= ((off & 0x3fff) << 1); 7399 newval |= (((off >> 14) & 0x3) << 16); 7400 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7401 7402 retval[1] = XNEW (arelent); 7403 retval[2] = NULL; 7404 retval[1]->sym_ptr_ptr = XNEW (asymbol *); 7405 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 7406 retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); 7407 7408 retval[1]->addend = 0; 7409 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); 7410 gas_assert (retval[1]->howto != NULL); 7411 7412 fixp->fx_r_type = BFD_RELOC_HI16_S; 7413 } 7414 7415 code = fixp->fx_r_type; 7416 switch (fixp->fx_r_type) 7417 { 7418 case BFD_RELOC_32: 7419 if (fixp->fx_pcrel) 7420 { 7421 code = BFD_RELOC_32_PCREL; 7422 break; 7423 } 7424 /* Fall through. */ 7425 case BFD_RELOC_HI16_S: 7426 case BFD_RELOC_LO16: 7427 case BFD_RELOC_SCORE_JMP: 7428 case BFD_RELOC_SCORE_BRANCH: 7429 case BFD_RELOC_SCORE16_JMP: 7430 case BFD_RELOC_SCORE16_BRANCH: 7431 case BFD_RELOC_SCORE_BCMP: 7432 case BFD_RELOC_VTABLE_ENTRY: 7433 case BFD_RELOC_VTABLE_INHERIT: 7434 case BFD_RELOC_SCORE_GPREL15: 7435 case BFD_RELOC_SCORE_GOT15: 7436 case BFD_RELOC_SCORE_DUMMY_HI16: 7437 case BFD_RELOC_SCORE_GOT_LO16: 7438 case BFD_RELOC_SCORE_CALL15: 7439 case BFD_RELOC_GPREL32: 7440 case BFD_RELOC_NONE: 7441 case BFD_RELOC_SCORE_IMM30: 7442 case BFD_RELOC_SCORE_IMM32: 7443 code = fixp->fx_r_type; 7444 break; 7445 default: 7446 type = _("<unknown>"); 7447 as_bad_where (fixp->fx_file, fixp->fx_line, 7448 _("cannot represent %s relocation in this object file format"), type); 7449 return NULL; 7450 } 7451 7452 reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 7453 if (reloc->howto == NULL) 7454 { 7455 as_bad_where (fixp->fx_file, fixp->fx_line, 7456 _("cannot represent %s relocation in this object file format1"), 7457 bfd_get_reloc_code_name (code)); 7458 return NULL; 7459 } 7460 /* HACK: Since arm ELF uses Rel instead of Rela, encode the 7461 vtable entry to be used in the relocation's section offset. */ 7462 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 7463 reloc->address = fixp->fx_offset; 7464 7465 return retval; 7466} 7467 7468void 7469md_assemble (char *str) 7470{ 7471 if (score3) 7472 s3_assemble (str); 7473 else 7474 s7_assemble (str); 7475} 7476 7477/* We handle all bad expressions here, so that we can report the faulty 7478 instruction in the error message. */ 7479void 7480md_operand (expressionS * exp) 7481{ 7482 if (score3) 7483 s3_operand (exp); 7484 else 7485 s7_operand (exp); 7486} 7487 7488/* Turn an integer of n bytes (in val) into a stream of bytes appropriate 7489 for use in the a.out file, and stores them in the array pointed to by buf. 7490 This knows about the endian-ness of the target machine and does 7491 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) 7492 2 (short) and 4 (long) Floating numbers are put out as a series of 7493 LITTLENUMS (shorts, here at least). */ 7494void 7495md_number_to_chars (char *buf, valueT val, int n) 7496{ 7497 if (score3) 7498 s3_number_to_chars (buf, val, n); 7499 else 7500 s7_number_to_chars (buf, val, n); 7501} 7502 7503/* Turn a string in input_line_pointer into a floating point constant 7504 of type TYPE, and store the appropriate bytes in *LITP. The number 7505 of LITTLENUMS emitted is stored in *SIZEP. An error message is 7506 returned, or NULL on OK. 7507 7508 Note that fp constants aren't represent in the normal way on the ARM. 7509 In big endian mode, things are as expected. However, in little endian 7510 mode fp constants are big-endian word-wise, and little-endian byte-wise 7511 within the words. For example, (double) 1.1 in big endian mode is 7512 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is 7513 the byte sequence 99 99 f1 3f 9a 99 99 99. */ 7514const char * 7515md_atof (int type, char *litP, int *sizeP) 7516{ 7517 if (score3) 7518 return s3_atof (type, litP, sizeP); 7519 else 7520 return s7_atof (type, litP, sizeP); 7521} 7522 7523void 7524score_frag_check (fragS * fragp ATTRIBUTE_UNUSED) 7525{ 7526 if (score3) 7527 s3_frag_check (fragp); 7528 else 7529 s7_frag_check (fragp); 7530} 7531 7532/* Implementation of TC_VALIDATE_FIX. 7533 Called before md_apply_fix() and after md_convert_frag(). */ 7534void 7535score_validate_fix (fixS *fixP) 7536{ 7537 if (score3) 7538 s3_validate_fix (fixP); 7539 else 7540 s7_validate_fix (fixP); 7541} 7542 7543int 7544score_force_relocation (struct fix *fixp) 7545{ 7546 if (score3) 7547 return s3_force_relocation (fixp); 7548 else 7549 return s7_force_relocation (fixp); 7550} 7551 7552/* Implementation of md_frag_check. 7553 Called after md_convert_frag(). */ 7554bool 7555score_fix_adjustable (fixS * fixP) 7556{ 7557 if (score3) 7558 return s3_fix_adjustable (fixP); 7559 else 7560 return s7_fix_adjustable (fixP); 7561} 7562 7563void 7564score_elf_final_processing (void) 7565{ 7566 if (score3) 7567 s3_elf_final_processing (); 7568 else 7569 s7_elf_final_processing (); 7570} 7571 7572/* In this function, we determine whether s3_GP instruction should do relaxation, 7573 for the label being against was known now. 7574 Doing this here but not in md_relax_frag() can induce iteration times 7575 in stage of doing relax. */ 7576int 7577md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) 7578{ 7579 if (score3) 7580 return s3_estimate_size_before_relax (fragp, sec); 7581 else 7582 return s7_estimate_size_before_relax (fragp, sec); 7583} 7584 7585int 7586score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) 7587{ 7588 if (score3) 7589 return s3_relax_frag (sec, fragp, stretch); 7590 else 7591 return s7_relax_frag (sec, fragp, stretch); 7592} 7593 7594void 7595md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) 7596{ 7597 if (score3) 7598 return s3_convert_frag (abfd, sec, fragp); 7599 else 7600 return s7_convert_frag (abfd, sec, fragp); 7601} 7602 7603long 7604md_pcrel_from (fixS * fixP) 7605{ 7606 if (score3) 7607 return s3_pcrel_from (fixP); 7608 else 7609 return s7_pcrel_from (fixP); 7610} 7611 7612/* Round up a section size to the appropriate boundary. */ 7613valueT 7614md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 7615{ 7616 if (score3) 7617 return s3_section_align (segment, size); 7618 else 7619 return s7_section_align (segment, size); 7620} 7621 7622void 7623md_apply_fix (fixS *fixP, valueT *valP, segT seg) 7624{ 7625 if (score3) 7626 return s3_apply_fix (fixP, valP, seg); 7627 else 7628 return s7_apply_fix (fixP, valP, seg); 7629} 7630 7631/* Translate internal representation of relocation info to BFD target format. */ 7632arelent ** 7633tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 7634{ 7635 if (score3) 7636 return s3_gen_reloc (section, fixp); 7637 else 7638 return s7_gen_reloc (section, fixp); 7639} 7640 7641void 7642md_begin (void) 7643{ 7644 s3_begin (); 7645 s7_begin (); 7646} 7647 7648static void 7649score_set_mach (const char *arg) 7650{ 7651 if (strcmp (arg, MARCH_SCORE3) == 0) 7652 { 7653 score3 = 1; 7654 score7 = 0; 7655 s3_score3d = 1; 7656 } 7657 else if (strcmp (arg, MARCH_SCORE7) == 0) 7658 { 7659 score3 = 0; 7660 score7 = 1; 7661 s7_score7d = 1; 7662 s7_university_version = 0; 7663 s7_vector_size = s7_SCORE7_PIPELINE; 7664 } 7665 else if (strcmp (arg, MARCH_SCORE5) == 0) 7666 { 7667 score3 = 0; 7668 score7 = 1; 7669 s7_score7d = 1; 7670 s7_university_version = 0; 7671 s7_vector_size = s7_SCORE5_PIPELINE; 7672 } 7673 else if (strcmp (arg, MARCH_SCORE5U) == 0) 7674 { 7675 score3 = 0; 7676 score7 = 1; 7677 s7_score7d = 1; 7678 s7_university_version = 1; 7679 s7_vector_size = s7_SCORE5_PIPELINE; 7680 } 7681 else 7682 { 7683 as_bad (_("unknown architecture `%s'\n"), arg); 7684 } 7685} 7686 7687int 7688md_parse_option (int c, const char *arg) 7689{ 7690 switch (c) 7691 { 7692#ifdef OPTION_EB 7693 case OPTION_EB: 7694 target_big_endian = 1; 7695 break; 7696#endif 7697#ifdef OPTION_EL 7698 case OPTION_EL: 7699 target_big_endian = 0; 7700 break; 7701#endif 7702 case OPTION_FIXDD: 7703 s3_fix_data_dependency = 1; 7704 s7_fix_data_dependency = 1; 7705 break; 7706 case OPTION_NWARN: 7707 s3_warn_fix_data_dependency = 0; 7708 s7_warn_fix_data_dependency = 0; 7709 break; 7710 case OPTION_SCORE5: 7711 score3 = 0; 7712 score7 = 1; 7713 s7_university_version = 0; 7714 s7_vector_size = s7_SCORE5_PIPELINE; 7715 break; 7716 case OPTION_SCORE5U: 7717 score3 = 0; 7718 score7 = 1; 7719 s7_university_version = 1; 7720 s7_vector_size = s7_SCORE5_PIPELINE; 7721 break; 7722 case OPTION_SCORE7: 7723 score3 = 0; 7724 score7 = 1; 7725 s7_score7d = 1; 7726 s7_university_version = 0; 7727 s7_vector_size = s7_SCORE7_PIPELINE; 7728 break; 7729 case OPTION_SCORE3: 7730 score3 = 1; 7731 score7 = 0; 7732 s3_score3d = 1; 7733 break; 7734 case OPTION_R1: 7735 s3_nor1 = 0; 7736 s7_nor1 = 0; 7737 break; 7738 case 'G': 7739 s3_g_switch_value = atoi (arg); 7740 s7_g_switch_value = atoi (arg); 7741 break; 7742 case OPTION_O0: 7743 s3_g_opt = 0; 7744 s7_g_opt = 0; 7745 break; 7746 case OPTION_SCORE_VERSION: 7747 printf (_("Sunplus-v2-0-0-20060510\n")); 7748 break; 7749 case OPTION_PIC: 7750 s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */ 7751 s7_score_pic = s7_PIC; 7752 s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */ 7753 s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */ 7754 break; 7755 case OPTION_MARCH: 7756 score_set_mach (arg); 7757 break; 7758 default: 7759 return 0; 7760 } 7761 return 1; 7762} 7763 7764void 7765md_show_usage (FILE * fp) 7766{ 7767 fprintf (fp, _(" Score-specific assembler options:\n")); 7768#ifdef OPTION_EB 7769 fprintf (fp, _("\ 7770 -EB\t\tassemble code for a big-endian cpu\n")); 7771#endif 7772 7773#ifdef OPTION_EL 7774 fprintf (fp, _("\ 7775 -EL\t\tassemble code for a little-endian cpu\n")); 7776#endif 7777 7778 fprintf (fp, _("\ 7779 -FIXDD\t\tfix data dependencies\n")); 7780 fprintf (fp, _("\ 7781 -NWARN\t\tdo not print warning message when fixing data dependencies\n")); 7782 fprintf (fp, _("\ 7783 -SCORE5\t\tassemble code for target SCORE5\n")); 7784 fprintf (fp, _("\ 7785 -SCORE5U\tassemble code for target SCORE5U\n")); 7786 fprintf (fp, _("\ 7787 -SCORE7\t\tassemble code for target SCORE7 [default]\n")); 7788 fprintf (fp, _("\ 7789 -SCORE3\t\tassemble code for target SCORE3\n")); 7790 fprintf (fp, _("\ 7791 -march=score7\tassemble code for target SCORE7 [default]\n")); 7792 fprintf (fp, _("\ 7793 -march=score3\tassemble code for target SCORE3\n")); 7794 fprintf (fp, _("\ 7795 -USE_R1\t\tassemble code for no warning message when using temp register r1\n")); 7796 fprintf (fp, _("\ 7797 -KPIC\t\tgenerate PIC\n")); 7798 fprintf (fp, _("\ 7799 -O0\t\tdo not perform any optimizations\n")); 7800 fprintf (fp, _("\ 7801 -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n")); 7802 fprintf (fp, _("\ 7803 -V \t\tSunplus release version\n")); 7804} 7805