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