1 /* tc-score.c -- Assembler for Score 2 Copyright (C) 2006-2020 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 27 static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED); 28 static void s3_s_score_text (int ignore); 29 static void s3_score_s_section (int ignore); 30 static void s3_s_change_sec (int sec); 31 static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED); 32 static void s3_s_score_ent (int aent); 33 static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED); 34 static void s3_s_score_end (int x ATTRIBUTE_UNUSED); 35 static void s3_s_score_set (int x ATTRIBUTE_UNUSED); 36 static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED); 37 static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED); 38 static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED); 39 static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED); 40 static void s3_s_score_lcomm (int bytes_p); 41 42 static void s_score_bss (int ignore ATTRIBUTE_UNUSED); 43 static void s_score_text (int ignore); 44 static void s_section (int ignore); 45 static void s_change_sec (int sec); 46 static void s_score_mask (int reg_type ATTRIBUTE_UNUSED); 47 static void s_score_ent (int aent); 48 static void s_score_frame (int ignore ATTRIBUTE_UNUSED); 49 static void s_score_end (int x ATTRIBUTE_UNUSED); 50 static void s_score_set (int x ATTRIBUTE_UNUSED); 51 static void s_score_cpload (int ignore ATTRIBUTE_UNUSED); 52 static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED); 53 static void s_score_gpword (int ignore ATTRIBUTE_UNUSED); 54 static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED); 55 static void s_score_lcomm (int bytes_p); 56 57 /* s3: hooks. */ 58 static void s3_md_number_to_chars (char *buf, valueT val, int n); 59 static valueT s3_md_chars_to_number (char *buf, int n); 60 static void s3_assemble (char *str); 61 static void s3_operand (expressionS *); 62 static void s3_begin (void); 63 static void s3_number_to_chars (char *buf, valueT val, int n); 64 static const char *s3_atof (int type, char *litP, int *sizeP); 65 static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED); 66 static void s3_validate_fix (fixS *fixP); 67 static int s3_force_relocation (struct fix *fixp); 68 static bfd_boolean s3_fix_adjustable (fixS * fixP); 69 static void s3_elf_final_processing (void); 70 static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED); 71 static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED); 72 static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp); 73 static long s3_pcrel_from (fixS * fixP); 74 static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size); 75 static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg); 76 static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp); 77 78 /* s3: utils. */ 79 static void s3_do_ldst_insn (char *); 80 static void s3_do_crdcrscrsimm5 (char *); 81 static void s3_do_ldst_unalign (char *); 82 static void s3_do_ldst_atomic (char *); 83 static void s3_do_ldst_cop (char *); 84 static void s3_do_macro_li_rdi32 (char *); 85 static void s3_do_macro_la_rdi32 (char *); 86 static void s3_do_macro_rdi32hi (char *); 87 static void s3_do_macro_rdi32lo (char *); 88 static void s3_do_macro_mul_rdrsrs (char *); 89 static void s3_do_macro_bcmp (char *); 90 static void s3_do_macro_bcmpz (char *); 91 static void s3_do_macro_ldst_label (char *); 92 static void s3_do_branch (char *); 93 static void s3_do_jump (char *); 94 static void s3_do_empty (char *); 95 static void s3_do16_int (char *); 96 static void s3_do_rdrsrs (char *); 97 static void s3_do_rdsi16 (char *); 98 static void s3_do_rdrssi14 (char *); 99 static void s3_do_sub_rdsi16 (char *); 100 static void s3_do_sub_rdi16 (char *); 101 static void s3_do_sub_rdrssi14 (char *); 102 static void s3_do_rdrsi5 (char *); 103 static void s3_do_rdrsi14 (char *); 104 static void s3_do_rdi16 (char *); 105 static void s3_do_ldis (char *); 106 static void s3_do_xrsi5 (char *); 107 static void s3_do_rdrs (char *); 108 static void s3_do_rdxrs (char *); 109 static void s3_do_rsrs (char *); 110 static void s3_do_rdcrs (char *); 111 static void s3_do_rdsrs (char *); 112 static void s3_do_rd (char *); 113 static void s3_do16_dsp (char *); 114 static void s3_do16_dsp2 (char *); 115 static void s3_do_dsp (char *); 116 static void s3_do_dsp2 (char *); 117 static void s3_do_dsp3 (char *); 118 static void s3_do_rs (char *); 119 static void s3_do_i15 (char *); 120 static void s3_do_xi5x (char *); 121 static void s3_do_ceinst (char *); 122 static void s3_do_cache (char *); 123 static void s3_do16_rdrs2 (char *); 124 static void s3_do16_br (char *); 125 static void s3_do16_brr (char *); 126 static void s3_do_ltb (char *); 127 static void s3_do16_mv_cmp (char *); 128 static void s3_do16_addi (char *); 129 static void s3_do16_cmpi (char *); 130 static void s3_do16_rdi5 (char *); 131 static void s3_do16_xi5 (char *); 132 static void s3_do16_ldst_insn (char *); 133 static void s3_do16_slli_srli (char *); 134 static void s3_do16_ldiu (char *); 135 static void s3_do16_push_pop (char *); 136 static void s3_do16_rpush (char *); 137 static void s3_do16_rpop (char *); 138 static void s3_do16_branch (char *); 139 static void s3_do_lw48 (char *); 140 static void s3_do_sw48 (char *); 141 static void s3_do_ldi48 (char *); 142 static void s3_do_sdbbp48 (char *); 143 static void s3_do_and48 (char *); 144 static void s3_do_or48 (char *); 145 static void s3_do_mbitclr (char *); 146 static void s3_do_mbitset (char *); 147 static void s3_do_rdi16_pic (char *); 148 static void s3_do_addi_s_pic (char *); 149 static void s3_do_addi_u_pic (char *); 150 static 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. */ 185 const char comment_chars[] = "#"; 186 const char line_comment_chars[] = "#"; 187 const char line_separator_chars[] = ";"; 188 /* Chars that can be used to separate mant from exp in floating point numbers. */ 189 const char EXP_CHARS[] = "eE"; 190 const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; 191 192 #ifdef OBJ_ELF 193 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ 194 symbolS *GOT_symbol; 195 #endif 196 197 const 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 223 const char *md_shortopts = "nO::g::G:"; 224 struct 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 246 size_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. */ 312 enum 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 321 enum s3_score_pic_level 322 { 323 s3_NO_PIC, 324 s3_PIC 325 }; 326 static enum s3_score_pic_level s3_score_pic = s3_NO_PIC; 327 328 enum s3_insn_type_for_dependency 329 { 330 s3_D_mtcr, 331 s3_D_all_insn 332 }; 333 334 struct s3_insn_to_dependency 335 { 336 const char *insn_name; 337 enum s3_insn_type_for_dependency type; 338 }; 339 340 struct 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 351 static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] = 352 { 353 /* move special instruction. */ 354 {"mtcr", s3_D_mtcr}, 355 }; 356 357 static 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. */ 364 static char s3_err_msg[255]; 365 366 static int s3_fix_data_dependency = 0; 367 static int s3_warn_fix_data_dependency = 1; 368 369 static int s3_in_my_get_expression = 0; 370 371 /* Default, pop warning message when using r1. */ 372 static int s3_nor1 = 1; 373 374 /* Default will do instruction relax, -O0 will set s3_g_opt = 0. */ 375 static unsigned int s3_g_opt = 1; 376 377 /* The size of the small data section. */ 378 static unsigned int s3_g_switch_value = 8; 379 380 static segT s3_pdr_seg; 381 382 struct 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 }; 401 static struct s3_score_it s3_inst; 402 403 typedef 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; 414 static s3_procS s3_cur_proc; 415 static s3_procS *s3_cur_proc_ptr; 416 static int s3_numprocs; 417 418 419 /* Structure for a hash table entry for a register. */ 420 struct s3_reg_entry 421 { 422 const char *name; 423 int number; 424 }; 425 426 static 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 439 static const struct s3_reg_entry s3_score_srn_table[] = 440 { 441 {"sr0", 0}, {"sr1", 1}, {"sr2", 2}, 442 {NULL, 0} 443 }; 444 445 static 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 458 struct s3_reg_map 459 { 460 const struct s3_reg_entry *names; 461 int max_regno; 462 struct hash_control *htab; 463 const char *expected; 464 }; 465 466 static 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 473 static struct hash_control *s3_score_ops_hsh = NULL; 474 static struct hash_control *s3_dependency_insn_hsh = NULL; 475 476 477 struct s3_datafield_range 478 { 479 int data_type; 480 int bits; 481 int range[2]; 482 }; 483 484 static 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 538 struct 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 559 static 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 587 static 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 1006 static int s3_university_version = 0; 1007 static int s3_vector_size = s3_SCORE3_PIPELINE; 1008 static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE]; 1009 1010 static int s3_score3d = 1; 1011 1012 static int 1013 s3_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 1029 static int 1030 s3_score_reg_parse (char **ccp, struct hash_control *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 *) 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 1060 static int 1061 s3_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 1099 static int 1100 s3_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 1126 static void 1127 s3_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 1169 static int 1170 s3_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 1183 static int 1184 s3_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. */ 1240 static bfd_signed_vma 1241 s3_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 1337 static int 1338 s3_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. */ 1566 static void 1567 s3_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 1634 static void 1635 s3_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. */ 1647 static void 1648 s3_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. */ 1659 static void 1660 s3_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. */ 1671 static void 1672 s3_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. */ 1684 static void 1685 s3_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) */ 1699 static void 1700 s3_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) */ 1724 static void 1725 s3_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. */ 1738 static void 1739 s3_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. */ 1759 static void 1760 s3_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 1807 static void 1808 s3_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 1818 static void 1819 s3_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. */ 1830 static void 1831 s3_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 . */ 1842 static void 1843 s3_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 . */ 1854 static void 1855 s3_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. */ 1866 static void 1867 s3_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 */ 1876 static void 1877 s3_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 1894 static void 1895 s3_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 1903 static void 1904 s3_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 1918 static void 1919 s3_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. */ 1951 static void 1952 s3_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. */ 1963 static void 1964 s3_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. */ 1985 static void 1986 s3_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>. */ 2007 static void 2008 s3_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 2027 static void 2028 s3_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 2056 static int 2057 s3_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!. */ 2087 static void 2088 s3_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!. */ 2102 static void 2103 s3_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!. */ 2115 static void 2116 s3_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 */ 2130 static void 2131 s3_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. */ 2168 static fixS * 2169 s3_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 2188 static void 2189 s3_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 2199 static enum s3_insn_type_for_dependency 2200 s3_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 *) hash_find (s3_dependency_insn_hsh, name); 2207 2208 if (tmp) 2209 return tmp->type; 2210 2211 return s3_D_all_insn; 2212 } 2213 2214 static int 2215 s3_check_dependency (char *pre_insn, char *pre_reg, 2216 char *cur_insn, char *cur_reg, int *warn_or_error) 2217 { 2218 int bubbles = 0; 2219 unsigned int i; 2220 enum s3_insn_type_for_dependency pre_insn_type; 2221 enum s3_insn_type_for_dependency cur_insn_type; 2222 2223 pre_insn_type = s3_dependency_type_from_insn (pre_insn); 2224 cur_insn_type = s3_dependency_type_from_insn (cur_insn); 2225 2226 for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++) 2227 { 2228 if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type) 2229 && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type 2230 || cur_insn_type == s3_data_dependency_table[i].cur_insn_type) 2231 && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0 2232 || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0) 2233 && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0 2234 || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0)) 2235 { 2236 bubbles = s3_data_dependency_table[i].bubblenum_3; 2237 *warn_or_error = s3_data_dependency_table[i].warn_or_error; 2238 break; 2239 } 2240 } 2241 2242 return bubbles; 2243 } 2244 2245 static void 2246 s3_build_one_frag (struct s3_score_it one_inst) 2247 { 2248 char *p; 2249 int relaxable_p = s3_g_opt; 2250 int relax_size = 0; 2251 2252 /* Start a new frag if frag_now is not empty. */ 2253 if (frag_now_fix () != 0) 2254 { 2255 if (!frag_now->tc_frag_data.is_insn) 2256 frag_wane (frag_now); 2257 2258 frag_new (0); 2259 } 2260 frag_grow (20); 2261 2262 p = frag_more (one_inst.size); 2263 s3_md_number_to_chars (p, one_inst.instruction, one_inst.size); 2264 2265 #ifdef OBJ_ELF 2266 dwarf2_emit_insn (one_inst.size); 2267 #endif 2268 2269 relaxable_p &= (one_inst.relax_size != 0); 2270 relax_size = relaxable_p ? one_inst.relax_size : 0; 2271 2272 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, 2273 s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size, 2274 one_inst.type, 0, 0, relaxable_p), 2275 NULL, 0, NULL); 2276 2277 if (relaxable_p) 2278 s3_md_number_to_chars (p, one_inst.relax_inst, relax_size); 2279 } 2280 2281 static void 2282 s3_handle_dependency (struct s3_score_it *theinst) 2283 { 2284 int i; 2285 int warn_or_error = 0; /* warn - 0; error - 1 */ 2286 int bubbles = 0; 2287 int remainder_bubbles = 0; 2288 char cur_insn[s3_INSN_NAME_LEN]; 2289 char pre_insn[s3_INSN_NAME_LEN]; 2290 struct s3_score_it nop_inst; 2291 struct s3_score_it pflush_inst; 2292 2293 nop_inst.instruction = 0x0000; 2294 nop_inst.size = 2; 2295 nop_inst.relax_inst = 0x80008000; 2296 nop_inst.relax_size = 4; 2297 nop_inst.type = NO16_OPD; 2298 2299 pflush_inst.instruction = 0x8000800a; 2300 pflush_inst.size = 4; 2301 pflush_inst.relax_inst = 0x8000; 2302 pflush_inst.relax_size = 0; 2303 pflush_inst.type = NO_OPD; 2304 2305 /* pflush will clear all data dependency. */ 2306 if (strcmp (theinst->name, "pflush") == 0) 2307 { 2308 s3_init_dependency_vector (); 2309 return; 2310 } 2311 2312 /* Push current instruction to s3_dependency_vector[0]. */ 2313 for (i = s3_vector_size - 1; i > 0; i--) 2314 memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i])); 2315 2316 memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i])); 2317 2318 /* There is no dependency between nop and any instruction. */ 2319 if (strcmp (s3_dependency_vector[0].name, "nop") == 0 2320 || strcmp (s3_dependency_vector[0].name, "nop!") == 0) 2321 return; 2322 2323 strcpy (cur_insn, s3_dependency_vector[0].name); 2324 2325 for (i = 1; i < s3_vector_size; i++) 2326 { 2327 /* The element of s3_dependency_vector is NULL. */ 2328 if (s3_dependency_vector[i].name[0] == '\0') 2329 continue; 2330 2331 strcpy (pre_insn, s3_dependency_vector[i].name); 2332 2333 bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg, 2334 cur_insn, s3_dependency_vector[0].reg, &warn_or_error); 2335 remainder_bubbles = bubbles - i + 1; 2336 2337 if (remainder_bubbles > 0) 2338 { 2339 int j; 2340 2341 if (s3_fix_data_dependency == 1) 2342 { 2343 if (remainder_bubbles <= 2) 2344 { 2345 if (s3_warn_fix_data_dependency) 2346 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"), 2347 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2348 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2349 remainder_bubbles, bubbles); 2350 2351 for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--) 2352 memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles], 2353 sizeof (s3_dependency_vector[j])); 2354 2355 for (j = 1; j <= remainder_bubbles; j++) 2356 { 2357 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); 2358 /* Insert nop!. */ 2359 s3_build_one_frag (nop_inst); 2360 } 2361 } 2362 else 2363 { 2364 if (s3_warn_fix_data_dependency) 2365 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"), 2366 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2367 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2368 bubbles); 2369 2370 for (j = 1; j < s3_vector_size; j++) 2371 memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); 2372 2373 /* Insert pflush. */ 2374 s3_build_one_frag (pflush_inst); 2375 } 2376 } 2377 else 2378 { 2379 if (warn_or_error) 2380 { 2381 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2382 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2383 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2384 remainder_bubbles, bubbles); 2385 } 2386 else 2387 { 2388 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2389 s3_dependency_vector[i].name, s3_dependency_vector[i].reg, 2390 s3_dependency_vector[0].name, s3_dependency_vector[0].reg, 2391 remainder_bubbles, bubbles); 2392 } 2393 } 2394 } 2395 } 2396 } 2397 2398 static enum insn_class 2399 s3_get_insn_class_from_type (enum score_insn_type type) 2400 { 2401 enum insn_class retval = (int) s3_FAIL; 2402 2403 switch (type) 2404 { 2405 case Rd_I4: 2406 case Rd_I5: 2407 case Rd_rvalueBP_I5: 2408 case Rd_lvalueBP_I5: 2409 case Rd_I8: 2410 case PC_DISP8div2: 2411 case PC_DISP11div2: 2412 case Rd_Rs: 2413 case Rd_HighRs: 2414 case Rd_lvalueRs: 2415 case Rd_rvalueRs: 2416 case x_Rs: 2417 case Rd_LowRs: 2418 case NO16_OPD: 2419 case Rd_SI5: 2420 case Rd_SI6: 2421 retval = INSN_CLASS_16; 2422 break; 2423 case Rd_Rs_I5: 2424 case x_Rs_I5: 2425 case x_I5_x: 2426 case Rd_Rs_I14: 2427 case I15: 2428 case Rd_I16: 2429 case Rd_SI16: 2430 case Rd_rvalueRs_SI10: 2431 case Rd_lvalueRs_SI10: 2432 case Rd_rvalueRs_preSI12: 2433 case Rd_rvalueRs_postSI12: 2434 case Rd_lvalueRs_preSI12: 2435 case Rd_lvalueRs_postSI12: 2436 case Rd_Rs_SI14: 2437 case Rd_rvalueRs_SI15: 2438 case Rd_lvalueRs_SI15: 2439 case PC_DISP19div2: 2440 case PC_DISP24div2: 2441 case Rd_Rs_Rs: 2442 case x_Rs_x: 2443 case x_Rs_Rs: 2444 case Rd_Rs_x: 2445 case Rd_x_Rs: 2446 case Rd_x_x: 2447 case OP5_rvalueRs_SI15: 2448 case I5_Rs_Rs_I5_OP5: 2449 case x_rvalueRs_post4: 2450 case Rd_rvalueRs_post4: 2451 case Rd_x_I5: 2452 case Rd_lvalueRs_post4: 2453 case x_lvalueRs_post4: 2454 case Rd_Rs_Rs_imm: 2455 case NO_OPD: 2456 case Rd_lvalue32Rs: 2457 case Rd_rvalue32Rs: 2458 case Insn_GP: 2459 case Insn_PIC: 2460 case Insn_internal: 2461 case Insn_BCMP: 2462 case Ra_I9_I5: 2463 retval = INSN_CLASS_32; 2464 break; 2465 case Insn_Type_PCE: 2466 retval = INSN_CLASS_PCE; 2467 break; 2468 case Insn_Type_SYN: 2469 retval = INSN_CLASS_SYN; 2470 break; 2471 case Rd_I30: 2472 case Rd_I32: 2473 retval = INSN_CLASS_48; 2474 break; 2475 default: 2476 abort (); 2477 break; 2478 } 2479 return retval; 2480 } 2481 2482 /* Type of p-bits: 2483 48-bit instruction: 1, 1, 0. 2484 32-bit instruction: 1, 0. 2485 16-bit instruction: 0. */ 2486 static bfd_vma 2487 s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class) 2488 { 2489 bfd_vma result = 0; 2490 bfd_vma m_code_high = 0; 2491 unsigned long m_code_middle = 0; 2492 unsigned long m_code_low = 0; 2493 bfd_vma pb_high = 0; 2494 unsigned long pb_middle = 0; 2495 unsigned long pb_low = 0; 2496 2497 if (i_class == INSN_CLASS_48) 2498 { 2499 pb_high = 0x800000000000LL; 2500 pb_middle = 0x80000000; 2501 pb_low = 0x00000000; 2502 m_code_high = m_code & 0x1fffc0000000LL; 2503 m_code_middle = m_code & 0x3fff8000; 2504 m_code_low = m_code & 0x00007fff; 2505 result = pb_high | (m_code_high << 2) | 2506 pb_middle | (m_code_middle << 1) | 2507 pb_low | m_code_low; 2508 } 2509 else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN) 2510 { 2511 pb_high = 0x80000000; 2512 pb_low = 0x00000000; 2513 m_code_high = m_code & 0x3fff8000; 2514 m_code_low = m_code & 0x00007fff; 2515 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2516 } 2517 else if (i_class == INSN_CLASS_16) 2518 { 2519 pb_high = 0; 2520 pb_low = 0; 2521 m_code_high = m_code & 0x3fff8000; 2522 m_code_low = m_code & 0x00007fff; 2523 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2524 } 2525 else if (i_class == INSN_CLASS_PCE) 2526 { 2527 /* Keep original. */ 2528 pb_high = 0; 2529 pb_low = 0x00008000; 2530 m_code_high = m_code & 0x3fff8000; 2531 m_code_low = m_code & 0x00007fff; 2532 result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2533 } 2534 else 2535 { 2536 abort (); 2537 } 2538 2539 return result; 2540 } 2541 2542 static void 2543 s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2) 2544 { 2545 char *p; 2546 bfd_boolean pce_p = FALSE; 2547 int relaxable_p = s3_g_opt; 2548 int relax_size = 0; 2549 struct s3_score_it *inst1 = part_1; 2550 struct s3_score_it *inst2 = part_2; 2551 struct s3_score_it backup_inst1; 2552 2553 pce_p = (inst2) ? TRUE : FALSE; 2554 memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it)); 2555 2556 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 2557 if (pce_p) 2558 { 2559 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15) 2560 | (inst2->instruction & 0x7FFF); 2561 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); 2562 backup_inst1.relax_inst = 0x8000; 2563 backup_inst1.size = s3_INSN_SIZE; 2564 backup_inst1.relax_size = 0; 2565 backup_inst1.type = Insn_Type_PCE; 2566 } 2567 else 2568 { 2569 backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, 2570 s3_GET_INSN_CLASS (backup_inst1.type)); 2571 } 2572 2573 if (backup_inst1.relax_size != 0) 2574 { 2575 enum insn_class tmp; 2576 2577 tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; 2578 backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp); 2579 } 2580 2581 /* Check data dependency. */ 2582 s3_handle_dependency (&backup_inst1); 2583 2584 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains 2585 data produced by .ascii etc. Doing this is to make one instruction per frag. */ 2586 if (frag_now_fix () != 0) 2587 { 2588 if (!frag_now->tc_frag_data.is_insn) 2589 frag_wane (frag_now); 2590 2591 frag_new (0); 2592 } 2593 2594 /* Here, we must call frag_grow in order to keep the instruction frag type is 2595 rs_machine_dependent. 2596 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which 2597 actually will call frag_wane. 2598 Calling frag_grow first will create a new frag_now which free size is 20 that is enough 2599 for frag_var. */ 2600 frag_grow (20); 2601 2602 p = frag_more (backup_inst1.size); 2603 s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); 2604 2605 #ifdef OBJ_ELF 2606 dwarf2_emit_insn (backup_inst1.size); 2607 #endif 2608 2609 /* Generate fixup structure. */ 2610 if (pce_p) 2611 { 2612 if (inst1->reloc.type != BFD_RELOC_NONE) 2613 s3_fix_new_score (frag_now, p - frag_now->fr_literal, 2614 inst1->size, &inst1->reloc.exp, 2615 inst1->reloc.pc_rel, inst1->reloc.type); 2616 2617 if (inst2->reloc.type != BFD_RELOC_NONE) 2618 s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2, 2619 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type); 2620 } 2621 else 2622 { 2623 if (backup_inst1.reloc.type != BFD_RELOC_NONE) 2624 s3_fix_new_score (frag_now, p - frag_now->fr_literal, 2625 backup_inst1.size, &backup_inst1.reloc.exp, 2626 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type); 2627 } 2628 2629 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */ 2630 relaxable_p &= (backup_inst1.relax_size != 0); 2631 relax_size = relaxable_p ? backup_inst1.relax_size : 0; 2632 2633 p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, 2634 s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, 2635 backup_inst1.type, 0, 0, relaxable_p), 2636 backup_inst1.reloc.exp.X_add_symbol, 0, NULL); 2637 2638 if (relaxable_p) 2639 s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size); 2640 2641 memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it)); 2642 } 2643 2644 static void 2645 s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) 2646 { 2647 char c; 2648 char *p; 2649 char *operator = insnstr; 2650 const struct s3_asm_opcode *opcode; 2651 2652 /* Parse operator and operands. */ 2653 s3_skip_whitespace (operator); 2654 2655 for (p = operator; *p != '\0'; p++) 2656 if ((*p == ' ') || (*p == '!')) 2657 break; 2658 2659 if (*p == '!') 2660 p++; 2661 2662 c = *p; 2663 *p = '\0'; 2664 2665 opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator); 2666 *p = c; 2667 2668 memset (&s3_inst, '\0', sizeof (s3_inst)); 2669 sprintf (s3_inst.str, "%s", insnstr); 2670 if (opcode) 2671 { 2672 s3_inst.instruction = opcode->value; 2673 s3_inst.relax_inst = opcode->relax_value; 2674 s3_inst.type = opcode->type; 2675 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); 2676 s3_inst.relax_size = 0; 2677 s3_inst.bwarn = 0; 2678 sprintf (s3_inst.name, "%s", opcode->template_name); 2679 strcpy (s3_inst.reg, ""); 2680 s3_inst.error = NULL; 2681 s3_inst.reloc.type = BFD_RELOC_NONE; 2682 2683 (*opcode->parms) (p); 2684 2685 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ 2686 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) 2687 s3_gen_insn_frag (&s3_inst, NULL); 2688 } 2689 else 2690 s3_inst.error = _("unrecognized opcode"); 2691 } 2692 2693 static void 2694 s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p) 2695 { 2696 char c; 2697 char *p; 2698 char *operator = insnstr; 2699 const struct s3_asm_opcode *opcode; 2700 2701 /* Parse operator and operands. */ 2702 s3_skip_whitespace (operator); 2703 2704 for (p = operator; *p != '\0'; p++) 2705 if (*p == ' ') 2706 break; 2707 2708 c = *p; 2709 *p = '\0'; 2710 2711 opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator); 2712 *p = c; 2713 2714 memset (&s3_inst, '\0', sizeof (s3_inst)); 2715 sprintf (s3_inst.str, "%s", insnstr); 2716 if (opcode) 2717 { 2718 s3_inst.instruction = opcode->value; 2719 s3_inst.relax_inst = opcode->relax_value; 2720 s3_inst.type = opcode->type; 2721 s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); 2722 s3_inst.relax_size = 0; 2723 s3_inst.bwarn = 0; 2724 sprintf (s3_inst.name, "%s", opcode->template_name); 2725 strcpy (s3_inst.reg, ""); 2726 s3_inst.error = NULL; 2727 s3_inst.reloc.type = BFD_RELOC_NONE; 2728 2729 (*opcode->parms) (p); 2730 2731 /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ 2732 if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) 2733 s3_gen_insn_frag (&s3_inst, NULL); 2734 } 2735 else 2736 s3_inst.error = _("unrecognized opcode"); 2737 } 2738 2739 static int 2740 s3_append_insn (char *str, bfd_boolean gen_frag_p) 2741 { 2742 int retval = s3_SUCCESS; 2743 2744 s3_parse_16_32_inst (str, gen_frag_p); 2745 2746 if (s3_inst.error) 2747 { 2748 retval = (int) s3_FAIL; 2749 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); 2750 s3_inst.error = NULL; 2751 } 2752 2753 return retval; 2754 } 2755 2756 static void 2757 s3_do16_mv_cmp (char *str) 2758 { 2759 s3_skip_whitespace (str); 2760 2761 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2762 || s3_skip_past_comma (&str) == (int) s3_FAIL 2763 || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2764 || s3_end_of_line (str) == (int) s3_FAIL) 2765 { 2766 return; 2767 } 2768 } 2769 2770 static void 2771 s3_do16_cmpi (char *str) 2772 { 2773 s3_skip_whitespace (str); 2774 2775 if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL 2776 || s3_skip_past_comma (&str) == (int) s3_FAIL 2777 || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL 2778 || s3_end_of_line (str) == (int) s3_FAIL) 2779 { 2780 return; 2781 } 2782 } 2783 2784 static void 2785 s3_do16_addi (char *str) 2786 { 2787 s3_skip_whitespace (str); 2788 2789 if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL 2790 || s3_skip_past_comma (&str) == (int) s3_FAIL 2791 || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL 2792 || s3_end_of_line (str) == (int) s3_FAIL) 2793 { 2794 return; 2795 } 2796 } 2797 2798 /* Handle bitclr! / bitset! / bittst! / bittgl! */ 2799 static void 2800 s3_do16_rdi5 (char *str) 2801 { 2802 s3_skip_whitespace (str); 2803 2804 if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL 2805 || s3_skip_past_comma (&str) == (int) s3_FAIL 2806 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 2807 || s3_end_of_line (str) == (int) s3_FAIL) 2808 return; 2809 else 2810 { 2811 s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20) 2812 | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10); 2813 s3_inst.relax_size = 4; 2814 } 2815 } 2816 2817 2818 /* Handle sdbbp!. */ 2819 static void 2820 s3_do16_xi5 (char *str) 2821 { 2822 s3_skip_whitespace (str); 2823 2824 if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) 2825 return; 2826 } 2827 2828 /* Check that an immediate is word alignment or half word alignment. 2829 If so, convert it to the right format. */ 2830 static int 2831 s3_validate_immediate_align (int val, unsigned int data_type) 2832 { 2833 if (data_type == _IMM5_RSHIFT_1) 2834 { 2835 if (val % 2) 2836 { 2837 s3_inst.error = _("address offset must be half word alignment"); 2838 return (int) s3_FAIL; 2839 } 2840 } 2841 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2842 { 2843 if (val % 4) 2844 { 2845 s3_inst.error = _("address offset must be word alignment"); 2846 return (int) s3_FAIL; 2847 } 2848 } 2849 2850 return s3_SUCCESS; 2851 } 2852 2853 static int 2854 s3_exp_ldst_offset (char **str, int shift, unsigned int data_type) 2855 { 2856 char *dataptr; 2857 2858 dataptr = * str; 2859 2860 if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 2861 && (data_type != _SIMM16_LA) 2862 && (data_type != _VALUE_HI16) 2863 && (data_type != _VALUE_LO16) 2864 && (data_type != _IMM16) 2865 && (data_type != _IMM15) 2866 && (data_type != _IMM14) 2867 && (data_type != _IMM4) 2868 && (data_type != _IMM5) 2869 && (data_type != _IMM8) 2870 && (data_type != _IMM5_RSHIFT_1) 2871 && (data_type != _IMM5_RSHIFT_2) 2872 && (data_type != _SIMM14_NEG) 2873 && (data_type != _IMM10_RSHIFT_2)) 2874 { 2875 data_type += 24; 2876 } 2877 2878 if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL) 2879 return (int) s3_FAIL; 2880 2881 if (s3_inst.reloc.exp.X_op == O_constant) 2882 { 2883 /* Need to check the immediate align. */ 2884 int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type); 2885 2886 if (value == (int) s3_FAIL) 2887 return (int) s3_FAIL; 2888 2889 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 2890 if (value == (int) s3_FAIL) 2891 { 2892 if (data_type < 30) 2893 sprintf (s3_err_msg, 2894 _("invalid constant: %d bit expression not in range %d..%d"), 2895 s3_score_df_range[data_type].bits, 2896 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 2897 else 2898 sprintf (s3_err_msg, 2899 _("invalid constant: %d bit expression not in range %d..%d"), 2900 s3_score_df_range[data_type - 24].bits, 2901 s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]); 2902 s3_inst.error = s3_err_msg; 2903 return (int) s3_FAIL; 2904 } 2905 2906 if (data_type == _IMM5_RSHIFT_1) 2907 { 2908 value >>= 1; 2909 } 2910 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2911 { 2912 value >>= 2; 2913 } 2914 2915 if (s3_score_df_range[data_type].range[0] != 0) 2916 { 2917 value &= (1 << s3_score_df_range[data_type].bits) - 1; 2918 } 2919 2920 s3_inst.instruction |= value << shift; 2921 } 2922 else 2923 { 2924 s3_inst.reloc.pc_rel = 0; 2925 } 2926 2927 return s3_SUCCESS; 2928 } 2929 2930 static void 2931 s3_do_ldst_insn (char *str) 2932 { 2933 int pre_inc = 0; 2934 int conflict_reg; 2935 int value; 2936 char * temp; 2937 char *dataptr; 2938 int reg; 2939 int ldst_idx = 0; 2940 2941 s3_skip_whitespace (str); 2942 2943 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 2944 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 2945 return; 2946 2947 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */ 2948 if (*str == '[') 2949 { 2950 str++; 2951 s3_skip_whitespace (str); 2952 2953 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 2954 return; 2955 2956 /* Conflicts can occur on stores as well as loads. */ 2957 conflict_reg = (conflict_reg == reg); 2958 s3_skip_whitespace (str); 2959 temp = str + 1; /* The latter will process decimal/hex expression. */ 2960 2961 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */ 2962 if (*str == ']') 2963 { 2964 str++; 2965 if (*str == '+') 2966 { 2967 str++; 2968 /* ld/sw rD, [rA]+, simm12. */ 2969 if (s3_skip_past_comma (&str) == s3_SUCCESS) 2970 { 2971 if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL) 2972 || (s3_end_of_line (str) == (int) s3_FAIL)) 2973 return; 2974 2975 if (conflict_reg) 2976 { 2977 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 2978 2979 if ((ldst_func == INSN_LH) 2980 || (ldst_func == INSN_LHU) 2981 || (ldst_func == INSN_LW) 2982 || (ldst_func == INSN_LB) 2983 || (ldst_func == INSN_LBU)) 2984 { 2985 s3_inst.error = _("register same as write-back base"); 2986 return; 2987 } 2988 } 2989 2990 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 2991 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2992 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value; 2993 2994 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */ 2995 if ((s3_inst.instruction & 0x3e000007) == 0x0e000000) 2996 { 2997 /* rs = r0, offset = 4 */ 2998 if ((((s3_inst.instruction >> 15) & 0x1f) == 0) 2999 && (((s3_inst.instruction >> 3) & 0xfff) == 4)) 3000 { 3001 /* Relax to pop!. */ 3002 s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f); 3003 s3_inst.relax_size = 2; 3004 } 3005 } 3006 return; 3007 } 3008 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */ 3009 else 3010 { 3011 s3_SET_INSN_ERROR (NULL); 3012 if (s3_end_of_line (str) == (int) s3_FAIL) 3013 { 3014 return; 3015 } 3016 3017 pre_inc = 1; 3018 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0); 3019 value &= (1 << s3_score_df_range[_SIMM12].bits) - 1; 3020 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3021 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3022 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; 3023 s3_inst.instruction |= value << 3; 3024 s3_inst.relax_inst = 0x8000; 3025 return; 3026 } 3027 } 3028 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */ 3029 else 3030 { 3031 if (s3_end_of_line (str) == (int) s3_FAIL) 3032 return; 3033 3034 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3035 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3036 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; 3037 3038 /* lbu rd, [rs] -> lbu! rd, [rs] */ 3039 if (ldst_idx == INSN_LBU) 3040 { 3041 s3_inst.relax_inst = INSN16_LBU; 3042 } 3043 else if (ldst_idx == INSN_LH) 3044 { 3045 s3_inst.relax_inst = INSN16_LH; 3046 } 3047 else if (ldst_idx == INSN_LW) 3048 { 3049 s3_inst.relax_inst = INSN16_LW; 3050 } 3051 else if (ldst_idx == INSN_SB) 3052 { 3053 s3_inst.relax_inst = INSN16_SB; 3054 } 3055 else if (ldst_idx == INSN_SH) 3056 { 3057 s3_inst.relax_inst = INSN16_SH; 3058 } 3059 else if (ldst_idx == INSN_SW) 3060 { 3061 s3_inst.relax_inst = INSN16_SW; 3062 } 3063 else 3064 { 3065 s3_inst.relax_inst = 0x8000; 3066 } 3067 3068 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */ 3069 /* if ((ldst_idx == INSN_LBU) 3070 || (ldst_idx == INSN_LH) 3071 || (ldst_idx == INSN_LW) 3072 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/ 3073 if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW)) 3074 { 3075 /* ra only 3 bit , rd only 4 bit for lw! and sw! */ 3076 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3077 { 3078 s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) | 3079 (((s3_inst.instruction >> 15) & 0x7) << 5); 3080 s3_inst.relax_size = 2; 3081 } 3082 } 3083 3084 return; 3085 } 3086 } 3087 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */ 3088 else 3089 { 3090 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3091 { 3092 s3_inst.error = _("pre-indexed expression expected"); 3093 return; 3094 } 3095 3096 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 3097 return; 3098 3099 s3_skip_whitespace (str); 3100 if (*str++ != ']') 3101 { 3102 s3_inst.error = _("missing ]"); 3103 return; 3104 } 3105 3106 s3_skip_whitespace (str); 3107 /* ld/sw rD, [rA, simm12]+. */ 3108 if (*str == '+') 3109 { 3110 str++; 3111 pre_inc = 1; 3112 if (conflict_reg) 3113 { 3114 unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3115 3116 if ((ldst_func == INSN_LH) 3117 || (ldst_func == INSN_LHU) 3118 || (ldst_func == INSN_LW) 3119 || (ldst_func == INSN_LB) 3120 || (ldst_func == INSN_LBU)) 3121 { 3122 s3_inst.error = _("register same as write-back base"); 3123 return; 3124 } 3125 } 3126 } 3127 3128 if (s3_end_of_line (str) == (int) s3_FAIL) 3129 return; 3130 3131 if (s3_inst.reloc.exp.X_op == O_constant) 3132 { 3133 unsigned int data_type; 3134 3135 if (pre_inc == 1) 3136 data_type = _SIMM12; 3137 else 3138 data_type = _SIMM15; 3139 dataptr = temp; 3140 3141 if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 3142 && (data_type != _SIMM16_LA) 3143 && (data_type != _VALUE_HI16) 3144 && (data_type != _VALUE_LO16) 3145 && (data_type != _IMM16) 3146 && (data_type != _IMM15) 3147 && (data_type != _IMM14) 3148 && (data_type != _IMM4) 3149 && (data_type != _IMM5) 3150 && (data_type != _IMM8) 3151 && (data_type != _IMM5_RSHIFT_1) 3152 && (data_type != _IMM5_RSHIFT_2) 3153 && (data_type != _SIMM14_NEG) 3154 && (data_type != _IMM10_RSHIFT_2)) 3155 { 3156 data_type += 24; 3157 } 3158 3159 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 3160 if (value == (int) s3_FAIL) 3161 { 3162 if (data_type < 30) 3163 sprintf (s3_err_msg, 3164 _("invalid constant: %d bit expression not in range %d..%d"), 3165 s3_score_df_range[data_type].bits, 3166 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 3167 else 3168 sprintf (s3_err_msg, 3169 _("invalid constant: %d bit expression not in range %d..%d"), 3170 s3_score_df_range[data_type - 24].bits, 3171 s3_score_df_range[data_type - 24].range[0], 3172 s3_score_df_range[data_type - 24].range[1]); 3173 s3_inst.error = s3_err_msg; 3174 return; 3175 } 3176 3177 value &= (1 << s3_score_df_range[data_type].bits) - 1; 3178 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 3179 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 3180 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; 3181 if (pre_inc == 1) 3182 s3_inst.instruction |= value << 3; 3183 else 3184 s3_inst.instruction |= value; 3185 3186 /* lw rD, [rA, simm15] */ 3187 if ((s3_inst.instruction & 0x3e000000) == 0x20000000) 3188 { 3189 /* rD in [r0 - r15]. , ra in [r0-r7] */ 3190 if ((((s3_inst.instruction >> 15) & 0x18) == 0) 3191 && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3192 { 3193 /* simm = [bit 7], lw -> lw!. */ 3194 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) 3195 { 3196 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5) 3197 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); 3198 s3_inst.relax_size = 2; 3199 } 3200 else 3201 { 3202 s3_inst.relax_inst = 0x8000; 3203 } 3204 } 3205 else 3206 { 3207 s3_inst.relax_inst = 0x8000; 3208 } 3209 } 3210 /* sw rD, [rA, simm15] */ 3211 else if ((s3_inst.instruction & 0x3e000000) == 0x28000000) 3212 { 3213 /* rD is in [r0 - r15] and ra in [r0-r7] */ 3214 if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) 3215 { 3216 /* simm15 =7 bit , sw -> sw!. */ 3217 if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) 3218 { 3219 s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5) 3220 | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); 3221 s3_inst.relax_size = 2; 3222 } 3223 /* rA = r2, sw -> swp!. */ 3224 else 3225 { 3226 s3_inst.relax_inst = 0x8000; 3227 } 3228 } 3229 else 3230 { 3231 s3_inst.relax_inst = 0x8000; 3232 } 3233 } 3234 /* sw rD, [rA, simm15]+ sw pre. */ 3235 else if ((s3_inst.instruction & 0x3e000007) == 0x06000004) 3236 { 3237 /* simm15 = -4. and ra==r0 */ 3238 if ((((s3_inst.instruction >> 15) & 0x1f) == 0) 3239 && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc)) 3240 { 3241 /* sw -> push!. */ 3242 s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f); 3243 s3_inst.relax_size = 2; 3244 } 3245 else 3246 { 3247 s3_inst.relax_inst = 0x8000; 3248 } 3249 } 3250 else 3251 { 3252 s3_inst.relax_inst = 0x8000; 3253 } 3254 3255 return; 3256 } 3257 else 3258 { 3259 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */ 3260 s3_inst.reloc.pc_rel = 0; 3261 } 3262 } 3263 } 3264 else 3265 { 3266 s3_inst.error = s3_BAD_ARGS; 3267 } 3268 } 3269 3270 /* Handle cache. */ 3271 static void 3272 s3_do_cache (char *str) 3273 { 3274 s3_skip_whitespace (str); 3275 3276 if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3277 { 3278 return; 3279 } 3280 else 3281 { 3282 int cache_op; 3283 3284 cache_op = (s3_inst.instruction >> 20) & 0x1F; 3285 sprintf (s3_inst.name, "cache %d", cache_op); 3286 } 3287 3288 if (*str == '[') 3289 { 3290 str++; 3291 s3_skip_whitespace (str); 3292 3293 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3294 return; 3295 3296 s3_skip_whitespace (str); 3297 3298 /* cache op, [rA] */ 3299 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3300 { 3301 s3_SET_INSN_ERROR (NULL); 3302 if (*str != ']') 3303 { 3304 s3_inst.error = _("missing ]"); 3305 return; 3306 } 3307 str++; 3308 } 3309 /* cache op, [rA, simm15] */ 3310 else 3311 { 3312 if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL) 3313 { 3314 return; 3315 } 3316 3317 s3_skip_whitespace (str); 3318 if (*str++ != ']') 3319 { 3320 s3_inst.error = _("missing ]"); 3321 return; 3322 } 3323 } 3324 3325 if (s3_end_of_line (str) == (int) s3_FAIL) 3326 return; 3327 } 3328 else 3329 { 3330 s3_inst.error = s3_BAD_ARGS; 3331 } 3332 } 3333 3334 static void 3335 s3_do_crdcrscrsimm5 (char *str) 3336 { 3337 char *strbak; 3338 3339 strbak = str; 3340 s3_skip_whitespace (str); 3341 3342 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3343 || s3_skip_past_comma (&str) == (int) s3_FAIL 3344 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3345 || s3_skip_past_comma (&str) == (int) s3_FAIL 3346 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL 3347 || s3_skip_past_comma (&str) == (int) s3_FAIL) 3348 { 3349 str = strbak; 3350 /* cop1 cop_code20. */ 3351 if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL) 3352 return; 3353 } 3354 else 3355 { 3356 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL) 3357 return; 3358 } 3359 3360 s3_end_of_line (str); 3361 } 3362 3363 /* Handle ldc/stc. */ 3364 static void 3365 s3_do_ldst_cop (char *str) 3366 { 3367 s3_skip_whitespace (str); 3368 3369 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL) 3370 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3371 return; 3372 3373 if (*str == '[') 3374 { 3375 str++; 3376 s3_skip_whitespace (str); 3377 3378 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3379 return; 3380 3381 s3_skip_whitespace (str); 3382 3383 if (*str++ != ']') 3384 { 3385 if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL) 3386 return; 3387 3388 s3_skip_whitespace (str); 3389 if (*str++ != ']') 3390 { 3391 s3_inst.error = _("missing ]"); 3392 return; 3393 } 3394 } 3395 3396 s3_end_of_line (str); 3397 } 3398 else 3399 s3_inst.error = s3_BAD_ARGS; 3400 } 3401 3402 static void 3403 s3_do16_ldst_insn (char *str) 3404 { 3405 int conflict_reg = 0; 3406 s3_skip_whitespace (str); 3407 3408 if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3409 return; 3410 3411 if (*str == '[') 3412 { 3413 3414 str++; 3415 s3_skip_whitespace (str); 3416 3417 if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL) 3418 return; 3419 if (conflict_reg&0x8) 3420 { 3421 sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg); 3422 s3_inst.error = s3_err_msg; 3423 return; 3424 } 3425 3426 s3_skip_whitespace (str); 3427 3428 if (*str == ']') 3429 { 3430 str++; 3431 if (s3_end_of_line (str) == (int) s3_FAIL) 3432 return; 3433 } 3434 else 3435 { 3436 if (s3_skip_past_comma (&str) == (int) s3_FAIL) 3437 { 3438 s3_inst.error = _("comma is expected"); 3439 return; 3440 } 3441 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 3442 return; 3443 s3_skip_whitespace (str); 3444 if (*str++ != ']') 3445 { 3446 s3_inst.error = _("missing ]"); 3447 return; 3448 } 3449 if (s3_end_of_line (str) == (int) s3_FAIL) 3450 return; 3451 if (s3_inst.reloc.exp.X_op == O_constant) 3452 { 3453 int value; 3454 unsigned int data_type; 3455 data_type = _IMM5_RSHIFT_2; 3456 value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); 3457 if (value == (int) s3_FAIL) 3458 { 3459 if (data_type < 30) 3460 sprintf (s3_err_msg, 3461 _("invalid constant: %d bit expression not in range %d..%d"), 3462 s3_score_df_range[data_type].bits, 3463 s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); 3464 s3_inst.error = s3_err_msg; 3465 return; 3466 } 3467 if (value & 0x3) 3468 { 3469 sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value); 3470 s3_inst.error = s3_err_msg; 3471 return; 3472 } 3473 3474 value >>= 2; 3475 s3_inst.instruction |= value; 3476 } 3477 } 3478 } 3479 else 3480 { 3481 sprintf (s3_err_msg, _("missing [")); 3482 s3_inst.error = s3_err_msg; 3483 return; 3484 } 3485 } 3486 3487 static void 3488 s3_do_lw48 (char *str) 3489 { 3490 bfd_signed_vma val = 0; 3491 3492 s3_skip_whitespace (str); 3493 3494 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3495 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3496 return; 3497 3498 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3499 || s3_end_of_line (str) == (int) s3_FAIL) 3500 { 3501 return; 3502 } 3503 3504 /* Check word align for lw48 rd, value. */ 3505 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3506 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) 3507 { 3508 s3_inst.error = _("invalid constant: 32 bit expression not word align"); 3509 return; 3510 } 3511 3512 /* Check and set offset. */ 3513 val = s3_inst.reloc.exp.X_add_number; 3514 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3515 && (!(val >= 0 && val <= 0xffffffffLL))) 3516 { 3517 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); 3518 return; 3519 } 3520 3521 val &= 0xffffffff; 3522 val >>= 2; 3523 s3_inst.instruction |= (val << 7); 3524 3525 /* Set reloc type. */ 3526 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; 3527 3528 } 3529 3530 static void 3531 s3_do_sw48 (char *str) 3532 { 3533 bfd_signed_vma val = 0; 3534 3535 s3_skip_whitespace (str); 3536 3537 if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3538 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3539 return; 3540 3541 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3542 || s3_end_of_line (str) == (int) s3_FAIL) 3543 { 3544 return; 3545 } 3546 3547 /* Check word align for lw48 rd, value. */ 3548 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3549 && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) 3550 { 3551 s3_inst.error = _("invalid constant: 32 bit expression not word align"); 3552 return; 3553 } 3554 3555 /* Check and set offset. */ 3556 val = s3_inst.reloc.exp.X_add_number; 3557 if ((s3_inst.reloc.exp.X_add_symbol == NULL) 3558 && (!(val >= 0 && val <= 0xffffffffLL))) 3559 { 3560 s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); 3561 return; 3562 } 3563 3564 val &= 0xffffffff; 3565 val >>= 2; 3566 s3_inst.instruction |= (val << 7); 3567 3568 /* Set reloc type. */ 3569 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; 3570 } 3571 3572 static void 3573 s3_do_ldi48 (char *str) 3574 { 3575 bfd_signed_vma val; 3576 3577 s3_skip_whitespace (str); 3578 3579 if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL 3580 || s3_skip_past_comma (&str) == (int) s3_FAIL) 3581 return; 3582 3583 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 3584 || s3_end_of_line (str) == (int) s3_FAIL) 3585 { 3586 return; 3587 } 3588 3589 /* Check and set offset. */ 3590 val = s3_inst.reloc.exp.X_add_number; 3591 if (!(val >= -0xffffffffLL && val <= 0xffffffffLL)) 3592 { 3593 s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]"); 3594 return; 3595 } 3596 3597 val &= 0xffffffff; 3598 s3_inst.instruction |= (val << 5); 3599 3600 /* Set reloc type. */ 3601 s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32; 3602 } 3603 3604 static void 3605 s3_do_sdbbp48 (char *str) 3606 { 3607 s3_skip_whitespace (str); 3608 3609 if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) 3610 return; 3611 } 3612 3613 static void 3614 s3_do_and48 (char *str) 3615 { 3616 s3_skip_whitespace (str); 3617 3618 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL 3619 || s3_skip_past_comma (&str) == (int) s3_FAIL 3620 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL 3621 || s3_skip_past_comma (&str) == (int) s3_FAIL 3622 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL 3623 || s3_end_of_line (str) == (int) s3_FAIL) 3624 return; 3625 } 3626 3627 static void 3628 s3_do_or48 (char *str) 3629 { 3630 s3_skip_whitespace (str); 3631 3632 if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL 3633 || s3_skip_past_comma (&str) == (int) s3_FAIL 3634 || s3_reglow_required_here (&str, 34) == (int) s3_FAIL 3635 || s3_skip_past_comma (&str) == (int) s3_FAIL 3636 || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL 3637 || s3_end_of_line (str) == (int) s3_FAIL) 3638 return; 3639 } 3640 3641 static void 3642 s3_do_mbitclr (char *str) 3643 { 3644 int val; 3645 s3_skip_whitespace (str); 3646 3647 if (*str != '[') 3648 { 3649 sprintf (s3_err_msg, _("missing [")); 3650 s3_inst.error = s3_err_msg; 3651 return; 3652 } 3653 str++; 3654 3655 s3_inst.instruction &= 0x0; 3656 3657 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3658 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3659 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) 3660 return; 3661 3662 /* Get imm11 and refill opcode. */ 3663 val = s3_inst.instruction & 0x7ff; 3664 val >>= 2; 3665 s3_inst.instruction &= 0x000f8000; 3666 s3_inst.instruction |= 0x00000064; 3667 3668 if (*str != ']') 3669 { 3670 sprintf (s3_err_msg, _("missing ]")); 3671 s3_inst.error = s3_err_msg; 3672 return; 3673 } 3674 str++; 3675 3676 if ((s3_skip_past_comma (&str) == (int) s3_FAIL) 3677 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) 3678 return; 3679 3680 /* Set imm11 to opcode. */ 3681 s3_inst.instruction |= (val & 0x1) 3682 | (((val >> 1 ) & 0x7) << 7) 3683 | (((val >> 4 ) & 0x1f) << 20); 3684 } 3685 3686 static void 3687 s3_do_mbitset (char *str) 3688 { 3689 int val; 3690 s3_skip_whitespace (str); 3691 3692 if (*str != '[') 3693 { 3694 sprintf (s3_err_msg, _("missing [")); 3695 s3_inst.error = s3_err_msg; 3696 return; 3697 } 3698 str++; 3699 3700 s3_inst.instruction &= 0x0; 3701 3702 if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3703 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3704 || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) 3705 return; 3706 3707 /* Get imm11 and refill opcode. */ 3708 val = s3_inst.instruction & 0x7ff; 3709 val >>= 2; 3710 s3_inst.instruction &= 0x000f8000; 3711 s3_inst.instruction |= 0x0000006c; 3712 3713 if (*str != ']') 3714 { 3715 sprintf (s3_err_msg, _("missing ]")); 3716 s3_inst.error = s3_err_msg; 3717 return; 3718 } 3719 str++; 3720 3721 if ((s3_skip_past_comma (&str) == (int) s3_FAIL) 3722 || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) 3723 return; 3724 3725 /* Set imm11 to opcode. */ 3726 s3_inst.instruction |= (val & 0x1) 3727 | (((val >> 1 ) & 0x7) << 7) 3728 | (((val >> 4 ) & 0x1f) << 20); 3729 } 3730 3731 static void 3732 s3_do16_slli_srli (char *str) 3733 { 3734 s3_skip_whitespace (str); 3735 3736 if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL) 3737 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3738 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 3739 || s3_end_of_line (str) == (int) s3_FAIL) 3740 return; 3741 } 3742 3743 static void 3744 s3_do16_ldiu (char *str) 3745 { 3746 s3_skip_whitespace (str); 3747 3748 if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3749 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 3750 || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL 3751 || s3_end_of_line (str) == (int) s3_FAIL) 3752 return; 3753 } 3754 3755 static void 3756 s3_do16_push_pop (char *str) 3757 { 3758 s3_skip_whitespace (str); 3759 if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 3760 || s3_end_of_line (str) == (int) s3_FAIL) 3761 return; 3762 } 3763 3764 static void 3765 s3_do16_rpush (char *str) 3766 { 3767 int reg; 3768 int val; 3769 s3_skip_whitespace (str); 3770 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL 3771 || s3_skip_past_comma (&str) == (int) s3_FAIL 3772 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL 3773 || s3_end_of_line (str) == (int) s3_FAIL) 3774 return; 3775 3776 /* 0: indicate 32. 3777 1: invalid value. 3778 2: to 31: normal value. */ 3779 val = s3_inst.instruction & 0x1f; 3780 if (val == 1) 3781 { 3782 s3_inst.error = _("imm5 should >= 2"); 3783 return; 3784 } 3785 if (reg >= 32) 3786 { 3787 s3_inst.error = _("reg should <= 31"); 3788 return; 3789 } 3790 } 3791 3792 static void 3793 s3_do16_rpop (char *str) 3794 { 3795 int reg; 3796 int val; 3797 s3_skip_whitespace (str); 3798 if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL 3799 || s3_skip_past_comma (&str) == (int) s3_FAIL 3800 || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL 3801 || s3_end_of_line (str) == (int) s3_FAIL) 3802 return; 3803 3804 /* 0: indicate 32. 3805 1: invalid value. 3806 2: to 31: normal value. */ 3807 val = s3_inst.instruction & 0x1f; 3808 if (val == 1) 3809 { 3810 s3_inst.error = _("imm5 should >= 2"); 3811 return; 3812 } 3813 3814 if (reg >= 32) 3815 { 3816 s3_inst.error = _("reg should <= 31"); 3817 return; 3818 } 3819 else 3820 { 3821 if ((reg + val) <= 32) 3822 reg = reg + val - 1; 3823 else 3824 reg = reg + val - 33; 3825 s3_inst.instruction &= 0x7c1f; 3826 s3_inst.instruction |= (reg << 5); 3827 return; 3828 } 3829 } 3830 3831 /* Handle lcb/lcw/lce/scb/scw/sce. */ 3832 static void 3833 s3_do_ldst_unalign (char *str) 3834 { 3835 int conflict_reg; 3836 3837 if (s3_university_version == 1) 3838 { 3839 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; 3840 return; 3841 } 3842 3843 s3_skip_whitespace (str); 3844 3845 /* lcb/scb [rA]+. */ 3846 if (*str == '[') 3847 { 3848 str++; 3849 s3_skip_whitespace (str); 3850 3851 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3852 return; 3853 3854 if (*str++ == ']') 3855 { 3856 if (*str++ != '+') 3857 { 3858 s3_inst.error = _("missing +"); 3859 return; 3860 } 3861 } 3862 else 3863 { 3864 s3_inst.error = _("missing ]"); 3865 return; 3866 } 3867 3868 if (s3_end_of_line (str) == (int) s3_FAIL) 3869 return; 3870 } 3871 /* lcw/lce/scb/sce rD, [rA]+. */ 3872 else 3873 { 3874 if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3875 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3876 { 3877 return; 3878 } 3879 3880 s3_skip_whitespace (str); 3881 if (*str++ == '[') 3882 { 3883 int reg; 3884 3885 s3_skip_whitespace (str); 3886 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3887 { 3888 return; 3889 } 3890 3891 /* Conflicts can occur on stores as well as loads. */ 3892 conflict_reg = (conflict_reg == reg); 3893 s3_skip_whitespace (str); 3894 if (*str++ == ']') 3895 { 3896 unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK; 3897 3898 if (*str++ == '+') 3899 { 3900 if (conflict_reg) 3901 { 3902 as_warn (_("%s register same as write-back base"), 3903 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW) 3904 ? _("destination") : _("source"))); 3905 } 3906 } 3907 else 3908 { 3909 s3_inst.error = _("missing +"); 3910 return; 3911 } 3912 3913 if (s3_end_of_line (str) == (int) s3_FAIL) 3914 return; 3915 } 3916 else 3917 { 3918 s3_inst.error = _("missing ]"); 3919 return; 3920 } 3921 } 3922 else 3923 { 3924 s3_inst.error = s3_BAD_ARGS; 3925 return; 3926 } 3927 } 3928 } 3929 3930 /* Handle alw/asw. */ 3931 static void 3932 s3_do_ldst_atomic (char *str) 3933 { 3934 if (s3_university_version == 1) 3935 { 3936 s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; 3937 return; 3938 } 3939 3940 s3_skip_whitespace (str); 3941 3942 if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) 3943 || (s3_skip_past_comma (&str) == (int) s3_FAIL)) 3944 { 3945 return; 3946 } 3947 else 3948 { 3949 3950 s3_skip_whitespace (str); 3951 if (*str++ == '[') 3952 { 3953 int reg; 3954 3955 s3_skip_whitespace (str); 3956 if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 3957 { 3958 return; 3959 } 3960 3961 s3_skip_whitespace (str); 3962 if (*str++ != ']') 3963 { 3964 s3_inst.error = _("missing ]"); 3965 return; 3966 } 3967 3968 s3_end_of_line (str); 3969 } 3970 else 3971 s3_inst.error = s3_BAD_ARGS; 3972 } 3973 } 3974 3975 static void 3976 s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED, 3977 struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num, 3978 symbolS *add_symbol) 3979 { 3980 int i; 3981 char *p; 3982 fixS *fixp = NULL; 3983 fixS *cur_fixp = NULL; 3984 long where; 3985 struct s3_score_it inst_main; 3986 3987 memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it)); 3988 3989 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 3990 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 3991 inst_main.type = Insn_PIC; 3992 3993 for (i = 0; i < var_num; i++) 3994 { 3995 inst_main.relax_size += var_insts[i].size; 3996 var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction, 3997 s3_GET_INSN_CLASS (var_insts[i].type)); 3998 } 3999 4000 /* Check data dependency. */ 4001 s3_handle_dependency (&inst_main); 4002 4003 /* Start a new frag if frag_now is not empty. */ 4004 if (frag_now_fix () != 0) 4005 { 4006 if (!frag_now->tc_frag_data.is_insn) 4007 { 4008 frag_wane (frag_now); 4009 } 4010 frag_new (0); 4011 } 4012 frag_grow (20); 4013 4014 /* Write fr_fix part. */ 4015 p = frag_more (inst_main.size); 4016 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4017 4018 if (inst_main.reloc.type != BFD_RELOC_NONE) 4019 fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4020 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4021 4022 frag_now->tc_frag_data.fixp = fixp; 4023 cur_fixp = frag_now->tc_frag_data.fixp; 4024 4025 #ifdef OBJ_ELF 4026 dwarf2_emit_insn (inst_main.size); 4027 #endif 4028 4029 where = p - frag_now->fr_literal + inst_main.size; 4030 for (i = 0; i < var_num; i++) 4031 { 4032 if (i > 0) 4033 where += var_insts[i - 1].size; 4034 4035 if (var_insts[i].reloc.type != BFD_RELOC_NONE) 4036 { 4037 fixp = s3_fix_new_score (frag_now, where, var_insts[i].size, 4038 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel, 4039 var_insts[i].reloc.type); 4040 if (fixp) 4041 { 4042 if (cur_fixp) 4043 { 4044 cur_fixp->fx_next = fixp; 4045 cur_fixp = cur_fixp->fx_next; 4046 } 4047 else 4048 { 4049 frag_now->tc_frag_data.fixp = fixp; 4050 cur_fixp = frag_now->tc_frag_data.fixp; 4051 } 4052 } 4053 } 4054 } 4055 4056 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4057 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 4058 0, inst_main.size, 0), add_symbol, 0, NULL); 4059 4060 /* Write fr_var part. 4061 no calling s3_gen_insn_frag, no fixS will be generated. */ 4062 for (i = 0; i < var_num; i++) 4063 { 4064 s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); 4065 p += var_insts[i].size; 4066 } 4067 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4068 s3_inst.bwarn = -1; 4069 } 4070 4071 /* Build a relax frag for la instruction when generating s3_PIC, 4072 external symbol first and local symbol second. */ 4073 static void 4074 s3_build_la_pic (int reg_rd, expressionS exp) 4075 { 4076 symbolS *add_symbol = exp.X_add_symbol; 4077 offsetT add_number = exp.X_add_number; 4078 struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; 4079 struct s3_score_it var_insts[s3_RELAX_INST_NUM]; 4080 int fix_num = 0; 4081 int var_num = 0; 4082 char tmp[s3_MAX_LITERAL_POOL_SIZE]; 4083 int r1_bak; 4084 4085 r1_bak = s3_nor1; 4086 s3_nor1 = 0; 4087 4088 if (add_number == 0) 4089 { 4090 fix_num = 1; 4091 var_num = 2; 4092 4093 /* For an external symbol, only one insn is generated; 4094 For a local symbol, two insns are generated. */ 4095 /* Fix part 4096 For an external symbol: lw rD, <sym>($gp) 4097 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */ 4098 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4099 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4100 return; 4101 4102 if (reg_rd == s3_PIC_CALL_REG) 4103 s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15; 4104 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4105 4106 /* Var part 4107 For a local symbol : 4108 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 4109 addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 4110 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4111 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4112 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4113 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4114 return; 4115 4116 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); 4117 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4118 } 4119 else if (add_number >= -0x8000 && add_number <= 0x7fff) 4120 { 4121 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 4122 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4123 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) 4124 return; 4125 4126 /* Insn 2 */ 4127 fix_num = 1; 4128 var_num = 1; 4129 /* Fix part 4130 For an external symbol: addi rD, <constant> */ 4131 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number); 4132 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4133 return; 4134 4135 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4136 4137 /* Var part 4138 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */ 4139 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, 4140 S_GET_NAME (add_symbol), (int) add_number); 4141 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4142 return; 4143 4144 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4145 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4146 } 4147 else 4148 { 4149 int hi = (add_number >> 16) & 0x0000FFFF; 4150 int lo = add_number & 0x0000FFFF; 4151 4152 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 4153 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol)); 4154 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) 4155 return; 4156 4157 /* Insn 2 */ 4158 fix_num = 1; 4159 var_num = 1; 4160 /* Fix part 4161 For an external symbol: ldis r1, HI%<constant> */ 4162 sprintf (tmp, "ldis r1, %d", hi); 4163 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4164 return; 4165 4166 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4167 4168 /* Var part 4169 For a local symbol: ldis r1, HI%<constant> 4170 but, if lo is out of 16 bit, make hi plus 1 */ 4171 if ((lo < -0x8000) || (lo > 0x7fff)) 4172 { 4173 hi += 1; 4174 } 4175 sprintf (tmp, "ldis_pic r1, %d", hi); 4176 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4177 return; 4178 4179 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4180 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4181 4182 /* Insn 3 */ 4183 fix_num = 1; 4184 var_num = 1; 4185 /* Fix part 4186 For an external symbol: ori r1, LO%<constant> */ 4187 sprintf (tmp, "ori r1, %d", lo); 4188 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4189 return; 4190 4191 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4192 4193 /* Var part 4194 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */ 4195 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo); 4196 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4197 return; 4198 4199 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4200 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4201 4202 /* Insn 4: add rD, rD, r1 */ 4203 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd); 4204 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) 4205 return; 4206 4207 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4208 s3_inst.bwarn = -1; 4209 } 4210 4211 s3_nor1 = r1_bak; 4212 } 4213 4214 /* Handle la. */ 4215 static void 4216 s3_do_macro_la_rdi32 (char *str) 4217 { 4218 int reg_rd; 4219 4220 s3_skip_whitespace (str); 4221 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4222 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4223 { 4224 return; 4225 } 4226 else 4227 { 4228 /* Save str. */ 4229 char *keep_data = str; 4230 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4231 4232 /* Check immediate value. */ 4233 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 4234 { 4235 s3_inst.error = _("expression error"); 4236 return; 4237 } 4238 else if ((s3_inst.reloc.exp.X_add_symbol == NULL) 4239 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL)) 4240 { 4241 s3_inst.error = _("value not in range [0, 0xffffffff]"); 4242 return; 4243 } 4244 4245 /* Reset str. */ 4246 str = keep_data; 4247 4248 /* la rd, simm16. */ 4249 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) 4250 { 4251 s3_end_of_line (str); 4252 return; 4253 } 4254 /* la rd, imm32 or la rd, label. */ 4255 else 4256 { 4257 s3_SET_INSN_ERROR (NULL); 4258 /* Reset str. */ 4259 str = keep_data; 4260 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) 4261 || (s3_end_of_line (str) == (int) s3_FAIL)) 4262 { 4263 return; 4264 } 4265 else 4266 { 4267 if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol)) 4268 { 4269 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 4270 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4271 return; 4272 4273 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 4274 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4275 return; 4276 } 4277 else 4278 { 4279 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4280 s3_build_la_pic (reg_rd, s3_inst.reloc.exp); 4281 } 4282 4283 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4284 s3_inst.bwarn = -1; 4285 } 4286 } 4287 } 4288 } 4289 4290 /* Handle li. */ 4291 static void 4292 s3_do_macro_li_rdi32 (char *str) 4293 { 4294 4295 int reg_rd; 4296 4297 s3_skip_whitespace (str); 4298 if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4299 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4300 { 4301 return; 4302 } 4303 else 4304 { 4305 /* Save str. */ 4306 char *keep_data = str; 4307 4308 /* Check immediate value. */ 4309 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 4310 { 4311 s3_inst.error = _("expression error"); 4312 return; 4313 } 4314 else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL 4315 && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL)) 4316 { 4317 s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]"); 4318 return; 4319 } 4320 4321 /* Reset str. */ 4322 str = keep_data; 4323 4324 /* li rd, simm16. */ 4325 if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) 4326 { 4327 s3_end_of_line (str); 4328 return; 4329 } 4330 /* li rd, imm32. */ 4331 else 4332 { 4333 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4334 4335 /* Reset str. */ 4336 str = keep_data; 4337 4338 if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) 4339 || (s3_end_of_line (str) == (int) s3_FAIL)) 4340 { 4341 return; 4342 } 4343 else if (s3_inst.reloc.exp.X_add_symbol) 4344 { 4345 s3_inst.error = _("li rd label isn't correct instruction form"); 4346 return; 4347 } 4348 else 4349 { 4350 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 4351 4352 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4353 return; 4354 else 4355 { 4356 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 4357 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4358 return; 4359 4360 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4361 s3_inst.bwarn = -1; 4362 } 4363 } 4364 } 4365 } 4366 } 4367 4368 /* Handle mul/mulu/div/divu/rem/remu. */ 4369 static void 4370 s3_do_macro_mul_rdrsrs (char *str) 4371 { 4372 int reg_rd; 4373 int reg_rs1; 4374 int reg_rs2; 4375 char *backupstr; 4376 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4377 4378 if (s3_university_version == 1) 4379 as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV); 4380 4381 strcpy (append_str, str); 4382 backupstr = append_str; 4383 s3_skip_whitespace (backupstr); 4384 if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4385 || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4386 || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)) 4387 { 4388 s3_inst.error = s3_BAD_ARGS; 4389 return; 4390 } 4391 4392 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4393 { 4394 /* rem/remu rA, rB is error format. */ 4395 if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0) 4396 { 4397 s3_SET_INSN_ERROR (s3_BAD_ARGS); 4398 } 4399 else 4400 { 4401 s3_SET_INSN_ERROR (NULL); 4402 s3_do_rsrs (str); 4403 } 4404 return; 4405 } 4406 else 4407 { 4408 s3_SET_INSN_ERROR (NULL); 4409 if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4410 || (s3_end_of_line (backupstr) == (int) s3_FAIL)) 4411 { 4412 return; 4413 } 4414 else 4415 { 4416 char append_str1[s3_MAX_LITERAL_POOL_SIZE]; 4417 4418 if (strcmp (s3_inst.name, "rem") == 0) 4419 { 4420 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2); 4421 sprintf (append_str1, "mfceh r%d", reg_rd); 4422 } 4423 else if (strcmp (s3_inst.name, "remu") == 0) 4424 { 4425 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2); 4426 sprintf (append_str1, "mfceh r%d", reg_rd); 4427 } 4428 else 4429 { 4430 sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2); 4431 sprintf (append_str1, "mfcel r%d", reg_rd); 4432 } 4433 4434 /* Output mul/mulu or div/divu or rem/remu. */ 4435 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4436 return; 4437 4438 /* Output mfcel or mfceh. */ 4439 if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL) 4440 return; 4441 4442 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4443 s3_inst.bwarn = -1; 4444 } 4445 } 4446 } 4447 4448 static void 4449 s3_exp_macro_ldst_abs (char *str) 4450 { 4451 int reg_rd; 4452 char *backupstr, *tmp; 4453 char append_str[s3_MAX_LITERAL_POOL_SIZE]; 4454 char verifystr[s3_MAX_LITERAL_POOL_SIZE]; 4455 struct s3_score_it inst_backup; 4456 int r1_bak = 0; 4457 4458 r1_bak = s3_nor1; 4459 s3_nor1 = 0; 4460 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); 4461 4462 strcpy (verifystr, str); 4463 backupstr = verifystr; 4464 s3_skip_whitespace (backupstr); 4465 if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4466 return; 4467 4468 tmp = backupstr; 4469 if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) 4470 return; 4471 4472 backupstr = tmp; 4473 sprintf (append_str, "li r1 %s", backupstr); 4474 s3_append_insn (append_str, TRUE); 4475 4476 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); 4477 sprintf (append_str, " r%d, [r1,0]", reg_rd); 4478 s3_do_ldst_insn (append_str); 4479 4480 s3_nor1 = r1_bak; 4481 } 4482 4483 /* Handle bcmpeq / bcmpne */ 4484 static void 4485 s3_do_macro_bcmp (char *str) 4486 { 4487 int reg_a , reg_b; 4488 char *keep_data; 4489 size_t keep_data_size; 4490 int i; 4491 struct s3_score_it inst_expand[2]; 4492 struct s3_score_it inst_main; 4493 4494 memset (inst_expand, 0, sizeof inst_expand); 4495 s3_skip_whitespace (str); 4496 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4497 || s3_skip_past_comma (&str) == (int) s3_FAIL 4498 ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4499 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4500 return; 4501 4502 keep_data_size = strlen (str) + 1; 4503 keep_data = xmalloc (keep_data_size * 2 + 14); 4504 memcpy (keep_data, str, keep_data_size); 4505 4506 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 4507 ||reg_b == 0 4508 || s3_end_of_line (str) == (int) s3_FAIL) 4509 goto out; 4510 else if (s3_inst.reloc.exp.X_add_symbol == 0) 4511 { 4512 s3_inst.error = _("lacking label "); 4513 goto out; 4514 } 4515 else 4516 { 4517 char *append_str = keep_data + keep_data_size; 4518 s3_SET_INSN_ERROR (NULL); 4519 4520 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; 4521 s3_inst.reloc.pc_rel = 1; 4522 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; 4523 4524 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 4525 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1) 4526 | ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7 4527 | ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20; 4528 4529 /* Check and set offset. */ 4530 if (((val & 0xfffffe00) != 0) 4531 && ((val & 0xfffffe00) != 0xfffffe00)) 4532 { 4533 /* support bcmp --> cmp!+beq (bne) */ 4534 if (s3_score_pic == s3_NO_PIC) 4535 { 4536 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b); 4537 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4538 goto out; 4539 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4540 sprintf (append_str, "beq %s", keep_data); 4541 else 4542 sprintf (append_str, "bne %s", keep_data); 4543 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4544 goto out; 4545 } 4546 else 4547 { 4548 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4549 } 4550 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4551 s3_inst.bwarn = -1; 4552 goto out; 4553 } 4554 else 4555 { 4556 val >>= 1; 4557 s3_inst.instruction |= (val & 0x1) 4558 | (((val >> 1) & 0x7) << 7) 4559 | (((val >> 4) & 0x1f) << 20); 4560 } 4561 4562 /* Backup s3_inst. */ 4563 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 4564 4565 if (s3_score_pic == s3_NO_PIC) 4566 { 4567 sprintf (append_str, "cmp! r%d, r%d", reg_a, reg_b); 4568 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL) 4569 goto out; 4570 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); 4571 4572 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4573 sprintf (append_str, "beq %s", keep_data); 4574 else 4575 sprintf (append_str, "bne %s", keep_data); 4576 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL) 4577 goto out; 4578 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); 4579 } 4580 else 4581 { 4582 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4583 } 4584 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; 4585 inst_main.type = Insn_BCMP; 4586 4587 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 4588 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 4589 4590 for (i = 0; i < 2; i++) 4591 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, 4592 s3_GET_INSN_CLASS (inst_expand[i].type)); 4593 /* Check data dependency. */ 4594 s3_handle_dependency (&inst_main); 4595 /* Start a new frag if frag_now is not empty. */ 4596 if (frag_now_fix () != 0) 4597 { 4598 if (!frag_now->tc_frag_data.is_insn) 4599 frag_wane (frag_now); 4600 frag_new (0); 4601 } 4602 frag_grow (20); 4603 4604 /* Write fr_fix part. */ 4605 char *p; 4606 p = frag_more (inst_main.size); 4607 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4608 4609 if (inst_main.reloc.type != BFD_RELOC_NONE) 4610 { 4611 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4612 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4613 } 4614 #ifdef OBJ_ELF 4615 dwarf2_emit_insn (inst_main.size); 4616 #endif 4617 4618 /* s3_GP instruction can not do optimization, only can do relax between 4619 1 instruction and 3 instructions. */ 4620 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4621 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), 4622 inst_main.reloc.exp.X_add_symbol, 0, NULL); 4623 4624 /* Write fr_var part. 4625 no calling s3_gen_insn_frag, no fixS will be generated. */ 4626 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 4627 p += inst_expand[0].size; 4628 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 4629 p += inst_expand[1].size; 4630 4631 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4632 s3_inst.bwarn = -1; 4633 } 4634 out: 4635 free (keep_data); 4636 } 4637 4638 /* Handle bcmpeqz / bcmpnez */ 4639 static void 4640 s3_do_macro_bcmpz (char *str) 4641 { 4642 int reg_a; 4643 char *keep_data; 4644 size_t keep_data_size; 4645 int i; 4646 struct s3_score_it inst_expand[2]; 4647 struct s3_score_it inst_main; 4648 4649 memset (inst_expand, 0, sizeof inst_expand); 4650 s3_skip_whitespace (str); 4651 if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 4652 || s3_skip_past_comma (&str) == (int) s3_FAIL) 4653 return; 4654 4655 keep_data_size = strlen (str) + 1; 4656 keep_data = xmalloc (keep_data_size * 2 + 13); 4657 memcpy (keep_data, str, keep_data_size); 4658 4659 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 4660 || s3_end_of_line (str) == (int) s3_FAIL) 4661 goto out; 4662 else if (s3_inst.reloc.exp.X_add_symbol == 0) 4663 { 4664 s3_inst.error = _("lacking label "); 4665 goto out; 4666 } 4667 else 4668 { 4669 char *append_str = keep_data + keep_data_size; 4670 s3_SET_INSN_ERROR (NULL); 4671 s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; 4672 s3_inst.reloc.pc_rel = 1; 4673 bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; 4674 4675 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 4676 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; 4677 4678 /* Check and set offset. */ 4679 if (((val & 0xfffffe00) != 0) 4680 && ((val & 0xfffffe00) != 0xfffffe00)) 4681 { 4682 if (s3_score_pic == s3_NO_PIC) 4683 { 4684 sprintf (append_str, "cmpi! r%d, 0", reg_a); 4685 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4686 goto out; 4687 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4688 sprintf (append_str, "beq %s", keep_data); 4689 else 4690 sprintf (append_str, "bne %s", keep_data); 4691 if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) 4692 goto out; 4693 } 4694 else 4695 { 4696 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4697 } 4698 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4699 s3_inst.bwarn = -1; 4700 goto out; 4701 } 4702 else 4703 { 4704 val >>= 1; 4705 s3_inst.instruction |= (val & 0x1) 4706 | (((val >> 1) & 0x7) << 7) 4707 | (((val >> 4) & 0x1f) << 20); 4708 } 4709 4710 /* Backup s3_inst. */ 4711 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 4712 4713 if (s3_score_pic == s3_NO_PIC) 4714 { 4715 sprintf (append_str, "cmpi! r%d, 0", reg_a); 4716 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL) 4717 goto out; 4718 memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); 4719 if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) 4720 sprintf (append_str, "beq %s", keep_data); 4721 else 4722 sprintf (append_str, "bne %s", keep_data); 4723 if (s3_append_insn (append_str, FALSE) == (int) s3_FAIL) 4724 goto out; 4725 memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); 4726 } 4727 else 4728 { 4729 gas_assert (s3_inst.reloc.exp.X_add_symbol); 4730 } 4731 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; 4732 inst_main.type = Insn_BCMP; 4733 4734 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 4735 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 4736 4737 for (i = 0; i < 2; i++) 4738 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction , 4739 s3_GET_INSN_CLASS (inst_expand[i].type)); 4740 /* Check data dependency. */ 4741 s3_handle_dependency (&inst_main); 4742 /* Start a new frag if frag_now is not empty. */ 4743 if (frag_now_fix () != 0) 4744 { 4745 if (!frag_now->tc_frag_data.is_insn) 4746 frag_wane (frag_now); 4747 frag_new (0); 4748 } 4749 frag_grow (20); 4750 4751 /* Write fr_fix part. */ 4752 char *p; 4753 p = frag_more (inst_main.size); 4754 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 4755 4756 if (inst_main.reloc.type != BFD_RELOC_NONE) 4757 { 4758 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4759 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4760 } 4761 #ifdef OBJ_ELF 4762 dwarf2_emit_insn (inst_main.size); 4763 #endif 4764 4765 /* s3_GP instruction can not do optimization, only can do relax between 4766 1 instruction and 3 instructions. */ 4767 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 4768 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), 4769 inst_main.reloc.exp.X_add_symbol, 0, NULL); 4770 4771 /* Write fr_var part. 4772 no calling s3_gen_insn_frag, no fixS will be generated. */ 4773 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 4774 p += inst_expand[0].size; 4775 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 4776 p += inst_expand[1].size; 4777 4778 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4779 s3_inst.bwarn = -1; 4780 } 4781 out: 4782 free (keep_data); 4783 } 4784 4785 static int 4786 s3_nopic_need_relax (symbolS * sym, int before_relaxing) 4787 { 4788 if (sym == NULL) 4789 return 0; 4790 else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0) 4791 { 4792 const char *symname; 4793 const char *segname; 4794 4795 /* Find out whether this symbol can be referenced off the $gp 4796 register. It can be if it is smaller than the -G size or if 4797 it is in the .sdata or .sbss section. Certain symbols can 4798 not be referenced off the $gp, although it appears as though 4799 they can. */ 4800 symname = S_GET_NAME (sym); 4801 if (symname != (const char *)NULL 4802 && (strcmp (symname, "eprol") == 0 4803 || strcmp (symname, "etext") == 0 4804 || strcmp (symname, "_gp") == 0 4805 || strcmp (symname, "edata") == 0 4806 || strcmp (symname, "_fbss") == 0 4807 || strcmp (symname, "_fdata") == 0 4808 || strcmp (symname, "_ftext") == 0 4809 || strcmp (symname, "end") == 0 4810 || strcmp (symname, GP_DISP_LABEL) == 0)) 4811 { 4812 return 1; 4813 } 4814 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 4815 /* We must defer this decision until after the whole file has been read, 4816 since there might be a .extern after the first use of this symbol. */ 4817 || (before_relaxing 4818 && S_GET_VALUE (sym) == 0) 4819 || (S_GET_VALUE (sym) != 0 4820 && S_GET_VALUE (sym) <= s3_g_switch_value))) 4821 { 4822 return 0; 4823 } 4824 4825 segname = segment_name (S_GET_SEGMENT (sym)); 4826 return (strcmp (segname, ".sdata") != 0 4827 && strcmp (segname, ".sbss") != 0 4828 && strncmp (segname, ".sdata.", 7) != 0 4829 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0); 4830 } 4831 /* We are not optimizing for the $gp register. */ 4832 else 4833 return 1; 4834 } 4835 4836 /* Build a relax frag for lw/st instruction when generating s3_PIC, 4837 external symbol first and local symbol second. */ 4838 static void 4839 s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) 4840 { 4841 symbolS *add_symbol = exp.X_add_symbol; 4842 int add_number = exp.X_add_number; 4843 struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; 4844 struct s3_score_it var_insts[s3_RELAX_INST_NUM]; 4845 int fix_num = 0; 4846 int var_num = 0; 4847 char tmp[s3_MAX_LITERAL_POOL_SIZE]; 4848 int r1_bak; 4849 4850 r1_bak = s3_nor1; 4851 s3_nor1 = 0; 4852 4853 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) 4854 { 4855 fix_num = 1; 4856 var_num = 2; 4857 4858 /* For an external symbol, two insns are generated; 4859 For a local symbol, three insns are generated. */ 4860 /* Fix part 4861 For an external symbol: lw rD, <sym>($gp) 4862 (BFD_RELOC_SCORE_GOT15) */ 4863 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol)); 4864 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4865 return; 4866 4867 memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4868 4869 /* Var part 4870 For a local symbol : 4871 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 4872 addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 4873 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4874 memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); 4875 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol)); 4876 if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) 4877 return; 4878 4879 memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); 4880 s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4881 4882 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ 4883 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); 4884 if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) 4885 return; 4886 4887 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4888 s3_inst.bwarn = -1; 4889 } 4890 else 4891 { 4892 s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)"); 4893 return; 4894 } 4895 4896 s3_nor1 = r1_bak; 4897 } 4898 4899 static void 4900 s3_do_macro_ldst_label (char *str) 4901 { 4902 int i; 4903 int ldst_gp_p = 0; 4904 int reg_rd; 4905 int r1_bak; 4906 char *backup_str; 4907 char *label_str; 4908 char *absolute_value; 4909 char append_str[3][s3_MAX_LITERAL_POOL_SIZE]; 4910 char verifystr[s3_MAX_LITERAL_POOL_SIZE]; 4911 struct s3_score_it inst_backup; 4912 struct s3_score_it inst_expand[3]; 4913 struct s3_score_it inst_main; 4914 4915 memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); 4916 strcpy (verifystr, str); 4917 backup_str = verifystr; 4918 4919 s3_skip_whitespace (backup_str); 4920 if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 4921 return; 4922 4923 if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL) 4924 return; 4925 4926 label_str = backup_str; 4927 4928 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */ 4929 if (*backup_str == '[') 4930 { 4931 s3_inst.type = Rd_rvalueRs_preSI12; 4932 s3_do_ldst_insn (str); 4933 return; 4934 } 4935 4936 /* Ld/st rD, imm. */ 4937 absolute_value = backup_str; 4938 s3_inst.type = Rd_rvalueRs_SI15; 4939 4940 if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL) 4941 { 4942 s3_inst.error = _("expression error"); 4943 return; 4944 } 4945 else if ((s3_inst.reloc.exp.X_add_symbol == NULL) 4946 && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL)) 4947 { 4948 s3_inst.error = _("value not in range [0, 0x7fffffff]"); 4949 return; 4950 } 4951 else if (s3_end_of_line (backup_str) == (int) s3_FAIL) 4952 { 4953 s3_inst.error = _("end on line error"); 4954 return; 4955 } 4956 else 4957 { 4958 if (s3_inst.reloc.exp.X_add_symbol == 0) 4959 { 4960 memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); 4961 s3_exp_macro_ldst_abs (str); 4962 return; 4963 } 4964 } 4965 4966 /* Ld/st rD, label. */ 4967 s3_inst.type = Rd_rvalueRs_SI15; 4968 backup_str = absolute_value; 4969 if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL) 4970 || (s3_end_of_line (backup_str) == (int) s3_FAIL)) 4971 { 4972 return; 4973 } 4974 else 4975 { 4976 if (s3_inst.reloc.exp.X_add_symbol == 0) 4977 { 4978 if (!s3_inst.error) 4979 s3_inst.error = s3_BAD_ARGS; 4980 4981 return; 4982 } 4983 4984 if (s3_score_pic == s3_PIC) 4985 { 4986 int ldst_idx = 0; 4987 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 4988 s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp, 4989 s3_score_ldst_insns[ldst_idx * 3 + 0].template_name); 4990 return; 4991 } 4992 else 4993 { 4994 if ((s3_inst.reloc.exp.X_add_number <= 0x3fff) 4995 && (s3_inst.reloc.exp.X_add_number >= -0x4000) 4996 && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1))) 4997 { 4998 int ldst_idx = 0; 4999 5000 /* Assign the real opcode. */ 5001 ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; 5002 s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; 5003 s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value; 5004 s3_inst.instruction |= reg_rd << 20; 5005 s3_inst.instruction |= s3_GP << 15; 5006 s3_inst.relax_inst = 0x8000; 5007 s3_inst.relax_size = 0; 5008 ldst_gp_p = 1; 5009 } 5010 } 5011 } 5012 5013 /* Backup s3_inst. */ 5014 memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); 5015 r1_bak = s3_nor1; 5016 s3_nor1 = 0; 5017 5018 /* Determine which instructions should be output. */ 5019 sprintf (append_str[0], "ld_i32hi r1, %s", label_str); 5020 sprintf (append_str[1], "ld_i32lo r1, %s", label_str); 5021 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd); 5022 5023 /* Generate three instructions. 5024 la r1, label 5025 ld/st rd, [r1, 0] */ 5026 for (i = 0; i < 3; i++) 5027 { 5028 if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL) 5029 return; 5030 5031 memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it)); 5032 } 5033 5034 if (ldst_gp_p) 5035 { 5036 char *p; 5037 5038 /* Adjust instruction opcode and to be relaxed instruction opcode. */ 5039 inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); 5040 5041 /* relax lw rd, label -> ldis rs, imm16 5042 ori rd, imm16 5043 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ 5044 if (inst_expand[2].relax_size == 0) 5045 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; 5046 else 5047 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size; 5048 5049 inst_main.type = Insn_GP; 5050 5051 for (i = 0; i < 3; i++) 5052 inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, 5053 s3_GET_INSN_CLASS (inst_expand[i].type)); 5054 5055 /* Check data dependency. */ 5056 s3_handle_dependency (&inst_main); 5057 5058 /* Start a new frag if frag_now is not empty. */ 5059 if (frag_now_fix () != 0) 5060 { 5061 if (!frag_now->tc_frag_data.is_insn) 5062 frag_wane (frag_now); 5063 5064 frag_new (0); 5065 } 5066 frag_grow (20); 5067 5068 /* Write fr_fix part. */ 5069 p = frag_more (inst_main.size); 5070 s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); 5071 5072 if (inst_main.reloc.type != BFD_RELOC_NONE) 5073 { 5074 s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 5075 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 5076 } 5077 5078 #ifdef OBJ_ELF 5079 dwarf2_emit_insn (inst_main.size); 5080 #endif 5081 5082 /* s3_GP instruction can not do optimization, only can do relax between 5083 1 instruction and 3 instructions. */ 5084 p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, 5085 s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), 5086 inst_main.reloc.exp.X_add_symbol, 0, NULL); 5087 5088 /* Write fr_var part. 5089 no calling s3_gen_insn_frag, no fixS will be generated. */ 5090 s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 5091 p += inst_expand[0].size; 5092 s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 5093 p += inst_expand[1].size; 5094 5095 /* relax lw rd, label -> ldis rs, imm16 5096 ori rd, imm16 5097 lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ 5098 if (inst_expand[2].relax_size == 0) 5099 s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); 5100 else 5101 s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size); 5102 } 5103 else 5104 { 5105 s3_gen_insn_frag (&inst_expand[0], NULL); 5106 s3_gen_insn_frag (&inst_expand[1], NULL); 5107 s3_gen_insn_frag (&inst_expand[2], NULL); 5108 } 5109 s3_nor1 = r1_bak; 5110 5111 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 5112 s3_inst.bwarn = -1; 5113 } 5114 5115 static void 5116 s3_do_lw_pic (char *str) 5117 { 5118 int reg_rd; 5119 5120 s3_skip_whitespace (str); 5121 if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 5122 || (s3_skip_past_comma (&str) == (int) s3_FAIL) 5123 || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) 5124 || (s3_end_of_line (str) == (int) s3_FAIL)) 5125 { 5126 return; 5127 } 5128 else 5129 { 5130 if (s3_inst.reloc.exp.X_add_symbol == 0) 5131 { 5132 if (!s3_inst.error) 5133 s3_inst.error = s3_BAD_ARGS; 5134 5135 return; 5136 } 5137 5138 s3_inst.instruction |= s3_GP << 15; 5139 s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; 5140 } 5141 } 5142 5143 static void 5144 s3_do_empty (char *str) 5145 { 5146 str = str; 5147 if (s3_university_version == 1) 5148 { 5149 if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004) 5150 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024) 5151 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044) 5152 || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064)) 5153 { 5154 s3_inst.error = s3_ERR_FOR_SCORE5U_MMU; 5155 return; 5156 } 5157 } 5158 if (s3_end_of_line (str) == (int) s3_FAIL) 5159 return; 5160 5161 if (s3_inst.relax_inst != 0x8000) 5162 { 5163 if (s3_inst.type == NO_OPD) 5164 { 5165 s3_inst.relax_size = 2; 5166 } 5167 else 5168 { 5169 s3_inst.relax_size = 4; 5170 } 5171 } 5172 } 5173 5174 static void 5175 s3_do16_int (char *str) 5176 { 5177 s3_skip_whitespace (str); 5178 return; 5179 } 5180 5181 static void 5182 s3_do_jump (char *str) 5183 { 5184 char *save_in; 5185 5186 s3_skip_whitespace (str); 5187 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5188 || s3_end_of_line (str) == (int) s3_FAIL) 5189 return; 5190 5191 if (s3_inst.reloc.exp.X_add_symbol == 0) 5192 { 5193 s3_inst.error = _("lacking label "); 5194 return; 5195 } 5196 5197 if (!(s3_inst.reloc.exp.X_add_number >= -16777216 5198 && s3_inst.reloc.exp.X_add_number <= 16777215)) 5199 { 5200 s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]"); 5201 return; 5202 } 5203 5204 save_in = input_line_pointer; 5205 input_line_pointer = str; 5206 s3_inst.reloc.type = BFD_RELOC_SCORE_JMP; 5207 s3_inst.reloc.pc_rel = 1; 5208 input_line_pointer = save_in; 5209 } 5210 5211 static void 5212 s3_do_branch (char *str) 5213 { 5214 if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5215 || s3_end_of_line (str) == (int) s3_FAIL) 5216 { 5217 return; 5218 } 5219 else if (s3_inst.reloc.exp.X_add_symbol == 0) 5220 { 5221 s3_inst.error = _("lacking label "); 5222 return; 5223 } 5224 else if (!(s3_inst.reloc.exp.X_add_number >= -524288 5225 && s3_inst.reloc.exp.X_add_number <= 524287)) 5226 { 5227 s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19-1"); 5228 return; 5229 } 5230 5231 s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH; 5232 s3_inst.reloc.pc_rel = 1; 5233 5234 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 5235 s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5); 5236 5237 /* Compute 16 bit branch instruction. */ 5238 if ((s3_inst.relax_inst != 0x8000) 5239 && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511)) 5240 { 5241 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */ 5242 s3_inst.relax_size = 2; 5243 } 5244 else 5245 { 5246 s3_inst.relax_inst = 0x8000; 5247 } 5248 } 5249 5250 static void 5251 s3_do16_branch (char *str) 5252 { 5253 if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL 5254 || s3_end_of_line (str) == (int) s3_FAIL)) 5255 { 5256 ; 5257 } 5258 else if (s3_inst.reloc.exp.X_add_symbol == 0) 5259 { 5260 s3_inst.error = _("lacking label"); 5261 } 5262 else if (!(s3_inst.reloc.exp.X_add_number >= -512 5263 && s3_inst.reloc.exp.X_add_number <= 511)) 5264 { 5265 s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]"); 5266 } 5267 else 5268 { 5269 s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; 5270 s3_inst.reloc.pc_rel = 1; 5271 s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff); 5272 s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff); 5273 s3_inst.relax_size = 4; 5274 } 5275 } 5276 5277 /* Return true if the given symbol should be considered local for s3_PIC. */ 5278 static bfd_boolean 5279 s3_pic_need_relax (symbolS *sym, asection *segtype) 5280 { 5281 asection *symsec; 5282 bfd_boolean linkonce; 5283 5284 /* Handle the case of a symbol equated to another symbol. */ 5285 while (symbol_equated_reloc_p (sym)) 5286 { 5287 symbolS *n; 5288 5289 /* It's possible to get a loop here in a badly written 5290 program. */ 5291 n = symbol_get_value_expression (sym)->X_add_symbol; 5292 if (n == sym) 5293 break; 5294 sym = n; 5295 } 5296 5297 symsec = S_GET_SEGMENT (sym); 5298 5299 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ 5300 linkonce = FALSE; 5301 if (symsec != segtype && ! S_IS_LOCAL (sym)) 5302 { 5303 if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0) 5304 linkonce = TRUE; 5305 5306 /* The GNU toolchain uses an extension for ELF: a section 5307 beginning with the magic string .gnu.linkonce is a linkonce 5308 section. */ 5309 if (strncmp (segment_name (symsec), ".gnu.linkonce", 5310 sizeof ".gnu.linkonce" - 1) == 0) 5311 linkonce = TRUE; 5312 } 5313 5314 /* This must duplicate the test in adjust_reloc_syms. */ 5315 return (!bfd_is_und_section (symsec) 5316 && !bfd_is_abs_section (symsec) 5317 && !bfd_is_com_section (symsec) 5318 && !linkonce 5319 #ifdef OBJ_ELF 5320 /* A global or weak symbol is treated as external. */ 5321 && (OUTPUT_FLAVOR != bfd_target_elf_flavour 5322 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) 5323 #endif 5324 ); 5325 } 5326 5327 static void 5328 s3_parse_pce_inst (char *insnstr) 5329 { 5330 char c; 5331 char *p; 5332 char first[s3_MAX_LITERAL_POOL_SIZE]; 5333 char second[s3_MAX_LITERAL_POOL_SIZE]; 5334 struct s3_score_it pec_part_1; 5335 5336 /* Get first part string of PCE. */ 5337 p = strstr (insnstr, "||"); 5338 c = *p; 5339 *p = '\0'; 5340 sprintf (first, "%s", insnstr); 5341 5342 /* Get second part string of PCE. */ 5343 *p = c; 5344 p += 2; 5345 sprintf (second, "%s", p); 5346 5347 s3_parse_16_32_inst (first, FALSE); 5348 if (s3_inst.error) 5349 return; 5350 5351 memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst)); 5352 5353 s3_parse_16_32_inst (second, FALSE); 5354 if (s3_inst.error) 5355 return; 5356 5357 if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE)) 5358 || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE)) 5359 || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE))) 5360 { 5361 s3_inst.error = _("pce instruction error (16 bit || 16 bit)."); 5362 sprintf (s3_inst.str, "%s", insnstr); 5363 return; 5364 } 5365 5366 if (!s3_inst.error) 5367 s3_gen_insn_frag (&pec_part_1, &s3_inst); 5368 } 5369 5370 /* s3: dsp. */ 5371 static void 5372 s3_do16_dsp (char *str) 5373 { 5374 int rd = 0; 5375 5376 /* Check 3d. */ 5377 if (s3_score3d == 0) 5378 { 5379 s3_inst.error = _("score3d instruction."); 5380 return; 5381 } 5382 5383 s3_skip_whitespace (str); 5384 5385 if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL 5386 || s3_end_of_line (str) == (int) s3_FAIL) 5387 { 5388 return; 5389 } 5390 else 5391 { 5392 s3_inst.relax_inst |= rd << 20; 5393 s3_inst.relax_size = 4; 5394 } 5395 } 5396 5397 static void 5398 s3_do16_dsp2 (char *str) 5399 { 5400 /* Check 3d. */ 5401 if (s3_score3d == 0) 5402 { 5403 s3_inst.error = _("score3d instruction."); 5404 return; 5405 } 5406 5407 s3_skip_whitespace (str); 5408 5409 if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL 5410 || s3_skip_past_comma (&str) == (int) s3_FAIL 5411 || s3_reglow_required_here (&str, 0) == (int) s3_FAIL 5412 || s3_end_of_line (str) == (int) s3_FAIL) 5413 { 5414 return; 5415 } 5416 else 5417 { 5418 s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20) 5419 | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10); 5420 s3_inst.relax_size = 4; 5421 } 5422 } 5423 5424 static void 5425 s3_do_dsp (char *str) 5426 { 5427 /* Check 3d. */ 5428 if (s3_score3d == 0) 5429 { 5430 s3_inst.error = _("score3d instruction."); 5431 return; 5432 } 5433 5434 s3_skip_whitespace (str); 5435 5436 if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5437 || s3_skip_past_comma (&str) == (int) s3_FAIL 5438 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5439 || s3_end_of_line (str) == (int) s3_FAIL) 5440 return; 5441 5442 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) 5443 { 5444 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); 5445 s3_inst.relax_size = 2; 5446 } 5447 else 5448 s3_inst.relax_inst = 0x8000; 5449 } 5450 5451 static void 5452 s3_do_dsp2 (char *str) 5453 { 5454 int reg; 5455 5456 /* Check 3d. */ 5457 if (s3_score3d == 0) 5458 { 5459 s3_inst.error = _("score3d instruction."); 5460 return; 5461 } 5462 5463 s3_skip_whitespace (str); 5464 5465 if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 5466 || s3_skip_past_comma (&str) == (int) s3_FAIL 5467 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5468 || s3_skip_past_comma (&str) == (int) s3_FAIL 5469 || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5470 || s3_end_of_line (str) == (int) s3_FAIL) 5471 { 5472 return; 5473 } 5474 else 5475 { 5476 /* Check mulr, mulur rd is even number. */ 5477 if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340 5478 || (s3_inst.instruction & 0x3e0003ff) == 0x00000342) 5479 && (reg % 2)) 5480 { 5481 s3_inst.error = _("rd must be even number."); 5482 return; 5483 } 5484 5485 if ((((s3_inst.instruction >> 15) & 0x10) == 0) 5486 && (((s3_inst.instruction >> 10) & 0x10) == 0) 5487 && (((s3_inst.instruction >> 20) & 0x10) == 0) 5488 && (s3_inst.relax_inst != 0x8000) 5489 && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf))) 5490 { 5491 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) ) 5492 | (((s3_inst.instruction >> 15) & 0xf) << 4); 5493 s3_inst.relax_size = 2; 5494 } 5495 else 5496 { 5497 s3_inst.relax_inst = 0x8000; 5498 } 5499 } 5500 } 5501 5502 static void 5503 s3_do_dsp3 (char *str) 5504 { 5505 /* Check 3d. */ 5506 if (s3_score3d == 0) 5507 { 5508 s3_inst.error = _("score3d instruction."); 5509 return; 5510 } 5511 5512 s3_skip_whitespace (str); 5513 5514 if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5515 || s3_skip_past_comma (&str) == (int) s3_FAIL 5516 || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL 5517 || s3_end_of_line (str) == (int) s3_FAIL) 5518 return; 5519 5520 if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) 5521 { 5522 s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); 5523 s3_inst.relax_size = 2; 5524 } 5525 else 5526 s3_inst.relax_inst = 0x8000; 5527 } 5528 5529 5530 /* If we change section we must dump the literal pool first. */ 5531 static void 5532 s3_s_score_bss (int ignore ATTRIBUTE_UNUSED) 5533 { 5534 subseg_set (bss_section, (subsegT) get_absolute_expression ()); 5535 demand_empty_rest_of_line (); 5536 } 5537 5538 static void 5539 s3_s_score_text (int ignore) 5540 { 5541 obj_elf_text (ignore); 5542 record_alignment (now_seg, 2); 5543 } 5544 5545 static void 5546 s3_score_s_section (int ignore) 5547 { 5548 obj_elf_section (ignore); 5549 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5550 record_alignment (now_seg, 2); 5551 5552 } 5553 5554 static void 5555 s3_s_change_sec (int sec) 5556 { 5557 segT seg; 5558 5559 #ifdef OBJ_ELF 5560 /* The ELF backend needs to know that we are changing sections, so 5561 that .previous works correctly. We could do something like check 5562 for an obj_section_change_hook macro, but that might be confusing 5563 as it would not be appropriate to use it in the section changing 5564 functions in read.c, since obj-elf.c intercepts those. FIXME: 5565 This should be cleaner, somehow. */ 5566 obj_elf_section_change_hook (); 5567 #endif 5568 switch (sec) 5569 { 5570 case 'r': 5571 seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); 5572 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA)); 5573 if (strcmp (TARGET_OS, "elf") != 0) 5574 record_alignment (seg, 4); 5575 demand_empty_rest_of_line (); 5576 break; 5577 case 's': 5578 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); 5579 bfd_set_section_flags (seg, SEC_ALLOC | SEC_LOAD | 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 } 5585 } 5586 5587 static void 5588 s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED) 5589 { 5590 long mask, off; 5591 5592 if (s3_cur_proc_ptr == (s3_procS *) NULL) 5593 { 5594 as_warn (_(".mask outside of .ent")); 5595 demand_empty_rest_of_line (); 5596 return; 5597 } 5598 if (get_absolute_expression_and_terminator (&mask) != ',') 5599 { 5600 as_warn (_("Bad .mask directive")); 5601 --input_line_pointer; 5602 demand_empty_rest_of_line (); 5603 return; 5604 } 5605 off = get_absolute_expression (); 5606 s3_cur_proc_ptr->reg_mask = mask; 5607 s3_cur_proc_ptr->reg_offset = off; 5608 demand_empty_rest_of_line (); 5609 } 5610 5611 static symbolS * 5612 s3_get_symbol (void) 5613 { 5614 int c; 5615 char *name; 5616 symbolS *p; 5617 5618 c = get_symbol_name (&name); 5619 p = (symbolS *) symbol_find_or_make (name); 5620 (void) restore_line_pointer (c); 5621 return p; 5622 } 5623 5624 static long 5625 s3_get_number (void) 5626 { 5627 int negative = 0; 5628 long val = 0; 5629 5630 if (*input_line_pointer == '-') 5631 { 5632 ++input_line_pointer; 5633 negative = 1; 5634 } 5635 if (!ISDIGIT (*input_line_pointer)) 5636 as_bad (_("expected simple number")); 5637 if (input_line_pointer[0] == '0') 5638 { 5639 if (input_line_pointer[1] == 'x') 5640 { 5641 input_line_pointer += 2; 5642 while (ISXDIGIT (*input_line_pointer)) 5643 { 5644 val <<= 4; 5645 val |= hex_value (*input_line_pointer++); 5646 } 5647 return negative ? -val : val; 5648 } 5649 else 5650 { 5651 ++input_line_pointer; 5652 while (ISDIGIT (*input_line_pointer)) 5653 { 5654 val <<= 3; 5655 val |= *input_line_pointer++ - '0'; 5656 } 5657 return negative ? -val : val; 5658 } 5659 } 5660 if (!ISDIGIT (*input_line_pointer)) 5661 { 5662 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); 5663 as_warn (_("invalid number")); 5664 return -1; 5665 } 5666 while (ISDIGIT (*input_line_pointer)) 5667 { 5668 val *= 10; 5669 val += *input_line_pointer++ - '0'; 5670 } 5671 return negative ? -val : val; 5672 } 5673 5674 /* The .aent and .ent directives. */ 5675 static void 5676 s3_s_score_ent (int aent) 5677 { 5678 symbolS *symbolP; 5679 int maybe_text; 5680 5681 symbolP = s3_get_symbol (); 5682 if (*input_line_pointer == ',') 5683 ++input_line_pointer; 5684 SKIP_WHITESPACE (); 5685 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') 5686 s3_get_number (); 5687 5688 #ifdef BFD_ASSEMBLER 5689 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5690 maybe_text = 1; 5691 else 5692 maybe_text = 0; 5693 #else 5694 if (now_seg != data_section && now_seg != bss_section) 5695 maybe_text = 1; 5696 else 5697 maybe_text = 0; 5698 #endif 5699 if (!maybe_text) 5700 as_warn (_(".ent or .aent not in text section.")); 5701 if (!aent && s3_cur_proc_ptr) 5702 as_warn (_("missing .end")); 5703 if (!aent) 5704 { 5705 s3_cur_proc_ptr = &s3_cur_proc; 5706 s3_cur_proc_ptr->reg_mask = 0xdeadbeaf; 5707 s3_cur_proc_ptr->reg_offset = 0xdeadbeaf; 5708 s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf; 5709 s3_cur_proc_ptr->leaf = 0xdeafbeaf; 5710 s3_cur_proc_ptr->frame_offset = 0xdeafbeaf; 5711 s3_cur_proc_ptr->frame_reg = 0xdeafbeaf; 5712 s3_cur_proc_ptr->pc_reg = 0xdeafbeaf; 5713 s3_cur_proc_ptr->isym = symbolP; 5714 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; 5715 ++s3_numprocs; 5716 if (debug_type == DEBUG_STABS) 5717 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); 5718 } 5719 demand_empty_rest_of_line (); 5720 } 5721 5722 static void 5723 s3_s_score_frame (int ignore ATTRIBUTE_UNUSED) 5724 { 5725 char *backupstr; 5726 char str[30]; 5727 long val; 5728 int i = 0; 5729 5730 backupstr = input_line_pointer; 5731 5732 #ifdef OBJ_ELF 5733 if (s3_cur_proc_ptr == (s3_procS *) NULL) 5734 { 5735 as_warn (_(".frame outside of .ent")); 5736 demand_empty_rest_of_line (); 5737 return; 5738 } 5739 s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); 5740 SKIP_WHITESPACE (); 5741 s3_skip_past_comma (&backupstr); 5742 while (*backupstr != ',') 5743 { 5744 str[i] = *backupstr; 5745 i++; 5746 backupstr++; 5747 } 5748 str[i] = '\0'; 5749 val = atoi (str); 5750 5751 SKIP_WHITESPACE (); 5752 s3_skip_past_comma (&backupstr); 5753 s3_cur_proc_ptr->frame_offset = val; 5754 s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); 5755 5756 SKIP_WHITESPACE (); 5757 s3_skip_past_comma (&backupstr); 5758 i = 0; 5759 while (*backupstr != '\n') 5760 { 5761 str[i] = *backupstr; 5762 i++; 5763 backupstr++; 5764 } 5765 str[i] = '\0'; 5766 val = atoi (str); 5767 s3_cur_proc_ptr->leaf = val; 5768 SKIP_WHITESPACE (); 5769 s3_skip_past_comma (&backupstr); 5770 5771 #endif /* OBJ_ELF */ 5772 while (input_line_pointer != backupstr) 5773 input_line_pointer++; 5774 } 5775 5776 /* The .end directive. */ 5777 static void 5778 s3_s_score_end (int x ATTRIBUTE_UNUSED) 5779 { 5780 symbolS *p; 5781 int maybe_text; 5782 5783 /* Generate a .pdr section. */ 5784 segT saved_seg = now_seg; 5785 subsegT saved_subseg = now_subseg; 5786 expressionS exp; 5787 char *fragp; 5788 5789 if (!is_end_of_line[(unsigned char)*input_line_pointer]) 5790 { 5791 p = s3_get_symbol (); 5792 demand_empty_rest_of_line (); 5793 } 5794 else 5795 p = NULL; 5796 5797 #ifdef BFD_ASSEMBLER 5798 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0) 5799 maybe_text = 1; 5800 else 5801 maybe_text = 0; 5802 #else 5803 if (now_seg != data_section && now_seg != bss_section) 5804 maybe_text = 1; 5805 else 5806 maybe_text = 0; 5807 #endif 5808 5809 if (!maybe_text) 5810 as_warn (_(".end not in text section")); 5811 if (!s3_cur_proc_ptr) 5812 { 5813 as_warn (_(".end directive without a preceding .ent directive.")); 5814 demand_empty_rest_of_line (); 5815 return; 5816 } 5817 if (p != NULL) 5818 { 5819 gas_assert (S_GET_NAME (p)); 5820 if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym))) 5821 as_warn (_(".end symbol does not match .ent symbol.")); 5822 if (debug_type == DEBUG_STABS) 5823 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); 5824 } 5825 else 5826 as_warn (_(".end directive missing or unknown symbol")); 5827 5828 if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) || 5829 (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) || 5830 (s3_cur_proc_ptr->leaf == 0xdeafbeaf) || 5831 (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) || 5832 (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf)); 5833 5834 else 5835 { 5836 (void) frag_now_fix (); 5837 gas_assert (s3_pdr_seg); 5838 subseg_set (s3_pdr_seg, 0); 5839 /* Write the symbol. */ 5840 exp.X_op = O_symbol; 5841 exp.X_add_symbol = p; 5842 exp.X_add_number = 0; 5843 emit_expr (&exp, 4); 5844 fragp = frag_more (7 * 4); 5845 md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4); 5846 md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4); 5847 md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4); 5848 md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4); 5849 md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4); 5850 md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4); 5851 md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4); 5852 subseg_set (saved_seg, saved_subseg); 5853 5854 } 5855 s3_cur_proc_ptr = NULL; 5856 } 5857 5858 /* Handle the .set pseudo-op. */ 5859 static void 5860 s3_s_score_set (int x ATTRIBUTE_UNUSED) 5861 { 5862 int i = 0; 5863 char name[s3_MAX_LITERAL_POOL_SIZE]; 5864 char * orig_ilp = input_line_pointer; 5865 5866 while (!is_end_of_line[(unsigned char)*input_line_pointer]) 5867 { 5868 name[i] = (char) * input_line_pointer; 5869 i++; 5870 ++input_line_pointer; 5871 } 5872 5873 name[i] = '\0'; 5874 5875 if (strcmp (name, "nwarn") == 0) 5876 { 5877 s3_warn_fix_data_dependency = 0; 5878 } 5879 else if (strcmp (name, "fixdd") == 0) 5880 { 5881 s3_fix_data_dependency = 1; 5882 } 5883 else if (strcmp (name, "nofixdd") == 0) 5884 { 5885 s3_fix_data_dependency = 0; 5886 } 5887 else if (strcmp (name, "r1") == 0) 5888 { 5889 s3_nor1 = 0; 5890 } 5891 else if (strcmp (name, "nor1") == 0) 5892 { 5893 s3_nor1 = 1; 5894 } 5895 else if (strcmp (name, "optimize") == 0) 5896 { 5897 s3_g_opt = 1; 5898 } 5899 else if (strcmp (name, "volatile") == 0) 5900 { 5901 s3_g_opt = 0; 5902 } 5903 else if (strcmp (name, "pic") == 0) 5904 { 5905 s3_score_pic = s3_PIC; 5906 } 5907 else 5908 { 5909 input_line_pointer = orig_ilp; 5910 s_set (0); 5911 } 5912 } 5913 5914 /* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the 5915 $gp register for the function based on the function address, which is in the register 5916 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled 5917 specially by the linker. The result is: 5918 ldis gp, %hi(GP_DISP_LABEL) 5919 ori gp, %low(GP_DISP_LABEL) 5920 add gp, gp, .cpload argument 5921 The .cpload argument is normally r29. */ 5922 static void 5923 s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED) 5924 { 5925 int reg; 5926 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 5927 5928 /* If we are not generating s3_PIC code, .cpload is ignored. */ 5929 if (s3_score_pic == s3_NO_PIC) 5930 { 5931 s_ignore (0); 5932 return; 5933 } 5934 5935 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 5936 return; 5937 5938 demand_empty_rest_of_line (); 5939 5940 sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL); 5941 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5942 return; 5943 5944 sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL); 5945 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5946 return; 5947 5948 sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg); 5949 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5950 return; 5951 } 5952 5953 /* Handle the .cprestore pseudo-op. This stores $gp into a given 5954 offset from $sp. The offset is remembered, and after making a s3_PIC 5955 call $gp is restored from that location. */ 5956 static void 5957 s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED) 5958 { 5959 int reg; 5960 int cprestore_offset; 5961 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 5962 5963 /* If we are not generating s3_PIC code, .cprestore is ignored. */ 5964 if (s3_score_pic == s3_NO_PIC) 5965 { 5966 s_ignore (0); 5967 return; 5968 } 5969 5970 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL 5971 || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL) 5972 { 5973 return; 5974 } 5975 5976 cprestore_offset = get_absolute_expression (); 5977 5978 if (cprestore_offset <= 0x3fff) 5979 { 5980 sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset); 5981 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5982 return; 5983 } 5984 else 5985 { 5986 int r1_bak; 5987 5988 r1_bak = s3_nor1; 5989 s3_nor1 = 0; 5990 5991 sprintf (insn_str, "li r1, %d", cprestore_offset); 5992 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5993 return; 5994 5995 sprintf (insn_str, "add r1, r1, r%d", reg); 5996 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 5997 return; 5998 5999 sprintf (insn_str, "sw r%d, [r1]", s3_GP); 6000 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 6001 return; 6002 6003 s3_nor1 = r1_bak; 6004 } 6005 6006 demand_empty_rest_of_line (); 6007 } 6008 6009 /* Handle the .gpword pseudo-op. This is used when generating s3_PIC 6010 code. It generates a 32 bit s3_GP relative reloc. */ 6011 static void 6012 s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED) 6013 { 6014 expressionS ex; 6015 char *p; 6016 6017 /* When not generating s3_PIC code, this is treated as .word. */ 6018 if (s3_score_pic == s3_NO_PIC) 6019 { 6020 cons (4); 6021 return; 6022 } 6023 expression (&ex); 6024 if (ex.X_op != O_symbol || ex.X_add_number != 0) 6025 { 6026 as_bad (_("Unsupported use of .gpword")); 6027 ignore_rest_of_line (); 6028 } 6029 p = frag_more (4); 6030 s3_md_number_to_chars (p, (valueT) 0, 4); 6031 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32); 6032 demand_empty_rest_of_line (); 6033 } 6034 6035 /* Handle the .cpadd pseudo-op. This is used when dealing with switch 6036 tables in s3_PIC code. */ 6037 static void 6038 s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED) 6039 { 6040 int reg; 6041 char insn_str[s3_MAX_LITERAL_POOL_SIZE]; 6042 6043 /* If we are not generating s3_PIC code, .cpload is ignored. */ 6044 if (s3_score_pic == s3_NO_PIC) 6045 { 6046 s_ignore (0); 6047 return; 6048 } 6049 6050 if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) 6051 { 6052 return; 6053 } 6054 demand_empty_rest_of_line (); 6055 6056 /* Add $gp to the register named as an argument. */ 6057 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP); 6058 if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) 6059 return; 6060 } 6061 6062 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 6063 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 6064 do \ 6065 { \ 6066 if ((SIZE) >= 8) \ 6067 (P2VAR) = 3; \ 6068 else if ((SIZE) >= 4) \ 6069 (P2VAR) = 2; \ 6070 else if ((SIZE) >= 2) \ 6071 (P2VAR) = 1; \ 6072 else \ 6073 (P2VAR) = 0; \ 6074 } \ 6075 while (0) 6076 #endif 6077 6078 static void 6079 s3_s_score_lcomm (int bytes_p) 6080 { 6081 char *name; 6082 char c; 6083 char *p; 6084 int temp; 6085 symbolS *symbolP; 6086 segT current_seg = now_seg; 6087 subsegT current_subseg = now_subseg; 6088 const int max_alignment = 15; 6089 int align = 0; 6090 segT bss_seg = bss_section; 6091 int needs_align = 0; 6092 6093 c = get_symbol_name (&name); 6094 p = input_line_pointer; 6095 (void) restore_line_pointer (c); 6096 6097 if (name == p) 6098 { 6099 as_bad (_("expected symbol name")); 6100 discard_rest_of_line (); 6101 return; 6102 } 6103 6104 SKIP_WHITESPACE (); 6105 6106 /* Accept an optional comma after the name. The comma used to be 6107 required, but Irix 5 cc does not generate it. */ 6108 if (*input_line_pointer == ',') 6109 { 6110 ++input_line_pointer; 6111 SKIP_WHITESPACE (); 6112 } 6113 6114 if (is_end_of_line[(unsigned char)*input_line_pointer]) 6115 { 6116 as_bad (_("missing size expression")); 6117 return; 6118 } 6119 6120 if ((temp = get_absolute_expression ()) < 0) 6121 { 6122 as_warn (_("BSS length (%d) < 0 ignored"), temp); 6123 ignore_rest_of_line (); 6124 return; 6125 } 6126 6127 #if defined (TC_SCORE) 6128 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) 6129 { 6130 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ 6131 if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) 6132 { 6133 bss_seg = subseg_new (".sbss", 1); 6134 seg_info (bss_seg)->bss = 1; 6135 #ifdef BFD_ASSEMBLER 6136 if (!bfd_set_section_flags (bss_seg, SEC_ALLOC)) 6137 as_warn (_("error setting flags for \".sbss\": %s"), 6138 bfd_errmsg (bfd_get_error ())); 6139 #endif 6140 } 6141 } 6142 #endif 6143 6144 SKIP_WHITESPACE (); 6145 if (*input_line_pointer == ',') 6146 { 6147 ++input_line_pointer; 6148 SKIP_WHITESPACE (); 6149 6150 if (is_end_of_line[(unsigned char)*input_line_pointer]) 6151 { 6152 as_bad (_("missing alignment")); 6153 return; 6154 } 6155 else 6156 { 6157 align = get_absolute_expression (); 6158 needs_align = 1; 6159 } 6160 } 6161 6162 if (!needs_align) 6163 { 6164 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); 6165 6166 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ 6167 if (align) 6168 record_alignment (bss_seg, align); 6169 } 6170 6171 if (needs_align) 6172 { 6173 if (bytes_p) 6174 { 6175 /* Convert to a power of 2. */ 6176 if (align != 0) 6177 { 6178 unsigned int i; 6179 6180 for (i = 0; align != 0; align >>= 1, ++i) 6181 ; 6182 align = i - 1; 6183 } 6184 } 6185 6186 if (align > max_alignment) 6187 { 6188 align = max_alignment; 6189 as_warn (_("alignment too large; %d assumed"), align); 6190 } 6191 else if (align < 0) 6192 { 6193 align = 0; 6194 as_warn (_("alignment negative; 0 assumed")); 6195 } 6196 6197 record_alignment (bss_seg, align); 6198 } 6199 else 6200 { 6201 /* Assume some objects may require alignment on some systems. */ 6202 #if defined (TC_ALPHA) && ! defined (VMS) 6203 if (temp > 1) 6204 { 6205 align = ffs (temp) - 1; 6206 if (temp % (1 << align)) 6207 abort (); 6208 } 6209 #endif 6210 } 6211 6212 *p = 0; 6213 symbolP = symbol_find_or_make (name); 6214 *p = c; 6215 6216 if ( 6217 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)) 6218 #ifdef BFD_ASSEMBLER 6219 (OUTPUT_FLAVOR != bfd_target_aout_flavour 6220 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && 6221 #else 6222 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && 6223 #endif 6224 #endif 6225 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) 6226 { 6227 char *pfrag; 6228 6229 subseg_set (bss_seg, 1); 6230 6231 if (align) 6232 frag_align (align, 0, 0); 6233 6234 /* Detach from old frag. */ 6235 if (S_GET_SEGMENT (symbolP) == bss_seg) 6236 symbol_get_frag (symbolP)->fr_symbol = NULL; 6237 6238 symbol_set_frag (symbolP, frag_now); 6239 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); 6240 *pfrag = 0; 6241 6242 6243 S_SET_SEGMENT (symbolP, bss_seg); 6244 6245 #ifdef OBJ_COFF 6246 /* The symbol may already have been created with a preceding 6247 ".globl" directive -- be careful not to step on storage class 6248 in that case. Otherwise, set it to static. */ 6249 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 6250 { 6251 S_SET_STORAGE_CLASS (symbolP, C_STAT); 6252 } 6253 #endif /* OBJ_COFF */ 6254 6255 #ifdef S_SET_SIZE 6256 S_SET_SIZE (symbolP, temp); 6257 #endif 6258 } 6259 else 6260 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 6261 6262 subseg_set (current_seg, current_subseg); 6263 6264 demand_empty_rest_of_line (); 6265 } 6266 6267 static void 6268 s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab) 6269 { 6270 int i = 0; 6271 int len = strlen (r->name) + 2; 6272 char *buf = XNEWVEC (char, len); 6273 char *buf2 = XNEWVEC (char, len); 6274 6275 strcpy (buf + i, r->name); 6276 for (i = 0; buf[i]; i++) 6277 { 6278 buf2[i] = TOUPPER (buf[i]); 6279 } 6280 buf2[i] = '\0'; 6281 6282 hash_insert (htab, buf, (void *) r); 6283 hash_insert (htab, buf2, (void *) r); 6284 } 6285 6286 static void 6287 s3_build_reg_hsh (struct s3_reg_map *map) 6288 { 6289 const struct s3_reg_entry *r; 6290 6291 if ((map->htab = hash_new ()) == NULL) 6292 { 6293 as_fatal (_("virtual memory exhausted")); 6294 } 6295 for (r = map->names; r->name != NULL; r++) 6296 { 6297 s3_insert_reg (r, map->htab); 6298 } 6299 } 6300 6301 /* Iterate over the base tables to create the instruction patterns. */ 6302 static void 6303 s3_build_score_ops_hsh (void) 6304 { 6305 unsigned int i; 6306 static struct obstack insn_obstack; 6307 6308 obstack_begin (&insn_obstack, 4000); 6309 for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++) 6310 { 6311 const struct s3_asm_opcode *insn = s3_score_insns + i; 6312 size_t len = strlen (insn->template_name); 6313 struct s3_asm_opcode *new_opcode; 6314 char *template_name; 6315 new_opcode = (struct s3_asm_opcode *) 6316 obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode)); 6317 template_name = (char *) obstack_alloc (& insn_obstack, len + 1); 6318 6319 strcpy (template_name, insn->template_name); 6320 new_opcode->template_name = template_name; 6321 new_opcode->parms = insn->parms; 6322 new_opcode->value = insn->value; 6323 new_opcode->relax_value = insn->relax_value; 6324 new_opcode->type = insn->type; 6325 new_opcode->bitmask = insn->bitmask; 6326 hash_insert (s3_score_ops_hsh, new_opcode->template_name, 6327 (void *) new_opcode); 6328 } 6329 } 6330 6331 static void 6332 s3_build_dependency_insn_hsh (void) 6333 { 6334 unsigned int i; 6335 static struct obstack dependency_obstack; 6336 6337 obstack_begin (&dependency_obstack, 4000); 6338 for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++) 6339 { 6340 const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i; 6341 size_t len = strlen (tmp->insn_name); 6342 struct s3_insn_to_dependency *new_i2n; 6343 char *buf; 6344 6345 new_i2n = (struct s3_insn_to_dependency *) 6346 obstack_alloc (&dependency_obstack, 6347 sizeof (struct s3_insn_to_dependency)); 6348 buf = (char *) obstack_alloc (&dependency_obstack, len + 1); 6349 6350 strcpy (buf, tmp->insn_name); 6351 new_i2n->insn_name = buf; 6352 new_i2n->type = tmp->type; 6353 hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name, 6354 (void *) new_i2n); 6355 } 6356 } 6357 6358 static void 6359 s_score_bss (int ignore ATTRIBUTE_UNUSED) 6360 { 6361 if (score3) 6362 return s3_s_score_bss (ignore); 6363 else 6364 return s7_s_score_bss (ignore); 6365 } 6366 6367 static void 6368 s_score_text (int ignore) 6369 { 6370 if (score3) 6371 return s3_s_score_text (ignore); 6372 else 6373 return s7_s_score_text (ignore); 6374 } 6375 6376 static void 6377 s_section (int ignore) 6378 { 6379 if (score3) 6380 return s3_score_s_section (ignore); 6381 else 6382 return s7_s_section (ignore); 6383 } 6384 6385 static void 6386 s_change_sec (int sec) 6387 { 6388 if (score3) 6389 return s3_s_change_sec (sec); 6390 else 6391 return s7_s_change_sec (sec); 6392 } 6393 6394 static void 6395 s_score_mask (int reg_type ATTRIBUTE_UNUSED) 6396 { 6397 if (score3) 6398 return s3_s_score_mask (reg_type); 6399 else 6400 return s7_s_score_mask (reg_type); 6401 } 6402 6403 static void 6404 s_score_ent (int aent) 6405 { 6406 if (score3) 6407 return s3_s_score_ent (aent); 6408 else 6409 return s7_s_score_ent (aent); 6410 } 6411 6412 static void 6413 s_score_frame (int ignore ATTRIBUTE_UNUSED) 6414 { 6415 if (score3) 6416 return s3_s_score_frame (ignore); 6417 else 6418 return s7_s_score_frame (ignore); 6419 } 6420 6421 static void 6422 s_score_end (int x ATTRIBUTE_UNUSED) 6423 { 6424 if (score3) 6425 return s3_s_score_end (x); 6426 else 6427 return s7_s_score_end (x); 6428 } 6429 6430 static void 6431 s_score_set (int x ATTRIBUTE_UNUSED) 6432 { 6433 if (score3) 6434 return s3_s_score_set (x); 6435 else 6436 return s7_s_score_set (x); 6437 } 6438 6439 static void 6440 s_score_cpload (int ignore ATTRIBUTE_UNUSED) 6441 { 6442 if (score3) 6443 return s3_s_score_cpload (ignore); 6444 else 6445 return s7_s_score_cpload (ignore); 6446 } 6447 6448 static void 6449 s_score_cprestore (int ignore ATTRIBUTE_UNUSED) 6450 { 6451 if (score3) 6452 return s3_s_score_cprestore (ignore); 6453 else 6454 return s7_s_score_cprestore (ignore); 6455 } 6456 6457 static void 6458 s_score_gpword (int ignore ATTRIBUTE_UNUSED) 6459 { 6460 if (score3) 6461 return s3_s_score_gpword (ignore); 6462 else 6463 return s7_s_score_gpword (ignore); 6464 } 6465 6466 static void 6467 s_score_cpadd (int ignore ATTRIBUTE_UNUSED) 6468 { 6469 if (score3) 6470 return s3_s_score_cpadd (ignore); 6471 else 6472 return s7_s_score_cpadd (ignore); 6473 } 6474 6475 static void 6476 s_score_lcomm (int bytes_p) 6477 { 6478 if (score3) 6479 return s3_s_score_lcomm (bytes_p); 6480 else 6481 return s7_s_score_lcomm (bytes_p); 6482 } 6483 6484 static void 6485 s3_assemble (char *str) 6486 { 6487 know (str); 6488 know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE); 6489 6490 memset (&s3_inst, '\0', sizeof (s3_inst)); 6491 if (s3_INSN_IS_PCE_P (str)) 6492 s3_parse_pce_inst (str); 6493 else if (s3_INSN_IS_48_P (str)) 6494 s3_parse_48_inst (str, TRUE); 6495 else 6496 s3_parse_16_32_inst (str, TRUE); 6497 6498 if (s3_inst.error) 6499 as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); 6500 } 6501 6502 static void 6503 s3_operand (expressionS * exp) 6504 { 6505 if (s3_in_my_get_expression) 6506 { 6507 exp->X_op = O_illegal; 6508 if (s3_inst.error == NULL) 6509 { 6510 s3_inst.error = _("bad expression"); 6511 } 6512 } 6513 } 6514 6515 static void 6516 s3_begin (void) 6517 { 6518 unsigned int i; 6519 segT seg; 6520 subsegT subseg; 6521 6522 if ((s3_score_ops_hsh = hash_new ()) == NULL) 6523 as_fatal (_("virtual memory exhausted")); 6524 6525 s3_build_score_ops_hsh (); 6526 6527 if ((s3_dependency_insn_hsh = hash_new ()) == NULL) 6528 as_fatal (_("virtual memory exhausted")); 6529 6530 s3_build_dependency_insn_hsh (); 6531 6532 for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++) 6533 s3_build_reg_hsh (s3_all_reg_maps + i); 6534 6535 /* Initialize dependency vector. */ 6536 s3_init_dependency_vector (); 6537 6538 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 6539 seg = now_seg; 6540 subseg = now_subseg; 6541 s3_pdr_seg = subseg_new (".pdr", (subsegT) 0); 6542 bfd_set_section_flags (s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); 6543 bfd_set_section_alignment (s3_pdr_seg, 2); 6544 subseg_set (seg, subseg); 6545 6546 if (s3_USE_GLOBAL_POINTER_OPT) 6547 bfd_set_gp_size (stdoutput, s3_g_switch_value); 6548 } 6549 6550 static void 6551 s3_number_to_chars (char *buf, valueT val, int n) 6552 { 6553 if (target_big_endian) 6554 number_to_chars_bigendian (buf, val, n); 6555 else 6556 number_to_chars_littleendian (buf, val, n); 6557 } 6558 6559 static valueT 6560 s3_normal_chars_to_number (char *buf, int n) 6561 { 6562 valueT result = 0; 6563 unsigned char *where = (unsigned char *)buf; 6564 6565 if (target_big_endian) 6566 { 6567 while (n--) 6568 { 6569 result <<= 8; 6570 result |= (*where++ & 255); 6571 } 6572 } 6573 else 6574 { 6575 while (n--) 6576 { 6577 result <<= 8; 6578 result |= (where[n] & 255); 6579 } 6580 } 6581 6582 return result; 6583 } 6584 6585 static void 6586 s3_number_to_chars_littleendian (void *p, valueT data, int n) 6587 { 6588 char *buf = (char *) p; 6589 6590 switch (n) 6591 { 6592 case 4: 6593 md_number_to_chars (buf, data >> 16, 2); 6594 md_number_to_chars (buf + 2, data, 2); 6595 break; 6596 case 6: 6597 md_number_to_chars (buf, data >> 32, 2); 6598 md_number_to_chars (buf + 2, data >> 16, 2); 6599 md_number_to_chars (buf + 4, data, 2); 6600 break; 6601 default: 6602 /* Error routine. */ 6603 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); 6604 break; 6605 } 6606 } 6607 6608 static valueT 6609 s3_chars_to_number_littleendian (const void *p, int n) 6610 { 6611 char *buf = (char *) p; 6612 valueT result = 0; 6613 6614 switch (n) 6615 { 6616 case 4: 6617 result = s3_normal_chars_to_number (buf, 2) << 16; 6618 result |= s3_normal_chars_to_number (buf + 2, 2); 6619 break; 6620 case 6: 6621 result = s3_normal_chars_to_number (buf, 2) << 32; 6622 result |= s3_normal_chars_to_number (buf + 2, 2) << 16; 6623 result |= s3_normal_chars_to_number (buf + 4, 2); 6624 break; 6625 default: 6626 /* Error routine. */ 6627 as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); 6628 break; 6629 } 6630 6631 return result; 6632 } 6633 6634 static void 6635 s3_md_number_to_chars (char *buf, valueT val, int n) 6636 { 6637 if (!target_big_endian && n >= 4) 6638 s3_number_to_chars_littleendian (buf, val, n); 6639 else 6640 md_number_to_chars (buf, val, n); 6641 } 6642 6643 static valueT 6644 s3_md_chars_to_number (char *buf, int n) 6645 { 6646 valueT result = 0; 6647 6648 if (!target_big_endian && n >= 4) 6649 result = s3_chars_to_number_littleendian (buf, n); 6650 else 6651 result = s3_normal_chars_to_number (buf, n); 6652 6653 return result; 6654 } 6655 6656 static const char * 6657 s3_atof (int type, char *litP, int *sizeP) 6658 { 6659 int prec; 6660 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 6661 char *t; 6662 int i; 6663 6664 switch (type) 6665 { 6666 case 'f': 6667 case 'F': 6668 case 's': 6669 case 'S': 6670 prec = 2; 6671 break; 6672 case 'd': 6673 case 'D': 6674 case 'r': 6675 case 'R': 6676 prec = 4; 6677 break; 6678 case 'x': 6679 case 'X': 6680 case 'p': 6681 case 'P': 6682 prec = 6; 6683 break; 6684 default: 6685 *sizeP = 0; 6686 return _("bad call to MD_ATOF()"); 6687 } 6688 6689 t = atof_ieee (input_line_pointer, type, words); 6690 if (t) 6691 input_line_pointer = t; 6692 *sizeP = prec * 2; 6693 6694 if (target_big_endian) 6695 { 6696 for (i = 0; i < prec; i++) 6697 { 6698 s3_md_number_to_chars (litP, (valueT) words[i], 2); 6699 litP += 2; 6700 } 6701 } 6702 else 6703 { 6704 for (i = 0; i < prec; i += 2) 6705 { 6706 s3_md_number_to_chars (litP, (valueT) words[i + 1], 2); 6707 s3_md_number_to_chars (litP + 2, (valueT) words[i], 2); 6708 litP += 4; 6709 } 6710 } 6711 6712 return 0; 6713 } 6714 6715 static void 6716 s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED) 6717 { 6718 know (fragp->insn_addr <= s3_RELAX_PAD_BYTE); 6719 } 6720 6721 static void 6722 s3_validate_fix (fixS *fixP) 6723 { 6724 fixP->fx_where += fixP->fx_frag->insn_addr; 6725 } 6726 6727 static int 6728 s3_force_relocation (struct fix *fixp) 6729 { 6730 int retval = 0; 6731 6732 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 6733 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY 6734 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP 6735 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH 6736 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP 6737 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH 6738 || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP) 6739 { 6740 retval = 1; 6741 } 6742 return retval; 6743 } 6744 6745 static bfd_boolean 6746 s3_fix_adjustable (fixS * fixP) 6747 { 6748 if (fixP->fx_addsy == NULL) 6749 { 6750 return 1; 6751 } 6752 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour 6753 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) 6754 { 6755 return 0; 6756 } 6757 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 6758 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY 6759 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP 6760 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP) 6761 { 6762 return 0; 6763 } 6764 6765 return 1; 6766 } 6767 6768 static void 6769 s3_elf_final_processing (void) 6770 { 6771 unsigned long val = 0; 6772 6773 if (score3) 6774 val = E_SCORE_MACH_SCORE3; 6775 else if (score7) 6776 val = E_SCORE_MACH_SCORE7; 6777 6778 elf_elfheader (stdoutput)->e_machine = EM_SCORE; 6779 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH; 6780 elf_elfheader (stdoutput)->e_flags |= val; 6781 6782 if (s3_fix_data_dependency == 1) 6783 { 6784 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; 6785 } 6786 if (s3_score_pic == s3_PIC) 6787 { 6788 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; 6789 } 6790 } 6791 6792 static int 6793 s3_judge_size_before_relax (fragS * fragp, asection *sec) 6794 { 6795 int change = 0; 6796 6797 if (s3_score_pic == s3_NO_PIC) 6798 change = s3_nopic_need_relax (fragp->fr_symbol, 0); 6799 else 6800 change = s3_pic_need_relax (fragp->fr_symbol, sec); 6801 6802 if (change == 1) 6803 { 6804 /* Only at the first time determining whether s3_GP instruction relax should be done, 6805 return the difference between instruction size and instruction relax size. */ 6806 if (fragp->fr_opcode == NULL) 6807 { 6808 fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype); 6809 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6810 return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype); 6811 } 6812 } 6813 6814 return 0; 6815 } 6816 6817 static int 6818 s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) 6819 { 6820 if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP) 6821 || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) 6822 return s3_judge_size_before_relax (fragp, sec); 6823 6824 return 0; 6825 } 6826 6827 static int 6828 s3_relax_branch_inst32 (fragS * fragp) 6829 { 6830 fragp->fr_opcode = NULL; 6831 return 0; 6832 } 6833 6834 static int 6835 s3_relax_branch_inst16 (fragS * fragp) 6836 { 6837 int relaxable_p = 0; 6838 int frag_addr = fragp->fr_address + fragp->insn_addr; 6839 addressT symbol_address = 0; 6840 symbolS *s; 6841 offsetT offset; 6842 long value; 6843 unsigned long inst_value; 6844 6845 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6846 6847 s = fragp->fr_symbol; 6848 if (s == NULL) 6849 frag_addr = 0; 6850 else 6851 symbol_address = (addressT) symbol_get_frag (s)->fr_address; 6852 6853 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE); 6854 offset = (inst_value & 0x1ff) << 1; 6855 if ((offset & 0x200) == 0x200) 6856 offset |= 0xfffffc00; 6857 6858 value = offset + symbol_address - frag_addr; 6859 6860 if (relaxable_p 6861 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) 6862 && fragp->fr_fix == 2 6863 && (S_IS_DEFINED (s) 6864 && !S_IS_COMMON (s) 6865 && !S_IS_EXTERNAL (s))) 6866 { 6867 /* Relax branch 32 to branch 16. */ 6868 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6869 fragp->fr_fix = 4; 6870 return 2; 6871 } 6872 else 6873 return 0; 6874 } 6875 6876 static int 6877 s3_relax_cmpbranch_inst32 (fragS * fragp) 6878 { 6879 int relaxable_p = 0; 6880 symbolS *s; 6881 /* For sign bit. */ 6882 long offset; 6883 long frag_addr = fragp->fr_address + fragp->insn_addr; 6884 long symbol_address = 0; 6885 long value; 6886 unsigned long inst_value; 6887 6888 relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6889 6890 s = fragp->fr_symbol; 6891 if (s == NULL) 6892 frag_addr = 0; 6893 else 6894 symbol_address = (addressT) symbol_get_frag (s)->fr_address; 6895 6896 inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE); 6897 offset = (inst_value & 0x1) 6898 | (((inst_value >> 7) & 0x7) << 1) 6899 | (((inst_value >> 21) & 0x1f) << 4); 6900 offset <<= 1; 6901 if ((offset & 0x200) == 0x200) 6902 offset |= 0xfffffe00; 6903 6904 value = offset + symbol_address - frag_addr; 6905 /* change the order of judging rule is because 6906 1.not defined symbol or common symbol or external symbol will change 6907 bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode 6908 2.if the flow is as before : it will results to recursive loop 6909 */ 6910 if (fragp->fr_fix == 6) 6911 { 6912 /* Have already relaxed! Just return 0 to terminate the loop. */ 6913 return 0; 6914 } 6915 /* need to translate when extern or not defined or common symbol */ 6916 else if ((relaxable_p 6917 && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) 6918 && fragp->fr_fix == 4) 6919 || !S_IS_DEFINED (s) 6920 ||S_IS_COMMON (s) 6921 ||S_IS_EXTERNAL (s)) 6922 { 6923 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6924 fragp->fr_fix = 6; 6925 return 2; 6926 } 6927 else 6928 { 6929 /* Never relax. Modify fr_opcode to NULL to verify it's value in 6930 md_apply_fix. */ 6931 fragp->fr_opcode = NULL; 6932 return 0; 6933 } 6934 } 6935 6936 6937 static int 6938 s3_relax_other_inst32 (fragS * fragp) 6939 { 6940 int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); 6941 6942 if (relaxable_p 6943 && fragp->fr_fix == 4) 6944 { 6945 fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); 6946 fragp->fr_fix = 2; 6947 return -2; 6948 } 6949 else 6950 return 0; 6951 } 6952 6953 static int 6954 s3_relax_gp_and_pic_inst32 (void) 6955 { 6956 /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC 6957 instructions. We don't change relax size here. */ 6958 return 0; 6959 } 6960 6961 static int 6962 s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) 6963 { 6964 int grows = 0; 6965 int adjust_align_p = 0; 6966 6967 /* If the instruction address is odd, make it half word align first. */ 6968 if ((fragp->fr_address) % 2 != 0) 6969 { 6970 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) 6971 { 6972 fragp->insn_addr = 1; 6973 grows += 1; 6974 adjust_align_p = 1; 6975 } 6976 } 6977 6978 switch (s3_RELAX_TYPE (fragp->fr_subtype)) 6979 { 6980 case PC_DISP19div2: 6981 grows += s3_relax_branch_inst32 (fragp); 6982 break; 6983 6984 case PC_DISP8div2: 6985 grows += s3_relax_branch_inst16 (fragp); 6986 break; 6987 6988 case Insn_BCMP : 6989 grows += s3_relax_cmpbranch_inst32 (fragp); 6990 break; 6991 6992 case Insn_GP: 6993 case Insn_PIC: 6994 grows += s3_relax_gp_and_pic_inst32 (); 6995 break; 6996 6997 default: 6998 grows += s3_relax_other_inst32 (fragp); 6999 break; 7000 } 7001 7002 /* newly added */ 7003 if (adjust_align_p && fragp->insn_addr) 7004 { 7005 fragp->fr_fix += fragp->insn_addr; 7006 } 7007 7008 return grows; 7009 } 7010 7011 static void 7012 s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) 7013 { 7014 unsigned int r_old; 7015 unsigned int r_new; 7016 char backup[20]; 7017 fixS *fixp; 7018 7019 r_old = s3_RELAX_OLD (fragp->fr_subtype); 7020 r_new = s3_RELAX_NEW (fragp->fr_subtype); 7021 7022 /* fragp->fr_opcode indicates whether this frag should be relaxed. */ 7023 if (fragp->fr_opcode == NULL) 7024 { 7025 memcpy (backup, fragp->fr_literal, r_old); 7026 fragp->fr_fix = r_old; 7027 } 7028 else 7029 { 7030 memcpy (backup, fragp->fr_literal + r_old, r_new); 7031 fragp->fr_fix = r_new; 7032 } 7033 7034 fixp = fragp->tc_frag_data.fixp; 7035 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old) 7036 { 7037 if (fragp->fr_opcode) 7038 fixp->fx_done = 1; 7039 fixp = fixp->fx_next; 7040 } 7041 while (fixp && fixp->fx_frag == fragp) 7042 { 7043 if (fragp->fr_opcode) 7044 fixp->fx_where -= r_old + fragp->insn_addr; 7045 else 7046 fixp->fx_done = 1; 7047 fixp = fixp->fx_next; 7048 } 7049 7050 if (fragp->insn_addr) 7051 { 7052 s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); 7053 } 7054 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); 7055 fragp->fr_fix += fragp->insn_addr; 7056 } 7057 7058 static long 7059 s3_pcrel_from (fixS * fixP) 7060 { 7061 long retval = 0; 7062 7063 if (fixP->fx_addsy 7064 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) 7065 && (fixP->fx_subsy == NULL)) 7066 { 7067 retval = 0; 7068 } 7069 else 7070 { 7071 retval = fixP->fx_where + fixP->fx_frag->fr_address; 7072 } 7073 7074 return retval; 7075 } 7076 7077 static valueT 7078 s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 7079 { 7080 int align = bfd_section_alignment (segment); 7081 return ((size + (1 << align) - 1) & -(1 << align)); 7082 } 7083 7084 static void 7085 s3_apply_fix (fixS *fixP, valueT *valP, segT seg) 7086 { 7087 offsetT value = *valP; 7088 offsetT newval; 7089 offsetT content; 7090 unsigned short HI, LO; 7091 7092 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; 7093 7094 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED); 7095 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) 7096 { 7097 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) 7098 fixP->fx_done = 1; 7099 } 7100 7101 /* If this symbol is in a different section then we need to leave it for 7102 the linker to deal with. Unfortunately, md_pcrel_from can't tell, 7103 so we have to undo it's effects here. */ 7104 if (fixP->fx_pcrel) 7105 { 7106 if (fixP->fx_addsy != NULL 7107 && S_IS_DEFINED (fixP->fx_addsy) 7108 && S_GET_SEGMENT (fixP->fx_addsy) != seg) 7109 value += md_pcrel_from (fixP); 7110 } 7111 7112 /* Remember value for emit_reloc. */ 7113 fixP->fx_addnumber = value; 7114 7115 switch (fixP->fx_r_type) 7116 { 7117 case BFD_RELOC_HI16_S: 7118 if (fixP->fx_done) /* For la rd, imm32. */ 7119 { 7120 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7121 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */ 7122 newval |= (HI & 0x3fff) << 1; 7123 newval |= ((HI >> 14) & 0x3) << 16; 7124 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7125 } 7126 break; 7127 case BFD_RELOC_LO16: 7128 if (fixP->fx_done) /* For la rd, imm32. */ 7129 { 7130 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7131 LO = (value) & 0xffff; 7132 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ 7133 newval |= ((LO >> 14) & 0x3) << 16; 7134 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7135 } 7136 break; 7137 case BFD_RELOC_SCORE_JMP: 7138 { 7139 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7140 value = fixP->fx_offset; 7141 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); 7142 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7143 } 7144 break; 7145 7146 case BFD_RELOC_SCORE_IMM30: 7147 { 7148 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); 7149 value = fixP->fx_offset; 7150 value >>= 2; 7151 content = (content & ~0x7f7fff7f80LL) 7152 | (((value & 0xff) >> 0) << 7) 7153 | (((value & 0x7fff00) >> 8) << 16) 7154 | (((value & 0x3f800000) >> 23) << 32); 7155 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); 7156 break; 7157 } 7158 7159 case BFD_RELOC_SCORE_IMM32: 7160 { 7161 content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); 7162 value = fixP->fx_offset; 7163 content = (content & ~0x7f7fff7fe0LL) 7164 | ((value & 0x3ff) << 5) 7165 | (((value >> 10) & 0x7fff) << 16) 7166 | (((value >> 25) & 0x7f) << 32); 7167 s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); 7168 break; 7169 } 7170 7171 case BFD_RELOC_SCORE_BRANCH: 7172 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7173 value = fixP->fx_offset; 7174 else 7175 fixP->fx_done = 1; 7176 7177 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7178 7179 /* Don't check c-bit. */ 7180 if (fixP->fx_frag->fr_opcode != 0) 7181 { 7182 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7183 { 7184 as_bad_where (fixP->fx_file, fixP->fx_line, 7185 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7186 return; 7187 } 7188 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7189 content &= 0xfe00; 7190 content = (content & 0xfe00) | ((value >> 1) & 0x1ff); 7191 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7192 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; 7193 fixP->fx_size = 2; 7194 } 7195 else 7196 { 7197 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7198 { 7199 as_bad_where (fixP->fx_file, fixP->fx_line, 7200 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7201 return; 7202 } 7203 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7204 content &= 0xfc00fc01; 7205 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7206 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7207 } 7208 break; 7209 case BFD_RELOC_SCORE16_JMP: 7210 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7211 content &= 0xf001; 7212 value = fixP->fx_offset & 0xfff; 7213 content = (content & 0xfc01) | (value & 0xffe); 7214 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7215 break; 7216 case BFD_RELOC_SCORE16_BRANCH: 7217 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7218 /* Don't check c-bit. */ 7219 if (fixP->fx_frag->fr_opcode != 0) 7220 { 7221 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 7222 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7223 value = fixP->fx_offset; 7224 else 7225 fixP->fx_done = 1; 7226 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7227 { 7228 as_bad_where (fixP->fx_file, fixP->fx_line, 7229 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7230 return; 7231 } 7232 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7233 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7234 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7235 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; 7236 fixP->fx_size = 4; 7237 break; 7238 } 7239 else 7240 { 7241 /* In different section. */ 7242 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 7243 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7244 value = fixP->fx_offset; 7245 else 7246 fixP->fx_done = 1; 7247 7248 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7249 { 7250 as_bad_where (fixP->fx_file, fixP->fx_line, 7251 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7252 return; 7253 } 7254 7255 content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); 7256 content = (content & 0xfe00) | ((value >> 1) & 0x1ff); 7257 s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); 7258 break; 7259 } 7260 7261 break; 7262 7263 case BFD_RELOC_SCORE_BCMP: 7264 if (fixP->fx_frag->fr_opcode != 0) 7265 { 7266 char *buf_ptr = buf; 7267 buf_ptr += 2; 7268 7269 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7270 value = fixP->fx_offset; 7271 else 7272 fixP->fx_done = 1; 7273 7274 /* NOTE!!! 7275 bcmp -> cmp! and branch, so value -= 2. */ 7276 value -= 2; 7277 7278 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) 7279 { 7280 as_bad_where (fixP->fx_file, fixP->fx_line, 7281 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19-1]"), (unsigned int) value); 7282 return; 7283 } 7284 7285 content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE); 7286 content &= 0xfc00fc01; 7287 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 7288 s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE); 7289 /* change relocation type to BFD_RELOC_SCORE_BRANCH */ 7290 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; 7291 fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */ 7292 break; 7293 } 7294 else 7295 { 7296 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 7297 value = fixP->fx_offset; 7298 else 7299 fixP->fx_done = 1; 7300 7301 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7302 7303 if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) 7304 { 7305 as_bad_where (fixP->fx_file, fixP->fx_line, 7306 _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9-1]"), (unsigned int) value); 7307 return; 7308 } 7309 7310 value >>= 1; 7311 content &= ~0x03e00381; 7312 content = content 7313 | (value & 0x1) 7314 | (((value & 0xe) >> 1) << 7) 7315 | (((value & 0x1f0) >> 4) << 21); 7316 7317 s3_md_number_to_chars (buf, content, s3_INSN_SIZE); 7318 break; 7319 } 7320 7321 case BFD_RELOC_8: 7322 if (fixP->fx_done || fixP->fx_pcrel) 7323 s3_md_number_to_chars (buf, value, 1); 7324 #ifdef OBJ_ELF 7325 else 7326 { 7327 value = fixP->fx_offset; 7328 s3_md_number_to_chars (buf, value, 1); 7329 } 7330 #endif 7331 break; 7332 7333 case BFD_RELOC_16: 7334 if (fixP->fx_done || fixP->fx_pcrel) 7335 s3_md_number_to_chars (buf, value, 2); 7336 #ifdef OBJ_ELF 7337 else 7338 { 7339 value = fixP->fx_offset; 7340 s3_md_number_to_chars (buf, value, 2); 7341 } 7342 #endif 7343 break; 7344 case BFD_RELOC_RVA: 7345 case BFD_RELOC_32: 7346 if (fixP->fx_done || fixP->fx_pcrel) 7347 md_number_to_chars (buf, value, 4); 7348 #ifdef OBJ_ELF 7349 else 7350 { 7351 value = fixP->fx_offset; 7352 md_number_to_chars (buf, value, 4); 7353 } 7354 #endif 7355 break; 7356 case BFD_RELOC_VTABLE_INHERIT: 7357 fixP->fx_done = 0; 7358 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) 7359 S_SET_WEAK (fixP->fx_addsy); 7360 break; 7361 case BFD_RELOC_VTABLE_ENTRY: 7362 fixP->fx_done = 0; 7363 break; 7364 case BFD_RELOC_SCORE_GPREL15: 7365 content = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7366 /* c-bit. */ 7367 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000)) 7368 fixP->fx_r_type = BFD_RELOC_NONE; 7369 fixP->fx_done = 0; 7370 break; 7371 case BFD_RELOC_SCORE_GOT15: 7372 case BFD_RELOC_SCORE_DUMMY_HI16: 7373 case BFD_RELOC_SCORE_GOT_LO16: 7374 case BFD_RELOC_SCORE_CALL15: 7375 case BFD_RELOC_GPREL32: 7376 break; 7377 case BFD_RELOC_NONE: 7378 default: 7379 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); 7380 } 7381 } 7382 7383 static arelent ** 7384 s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 7385 { 7386 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ 7387 arelent *reloc; 7388 bfd_reloc_code_real_type code; 7389 const char *type; 7390 7391 reloc = retval[0] = XNEW (arelent); 7392 retval[1] = NULL; 7393 7394 reloc->sym_ptr_ptr = XNEW (asymbol *); 7395 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 7396 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 7397 reloc->addend = fixp->fx_offset; 7398 7399 /* If this is a variant frag, we may need to adjust the existing 7400 reloc and generate a new one. */ 7401 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) 7402 { 7403 /* Update instruction imm bit. */ 7404 offsetT newval; 7405 unsigned short off; 7406 char *buf; 7407 7408 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; 7409 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7410 off = fixp->fx_offset >> 16; 7411 newval |= (off & 0x3fff) << 1; 7412 newval |= ((off >> 14) & 0x3) << 16; 7413 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7414 7415 buf += s3_INSN_SIZE; 7416 newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); 7417 off = fixp->fx_offset & 0xffff; 7418 newval |= ((off & 0x3fff) << 1); 7419 newval |= (((off >> 14) & 0x3) << 16); 7420 s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); 7421 7422 retval[1] = XNEW (arelent); 7423 retval[2] = NULL; 7424 retval[1]->sym_ptr_ptr = XNEW (asymbol *); 7425 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 7426 retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); 7427 7428 retval[1]->addend = 0; 7429 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); 7430 gas_assert (retval[1]->howto != NULL); 7431 7432 fixp->fx_r_type = BFD_RELOC_HI16_S; 7433 } 7434 7435 code = fixp->fx_r_type; 7436 switch (fixp->fx_r_type) 7437 { 7438 case BFD_RELOC_32: 7439 if (fixp->fx_pcrel) 7440 { 7441 code = BFD_RELOC_32_PCREL; 7442 break; 7443 } 7444 /* Fall through. */ 7445 case BFD_RELOC_HI16_S: 7446 case BFD_RELOC_LO16: 7447 case BFD_RELOC_SCORE_JMP: 7448 case BFD_RELOC_SCORE_BRANCH: 7449 case BFD_RELOC_SCORE16_JMP: 7450 case BFD_RELOC_SCORE16_BRANCH: 7451 case BFD_RELOC_SCORE_BCMP: 7452 case BFD_RELOC_VTABLE_ENTRY: 7453 case BFD_RELOC_VTABLE_INHERIT: 7454 case BFD_RELOC_SCORE_GPREL15: 7455 case BFD_RELOC_SCORE_GOT15: 7456 case BFD_RELOC_SCORE_DUMMY_HI16: 7457 case BFD_RELOC_SCORE_GOT_LO16: 7458 case BFD_RELOC_SCORE_CALL15: 7459 case BFD_RELOC_GPREL32: 7460 case BFD_RELOC_NONE: 7461 case BFD_RELOC_SCORE_IMM30: 7462 case BFD_RELOC_SCORE_IMM32: 7463 code = fixp->fx_r_type; 7464 break; 7465 default: 7466 type = _("<unknown>"); 7467 as_bad_where (fixp->fx_file, fixp->fx_line, 7468 _("cannot represent %s relocation in this object file format"), type); 7469 return NULL; 7470 } 7471 7472 reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 7473 if (reloc->howto == NULL) 7474 { 7475 as_bad_where (fixp->fx_file, fixp->fx_line, 7476 _("cannot represent %s relocation in this object file format1"), 7477 bfd_get_reloc_code_name (code)); 7478 return NULL; 7479 } 7480 /* HACK: Since arm ELF uses Rel instead of Rela, encode the 7481 vtable entry to be used in the relocation's section offset. */ 7482 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 7483 reloc->address = fixp->fx_offset; 7484 7485 return retval; 7486 } 7487 7488 void 7489 md_assemble (char *str) 7490 { 7491 if (score3) 7492 s3_assemble (str); 7493 else 7494 s7_assemble (str); 7495 } 7496 7497 /* We handle all bad expressions here, so that we can report the faulty 7498 instruction in the error message. */ 7499 void 7500 md_operand (expressionS * exp) 7501 { 7502 if (score3) 7503 s3_operand (exp); 7504 else 7505 s7_operand (exp); 7506 } 7507 7508 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate 7509 for use in the a.out file, and stores them in the array pointed to by buf. 7510 This knows about the endian-ness of the target machine and does 7511 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) 7512 2 (short) and 4 (long) Floating numbers are put out as a series of 7513 LITTLENUMS (shorts, here at least). */ 7514 void 7515 md_number_to_chars (char *buf, valueT val, int n) 7516 { 7517 if (score3) 7518 s3_number_to_chars (buf, val, n); 7519 else 7520 s7_number_to_chars (buf, val, n); 7521 } 7522 7523 /* Turn a string in input_line_pointer into a floating point constant 7524 of type TYPE, and store the appropriate bytes in *LITP. The number 7525 of LITTLENUMS emitted is stored in *SIZEP. An error message is 7526 returned, or NULL on OK. 7527 7528 Note that fp constants aren't represent in the normal way on the ARM. 7529 In big endian mode, things are as expected. However, in little endian 7530 mode fp constants are big-endian word-wise, and little-endian byte-wise 7531 within the words. For example, (double) 1.1 in big endian mode is 7532 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is 7533 the byte sequence 99 99 f1 3f 9a 99 99 99. */ 7534 const char * 7535 md_atof (int type, char *litP, int *sizeP) 7536 { 7537 if (score3) 7538 return s3_atof (type, litP, sizeP); 7539 else 7540 return s7_atof (type, litP, sizeP); 7541 } 7542 7543 void 7544 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED) 7545 { 7546 if (score3) 7547 s3_frag_check (fragp); 7548 else 7549 s7_frag_check (fragp); 7550 } 7551 7552 /* Implementation of TC_VALIDATE_FIX. 7553 Called before md_apply_fix() and after md_convert_frag(). */ 7554 void 7555 score_validate_fix (fixS *fixP) 7556 { 7557 if (score3) 7558 s3_validate_fix (fixP); 7559 else 7560 s7_validate_fix (fixP); 7561 } 7562 7563 int 7564 score_force_relocation (struct fix *fixp) 7565 { 7566 if (score3) 7567 return s3_force_relocation (fixp); 7568 else 7569 return s7_force_relocation (fixp); 7570 } 7571 7572 /* Implementation of md_frag_check. 7573 Called after md_convert_frag(). */ 7574 bfd_boolean 7575 score_fix_adjustable (fixS * fixP) 7576 { 7577 if (score3) 7578 return s3_fix_adjustable (fixP); 7579 else 7580 return s7_fix_adjustable (fixP); 7581 } 7582 7583 void 7584 score_elf_final_processing (void) 7585 { 7586 if (score3) 7587 s3_elf_final_processing (); 7588 else 7589 s7_elf_final_processing (); 7590 } 7591 7592 /* In this function, we determine whether s3_GP instruction should do relaxation, 7593 for the label being against was known now. 7594 Doing this here but not in md_relax_frag() can induce iteration times 7595 in stage of doing relax. */ 7596 int 7597 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) 7598 { 7599 if (score3) 7600 return s3_estimate_size_before_relax (fragp, sec); 7601 else 7602 return s7_estimate_size_before_relax (fragp, sec); 7603 } 7604 7605 int 7606 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) 7607 { 7608 if (score3) 7609 return s3_relax_frag (sec, fragp, stretch); 7610 else 7611 return s7_relax_frag (sec, fragp, stretch); 7612 } 7613 7614 void 7615 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) 7616 { 7617 if (score3) 7618 return s3_convert_frag (abfd, sec, fragp); 7619 else 7620 return s7_convert_frag (abfd, sec, fragp); 7621 } 7622 7623 long 7624 md_pcrel_from (fixS * fixP) 7625 { 7626 if (score3) 7627 return s3_pcrel_from (fixP); 7628 else 7629 return s7_pcrel_from (fixP); 7630 } 7631 7632 /* Round up a section size to the appropriate boundary. */ 7633 valueT 7634 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 7635 { 7636 if (score3) 7637 return s3_section_align (segment, size); 7638 else 7639 return s7_section_align (segment, size); 7640 } 7641 7642 void 7643 md_apply_fix (fixS *fixP, valueT *valP, segT seg) 7644 { 7645 if (score3) 7646 return s3_apply_fix (fixP, valP, seg); 7647 else 7648 return s7_apply_fix (fixP, valP, seg); 7649 } 7650 7651 /* Translate internal representation of relocation info to BFD target format. */ 7652 arelent ** 7653 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 7654 { 7655 if (score3) 7656 return s3_gen_reloc (section, fixp); 7657 else 7658 return s7_gen_reloc (section, fixp); 7659 } 7660 7661 void 7662 md_begin (void) 7663 { 7664 s3_begin (); 7665 s7_begin (); 7666 } 7667 7668 static void 7669 score_set_mach (const char *arg) 7670 { 7671 if (strcmp (arg, MARCH_SCORE3) == 0) 7672 { 7673 score3 = 1; 7674 score7 = 0; 7675 s3_score3d = 1; 7676 } 7677 else if (strcmp (arg, MARCH_SCORE7) == 0) 7678 { 7679 score3 = 0; 7680 score7 = 1; 7681 s7_score7d = 1; 7682 s7_university_version = 0; 7683 s7_vector_size = s7_SCORE7_PIPELINE; 7684 } 7685 else if (strcmp (arg, MARCH_SCORE5) == 0) 7686 { 7687 score3 = 0; 7688 score7 = 1; 7689 s7_score7d = 1; 7690 s7_university_version = 0; 7691 s7_vector_size = s7_SCORE5_PIPELINE; 7692 } 7693 else if (strcmp (arg, MARCH_SCORE5U) == 0) 7694 { 7695 score3 = 0; 7696 score7 = 1; 7697 s7_score7d = 1; 7698 s7_university_version = 1; 7699 s7_vector_size = s7_SCORE5_PIPELINE; 7700 } 7701 else 7702 { 7703 as_bad (_("unknown architecture `%s'\n"), arg); 7704 } 7705 } 7706 7707 int 7708 md_parse_option (int c, const char *arg) 7709 { 7710 switch (c) 7711 { 7712 #ifdef OPTION_EB 7713 case OPTION_EB: 7714 target_big_endian = 1; 7715 break; 7716 #endif 7717 #ifdef OPTION_EL 7718 case OPTION_EL: 7719 target_big_endian = 0; 7720 break; 7721 #endif 7722 case OPTION_FIXDD: 7723 s3_fix_data_dependency = 1; 7724 s7_fix_data_dependency = 1; 7725 break; 7726 case OPTION_NWARN: 7727 s3_warn_fix_data_dependency = 0; 7728 s7_warn_fix_data_dependency = 0; 7729 break; 7730 case OPTION_SCORE5: 7731 score3 = 0; 7732 score7 = 1; 7733 s7_university_version = 0; 7734 s7_vector_size = s7_SCORE5_PIPELINE; 7735 break; 7736 case OPTION_SCORE5U: 7737 score3 = 0; 7738 score7 = 1; 7739 s7_university_version = 1; 7740 s7_vector_size = s7_SCORE5_PIPELINE; 7741 break; 7742 case OPTION_SCORE7: 7743 score3 = 0; 7744 score7 = 1; 7745 s7_score7d = 1; 7746 s7_university_version = 0; 7747 s7_vector_size = s7_SCORE7_PIPELINE; 7748 break; 7749 case OPTION_SCORE3: 7750 score3 = 1; 7751 score7 = 0; 7752 s3_score3d = 1; 7753 break; 7754 case OPTION_R1: 7755 s3_nor1 = 0; 7756 s7_nor1 = 0; 7757 break; 7758 case 'G': 7759 s3_g_switch_value = atoi (arg); 7760 s7_g_switch_value = atoi (arg); 7761 break; 7762 case OPTION_O0: 7763 s3_g_opt = 0; 7764 s7_g_opt = 0; 7765 break; 7766 case OPTION_SCORE_VERSION: 7767 printf (_("Sunplus-v2-0-0-20060510\n")); 7768 break; 7769 case OPTION_PIC: 7770 s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */ 7771 s7_score_pic = s7_PIC; 7772 s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */ 7773 s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */ 7774 break; 7775 case OPTION_MARCH: 7776 score_set_mach (arg); 7777 break; 7778 default: 7779 return 0; 7780 } 7781 return 1; 7782 } 7783 7784 void 7785 md_show_usage (FILE * fp) 7786 { 7787 fprintf (fp, _(" Score-specific assembler options:\n")); 7788 #ifdef OPTION_EB 7789 fprintf (fp, _("\ 7790 -EB\t\tassemble code for a big-endian cpu\n")); 7791 #endif 7792 7793 #ifdef OPTION_EL 7794 fprintf (fp, _("\ 7795 -EL\t\tassemble code for a little-endian cpu\n")); 7796 #endif 7797 7798 fprintf (fp, _("\ 7799 -FIXDD\t\tfix data dependencies\n")); 7800 fprintf (fp, _("\ 7801 -NWARN\t\tdo not print warning message when fixing data dependencies\n")); 7802 fprintf (fp, _("\ 7803 -SCORE5\t\tassemble code for target SCORE5\n")); 7804 fprintf (fp, _("\ 7805 -SCORE5U\tassemble code for target SCORE5U\n")); 7806 fprintf (fp, _("\ 7807 -SCORE7\t\tassemble code for target SCORE7 [default]\n")); 7808 fprintf (fp, _("\ 7809 -SCORE3\t\tassemble code for target SCORE3\n")); 7810 fprintf (fp, _("\ 7811 -march=score7\tassemble code for target SCORE7 [default]\n")); 7812 fprintf (fp, _("\ 7813 -march=score3\tassemble code for target SCORE3\n")); 7814 fprintf (fp, _("\ 7815 -USE_R1\t\tassemble code for no warning message when using temp register r1\n")); 7816 fprintf (fp, _("\ 7817 -KPIC\t\tgenerate PIC\n")); 7818 fprintf (fp, _("\ 7819 -O0\t\tdo not perform any optimizations\n")); 7820 fprintf (fp, _("\ 7821 -G gpnum\tassemble code for setting gpsize, default is 8 bytes\n")); 7822 fprintf (fp, _("\ 7823 -V \t\tSunplus release version\n")); 7824 } 7825