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