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