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