1214571Sdim/* tc-score.c -- Assembler for Score 2214571Sdim Copyright 2006 Free Software Foundation, Inc. 3214571Sdim Contributed by: 4214571Sdim Mei Ligang (ligang@sunnorth.com.cn) 5214571Sdim Pei-Lin Tsai (pltsai@sunplus.com) 6214571Sdim 7214571Sdim This file is part of GAS, the GNU Assembler. 8214571Sdim 9214571Sdim GAS is free software; you can redistribute it and/or modify 10214571Sdim it under the terms of the GNU General Public License as published by 11214571Sdim the Free Software Foundation; either version 2, or (at your option) 12214571Sdim any later version. 13214571Sdim 14214571Sdim GAS is distributed in the hope that it will be useful, 15214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 16214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17214571Sdim GNU General Public License for more details. 18214571Sdim 19214571Sdim You should have received a copy of the GNU General Public License 20214571Sdim along with GAS; see the file COPYING. If not, write to the Free 21214571Sdim Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22214571Sdim 02110-1301, USA. */ 23214571Sdim 24214571Sdim#include "as.h" 25214571Sdim#include "config.h" 26214571Sdim#include "subsegs.h" 27214571Sdim#include "safe-ctype.h" 28214571Sdim#include "opcode/score-inst.h" 29214571Sdim#include "opcode/score-datadep.h" 30214571Sdim#include "struc-symbol.h" 31214571Sdim 32214571Sdim#ifdef OBJ_ELF 33214571Sdim#include "elf/score.h" 34214571Sdim#include "dwarf2dbg.h" 35214571Sdim#endif 36214571Sdim 37214571Sdim#define GP 28 38214571Sdim#define PIC_CALL_REG 29 39214571Sdim#define MAX_LITERAL_POOL_SIZE 1024 40214571Sdim#define FAIL 0x80000000 41214571Sdim#define SUCCESS 0 42214571Sdim#define INSN_SIZE 4 43214571Sdim#define INSN16_SIZE 2 44214571Sdim#define RELAX_INST_NUM 3 45214571Sdim 46214571Sdim/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */ 47214571Sdim#define BAD_ARGS _("bad arguments to instruction") 48214571Sdim#define BAD_PC _("r15 not allowed here") 49214571Sdim#define BAD_COND _("instruction is not conditional") 50214571Sdim#define ERR_NO_ACCUM _("acc0 expected") 51214571Sdim#define ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions") 52214571Sdim#define ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu") 53214571Sdim#define ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction") 54214571Sdim#define LONG_LABEL_LEN _("the label length is longer than 1024"); 55214571Sdim#define BAD_SKIP_COMMA BAD_ARGS 56214571Sdim#define BAD_GARBAGE _("garbage following instruction"); 57214571Sdim 58214571Sdim#define skip_whitespace(str) while (*(str) == ' ') ++(str) 59214571Sdim 60214571Sdim/* The name of the readonly data section. */ 61214571Sdim#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ 62214571Sdim ? ".data" \ 63214571Sdim : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ 64214571Sdim ? ".rdata" \ 65214571Sdim : OUTPUT_FLAVOR == bfd_target_coff_flavour \ 66214571Sdim ? ".rdata" \ 67214571Sdim : OUTPUT_FLAVOR == bfd_target_elf_flavour \ 68214571Sdim ? ".rodata" \ 69214571Sdim : (abort (), "")) 70214571Sdim 71214571Sdim#define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \ 72214571Sdim ((relax_substateT) \ 73214571Sdim (((old) << 23) \ 74214571Sdim | ((new) << 16) \ 75214571Sdim | ((type) << 9) \ 76214571Sdim | ((reloc1) << 5) \ 77214571Sdim | ((reloc2) << 1) \ 78214571Sdim | ((opt) ? 1 : 0))) 79214571Sdim 80214571Sdim#define RELAX_OLD(i) (((i) >> 23) & 0x7f) 81214571Sdim#define RELAX_NEW(i) (((i) >> 16) & 0x7f) 82214571Sdim#define RELAX_TYPE(i) (((i) >> 9) & 0x7f) 83214571Sdim#define RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf) 84214571Sdim#define RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf) 85214571Sdim#define RELAX_OPT(i) ((i) & 1) 86214571Sdim#define RELAX_OPT_CLEAR(i) ((i) & ~1) 87214571Sdim 88214571Sdim#define SET_INSN_ERROR(s) (inst.error = (s)) 89214571Sdim#define INSN_IS_PCE_P(s) (strstr (str, "||") != NULL) 90214571Sdim 91214571Sdim#define GET_INSN_CLASS(type) (get_insn_class_from_type (type)) 92214571Sdim 93214571Sdim#define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \ 94214571Sdim ? INSN16_SIZE : INSN_SIZE) 95214571Sdim 96214571Sdim/* This array holds the chars that always start a comment. If the 97214571Sdim pre-processor is disabled, these aren't very useful. */ 98214571Sdimconst char comment_chars[] = "#"; 99214571Sdimconst char line_comment_chars[] = "#"; 100214571Sdimconst char line_separator_chars[] = ";"; 101214571Sdim 102214571Sdim/* Chars that can be used to separate mant from exp in floating point numbers. */ 103214571Sdimconst char EXP_CHARS[] = "eE"; 104214571Sdimconst char FLT_CHARS[] = "rRsSfFdDxXeEpP"; 105214571Sdim 106214571Sdim/* Used to contain constructed error messages. */ 107214571Sdimstatic char err_msg[255]; 108214571Sdim 109214571SdimfragS *score_fragp = 0; 110214571Sdimstatic int fix_data_dependency = 0; 111214571Sdimstatic int warn_fix_data_dependency = 1; 112214571Sdimstatic int score7 = 1; 113214571Sdimstatic int university_version = 0; 114214571Sdim 115214571Sdimstatic int in_my_get_expression = 0; 116214571Sdim 117214571Sdim#define USE_GLOBAL_POINTER_OPT 1 118214571Sdim#define SCORE_BI_ENDIAN 119214571Sdim 120214571Sdim/* Default, pop warning message when using r1. */ 121214571Sdimstatic int nor1 = 1; 122214571Sdim 123214571Sdim/* Default will do instruction relax, -O0 will set g_opt = 0. */ 124214571Sdimstatic unsigned int g_opt = 1; 125214571Sdim 126214571Sdim/* The size of the small data section. */ 127214571Sdimstatic unsigned int g_switch_value = 8; 128214571Sdim 129214571Sdim#ifdef OBJ_ELF 130214571Sdim/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ 131214571SdimsymbolS *GOT_symbol; 132214571Sdim#endif 133214571Sdimstatic segT pdr_seg; 134214571Sdim 135214571Sdimenum score_pic_level score_pic = NO_PIC; 136214571Sdim 137214571Sdim#define INSN_NAME_LEN 16 138214571Sdimstruct score_it 139214571Sdim{ 140214571Sdim char name[INSN_NAME_LEN]; 141214571Sdim unsigned long instruction; 142214571Sdim unsigned long relax_inst; 143214571Sdim int size; 144214571Sdim int relax_size; 145214571Sdim enum score_insn_type type; 146214571Sdim char str[MAX_LITERAL_POOL_SIZE]; 147214571Sdim const char *error; 148214571Sdim int bwarn; 149214571Sdim char reg[INSN_NAME_LEN]; 150214571Sdim struct 151214571Sdim { 152214571Sdim bfd_reloc_code_real_type type; 153214571Sdim expressionS exp; 154214571Sdim int pc_rel; 155214571Sdim }reloc; 156214571Sdim}; 157214571Sdimstruct score_it inst; 158214571Sdim 159214571Sdimtypedef struct proc 160214571Sdim{ 161214571Sdim symbolS *isym; 162214571Sdim unsigned long reg_mask; 163214571Sdim unsigned long reg_offset; 164214571Sdim unsigned long fpreg_mask; 165214571Sdim unsigned long leaf; 166214571Sdim unsigned long frame_offset; 167214571Sdim unsigned long frame_reg; 168214571Sdim unsigned long pc_reg; 169214571Sdim} 170214571SdimprocS; 171214571Sdim 172214571Sdimstatic procS cur_proc; 173214571Sdimstatic procS *cur_proc_ptr; 174214571Sdimstatic int numprocs; 175214571Sdim 176214571Sdim#define SCORE7_PIPELINE 7 177214571Sdim#define SCORE5_PIPELINE 5 178214571Sdimstatic int vector_size = SCORE7_PIPELINE; 179214571Sdimstruct score_it dependency_vector[SCORE7_PIPELINE]; 180214571Sdim 181214571Sdim/* Relax will need some padding for alignment. */ 182214571Sdim#define RELAX_PAD_BYTE 3 183214571Sdim 184214571Sdim/* Number of littlenums required to hold an extended precision number. For md_atof. */ 185214571Sdim#define NUM_FLOAT_VALS 8 186214571Sdim#define MAX_LITTLENUMS 6 187214571SdimLITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS]; 188214571Sdim 189214571Sdim/* Structure for a hash table entry for a register. */ 190214571Sdimstruct reg_entry 191214571Sdim{ 192214571Sdim const char *name; 193214571Sdim int number; 194214571Sdim}; 195214571Sdim 196214571Sdimstatic const struct reg_entry score_rn_table[] = 197214571Sdim{ 198214571Sdim {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, 199214571Sdim {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, 200214571Sdim {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11}, 201214571Sdim {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15}, 202214571Sdim {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19}, 203214571Sdim {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23}, 204214571Sdim {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27}, 205214571Sdim {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31}, 206214571Sdim {NULL, 0} 207214571Sdim}; 208214571Sdim 209214571Sdimstatic const struct reg_entry score_srn_table[] = 210214571Sdim{ 211214571Sdim {"sr0", 0}, {"sr1", 1}, {"sr2", 2}, 212214571Sdim {NULL, 0} 213214571Sdim}; 214214571Sdim 215214571Sdimstatic const struct reg_entry score_crn_table[] = 216214571Sdim{ 217214571Sdim {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3}, 218214571Sdim {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7}, 219214571Sdim {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11}, 220214571Sdim {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15}, 221214571Sdim {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19}, 222214571Sdim {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23}, 223214571Sdim {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27}, 224214571Sdim {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31}, 225214571Sdim {NULL, 0} 226214571Sdim}; 227214571Sdim 228214571Sdimstruct reg_map 229214571Sdim{ 230214571Sdim const struct reg_entry *names; 231214571Sdim int max_regno; 232214571Sdim struct hash_control *htab; 233214571Sdim const char *expected; 234214571Sdim}; 235214571Sdim 236214571Sdimstruct reg_map all_reg_maps[] = 237214571Sdim{ 238214571Sdim {score_rn_table, 31, NULL, N_("S+core register expected")}, 239214571Sdim {score_srn_table, 2, NULL, N_("S+core special-register expected")}, 240214571Sdim {score_crn_table, 31, NULL, N_("S+core co-processor register expected")}, 241214571Sdim}; 242214571Sdim 243214571Sdimstatic struct hash_control *score_ops_hsh = NULL; 244214571Sdim 245214571Sdimstatic struct hash_control *dependency_insn_hsh = NULL; 246214571Sdim 247214571Sdim/* Enumeration matching entries in table above. */ 248214571Sdimenum score_reg_type 249214571Sdim{ 250214571Sdim REG_TYPE_SCORE = 0, 251214571Sdim#define REG_TYPE_FIRST REG_TYPE_SCORE 252214571Sdim REG_TYPE_SCORE_SR = 1, 253214571Sdim REG_TYPE_SCORE_CR = 2, 254214571Sdim REG_TYPE_MAX = 3 255214571Sdim}; 256214571Sdim 257214571Sdimtypedef struct literalS 258214571Sdim{ 259214571Sdim struct expressionS exp; 260214571Sdim struct score_it *inst; 261214571Sdim} 262214571SdimliteralT; 263214571Sdim 264214571SdimliteralT literals[MAX_LITERAL_POOL_SIZE]; 265214571Sdim 266214571Sdimstatic void do_ldst_insn (char *); 267214571Sdimstatic void do_crdcrscrsimm5 (char *); 268214571Sdimstatic void do_ldst_unalign (char *); 269214571Sdimstatic void do_ldst_atomic (char *); 270214571Sdimstatic void do_ldst_cop (char *); 271214571Sdimstatic void do_macro_li_rdi32 (char *); 272214571Sdimstatic void do_macro_la_rdi32 (char *); 273214571Sdimstatic void do_macro_rdi32hi (char *); 274214571Sdimstatic void do_macro_rdi32lo (char *); 275214571Sdimstatic void do_macro_mul_rdrsrs (char *); 276214571Sdimstatic void do_macro_ldst_label (char *); 277214571Sdimstatic void do_branch (char *); 278214571Sdimstatic void do_jump (char *); 279214571Sdimstatic void do_empty (char *); 280214571Sdimstatic void do_rdrsrs (char *); 281214571Sdimstatic void do_rdsi16 (char *); 282214571Sdimstatic void do_rdrssi14 (char *); 283214571Sdimstatic void do_sub_rdsi16 (char *); 284214571Sdimstatic void do_sub_rdrssi14 (char *); 285214571Sdimstatic void do_rdrsi5 (char *); 286214571Sdimstatic void do_rdrsi14 (char *); 287214571Sdimstatic void do_rdi16 (char *); 288214571Sdimstatic void do_xrsi5 (char *); 289214571Sdimstatic void do_rdrs (char *); 290214571Sdimstatic void do_rdxrs (char *); 291214571Sdimstatic void do_rsrs (char *); 292214571Sdimstatic void do_rdcrs (char *); 293214571Sdimstatic void do_rdsrs (char *); 294214571Sdimstatic void do_rd (char *); 295214571Sdimstatic void do_rs (char *); 296214571Sdimstatic void do_i15 (char *); 297214571Sdimstatic void do_xi5x (char *); 298214571Sdimstatic void do_ceinst (char *); 299214571Sdimstatic void do_cache (char *); 300214571Sdimstatic void do16_rdrs (char *); 301214571Sdimstatic void do16_rs (char *); 302214571Sdimstatic void do16_xrs (char *); 303214571Sdimstatic void do16_mv_rdrs (char *); 304214571Sdimstatic void do16_hrdrs (char *); 305214571Sdimstatic void do16_rdhrs (char *); 306214571Sdimstatic void do16_rdi4 (char *); 307214571Sdimstatic void do16_rdi5 (char *); 308214571Sdimstatic void do16_xi5 (char *); 309214571Sdimstatic void do16_ldst_insn (char *); 310214571Sdimstatic void do16_ldst_imm_insn (char *); 311214571Sdimstatic void do16_push_pop (char *); 312214571Sdimstatic void do16_branch (char *); 313214571Sdimstatic void do16_jump (char *); 314214571Sdimstatic void do_rdi16_pic (char *); 315214571Sdimstatic void do_addi_s_pic (char *); 316214571Sdimstatic void do_addi_u_pic (char *); 317214571Sdimstatic void do_lw_pic (char *); 318214571Sdim 319214571Sdimstatic const struct asm_opcode score_ldst_insns[] = 320214571Sdim{ 321214571Sdim {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_ldst_insn}, 322214571Sdim {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, 323214571Sdim {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, do_ldst_insn}, 324214571Sdim {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, do_ldst_insn}, 325214571Sdim {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, 326214571Sdim {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, 327214571Sdim {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn}, 328214571Sdim {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, 329214571Sdim {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, 330214571Sdim {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn}, 331214571Sdim {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, 332214571Sdim {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, 333214571Sdim {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, do_ldst_insn}, 334214571Sdim {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, do_ldst_insn}, 335214571Sdim {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, 336214571Sdim {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, do_ldst_insn}, 337214571Sdim {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn}, 338214571Sdim {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, 339214571Sdim {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, do_ldst_insn}, 340214571Sdim {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, 341214571Sdim {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, 342214571Sdim {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, do_ldst_insn}, 343214571Sdim {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn}, 344214571Sdim {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, 345214571Sdim}; 346214571Sdim 347214571Sdimstatic const struct asm_opcode score_insns[] = 348214571Sdim{ 349214571Sdim {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 350214571Sdim {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 351214571Sdim {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 352214571Sdim {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, do_rdrsrs}, 353214571Sdim {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 354214571Sdim {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 355214571Sdim {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, do_rdrsrs}, 356214571Sdim {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, 357214571Sdim {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, 358214571Sdim {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16}, 359214571Sdim {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16}, 360214571Sdim {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14}, 361214571Sdim {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14}, 362214571Sdim {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, do16_rdrs}, 363214571Sdim {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, do16_rdrs}, 364214571Sdim {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, do16_rdi4}, 365214571Sdim {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16}, 366214571Sdim {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16}, 367214571Sdim {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14}, 368214571Sdim {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14}, 369214571Sdim {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 370214571Sdim {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, do_rdrsrs}, 371214571Sdim {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 372214571Sdim {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 373214571Sdim {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 374214571Sdim {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 375214571Sdim {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, 376214571Sdim {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, 377214571Sdim {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, do16_rdrs}, 378214571Sdim {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 379214571Sdim {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 380214571Sdim {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 381214571Sdim {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 382214571Sdim {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 383214571Sdim {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 384214571Sdim {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, do16_branch}, 385214571Sdim {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, do16_branch}, 386214571Sdim {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, do16_branch}, 387214571Sdim {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 388214571Sdim {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 389214571Sdim {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, do16_branch}, 390214571Sdim {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 391214571Sdim {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 392214571Sdim {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 393214571Sdim {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 394214571Sdim {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 395214571Sdim {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 396214571Sdim {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, do16_branch}, 397214571Sdim {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, do16_branch}, 398214571Sdim {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, do16_branch}, 399214571Sdim {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, do_rdrsi5}, 400214571Sdim {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 401214571Sdim {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, do_rdrsi5}, 402214571Sdim {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, do_xrsi5}, 403214571Sdim {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, do_rdrsi5}, 404214571Sdim {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, do16_rdi5}, 405214571Sdim {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, do16_rdi5}, 406214571Sdim {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, do16_rdi5}, 407214571Sdim {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, do16_rdi5}, 408214571Sdim {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 409214571Sdim {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 410214571Sdim {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 411214571Sdim {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 412214571Sdim {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 413214571Sdim {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 414214571Sdim {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 415214571Sdim {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, do16_branch}, 416214571Sdim {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, do16_branch}, 417214571Sdim {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, do16_branch}, 418214571Sdim {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 419214571Sdim {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 420214571Sdim {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, do16_branch}, 421214571Sdim {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 422214571Sdim {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 423214571Sdim {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, do16_branch}, 424214571Sdim {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 425214571Sdim {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 426214571Sdim {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, do16_branch}, 427214571Sdim {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, do_rs}, 428214571Sdim {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, do_rs}, 429214571Sdim {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, do_rs}, 430214571Sdim {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, do_rs}, 431214571Sdim {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, do_rs}, 432214571Sdim {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, do_rs}, 433214571Sdim {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, do_rs}, 434214571Sdim {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, do_rs}, 435214571Sdim {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, do_rs}, 436214571Sdim {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, do_rs}, 437214571Sdim {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, do_rs}, 438214571Sdim {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, do_rs}, 439214571Sdim {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, do_rs}, 440214571Sdim {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, do_rs}, 441214571Sdim {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, do_rs}, 442214571Sdim {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, do_rs}, 443214571Sdim {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, do_rs}, 444214571Sdim {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, do_rs}, 445214571Sdim {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, do_rs}, 446214571Sdim {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, do_rs}, 447214571Sdim {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, do_rs}, 448214571Sdim {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, do_rs}, 449214571Sdim {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, do_rs}, 450214571Sdim {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, do_rs}, 451214571Sdim {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, do_rs}, 452214571Sdim {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, do_rs}, 453214571Sdim {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, do_rs}, 454214571Sdim {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, do_rs}, 455214571Sdim {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, do_rs}, 456214571Sdim {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, do_rs}, 457214571Sdim {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, do_rs}, 458214571Sdim {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, do_rs}, 459214571Sdim {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, do16_xrs}, 460214571Sdim {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, do16_xrs}, 461214571Sdim {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, do16_xrs}, 462214571Sdim {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, do16_xrs}, 463214571Sdim {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, do16_xrs}, 464214571Sdim {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, do16_xrs}, 465214571Sdim {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, do16_xrs}, 466214571Sdim {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, do16_xrs}, 467214571Sdim {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, do16_xrs}, 468214571Sdim {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, do16_xrs}, 469214571Sdim {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, do16_xrs}, 470214571Sdim {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, do16_xrs}, 471214571Sdim {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, do16_xrs}, 472214571Sdim {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, do16_xrs}, 473214571Sdim {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, do16_xrs}, 474214571Sdim {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, do16_xrs}, 475214571Sdim {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, do16_xrs}, 476214571Sdim {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, do16_xrs}, 477214571Sdim {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, do16_xrs}, 478214571Sdim {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, do16_xrs}, 479214571Sdim {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, do16_xrs}, 480214571Sdim {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, do16_xrs}, 481214571Sdim {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, do16_xrs}, 482214571Sdim {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, do16_xrs}, 483214571Sdim {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, do16_xrs}, 484214571Sdim {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, do16_xrs}, 485214571Sdim {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, do16_xrs}, 486214571Sdim {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, do16_xrs}, 487214571Sdim {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, do16_xrs}, 488214571Sdim {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, do16_xrs}, 489214571Sdim {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, do16_xrs}, 490214571Sdim {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, do16_xrs}, 491214571Sdim {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 492214571Sdim {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 493214571Sdim {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 494214571Sdim {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, 495214571Sdim {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, do16_branch}, 496214571Sdim {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, do16_branch}, 497214571Sdim {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, do16_branch}, 498214571Sdim {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, 499214571Sdim {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, do_cache}, 500214571Sdim {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, do_ceinst}, 501214571Sdim {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 502214571Sdim {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 503214571Sdim {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 504214571Sdim {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, do_rsrs}, 505214571Sdim {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, 506214571Sdim {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, 507214571Sdim {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, 508214571Sdim {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, 509214571Sdim {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, do16_rdrs}, 510214571Sdim {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, 511214571Sdim {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, 512214571Sdim {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, 513214571Sdim {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 514214571Sdim {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 515214571Sdim {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 516214571Sdim {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 517214571Sdim {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 518214571Sdim {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 519214571Sdim {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 520214571Sdim {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 521214571Sdim {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 522214571Sdim {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, do_jump}, 523214571Sdim {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, do16_jump}, 524214571Sdim {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, do16_jump}, 525214571Sdim {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, do_jump}, 526214571Sdim {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, do16_ldst_insn}, 527214571Sdim {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, 528214571Sdim {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, do_ldst_atomic}, 529214571Sdim {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, do_ldst_unalign}, 530214571Sdim {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign}, 531214571Sdim {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign}, 532214571Sdim {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, 533214571Sdim {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, 534214571Sdim {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, 535214571Sdim {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, do16_ldst_insn}, 536214571Sdim {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, 537214571Sdim {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, do_rdsi16}, 538214571Sdim {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, do_rdi16}, 539214571Sdim {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, do16_ldst_imm_insn}, 540214571Sdim {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, do16_ldst_insn}, 541214571Sdim {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, 542214571Sdim {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, 543214571Sdim {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, do16_rs}, 544214571Sdim {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 545214571Sdim {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, do16_rdrs}, 546214571Sdim {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 547214571Sdim {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 548214571Sdim {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, do16_rdrs}, 549214571Sdim {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 550214571Sdim {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 551214571Sdim {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, do16_rdrs}, 552214571Sdim {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 553214571Sdim {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, do16_rdrs}, 554214571Sdim {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 555214571Sdim {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 556214571Sdim {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 557214571Sdim {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 558214571Sdim {"mazh.f!", 0x1009, 0x700f, 0x3800038c, Rd_Rs, do16_rdrs}, 559214571Sdim {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 560214571Sdim {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 561214571Sdim {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, do16_rdrs}, 562214571Sdim {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, 563214571Sdim {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, do16_rs}, 564214571Sdim {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 565214571Sdim {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, do_rdsrs}, 566214571Sdim {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 567214571Sdim {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 568214571Sdim {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 569214571Sdim {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 570214571Sdim {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 571214571Sdim {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 572214571Sdim {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 573214571Sdim {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, do16_hrdrs}, 574214571Sdim {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 575214571Sdim {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, do16_rdhrs}, 576214571Sdim {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 577214571Sdim {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, do16_rdrs}, 578214571Sdim {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 579214571Sdim {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 580214571Sdim {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, do16_rdrs}, 581214571Sdim {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 582214571Sdim {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 583214571Sdim {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, do16_rdrs}, 584214571Sdim {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 585214571Sdim {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, do16_rdrs}, 586214571Sdim {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 587214571Sdim {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 588214571Sdim {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 589214571Sdim {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, do16_rdrs}, 590214571Sdim {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 591214571Sdim {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, 592214571Sdim {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, do16_rdrs}, 593214571Sdim {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, do16_rs}, 594214571Sdim {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, 595214571Sdim {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, 596214571Sdim {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, do16_rs}, 597214571Sdim {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 598214571Sdim {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, do_rdsrs}, 599214571Sdim {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 600214571Sdim {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 601214571Sdim {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 602214571Sdim {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 603214571Sdim {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 604214571Sdim {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 605214571Sdim {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, 606214571Sdim {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, do16_rdrs}, 607214571Sdim {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, do16_rdrs}, 608214571Sdim {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 609214571Sdim {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 610214571Sdim {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 611214571Sdim {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 612214571Sdim {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 613214571Sdim {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 614214571Sdim {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 615214571Sdim {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 616214571Sdim {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 617214571Sdim {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 618214571Sdim {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 619214571Sdim {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 620214571Sdim {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 621214571Sdim {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, 622214571Sdim {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, do_rdrs}, 623214571Sdim {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, do16_mv_rdrs}, 624214571Sdim {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, do_rdxrs}, 625214571Sdim {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, do_rdxrs}, 626214571Sdim {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, do16_rdrs}, 627214571Sdim {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, do_empty}, 628214571Sdim {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, 629214571Sdim {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, do_rdrs}, 630214571Sdim {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, do_empty}, 631214571Sdim {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, do16_rdrs}, 632214571Sdim {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 633214571Sdim {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, do_rdrsrs}, 634214571Sdim {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 635214571Sdim {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 636214571Sdim {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 637214571Sdim {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, 638214571Sdim {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, 639214571Sdim {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, 640214571Sdim {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, do16_rdrs}, 641214571Sdim {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 642214571Sdim {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, do16_push_pop}, 643214571Sdim {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, do16_push_pop}, 644214571Sdim {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 645214571Sdim {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 646214571Sdim {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 647214571Sdim {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 648214571Sdim {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 649214571Sdim {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 650214571Sdim {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 651214571Sdim {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 652214571Sdim {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 653214571Sdim {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 654214571Sdim {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 655214571Sdim {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 656214571Sdim {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 657214571Sdim {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, do16_ldst_insn}, 658214571Sdim {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, 659214571Sdim {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, do_ldst_atomic}, 660214571Sdim {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign}, 661214571Sdim {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign}, 662214571Sdim {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, do_ldst_unalign}, 663214571Sdim {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, do_xi5x}, 664214571Sdim {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, do16_xi5}, 665214571Sdim {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, do16_ldst_insn}, 666214571Sdim {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, 667214571Sdim {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 668214571Sdim {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 669214571Sdim {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, do_rdrsrs}, 670214571Sdim {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 671214571Sdim {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 672214571Sdim {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, do_rdrsi5}, 673214571Sdim {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, do16_rdrs}, 674214571Sdim {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, do16_rdi5}, 675214571Sdim {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 676214571Sdim {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, do_rdrsrs}, 677214571Sdim {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 678214571Sdim {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, do_rdrsrs}, 679214571Sdim {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 680214571Sdim {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, do_rdrsi5}, 681214571Sdim {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 682214571Sdim {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, 683214571Sdim {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, do16_rdrs}, 684214571Sdim {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, do16_rdrs}, 685214571Sdim {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, do16_rdi5}, 686214571Sdim {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, 687214571Sdim {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, 688214571Sdim {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, 689214571Sdim {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 690214571Sdim {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, do_rdrsrs}, 691214571Sdim {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 692214571Sdim {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 693214571Sdim {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 694214571Sdim {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, do16_rdrs}, 695214571Sdim {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, do16_rdi4}, 696214571Sdim {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, do16_ldst_insn}, 697214571Sdim {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, 698214571Sdim {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, do_i15}, 699214571Sdim {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, do_empty}, 700214571Sdim {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, do_empty}, 701214571Sdim {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, do_empty}, 702214571Sdim {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, do_empty}, 703214571Sdim {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, do_empty}, 704214571Sdim {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, do_empty}, 705214571Sdim {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, do_empty}, 706214571Sdim {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, do_empty}, 707214571Sdim {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, do_empty}, 708214571Sdim {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, do_empty}, 709214571Sdim {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, do_empty}, 710214571Sdim {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, do_empty}, 711214571Sdim {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, do_empty}, 712214571Sdim {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, do_empty}, 713214571Sdim {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, do_empty}, 714214571Sdim {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, do_empty}, 715214571Sdim {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, do_empty}, 716214571Sdim {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 717214571Sdim {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 718214571Sdim {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 719214571Sdim {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, 720214571Sdim {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, do_empty}, 721214571Sdim {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, do_empty}, 722214571Sdim {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, do_empty}, 723214571Sdim {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, do_empty}, 724214571Sdim {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, do_empty}, 725214571Sdim {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, do_empty}, 726214571Sdim {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, do_empty}, 727214571Sdim {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, do_empty}, 728214571Sdim {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, do_empty}, 729214571Sdim {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 730214571Sdim {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 731214571Sdim {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 732214571Sdim {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 733214571Sdim {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 734214571Sdim {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 735214571Sdim {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 736214571Sdim {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 737214571Sdim {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 738214571Sdim {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 739214571Sdim {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 740214571Sdim {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 741214571Sdim {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 742214571Sdim {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 743214571Sdim {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, 744214571Sdim {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, do_empty}, 745214571Sdim {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, do_empty}, 746214571Sdim {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, do_empty}, 747214571Sdim {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, do_empty}, 748214571Sdim {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, do_empty}, 749214571Sdim {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, do_empty}, 750214571Sdim {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, 751214571Sdim {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, do_rdrsrs}, 752214571Sdim {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, do16_rdrs}, 753214571Sdim /* Macro instruction. */ 754214571Sdim {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_li_rdi32}, 755214571Sdim /* la reg, imm32 -->(1) ldi reg, simm16 756214571Sdim (2) ldis reg, %HI(imm32) 757214571Sdim ori reg, %LO(imm32) 758214571Sdim 759214571Sdim la reg, symbol -->(1) lis reg, %HI(imm32) 760214571Sdim ori reg, %LO(imm32) */ 761214571Sdim {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_la_rdi32}, 762214571Sdim {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 763214571Sdim {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 764214571Sdim {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 765214571Sdim {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 766214571Sdim {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 767214571Sdim {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 768214571Sdim {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 769214571Sdim {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 770214571Sdim {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 771214571Sdim {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, 772214571Sdim {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label}, 773214571Sdim {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, do_macro_ldst_label}, 774214571Sdim {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, do_macro_ldst_label}, 775214571Sdim {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label}, 776214571Sdim {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, do_macro_ldst_label}, 777214571Sdim {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, do_macro_ldst_label}, 778214571Sdim {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, do_macro_ldst_label}, 779214571Sdim {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, do_macro_ldst_label}, 780214571Sdim /* Assembler use internal. */ 781214571Sdim {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, do_macro_rdi32hi}, 782214571Sdim {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, do_macro_rdi32lo}, 783214571Sdim {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, do_rdi16_pic}, 784214571Sdim {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_s_pic}, 785214571Sdim {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_u_pic}, 786214571Sdim {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, do_lw_pic}, 787214571Sdim}; 788214571Sdim 789214571Sdim/* Next free entry in the pool. */ 790214571Sdimint next_literal_pool_place = 0; 791214571Sdim 792214571Sdim/* Next literal pool number. */ 793214571Sdimint lit_pool_num = 1; 794214571SdimsymbolS *current_poolP = NULL; 795214571Sdim 796214571Sdim 797214571Sdimstatic int 798214571Sdimend_of_line (char *str) 799214571Sdim{ 800214571Sdim int retval = SUCCESS; 801214571Sdim 802214571Sdim skip_whitespace (str); 803214571Sdim if (*str != '\0') 804214571Sdim { 805214571Sdim retval = (int) FAIL; 806214571Sdim 807214571Sdim if (!inst.error) 808214571Sdim inst.error = BAD_GARBAGE; 809214571Sdim } 810214571Sdim 811214571Sdim return retval; 812214571Sdim} 813214571Sdim 814214571Sdimstatic int 815214571Sdimscore_reg_parse (char **ccp, struct hash_control *htab) 816214571Sdim{ 817214571Sdim char *start = *ccp; 818214571Sdim char c; 819214571Sdim char *p; 820214571Sdim struct reg_entry *reg; 821214571Sdim 822214571Sdim p = start; 823214571Sdim if (!ISALPHA (*p) || !is_name_beginner (*p)) 824214571Sdim return (int) FAIL; 825214571Sdim 826214571Sdim c = *p++; 827214571Sdim 828214571Sdim while (ISALPHA (c) || ISDIGIT (c) || c == '_') 829214571Sdim c = *p++; 830214571Sdim 831214571Sdim *--p = 0; 832214571Sdim reg = (struct reg_entry *) hash_find (htab, start); 833214571Sdim *p = c; 834214571Sdim 835214571Sdim if (reg) 836214571Sdim { 837214571Sdim *ccp = p; 838214571Sdim return reg->number; 839214571Sdim } 840214571Sdim return (int) FAIL; 841214571Sdim} 842214571Sdim 843214571Sdim/* If shift <= 0, only return reg. */ 844214571Sdim 845214571Sdimstatic int 846214571Sdimreg_required_here (char **str, int shift, enum score_reg_type reg_type) 847214571Sdim{ 848214571Sdim static char buff[MAX_LITERAL_POOL_SIZE]; 849214571Sdim int reg = (int) FAIL; 850214571Sdim char *start = *str; 851214571Sdim 852214571Sdim if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL) 853214571Sdim { 854214571Sdim if (reg_type == REG_TYPE_SCORE) 855214571Sdim { 856214571Sdim if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0)) 857214571Sdim { 858214571Sdim as_warn (_("Using temp register(r1)")); 859214571Sdim inst.bwarn = 1; 860214571Sdim } 861214571Sdim } 862214571Sdim if (shift >= 0) 863214571Sdim { 864214571Sdim if (reg_type == REG_TYPE_SCORE_CR) 865214571Sdim strcpy (inst.reg, score_crn_table[reg].name); 866214571Sdim else if (reg_type == REG_TYPE_SCORE_SR) 867214571Sdim strcpy (inst.reg, score_srn_table[reg].name); 868214571Sdim else 869214571Sdim strcpy (inst.reg, ""); 870214571Sdim 871214571Sdim inst.instruction |= reg << shift; 872214571Sdim } 873214571Sdim } 874214571Sdim else 875214571Sdim { 876214571Sdim *str = start; 877214571Sdim sprintf (buff, _("register expected, not '%.100s'"), start); 878214571Sdim inst.error = buff; 879214571Sdim } 880214571Sdim 881214571Sdim return reg; 882214571Sdim} 883214571Sdim 884214571Sdimstatic int 885214571Sdimskip_past_comma (char **str) 886214571Sdim{ 887214571Sdim char *p = *str; 888214571Sdim char c; 889214571Sdim int comma = 0; 890214571Sdim 891214571Sdim while ((c = *p) == ' ' || c == ',') 892214571Sdim { 893214571Sdim p++; 894214571Sdim if (c == ',' && comma++) 895214571Sdim { 896214571Sdim inst.error = BAD_SKIP_COMMA; 897214571Sdim return (int) FAIL; 898214571Sdim } 899214571Sdim } 900214571Sdim 901214571Sdim if ((c == '\0') || (comma == 0)) 902214571Sdim { 903214571Sdim inst.error = BAD_SKIP_COMMA; 904214571Sdim return (int) FAIL; 905214571Sdim } 906214571Sdim 907214571Sdim *str = p; 908214571Sdim return comma ? SUCCESS : (int) FAIL; 909214571Sdim} 910214571Sdim 911214571Sdimstatic void 912214571Sdimdo_rdrsrs (char *str) 913214571Sdim{ 914214571Sdim skip_whitespace (str); 915214571Sdim 916214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 917214571Sdim || skip_past_comma (&str) == (int) FAIL 918214571Sdim || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 919214571Sdim || skip_past_comma (&str) == (int) FAIL 920214571Sdim || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL 921214571Sdim || end_of_line (str) == (int) FAIL) 922214571Sdim { 923214571Sdim return; 924214571Sdim } 925214571Sdim else 926214571Sdim { 927214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) 928214571Sdim && (((inst.instruction >> 10) & 0x10) == 0) 929214571Sdim && (((inst.instruction >> 20) & 0x10) == 0) 930214571Sdim && (inst.relax_inst != 0x8000) 931214571Sdim && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf))) 932214571Sdim { 933214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) 934214571Sdim | (((inst.instruction >> 15) & 0xf) << 8); 935214571Sdim inst.relax_size = 2; 936214571Sdim } 937214571Sdim else 938214571Sdim { 939214571Sdim inst.relax_inst = 0x8000; 940214571Sdim } 941214571Sdim } 942214571Sdim} 943214571Sdim 944214571Sdimstatic int 945214571Sdimwalk_no_bignums (symbolS * sp) 946214571Sdim{ 947214571Sdim if (symbol_get_value_expression (sp)->X_op == O_big) 948214571Sdim return 1; 949214571Sdim 950214571Sdim if (symbol_get_value_expression (sp)->X_add_symbol) 951214571Sdim return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) 952214571Sdim || (symbol_get_value_expression (sp)->X_op_symbol 953214571Sdim && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); 954214571Sdim 955214571Sdim return 0; 956214571Sdim} 957214571Sdim 958214571Sdimstatic int 959214571Sdimmy_get_expression (expressionS * ep, char **str) 960214571Sdim{ 961214571Sdim char *save_in; 962214571Sdim segT seg; 963214571Sdim 964214571Sdim save_in = input_line_pointer; 965214571Sdim input_line_pointer = *str; 966214571Sdim in_my_get_expression = 1; 967214571Sdim seg = expression (ep); 968214571Sdim in_my_get_expression = 0; 969214571Sdim 970214571Sdim if (ep->X_op == O_illegal) 971214571Sdim { 972214571Sdim *str = input_line_pointer; 973214571Sdim input_line_pointer = save_in; 974214571Sdim inst.error = _("illegal expression"); 975214571Sdim return (int) FAIL; 976214571Sdim } 977214571Sdim /* Get rid of any bignums now, so that we don't generate an error for which 978214571Sdim we can't establish a line number later on. Big numbers are never valid 979214571Sdim in instructions, which is where this routine is always called. */ 980214571Sdim if (ep->X_op == O_big 981214571Sdim || (ep->X_add_symbol 982214571Sdim && (walk_no_bignums (ep->X_add_symbol) 983214571Sdim || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol))))) 984214571Sdim { 985214571Sdim inst.error = _("invalid constant"); 986214571Sdim *str = input_line_pointer; 987214571Sdim input_line_pointer = save_in; 988214571Sdim return (int) FAIL; 989214571Sdim } 990214571Sdim 991214571Sdim if ((ep->X_add_symbol != NULL) 992214571Sdim && (inst.type != PC_DISP19div2) 993214571Sdim && (inst.type != PC_DISP8div2) 994214571Sdim && (inst.type != PC_DISP24div2) 995214571Sdim && (inst.type != PC_DISP11div2) 996214571Sdim && (inst.type != Insn_Type_SYN) 997214571Sdim && (inst.type != Rd_rvalueRs_SI15) 998214571Sdim && (inst.type != Rd_lvalueRs_SI15) 999214571Sdim && (inst.type != Insn_internal)) 1000214571Sdim { 1001214571Sdim inst.error = BAD_ARGS; 1002214571Sdim *str = input_line_pointer; 1003214571Sdim input_line_pointer = save_in; 1004214571Sdim return (int) FAIL; 1005214571Sdim } 1006214571Sdim 1007214571Sdim *str = input_line_pointer; 1008214571Sdim input_line_pointer = save_in; 1009214571Sdim return SUCCESS; 1010214571Sdim} 1011214571Sdim 1012214571Sdim/* Check if an immediate is valid. If so, convert it to the right format. */ 1013214571Sdim 1014214571Sdimstatic int 1015214571Sdimvalidate_immediate (int val, unsigned int data_type, int hex_p) 1016214571Sdim{ 1017214571Sdim switch (data_type) 1018214571Sdim { 1019214571Sdim case _VALUE_HI16: 1020214571Sdim { 1021214571Sdim int val_hi = ((val & 0xffff0000) >> 16); 1022214571Sdim 1023214571Sdim if (score_df_range[data_type].range[0] <= val_hi 1024214571Sdim && val_hi <= score_df_range[data_type].range[1]) 1025214571Sdim return val_hi; 1026214571Sdim } 1027214571Sdim break; 1028214571Sdim 1029214571Sdim case _VALUE_LO16: 1030214571Sdim { 1031214571Sdim int val_lo = (val & 0xffff); 1032214571Sdim 1033214571Sdim if (score_df_range[data_type].range[0] <= val_lo 1034214571Sdim && val_lo <= score_df_range[data_type].range[1]) 1035214571Sdim return val_lo; 1036214571Sdim } 1037214571Sdim break; 1038214571Sdim 1039214571Sdim case _VALUE: 1040214571Sdim return val; 1041214571Sdim break; 1042214571Sdim 1043214571Sdim case _SIMM14: 1044214571Sdim if (hex_p == 1) 1045214571Sdim { 1046214571Sdim if (!(val >= -0x2000 && val <= 0x3fff)) 1047214571Sdim { 1048214571Sdim return (int) FAIL; 1049214571Sdim } 1050214571Sdim } 1051214571Sdim else 1052214571Sdim { 1053214571Sdim if (!(val >= -8192 && val <= 8191)) 1054214571Sdim { 1055214571Sdim return (int) FAIL; 1056214571Sdim } 1057214571Sdim } 1058214571Sdim 1059214571Sdim return val; 1060214571Sdim break; 1061214571Sdim 1062214571Sdim case _SIMM16_NEG: 1063214571Sdim if (hex_p == 1) 1064214571Sdim { 1065214571Sdim if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000)) 1066214571Sdim { 1067214571Sdim return (int) FAIL; 1068214571Sdim } 1069214571Sdim } 1070214571Sdim else 1071214571Sdim { 1072214571Sdim if (!(val >= -32767 && val <= 32768)) 1073214571Sdim { 1074214571Sdim return (int) FAIL; 1075214571Sdim } 1076214571Sdim } 1077214571Sdim 1078214571Sdim val = -val; 1079214571Sdim return val; 1080214571Sdim break; 1081214571Sdim 1082214571Sdim default: 1083214571Sdim if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG) 1084214571Sdim val = -val; 1085214571Sdim 1086214571Sdim if (score_df_range[data_type].range[0] <= val 1087214571Sdim && val <= score_df_range[data_type].range[1]) 1088214571Sdim return val; 1089214571Sdim 1090214571Sdim break; 1091214571Sdim } 1092214571Sdim 1093214571Sdim return (int) FAIL; 1094214571Sdim} 1095214571Sdim 1096214571Sdimstatic int 1097214571Sdimdata_op2 (char **str, int shift, enum score_data_type data_type) 1098214571Sdim{ 1099214571Sdim int value; 1100214571Sdim char data_exp[MAX_LITERAL_POOL_SIZE]; 1101214571Sdim char *dataptr; 1102214571Sdim int cnt = 0; 1103214571Sdim char *pp = NULL; 1104214571Sdim 1105214571Sdim skip_whitespace (*str); 1106214571Sdim inst.error = NULL; 1107214571Sdim dataptr = * str; 1108214571Sdim 1109214571Sdim /* Set hex_p to zero. */ 1110214571Sdim int hex_p = 0; 1111214571Sdim 1112214571Sdim while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */ 1113214571Sdim { 1114214571Sdim data_exp[cnt] = *dataptr; 1115214571Sdim dataptr++; 1116214571Sdim cnt++; 1117214571Sdim } 1118214571Sdim 1119214571Sdim data_exp[cnt] = '\0'; 1120214571Sdim pp = (char *)&data_exp; 1121214571Sdim 1122214571Sdim if (*dataptr == '|') /* process PCE */ 1123214571Sdim { 1124214571Sdim if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL) 1125214571Sdim return (int) FAIL; 1126214571Sdim end_of_line (pp); 1127214571Sdim if (inst.error != 0) 1128214571Sdim return (int) FAIL; /* to ouptut_inst to printf out the error */ 1129214571Sdim *str = dataptr; 1130214571Sdim } 1131214571Sdim else /* process 16 bit */ 1132214571Sdim { 1133214571Sdim if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL) 1134214571Sdim { 1135214571Sdim return (int) FAIL; 1136214571Sdim } 1137214571Sdim 1138214571Sdim dataptr = (char *)data_exp; 1139214571Sdim for (; *dataptr != '\0'; dataptr++) 1140214571Sdim { 1141214571Sdim *dataptr = TOLOWER (*dataptr); 1142214571Sdim if (*dataptr == '!' || *dataptr == ' ') 1143214571Sdim break; 1144214571Sdim } 1145214571Sdim dataptr = (char *)data_exp; 1146214571Sdim 1147214571Sdim if ((dataptr != NULL) 1148214571Sdim && (((strstr (dataptr, "0x")) != NULL) 1149214571Sdim || ((strstr (dataptr, "0X")) != NULL))) 1150214571Sdim { 1151214571Sdim hex_p = 1; 1152214571Sdim if ((data_type != _SIMM16_LA) 1153214571Sdim && (data_type != _VALUE_HI16) 1154214571Sdim && (data_type != _VALUE_LO16) 1155214571Sdim && (data_type != _IMM16) 1156214571Sdim && (data_type != _IMM15) 1157214571Sdim && (data_type != _IMM14) 1158214571Sdim && (data_type != _IMM4) 1159214571Sdim && (data_type != _IMM5) 1160214571Sdim && (data_type != _IMM8) 1161214571Sdim && (data_type != _IMM5_RSHIFT_1) 1162214571Sdim && (data_type != _IMM5_RSHIFT_2) 1163214571Sdim && (data_type != _SIMM14) 1164214571Sdim && (data_type != _SIMM14_NEG) 1165214571Sdim && (data_type != _SIMM16_NEG) 1166214571Sdim && (data_type != _IMM10_RSHIFT_2) 1167214571Sdim && (data_type != _GP_IMM15)) 1168214571Sdim { 1169214571Sdim data_type += 24; 1170214571Sdim } 1171214571Sdim } 1172214571Sdim 1173214571Sdim if ((inst.reloc.exp.X_add_number == 0) 1174214571Sdim && (inst.type != Insn_Type_SYN) 1175214571Sdim && (inst.type != Rd_rvalueRs_SI15) 1176214571Sdim && (inst.type != Rd_lvalueRs_SI15) 1177214571Sdim && (inst.type != Insn_internal) 1178214571Sdim && (((*dataptr >= 'a') && (*dataptr <= 'z')) 1179214571Sdim || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0')) 1180214571Sdim || ((*dataptr == '+') && (*(dataptr + 1) != '0')) 1181214571Sdim || ((*dataptr == '-') && (*(dataptr + 1) != '0')))) 1182214571Sdim { 1183214571Sdim inst.error = BAD_ARGS; 1184214571Sdim return (int) FAIL; 1185214571Sdim } 1186214571Sdim } 1187214571Sdim 1188214571Sdim if ((inst.reloc.exp.X_add_symbol) 1189214571Sdim && ((data_type == _SIMM16) 1190214571Sdim || (data_type == _SIMM16_NEG) 1191214571Sdim || (data_type == _IMM16_NEG) 1192214571Sdim || (data_type == _SIMM14) 1193214571Sdim || (data_type == _SIMM14_NEG) 1194214571Sdim || (data_type == _IMM5) 1195214571Sdim || (data_type == _IMM14) 1196214571Sdim || (data_type == _IMM20) 1197214571Sdim || (data_type == _IMM16) 1198214571Sdim || (data_type == _IMM15) 1199214571Sdim || (data_type == _IMM4))) 1200214571Sdim { 1201214571Sdim inst.error = BAD_ARGS; 1202214571Sdim return (int) FAIL; 1203214571Sdim } 1204214571Sdim 1205214571Sdim if (inst.reloc.exp.X_add_symbol) 1206214571Sdim { 1207214571Sdim switch (data_type) 1208214571Sdim { 1209214571Sdim case _SIMM16_LA: 1210214571Sdim return (int) FAIL; 1211214571Sdim case _VALUE_HI16: 1212214571Sdim inst.reloc.type = BFD_RELOC_HI16_S; 1213214571Sdim inst.reloc.pc_rel = 0; 1214214571Sdim break; 1215214571Sdim case _VALUE_LO16: 1216214571Sdim inst.reloc.type = BFD_RELOC_LO16; 1217214571Sdim inst.reloc.pc_rel = 0; 1218214571Sdim break; 1219214571Sdim case _GP_IMM15: 1220214571Sdim inst.reloc.type = BFD_RELOC_SCORE_GPREL15; 1221214571Sdim inst.reloc.pc_rel = 0; 1222214571Sdim break; 1223214571Sdim case _SIMM16_pic: 1224214571Sdim case _IMM16_LO16_pic: 1225214571Sdim inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16; 1226214571Sdim inst.reloc.pc_rel = 0; 1227214571Sdim break; 1228214571Sdim default: 1229214571Sdim inst.reloc.type = BFD_RELOC_32; 1230214571Sdim inst.reloc.pc_rel = 0; 1231214571Sdim break; 1232214571Sdim } 1233214571Sdim } 1234214571Sdim else 1235214571Sdim { 1236214571Sdim if (data_type == _IMM16_pic) 1237214571Sdim { 1238214571Sdim inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16; 1239214571Sdim inst.reloc.pc_rel = 0; 1240214571Sdim } 1241214571Sdim 1242214571Sdim if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1) 1243214571Sdim { 1244214571Sdim value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p); 1245214571Sdim if (value == (int) FAIL) /* for advance to check if this is ldis */ 1246214571Sdim if ((inst.reloc.exp.X_add_number & 0xffff) == 0) 1247214571Sdim { 1248214571Sdim inst.instruction |= 0x8000000; 1249214571Sdim inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe; 1250214571Sdim return SUCCESS; 1251214571Sdim } 1252214571Sdim } 1253214571Sdim else 1254214571Sdim { 1255214571Sdim value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p); 1256214571Sdim } 1257214571Sdim 1258214571Sdim if (value == (int) FAIL) 1259214571Sdim { 1260214571Sdim if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG)) 1261214571Sdim { 1262214571Sdim sprintf (err_msg, 1263214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 1264214571Sdim score_df_range[data_type].bits, 1265214571Sdim score_df_range[data_type].range[0], score_df_range[data_type].range[1]); 1266214571Sdim } 1267214571Sdim else 1268214571Sdim { 1269214571Sdim sprintf (err_msg, 1270214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 1271214571Sdim score_df_range[data_type].bits, 1272214571Sdim -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]); 1273214571Sdim } 1274214571Sdim 1275214571Sdim inst.error = err_msg; 1276214571Sdim return (int) FAIL; 1277214571Sdim } 1278214571Sdim 1279214571Sdim if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31)) 1280214571Sdim { 1281214571Sdim value &= (1 << score_df_range[data_type].bits) - 1; 1282214571Sdim } 1283214571Sdim 1284214571Sdim inst.instruction |= value << shift; 1285214571Sdim } 1286214571Sdim 1287214571Sdim if ((inst.instruction & 0xf0000000) == 0x30000000) 1288214571Sdim { 1289214571Sdim if ((((inst.instruction >> 20) & 0x1F) != 0) 1290214571Sdim && (((inst.instruction >> 20) & 0x1F) != 1) 1291214571Sdim && (((inst.instruction >> 20) & 0x1F) != 2) 1292214571Sdim && (((inst.instruction >> 20) & 0x1F) != 3) 1293214571Sdim && (((inst.instruction >> 20) & 0x1F) != 4) 1294214571Sdim && (((inst.instruction >> 20) & 0x1F) != 8) 1295214571Sdim && (((inst.instruction >> 20) & 0x1F) != 9) 1296214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0xa) 1297214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0xb) 1298214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0xc) 1299214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0xd) 1300214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0xe) 1301214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x10) 1302214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x11) 1303214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x18) 1304214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x1A) 1305214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x1B) 1306214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x1d) 1307214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x1e) 1308214571Sdim && (((inst.instruction >> 20) & 0x1F) != 0x1f)) 1309214571Sdim { 1310214571Sdim inst.error = _("invalid constant: bit expression not defined"); 1311214571Sdim return (int) FAIL; 1312214571Sdim } 1313214571Sdim } 1314214571Sdim 1315214571Sdim return SUCCESS; 1316214571Sdim} 1317214571Sdim 1318214571Sdim/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */ 1319214571Sdim 1320214571Sdimstatic void 1321214571Sdimdo_rdsi16 (char *str) 1322214571Sdim{ 1323214571Sdim skip_whitespace (str); 1324214571Sdim 1325214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 1326214571Sdim || skip_past_comma (&str) == (int) FAIL 1327214571Sdim || data_op2 (&str, 1, _SIMM16) == (int) FAIL 1328214571Sdim || end_of_line (str) == (int) FAIL) 1329214571Sdim return; 1330214571Sdim 1331214571Sdim /* ldi. */ 1332214571Sdim if ((inst.instruction & 0x20c0000) == 0x20c0000) 1333214571Sdim { 1334214571Sdim if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0)) 1335214571Sdim { 1336214571Sdim inst.relax_inst = 0x8000; 1337214571Sdim } 1338214571Sdim else 1339214571Sdim { 1340214571Sdim inst.relax_inst |= (inst.instruction >> 1) & 0xff; 1341214571Sdim inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8); 1342214571Sdim inst.relax_size = 2; 1343214571Sdim } 1344214571Sdim } 1345214571Sdim else if (((inst.instruction >> 20) & 0x10) == 0x10) 1346214571Sdim { 1347214571Sdim inst.relax_inst = 0x8000; 1348214571Sdim } 1349214571Sdim} 1350214571Sdim 1351214571Sdim/* Handle subi/subi.c. */ 1352214571Sdim 1353214571Sdimstatic void 1354214571Sdimdo_sub_rdsi16 (char *str) 1355214571Sdim{ 1356214571Sdim skip_whitespace (str); 1357214571Sdim 1358214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1359214571Sdim && skip_past_comma (&str) != (int) FAIL 1360214571Sdim && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL) 1361214571Sdim end_of_line (str); 1362214571Sdim} 1363214571Sdim 1364214571Sdim/* Handle addri/addri.c. */ 1365214571Sdim 1366214571Sdimstatic void 1367214571Sdimdo_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ 1368214571Sdim{ 1369214571Sdim skip_whitespace (str); 1370214571Sdim 1371214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1372214571Sdim && skip_past_comma (&str) != (int) FAIL 1373214571Sdim && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL 1374214571Sdim && skip_past_comma (&str) != (int) FAIL) 1375214571Sdim data_op2 (&str, 1, _SIMM14); 1376214571Sdim} 1377214571Sdim 1378214571Sdim/* Handle subri.c/subri. */ 1379214571Sdimstatic void 1380214571Sdimdo_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ 1381214571Sdim{ 1382214571Sdim skip_whitespace (str); 1383214571Sdim 1384214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1385214571Sdim && skip_past_comma (&str) != (int) FAIL 1386214571Sdim && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL 1387214571Sdim && skip_past_comma (&str) != (int) FAIL 1388214571Sdim && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL) 1389214571Sdim end_of_line (str); 1390214571Sdim} 1391214571Sdim 1392214571Sdim/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */ 1393214571Sdimstatic void 1394214571Sdimdo_rdrsi5 (char *str) /* 0~((2^14)-1) */ 1395214571Sdim{ 1396214571Sdim skip_whitespace (str); 1397214571Sdim 1398214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 1399214571Sdim || skip_past_comma (&str) == (int) FAIL 1400214571Sdim || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1401214571Sdim || skip_past_comma (&str) == (int) FAIL 1402214571Sdim || data_op2 (&str, 10, _IMM5) == (int) FAIL 1403214571Sdim || end_of_line (str) == (int) FAIL) 1404214571Sdim return; 1405214571Sdim 1406214571Sdim if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f)) 1407214571Sdim && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) 1408214571Sdim { 1409214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8); 1410214571Sdim inst.relax_size = 2; 1411214571Sdim } 1412214571Sdim else 1413214571Sdim inst.relax_inst = 0x8000; 1414214571Sdim} 1415214571Sdim 1416214571Sdim/* Handle andri/orri/andri.c/orri.c. */ 1417214571Sdim 1418214571Sdimstatic void 1419214571Sdimdo_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */ 1420214571Sdim{ 1421214571Sdim skip_whitespace (str); 1422214571Sdim 1423214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1424214571Sdim && skip_past_comma (&str) != (int) FAIL 1425214571Sdim && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL 1426214571Sdim && skip_past_comma (&str) != (int) FAIL 1427214571Sdim && data_op2 (&str, 1, _IMM14) != (int) FAIL) 1428214571Sdim end_of_line (str); 1429214571Sdim} 1430214571Sdim 1431214571Sdim/* Handle bittst.c. */ 1432214571Sdimstatic void 1433214571Sdimdo_xrsi5 (char *str) 1434214571Sdim{ 1435214571Sdim skip_whitespace (str); 1436214571Sdim 1437214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1438214571Sdim || skip_past_comma (&str) == (int) FAIL 1439214571Sdim || data_op2 (&str, 10, _IMM5) == (int) FAIL 1440214571Sdim || end_of_line (str) == (int) FAIL) 1441214571Sdim return; 1442214571Sdim 1443214571Sdim if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) 1444214571Sdim { 1445214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8); 1446214571Sdim inst.relax_size = 2; 1447214571Sdim } 1448214571Sdim else 1449214571Sdim inst.relax_inst = 0x8000; 1450214571Sdim} 1451214571Sdim 1452214571Sdim/* Handle addis/andi/ori/andis/oris/ldis. */ 1453214571Sdimstatic void 1454214571Sdimdo_rdi16 (char *str) 1455214571Sdim{ 1456214571Sdim skip_whitespace (str); 1457214571Sdim 1458214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 1459214571Sdim || skip_past_comma (&str) == (int) FAIL 1460214571Sdim || data_op2 (&str, 1, _IMM16) == (int) FAIL 1461214571Sdim || end_of_line (str) == (int) FAIL) 1462214571Sdim return; 1463214571Sdim /* 1464214571Sdim if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10)) 1465214571Sdim inst.relax_inst = 0x8000; 1466214571Sdim else 1467214571Sdim inst.relax_size = 2; 1468214571Sdim */ 1469214571Sdim} 1470214571Sdim 1471214571Sdimstatic void 1472214571Sdimdo_macro_rdi32hi (char *str) 1473214571Sdim{ 1474214571Sdim skip_whitespace (str); 1475214571Sdim 1476214571Sdim /* Do not handle end_of_line(). */ 1477214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1478214571Sdim && skip_past_comma (&str) != (int) FAIL) 1479214571Sdim data_op2 (&str, 1, _VALUE_HI16); 1480214571Sdim} 1481214571Sdim 1482214571Sdimstatic void 1483214571Sdimdo_macro_rdi32lo (char *str) 1484214571Sdim{ 1485214571Sdim skip_whitespace (str); 1486214571Sdim 1487214571Sdim /* Do not handle end_of_line(). */ 1488214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1489214571Sdim && skip_past_comma (&str) != (int) FAIL) 1490214571Sdim data_op2 (&str, 1, _VALUE_LO16); 1491214571Sdim} 1492214571Sdim 1493214571Sdim/* Handle ldis_pic. */ 1494214571Sdim 1495214571Sdimstatic void 1496214571Sdimdo_rdi16_pic (char *str) 1497214571Sdim{ 1498214571Sdim skip_whitespace (str); 1499214571Sdim 1500214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1501214571Sdim && skip_past_comma (&str) != (int) FAIL 1502214571Sdim && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL) 1503214571Sdim end_of_line (str); 1504214571Sdim} 1505214571Sdim 1506214571Sdim/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */ 1507214571Sdim 1508214571Sdimstatic void 1509214571Sdimdo_addi_s_pic (char *str) 1510214571Sdim{ 1511214571Sdim skip_whitespace (str); 1512214571Sdim 1513214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1514214571Sdim && skip_past_comma (&str) != (int) FAIL 1515214571Sdim && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL) 1516214571Sdim end_of_line (str); 1517214571Sdim} 1518214571Sdim 1519214571Sdim/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */ 1520214571Sdim 1521214571Sdimstatic void 1522214571Sdimdo_addi_u_pic (char *str) 1523214571Sdim{ 1524214571Sdim skip_whitespace (str); 1525214571Sdim 1526214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1527214571Sdim && skip_past_comma (&str) != (int) FAIL 1528214571Sdim && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL) 1529214571Sdim end_of_line (str); 1530214571Sdim} 1531214571Sdim 1532214571Sdim/* Handle mfceh/mfcel/mtceh/mtchl. */ 1533214571Sdim 1534214571Sdimstatic void 1535214571Sdimdo_rd (char *str) 1536214571Sdim{ 1537214571Sdim skip_whitespace (str); 1538214571Sdim 1539214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL) 1540214571Sdim end_of_line (str); 1541214571Sdim} 1542214571Sdim 1543214571Sdimstatic void 1544214571Sdimdo_rs (char *str) 1545214571Sdim{ 1546214571Sdim skip_whitespace (str); 1547214571Sdim 1548214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1549214571Sdim || end_of_line (str) == (int) FAIL) 1550214571Sdim return; 1551214571Sdim 1552214571Sdim if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) 1553214571Sdim { 1554214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4); 1555214571Sdim inst.relax_size = 2; 1556214571Sdim } 1557214571Sdim else 1558214571Sdim inst.relax_inst = 0x8000; 1559214571Sdim} 1560214571Sdim 1561214571Sdimstatic void 1562214571Sdimdo_i15 (char *str) 1563214571Sdim{ 1564214571Sdim skip_whitespace (str); 1565214571Sdim 1566214571Sdim if (data_op2 (&str, 10, _IMM15) != (int) FAIL) 1567214571Sdim end_of_line (str); 1568214571Sdim} 1569214571Sdim 1570214571Sdimstatic void 1571214571Sdimdo_xi5x (char *str) 1572214571Sdim{ 1573214571Sdim skip_whitespace (str); 1574214571Sdim 1575214571Sdim if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL) 1576214571Sdim return; 1577214571Sdim 1578214571Sdim if (inst.relax_inst != 0x8000) 1579214571Sdim { 1580214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3); 1581214571Sdim inst.relax_size = 2; 1582214571Sdim } 1583214571Sdim} 1584214571Sdim 1585214571Sdimstatic void 1586214571Sdimdo_rdrs (char *str) 1587214571Sdim{ 1588214571Sdim skip_whitespace (str); 1589214571Sdim 1590214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 1591214571Sdim || skip_past_comma (&str) == (int) FAIL 1592214571Sdim || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1593214571Sdim || end_of_line (str) == (int) FAIL) 1594214571Sdim return; 1595214571Sdim 1596214571Sdim if (inst.relax_inst != 0x8000) 1597214571Sdim { 1598214571Sdim if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */ 1599214571Sdim { 1600214571Sdim /* mlfh */ 1601214571Sdim if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) 1602214571Sdim { 1603214571Sdim inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4) 1604214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 1605214571Sdim inst.relax_size = 2; 1606214571Sdim } 1607214571Sdim /* mhfl */ 1608214571Sdim else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0) 1609214571Sdim { 1610214571Sdim inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4) 1611214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 1612214571Sdim inst.relax_size = 2; 1613214571Sdim } 1614214571Sdim else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) 1615214571Sdim { 1616214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 1617214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 1618214571Sdim inst.relax_size = 2; 1619214571Sdim } 1620214571Sdim else 1621214571Sdim { 1622214571Sdim inst.relax_inst = 0x8000; 1623214571Sdim } 1624214571Sdim } 1625214571Sdim else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) 1626214571Sdim { 1627214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 1628214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 1629214571Sdim inst.relax_size = 2; 1630214571Sdim } 1631214571Sdim else 1632214571Sdim { 1633214571Sdim inst.relax_inst = 0x8000; 1634214571Sdim } 1635214571Sdim } 1636214571Sdim} 1637214571Sdim 1638214571Sdim/* Handle mfcr/mtcr. */ 1639214571Sdimstatic void 1640214571Sdimdo_rdcrs (char *str) 1641214571Sdim{ 1642214571Sdim skip_whitespace (str); 1643214571Sdim 1644214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1645214571Sdim && skip_past_comma (&str) != (int) FAIL 1646214571Sdim && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL) 1647214571Sdim end_of_line (str); 1648214571Sdim} 1649214571Sdim 1650214571Sdim/* Handle mfsr/mtsr. */ 1651214571Sdim 1652214571Sdimstatic void 1653214571Sdimdo_rdsrs (char *str) 1654214571Sdim{ 1655214571Sdim skip_whitespace (str); 1656214571Sdim 1657214571Sdim /* mfsr */ 1658214571Sdim if ((inst.instruction & 0xff) == 0x50) 1659214571Sdim { 1660214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL 1661214571Sdim && skip_past_comma (&str) != (int) FAIL 1662214571Sdim && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL) 1663214571Sdim end_of_line (str); 1664214571Sdim } 1665214571Sdim else 1666214571Sdim { 1667214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL 1668214571Sdim && skip_past_comma (&str) != (int) FAIL) 1669214571Sdim reg_required_here (&str, 10, REG_TYPE_SCORE_SR); 1670214571Sdim } 1671214571Sdim} 1672214571Sdim 1673214571Sdim/* Handle neg. */ 1674214571Sdim 1675214571Sdimstatic void 1676214571Sdimdo_rdxrs (char *str) 1677214571Sdim{ 1678214571Sdim skip_whitespace (str); 1679214571Sdim 1680214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL 1681214571Sdim || skip_past_comma (&str) == (int) FAIL 1682214571Sdim || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL 1683214571Sdim || end_of_line (str) == (int) FAIL) 1684214571Sdim return; 1685214571Sdim 1686214571Sdim if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0) 1687214571Sdim && (((inst.instruction >> 20) & 0x10) == 0)) 1688214571Sdim { 1689214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8); 1690214571Sdim inst.relax_size = 2; 1691214571Sdim } 1692214571Sdim else 1693214571Sdim inst.relax_inst = 0x8000; 1694214571Sdim} 1695214571Sdim 1696214571Sdim/* Handle cmp.c/cmp<cond>. */ 1697214571Sdimstatic void 1698214571Sdimdo_rsrs (char *str) 1699214571Sdim{ 1700214571Sdim skip_whitespace (str); 1701214571Sdim 1702214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1703214571Sdim || skip_past_comma (&str) == (int) FAIL 1704214571Sdim || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL 1705214571Sdim || end_of_line (str) == (int) FAIL) 1706214571Sdim return; 1707214571Sdim 1708214571Sdim if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3) 1709214571Sdim && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0)) 1710214571Sdim { 1711214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8); 1712214571Sdim inst.relax_size = 2; 1713214571Sdim } 1714214571Sdim else 1715214571Sdim inst.relax_inst = 0x8000; 1716214571Sdim} 1717214571Sdim 1718214571Sdimstatic void 1719214571Sdimdo_ceinst (char *str) 1720214571Sdim{ 1721214571Sdim char *strbak; 1722214571Sdim 1723214571Sdim strbak = str; 1724214571Sdim skip_whitespace (str); 1725214571Sdim 1726214571Sdim if (data_op2 (&str, 20, _IMM5) == (int) FAIL 1727214571Sdim || skip_past_comma (&str) == (int) FAIL 1728214571Sdim || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL 1729214571Sdim || skip_past_comma (&str) == (int) FAIL 1730214571Sdim || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL 1731214571Sdim || skip_past_comma (&str) == (int) FAIL 1732214571Sdim || data_op2 (&str, 5, _IMM5) == (int) FAIL 1733214571Sdim || skip_past_comma (&str) == (int) FAIL 1734214571Sdim || data_op2 (&str, 0, _IMM5) == (int) FAIL 1735214571Sdim || end_of_line (str) == (int) FAIL) 1736214571Sdim { 1737214571Sdim return; 1738214571Sdim } 1739214571Sdim else 1740214571Sdim { 1741214571Sdim str = strbak; 1742214571Sdim if (data_op2 (&str, 0, _IMM25) == (int) FAIL) 1743214571Sdim return; 1744214571Sdim } 1745214571Sdim} 1746214571Sdim 1747214571Sdimstatic int 1748214571Sdimreglow_required_here (char **str, int shift) 1749214571Sdim{ 1750214571Sdim static char buff[MAX_LITERAL_POOL_SIZE]; 1751214571Sdim int reg; 1752214571Sdim char *start = *str; 1753214571Sdim 1754214571Sdim if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL) 1755214571Sdim { 1756214571Sdim if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0)) 1757214571Sdim { 1758214571Sdim as_warn (_("Using temp register(r1)")); 1759214571Sdim inst.bwarn = 1; 1760214571Sdim } 1761214571Sdim if (reg < 16) 1762214571Sdim { 1763214571Sdim if (shift >= 0) 1764214571Sdim inst.instruction |= reg << shift; 1765214571Sdim 1766214571Sdim return reg; 1767214571Sdim } 1768214571Sdim } 1769214571Sdim 1770214571Sdim /* Restore the start point, we may have got a reg of the wrong class. */ 1771214571Sdim *str = start; 1772214571Sdim sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start); 1773214571Sdim inst.error = buff; 1774214571Sdim return (int) FAIL; 1775214571Sdim} 1776214571Sdim 1777214571Sdim/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */ 1778214571Sdimstatic void 1779214571Sdimdo16_rdrs (char *str) 1780214571Sdim{ 1781214571Sdim skip_whitespace (str); 1782214571Sdim 1783214571Sdim if (reglow_required_here (&str, 8) == (int) FAIL 1784214571Sdim || skip_past_comma (&str) == (int) FAIL 1785214571Sdim || reglow_required_here (&str, 4) == (int) FAIL 1786214571Sdim || end_of_line (str) == (int) FAIL) 1787214571Sdim { 1788214571Sdim return; 1789214571Sdim } 1790214571Sdim else 1791214571Sdim { 1792214571Sdim if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */ 1793214571Sdim { 1794214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15) 1795214571Sdim | (((inst.instruction >> 4) & 0xf) << 10); 1796214571Sdim } 1797214571Sdim else if ((inst.instruction & 0x700f) == 0x2006) /* not! */ 1798214571Sdim { 1799214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 1800214571Sdim | (((inst.instruction >> 4) & 0xf) << 15); 1801214571Sdim } 1802214571Sdim else 1803214571Sdim { 1804214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 1805214571Sdim | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10); 1806214571Sdim } 1807214571Sdim inst.relax_size = 4; 1808214571Sdim } 1809214571Sdim} 1810214571Sdim 1811214571Sdimstatic void 1812214571Sdimdo16_rs (char *str) 1813214571Sdim{ 1814214571Sdim int rd = 0; 1815214571Sdim 1816214571Sdim skip_whitespace (str); 1817214571Sdim 1818214571Sdim if ((rd = reglow_required_here (&str, 4)) == (int) FAIL 1819214571Sdim || end_of_line (str) == (int) FAIL) 1820214571Sdim { 1821214571Sdim return; 1822214571Sdim } 1823214571Sdim else 1824214571Sdim { 1825214571Sdim inst.relax_inst |= rd << 20; 1826214571Sdim inst.relax_size = 4; 1827214571Sdim } 1828214571Sdim} 1829214571Sdim 1830214571Sdim/* Handle br!/brl!. */ 1831214571Sdimstatic void 1832214571Sdimdo16_xrs (char *str) 1833214571Sdim{ 1834214571Sdim skip_whitespace (str); 1835214571Sdim 1836214571Sdim if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL) 1837214571Sdim { 1838214571Sdim return; 1839214571Sdim } 1840214571Sdim else 1841214571Sdim { 1842214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10) 1843214571Sdim | (((inst.instruction >> 4) & 0xf) << 15); 1844214571Sdim inst.relax_size = 4; 1845214571Sdim } 1846214571Sdim} 1847214571Sdim 1848214571Sdimstatic int 1849214571Sdimreghigh_required_here (char **str, int shift) 1850214571Sdim{ 1851214571Sdim static char buff[MAX_LITERAL_POOL_SIZE]; 1852214571Sdim int reg; 1853214571Sdim char *start = *str; 1854214571Sdim 1855214571Sdim if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL) 1856214571Sdim { 1857214571Sdim if (15 < reg && reg < 32) 1858214571Sdim { 1859214571Sdim if (shift >= 0) 1860214571Sdim inst.instruction |= (reg & 0xf) << shift; 1861214571Sdim 1862214571Sdim return reg; 1863214571Sdim } 1864214571Sdim } 1865214571Sdim 1866214571Sdim *str = start; 1867214571Sdim sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start); 1868214571Sdim inst.error = buff; 1869214571Sdim return (int) FAIL; 1870214571Sdim} 1871214571Sdim 1872214571Sdim/* Handle mhfl!. */ 1873214571Sdimstatic void 1874214571Sdimdo16_hrdrs (char *str) 1875214571Sdim{ 1876214571Sdim skip_whitespace (str); 1877214571Sdim 1878214571Sdim if (reghigh_required_here (&str, 8) != (int) FAIL 1879214571Sdim && skip_past_comma (&str) != (int) FAIL 1880214571Sdim && reglow_required_here (&str, 4) != (int) FAIL 1881214571Sdim && end_of_line (str) != (int) FAIL) 1882214571Sdim { 1883214571Sdim inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) 1884214571Sdim | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); 1885214571Sdim inst.relax_size = 4; 1886214571Sdim } 1887214571Sdim} 1888214571Sdim 1889214571Sdim/* Handle mlfh!. */ 1890214571Sdimstatic void 1891214571Sdimdo16_rdhrs (char *str) 1892214571Sdim{ 1893214571Sdim skip_whitespace (str); 1894214571Sdim 1895214571Sdim if (reglow_required_here (&str, 8) != (int) FAIL 1896214571Sdim && skip_past_comma (&str) != (int) FAIL 1897214571Sdim && reghigh_required_here (&str, 4) != (int) FAIL 1898214571Sdim && end_of_line (str) != (int) FAIL) 1899214571Sdim { 1900214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 1901214571Sdim | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10); 1902214571Sdim inst.relax_size = 4; 1903214571Sdim } 1904214571Sdim} 1905214571Sdim 1906214571Sdim/* We need to be able to fix up arbitrary expressions in some statements. 1907214571Sdim This is so that we can handle symbols that are an arbitrary distance from 1908214571Sdim the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask), 1909214571Sdim which returns part of an address in a form which will be valid for 1910214571Sdim a data instruction. We do this by pushing the expression into a symbol 1911214571Sdim in the expr_section, and creating a fix for that. */ 1912214571Sdimstatic fixS * 1913214571Sdimfix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc) 1914214571Sdim{ 1915214571Sdim fixS *new_fix; 1916214571Sdim 1917214571Sdim switch (exp->X_op) 1918214571Sdim { 1919214571Sdim case O_constant: 1920214571Sdim case O_symbol: 1921214571Sdim case O_add: 1922214571Sdim case O_subtract: 1923214571Sdim new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc); 1924214571Sdim break; 1925214571Sdim default: 1926214571Sdim new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc); 1927214571Sdim break; 1928214571Sdim } 1929214571Sdim return new_fix; 1930214571Sdim} 1931214571Sdim 1932214571Sdimstatic void 1933214571Sdiminit_dependency_vector (void) 1934214571Sdim{ 1935214571Sdim int i; 1936214571Sdim 1937214571Sdim for (i = 0; i < vector_size; i++) 1938214571Sdim memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i])); 1939214571Sdim 1940214571Sdim return; 1941214571Sdim} 1942214571Sdim 1943214571Sdimstatic enum insn_type_for_dependency 1944214571Sdimdependency_type_from_insn (char *insn_name) 1945214571Sdim{ 1946214571Sdim char name[INSN_NAME_LEN]; 1947214571Sdim const struct insn_to_dependency *tmp; 1948214571Sdim 1949214571Sdim strcpy (name, insn_name); 1950214571Sdim tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name); 1951214571Sdim 1952214571Sdim if (tmp) 1953214571Sdim return tmp->type; 1954214571Sdim 1955214571Sdim return D_all_insn; 1956214571Sdim} 1957214571Sdim 1958214571Sdimstatic int 1959214571Sdimcheck_dependency (char *pre_insn, char *pre_reg, 1960214571Sdim char *cur_insn, char *cur_reg, int *warn_or_error) 1961214571Sdim{ 1962214571Sdim int bubbles = 0; 1963214571Sdim unsigned int i; 1964214571Sdim enum insn_type_for_dependency pre_insn_type; 1965214571Sdim enum insn_type_for_dependency cur_insn_type; 1966214571Sdim 1967214571Sdim pre_insn_type = dependency_type_from_insn (pre_insn); 1968214571Sdim cur_insn_type = dependency_type_from_insn (cur_insn); 1969214571Sdim 1970214571Sdim for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++) 1971214571Sdim { 1972214571Sdim if ((pre_insn_type == data_dependency_table[i].pre_insn_type) 1973214571Sdim && (D_all_insn == data_dependency_table[i].cur_insn_type 1974214571Sdim || cur_insn_type == data_dependency_table[i].cur_insn_type) 1975214571Sdim && (strcmp (data_dependency_table[i].pre_reg, "") == 0 1976214571Sdim || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0) 1977214571Sdim && (strcmp (data_dependency_table[i].cur_reg, "") == 0 1978214571Sdim || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0)) 1979214571Sdim { 1980214571Sdim bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5; 1981214571Sdim *warn_or_error = data_dependency_table[i].warn_or_error; 1982214571Sdim break; 1983214571Sdim } 1984214571Sdim } 1985214571Sdim 1986214571Sdim return bubbles; 1987214571Sdim} 1988214571Sdim 1989214571Sdimstatic void 1990214571Sdimbuild_one_frag (struct score_it one_inst) 1991214571Sdim{ 1992214571Sdim char *p; 1993214571Sdim int relaxable_p = g_opt; 1994214571Sdim int relax_size = 0; 1995214571Sdim 1996214571Sdim /* Start a new frag if frag_now is not empty. */ 1997214571Sdim if (frag_now_fix () != 0) 1998214571Sdim { 1999214571Sdim if (!frag_now->tc_frag_data.is_insn) 2000214571Sdim frag_wane (frag_now); 2001214571Sdim 2002214571Sdim frag_new (0); 2003214571Sdim } 2004214571Sdim frag_grow (20); 2005214571Sdim 2006214571Sdim p = frag_more (one_inst.size); 2007214571Sdim md_number_to_chars (p, one_inst.instruction, one_inst.size); 2008214571Sdim 2009214571Sdim#ifdef OBJ_ELF 2010214571Sdim dwarf2_emit_insn (one_inst.size); 2011214571Sdim#endif 2012214571Sdim 2013214571Sdim relaxable_p &= (one_inst.relax_size != 0); 2014214571Sdim relax_size = relaxable_p ? one_inst.relax_size : 0; 2015214571Sdim 2016214571Sdim p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0, 2017214571Sdim RELAX_ENCODE (one_inst.size, one_inst.relax_size, 2018214571Sdim one_inst.type, 0, 0, relaxable_p), 2019214571Sdim NULL, 0, NULL); 2020214571Sdim 2021214571Sdim if (relaxable_p) 2022214571Sdim md_number_to_chars (p, one_inst.relax_inst, relax_size); 2023214571Sdim} 2024214571Sdim 2025214571Sdimstatic void 2026214571Sdimhandle_dependency (struct score_it *theinst) 2027214571Sdim{ 2028214571Sdim int i; 2029214571Sdim int warn_or_error = 0; /* warn - 0; error - 1 */ 2030214571Sdim int bubbles = 0; 2031214571Sdim int remainder_bubbles = 0; 2032214571Sdim char cur_insn[INSN_NAME_LEN]; 2033214571Sdim char pre_insn[INSN_NAME_LEN]; 2034214571Sdim struct score_it nop_inst; 2035214571Sdim struct score_it pflush_inst; 2036214571Sdim 2037214571Sdim nop_inst.instruction = 0x0000; 2038214571Sdim nop_inst.size = 2; 2039214571Sdim nop_inst.relax_inst = 0x80008000; 2040214571Sdim nop_inst.relax_size = 4; 2041214571Sdim nop_inst.type = NO16_OPD; 2042214571Sdim 2043214571Sdim pflush_inst.instruction = 0x8000800a; 2044214571Sdim pflush_inst.size = 4; 2045214571Sdim pflush_inst.relax_inst = 0x8000; 2046214571Sdim pflush_inst.relax_size = 0; 2047214571Sdim pflush_inst.type = NO_OPD; 2048214571Sdim 2049214571Sdim /* pflush will clear all data dependency. */ 2050214571Sdim if (strcmp (theinst->name, "pflush") == 0) 2051214571Sdim { 2052214571Sdim init_dependency_vector (); 2053214571Sdim return; 2054214571Sdim } 2055214571Sdim 2056214571Sdim /* Push current instruction to dependency_vector[0]. */ 2057214571Sdim for (i = vector_size - 1; i > 0; i--) 2058214571Sdim memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i])); 2059214571Sdim 2060214571Sdim memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i])); 2061214571Sdim 2062214571Sdim /* There is no dependency between nop and any instruction. */ 2063214571Sdim if (strcmp (dependency_vector[0].name, "nop") == 0 2064214571Sdim || strcmp (dependency_vector[0].name, "nop!") == 0) 2065214571Sdim return; 2066214571Sdim 2067214571Sdim /* "pce" is defined in insn_to_dependency_table. */ 2068214571Sdim#define PCE_NAME "pce" 2069214571Sdim 2070214571Sdim if (dependency_vector[0].type == Insn_Type_PCE) 2071214571Sdim strcpy (cur_insn, PCE_NAME); 2072214571Sdim else 2073214571Sdim strcpy (cur_insn, dependency_vector[0].name); 2074214571Sdim 2075214571Sdim for (i = 1; i < vector_size; i++) 2076214571Sdim { 2077214571Sdim /* The element of dependency_vector is NULL. */ 2078214571Sdim if (dependency_vector[i].name[0] == '\0') 2079214571Sdim continue; 2080214571Sdim 2081214571Sdim if (dependency_vector[i].type == Insn_Type_PCE) 2082214571Sdim strcpy (pre_insn, PCE_NAME); 2083214571Sdim else 2084214571Sdim strcpy (pre_insn, dependency_vector[i].name); 2085214571Sdim 2086214571Sdim bubbles = check_dependency (pre_insn, dependency_vector[i].reg, 2087214571Sdim cur_insn, dependency_vector[0].reg, &warn_or_error); 2088214571Sdim remainder_bubbles = bubbles - i + 1; 2089214571Sdim 2090214571Sdim if (remainder_bubbles > 0) 2091214571Sdim { 2092214571Sdim int j; 2093214571Sdim 2094214571Sdim if (fix_data_dependency == 1) 2095214571Sdim { 2096214571Sdim if (remainder_bubbles <= 2) 2097214571Sdim { 2098214571Sdim if (warn_fix_data_dependency) 2099214571Sdim as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"), 2100214571Sdim dependency_vector[i].name, dependency_vector[i].reg, 2101214571Sdim dependency_vector[0].name, dependency_vector[0].reg, 2102214571Sdim remainder_bubbles, bubbles); 2103214571Sdim 2104214571Sdim for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--) 2105214571Sdim memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles], 2106214571Sdim sizeof (dependency_vector[j])); 2107214571Sdim 2108214571Sdim for (j = 1; j <= remainder_bubbles; j++) 2109214571Sdim { 2110214571Sdim memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j])); 2111214571Sdim /* Insert nop!. */ 2112214571Sdim build_one_frag (nop_inst); 2113214571Sdim } 2114214571Sdim } 2115214571Sdim else 2116214571Sdim { 2117214571Sdim if (warn_fix_data_dependency) 2118214571Sdim as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"), 2119214571Sdim dependency_vector[i].name, dependency_vector[i].reg, 2120214571Sdim dependency_vector[0].name, dependency_vector[0].reg, 2121214571Sdim bubbles); 2122214571Sdim 2123214571Sdim for (j = 1; j < vector_size; j++) 2124214571Sdim memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j])); 2125214571Sdim 2126214571Sdim /* Insert pflush. */ 2127214571Sdim build_one_frag (pflush_inst); 2128214571Sdim } 2129214571Sdim } 2130214571Sdim else 2131214571Sdim { 2132214571Sdim if (warn_or_error) 2133214571Sdim { 2134214571Sdim as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2135214571Sdim dependency_vector[i].name, dependency_vector[i].reg, 2136214571Sdim dependency_vector[0].name, dependency_vector[0].reg, 2137214571Sdim remainder_bubbles, bubbles); 2138214571Sdim } 2139214571Sdim else 2140214571Sdim { 2141214571Sdim as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), 2142214571Sdim dependency_vector[i].name, dependency_vector[i].reg, 2143214571Sdim dependency_vector[0].name, dependency_vector[0].reg, 2144214571Sdim remainder_bubbles, bubbles); 2145214571Sdim } 2146214571Sdim } 2147214571Sdim } 2148214571Sdim } 2149214571Sdim} 2150214571Sdim 2151214571Sdimstatic enum insn_class 2152214571Sdimget_insn_class_from_type (enum score_insn_type type) 2153214571Sdim{ 2154214571Sdim enum insn_class retval = (int) FAIL; 2155214571Sdim 2156214571Sdim switch (type) 2157214571Sdim { 2158214571Sdim case Rd_I4: 2159214571Sdim case Rd_I5: 2160214571Sdim case Rd_rvalueBP_I5: 2161214571Sdim case Rd_lvalueBP_I5: 2162214571Sdim case Rd_I8: 2163214571Sdim case PC_DISP8div2: 2164214571Sdim case PC_DISP11div2: 2165214571Sdim case Rd_Rs: 2166214571Sdim case Rd_HighRs: 2167214571Sdim case Rd_lvalueRs: 2168214571Sdim case Rd_rvalueRs: 2169214571Sdim case x_Rs: 2170214571Sdim case Rd_LowRs: 2171214571Sdim case NO16_OPD: 2172214571Sdim retval = INSN_CLASS_16; 2173214571Sdim break; 2174214571Sdim case Rd_Rs_I5: 2175214571Sdim case x_Rs_I5: 2176214571Sdim case x_I5_x: 2177214571Sdim case Rd_Rs_I14: 2178214571Sdim case I15: 2179214571Sdim case Rd_I16: 2180214571Sdim case Rd_SI16: 2181214571Sdim case Rd_rvalueRs_SI10: 2182214571Sdim case Rd_lvalueRs_SI10: 2183214571Sdim case Rd_rvalueRs_preSI12: 2184214571Sdim case Rd_rvalueRs_postSI12: 2185214571Sdim case Rd_lvalueRs_preSI12: 2186214571Sdim case Rd_lvalueRs_postSI12: 2187214571Sdim case Rd_Rs_SI14: 2188214571Sdim case Rd_rvalueRs_SI15: 2189214571Sdim case Rd_lvalueRs_SI15: 2190214571Sdim case PC_DISP19div2: 2191214571Sdim case PC_DISP24div2: 2192214571Sdim case Rd_Rs_Rs: 2193214571Sdim case x_Rs_x: 2194214571Sdim case x_Rs_Rs: 2195214571Sdim case Rd_Rs_x: 2196214571Sdim case Rd_x_Rs: 2197214571Sdim case Rd_x_x: 2198214571Sdim case OP5_rvalueRs_SI15: 2199214571Sdim case I5_Rs_Rs_I5_OP5: 2200214571Sdim case x_rvalueRs_post4: 2201214571Sdim case Rd_rvalueRs_post4: 2202214571Sdim case Rd_x_I5: 2203214571Sdim case Rd_lvalueRs_post4: 2204214571Sdim case x_lvalueRs_post4: 2205214571Sdim case Rd_Rs_Rs_imm: 2206214571Sdim case NO_OPD: 2207214571Sdim case Rd_lvalue32Rs: 2208214571Sdim case Rd_rvalue32Rs: 2209214571Sdim case Insn_GP: 2210214571Sdim case Insn_PIC: 2211214571Sdim case Insn_internal: 2212214571Sdim retval = INSN_CLASS_32; 2213214571Sdim break; 2214214571Sdim case Insn_Type_PCE: 2215214571Sdim retval = INSN_CLASS_PCE; 2216214571Sdim break; 2217214571Sdim case Insn_Type_SYN: 2218214571Sdim retval = INSN_CLASS_SYN; 2219214571Sdim break; 2220214571Sdim default: 2221214571Sdim abort (); 2222214571Sdim break; 2223214571Sdim } 2224214571Sdim return retval; 2225214571Sdim} 2226214571Sdim 2227214571Sdimstatic unsigned long 2228214571Sdimadjust_paritybit (unsigned long m_code, enum insn_class class) 2229214571Sdim{ 2230214571Sdim unsigned long result = 0; 2231214571Sdim unsigned long m_code_high = 0; 2232214571Sdim unsigned long m_code_low = 0; 2233214571Sdim unsigned long pb_high = 0; 2234214571Sdim unsigned long pb_low = 0; 2235214571Sdim 2236214571Sdim if (class == INSN_CLASS_32) 2237214571Sdim { 2238214571Sdim pb_high = 0x80000000; 2239214571Sdim pb_low = 0x00008000; 2240214571Sdim } 2241214571Sdim else if (class == INSN_CLASS_16) 2242214571Sdim { 2243214571Sdim pb_high = 0; 2244214571Sdim pb_low = 0; 2245214571Sdim } 2246214571Sdim else if (class == INSN_CLASS_PCE) 2247214571Sdim { 2248214571Sdim pb_high = 0; 2249214571Sdim pb_low = 0x00008000; 2250214571Sdim } 2251214571Sdim else if (class == INSN_CLASS_SYN) 2252214571Sdim { 2253214571Sdim /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should 2254214571Sdim be changed if macro instruction has been expanded. */ 2255214571Sdim pb_high = 0x80000000; 2256214571Sdim pb_low = 0x00008000; 2257214571Sdim } 2258214571Sdim else 2259214571Sdim { 2260214571Sdim abort (); 2261214571Sdim } 2262214571Sdim 2263214571Sdim m_code_high = m_code & 0x3fff8000; 2264214571Sdim m_code_low = m_code & 0x00007fff; 2265214571Sdim result = pb_high | (m_code_high << 1) | pb_low | m_code_low; 2266214571Sdim return result; 2267214571Sdim 2268214571Sdim} 2269214571Sdim 2270214571Sdimstatic void 2271214571Sdimgen_insn_frag (struct score_it *part_1, struct score_it *part_2) 2272214571Sdim{ 2273214571Sdim char *p; 2274214571Sdim bfd_boolean pce_p = FALSE; 2275214571Sdim int relaxable_p = g_opt; 2276214571Sdim int relax_size = 0; 2277214571Sdim struct score_it *inst1 = part_1; 2278214571Sdim struct score_it *inst2 = part_2; 2279214571Sdim struct score_it backup_inst1; 2280214571Sdim 2281214571Sdim pce_p = (inst2) ? TRUE : FALSE; 2282214571Sdim memcpy (&backup_inst1, inst1, sizeof (struct score_it)); 2283214571Sdim 2284214571Sdim /* Adjust instruction opcode and to be relaxed instruction opcode. */ 2285214571Sdim if (pce_p) 2286214571Sdim { 2287214571Sdim backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15) 2288214571Sdim | (inst2->instruction & 0x7FFF); 2289214571Sdim backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); 2290214571Sdim backup_inst1.relax_inst = 0x8000; 2291214571Sdim backup_inst1.size = INSN_SIZE; 2292214571Sdim backup_inst1.relax_size = 0; 2293214571Sdim backup_inst1.type = Insn_Type_PCE; 2294214571Sdim } 2295214571Sdim else 2296214571Sdim { 2297214571Sdim backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, 2298214571Sdim GET_INSN_CLASS (backup_inst1.type)); 2299214571Sdim } 2300214571Sdim 2301214571Sdim if (backup_inst1.relax_size != 0) 2302214571Sdim { 2303214571Sdim enum insn_class tmp; 2304214571Sdim 2305214571Sdim tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; 2306214571Sdim backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp); 2307214571Sdim } 2308214571Sdim 2309214571Sdim /* Check data dependency. */ 2310214571Sdim handle_dependency (&backup_inst1); 2311214571Sdim 2312214571Sdim /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains 2313214571Sdim data produced by .ascii etc. Doing this is to make one instruction per frag. */ 2314214571Sdim if (frag_now_fix () != 0) 2315214571Sdim { 2316214571Sdim if (!frag_now->tc_frag_data.is_insn) 2317214571Sdim frag_wane (frag_now); 2318214571Sdim 2319214571Sdim frag_new (0); 2320214571Sdim } 2321214571Sdim 2322214571Sdim /* Here, we must call frag_grow in order to keep the instruction frag type is 2323214571Sdim rs_machine_dependent. 2324214571Sdim For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which 2325214571Sdim acturally will call frag_wane. 2326214571Sdim Calling frag_grow first will create a new frag_now which free size is 20 that is enough 2327214571Sdim for frag_var. */ 2328214571Sdim frag_grow (20); 2329214571Sdim 2330214571Sdim p = frag_more (backup_inst1.size); 2331214571Sdim md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); 2332214571Sdim 2333214571Sdim#ifdef OBJ_ELF 2334214571Sdim dwarf2_emit_insn (backup_inst1.size); 2335214571Sdim#endif 2336214571Sdim 2337214571Sdim /* Generate fixup structure. */ 2338214571Sdim if (pce_p) 2339214571Sdim { 2340214571Sdim if (inst1->reloc.type != BFD_RELOC_NONE) 2341214571Sdim fix_new_score (frag_now, p - frag_now->fr_literal, 2342214571Sdim inst1->size, &inst1->reloc.exp, 2343214571Sdim inst1->reloc.pc_rel, inst1->reloc.type); 2344214571Sdim 2345214571Sdim if (inst2->reloc.type != BFD_RELOC_NONE) 2346214571Sdim fix_new_score (frag_now, p - frag_now->fr_literal + 2, 2347214571Sdim inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type); 2348214571Sdim } 2349214571Sdim else 2350214571Sdim { 2351214571Sdim if (backup_inst1.reloc.type != BFD_RELOC_NONE) 2352214571Sdim fix_new_score (frag_now, p - frag_now->fr_literal, 2353214571Sdim backup_inst1.size, &backup_inst1.reloc.exp, 2354214571Sdim backup_inst1.reloc.pc_rel, backup_inst1.reloc.type); 2355214571Sdim } 2356214571Sdim 2357214571Sdim /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */ 2358214571Sdim relaxable_p &= (backup_inst1.relax_size != 0); 2359214571Sdim relax_size = relaxable_p ? backup_inst1.relax_size : 0; 2360214571Sdim 2361214571Sdim p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0, 2362214571Sdim RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, 2363214571Sdim backup_inst1.type, 0, 0, relaxable_p), 2364214571Sdim backup_inst1.reloc.exp.X_add_symbol, 0, NULL); 2365214571Sdim 2366214571Sdim if (relaxable_p) 2367214571Sdim md_number_to_chars (p, backup_inst1.relax_inst, relax_size); 2368214571Sdim 2369214571Sdim memcpy (inst1, &backup_inst1, sizeof (struct score_it)); 2370214571Sdim} 2371214571Sdim 2372214571Sdimstatic void 2373214571Sdimparse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) 2374214571Sdim{ 2375214571Sdim char c; 2376214571Sdim char *p; 2377214571Sdim char *operator = insnstr; 2378214571Sdim const struct asm_opcode *opcode; 2379214571Sdim 2380214571Sdim /* Parse operator and operands. */ 2381214571Sdim skip_whitespace (operator); 2382214571Sdim 2383214571Sdim for (p = operator; *p != '\0'; p++) 2384214571Sdim if ((*p == ' ') || (*p == '!')) 2385214571Sdim break; 2386214571Sdim 2387214571Sdim if (*p == '!') 2388214571Sdim p++; 2389214571Sdim 2390214571Sdim c = *p; 2391214571Sdim *p = '\0'; 2392214571Sdim 2393214571Sdim opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator); 2394214571Sdim *p = c; 2395214571Sdim 2396214571Sdim memset (&inst, '\0', sizeof (inst)); 2397214571Sdim sprintf (inst.str, "%s", insnstr); 2398214571Sdim if (opcode) 2399214571Sdim { 2400214571Sdim inst.instruction = opcode->value; 2401214571Sdim inst.relax_inst = opcode->relax_value; 2402214571Sdim inst.type = opcode->type; 2403214571Sdim inst.size = GET_INSN_SIZE (inst.type); 2404214571Sdim inst.relax_size = 0; 2405214571Sdim inst.bwarn = 0; 2406214571Sdim sprintf (inst.name, "%s", opcode->template); 2407214571Sdim strcpy (inst.reg, ""); 2408214571Sdim inst.error = NULL; 2409214571Sdim inst.reloc.type = BFD_RELOC_NONE; 2410214571Sdim 2411214571Sdim (*opcode->parms) (p); 2412214571Sdim 2413214571Sdim /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */ 2414214571Sdim if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p)) 2415214571Sdim gen_insn_frag (&inst, NULL); 2416214571Sdim } 2417214571Sdim else 2418214571Sdim inst.error = _("unrecognized opcode"); 2419214571Sdim} 2420214571Sdim 2421214571Sdimstatic int 2422214571Sdimappend_insn (char *str, bfd_boolean gen_frag_p) 2423214571Sdim{ 2424214571Sdim int retval = SUCCESS; 2425214571Sdim 2426214571Sdim parse_16_32_inst (str, gen_frag_p); 2427214571Sdim 2428214571Sdim if (inst.error) 2429214571Sdim { 2430214571Sdim retval = (int) FAIL; 2431214571Sdim as_bad (_("%s -- `%s'"), inst.error, inst.str); 2432214571Sdim inst.error = NULL; 2433214571Sdim } 2434214571Sdim 2435214571Sdim return retval; 2436214571Sdim} 2437214571Sdim 2438214571Sdim/* Handle mv! reg_high, reg_low; 2439214571Sdim mv! reg_low, reg_high; 2440214571Sdim mv! reg_low, reg_low; */ 2441214571Sdimstatic void 2442214571Sdimdo16_mv_rdrs (char *str) 2443214571Sdim{ 2444214571Sdim int reg_rd; 2445214571Sdim int reg_rs; 2446214571Sdim char *backupstr = NULL; 2447214571Sdim 2448214571Sdim backupstr = str; 2449214571Sdim skip_whitespace (str); 2450214571Sdim 2451214571Sdim if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL 2452214571Sdim || skip_past_comma (&str) == (int) FAIL 2453214571Sdim || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL 2454214571Sdim || end_of_line (str) == (int) FAIL) 2455214571Sdim { 2456214571Sdim return; 2457214571Sdim } 2458214571Sdim else 2459214571Sdim { 2460214571Sdim /* Case 1 : mv! or mlfh!. */ 2461214571Sdim if (reg_rd < 16) 2462214571Sdim { 2463214571Sdim if (reg_rs < 16) 2464214571Sdim { 2465214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 2466214571Sdim | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); 2467214571Sdim inst.relax_size = 4; 2468214571Sdim } 2469214571Sdim else 2470214571Sdim { 2471214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 2472214571Sdim 2473214571Sdim sprintf (append_str, "mlfh! %s", backupstr); 2474214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 2475214571Sdim return; 2476214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 2477214571Sdim inst.bwarn = -1; 2478214571Sdim } 2479214571Sdim } 2480214571Sdim /* Case 2 : mhfl!. */ 2481214571Sdim else 2482214571Sdim { 2483214571Sdim if (reg_rs > 16) 2484214571Sdim { 2485214571Sdim SET_INSN_ERROR (BAD_ARGS); 2486214571Sdim return; 2487214571Sdim } 2488214571Sdim else 2489214571Sdim { 2490214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 2491214571Sdim 2492214571Sdim sprintf (append_str, "mhfl! %s", backupstr); 2493214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 2494214571Sdim return; 2495214571Sdim 2496214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 2497214571Sdim inst.bwarn = -1; 2498214571Sdim } 2499214571Sdim } 2500214571Sdim } 2501214571Sdim} 2502214571Sdim 2503214571Sdimstatic void 2504214571Sdimdo16_rdi4 (char *str) 2505214571Sdim{ 2506214571Sdim skip_whitespace (str); 2507214571Sdim 2508214571Sdim if (reglow_required_here (&str, 8) == (int) FAIL 2509214571Sdim || skip_past_comma (&str) == (int) FAIL 2510214571Sdim || data_op2 (&str, 3, _IMM4) == (int) FAIL 2511214571Sdim || end_of_line (str) == (int) FAIL) 2512214571Sdim { 2513214571Sdim return; 2514214571Sdim } 2515214571Sdim else 2516214571Sdim { 2517214571Sdim if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */ 2518214571Sdim { 2519214571Sdim if (((inst.instruction >> 3) & 0xf) != 0xf) 2520214571Sdim { 2521214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 2522214571Sdim | ((1 << ((inst.instruction >> 3) & 0xf)) << 1); 2523214571Sdim inst.relax_size = 4; 2524214571Sdim } 2525214571Sdim else 2526214571Sdim { 2527214571Sdim inst.relax_inst = 0x8000; 2528214571Sdim } 2529214571Sdim } 2530214571Sdim else 2531214571Sdim { 2532214571Sdim if (((inst.instruction >> 3) & 0xf) != 0xf) 2533214571Sdim { 2534214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 2535214571Sdim | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1); 2536214571Sdim inst.relax_size = 4; 2537214571Sdim } 2538214571Sdim else 2539214571Sdim { 2540214571Sdim inst.relax_inst = 0x8000; 2541214571Sdim } 2542214571Sdim } 2543214571Sdim } 2544214571Sdim} 2545214571Sdim 2546214571Sdimstatic void 2547214571Sdimdo16_rdi5 (char *str) 2548214571Sdim{ 2549214571Sdim skip_whitespace (str); 2550214571Sdim 2551214571Sdim if (reglow_required_here (&str, 8) == (int) FAIL 2552214571Sdim || skip_past_comma (&str) == (int) FAIL 2553214571Sdim || data_op2 (&str, 3, _IMM5) == (int) FAIL 2554214571Sdim || end_of_line (str) == (int) FAIL) 2555214571Sdim return; 2556214571Sdim else 2557214571Sdim { 2558214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 2559214571Sdim | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10); 2560214571Sdim inst.relax_size = 4; 2561214571Sdim } 2562214571Sdim} 2563214571Sdim 2564214571Sdim/* Handle sdbbp. */ 2565214571Sdimstatic void 2566214571Sdimdo16_xi5 (char *str) 2567214571Sdim{ 2568214571Sdim skip_whitespace (str); 2569214571Sdim 2570214571Sdim if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL) 2571214571Sdim return; 2572214571Sdim else 2573214571Sdim { 2574214571Sdim inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15); 2575214571Sdim inst.relax_size = 4; 2576214571Sdim } 2577214571Sdim} 2578214571Sdim 2579214571Sdim/* Check that an immediate is word alignment or half word alignment. 2580214571Sdim If so, convert it to the right format. */ 2581214571Sdimstatic int 2582214571Sdimvalidate_immediate_align (int val, unsigned int data_type) 2583214571Sdim{ 2584214571Sdim if (data_type == _IMM5_RSHIFT_1) 2585214571Sdim { 2586214571Sdim if (val % 2) 2587214571Sdim { 2588214571Sdim inst.error = _("address offset must be half word alignment"); 2589214571Sdim return (int) FAIL; 2590214571Sdim } 2591214571Sdim } 2592214571Sdim else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2593214571Sdim { 2594214571Sdim if (val % 4) 2595214571Sdim { 2596214571Sdim inst.error = _("address offset must be word alignment"); 2597214571Sdim return (int) FAIL; 2598214571Sdim } 2599214571Sdim } 2600214571Sdim 2601214571Sdim return SUCCESS; 2602214571Sdim} 2603214571Sdim 2604214571Sdimstatic int 2605214571Sdimexp_ldst_offset (char **str, int shift, unsigned int data_type) 2606214571Sdim{ 2607214571Sdim char *dataptr; 2608214571Sdim 2609214571Sdim dataptr = * str; 2610214571Sdim 2611214571Sdim if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 2612214571Sdim && (data_type != _SIMM16_LA) 2613214571Sdim && (data_type != _VALUE_HI16) 2614214571Sdim && (data_type != _VALUE_LO16) 2615214571Sdim && (data_type != _IMM16) 2616214571Sdim && (data_type != _IMM15) 2617214571Sdim && (data_type != _IMM14) 2618214571Sdim && (data_type != _IMM4) 2619214571Sdim && (data_type != _IMM5) 2620214571Sdim && (data_type != _IMM8) 2621214571Sdim && (data_type != _IMM5_RSHIFT_1) 2622214571Sdim && (data_type != _IMM5_RSHIFT_2) 2623214571Sdim && (data_type != _SIMM14_NEG) 2624214571Sdim && (data_type != _IMM10_RSHIFT_2)) 2625214571Sdim { 2626214571Sdim data_type += 24; 2627214571Sdim } 2628214571Sdim 2629214571Sdim if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL) 2630214571Sdim return (int) FAIL; 2631214571Sdim 2632214571Sdim if (inst.reloc.exp.X_op == O_constant) 2633214571Sdim { 2634214571Sdim /* Need to check the immediate align. */ 2635214571Sdim int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type); 2636214571Sdim 2637214571Sdim if (value == (int) FAIL) 2638214571Sdim return (int) FAIL; 2639214571Sdim 2640214571Sdim value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0); 2641214571Sdim if (value == (int) FAIL) 2642214571Sdim { 2643214571Sdim if (data_type < 30) 2644214571Sdim sprintf (err_msg, 2645214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 2646214571Sdim score_df_range[data_type].bits, 2647214571Sdim score_df_range[data_type].range[0], score_df_range[data_type].range[1]); 2648214571Sdim else 2649214571Sdim sprintf (err_msg, 2650214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 2651214571Sdim score_df_range[data_type - 24].bits, 2652214571Sdim score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]); 2653214571Sdim inst.error = err_msg; 2654214571Sdim return (int) FAIL; 2655214571Sdim } 2656214571Sdim 2657214571Sdim if (data_type == _IMM5_RSHIFT_1) 2658214571Sdim { 2659214571Sdim value >>= 1; 2660214571Sdim } 2661214571Sdim else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) 2662214571Sdim { 2663214571Sdim value >>= 2; 2664214571Sdim } 2665214571Sdim 2666214571Sdim if (score_df_range[data_type].range[0] != 0) 2667214571Sdim { 2668214571Sdim value &= (1 << score_df_range[data_type].bits) - 1; 2669214571Sdim } 2670214571Sdim 2671214571Sdim inst.instruction |= value << shift; 2672214571Sdim } 2673214571Sdim else 2674214571Sdim { 2675214571Sdim inst.reloc.pc_rel = 0; 2676214571Sdim } 2677214571Sdim 2678214571Sdim return SUCCESS; 2679214571Sdim} 2680214571Sdim 2681214571Sdimstatic void 2682214571Sdimdo_ldst_insn (char *str) 2683214571Sdim{ 2684214571Sdim int pre_inc = 0; 2685214571Sdim int conflict_reg; 2686214571Sdim int value; 2687214571Sdim char * temp; 2688214571Sdim char *strbak; 2689214571Sdim char *dataptr; 2690214571Sdim int reg; 2691214571Sdim int ldst_idx = 0; 2692214571Sdim 2693214571Sdim strbak = str; 2694214571Sdim skip_whitespace (str); 2695214571Sdim 2696214571Sdim if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) 2697214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 2698214571Sdim return; 2699214571Sdim 2700214571Sdim /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */ 2701214571Sdim if (*str == '[') 2702214571Sdim { 2703214571Sdim str++; 2704214571Sdim skip_whitespace (str); 2705214571Sdim 2706214571Sdim if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) 2707214571Sdim return; 2708214571Sdim 2709214571Sdim /* Conflicts can occur on stores as well as loads. */ 2710214571Sdim conflict_reg = (conflict_reg == reg); 2711214571Sdim skip_whitespace (str); 2712214571Sdim temp = str + 1; /* The latter will process decimal/hex expression. */ 2713214571Sdim 2714214571Sdim /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */ 2715214571Sdim if (*str == ']') 2716214571Sdim { 2717214571Sdim str++; 2718214571Sdim if (*str == '+') 2719214571Sdim { 2720214571Sdim str++; 2721214571Sdim /* ld/sw rD, [rA]+, simm12. */ 2722214571Sdim if (skip_past_comma (&str) == SUCCESS) 2723214571Sdim { 2724214571Sdim if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL) 2725214571Sdim || (end_of_line (str) == (int) FAIL)) 2726214571Sdim return; 2727214571Sdim 2728214571Sdim if (conflict_reg) 2729214571Sdim { 2730214571Sdim unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK; 2731214571Sdim 2732214571Sdim if ((ldst_func == INSN_LH) 2733214571Sdim || (ldst_func == INSN_LHU) 2734214571Sdim || (ldst_func == INSN_LW) 2735214571Sdim || (ldst_func == INSN_LB) 2736214571Sdim || (ldst_func == INSN_LBU)) 2737214571Sdim { 2738214571Sdim inst.error = _("register same as write-back base"); 2739214571Sdim return; 2740214571Sdim } 2741214571Sdim } 2742214571Sdim 2743214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 2744214571Sdim inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2745214571Sdim inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value; 2746214571Sdim 2747214571Sdim /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */ 2748214571Sdim if ((inst.instruction & 0x3e000007) == 0x0e000000) 2749214571Sdim { 2750214571Sdim /* rs = r0-r7, offset = 4 */ 2751214571Sdim if ((((inst.instruction >> 15) & 0x18) == 0) 2752214571Sdim && (((inst.instruction >> 3) & 0xfff) == 4)) 2753214571Sdim { 2754214571Sdim /* Relax to pophi. */ 2755214571Sdim if ((((inst.instruction >> 20) & 0x10) == 0x10)) 2756214571Sdim { 2757214571Sdim inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf) 2758214571Sdim << 8) | 1 << 7 | 2759214571Sdim (((inst.instruction >> 15) & 0x7) << 4); 2760214571Sdim } 2761214571Sdim /* Relax to pop. */ 2762214571Sdim else 2763214571Sdim { 2764214571Sdim inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf) 2765214571Sdim << 8) | 0 << 7 | 2766214571Sdim (((inst.instruction >> 15) & 0x7) << 4); 2767214571Sdim } 2768214571Sdim inst.relax_size = 2; 2769214571Sdim } 2770214571Sdim } 2771214571Sdim return; 2772214571Sdim } 2773214571Sdim /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */ 2774214571Sdim else 2775214571Sdim { 2776214571Sdim SET_INSN_ERROR (NULL); 2777214571Sdim if (end_of_line (str) == (int) FAIL) 2778214571Sdim { 2779214571Sdim return; 2780214571Sdim } 2781214571Sdim 2782214571Sdim pre_inc = 1; 2783214571Sdim value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0); 2784214571Sdim value &= (1 << score_df_range[_SIMM12].bits) - 1; 2785214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 2786214571Sdim inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2787214571Sdim inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value; 2788214571Sdim inst.instruction |= value << 3; 2789214571Sdim inst.relax_inst = 0x8000; 2790214571Sdim return; 2791214571Sdim } 2792214571Sdim } 2793214571Sdim /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */ 2794214571Sdim else 2795214571Sdim { 2796214571Sdim if (end_of_line (str) == (int) FAIL) 2797214571Sdim return; 2798214571Sdim 2799214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 2800214571Sdim inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2801214571Sdim inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; 2802214571Sdim 2803214571Sdim /* lbu rd, [rs] -> lbu! rd, [rs] */ 2804214571Sdim if (ldst_idx == INSN_LBU) 2805214571Sdim { 2806214571Sdim inst.relax_inst = INSN16_LBU; 2807214571Sdim } 2808214571Sdim else if (ldst_idx == INSN_LH) 2809214571Sdim { 2810214571Sdim inst.relax_inst = INSN16_LH; 2811214571Sdim } 2812214571Sdim else if (ldst_idx == INSN_LW) 2813214571Sdim { 2814214571Sdim inst.relax_inst = INSN16_LW; 2815214571Sdim } 2816214571Sdim else if (ldst_idx == INSN_SB) 2817214571Sdim { 2818214571Sdim inst.relax_inst = INSN16_SB; 2819214571Sdim } 2820214571Sdim else if (ldst_idx == INSN_SH) 2821214571Sdim { 2822214571Sdim inst.relax_inst = INSN16_SH; 2823214571Sdim } 2824214571Sdim else if (ldst_idx == INSN_SW) 2825214571Sdim { 2826214571Sdim inst.relax_inst = INSN16_SW; 2827214571Sdim } 2828214571Sdim else 2829214571Sdim { 2830214571Sdim inst.relax_inst = 0x8000; 2831214571Sdim } 2832214571Sdim 2833214571Sdim /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */ 2834214571Sdim if ((ldst_idx == INSN_LBU) 2835214571Sdim || (ldst_idx == INSN_LH) 2836214571Sdim || (ldst_idx == INSN_LW) 2837214571Sdim || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW)) 2838214571Sdim { 2839214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 2840214571Sdim { 2841214571Sdim inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) | 2842214571Sdim (((inst.instruction >> 15) & 0xf) << 4); 2843214571Sdim inst.relax_size = 2; 2844214571Sdim } 2845214571Sdim } 2846214571Sdim 2847214571Sdim return; 2848214571Sdim } 2849214571Sdim } 2850214571Sdim /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */ 2851214571Sdim else 2852214571Sdim { 2853214571Sdim if (skip_past_comma (&str) == (int) FAIL) 2854214571Sdim { 2855214571Sdim inst.error = _("pre-indexed expression expected"); 2856214571Sdim return; 2857214571Sdim } 2858214571Sdim 2859214571Sdim if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL) 2860214571Sdim return; 2861214571Sdim 2862214571Sdim skip_whitespace (str); 2863214571Sdim if (*str++ != ']') 2864214571Sdim { 2865214571Sdim inst.error = _("missing ]"); 2866214571Sdim return; 2867214571Sdim } 2868214571Sdim 2869214571Sdim skip_whitespace (str); 2870214571Sdim /* ld/sw rD, [rA, simm12]+. */ 2871214571Sdim if (*str == '+') 2872214571Sdim { 2873214571Sdim str++; 2874214571Sdim pre_inc = 1; 2875214571Sdim if (conflict_reg) 2876214571Sdim { 2877214571Sdim unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK; 2878214571Sdim 2879214571Sdim if ((ldst_func == INSN_LH) 2880214571Sdim || (ldst_func == INSN_LHU) 2881214571Sdim || (ldst_func == INSN_LW) 2882214571Sdim || (ldst_func == INSN_LB) 2883214571Sdim || (ldst_func == INSN_LBU)) 2884214571Sdim { 2885214571Sdim inst.error = _("register same as write-back base"); 2886214571Sdim return; 2887214571Sdim } 2888214571Sdim } 2889214571Sdim } 2890214571Sdim 2891214571Sdim if (end_of_line (str) == (int) FAIL) 2892214571Sdim return; 2893214571Sdim 2894214571Sdim if (inst.reloc.exp.X_op == O_constant) 2895214571Sdim { 2896214571Sdim int value; 2897214571Sdim unsigned int data_type; 2898214571Sdim 2899214571Sdim if (pre_inc == 1) 2900214571Sdim data_type = _SIMM12; 2901214571Sdim else 2902214571Sdim data_type = _SIMM15; 2903214571Sdim dataptr = temp; 2904214571Sdim 2905214571Sdim if ((*dataptr == '0') && (*(dataptr + 1) == 'x') 2906214571Sdim && (data_type != _SIMM16_LA) 2907214571Sdim && (data_type != _VALUE_HI16) 2908214571Sdim && (data_type != _VALUE_LO16) 2909214571Sdim && (data_type != _IMM16) 2910214571Sdim && (data_type != _IMM15) 2911214571Sdim && (data_type != _IMM14) 2912214571Sdim && (data_type != _IMM4) 2913214571Sdim && (data_type != _IMM5) 2914214571Sdim && (data_type != _IMM8) 2915214571Sdim && (data_type != _IMM5_RSHIFT_1) 2916214571Sdim && (data_type != _IMM5_RSHIFT_2) 2917214571Sdim && (data_type != _SIMM14_NEG) 2918214571Sdim && (data_type != _IMM10_RSHIFT_2)) 2919214571Sdim { 2920214571Sdim data_type += 24; 2921214571Sdim } 2922214571Sdim 2923214571Sdim value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0); 2924214571Sdim if (value == (int) FAIL) 2925214571Sdim { 2926214571Sdim if (data_type < 30) 2927214571Sdim sprintf (err_msg, 2928214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 2929214571Sdim score_df_range[data_type].bits, 2930214571Sdim score_df_range[data_type].range[0], score_df_range[data_type].range[1]); 2931214571Sdim else 2932214571Sdim sprintf (err_msg, 2933214571Sdim _("invalid constant: %d bit expression not in range %d..%d"), 2934214571Sdim score_df_range[data_type - 24].bits, 2935214571Sdim score_df_range[data_type - 24].range[0], 2936214571Sdim score_df_range[data_type - 24].range[1]); 2937214571Sdim inst.error = err_msg; 2938214571Sdim return; 2939214571Sdim } 2940214571Sdim 2941214571Sdim value &= (1 << score_df_range[data_type].bits) - 1; 2942214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 2943214571Sdim inst.instruction &= ~OPC_PSEUDOLDST_MASK; 2944214571Sdim inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value; 2945214571Sdim if (pre_inc == 1) 2946214571Sdim inst.instruction |= value << 3; 2947214571Sdim else 2948214571Sdim inst.instruction |= value; 2949214571Sdim 2950214571Sdim /* lw rD, [rA, simm15] */ 2951214571Sdim if ((inst.instruction & 0x3e000000) == 0x20000000) 2952214571Sdim { 2953214571Sdim /* Both rD and rA are in [r0 - r15]. */ 2954214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) 2955214571Sdim && (((inst.instruction >> 20) & 0x10) == 0)) 2956214571Sdim { 2957214571Sdim /* simm15 = 0, lw -> lw!. */ 2958214571Sdim if ((inst.instruction & 0x7fff) == 0) 2959214571Sdim { 2960214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 2961214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 2962214571Sdim inst.relax_size = 2; 2963214571Sdim } 2964214571Sdim /* rA = r2, lw -> lwp!. */ 2965214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 2966214571Sdim && ((inst.instruction & 0x3) == 0) 2967214571Sdim && ((inst.instruction & 0x7fff) < 128)) 2968214571Sdim { 2969214571Sdim inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8) 2970214571Sdim | (((inst.instruction & 0x7fff) >> 2) << 3); 2971214571Sdim inst.relax_size = 2; 2972214571Sdim } 2973214571Sdim else 2974214571Sdim { 2975214571Sdim inst.relax_inst = 0x8000; 2976214571Sdim } 2977214571Sdim } 2978214571Sdim else 2979214571Sdim { 2980214571Sdim inst.relax_inst = 0x8000; 2981214571Sdim } 2982214571Sdim } 2983214571Sdim /* sw rD, [rA, simm15] */ 2984214571Sdim else if ((inst.instruction & 0x3e000000) == 0x28000000) 2985214571Sdim { 2986214571Sdim /* Both rD and rA are in [r0 - r15]. */ 2987214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 2988214571Sdim { 2989214571Sdim /* simm15 = 0, sw -> sw!. */ 2990214571Sdim if ((inst.instruction & 0x7fff) == 0) 2991214571Sdim { 2992214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 2993214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 2994214571Sdim inst.relax_size = 2; 2995214571Sdim } 2996214571Sdim /* rA = r2, sw -> swp!. */ 2997214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 2998214571Sdim && ((inst.instruction & 0x3) == 0) 2999214571Sdim && ((inst.instruction & 0x7fff) < 128)) 3000214571Sdim { 3001214571Sdim inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8) 3002214571Sdim | (((inst.instruction & 0x7fff) >> 2) << 3); 3003214571Sdim inst.relax_size = 2; 3004214571Sdim } 3005214571Sdim else 3006214571Sdim { 3007214571Sdim inst.relax_inst = 0x8000; 3008214571Sdim } 3009214571Sdim } 3010214571Sdim else 3011214571Sdim { 3012214571Sdim inst.relax_inst = 0x8000; 3013214571Sdim } 3014214571Sdim } 3015214571Sdim /* sw rD, [rA, simm15]+ sw pre. */ 3016214571Sdim else if ((inst.instruction & 0x3e000007) == 0x06000004) 3017214571Sdim { 3018214571Sdim /* rA is in [r0 - r7], and simm15 = -4. */ 3019214571Sdim if ((((inst.instruction >> 15) & 0x18) == 0) 3020214571Sdim && (((inst.instruction >> 3) & 0xfff) == 0xffc)) 3021214571Sdim { 3022214571Sdim /* sw -> pushhi!. */ 3023214571Sdim if ((((inst.instruction >> 20) & 0x10) == 0x10)) 3024214571Sdim { 3025214571Sdim inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8) 3026214571Sdim | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4); 3027214571Sdim inst.relax_size = 2; 3028214571Sdim } 3029214571Sdim /* sw -> push!. */ 3030214571Sdim else 3031214571Sdim { 3032214571Sdim inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8) 3033214571Sdim | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4); 3034214571Sdim inst.relax_size = 2; 3035214571Sdim } 3036214571Sdim } 3037214571Sdim else 3038214571Sdim { 3039214571Sdim inst.relax_inst = 0x8000; 3040214571Sdim } 3041214571Sdim } 3042214571Sdim /* lh rD, [rA, simm15] */ 3043214571Sdim else if ((inst.instruction & 0x3e000000) == 0x22000000) 3044214571Sdim { 3045214571Sdim /* Both rD and rA are in [r0 - r15]. */ 3046214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 3047214571Sdim { 3048214571Sdim /* simm15 = 0, lh -> lh!. */ 3049214571Sdim if ((inst.instruction & 0x7fff) == 0) 3050214571Sdim { 3051214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 3052214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 3053214571Sdim inst.relax_size = 2; 3054214571Sdim } 3055214571Sdim /* rA = r2, lh -> lhp!. */ 3056214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 3057214571Sdim && ((inst.instruction & 0x1) == 0) 3058214571Sdim && ((inst.instruction & 0x7fff) < 64)) 3059214571Sdim { 3060214571Sdim inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8) 3061214571Sdim | (((inst.instruction & 0x7fff) >> 1) << 3); 3062214571Sdim inst.relax_size = 2; 3063214571Sdim } 3064214571Sdim else 3065214571Sdim { 3066214571Sdim inst.relax_inst = 0x8000; 3067214571Sdim } 3068214571Sdim } 3069214571Sdim else 3070214571Sdim { 3071214571Sdim inst.relax_inst = 0x8000; 3072214571Sdim } 3073214571Sdim } 3074214571Sdim /* sh rD, [rA, simm15] */ 3075214571Sdim else if ((inst.instruction & 0x3e000000) == 0x2a000000) 3076214571Sdim { 3077214571Sdim /* Both rD and rA are in [r0 - r15]. */ 3078214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 3079214571Sdim { 3080214571Sdim /* simm15 = 0, sh -> sh!. */ 3081214571Sdim if ((inst.instruction & 0x7fff) == 0) 3082214571Sdim { 3083214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 3084214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 3085214571Sdim inst.relax_size = 2; 3086214571Sdim } 3087214571Sdim /* rA = r2, sh -> shp!. */ 3088214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 3089214571Sdim && ((inst.instruction & 0x1) == 0) 3090214571Sdim && ((inst.instruction & 0x7fff) < 64)) 3091214571Sdim { 3092214571Sdim inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8) 3093214571Sdim | (((inst.instruction & 0x7fff) >> 1) << 3); 3094214571Sdim inst.relax_size = 2; 3095214571Sdim } 3096214571Sdim else 3097214571Sdim { 3098214571Sdim inst.relax_inst = 0x8000; 3099214571Sdim } 3100214571Sdim } 3101214571Sdim else 3102214571Sdim { 3103214571Sdim inst.relax_inst = 0x8000; 3104214571Sdim } 3105214571Sdim } 3106214571Sdim /* lbu rD, [rA, simm15] */ 3107214571Sdim else if ((inst.instruction & 0x3e000000) == 0x2c000000) 3108214571Sdim { 3109214571Sdim /* Both rD and rA are in [r0 - r15]. */ 3110214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 3111214571Sdim { 3112214571Sdim /* simm15 = 0, lbu -> lbu!. */ 3113214571Sdim if ((inst.instruction & 0x7fff) == 0) 3114214571Sdim { 3115214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 3116214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 3117214571Sdim inst.relax_size = 2; 3118214571Sdim } 3119214571Sdim /* rA = r2, lbu -> lbup!. */ 3120214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 3121214571Sdim && ((inst.instruction & 0x7fff) < 32)) 3122214571Sdim { 3123214571Sdim inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8) 3124214571Sdim | ((inst.instruction & 0x7fff) << 3); 3125214571Sdim inst.relax_size = 2; 3126214571Sdim } 3127214571Sdim else 3128214571Sdim { 3129214571Sdim inst.relax_inst = 0x8000; 3130214571Sdim } 3131214571Sdim } 3132214571Sdim else 3133214571Sdim { 3134214571Sdim inst.relax_inst = 0x8000; 3135214571Sdim } 3136214571Sdim } 3137214571Sdim /* sb rD, [rA, simm15] */ 3138214571Sdim else if ((inst.instruction & 0x3e000000) == 0x2e000000) 3139214571Sdim { 3140214571Sdim /* Both rD and rA are in [r0 - r15]. */ 3141214571Sdim if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) 3142214571Sdim { 3143214571Sdim /* simm15 = 0, sb -> sb!. */ 3144214571Sdim if ((inst.instruction & 0x7fff) == 0) 3145214571Sdim { 3146214571Sdim inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) 3147214571Sdim | (((inst.instruction >> 20) & 0xf) << 8); 3148214571Sdim inst.relax_size = 2; 3149214571Sdim } 3150214571Sdim /* rA = r2, sb -> sb!. */ 3151214571Sdim else if ((((inst.instruction >> 15) & 0xf) == 2) 3152214571Sdim && ((inst.instruction & 0x7fff) < 32)) 3153214571Sdim { 3154214571Sdim inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8) 3155214571Sdim | ((inst.instruction & 0x7fff) << 3); 3156214571Sdim inst.relax_size = 2; 3157214571Sdim } 3158214571Sdim else 3159214571Sdim { 3160214571Sdim inst.relax_inst = 0x8000; 3161214571Sdim } 3162214571Sdim } 3163214571Sdim else 3164214571Sdim { 3165214571Sdim inst.relax_inst = 0x8000; 3166214571Sdim } 3167214571Sdim } 3168214571Sdim else 3169214571Sdim { 3170214571Sdim inst.relax_inst = 0x8000; 3171214571Sdim } 3172214571Sdim 3173214571Sdim return; 3174214571Sdim } 3175214571Sdim else 3176214571Sdim { 3177214571Sdim /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */ 3178214571Sdim inst.reloc.pc_rel = 0; 3179214571Sdim } 3180214571Sdim } 3181214571Sdim } 3182214571Sdim else 3183214571Sdim { 3184214571Sdim inst.error = BAD_ARGS; 3185214571Sdim } 3186214571Sdim} 3187214571Sdim 3188214571Sdim/* Handle cache. */ 3189214571Sdim 3190214571Sdimstatic void 3191214571Sdimdo_cache (char *str) 3192214571Sdim{ 3193214571Sdim skip_whitespace (str); 3194214571Sdim 3195214571Sdim if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL)) 3196214571Sdim { 3197214571Sdim return; 3198214571Sdim } 3199214571Sdim else 3200214571Sdim { 3201214571Sdim int cache_op; 3202214571Sdim 3203214571Sdim cache_op = (inst.instruction >> 20) & 0x1F; 3204214571Sdim sprintf (inst.name, "cache %d", cache_op); 3205214571Sdim } 3206214571Sdim 3207214571Sdim if (*str == '[') 3208214571Sdim { 3209214571Sdim str++; 3210214571Sdim skip_whitespace (str); 3211214571Sdim 3212214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL) 3213214571Sdim return; 3214214571Sdim 3215214571Sdim skip_whitespace (str); 3216214571Sdim 3217214571Sdim /* cache op, [rA] */ 3218214571Sdim if (skip_past_comma (&str) == (int) FAIL) 3219214571Sdim { 3220214571Sdim SET_INSN_ERROR (NULL); 3221214571Sdim if (*str != ']') 3222214571Sdim { 3223214571Sdim inst.error = _("missing ]"); 3224214571Sdim return; 3225214571Sdim } 3226214571Sdim str++; 3227214571Sdim } 3228214571Sdim /* cache op, [rA, simm15] */ 3229214571Sdim else 3230214571Sdim { 3231214571Sdim if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL) 3232214571Sdim { 3233214571Sdim return; 3234214571Sdim } 3235214571Sdim 3236214571Sdim skip_whitespace (str); 3237214571Sdim if (*str++ != ']') 3238214571Sdim { 3239214571Sdim inst.error = _("missing ]"); 3240214571Sdim return; 3241214571Sdim } 3242214571Sdim } 3243214571Sdim 3244214571Sdim if (end_of_line (str) == (int) FAIL) 3245214571Sdim return; 3246214571Sdim } 3247214571Sdim else 3248214571Sdim { 3249214571Sdim inst.error = BAD_ARGS; 3250214571Sdim } 3251214571Sdim} 3252214571Sdim 3253214571Sdimstatic void 3254214571Sdimdo_crdcrscrsimm5 (char *str) 3255214571Sdim{ 3256214571Sdim char *strbak; 3257214571Sdim 3258214571Sdim strbak = str; 3259214571Sdim skip_whitespace (str); 3260214571Sdim 3261214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL 3262214571Sdim || skip_past_comma (&str) == (int) FAIL 3263214571Sdim || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL 3264214571Sdim || skip_past_comma (&str) == (int) FAIL 3265214571Sdim || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL 3266214571Sdim || skip_past_comma (&str) == (int) FAIL) 3267214571Sdim { 3268214571Sdim str = strbak; 3269214571Sdim /* cop1 cop_code20. */ 3270214571Sdim if (data_op2 (&str, 5, _IMM20) == (int) FAIL) 3271214571Sdim return; 3272214571Sdim } 3273214571Sdim else 3274214571Sdim { 3275214571Sdim if (data_op2 (&str, 5, _IMM5) == (int) FAIL) 3276214571Sdim return; 3277214571Sdim } 3278214571Sdim 3279214571Sdim end_of_line (str); 3280214571Sdim} 3281214571Sdim 3282214571Sdim/* Handle ldc/stc. */ 3283214571Sdimstatic void 3284214571Sdimdo_ldst_cop (char *str) 3285214571Sdim{ 3286214571Sdim skip_whitespace (str); 3287214571Sdim 3288214571Sdim if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL) 3289214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 3290214571Sdim return; 3291214571Sdim 3292214571Sdim if (*str == '[') 3293214571Sdim { 3294214571Sdim str++; 3295214571Sdim skip_whitespace (str); 3296214571Sdim 3297214571Sdim if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL) 3298214571Sdim return; 3299214571Sdim 3300214571Sdim skip_whitespace (str); 3301214571Sdim 3302214571Sdim if (*str++ != ']') 3303214571Sdim { 3304214571Sdim if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL) 3305214571Sdim return; 3306214571Sdim 3307214571Sdim skip_whitespace (str); 3308214571Sdim if (*str++ != ']') 3309214571Sdim { 3310214571Sdim inst.error = _("missing ]"); 3311214571Sdim return; 3312214571Sdim } 3313214571Sdim } 3314214571Sdim 3315214571Sdim end_of_line (str); 3316214571Sdim } 3317214571Sdim else 3318214571Sdim inst.error = BAD_ARGS; 3319214571Sdim} 3320214571Sdim 3321214571Sdimstatic void 3322214571Sdimdo16_ldst_insn (char *str) 3323214571Sdim{ 3324214571Sdim skip_whitespace (str); 3325214571Sdim 3326214571Sdim if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL)) 3327214571Sdim return; 3328214571Sdim 3329214571Sdim if (*str == '[') 3330214571Sdim { 3331214571Sdim int reg; 3332214571Sdim 3333214571Sdim str++; 3334214571Sdim skip_whitespace (str); 3335214571Sdim 3336214571Sdim if ((reg = reglow_required_here (&str, 4)) == (int) FAIL) 3337214571Sdim return; 3338214571Sdim 3339214571Sdim skip_whitespace (str); 3340214571Sdim if (*str++ == ']') 3341214571Sdim { 3342214571Sdim if (end_of_line (str) == (int) FAIL) 3343214571Sdim return; 3344214571Sdim else 3345214571Sdim { 3346214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 3347214571Sdim | (((inst.instruction >> 4) & 0xf) << 15); 3348214571Sdim inst.relax_size = 4; 3349214571Sdim } 3350214571Sdim } 3351214571Sdim else 3352214571Sdim { 3353214571Sdim inst.error = _("missing ]"); 3354214571Sdim } 3355214571Sdim } 3356214571Sdim else 3357214571Sdim { 3358214571Sdim inst.error = BAD_ARGS; 3359214571Sdim } 3360214571Sdim} 3361214571Sdim 3362214571Sdim/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */ 3363214571Sdimstatic void 3364214571Sdimdo16_ldst_imm_insn (char *str) 3365214571Sdim{ 3366214571Sdim char data_exp[MAX_LITERAL_POOL_SIZE]; 3367214571Sdim int reg_rd; 3368214571Sdim char *dataptr = NULL, *pp = NULL; 3369214571Sdim int cnt = 0; 3370214571Sdim int assign_data = (int) FAIL; 3371214571Sdim unsigned int ldst_func; 3372214571Sdim 3373214571Sdim skip_whitespace (str); 3374214571Sdim 3375214571Sdim if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL) 3376214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 3377214571Sdim return; 3378214571Sdim 3379214571Sdim skip_whitespace (str); 3380214571Sdim dataptr = str; 3381214571Sdim 3382214571Sdim while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) 3383214571Sdim { 3384214571Sdim data_exp[cnt] = *dataptr; 3385214571Sdim dataptr++; 3386214571Sdim cnt++; 3387214571Sdim } 3388214571Sdim 3389214571Sdim data_exp[cnt] = '\0'; 3390214571Sdim pp = &data_exp[0]; 3391214571Sdim 3392214571Sdim str = dataptr; 3393214571Sdim 3394214571Sdim ldst_func = inst.instruction & LDST16_RI_MASK; 3395214571Sdim if (ldst_func == N16_LIU) 3396214571Sdim assign_data = exp_ldst_offset (&pp, 0, _IMM8); 3397214571Sdim else if (ldst_func == N16_LHP || ldst_func == N16_SHP) 3398214571Sdim assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1); 3399214571Sdim else if (ldst_func == N16_LWP || ldst_func == N16_SWP) 3400214571Sdim assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2); 3401214571Sdim else 3402214571Sdim assign_data = exp_ldst_offset (&pp, 3, _IMM5); 3403214571Sdim 3404214571Sdim if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL)) 3405214571Sdim return; 3406214571Sdim else 3407214571Sdim { 3408214571Sdim if ((inst.instruction & 0x7000) == N16_LIU) 3409214571Sdim { 3410214571Sdim inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 3411214571Sdim | ((inst.instruction & 0xff) << 1); 3412214571Sdim } 3413214571Sdim else if (((inst.instruction & 0x7007) == N16_LHP) 3414214571Sdim || ((inst.instruction & 0x7007) == N16_SHP)) 3415214571Sdim { 3416214571Sdim inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 3417214571Sdim | (((inst.instruction >> 3) & 0x1f) << 1); 3418214571Sdim } 3419214571Sdim else if (((inst.instruction & 0x7007) == N16_LWP) 3420214571Sdim || ((inst.instruction & 0x7007) == N16_SWP)) 3421214571Sdim { 3422214571Sdim inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 3423214571Sdim | (((inst.instruction >> 3) & 0x1f) << 2); 3424214571Sdim } 3425214571Sdim else if (((inst.instruction & 0x7007) == N16_LBUP) 3426214571Sdim || ((inst.instruction & 0x7007) == N16_SBP)) 3427214571Sdim { 3428214571Sdim inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 3429214571Sdim | (((inst.instruction >> 3) & 0x1f)); 3430214571Sdim } 3431214571Sdim 3432214571Sdim inst.relax_size = 4; 3433214571Sdim } 3434214571Sdim} 3435214571Sdim 3436214571Sdimstatic void 3437214571Sdimdo16_push_pop (char *str) 3438214571Sdim{ 3439214571Sdim int reg_rd; 3440214571Sdim int H_bit_mask = 0; 3441214571Sdim 3442214571Sdim skip_whitespace (str); 3443214571Sdim if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL) 3444214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 3445214571Sdim return; 3446214571Sdim 3447214571Sdim if (reg_rd >= 16) 3448214571Sdim H_bit_mask = 1; 3449214571Sdim 3450214571Sdim /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */ 3451214571Sdim inst.instruction &= ~(1 << 12); 3452214571Sdim 3453214571Sdim inst.instruction |= H_bit_mask << 7; 3454214571Sdim 3455214571Sdim if (*str == '[') 3456214571Sdim { 3457214571Sdim int reg; 3458214571Sdim 3459214571Sdim str++; 3460214571Sdim skip_whitespace (str); 3461214571Sdim if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL) 3462214571Sdim return; 3463214571Sdim else if (reg > 7) 3464214571Sdim { 3465214571Sdim if (!inst.error) 3466214571Sdim inst.error = _("base register nums are over 3 bit"); 3467214571Sdim 3468214571Sdim return; 3469214571Sdim } 3470214571Sdim 3471214571Sdim skip_whitespace (str); 3472214571Sdim if ((*str++ != ']') || (end_of_line (str) == (int) FAIL)) 3473214571Sdim { 3474214571Sdim if (!inst.error) 3475214571Sdim inst.error = _("missing ]"); 3476214571Sdim 3477214571Sdim return; 3478214571Sdim } 3479214571Sdim 3480214571Sdim /* pop! */ 3481214571Sdim if ((inst.instruction & 0xf) == 0xa) 3482214571Sdim { 3483214571Sdim if (H_bit_mask) 3484214571Sdim { 3485214571Sdim inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) 3486214571Sdim | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3); 3487214571Sdim } 3488214571Sdim else 3489214571Sdim { 3490214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 3491214571Sdim | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3); 3492214571Sdim } 3493214571Sdim } 3494214571Sdim /* push! */ 3495214571Sdim else 3496214571Sdim { 3497214571Sdim if (H_bit_mask) 3498214571Sdim { 3499214571Sdim inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) 3500214571Sdim | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); 3501214571Sdim } 3502214571Sdim else 3503214571Sdim { 3504214571Sdim inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) 3505214571Sdim | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); 3506214571Sdim } 3507214571Sdim } 3508214571Sdim inst.relax_size = 4; 3509214571Sdim } 3510214571Sdim else 3511214571Sdim { 3512214571Sdim inst.error = BAD_ARGS; 3513214571Sdim } 3514214571Sdim} 3515214571Sdim 3516214571Sdim/* Handle lcb/lcw/lce/scb/scw/sce. */ 3517214571Sdimstatic void 3518214571Sdimdo_ldst_unalign (char *str) 3519214571Sdim{ 3520214571Sdim int conflict_reg; 3521214571Sdim 3522214571Sdim if (university_version == 1) 3523214571Sdim { 3524214571Sdim inst.error = ERR_FOR_SCORE5U_ATOMIC; 3525214571Sdim return; 3526214571Sdim } 3527214571Sdim 3528214571Sdim skip_whitespace (str); 3529214571Sdim 3530214571Sdim /* lcb/scb [rA]+. */ 3531214571Sdim if (*str == '[') 3532214571Sdim { 3533214571Sdim str++; 3534214571Sdim skip_whitespace (str); 3535214571Sdim 3536214571Sdim if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL) 3537214571Sdim return; 3538214571Sdim 3539214571Sdim if (*str++ == ']') 3540214571Sdim { 3541214571Sdim if (*str++ != '+') 3542214571Sdim { 3543214571Sdim inst.error = _("missing +"); 3544214571Sdim return; 3545214571Sdim } 3546214571Sdim } 3547214571Sdim else 3548214571Sdim { 3549214571Sdim inst.error = _("missing ]"); 3550214571Sdim return; 3551214571Sdim } 3552214571Sdim 3553214571Sdim if (end_of_line (str) == (int) FAIL) 3554214571Sdim return; 3555214571Sdim } 3556214571Sdim /* lcw/lce/scb/sce rD, [rA]+. */ 3557214571Sdim else 3558214571Sdim { 3559214571Sdim if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) 3560214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 3561214571Sdim { 3562214571Sdim return; 3563214571Sdim } 3564214571Sdim 3565214571Sdim skip_whitespace (str); 3566214571Sdim if (*str++ == '[') 3567214571Sdim { 3568214571Sdim int reg; 3569214571Sdim 3570214571Sdim skip_whitespace (str); 3571214571Sdim if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) 3572214571Sdim { 3573214571Sdim return; 3574214571Sdim } 3575214571Sdim 3576214571Sdim /* Conflicts can occur on stores as well as loads. */ 3577214571Sdim conflict_reg = (conflict_reg == reg); 3578214571Sdim skip_whitespace (str); 3579214571Sdim if (*str++ == ']') 3580214571Sdim { 3581214571Sdim unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK; 3582214571Sdim 3583214571Sdim if (*str++ == '+') 3584214571Sdim { 3585214571Sdim if (conflict_reg) 3586214571Sdim { 3587214571Sdim as_warn (_("%s register same as write-back base"), 3588214571Sdim ((ldst_func & UA_LCE) || (ldst_func & UA_LCW) 3589214571Sdim ? _("destination") : _("source"))); 3590214571Sdim } 3591214571Sdim } 3592214571Sdim else 3593214571Sdim { 3594214571Sdim inst.error = _("missing +"); 3595214571Sdim return; 3596214571Sdim } 3597214571Sdim 3598214571Sdim if (end_of_line (str) == (int) FAIL) 3599214571Sdim return; 3600214571Sdim } 3601214571Sdim else 3602214571Sdim { 3603214571Sdim inst.error = _("missing ]"); 3604214571Sdim return; 3605214571Sdim } 3606214571Sdim } 3607214571Sdim else 3608214571Sdim { 3609214571Sdim inst.error = BAD_ARGS; 3610214571Sdim return; 3611214571Sdim } 3612214571Sdim } 3613214571Sdim} 3614214571Sdim 3615214571Sdim/* Handle alw/asw. */ 3616214571Sdimstatic void 3617214571Sdimdo_ldst_atomic (char *str) 3618214571Sdim{ 3619214571Sdim if (university_version == 1) 3620214571Sdim { 3621214571Sdim inst.error = ERR_FOR_SCORE5U_ATOMIC; 3622214571Sdim return; 3623214571Sdim } 3624214571Sdim 3625214571Sdim skip_whitespace (str); 3626214571Sdim 3627214571Sdim if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL) 3628214571Sdim || (skip_past_comma (&str) == (int) FAIL)) 3629214571Sdim { 3630214571Sdim return; 3631214571Sdim } 3632214571Sdim else 3633214571Sdim { 3634214571Sdim 3635214571Sdim skip_whitespace (str); 3636214571Sdim if (*str++ == '[') 3637214571Sdim { 3638214571Sdim int reg; 3639214571Sdim 3640214571Sdim skip_whitespace (str); 3641214571Sdim if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) 3642214571Sdim { 3643214571Sdim return; 3644214571Sdim } 3645214571Sdim 3646214571Sdim skip_whitespace (str); 3647214571Sdim if (*str++ != ']') 3648214571Sdim { 3649214571Sdim inst.error = _("missing ]"); 3650214571Sdim return; 3651214571Sdim } 3652214571Sdim 3653214571Sdim end_of_line (str); 3654214571Sdim } 3655214571Sdim else 3656214571Sdim inst.error = BAD_ARGS; 3657214571Sdim } 3658214571Sdim} 3659214571Sdim 3660214571Sdimstatic void 3661214571Sdimbuild_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED, 3662214571Sdim struct score_it var_insts[RELAX_INST_NUM], int var_num, 3663214571Sdim symbolS *add_symbol) 3664214571Sdim{ 3665214571Sdim int i; 3666214571Sdim char *p; 3667214571Sdim fixS *fixp = NULL; 3668214571Sdim fixS *cur_fixp = NULL; 3669214571Sdim long where; 3670214571Sdim struct score_it inst_main; 3671214571Sdim 3672214571Sdim memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it)); 3673214571Sdim 3674214571Sdim /* Adjust instruction opcode and to be relaxed instruction opcode. */ 3675214571Sdim inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type)); 3676214571Sdim inst_main.type = Insn_PIC; 3677214571Sdim 3678214571Sdim for (i = 0; i < var_num; i++) 3679214571Sdim { 3680214571Sdim inst_main.relax_size += var_insts[i].size; 3681214571Sdim var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction, 3682214571Sdim GET_INSN_CLASS (var_insts[i].type)); 3683214571Sdim } 3684214571Sdim 3685214571Sdim /* Check data dependency. */ 3686214571Sdim handle_dependency (&inst_main); 3687214571Sdim 3688214571Sdim /* Start a new frag if frag_now is not empty. */ 3689214571Sdim if (frag_now_fix () != 0) 3690214571Sdim { 3691214571Sdim if (!frag_now->tc_frag_data.is_insn) 3692214571Sdim { 3693214571Sdim frag_wane (frag_now); 3694214571Sdim } 3695214571Sdim frag_new (0); 3696214571Sdim } 3697214571Sdim frag_grow (20); 3698214571Sdim 3699214571Sdim /* Write fr_fix part. */ 3700214571Sdim p = frag_more (inst_main.size); 3701214571Sdim md_number_to_chars (p, inst_main.instruction, inst_main.size); 3702214571Sdim 3703214571Sdim if (inst_main.reloc.type != BFD_RELOC_NONE) 3704214571Sdim fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 3705214571Sdim &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 3706214571Sdim 3707214571Sdim frag_now->tc_frag_data.fixp = fixp; 3708214571Sdim cur_fixp = frag_now->tc_frag_data.fixp; 3709214571Sdim 3710214571Sdim#ifdef OBJ_ELF 3711214571Sdim dwarf2_emit_insn (inst_main.size); 3712214571Sdim#endif 3713214571Sdim 3714214571Sdim where = p - frag_now->fr_literal + inst_main.size; 3715214571Sdim for (i = 0; i < var_num; i++) 3716214571Sdim { 3717214571Sdim if (i > 0) 3718214571Sdim where += var_insts[i - 1].size; 3719214571Sdim 3720214571Sdim if (var_insts[i].reloc.type != BFD_RELOC_NONE) 3721214571Sdim { 3722214571Sdim fixp = fix_new_score (frag_now, where, var_insts[i].size, 3723214571Sdim &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel, 3724214571Sdim var_insts[i].reloc.type); 3725214571Sdim if (fixp) 3726214571Sdim { 3727214571Sdim if (cur_fixp) 3728214571Sdim { 3729214571Sdim cur_fixp->fx_next = fixp; 3730214571Sdim cur_fixp = cur_fixp->fx_next; 3731214571Sdim } 3732214571Sdim else 3733214571Sdim { 3734214571Sdim frag_now->tc_frag_data.fixp = fixp; 3735214571Sdim cur_fixp = frag_now->tc_frag_data.fixp; 3736214571Sdim } 3737214571Sdim } 3738214571Sdim } 3739214571Sdim } 3740214571Sdim 3741214571Sdim p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0, 3742214571Sdim RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 3743214571Sdim 0, inst_main.size, 0), add_symbol, 0, NULL); 3744214571Sdim 3745214571Sdim /* Write fr_var part. 3746214571Sdim no calling gen_insn_frag, no fixS will be generated. */ 3747214571Sdim for (i = 0; i < var_num; i++) 3748214571Sdim { 3749214571Sdim md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); 3750214571Sdim p += var_insts[i].size; 3751214571Sdim } 3752214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 3753214571Sdim inst.bwarn = -1; 3754214571Sdim} 3755214571Sdim 3756214571Sdim/* Build a relax frag for la instruction when generating PIC, 3757214571Sdim external symbol first and local symbol second. */ 3758214571Sdim 3759214571Sdimstatic void 3760214571Sdimbuild_la_pic (int reg_rd, expressionS exp) 3761214571Sdim{ 3762214571Sdim symbolS *add_symbol = exp.X_add_symbol; 3763214571Sdim offsetT add_number = exp.X_add_number; 3764214571Sdim struct score_it fix_insts[RELAX_INST_NUM]; 3765214571Sdim struct score_it var_insts[RELAX_INST_NUM]; 3766214571Sdim int fix_num = 0; 3767214571Sdim int var_num = 0; 3768214571Sdim char tmp[MAX_LITERAL_POOL_SIZE]; 3769214571Sdim int r1_bak; 3770214571Sdim 3771214571Sdim r1_bak = nor1; 3772214571Sdim nor1 = 0; 3773214571Sdim 3774214571Sdim if (add_number == 0) 3775214571Sdim { 3776214571Sdim fix_num = 1; 3777214571Sdim var_num = 2; 3778214571Sdim 3779214571Sdim /* For an external symbol, only one insn is generated; 3780214571Sdim For a local symbol, two insns are generated. */ 3781214571Sdim /* Fix part 3782214571Sdim For an external symbol: lw rD, <sym>($gp) 3783214571Sdim (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */ 3784214571Sdim sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); 3785214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3786214571Sdim return; 3787214571Sdim 3788214571Sdim if (reg_rd == PIC_CALL_REG) 3789214571Sdim inst.reloc.type = BFD_RELOC_SCORE_CALL15; 3790214571Sdim memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); 3791214571Sdim 3792214571Sdim /* Var part 3793214571Sdim For a local symbol : 3794214571Sdim lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 3795214571Sdim addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 3796214571Sdim inst.reloc.type = BFD_RELOC_SCORE_GOT15; 3797214571Sdim memcpy (&var_insts[0], &inst, sizeof (struct score_it)); 3798214571Sdim sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name); 3799214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3800214571Sdim return; 3801214571Sdim 3802214571Sdim memcpy (&var_insts[1], &inst, sizeof (struct score_it)); 3803214571Sdim build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 3804214571Sdim } 3805214571Sdim else if (add_number >= -0x8000 && add_number <= 0x7fff) 3806214571Sdim { 3807214571Sdim /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 3808214571Sdim sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); 3809214571Sdim if (append_insn (tmp, TRUE) == (int) FAIL) 3810214571Sdim return; 3811214571Sdim 3812214571Sdim /* Insn 2 */ 3813214571Sdim fix_num = 1; 3814214571Sdim var_num = 1; 3815214571Sdim /* Fix part 3816214571Sdim For an external symbol: addi rD, <constant> */ 3817214571Sdim sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number); 3818214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3819214571Sdim return; 3820214571Sdim 3821214571Sdim memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); 3822214571Sdim 3823214571Sdim /* Var part 3824214571Sdim For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */ 3825214571Sdim sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number); 3826214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3827214571Sdim return; 3828214571Sdim 3829214571Sdim memcpy (&var_insts[0], &inst, sizeof (struct score_it)); 3830214571Sdim build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 3831214571Sdim } 3832214571Sdim else 3833214571Sdim { 3834214571Sdim int hi = (add_number >> 16) & 0x0000FFFF; 3835214571Sdim int lo = add_number & 0x0000FFFF; 3836214571Sdim 3837214571Sdim /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */ 3838214571Sdim sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); 3839214571Sdim if (append_insn (tmp, TRUE) == (int) FAIL) 3840214571Sdim return; 3841214571Sdim 3842214571Sdim /* Insn 2 */ 3843214571Sdim fix_num = 1; 3844214571Sdim var_num = 1; 3845214571Sdim /* Fix part 3846214571Sdim For an external symbol: ldis r1, HI%<constant> */ 3847214571Sdim sprintf (tmp, "ldis r1, %d", hi); 3848214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3849214571Sdim return; 3850214571Sdim 3851214571Sdim memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); 3852214571Sdim 3853214571Sdim /* Var part 3854214571Sdim For a local symbol: ldis r1, HI%<constant> 3855214571Sdim but, if lo is outof 16 bit, make hi plus 1 */ 3856214571Sdim if ((lo < -0x8000) || (lo > 0x7fff)) 3857214571Sdim { 3858214571Sdim hi += 1; 3859214571Sdim } 3860214571Sdim sprintf (tmp, "ldis_pic r1, %d", hi); 3861214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3862214571Sdim return; 3863214571Sdim 3864214571Sdim memcpy (&var_insts[0], &inst, sizeof (struct score_it)); 3865214571Sdim build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 3866214571Sdim 3867214571Sdim /* Insn 3 */ 3868214571Sdim fix_num = 1; 3869214571Sdim var_num = 1; 3870214571Sdim /* Fix part 3871214571Sdim For an external symbol: ori r1, LO%<constant> */ 3872214571Sdim sprintf (tmp, "ori r1, %d", lo); 3873214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3874214571Sdim return; 3875214571Sdim 3876214571Sdim memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); 3877214571Sdim 3878214571Sdim /* Var part 3879214571Sdim For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */ 3880214571Sdim sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo); 3881214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 3882214571Sdim return; 3883214571Sdim 3884214571Sdim memcpy (&var_insts[0], &inst, sizeof (struct score_it)); 3885214571Sdim build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 3886214571Sdim 3887214571Sdim /* Insn 4: add rD, rD, r1 */ 3888214571Sdim sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd); 3889214571Sdim if (append_insn (tmp, TRUE) == (int) FAIL) 3890214571Sdim return; 3891214571Sdim 3892214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 3893214571Sdim inst.bwarn = -1; 3894214571Sdim } 3895214571Sdim 3896214571Sdim nor1 = r1_bak; 3897214571Sdim} 3898214571Sdim 3899214571Sdim/* Handle la. */ 3900214571Sdimstatic void 3901214571Sdimdo_macro_la_rdi32 (char *str) 3902214571Sdim{ 3903214571Sdim int reg_rd; 3904214571Sdim 3905214571Sdim skip_whitespace (str); 3906214571Sdim if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL 3907214571Sdim || skip_past_comma (&str) == (int) FAIL) 3908214571Sdim { 3909214571Sdim return; 3910214571Sdim } 3911214571Sdim else 3912214571Sdim { 3913214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 3914214571Sdim char *keep_data = str; 3915214571Sdim 3916214571Sdim /* la rd, simm16. */ 3917214571Sdim if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL) 3918214571Sdim { 3919214571Sdim end_of_line (str); 3920214571Sdim return; 3921214571Sdim } 3922214571Sdim /* la rd, imm32 or la rd, label. */ 3923214571Sdim else 3924214571Sdim { 3925214571Sdim SET_INSN_ERROR (NULL); 3926214571Sdim str = keep_data; 3927214571Sdim if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL) 3928214571Sdim || (end_of_line (str) == (int) FAIL)) 3929214571Sdim { 3930214571Sdim return; 3931214571Sdim } 3932214571Sdim else 3933214571Sdim { 3934214571Sdim if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol)) 3935214571Sdim { 3936214571Sdim sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 3937214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 3938214571Sdim return; 3939214571Sdim 3940214571Sdim sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 3941214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 3942214571Sdim return; 3943214571Sdim } 3944214571Sdim else 3945214571Sdim { 3946214571Sdim assert (inst.reloc.exp.X_add_symbol); 3947214571Sdim build_la_pic (reg_rd, inst.reloc.exp); 3948214571Sdim } 3949214571Sdim 3950214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 3951214571Sdim inst.bwarn = -1; 3952214571Sdim } 3953214571Sdim } 3954214571Sdim } 3955214571Sdim} 3956214571Sdim 3957214571Sdim/* Handle li. */ 3958214571Sdimstatic void 3959214571Sdimdo_macro_li_rdi32 (char *str){ 3960214571Sdim 3961214571Sdim int reg_rd; 3962214571Sdim 3963214571Sdim skip_whitespace (str); 3964214571Sdim if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL 3965214571Sdim || skip_past_comma (&str) == (int) FAIL) 3966214571Sdim { 3967214571Sdim return; 3968214571Sdim } 3969214571Sdim else 3970214571Sdim { 3971214571Sdim char *keep_data = str; 3972214571Sdim 3973214571Sdim /* li rd, simm16. */ 3974214571Sdim if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL) 3975214571Sdim { 3976214571Sdim end_of_line (str); 3977214571Sdim return; 3978214571Sdim } 3979214571Sdim /* li rd, imm32. */ 3980214571Sdim else 3981214571Sdim { 3982214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 3983214571Sdim 3984214571Sdim str = keep_data; 3985214571Sdim 3986214571Sdim if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL) 3987214571Sdim || (end_of_line (str) == (int) FAIL)) 3988214571Sdim { 3989214571Sdim return; 3990214571Sdim } 3991214571Sdim else if (inst.reloc.exp.X_add_symbol) 3992214571Sdim { 3993214571Sdim inst.error = _("li rd label isn't correct instruction form"); 3994214571Sdim return; 3995214571Sdim } 3996214571Sdim else 3997214571Sdim { 3998214571Sdim sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); 3999214571Sdim 4000214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 4001214571Sdim return; 4002214571Sdim else 4003214571Sdim { 4004214571Sdim sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); 4005214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 4006214571Sdim return; 4007214571Sdim 4008214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4009214571Sdim inst.bwarn = -1; 4010214571Sdim } 4011214571Sdim } 4012214571Sdim } 4013214571Sdim } 4014214571Sdim} 4015214571Sdim 4016214571Sdim/* Handle mul/mulu/div/divu/rem/remu. */ 4017214571Sdimstatic void 4018214571Sdimdo_macro_mul_rdrsrs (char *str) 4019214571Sdim{ 4020214571Sdim int reg_rd; 4021214571Sdim int reg_rs1; 4022214571Sdim int reg_rs2; 4023214571Sdim char *backupstr; 4024214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 4025214571Sdim 4026214571Sdim if (university_version == 1) 4027214571Sdim as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV); 4028214571Sdim 4029214571Sdim strcpy (append_str, str); 4030214571Sdim backupstr = append_str; 4031214571Sdim skip_whitespace (backupstr); 4032214571Sdim if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) 4033214571Sdim || (skip_past_comma (&backupstr) == (int) FAIL) 4034214571Sdim || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)) 4035214571Sdim { 4036214571Sdim inst.error = BAD_ARGS; 4037214571Sdim return; 4038214571Sdim } 4039214571Sdim 4040214571Sdim if (skip_past_comma (&backupstr) == (int) FAIL) 4041214571Sdim { 4042214571Sdim /* rem/remu rA, rB is error format. */ 4043214571Sdim if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0) 4044214571Sdim { 4045214571Sdim SET_INSN_ERROR (BAD_ARGS); 4046214571Sdim } 4047214571Sdim else 4048214571Sdim { 4049214571Sdim SET_INSN_ERROR (NULL); 4050214571Sdim do_rsrs (str); 4051214571Sdim } 4052214571Sdim return; 4053214571Sdim } 4054214571Sdim else 4055214571Sdim { 4056214571Sdim SET_INSN_ERROR (NULL); 4057214571Sdim if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) 4058214571Sdim || (end_of_line (backupstr) == (int) FAIL)) 4059214571Sdim { 4060214571Sdim return; 4061214571Sdim } 4062214571Sdim else 4063214571Sdim { 4064214571Sdim char append_str1[MAX_LITERAL_POOL_SIZE]; 4065214571Sdim 4066214571Sdim if (strcmp (inst.name, "rem") == 0) 4067214571Sdim { 4068214571Sdim sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2); 4069214571Sdim sprintf (append_str1, "mfceh r%d", reg_rd); 4070214571Sdim } 4071214571Sdim else if (strcmp (inst.name, "remu") == 0) 4072214571Sdim { 4073214571Sdim sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2); 4074214571Sdim sprintf (append_str1, "mfceh r%d", reg_rd); 4075214571Sdim } 4076214571Sdim else 4077214571Sdim { 4078214571Sdim sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2); 4079214571Sdim sprintf (append_str1, "mfcel r%d", reg_rd); 4080214571Sdim } 4081214571Sdim 4082214571Sdim /* Output mul/mulu or div/divu or rem/remu. */ 4083214571Sdim if (append_insn (append_str, TRUE) == (int) FAIL) 4084214571Sdim return; 4085214571Sdim 4086214571Sdim /* Output mfcel or mfceh. */ 4087214571Sdim if (append_insn (append_str1, TRUE) == (int) FAIL) 4088214571Sdim return; 4089214571Sdim 4090214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4091214571Sdim inst.bwarn = -1; 4092214571Sdim } 4093214571Sdim } 4094214571Sdim} 4095214571Sdim 4096214571Sdimstatic void 4097214571Sdimexp_macro_ldst_abs (char *str) 4098214571Sdim{ 4099214571Sdim int reg_rd; 4100214571Sdim char *backupstr, *tmp; 4101214571Sdim char append_str[MAX_LITERAL_POOL_SIZE]; 4102214571Sdim char verifystr[MAX_LITERAL_POOL_SIZE]; 4103214571Sdim struct score_it inst_backup; 4104214571Sdim int r1_bak = 0; 4105214571Sdim 4106214571Sdim r1_bak = nor1; 4107214571Sdim nor1 = 0; 4108214571Sdim memcpy (&inst_backup, &inst, sizeof (struct score_it)); 4109214571Sdim 4110214571Sdim strcpy (verifystr, str); 4111214571Sdim backupstr = verifystr; 4112214571Sdim skip_whitespace (backupstr); 4113214571Sdim if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) 4114214571Sdim return; 4115214571Sdim 4116214571Sdim tmp = backupstr; 4117214571Sdim if (skip_past_comma (&backupstr) == (int) FAIL) 4118214571Sdim return; 4119214571Sdim 4120214571Sdim backupstr = tmp; 4121214571Sdim sprintf (append_str, "li r1 %s", backupstr); 4122214571Sdim append_insn (append_str, TRUE); 4123214571Sdim 4124214571Sdim memcpy (&inst, &inst_backup, sizeof (struct score_it)); 4125214571Sdim sprintf (append_str, " r%d, [r1,0]", reg_rd); 4126214571Sdim do_ldst_insn (append_str); 4127214571Sdim 4128214571Sdim nor1 = r1_bak; 4129214571Sdim} 4130214571Sdim 4131214571Sdimstatic int 4132214571Sdimnopic_need_relax (symbolS * sym, int before_relaxing) 4133214571Sdim{ 4134214571Sdim if (sym == NULL) 4135214571Sdim return 0; 4136214571Sdim else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0) 4137214571Sdim { 4138214571Sdim const char *symname; 4139214571Sdim const char *segname; 4140214571Sdim 4141214571Sdim /* Find out whether this symbol can be referenced off the $gp 4142214571Sdim register. It can be if it is smaller than the -G size or if 4143214571Sdim it is in the .sdata or .sbss section. Certain symbols can 4144214571Sdim not be referenced off the $gp, although it appears as though 4145214571Sdim they can. */ 4146214571Sdim symname = S_GET_NAME (sym); 4147214571Sdim if (symname != (const char *)NULL 4148214571Sdim && (strcmp (symname, "eprol") == 0 4149214571Sdim || strcmp (symname, "etext") == 0 4150214571Sdim || strcmp (symname, "_gp") == 0 4151214571Sdim || strcmp (symname, "edata") == 0 4152214571Sdim || strcmp (symname, "_fbss") == 0 4153214571Sdim || strcmp (symname, "_fdata") == 0 4154214571Sdim || strcmp (symname, "_ftext") == 0 4155214571Sdim || strcmp (symname, "end") == 0 4156214571Sdim || strcmp (symname, GP_DISP_LABEL) == 0)) 4157214571Sdim { 4158214571Sdim return 1; 4159214571Sdim } 4160214571Sdim else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 4161214571Sdim /* We must defer this decision until after the whole file has been read, 4162214571Sdim since there might be a .extern after the first use of this symbol. */ 4163214571Sdim || (before_relaxing 4164214571Sdim && S_GET_VALUE (sym) == 0) 4165214571Sdim || (S_GET_VALUE (sym) != 0 4166214571Sdim && S_GET_VALUE (sym) <= g_switch_value))) 4167214571Sdim { 4168214571Sdim return 0; 4169214571Sdim } 4170214571Sdim 4171214571Sdim segname = segment_name (S_GET_SEGMENT (sym)); 4172214571Sdim return (strcmp (segname, ".sdata") != 0 4173214571Sdim && strcmp (segname, ".sbss") != 0 4174214571Sdim && strncmp (segname, ".sdata.", 7) != 0 4175214571Sdim && strncmp (segname, ".gnu.linkonce.s.", 16) != 0); 4176214571Sdim } 4177214571Sdim /* We are not optimizing for the $gp register. */ 4178214571Sdim else 4179214571Sdim return 1; 4180214571Sdim} 4181214571Sdim 4182214571Sdim/* Build a relax frag for lw/st instruction when generating PIC, 4183214571Sdim external symbol first and local symbol second. */ 4184214571Sdim 4185214571Sdimstatic void 4186214571Sdimbuild_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) 4187214571Sdim{ 4188214571Sdim symbolS *add_symbol = exp.X_add_symbol; 4189214571Sdim int add_number = exp.X_add_number; 4190214571Sdim struct score_it fix_insts[RELAX_INST_NUM]; 4191214571Sdim struct score_it var_insts[RELAX_INST_NUM]; 4192214571Sdim int fix_num = 0; 4193214571Sdim int var_num = 0; 4194214571Sdim char tmp[MAX_LITERAL_POOL_SIZE]; 4195214571Sdim int r1_bak; 4196214571Sdim 4197214571Sdim r1_bak = nor1; 4198214571Sdim nor1 = 0; 4199214571Sdim 4200214571Sdim if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) 4201214571Sdim { 4202214571Sdim fix_num = 1; 4203214571Sdim var_num = 2; 4204214571Sdim 4205214571Sdim /* For an external symbol, two insns are generated; 4206214571Sdim For a local symbol, three insns are generated. */ 4207214571Sdim /* Fix part 4208214571Sdim For an external symbol: lw rD, <sym>($gp) 4209214571Sdim (BFD_RELOC_SCORE_GOT15) */ 4210214571Sdim sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name); 4211214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 4212214571Sdim return; 4213214571Sdim 4214214571Sdim memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); 4215214571Sdim 4216214571Sdim /* Var part 4217214571Sdim For a local symbol : 4218214571Sdim lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) 4219214571Sdim addi rD, <sym> (BFD_RELOC_GOT_LO16) */ 4220214571Sdim inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4221214571Sdim memcpy (&var_insts[0], &inst, sizeof (struct score_it)); 4222214571Sdim sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name); 4223214571Sdim if (append_insn (tmp, FALSE) == (int) FAIL) 4224214571Sdim return; 4225214571Sdim 4226214571Sdim memcpy (&var_insts[1], &inst, sizeof (struct score_it)); 4227214571Sdim build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); 4228214571Sdim 4229214571Sdim /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ 4230214571Sdim sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); 4231214571Sdim if (append_insn (tmp, TRUE) == (int) FAIL) 4232214571Sdim return; 4233214571Sdim 4234214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4235214571Sdim inst.bwarn = -1; 4236214571Sdim } 4237214571Sdim else 4238214571Sdim { 4239214571Sdim inst.error = _("PIC code offset overflow (max 16 signed bits)"); 4240214571Sdim return; 4241214571Sdim } 4242214571Sdim 4243214571Sdim nor1 = r1_bak; 4244214571Sdim} 4245214571Sdim 4246214571Sdimstatic void 4247214571Sdimdo_macro_ldst_label (char *str) 4248214571Sdim{ 4249214571Sdim int i; 4250214571Sdim int ldst_gp_p = 0; 4251214571Sdim int reg_rd; 4252214571Sdim int r1_bak; 4253214571Sdim char *backup_str; 4254214571Sdim char *label_str; 4255214571Sdim char *absolute_value; 4256214571Sdim char append_str[3][MAX_LITERAL_POOL_SIZE]; 4257214571Sdim char verifystr[MAX_LITERAL_POOL_SIZE]; 4258214571Sdim struct score_it inst_backup; 4259214571Sdim struct score_it inst_expand[3]; 4260214571Sdim struct score_it inst_main; 4261214571Sdim 4262214571Sdim memcpy (&inst_backup, &inst, sizeof (struct score_it)); 4263214571Sdim strcpy (verifystr, str); 4264214571Sdim backup_str = verifystr; 4265214571Sdim 4266214571Sdim skip_whitespace (backup_str); 4267214571Sdim if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL) 4268214571Sdim return; 4269214571Sdim 4270214571Sdim if (skip_past_comma (&backup_str) == (int) FAIL) 4271214571Sdim return; 4272214571Sdim 4273214571Sdim label_str = backup_str; 4274214571Sdim 4275214571Sdim /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */ 4276214571Sdim if (*backup_str == '[') 4277214571Sdim { 4278214571Sdim inst.type = Rd_rvalueRs_preSI12; 4279214571Sdim do_ldst_insn (str); 4280214571Sdim return; 4281214571Sdim } 4282214571Sdim 4283214571Sdim /* Ld/st rD, imm. */ 4284214571Sdim absolute_value = backup_str; 4285214571Sdim inst.type = Rd_rvalueRs_SI15; 4286214571Sdim if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL) 4287214571Sdim || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL) 4288214571Sdim || (end_of_line (backup_str) == (int) FAIL)) 4289214571Sdim { 4290214571Sdim return; 4291214571Sdim } 4292214571Sdim else 4293214571Sdim { 4294214571Sdim if (inst.reloc.exp.X_add_symbol == 0) 4295214571Sdim { 4296214571Sdim memcpy (&inst, &inst_backup, sizeof (struct score_it)); 4297214571Sdim exp_macro_ldst_abs (str); 4298214571Sdim return; 4299214571Sdim } 4300214571Sdim } 4301214571Sdim 4302214571Sdim /* Ld/st rD, label. */ 4303214571Sdim inst.type = Rd_rvalueRs_SI15; 4304214571Sdim backup_str = absolute_value; 4305214571Sdim if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL) 4306214571Sdim || (end_of_line (backup_str) == (int) FAIL)) 4307214571Sdim { 4308214571Sdim return; 4309214571Sdim } 4310214571Sdim else 4311214571Sdim { 4312214571Sdim if (inst.reloc.exp.X_add_symbol == 0) 4313214571Sdim { 4314214571Sdim if (!inst.error) 4315214571Sdim inst.error = BAD_ARGS; 4316214571Sdim 4317214571Sdim return; 4318214571Sdim } 4319214571Sdim 4320214571Sdim if (score_pic == PIC) 4321214571Sdim { 4322214571Sdim int ldst_idx = 0; 4323214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 4324214571Sdim build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template); 4325214571Sdim return; 4326214571Sdim } 4327214571Sdim else 4328214571Sdim { 4329214571Sdim if ((inst.reloc.exp.X_add_number <= 0x3fff) 4330214571Sdim && (inst.reloc.exp.X_add_number >= -0x4000) 4331214571Sdim && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1))) 4332214571Sdim { 4333214571Sdim int ldst_idx = 0; 4334214571Sdim 4335214571Sdim /* Assign the real opcode. */ 4336214571Sdim ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; 4337214571Sdim inst.instruction &= ~OPC_PSEUDOLDST_MASK; 4338214571Sdim inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value; 4339214571Sdim inst.instruction |= reg_rd << 20; 4340214571Sdim inst.instruction |= GP << 15; 4341214571Sdim inst.relax_inst = 0x8000; 4342214571Sdim inst.relax_size = 0; 4343214571Sdim ldst_gp_p = 1; 4344214571Sdim } 4345214571Sdim } 4346214571Sdim } 4347214571Sdim 4348214571Sdim /* Backup inst. */ 4349214571Sdim memcpy (&inst_main, &inst, sizeof (struct score_it)); 4350214571Sdim r1_bak = nor1; 4351214571Sdim nor1 = 0; 4352214571Sdim 4353214571Sdim /* Determine which instructions should be output. */ 4354214571Sdim sprintf (append_str[0], "ld_i32hi r1, %s", label_str); 4355214571Sdim sprintf (append_str[1], "ld_i32lo r1, %s", label_str); 4356214571Sdim sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd); 4357214571Sdim 4358214571Sdim /* Generate three instructions. 4359214571Sdim la r1, label 4360214571Sdim ld/st rd, [r1, 0] */ 4361214571Sdim for (i = 0; i < 3; i++) 4362214571Sdim { 4363214571Sdim if (append_insn (append_str[i], FALSE) == (int) FAIL) 4364214571Sdim return; 4365214571Sdim 4366214571Sdim memcpy (&inst_expand[i], &inst, sizeof (struct score_it)); 4367214571Sdim } 4368214571Sdim 4369214571Sdim if (ldst_gp_p) 4370214571Sdim { 4371214571Sdim char *p; 4372214571Sdim 4373214571Sdim /* Adjust instruction opcode and to be relaxed instruction opcode. */ 4374214571Sdim inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type)); 4375214571Sdim inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; 4376214571Sdim inst_main.type = Insn_GP; 4377214571Sdim 4378214571Sdim for (i = 0; i < 3; i++) 4379214571Sdim inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction 4380214571Sdim , GET_INSN_CLASS (inst_expand[i].type)); 4381214571Sdim 4382214571Sdim /* Check data dependency. */ 4383214571Sdim handle_dependency (&inst_main); 4384214571Sdim 4385214571Sdim /* Start a new frag if frag_now is not empty. */ 4386214571Sdim if (frag_now_fix () != 0) 4387214571Sdim { 4388214571Sdim if (!frag_now->tc_frag_data.is_insn) 4389214571Sdim frag_wane (frag_now); 4390214571Sdim 4391214571Sdim frag_new (0); 4392214571Sdim } 4393214571Sdim frag_grow (20); 4394214571Sdim 4395214571Sdim /* Write fr_fix part. */ 4396214571Sdim p = frag_more (inst_main.size); 4397214571Sdim md_number_to_chars (p, inst_main.instruction, inst_main.size); 4398214571Sdim 4399214571Sdim if (inst_main.reloc.type != BFD_RELOC_NONE) 4400214571Sdim { 4401214571Sdim fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, 4402214571Sdim &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); 4403214571Sdim } 4404214571Sdim 4405214571Sdim#ifdef OBJ_ELF 4406214571Sdim dwarf2_emit_insn (inst_main.size); 4407214571Sdim#endif 4408214571Sdim 4409214571Sdim /* GP instruction can not do optimization, only can do relax between 4410214571Sdim 1 instruction and 3 instructions. */ 4411214571Sdim p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0, 4412214571Sdim RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), 4413214571Sdim inst_main.reloc.exp.X_add_symbol, 0, NULL); 4414214571Sdim 4415214571Sdim /* Write fr_var part. 4416214571Sdim no calling gen_insn_frag, no fixS will be generated. */ 4417214571Sdim md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); 4418214571Sdim p += inst_expand[0].size; 4419214571Sdim md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); 4420214571Sdim p += inst_expand[1].size; 4421214571Sdim md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); 4422214571Sdim } 4423214571Sdim else 4424214571Sdim { 4425214571Sdim gen_insn_frag (&inst_expand[0], NULL); 4426214571Sdim gen_insn_frag (&inst_expand[1], NULL); 4427214571Sdim gen_insn_frag (&inst_expand[2], NULL); 4428214571Sdim } 4429214571Sdim nor1 = r1_bak; 4430214571Sdim 4431214571Sdim /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ 4432214571Sdim inst.bwarn = -1; 4433214571Sdim} 4434214571Sdim 4435214571Sdimstatic void 4436214571Sdimdo_lw_pic (char *str) 4437214571Sdim{ 4438214571Sdim int reg_rd; 4439214571Sdim 4440214571Sdim skip_whitespace (str); 4441214571Sdim if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) 4442214571Sdim || (skip_past_comma (&str) == (int) FAIL) 4443214571Sdim || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL) 4444214571Sdim || (end_of_line (str) == (int) FAIL)) 4445214571Sdim { 4446214571Sdim return; 4447214571Sdim } 4448214571Sdim else 4449214571Sdim { 4450214571Sdim if (inst.reloc.exp.X_add_symbol == 0) 4451214571Sdim { 4452214571Sdim if (!inst.error) 4453214571Sdim inst.error = BAD_ARGS; 4454214571Sdim 4455214571Sdim return; 4456214571Sdim } 4457214571Sdim 4458214571Sdim inst.instruction |= GP << 15; 4459214571Sdim inst.reloc.type = BFD_RELOC_SCORE_GOT15; 4460214571Sdim } 4461214571Sdim} 4462214571Sdim 4463214571Sdimstatic void 4464214571Sdimdo_empty (char *str) 4465214571Sdim{ 4466214571Sdim str = str; 4467214571Sdim if (university_version == 1) 4468214571Sdim { 4469214571Sdim if (((inst.instruction & 0x3e0003ff) == 0x0c000004) 4470214571Sdim || ((inst.instruction & 0x3e0003ff) == 0x0c000024) 4471214571Sdim || ((inst.instruction & 0x3e0003ff) == 0x0c000044) 4472214571Sdim || ((inst.instruction & 0x3e0003ff) == 0x0c000064)) 4473214571Sdim { 4474214571Sdim inst.error = ERR_FOR_SCORE5U_MMU; 4475214571Sdim return; 4476214571Sdim } 4477214571Sdim } 4478214571Sdim if (end_of_line (str) == (int) FAIL) 4479214571Sdim return; 4480214571Sdim 4481214571Sdim if (inst.relax_inst != 0x8000) 4482214571Sdim { 4483214571Sdim if (inst.type == NO_OPD) 4484214571Sdim { 4485214571Sdim inst.relax_size = 2; 4486214571Sdim } 4487214571Sdim else 4488214571Sdim { 4489214571Sdim inst.relax_size = 4; 4490214571Sdim } 4491214571Sdim } 4492214571Sdim} 4493214571Sdim 4494214571Sdimstatic void 4495214571Sdimdo_jump (char *str) 4496214571Sdim{ 4497214571Sdim char *save_in; 4498214571Sdim 4499214571Sdim skip_whitespace (str); 4500214571Sdim if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL 4501214571Sdim || end_of_line (str) == (int) FAIL) 4502214571Sdim return; 4503214571Sdim 4504214571Sdim if (inst.reloc.exp.X_add_symbol == 0) 4505214571Sdim { 4506214571Sdim inst.error = _("lacking label "); 4507214571Sdim return; 4508214571Sdim } 4509214571Sdim 4510214571Sdim if (((inst.reloc.exp.X_add_number & 0xff000000) != 0) 4511214571Sdim && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000)) 4512214571Sdim { 4513214571Sdim inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24"); 4514214571Sdim return; 4515214571Sdim } 4516214571Sdim 4517214571Sdim save_in = input_line_pointer; 4518214571Sdim input_line_pointer = str; 4519214571Sdim inst.reloc.type = BFD_RELOC_SCORE_JMP; 4520214571Sdim inst.reloc.pc_rel = 1; 4521214571Sdim input_line_pointer = save_in; 4522214571Sdim} 4523214571Sdim 4524214571Sdimstatic void 4525214571Sdimdo16_jump (char *str) 4526214571Sdim{ 4527214571Sdim skip_whitespace (str); 4528214571Sdim if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL 4529214571Sdim || end_of_line (str) == (int) FAIL) 4530214571Sdim { 4531214571Sdim return; 4532214571Sdim } 4533214571Sdim else if (inst.reloc.exp.X_add_symbol == 0) 4534214571Sdim { 4535214571Sdim inst.error = _("lacking label "); 4536214571Sdim return; 4537214571Sdim } 4538214571Sdim else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0) 4539214571Sdim && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800)) 4540214571Sdim { 4541214571Sdim inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11"); 4542214571Sdim return; 4543214571Sdim } 4544214571Sdim 4545214571Sdim inst.reloc.type = BFD_RELOC_SCORE16_JMP; 4546214571Sdim inst.reloc.pc_rel = 1; 4547214571Sdim} 4548214571Sdim 4549214571Sdimstatic void 4550214571Sdimdo_branch (char *str) 4551214571Sdim{ 4552214571Sdim unsigned long abs_value = 0; 4553214571Sdim 4554214571Sdim if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL 4555214571Sdim || end_of_line (str) == (int) FAIL) 4556214571Sdim { 4557214571Sdim return; 4558214571Sdim } 4559214571Sdim else if (inst.reloc.exp.X_add_symbol == 0) 4560214571Sdim { 4561214571Sdim inst.error = _("lacking label "); 4562214571Sdim return; 4563214571Sdim } 4564214571Sdim else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0) 4565214571Sdim && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000)) 4566214571Sdim { 4567214571Sdim inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19"); 4568214571Sdim return; 4569214571Sdim } 4570214571Sdim 4571214571Sdim inst.reloc.type = BFD_RELOC_SCORE_BRANCH; 4572214571Sdim inst.reloc.pc_rel = 1; 4573214571Sdim 4574214571Sdim /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ 4575214571Sdim inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5); 4576214571Sdim 4577214571Sdim /* Compute 16 bit branch instruction. */ 4578214571Sdim if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0) 4579214571Sdim { 4580214571Sdim inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8); 4581214571Sdim inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff); 4582214571Sdim inst.relax_size = 2; 4583214571Sdim } 4584214571Sdim else 4585214571Sdim { 4586214571Sdim inst.relax_inst = 0x8000; 4587214571Sdim } 4588214571Sdim} 4589214571Sdim 4590214571Sdimstatic void 4591214571Sdimdo16_branch (char *str) 4592214571Sdim{ 4593214571Sdim if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL 4594214571Sdim || end_of_line (str) == (int) FAIL)) 4595214571Sdim { 4596214571Sdim ; 4597214571Sdim } 4598214571Sdim else if (inst.reloc.exp.X_add_symbol == 0) 4599214571Sdim { 4600214571Sdim inst.error = _("lacking label"); 4601214571Sdim } 4602214571Sdim else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0) 4603214571Sdim && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00)) 4604214571Sdim { 4605214571Sdim inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8"); 4606214571Sdim } 4607214571Sdim else 4608214571Sdim { 4609214571Sdim inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; 4610214571Sdim inst.reloc.pc_rel = 1; 4611214571Sdim inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff); 4612214571Sdim } 4613214571Sdim} 4614214571Sdim 4615214571Sdim/* Iterate over the base tables to create the instruction patterns. */ 4616214571Sdimstatic void 4617214571Sdimbuild_score_ops_hsh (void) 4618214571Sdim{ 4619214571Sdim unsigned int i; 4620214571Sdim static struct obstack insn_obstack; 4621214571Sdim 4622214571Sdim obstack_begin (&insn_obstack, 4000); 4623214571Sdim for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++) 4624214571Sdim { 4625214571Sdim const struct asm_opcode *insn = score_insns + i; 4626214571Sdim unsigned len = strlen (insn->template); 4627214571Sdim struct asm_opcode *new; 4628214571Sdim char *template; 4629214571Sdim new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode)); 4630214571Sdim template = obstack_alloc (&insn_obstack, len + 1); 4631214571Sdim 4632214571Sdim strcpy (template, insn->template); 4633214571Sdim new->template = template; 4634214571Sdim new->parms = insn->parms; 4635214571Sdim new->value = insn->value; 4636214571Sdim new->relax_value = insn->relax_value; 4637214571Sdim new->type = insn->type; 4638214571Sdim new->bitmask = insn->bitmask; 4639214571Sdim hash_insert (score_ops_hsh, new->template, (void *) new); 4640214571Sdim } 4641214571Sdim} 4642214571Sdim 4643214571Sdimstatic void 4644214571Sdimbuild_dependency_insn_hsh (void) 4645214571Sdim{ 4646214571Sdim unsigned int i; 4647214571Sdim static struct obstack dependency_obstack; 4648214571Sdim 4649214571Sdim obstack_begin (&dependency_obstack, 4000); 4650214571Sdim for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++) 4651214571Sdim { 4652214571Sdim const struct insn_to_dependency *tmp = insn_to_dependency_table + i; 4653214571Sdim unsigned len = strlen (tmp->insn_name); 4654214571Sdim struct insn_to_dependency *new; 4655214571Sdim 4656214571Sdim new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency)); 4657214571Sdim new->insn_name = obstack_alloc (&dependency_obstack, len + 1); 4658214571Sdim 4659214571Sdim strcpy (new->insn_name, tmp->insn_name); 4660214571Sdim new->type = tmp->type; 4661214571Sdim hash_insert (dependency_insn_hsh, new->insn_name, (void *) new); 4662214571Sdim } 4663214571Sdim} 4664214571Sdim 4665214571Sdim/* Turn an integer of n bytes (in val) into a stream of bytes appropriate 4666214571Sdim for use in the a.out file, and stores them in the array pointed to by buf. 4667214571Sdim This knows about the endian-ness of the target machine and does 4668214571Sdim THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) 4669214571Sdim 2 (short) and 4 (long) Floating numbers are put out as a series of 4670214571Sdim LITTLENUMS (shorts, here at least). */ 4671214571Sdim 4672214571Sdimvoid 4673214571Sdimmd_number_to_chars (char *buf, valueT val, int n) 4674214571Sdim{ 4675214571Sdim if (target_big_endian) 4676214571Sdim number_to_chars_bigendian (buf, val, n); 4677214571Sdim else 4678214571Sdim number_to_chars_littleendian (buf, val, n); 4679214571Sdim} 4680214571Sdim 4681214571Sdimstatic valueT 4682214571Sdimmd_chars_to_number (char *buf, int n) 4683214571Sdim{ 4684214571Sdim valueT result = 0; 4685214571Sdim unsigned char *where = (unsigned char *)buf; 4686214571Sdim 4687214571Sdim if (target_big_endian) 4688214571Sdim { 4689214571Sdim while (n--) 4690214571Sdim { 4691214571Sdim result <<= 8; 4692214571Sdim result |= (*where++ & 255); 4693214571Sdim } 4694214571Sdim } 4695214571Sdim else 4696214571Sdim { 4697214571Sdim while (n--) 4698214571Sdim { 4699214571Sdim result <<= 8; 4700214571Sdim result |= (where[n] & 255); 4701214571Sdim } 4702214571Sdim } 4703214571Sdim 4704214571Sdim return result; 4705214571Sdim} 4706214571Sdim 4707214571Sdim/* Turn a string in input_line_pointer into a floating point constant 4708214571Sdim of type TYPE, and store the appropriate bytes in *LITP. The number 4709214571Sdim of LITTLENUMS emitted is stored in *SIZEP. An error message is 4710214571Sdim returned, or NULL on OK. 4711214571Sdim 4712214571Sdim Note that fp constants aren't represent in the normal way on the ARM. 4713214571Sdim In big endian mode, things are as expected. However, in little endian 4714214571Sdim mode fp constants are big-endian word-wise, and little-endian byte-wise 4715214571Sdim within the words. For example, (double) 1.1 in big endian mode is 4716214571Sdim the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is 4717214571Sdim the byte sequence 99 99 f1 3f 9a 99 99 99. */ 4718214571Sdim 4719214571Sdimchar * 4720214571Sdimmd_atof (int type, char *litP, int *sizeP) 4721214571Sdim{ 4722214571Sdim int prec; 4723214571Sdim LITTLENUM_TYPE words[MAX_LITTLENUMS]; 4724214571Sdim char *t; 4725214571Sdim int i; 4726214571Sdim 4727214571Sdim switch (type) 4728214571Sdim { 4729214571Sdim case 'f': 4730214571Sdim case 'F': 4731214571Sdim case 's': 4732214571Sdim case 'S': 4733214571Sdim prec = 2; 4734214571Sdim break; 4735214571Sdim case 'd': 4736214571Sdim case 'D': 4737214571Sdim case 'r': 4738214571Sdim case 'R': 4739214571Sdim prec = 4; 4740214571Sdim break; 4741214571Sdim case 'x': 4742214571Sdim case 'X': 4743214571Sdim case 'p': 4744214571Sdim case 'P': 4745214571Sdim prec = 6; 4746214571Sdim break; 4747214571Sdim default: 4748214571Sdim *sizeP = 0; 4749214571Sdim return _("bad call to MD_ATOF()"); 4750214571Sdim } 4751214571Sdim 4752214571Sdim t = atof_ieee (input_line_pointer, type, words); 4753214571Sdim if (t) 4754214571Sdim input_line_pointer = t; 4755214571Sdim *sizeP = prec * 2; 4756214571Sdim 4757214571Sdim if (target_big_endian) 4758214571Sdim { 4759214571Sdim for (i = 0; i < prec; i++) 4760214571Sdim { 4761214571Sdim md_number_to_chars (litP, (valueT) words[i], 2); 4762214571Sdim litP += 2; 4763214571Sdim } 4764214571Sdim } 4765214571Sdim else 4766214571Sdim { 4767214571Sdim for (i = 0; i < prec; i += 2) 4768214571Sdim { 4769214571Sdim md_number_to_chars (litP, (valueT) words[i + 1], 2); 4770214571Sdim md_number_to_chars (litP + 2, (valueT) words[i], 2); 4771214571Sdim litP += 4; 4772214571Sdim } 4773214571Sdim } 4774214571Sdim 4775214571Sdim return 0; 4776214571Sdim} 4777214571Sdim 4778214571Sdim/* Return true if the given symbol should be considered local for PIC. */ 4779214571Sdim 4780214571Sdimstatic bfd_boolean 4781214571Sdimpic_need_relax (symbolS *sym, asection *segtype) 4782214571Sdim{ 4783214571Sdim asection *symsec; 4784214571Sdim bfd_boolean linkonce; 4785214571Sdim 4786214571Sdim /* Handle the case of a symbol equated to another symbol. */ 4787214571Sdim while (symbol_equated_reloc_p (sym)) 4788214571Sdim { 4789214571Sdim symbolS *n; 4790214571Sdim 4791214571Sdim /* It's possible to get a loop here in a badly written 4792214571Sdim program. */ 4793214571Sdim n = symbol_get_value_expression (sym)->X_add_symbol; 4794214571Sdim if (n == sym) 4795214571Sdim break; 4796214571Sdim sym = n; 4797214571Sdim } 4798214571Sdim 4799214571Sdim symsec = S_GET_SEGMENT (sym); 4800214571Sdim 4801214571Sdim /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ 4802214571Sdim linkonce = FALSE; 4803214571Sdim if (symsec != segtype && ! S_IS_LOCAL (sym)) 4804214571Sdim { 4805214571Sdim if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0) 4806214571Sdim linkonce = TRUE; 4807214571Sdim 4808214571Sdim /* The GNU toolchain uses an extension for ELF: a section 4809214571Sdim beginning with the magic string .gnu.linkonce is a linkonce 4810214571Sdim section. */ 4811214571Sdim if (strncmp (segment_name (symsec), ".gnu.linkonce", 4812214571Sdim sizeof ".gnu.linkonce" - 1) == 0) 4813214571Sdim linkonce = TRUE; 4814214571Sdim } 4815214571Sdim 4816214571Sdim /* This must duplicate the test in adjust_reloc_syms. */ 4817214571Sdim return (symsec != &bfd_und_section 4818214571Sdim && symsec != &bfd_abs_section 4819214571Sdim && ! bfd_is_com_section (symsec) 4820214571Sdim && !linkonce 4821214571Sdim#ifdef OBJ_ELF 4822214571Sdim /* A global or weak symbol is treated as external. */ 4823214571Sdim && (OUTPUT_FLAVOR != bfd_target_elf_flavour 4824214571Sdim || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) 4825214571Sdim#endif 4826214571Sdim ); 4827214571Sdim} 4828214571Sdim 4829214571Sdimstatic int 4830214571Sdimjudge_size_before_relax (fragS * fragp, asection *sec) 4831214571Sdim{ 4832214571Sdim int change = 0; 4833214571Sdim 4834214571Sdim if (score_pic == NO_PIC) 4835214571Sdim change = nopic_need_relax (fragp->fr_symbol, 0); 4836214571Sdim else 4837214571Sdim change = pic_need_relax (fragp->fr_symbol, sec); 4838214571Sdim 4839214571Sdim if (change == 1) 4840214571Sdim { 4841214571Sdim /* Only at the first time determining whether GP instruction relax should be done, 4842214571Sdim return the difference between insntruction size and instruction relax size. */ 4843214571Sdim if (fragp->fr_opcode == NULL) 4844214571Sdim { 4845214571Sdim fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); 4846214571Sdim fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype); 4847214571Sdim return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype); 4848214571Sdim } 4849214571Sdim } 4850214571Sdim 4851214571Sdim return 0; 4852214571Sdim} 4853214571Sdim 4854214571Sdim/* In this function, we determine whether GP instruction should do relaxation, 4855214571Sdim for the label being against was known now. 4856214571Sdim Doing this here but not in md_relax_frag() can induce iteration times 4857214571Sdim in stage of doing relax. */ 4858214571Sdimint 4859214571Sdimmd_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) 4860214571Sdim{ 4861214571Sdim if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP) 4862214571Sdim || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) 4863214571Sdim return judge_size_before_relax (fragp, sec); 4864214571Sdim 4865214571Sdim return 0; 4866214571Sdim} 4867214571Sdim 4868214571Sdimstatic int 4869214571Sdimb32_relax_to_b16 (fragS * fragp) 4870214571Sdim{ 4871214571Sdim int grows = 0; 4872214571Sdim int relaxable_p = 0; 4873214571Sdim int old; 4874214571Sdim int new; 4875214571Sdim int frag_addr = fragp->fr_address + fragp->insn_addr; 4876214571Sdim 4877214571Sdim addressT symbol_address = 0; 4878214571Sdim symbolS *s; 4879214571Sdim offsetT offset; 4880214571Sdim unsigned long value; 4881214571Sdim unsigned long abs_value; 4882214571Sdim 4883214571Sdim /* FIXME : here may be able to modify better . 4884214571Sdim I don't know how to get the fragp's section , 4885214571Sdim so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section 4886214571Sdim is different from the symbol's. */ 4887214571Sdim 4888214571Sdim old = RELAX_OLD (fragp->fr_subtype); 4889214571Sdim new = RELAX_NEW (fragp->fr_subtype); 4890214571Sdim relaxable_p = RELAX_OPT (fragp->fr_subtype); 4891214571Sdim 4892214571Sdim s = fragp->fr_symbol; 4893214571Sdim /* b/bl immediate */ 4894214571Sdim if (s == NULL) 4895214571Sdim frag_addr = 0; 4896214571Sdim else 4897214571Sdim { 4898214571Sdim if (s->bsym != 0) 4899214571Sdim symbol_address = (addressT) s->sy_frag->fr_address; 4900214571Sdim } 4901214571Sdim 4902214571Sdim value = md_chars_to_number (fragp->fr_literal, INSN_SIZE); 4903214571Sdim 4904214571Sdim /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */ 4905214571Sdim offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe); 4906214571Sdim if ((offset & 0x80000) == 0x80000) 4907214571Sdim offset |= 0xfff00000; 4908214571Sdim 4909214571Sdim abs_value = offset + symbol_address - frag_addr; 4910214571Sdim if ((abs_value & 0x80000000) == 0x80000000) 4911214571Sdim abs_value = 0xffffffff - abs_value + 1; 4912214571Sdim 4913214571Sdim /* Relax branch 32 to branch 16. */ 4914214571Sdim if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0) 4915214571Sdim && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s))) 4916214571Sdim { 4917214571Sdim /* do nothing. */ 4918214571Sdim } 4919214571Sdim else 4920214571Sdim { 4921214571Sdim /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */ 4922214571Sdim fragp->fr_opcode = NULL; 4923214571Sdim fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype); 4924214571Sdim } 4925214571Sdim 4926214571Sdim return grows; 4927214571Sdim} 4928214571Sdim 4929214571Sdim/* Main purpose is to determine whether one frag should do relax. 4930214571Sdim frag->fr_opcode indicates this point. */ 4931214571Sdim 4932214571Sdimint 4933214571Sdimscore_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) 4934214571Sdim{ 4935214571Sdim int grows = 0; 4936214571Sdim int insn_size; 4937214571Sdim int insn_relax_size; 4938214571Sdim int do_relax_p = 0; /* Indicate doing relaxation for this frag. */ 4939214571Sdim int relaxable_p = 0; 4940214571Sdim bfd_boolean word_align_p = FALSE; 4941214571Sdim fragS *next_fragp; 4942214571Sdim 4943214571Sdim /* If the instruction address is odd, make it half word align first. */ 4944214571Sdim if ((fragp->fr_address) % 2 != 0) 4945214571Sdim { 4946214571Sdim if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) 4947214571Sdim { 4948214571Sdim fragp->insn_addr = 1; 4949214571Sdim grows += 1; 4950214571Sdim } 4951214571Sdim } 4952214571Sdim 4953214571Sdim word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE; 4954214571Sdim 4955214571Sdim /* Get instruction size and relax size after the last relaxation. */ 4956214571Sdim if (fragp->fr_opcode) 4957214571Sdim { 4958214571Sdim insn_size = RELAX_NEW (fragp->fr_subtype); 4959214571Sdim insn_relax_size = RELAX_OLD (fragp->fr_subtype); 4960214571Sdim } 4961214571Sdim else 4962214571Sdim { 4963214571Sdim insn_size = RELAX_OLD (fragp->fr_subtype); 4964214571Sdim insn_relax_size = RELAX_NEW (fragp->fr_subtype); 4965214571Sdim } 4966214571Sdim 4967214571Sdim /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine 4968214571Sdim whether the GP instruction should do relax. */ 4969214571Sdim if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP) 4970214571Sdim || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) 4971214571Sdim { 4972214571Sdim if (!word_align_p) 4973214571Sdim { 4974214571Sdim if (fragp->insn_addr < 2) 4975214571Sdim { 4976214571Sdim fragp->insn_addr += 2; 4977214571Sdim grows += 2; 4978214571Sdim } 4979214571Sdim else 4980214571Sdim { 4981214571Sdim fragp->insn_addr -= 2; 4982214571Sdim grows -= 2; 4983214571Sdim } 4984214571Sdim } 4985214571Sdim 4986214571Sdim if (fragp->fr_opcode) 4987214571Sdim fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr; 4988214571Sdim else 4989214571Sdim fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr; 4990214571Sdim } 4991214571Sdim else 4992214571Sdim { 4993214571Sdim if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2) 4994214571Sdim b32_relax_to_b16 (fragp); 4995214571Sdim 4996214571Sdim relaxable_p = RELAX_OPT (fragp->fr_subtype); 4997214571Sdim next_fragp = fragp->fr_next; 4998214571Sdim while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent)) 4999214571Sdim { 5000214571Sdim next_fragp = next_fragp->fr_next; 5001214571Sdim } 5002214571Sdim 5003214571Sdim if (next_fragp) 5004214571Sdim { 5005214571Sdim int n_insn_size; 5006214571Sdim int n_relaxable_p = 0; 5007214571Sdim 5008214571Sdim if (next_fragp->fr_opcode) 5009214571Sdim { 5010214571Sdim n_insn_size = RELAX_NEW (next_fragp->fr_subtype); 5011214571Sdim } 5012214571Sdim else 5013214571Sdim { 5014214571Sdim n_insn_size = RELAX_OLD (next_fragp->fr_subtype); 5015214571Sdim } 5016214571Sdim 5017214571Sdim if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2) 5018214571Sdim b32_relax_to_b16 (next_fragp); 5019214571Sdim n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype); 5020214571Sdim 5021214571Sdim if (word_align_p) 5022214571Sdim { 5023214571Sdim if (insn_size == 4) 5024214571Sdim { 5025214571Sdim /* 32 -> 16. */ 5026214571Sdim if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p)) 5027214571Sdim { 5028214571Sdim grows -= 2; 5029214571Sdim do_relax_p = 1; 5030214571Sdim } 5031214571Sdim } 5032214571Sdim else if (insn_size == 2) 5033214571Sdim { 5034214571Sdim /* 16 -> 32. */ 5035214571Sdim if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4))) 5036214571Sdim { 5037214571Sdim grows += 2; 5038214571Sdim do_relax_p = 1; 5039214571Sdim } 5040214571Sdim } 5041214571Sdim else 5042214571Sdim { 5043214571Sdim abort (); 5044214571Sdim } 5045214571Sdim } 5046214571Sdim else 5047214571Sdim { 5048214571Sdim if (insn_size == 4) 5049214571Sdim { 5050214571Sdim /* 32 -> 16. */ 5051214571Sdim if (relaxable_p) 5052214571Sdim { 5053214571Sdim grows -= 2; 5054214571Sdim do_relax_p = 1; 5055214571Sdim } 5056214571Sdim /* Make the 32 bit insturction word align. */ 5057214571Sdim else 5058214571Sdim { 5059214571Sdim fragp->insn_addr += 2; 5060214571Sdim grows += 2; 5061214571Sdim } 5062214571Sdim } 5063214571Sdim else if (insn_size == 2) 5064214571Sdim { 5065214571Sdim /* Do nothing. */ 5066214571Sdim } 5067214571Sdim else 5068214571Sdim { 5069214571Sdim abort (); 5070214571Sdim } 5071214571Sdim } 5072214571Sdim } 5073214571Sdim else 5074214571Sdim { 5075214571Sdim /* Here, try best to do relax regardless fragp->fr_next->fr_type. */ 5076214571Sdim if (word_align_p == FALSE) 5077214571Sdim { 5078214571Sdim if (insn_size % 4 == 0) 5079214571Sdim { 5080214571Sdim /* 32 -> 16. */ 5081214571Sdim if (relaxable_p) 5082214571Sdim { 5083214571Sdim grows -= 2; 5084214571Sdim do_relax_p = 1; 5085214571Sdim } 5086214571Sdim else 5087214571Sdim { 5088214571Sdim fragp->insn_addr += 2; 5089214571Sdim grows += 2; 5090214571Sdim } 5091214571Sdim } 5092214571Sdim } 5093214571Sdim else 5094214571Sdim { 5095214571Sdim /* Do nothing. */ 5096214571Sdim } 5097214571Sdim } 5098214571Sdim 5099214571Sdim /* fragp->fr_opcode indicates whether this frag should be relaxed. */ 5100214571Sdim if (do_relax_p) 5101214571Sdim { 5102214571Sdim if (fragp->fr_opcode) 5103214571Sdim { 5104214571Sdim fragp->fr_opcode = NULL; 5105214571Sdim /* Guarantee estimate stage is correct. */ 5106214571Sdim fragp->fr_fix = RELAX_OLD (fragp->fr_subtype); 5107214571Sdim fragp->fr_fix += fragp->insn_addr; 5108214571Sdim } 5109214571Sdim else 5110214571Sdim { 5111214571Sdim fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype); 5112214571Sdim /* Guarantee estimate stage is correct. */ 5113214571Sdim fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); 5114214571Sdim fragp->fr_fix += fragp->insn_addr; 5115214571Sdim } 5116214571Sdim } 5117214571Sdim else 5118214571Sdim { 5119214571Sdim if (fragp->fr_opcode) 5120214571Sdim { 5121214571Sdim /* Guarantee estimate stage is correct. */ 5122214571Sdim fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); 5123214571Sdim fragp->fr_fix += fragp->insn_addr; 5124214571Sdim } 5125214571Sdim else 5126214571Sdim { 5127214571Sdim /* Guarantee estimate stage is correct. */ 5128214571Sdim fragp->fr_fix = RELAX_OLD (fragp->fr_subtype); 5129214571Sdim fragp->fr_fix += fragp->insn_addr; 5130214571Sdim } 5131214571Sdim } 5132214571Sdim } 5133214571Sdim 5134214571Sdim return grows; 5135214571Sdim} 5136214571Sdim 5137214571Sdimvoid 5138214571Sdimmd_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) 5139214571Sdim{ 5140214571Sdim int old; 5141214571Sdim int new; 5142214571Sdim char backup[20]; 5143214571Sdim fixS *fixp; 5144214571Sdim 5145214571Sdim old = RELAX_OLD (fragp->fr_subtype); 5146214571Sdim new = RELAX_NEW (fragp->fr_subtype); 5147214571Sdim 5148214571Sdim /* fragp->fr_opcode indicates whether this frag should be relaxed. */ 5149214571Sdim if (fragp->fr_opcode == NULL) 5150214571Sdim { 5151214571Sdim memcpy (backup, fragp->fr_literal, old); 5152214571Sdim fragp->fr_fix = old; 5153214571Sdim } 5154214571Sdim else 5155214571Sdim { 5156214571Sdim memcpy (backup, fragp->fr_literal + old, new); 5157214571Sdim fragp->fr_fix = new; 5158214571Sdim } 5159214571Sdim 5160214571Sdim fixp = fragp->tc_frag_data.fixp; 5161214571Sdim while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old) 5162214571Sdim { 5163214571Sdim if (fragp->fr_opcode) 5164214571Sdim fixp->fx_done = 1; 5165214571Sdim fixp = fixp->fx_next; 5166214571Sdim } 5167214571Sdim while (fixp && fixp->fx_frag == fragp) 5168214571Sdim { 5169214571Sdim if (fragp->fr_opcode) 5170214571Sdim fixp->fx_where -= old + fragp->insn_addr; 5171214571Sdim else 5172214571Sdim fixp->fx_done = 1; 5173214571Sdim fixp = fixp->fx_next; 5174214571Sdim } 5175214571Sdim 5176214571Sdim if (fragp->insn_addr) 5177214571Sdim { 5178214571Sdim md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); 5179214571Sdim } 5180214571Sdim memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); 5181214571Sdim fragp->fr_fix += fragp->insn_addr; 5182214571Sdim} 5183214571Sdim 5184214571Sdim/* Implementation of md_frag_check. 5185214571Sdim Called after md_convert_frag(). */ 5186214571Sdim 5187214571Sdimvoid 5188214571Sdimscore_frag_check (fragS * fragp ATTRIBUTE_UNUSED) 5189214571Sdim{ 5190214571Sdim know (fragp->insn_addr <= RELAX_PAD_BYTE); 5191214571Sdim} 5192214571Sdim 5193214571Sdimbfd_boolean 5194214571Sdimscore_fix_adjustable (fixS * fixP) 5195214571Sdim{ 5196214571Sdim if (fixP->fx_addsy == NULL) 5197214571Sdim { 5198214571Sdim return 1; 5199214571Sdim } 5200214571Sdim else if (OUTPUT_FLAVOR == bfd_target_elf_flavour 5201214571Sdim && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) 5202214571Sdim { 5203214571Sdim return 0; 5204214571Sdim } 5205214571Sdim else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT 5206214571Sdim || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 5207214571Sdim { 5208214571Sdim return 0; 5209214571Sdim } 5210214571Sdim 5211214571Sdim return 1; 5212214571Sdim} 5213214571Sdim 5214214571Sdim/* Implementation of TC_VALIDATE_FIX. 5215214571Sdim Called before md_apply_fix() and after md_convert_frag(). */ 5216214571Sdimvoid 5217214571Sdimscore_validate_fix (fixS *fixP) 5218214571Sdim{ 5219214571Sdim fixP->fx_where += fixP->fx_frag->insn_addr; 5220214571Sdim} 5221214571Sdim 5222214571Sdimlong 5223214571Sdimmd_pcrel_from (fixS * fixP) 5224214571Sdim{ 5225214571Sdim long retval = 0; 5226214571Sdim 5227214571Sdim if (fixP->fx_addsy 5228214571Sdim && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) 5229214571Sdim && (fixP->fx_subsy == NULL)) 5230214571Sdim { 5231214571Sdim retval = 0; 5232214571Sdim } 5233214571Sdim else 5234214571Sdim { 5235214571Sdim retval = fixP->fx_where + fixP->fx_frag->fr_address; 5236214571Sdim } 5237214571Sdim 5238214571Sdim return retval; 5239214571Sdim} 5240214571Sdim 5241214571Sdimint 5242214571Sdimscore_force_relocation (struct fix *fixp) 5243214571Sdim{ 5244214571Sdim int retval = 0; 5245214571Sdim 5246214571Sdim if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 5247214571Sdim || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY 5248214571Sdim || fixp->fx_r_type == BFD_RELOC_SCORE_JMP 5249214571Sdim || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH 5250214571Sdim || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP 5251214571Sdim || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH) 5252214571Sdim { 5253214571Sdim retval = 1; 5254214571Sdim } 5255214571Sdim 5256214571Sdim return retval; 5257214571Sdim} 5258214571Sdim 5259214571Sdim/* Round up a section size to the appropriate boundary. */ 5260214571SdimvalueT 5261214571Sdimmd_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 5262214571Sdim{ 5263214571Sdim int align = bfd_get_section_alignment (stdoutput, segment); 5264214571Sdim 5265214571Sdim return ((size + (1 << align) - 1) & (-1 << align)); 5266214571Sdim} 5267214571Sdim 5268214571Sdimvoid 5269214571Sdimmd_apply_fix (fixS *fixP, valueT *valP, segT seg) 5270214571Sdim{ 5271214571Sdim offsetT value = *valP; 5272214571Sdim offsetT abs_value = 0; 5273214571Sdim offsetT newval; 5274214571Sdim offsetT content; 5275214571Sdim unsigned short HI, LO; 5276214571Sdim 5277214571Sdim char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; 5278214571Sdim 5279214571Sdim assert (fixP->fx_r_type < BFD_RELOC_UNUSED); 5280214571Sdim if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) 5281214571Sdim { 5282214571Sdim if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) 5283214571Sdim fixP->fx_done = 1; 5284214571Sdim } 5285214571Sdim 5286214571Sdim /* If this symbol is in a different section then we need to leave it for 5287214571Sdim the linker to deal with. Unfortunately, md_pcrel_from can't tell, 5288214571Sdim so we have to undo it's effects here. */ 5289214571Sdim if (fixP->fx_pcrel) 5290214571Sdim { 5291214571Sdim if (fixP->fx_addsy != NULL 5292214571Sdim && S_IS_DEFINED (fixP->fx_addsy) 5293214571Sdim && S_GET_SEGMENT (fixP->fx_addsy) != seg) 5294214571Sdim value += md_pcrel_from (fixP); 5295214571Sdim } 5296214571Sdim 5297214571Sdim /* Remember value for emit_reloc. */ 5298214571Sdim fixP->fx_addnumber = value; 5299214571Sdim 5300214571Sdim switch (fixP->fx_r_type) 5301214571Sdim { 5302214571Sdim case BFD_RELOC_HI16_S: 5303214571Sdim if (fixP->fx_done) 5304214571Sdim { /* For la rd, imm32. */ 5305214571Sdim newval = md_chars_to_number (buf, INSN_SIZE); 5306214571Sdim HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */ 5307214571Sdim newval |= (HI & 0x3fff) << 1; 5308214571Sdim newval |= ((HI >> 14) & 0x3) << 16; 5309214571Sdim md_number_to_chars (buf, newval, INSN_SIZE); 5310214571Sdim } 5311214571Sdim break; 5312214571Sdim case BFD_RELOC_LO16: 5313214571Sdim if (fixP->fx_done) /* For la rd, imm32. */ 5314214571Sdim { 5315214571Sdim newval = md_chars_to_number (buf, INSN_SIZE); 5316214571Sdim LO = (value) & 0xffff; 5317214571Sdim newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ 5318214571Sdim newval |= ((LO >> 14) & 0x3) << 16; 5319214571Sdim md_number_to_chars (buf, newval, INSN_SIZE); 5320214571Sdim } 5321214571Sdim break; 5322214571Sdim case BFD_RELOC_SCORE_JMP: 5323214571Sdim { 5324214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5325214571Sdim value = fixP->fx_offset; 5326214571Sdim content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); 5327214571Sdim md_number_to_chars (buf, content, INSN_SIZE); 5328214571Sdim } 5329214571Sdim break; 5330214571Sdim case BFD_RELOC_SCORE_BRANCH: 5331214571Sdim if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 5332214571Sdim value = fixP->fx_offset; 5333214571Sdim else 5334214571Sdim fixP->fx_done = 1; 5335214571Sdim 5336214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5337214571Sdim if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000)) 5338214571Sdim { 5339214571Sdim if ((value & 0x80000000) == 0x80000000) 5340214571Sdim abs_value = 0xffffffff - value + 1; 5341214571Sdim if ((abs_value & 0xffffff00) != 0) 5342214571Sdim { 5343214571Sdim as_bad_where (fixP->fx_file, fixP->fx_line, 5344214571Sdim _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value); 5345214571Sdim return; 5346214571Sdim } 5347214571Sdim content = md_chars_to_number (buf, INSN16_SIZE); 5348214571Sdim content &= 0xff00; 5349214571Sdim content = (content & 0xff00) | ((value >> 1) & 0xff); 5350214571Sdim md_number_to_chars (buf, content, INSN16_SIZE); 5351214571Sdim fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; 5352214571Sdim fixP->fx_size = 2; 5353214571Sdim } 5354214571Sdim else 5355214571Sdim { 5356214571Sdim if ((value & 0x80000000) == 0x80000000) 5357214571Sdim abs_value = 0xffffffff - value + 1; 5358214571Sdim if ((abs_value & 0xfff80000) != 0) 5359214571Sdim { 5360214571Sdim as_bad_where (fixP->fx_file, fixP->fx_line, 5361214571Sdim _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); 5362214571Sdim return; 5363214571Sdim } 5364214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5365214571Sdim content &= 0xfc00fc01; 5366214571Sdim content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 5367214571Sdim md_number_to_chars (buf, content, INSN_SIZE); 5368214571Sdim } 5369214571Sdim break; 5370214571Sdim case BFD_RELOC_SCORE16_JMP: 5371214571Sdim content = md_chars_to_number (buf, INSN16_SIZE); 5372214571Sdim content &= 0xf001; 5373214571Sdim value = fixP->fx_offset & 0xfff; 5374214571Sdim content = (content & 0xfc01) | (value & 0xffe); 5375214571Sdim md_number_to_chars (buf, content, INSN16_SIZE); 5376214571Sdim break; 5377214571Sdim case BFD_RELOC_SCORE16_BRANCH: 5378214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5379214571Sdim if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000)) 5380214571Sdim { 5381214571Sdim if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 5382214571Sdim (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 5383214571Sdim value = fixP->fx_offset; 5384214571Sdim else 5385214571Sdim fixP->fx_done = 1; 5386214571Sdim if ((value & 0x80000000) == 0x80000000) 5387214571Sdim abs_value = 0xffffffff - value + 1; 5388214571Sdim if ((abs_value & 0xfff80000) != 0) 5389214571Sdim { 5390214571Sdim as_bad_where (fixP->fx_file, fixP->fx_line, 5391214571Sdim _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); 5392214571Sdim return; 5393214571Sdim } 5394214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5395214571Sdim content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); 5396214571Sdim md_number_to_chars (buf, content, INSN_SIZE); 5397214571Sdim fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; 5398214571Sdim fixP->fx_size = 4; 5399214571Sdim break; 5400214571Sdim } 5401214571Sdim else 5402214571Sdim { 5403214571Sdim /* In differnt section. */ 5404214571Sdim if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || 5405214571Sdim (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) 5406214571Sdim value = fixP->fx_offset; 5407214571Sdim else 5408214571Sdim fixP->fx_done = 1; 5409214571Sdim 5410214571Sdim if ((value & 0x80000000) == 0x80000000) 5411214571Sdim abs_value = 0xffffffff - value + 1; 5412214571Sdim if ((abs_value & 0xffffff00) != 0) 5413214571Sdim { 5414214571Sdim as_bad_where (fixP->fx_file, fixP->fx_line, 5415214571Sdim _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value); 5416214571Sdim return; 5417214571Sdim } 5418214571Sdim content = md_chars_to_number (buf, INSN16_SIZE); 5419214571Sdim content = (content & 0xff00) | ((value >> 1) & 0xff); 5420214571Sdim md_number_to_chars (buf, content, INSN16_SIZE); 5421214571Sdim break; 5422214571Sdim } 5423214571Sdim case BFD_RELOC_8: 5424214571Sdim if (fixP->fx_done || fixP->fx_pcrel) 5425214571Sdim md_number_to_chars (buf, value, 1); 5426214571Sdim#ifdef OBJ_ELF 5427214571Sdim else 5428214571Sdim { 5429214571Sdim value = fixP->fx_offset; 5430214571Sdim md_number_to_chars (buf, value, 1); 5431214571Sdim } 5432214571Sdim#endif 5433214571Sdim break; 5434214571Sdim 5435214571Sdim case BFD_RELOC_16: 5436214571Sdim if (fixP->fx_done || fixP->fx_pcrel) 5437214571Sdim md_number_to_chars (buf, value, 2); 5438214571Sdim#ifdef OBJ_ELF 5439214571Sdim else 5440214571Sdim { 5441214571Sdim value = fixP->fx_offset; 5442214571Sdim md_number_to_chars (buf, value, 2); 5443214571Sdim } 5444214571Sdim#endif 5445214571Sdim break; 5446214571Sdim case BFD_RELOC_RVA: 5447214571Sdim case BFD_RELOC_32: 5448214571Sdim if (fixP->fx_done || fixP->fx_pcrel) 5449214571Sdim md_number_to_chars (buf, value, 4); 5450214571Sdim#ifdef OBJ_ELF 5451214571Sdim else 5452214571Sdim { 5453214571Sdim value = fixP->fx_offset; 5454214571Sdim md_number_to_chars (buf, value, 4); 5455214571Sdim } 5456214571Sdim#endif 5457214571Sdim break; 5458214571Sdim case BFD_RELOC_VTABLE_INHERIT: 5459214571Sdim fixP->fx_done = 0; 5460214571Sdim if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) 5461214571Sdim S_SET_WEAK (fixP->fx_addsy); 5462214571Sdim break; 5463214571Sdim case BFD_RELOC_VTABLE_ENTRY: 5464214571Sdim fixP->fx_done = 0; 5465214571Sdim break; 5466214571Sdim case BFD_RELOC_SCORE_GPREL15: 5467214571Sdim content = md_chars_to_number (buf, INSN_SIZE); 5468214571Sdim if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000)) 5469214571Sdim fixP->fx_r_type = BFD_RELOC_NONE; 5470214571Sdim fixP->fx_done = 0; 5471214571Sdim break; 5472214571Sdim case BFD_RELOC_SCORE_GOT15: 5473214571Sdim case BFD_RELOC_SCORE_DUMMY_HI16: 5474214571Sdim case BFD_RELOC_SCORE_GOT_LO16: 5475214571Sdim case BFD_RELOC_SCORE_CALL15: 5476214571Sdim case BFD_RELOC_GPREL32: 5477214571Sdim break; 5478214571Sdim case BFD_RELOC_NONE: 5479214571Sdim default: 5480214571Sdim as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); 5481214571Sdim } 5482214571Sdim} 5483214571Sdim 5484214571Sdim/* Translate internal representation of relocation info to BFD target format. */ 5485214571Sdimarelent ** 5486214571Sdimtc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) 5487214571Sdim{ 5488214571Sdim static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ 5489214571Sdim arelent *reloc; 5490214571Sdim bfd_reloc_code_real_type code; 5491214571Sdim char *type; 5492214571Sdim fragS *f; 5493214571Sdim symbolS *s; 5494214571Sdim expressionS e; 5495214571Sdim 5496214571Sdim reloc = retval[0] = xmalloc (sizeof (arelent)); 5497214571Sdim retval[1] = NULL; 5498214571Sdim 5499214571Sdim reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); 5500214571Sdim *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 5501214571Sdim reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; 5502214571Sdim reloc->addend = fixp->fx_offset; 5503214571Sdim 5504214571Sdim /* If this is a variant frag, we may need to adjust the existing 5505214571Sdim reloc and generate a new one. */ 5506214571Sdim if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) 5507214571Sdim { 5508214571Sdim /* Update instruction imm bit. */ 5509214571Sdim offsetT newval; 5510214571Sdim unsigned short off; 5511214571Sdim char *buf; 5512214571Sdim 5513214571Sdim buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; 5514214571Sdim newval = md_chars_to_number (buf, INSN_SIZE); 5515214571Sdim off = fixp->fx_offset >> 16; 5516214571Sdim newval |= (off & 0x3fff) << 1; 5517214571Sdim newval |= ((off >> 14) & 0x3) << 16; 5518214571Sdim md_number_to_chars (buf, newval, INSN_SIZE); 5519214571Sdim 5520214571Sdim buf += INSN_SIZE; 5521214571Sdim newval = md_chars_to_number (buf, INSN_SIZE); 5522214571Sdim off = fixp->fx_offset & 0xffff; 5523214571Sdim newval |= ((off & 0x3fff) << 1); 5524214571Sdim newval |= (((off >> 14) & 0x3) << 16); 5525214571Sdim md_number_to_chars (buf, newval, INSN_SIZE); 5526214571Sdim 5527214571Sdim retval[1] = xmalloc (sizeof (arelent)); 5528214571Sdim retval[2] = NULL; 5529214571Sdim retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); 5530214571Sdim *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 5531214571Sdim retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); 5532214571Sdim 5533214571Sdim f = fixp->fx_frag; 5534214571Sdim s = f->fr_symbol; 5535214571Sdim e = s->sy_value; 5536214571Sdim 5537214571Sdim retval[1]->addend = 0; 5538214571Sdim retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); 5539214571Sdim assert (retval[1]->howto != NULL); 5540214571Sdim 5541214571Sdim fixp->fx_r_type = BFD_RELOC_HI16_S; 5542214571Sdim } 5543214571Sdim 5544214571Sdim code = fixp->fx_r_type; 5545214571Sdim switch (fixp->fx_r_type) 5546214571Sdim { 5547214571Sdim case BFD_RELOC_32: 5548214571Sdim if (fixp->fx_pcrel) 5549214571Sdim { 5550214571Sdim code = BFD_RELOC_32_PCREL; 5551214571Sdim break; 5552214571Sdim } 5553214571Sdim case BFD_RELOC_HI16_S: 5554214571Sdim case BFD_RELOC_LO16: 5555214571Sdim case BFD_RELOC_SCORE_JMP: 5556214571Sdim case BFD_RELOC_SCORE_BRANCH: 5557214571Sdim case BFD_RELOC_SCORE16_JMP: 5558214571Sdim case BFD_RELOC_SCORE16_BRANCH: 5559214571Sdim case BFD_RELOC_VTABLE_ENTRY: 5560214571Sdim case BFD_RELOC_VTABLE_INHERIT: 5561214571Sdim case BFD_RELOC_SCORE_GPREL15: 5562214571Sdim case BFD_RELOC_SCORE_GOT15: 5563214571Sdim case BFD_RELOC_SCORE_DUMMY_HI16: 5564214571Sdim case BFD_RELOC_SCORE_GOT_LO16: 5565214571Sdim case BFD_RELOC_SCORE_CALL15: 5566214571Sdim case BFD_RELOC_GPREL32: 5567214571Sdim case BFD_RELOC_NONE: 5568214571Sdim code = fixp->fx_r_type; 5569214571Sdim break; 5570214571Sdim default: 5571214571Sdim type = _("<unknown>"); 5572214571Sdim as_bad_where (fixp->fx_file, fixp->fx_line, 5573214571Sdim _("cannot represent %s relocation in this object file format"), type); 5574214571Sdim return NULL; 5575214571Sdim } 5576214571Sdim 5577214571Sdim reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 5578214571Sdim if (reloc->howto == NULL) 5579214571Sdim { 5580214571Sdim as_bad_where (fixp->fx_file, fixp->fx_line, 5581214571Sdim _("cannot represent %s relocation in this object file format1"), 5582214571Sdim bfd_get_reloc_code_name (code)); 5583214571Sdim return NULL; 5584214571Sdim } 5585214571Sdim /* HACK: Since arm ELF uses Rel instead of Rela, encode the 5586214571Sdim vtable entry to be used in the relocation's section offset. */ 5587214571Sdim if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 5588214571Sdim reloc->address = fixp->fx_offset; 5589214571Sdim 5590214571Sdim return retval; 5591214571Sdim} 5592214571Sdim 5593214571Sdimvoid 5594214571Sdimscore_elf_final_processing (void) 5595214571Sdim{ 5596214571Sdim if (fix_data_dependency == 1) 5597214571Sdim { 5598214571Sdim elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; 5599214571Sdim } 5600214571Sdim if (score_pic == PIC) 5601214571Sdim { 5602214571Sdim elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; 5603214571Sdim } 5604214571Sdim} 5605214571Sdim 5606214571Sdimstatic void 5607214571Sdimparse_pce_inst (char *insnstr) 5608214571Sdim{ 5609214571Sdim char c; 5610214571Sdim char *p; 5611214571Sdim char first[MAX_LITERAL_POOL_SIZE]; 5612214571Sdim char second[MAX_LITERAL_POOL_SIZE]; 5613214571Sdim struct score_it pec_part_1; 5614214571Sdim 5615214571Sdim /* Get first part string of PCE. */ 5616214571Sdim p = strstr (insnstr, "||"); 5617214571Sdim c = *p; 5618214571Sdim *p = '\0'; 5619214571Sdim sprintf (first, "%s", insnstr); 5620214571Sdim 5621214571Sdim /* Get second part string of PCE. */ 5622214571Sdim *p = c; 5623214571Sdim p += 2; 5624214571Sdim sprintf (second, "%s", p); 5625214571Sdim 5626214571Sdim parse_16_32_inst (first, FALSE); 5627214571Sdim if (inst.error) 5628214571Sdim return; 5629214571Sdim 5630214571Sdim memcpy (&pec_part_1, &inst, sizeof (inst)); 5631214571Sdim 5632214571Sdim parse_16_32_inst (second, FALSE); 5633214571Sdim if (inst.error) 5634214571Sdim return; 5635214571Sdim 5636214571Sdim if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE)) 5637214571Sdim || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE)) 5638214571Sdim || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE))) 5639214571Sdim { 5640214571Sdim inst.error = _("pce instruction error (16 bit || 16 bit)'"); 5641214571Sdim sprintf (inst.str, insnstr); 5642214571Sdim return; 5643214571Sdim } 5644214571Sdim 5645214571Sdim if (!inst.error) 5646214571Sdim gen_insn_frag (&pec_part_1, &inst); 5647214571Sdim} 5648214571Sdim 5649214571Sdimvoid 5650214571Sdimmd_assemble (char *str) 5651214571Sdim{ 5652214571Sdim know (str); 5653214571Sdim know (strlen (str) < MAX_LITERAL_POOL_SIZE); 5654214571Sdim 5655214571Sdim memset (&inst, '\0', sizeof (inst)); 5656214571Sdim if (INSN_IS_PCE_P (str)) 5657214571Sdim parse_pce_inst (str); 5658214571Sdim else 5659214571Sdim parse_16_32_inst (str, TRUE); 5660214571Sdim 5661214571Sdim if (inst.error) 5662214571Sdim as_bad (_("%s -- `%s'"), inst.error, inst.str); 5663214571Sdim} 5664214571Sdim 5665214571Sdim/* We handle all bad expressions here, so that we can report the faulty 5666214571Sdim instruction in the error message. */ 5667214571Sdimvoid 5668214571Sdimmd_operand (expressionS * expr) 5669214571Sdim{ 5670214571Sdim if (in_my_get_expression) 5671214571Sdim { 5672214571Sdim expr->X_op = O_illegal; 5673214571Sdim if (inst.error == NULL) 5674214571Sdim { 5675214571Sdim inst.error = _("bad expression"); 5676214571Sdim } 5677214571Sdim } 5678214571Sdim} 5679214571Sdim 5680214571Sdimconst char *md_shortopts = "nO::g::G:"; 5681214571Sdim 5682214571Sdim#ifdef SCORE_BI_ENDIAN 5683214571Sdim#define OPTION_EB (OPTION_MD_BASE + 0) 5684214571Sdim#define OPTION_EL (OPTION_MD_BASE + 1) 5685214571Sdim#else 5686214571Sdim#if TARGET_BYTES_BIG_ENDIAN 5687214571Sdim#define OPTION_EB (OPTION_MD_BASE + 0) 5688214571Sdim#else 5689214571Sdim#define OPTION_EL (OPTION_MD_BASE + 1) 5690214571Sdim#endif 5691214571Sdim#endif 5692214571Sdim#define OPTION_FIXDD (OPTION_MD_BASE + 2) 5693214571Sdim#define OPTION_NWARN (OPTION_MD_BASE + 3) 5694214571Sdim#define OPTION_SCORE5 (OPTION_MD_BASE + 4) 5695214571Sdim#define OPTION_SCORE5U (OPTION_MD_BASE + 5) 5696214571Sdim#define OPTION_SCORE7 (OPTION_MD_BASE + 6) 5697214571Sdim#define OPTION_R1 (OPTION_MD_BASE + 7) 5698214571Sdim#define OPTION_O0 (OPTION_MD_BASE + 8) 5699214571Sdim#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9) 5700214571Sdim#define OPTION_PIC (OPTION_MD_BASE + 10) 5701214571Sdim 5702214571Sdimstruct option md_longopts[] = 5703214571Sdim{ 5704214571Sdim#ifdef OPTION_EB 5705214571Sdim {"EB" , no_argument, NULL, OPTION_EB}, 5706214571Sdim#endif 5707214571Sdim#ifdef OPTION_EL 5708214571Sdim {"EL" , no_argument, NULL, OPTION_EL}, 5709214571Sdim#endif 5710214571Sdim {"FIXDD" , no_argument, NULL, OPTION_FIXDD}, 5711214571Sdim {"NWARN" , no_argument, NULL, OPTION_NWARN}, 5712214571Sdim {"SCORE5" , no_argument, NULL, OPTION_SCORE5}, 5713214571Sdim {"SCORE5U", no_argument, NULL, OPTION_SCORE5U}, 5714214571Sdim {"SCORE7" , no_argument, NULL, OPTION_SCORE7}, 5715214571Sdim {"USE_R1" , no_argument, NULL, OPTION_R1}, 5716214571Sdim {"O0" , no_argument, NULL, OPTION_O0}, 5717214571Sdim {"V" , no_argument, NULL, OPTION_SCORE_VERSION}, 5718214571Sdim {"KPIC" , no_argument, NULL, OPTION_PIC}, 5719214571Sdim {NULL , no_argument, NULL, 0} 5720214571Sdim}; 5721214571Sdim 5722214571Sdimsize_t md_longopts_size = sizeof (md_longopts); 5723214571Sdim 5724214571Sdimint 5725214571Sdimmd_parse_option (int c, char *arg) 5726214571Sdim{ 5727214571Sdim switch (c) 5728214571Sdim { 5729214571Sdim#ifdef OPTION_EB 5730214571Sdim case OPTION_EB: 5731214571Sdim target_big_endian = 1; 5732214571Sdim break; 5733214571Sdim#endif 5734214571Sdim#ifdef OPTION_EL 5735214571Sdim case OPTION_EL: 5736214571Sdim target_big_endian = 0; 5737214571Sdim break; 5738214571Sdim#endif 5739214571Sdim case OPTION_FIXDD: 5740214571Sdim fix_data_dependency = 1; 5741214571Sdim break; 5742214571Sdim case OPTION_NWARN: 5743214571Sdim warn_fix_data_dependency = 0; 5744214571Sdim break; 5745214571Sdim case OPTION_SCORE5: 5746214571Sdim score7 = 0; 5747214571Sdim university_version = 0; 5748214571Sdim vector_size = SCORE5_PIPELINE; 5749214571Sdim break; 5750214571Sdim case OPTION_SCORE5U: 5751214571Sdim score7 = 0; 5752214571Sdim university_version = 1; 5753214571Sdim vector_size = SCORE5_PIPELINE; 5754214571Sdim break; 5755214571Sdim case OPTION_SCORE7: 5756214571Sdim score7 = 1; 5757214571Sdim university_version = 0; 5758214571Sdim vector_size = SCORE7_PIPELINE; 5759214571Sdim break; 5760214571Sdim case OPTION_R1: 5761214571Sdim nor1 = 0; 5762214571Sdim break; 5763214571Sdim case 'G': 5764214571Sdim g_switch_value = atoi (arg); 5765214571Sdim break; 5766214571Sdim case OPTION_O0: 5767214571Sdim g_opt = 0; 5768214571Sdim break; 5769214571Sdim case OPTION_SCORE_VERSION: 5770214571Sdim printf (_("Sunplus-v2-0-0-20060510\n")); 5771214571Sdim break; 5772214571Sdim case OPTION_PIC: 5773214571Sdim score_pic = PIC; 5774214571Sdim g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */ 5775214571Sdim break; 5776214571Sdim default: 5777214571Sdim /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */ 5778214571Sdim return 0; 5779214571Sdim } 5780214571Sdim return 1; 5781214571Sdim} 5782214571Sdim 5783214571Sdimvoid 5784214571Sdimmd_show_usage (FILE * fp) 5785214571Sdim{ 5786214571Sdim fprintf (fp, _(" Score-specific assembler options:\n")); 5787214571Sdim#ifdef OPTION_EB 5788214571Sdim fprintf (fp, _("\ 5789214571Sdim -EB\t\tassemble code for a big-endian cpu\n")); 5790214571Sdim#endif 5791214571Sdim 5792214571Sdim#ifdef OPTION_EL 5793214571Sdim fprintf (fp, _("\ 5794214571Sdim -EL\t\tassemble code for a little-endian cpu\n")); 5795214571Sdim#endif 5796214571Sdim 5797214571Sdim fprintf (fp, _("\ 5798214571Sdim -FIXDD\t\tassemble code for fix data dependency\n")); 5799214571Sdim fprintf (fp, _("\ 5800214571Sdim -NWARN\t\tassemble code for no warning message for fix data dependency\n")); 5801214571Sdim fprintf (fp, _("\ 5802214571Sdim -SCORE5\t\tassemble code for target is SCORE5\n")); 5803214571Sdim fprintf (fp, _("\ 5804214571Sdim -SCORE5U\tassemble code for target is SCORE5U\n")); 5805214571Sdim fprintf (fp, _("\ 5806214571Sdim -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n")); 5807214571Sdim fprintf (fp, _("\ 5808214571Sdim -USE_R1\t\tassemble code for no warning message when using temp register r1\n")); 5809214571Sdim fprintf (fp, _("\ 5810214571Sdim -KPIC\t\tassemble code for PIC\n")); 5811214571Sdim fprintf (fp, _("\ 5812214571Sdim -O0\t\tassembler will not perform any optimizations\n")); 5813214571Sdim fprintf (fp, _("\ 5814214571Sdim -G gpnum\tassemble code for setting gpsize and default is 8 byte\n")); 5815214571Sdim fprintf (fp, _("\ 5816214571Sdim -V \t\tSunplus release version \n")); 5817214571Sdim} 5818214571Sdim 5819214571Sdim 5820214571Sdim/* Pesudo handling functions. */ 5821214571Sdim 5822214571Sdim/* If we change section we must dump the literal pool first. */ 5823214571Sdimstatic void 5824214571Sdims_score_bss (int ignore ATTRIBUTE_UNUSED) 5825214571Sdim{ 5826214571Sdim subseg_set (bss_section, (subsegT) get_absolute_expression ()); 5827214571Sdim demand_empty_rest_of_line (); 5828214571Sdim} 5829214571Sdim 5830214571Sdimstatic void 5831214571Sdims_score_text (int ignore) 5832214571Sdim{ 5833214571Sdim obj_elf_text (ignore); 5834214571Sdim record_alignment (now_seg, 2); 5835214571Sdim} 5836214571Sdim 5837214571Sdimstatic void 5838214571Sdimscore_s_section (int ignore) 5839214571Sdim{ 5840214571Sdim obj_elf_section (ignore); 5841214571Sdim if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) 5842214571Sdim record_alignment (now_seg, 2); 5843214571Sdim 5844214571Sdim} 5845214571Sdim 5846214571Sdimstatic void 5847214571Sdims_change_sec (int sec) 5848214571Sdim{ 5849214571Sdim segT seg; 5850214571Sdim 5851214571Sdim#ifdef OBJ_ELF 5852214571Sdim /* The ELF backend needs to know that we are changing sections, so 5853214571Sdim that .previous works correctly. We could do something like check 5854214571Sdim for an obj_section_change_hook macro, but that might be confusing 5855214571Sdim as it would not be appropriate to use it in the section changing 5856214571Sdim functions in read.c, since obj-elf.c intercepts those. FIXME: 5857214571Sdim This should be cleaner, somehow. */ 5858214571Sdim obj_elf_section_change_hook (); 5859214571Sdim#endif 5860214571Sdim switch (sec) 5861214571Sdim { 5862214571Sdim case 'r': 5863214571Sdim seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); 5864214571Sdim bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA)); 5865214571Sdim if (strcmp (TARGET_OS, "elf") != 0) 5866214571Sdim record_alignment (seg, 4); 5867214571Sdim demand_empty_rest_of_line (); 5868214571Sdim break; 5869214571Sdim case 's': 5870214571Sdim seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); 5871214571Sdim bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); 5872214571Sdim if (strcmp (TARGET_OS, "elf") != 0) 5873214571Sdim record_alignment (seg, 4); 5874214571Sdim demand_empty_rest_of_line (); 5875214571Sdim break; 5876214571Sdim } 5877214571Sdim} 5878214571Sdim 5879214571Sdimstatic void 5880214571Sdims_score_mask (int reg_type ATTRIBUTE_UNUSED) 5881214571Sdim{ 5882214571Sdim long mask, off; 5883214571Sdim 5884214571Sdim if (cur_proc_ptr == (procS *) NULL) 5885214571Sdim { 5886214571Sdim as_warn (_(".mask outside of .ent")); 5887214571Sdim demand_empty_rest_of_line (); 5888214571Sdim return; 5889214571Sdim } 5890214571Sdim if (get_absolute_expression_and_terminator (&mask) != ',') 5891214571Sdim { 5892214571Sdim as_warn (_("Bad .mask directive")); 5893214571Sdim --input_line_pointer; 5894214571Sdim demand_empty_rest_of_line (); 5895214571Sdim return; 5896214571Sdim } 5897214571Sdim off = get_absolute_expression (); 5898214571Sdim cur_proc_ptr->reg_mask = mask; 5899214571Sdim cur_proc_ptr->reg_offset = off; 5900214571Sdim demand_empty_rest_of_line (); 5901214571Sdim} 5902214571Sdim 5903214571Sdimstatic symbolS * 5904214571Sdimget_symbol (void) 5905214571Sdim{ 5906214571Sdim int c; 5907214571Sdim char *name; 5908214571Sdim symbolS *p; 5909214571Sdim 5910214571Sdim name = input_line_pointer; 5911214571Sdim c = get_symbol_end (); 5912214571Sdim p = (symbolS *) symbol_find_or_make (name); 5913214571Sdim *input_line_pointer = c; 5914214571Sdim return p; 5915214571Sdim} 5916214571Sdim 5917214571Sdimstatic long 5918214571Sdimget_number (void) 5919214571Sdim{ 5920214571Sdim int negative = 0; 5921214571Sdim long val = 0; 5922214571Sdim 5923214571Sdim if (*input_line_pointer == '-') 5924214571Sdim { 5925214571Sdim ++input_line_pointer; 5926214571Sdim negative = 1; 5927214571Sdim } 5928214571Sdim if (!ISDIGIT (*input_line_pointer)) 5929214571Sdim as_bad (_("expected simple number")); 5930214571Sdim if (input_line_pointer[0] == '0') 5931214571Sdim { 5932214571Sdim if (input_line_pointer[1] == 'x') 5933214571Sdim { 5934214571Sdim input_line_pointer += 2; 5935214571Sdim while (ISXDIGIT (*input_line_pointer)) 5936214571Sdim { 5937214571Sdim val <<= 4; 5938214571Sdim val |= hex_value (*input_line_pointer++); 5939214571Sdim } 5940214571Sdim return negative ? -val : val; 5941214571Sdim } 5942214571Sdim else 5943214571Sdim { 5944214571Sdim ++input_line_pointer; 5945214571Sdim while (ISDIGIT (*input_line_pointer)) 5946214571Sdim { 5947214571Sdim val <<= 3; 5948214571Sdim val |= *input_line_pointer++ - '0'; 5949214571Sdim } 5950214571Sdim return negative ? -val : val; 5951214571Sdim } 5952214571Sdim } 5953214571Sdim if (!ISDIGIT (*input_line_pointer)) 5954214571Sdim { 5955214571Sdim printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); 5956214571Sdim as_warn (_("invalid number")); 5957214571Sdim return -1; 5958214571Sdim } 5959214571Sdim while (ISDIGIT (*input_line_pointer)) 5960214571Sdim { 5961214571Sdim val *= 10; 5962214571Sdim val += *input_line_pointer++ - '0'; 5963214571Sdim } 5964214571Sdim return negative ? -val : val; 5965214571Sdim} 5966214571Sdim 5967214571Sdim/* The .aent and .ent directives. */ 5968214571Sdim 5969214571Sdimstatic void 5970214571Sdims_score_ent (int aent) 5971214571Sdim{ 5972214571Sdim symbolS *symbolP; 5973214571Sdim int maybe_text; 5974214571Sdim 5975214571Sdim symbolP = get_symbol (); 5976214571Sdim if (*input_line_pointer == ',') 5977214571Sdim ++input_line_pointer; 5978214571Sdim SKIP_WHITESPACE (); 5979214571Sdim if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') 5980214571Sdim get_number (); 5981214571Sdim 5982214571Sdim#ifdef BFD_ASSEMBLER 5983214571Sdim if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) 5984214571Sdim maybe_text = 1; 5985214571Sdim else 5986214571Sdim maybe_text = 0; 5987214571Sdim#else 5988214571Sdim if (now_seg != data_section && now_seg != bss_section) 5989214571Sdim maybe_text = 1; 5990214571Sdim else 5991214571Sdim maybe_text = 0; 5992214571Sdim#endif 5993214571Sdim if (!maybe_text) 5994214571Sdim as_warn (_(".ent or .aent not in text section.")); 5995214571Sdim if (!aent && cur_proc_ptr) 5996214571Sdim as_warn (_("missing .end")); 5997214571Sdim if (!aent) 5998214571Sdim { 5999214571Sdim cur_proc_ptr = &cur_proc; 6000214571Sdim cur_proc_ptr->reg_mask = 0xdeadbeaf; 6001214571Sdim cur_proc_ptr->reg_offset = 0xdeadbeaf; 6002214571Sdim cur_proc_ptr->fpreg_mask = 0xdeafbeaf; 6003214571Sdim cur_proc_ptr->leaf = 0xdeafbeaf; 6004214571Sdim cur_proc_ptr->frame_offset = 0xdeafbeaf; 6005214571Sdim cur_proc_ptr->frame_reg = 0xdeafbeaf; 6006214571Sdim cur_proc_ptr->pc_reg = 0xdeafbeaf; 6007214571Sdim cur_proc_ptr->isym = symbolP; 6008214571Sdim symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; 6009214571Sdim ++numprocs; 6010214571Sdim if (debug_type == DEBUG_STABS) 6011214571Sdim stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); 6012214571Sdim } 6013214571Sdim demand_empty_rest_of_line (); 6014214571Sdim} 6015214571Sdim 6016214571Sdimstatic void 6017214571Sdims_score_frame (int ignore ATTRIBUTE_UNUSED) 6018214571Sdim{ 6019214571Sdim char *backupstr; 6020214571Sdim char str[30]; 6021214571Sdim long val; 6022214571Sdim int i = 0; 6023214571Sdim 6024214571Sdim backupstr = input_line_pointer; 6025214571Sdim 6026214571Sdim#ifdef OBJ_ELF 6027214571Sdim if (cur_proc_ptr == (procS *) NULL) 6028214571Sdim { 6029214571Sdim as_warn (_(".frame outside of .ent")); 6030214571Sdim demand_empty_rest_of_line (); 6031214571Sdim return; 6032214571Sdim } 6033214571Sdim cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE); 6034214571Sdim SKIP_WHITESPACE (); 6035214571Sdim skip_past_comma (&backupstr); 6036214571Sdim while (*backupstr != ',') 6037214571Sdim { 6038214571Sdim str[i] = *backupstr; 6039214571Sdim i++; 6040214571Sdim backupstr++; 6041214571Sdim } 6042214571Sdim str[i] = '\0'; 6043214571Sdim val = atoi (str); 6044214571Sdim 6045214571Sdim SKIP_WHITESPACE (); 6046214571Sdim skip_past_comma (&backupstr); 6047214571Sdim cur_proc_ptr->frame_offset = val; 6048214571Sdim cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE); 6049214571Sdim 6050214571Sdim SKIP_WHITESPACE (); 6051214571Sdim skip_past_comma (&backupstr); 6052214571Sdim i = 0; 6053214571Sdim while (*backupstr != '\n') 6054214571Sdim { 6055214571Sdim str[i] = *backupstr; 6056214571Sdim i++; 6057214571Sdim backupstr++; 6058214571Sdim } 6059214571Sdim str[i] = '\0'; 6060214571Sdim val = atoi (str); 6061214571Sdim cur_proc_ptr->leaf = val; 6062214571Sdim SKIP_WHITESPACE (); 6063214571Sdim skip_past_comma (&backupstr); 6064214571Sdim 6065214571Sdim#endif /* OBJ_ELF */ 6066214571Sdim while (input_line_pointer != backupstr) 6067214571Sdim input_line_pointer++; 6068214571Sdim} 6069214571Sdim 6070214571Sdim/* The .end directive. */ 6071214571Sdimstatic void 6072214571Sdims_score_end (int x ATTRIBUTE_UNUSED) 6073214571Sdim{ 6074214571Sdim symbolS *p; 6075214571Sdim int maybe_text; 6076214571Sdim 6077214571Sdim /* Generate a .pdr section. */ 6078214571Sdim segT saved_seg = now_seg; 6079214571Sdim subsegT saved_subseg = now_subseg; 6080214571Sdim valueT dot; 6081214571Sdim expressionS exp; 6082214571Sdim char *fragp; 6083214571Sdim 6084214571Sdim if (!is_end_of_line[(unsigned char)*input_line_pointer]) 6085214571Sdim { 6086214571Sdim p = get_symbol (); 6087214571Sdim demand_empty_rest_of_line (); 6088214571Sdim } 6089214571Sdim else 6090214571Sdim p = NULL; 6091214571Sdim 6092214571Sdim#ifdef BFD_ASSEMBLER 6093214571Sdim if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) 6094214571Sdim maybe_text = 1; 6095214571Sdim else 6096214571Sdim maybe_text = 0; 6097214571Sdim#else 6098214571Sdim if (now_seg != data_section && now_seg != bss_section) 6099214571Sdim maybe_text = 1; 6100214571Sdim else 6101214571Sdim maybe_text = 0; 6102214571Sdim#endif 6103214571Sdim 6104214571Sdim if (!maybe_text) 6105214571Sdim as_warn (_(".end not in text section")); 6106214571Sdim if (!cur_proc_ptr) 6107214571Sdim { 6108214571Sdim as_warn (_(".end directive without a preceding .ent directive.")); 6109214571Sdim demand_empty_rest_of_line (); 6110214571Sdim return; 6111214571Sdim } 6112214571Sdim if (p != NULL) 6113214571Sdim { 6114214571Sdim assert (S_GET_NAME (p)); 6115214571Sdim if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym))) 6116214571Sdim as_warn (_(".end symbol does not match .ent symbol.")); 6117214571Sdim if (debug_type == DEBUG_STABS) 6118214571Sdim stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); 6119214571Sdim } 6120214571Sdim else 6121214571Sdim as_warn (_(".end directive missing or unknown symbol")); 6122214571Sdim 6123214571Sdim if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) || 6124214571Sdim (cur_proc_ptr->reg_offset == 0xdeadbeaf) || 6125214571Sdim (cur_proc_ptr->leaf == 0xdeafbeaf) || 6126214571Sdim (cur_proc_ptr->frame_offset == 0xdeafbeaf) || 6127214571Sdim (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf)); 6128214571Sdim 6129214571Sdim else 6130214571Sdim { 6131214571Sdim dot = frag_now_fix (); 6132214571Sdim assert (pdr_seg); 6133214571Sdim subseg_set (pdr_seg, 0); 6134214571Sdim /* Write the symbol. */ 6135214571Sdim exp.X_op = O_symbol; 6136214571Sdim exp.X_add_symbol = p; 6137214571Sdim exp.X_add_number = 0; 6138214571Sdim emit_expr (&exp, 4); 6139214571Sdim fragp = frag_more (7 * 4); 6140214571Sdim md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4); 6141214571Sdim md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4); 6142214571Sdim md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4); 6143214571Sdim md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4); 6144214571Sdim md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4); 6145214571Sdim md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4); 6146214571Sdim md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4); 6147214571Sdim subseg_set (saved_seg, saved_subseg); 6148214571Sdim 6149214571Sdim } 6150214571Sdim cur_proc_ptr = NULL; 6151214571Sdim} 6152214571Sdim 6153214571Sdim/* Handle the .set pseudo-op. */ 6154214571Sdimstatic void 6155214571Sdims_score_set (int x ATTRIBUTE_UNUSED) 6156214571Sdim{ 6157214571Sdim int i = 0; 6158214571Sdim char name[MAX_LITERAL_POOL_SIZE]; 6159214571Sdim char * orig_ilp = input_line_pointer; 6160214571Sdim 6161214571Sdim while (!is_end_of_line[(unsigned char)*input_line_pointer]) 6162214571Sdim { 6163214571Sdim name[i] = (char) * input_line_pointer; 6164214571Sdim i++; 6165214571Sdim ++input_line_pointer; 6166214571Sdim } 6167214571Sdim 6168214571Sdim name[i] = '\0'; 6169214571Sdim 6170214571Sdim if (strcmp (name, "nwarn") == 0) 6171214571Sdim { 6172214571Sdim warn_fix_data_dependency = 0; 6173214571Sdim } 6174214571Sdim else if (strcmp (name, "fixdd") == 0) 6175214571Sdim { 6176214571Sdim fix_data_dependency = 1; 6177214571Sdim } 6178214571Sdim else if (strcmp (name, "nofixdd") == 0) 6179214571Sdim { 6180214571Sdim fix_data_dependency = 0; 6181214571Sdim } 6182214571Sdim else if (strcmp (name, "r1") == 0) 6183214571Sdim { 6184214571Sdim nor1 = 0; 6185214571Sdim } 6186214571Sdim else if (strcmp (name, "nor1") == 0) 6187214571Sdim { 6188214571Sdim nor1 = 1; 6189214571Sdim } 6190214571Sdim else if (strcmp (name, "optimize") == 0) 6191214571Sdim { 6192214571Sdim g_opt = 1; 6193214571Sdim } 6194214571Sdim else if (strcmp (name, "volatile") == 0) 6195214571Sdim { 6196214571Sdim g_opt = 0; 6197214571Sdim } 6198214571Sdim else if (strcmp (name, "pic") == 0) 6199214571Sdim { 6200214571Sdim score_pic = PIC; 6201214571Sdim } 6202214571Sdim else 6203214571Sdim { 6204214571Sdim input_line_pointer = orig_ilp; 6205214571Sdim s_set (0); 6206214571Sdim } 6207214571Sdim} 6208214571Sdim 6209214571Sdim/* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the 6210214571Sdim $gp register for the function based on the function address, which is in the register 6211214571Sdim named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled 6212214571Sdim specially by the linker. The result is: 6213214571Sdim ldis gp, %hi(GP_DISP_LABEL) 6214214571Sdim ori gp, %low(GP_DISP_LABEL) 6215214571Sdim add gp, gp, .cpload argument 6216214571Sdim The .cpload argument is normally r29. */ 6217214571Sdim 6218214571Sdimstatic void 6219214571Sdims_score_cpload (int ignore ATTRIBUTE_UNUSED) 6220214571Sdim{ 6221214571Sdim int reg; 6222214571Sdim char insn_str[MAX_LITERAL_POOL_SIZE]; 6223214571Sdim 6224214571Sdim /* If we are not generating PIC code, .cpload is ignored. */ 6225214571Sdim if (score_pic == NO_PIC) 6226214571Sdim { 6227214571Sdim s_ignore (0); 6228214571Sdim return; 6229214571Sdim } 6230214571Sdim 6231214571Sdim if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL) 6232214571Sdim return; 6233214571Sdim 6234214571Sdim demand_empty_rest_of_line (); 6235214571Sdim 6236214571Sdim sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL); 6237214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6238214571Sdim return; 6239214571Sdim 6240214571Sdim sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL); 6241214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6242214571Sdim return; 6243214571Sdim 6244214571Sdim sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg); 6245214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6246214571Sdim return; 6247214571Sdim} 6248214571Sdim 6249214571Sdim/* Handle the .cprestore pseudo-op. This stores $gp into a given 6250214571Sdim offset from $sp. The offset is remembered, and after making a PIC 6251214571Sdim call $gp is restored from that location. */ 6252214571Sdim 6253214571Sdimstatic void 6254214571Sdims_score_cprestore (int ignore ATTRIBUTE_UNUSED) 6255214571Sdim{ 6256214571Sdim int reg; 6257214571Sdim int cprestore_offset; 6258214571Sdim char insn_str[MAX_LITERAL_POOL_SIZE]; 6259214571Sdim 6260214571Sdim /* If we are not generating PIC code, .cprestore is ignored. */ 6261214571Sdim if (score_pic == NO_PIC) 6262214571Sdim { 6263214571Sdim s_ignore (0); 6264214571Sdim return; 6265214571Sdim } 6266214571Sdim 6267214571Sdim if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL 6268214571Sdim || skip_past_comma (&input_line_pointer) == (int) FAIL) 6269214571Sdim { 6270214571Sdim return; 6271214571Sdim } 6272214571Sdim 6273214571Sdim cprestore_offset = get_absolute_expression (); 6274214571Sdim 6275214571Sdim if (cprestore_offset <= 0x3fff) 6276214571Sdim { 6277214571Sdim sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset); 6278214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6279214571Sdim return; 6280214571Sdim } 6281214571Sdim else 6282214571Sdim { 6283214571Sdim int r1_bak; 6284214571Sdim 6285214571Sdim r1_bak = nor1; 6286214571Sdim nor1 = 0; 6287214571Sdim 6288214571Sdim sprintf (insn_str, "li r1, %d", cprestore_offset); 6289214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6290214571Sdim return; 6291214571Sdim 6292214571Sdim sprintf (insn_str, "add r1, r1, r%d", reg); 6293214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6294214571Sdim return; 6295214571Sdim 6296214571Sdim sprintf (insn_str, "sw r%d, [r1]", GP); 6297214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6298214571Sdim return; 6299214571Sdim 6300214571Sdim nor1 = r1_bak; 6301214571Sdim } 6302214571Sdim 6303214571Sdim demand_empty_rest_of_line (); 6304214571Sdim} 6305214571Sdim 6306214571Sdim/* Handle the .gpword pseudo-op. This is used when generating PIC 6307214571Sdim code. It generates a 32 bit GP relative reloc. */ 6308214571Sdimstatic void 6309214571Sdims_score_gpword (int ignore ATTRIBUTE_UNUSED) 6310214571Sdim{ 6311214571Sdim expressionS ex; 6312214571Sdim char *p; 6313214571Sdim 6314214571Sdim /* When not generating PIC code, this is treated as .word. */ 6315214571Sdim if (score_pic == NO_PIC) 6316214571Sdim { 6317214571Sdim cons (4); 6318214571Sdim return; 6319214571Sdim } 6320214571Sdim expression (&ex); 6321214571Sdim if (ex.X_op != O_symbol || ex.X_add_number != 0) 6322214571Sdim { 6323214571Sdim as_bad (_("Unsupported use of .gpword")); 6324214571Sdim ignore_rest_of_line (); 6325214571Sdim } 6326214571Sdim p = frag_more (4); 6327214571Sdim md_number_to_chars (p, (valueT) 0, 4); 6328214571Sdim fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32); 6329214571Sdim demand_empty_rest_of_line (); 6330214571Sdim} 6331214571Sdim 6332214571Sdim/* Handle the .cpadd pseudo-op. This is used when dealing with switch 6333214571Sdim tables in PIC code. */ 6334214571Sdim 6335214571Sdimstatic void 6336214571Sdims_score_cpadd (int ignore ATTRIBUTE_UNUSED) 6337214571Sdim{ 6338214571Sdim int reg; 6339214571Sdim char insn_str[MAX_LITERAL_POOL_SIZE]; 6340214571Sdim 6341214571Sdim /* If we are not generating PIC code, .cpload is ignored. */ 6342214571Sdim if (score_pic == NO_PIC) 6343214571Sdim { 6344214571Sdim s_ignore (0); 6345214571Sdim return; 6346214571Sdim } 6347214571Sdim 6348214571Sdim if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL) 6349214571Sdim { 6350214571Sdim return; 6351214571Sdim } 6352214571Sdim demand_empty_rest_of_line (); 6353214571Sdim 6354214571Sdim /* Add $gp to the register named as an argument. */ 6355214571Sdim sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP); 6356214571Sdim if (append_insn (insn_str, TRUE) == (int) FAIL) 6357214571Sdim return; 6358214571Sdim} 6359214571Sdim 6360214571Sdim#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT 6361214571Sdim#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ 6362214571Sdim do \ 6363214571Sdim { \ 6364214571Sdim if ((SIZE) >= 8) \ 6365214571Sdim (P2VAR) = 3; \ 6366214571Sdim else if ((SIZE) >= 4) \ 6367214571Sdim (P2VAR) = 2; \ 6368214571Sdim else if ((SIZE) >= 2) \ 6369214571Sdim (P2VAR) = 1; \ 6370214571Sdim else \ 6371214571Sdim (P2VAR) = 0; \ 6372214571Sdim } \ 6373214571Sdim while (0) 6374214571Sdim#endif 6375214571Sdim 6376214571Sdimstatic void 6377214571Sdims_score_lcomm (int bytes_p) 6378214571Sdim{ 6379214571Sdim char *name; 6380214571Sdim char c; 6381214571Sdim char *p; 6382214571Sdim int temp; 6383214571Sdim symbolS *symbolP; 6384214571Sdim segT current_seg = now_seg; 6385214571Sdim subsegT current_subseg = now_subseg; 6386214571Sdim const int max_alignment = 15; 6387214571Sdim int align = 0; 6388214571Sdim segT bss_seg = bss_section; 6389214571Sdim int needs_align = 0; 6390214571Sdim 6391214571Sdim name = input_line_pointer; 6392214571Sdim c = get_symbol_end (); 6393214571Sdim p = input_line_pointer; 6394214571Sdim *p = c; 6395214571Sdim 6396214571Sdim if (name == p) 6397214571Sdim { 6398214571Sdim as_bad (_("expected symbol name")); 6399214571Sdim discard_rest_of_line (); 6400214571Sdim return; 6401214571Sdim } 6402214571Sdim 6403214571Sdim SKIP_WHITESPACE (); 6404214571Sdim 6405214571Sdim /* Accept an optional comma after the name. The comma used to be 6406214571Sdim required, but Irix 5 cc does not generate it. */ 6407214571Sdim if (*input_line_pointer == ',') 6408214571Sdim { 6409214571Sdim ++input_line_pointer; 6410214571Sdim SKIP_WHITESPACE (); 6411214571Sdim } 6412214571Sdim 6413214571Sdim if (is_end_of_line[(unsigned char)*input_line_pointer]) 6414214571Sdim { 6415214571Sdim as_bad (_("missing size expression")); 6416214571Sdim return; 6417214571Sdim } 6418214571Sdim 6419214571Sdim if ((temp = get_absolute_expression ()) < 0) 6420214571Sdim { 6421214571Sdim as_warn (_("BSS length (%d) < 0 ignored"), temp); 6422214571Sdim ignore_rest_of_line (); 6423214571Sdim return; 6424214571Sdim } 6425214571Sdim 6426214571Sdim#if defined (TC_SCORE) 6427214571Sdim if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) 6428214571Sdim { 6429214571Sdim /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ 6430214571Sdim if ((unsigned)temp <= bfd_get_gp_size (stdoutput)) 6431214571Sdim { 6432214571Sdim bss_seg = subseg_new (".sbss", 1); 6433214571Sdim seg_info (bss_seg)->bss = 1; 6434214571Sdim#ifdef BFD_ASSEMBLER 6435214571Sdim if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) 6436214571Sdim as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ())); 6437214571Sdim#endif 6438214571Sdim } 6439214571Sdim } 6440214571Sdim#endif 6441214571Sdim 6442214571Sdim SKIP_WHITESPACE (); 6443214571Sdim if (*input_line_pointer == ',') 6444214571Sdim { 6445214571Sdim ++input_line_pointer; 6446214571Sdim SKIP_WHITESPACE (); 6447214571Sdim 6448214571Sdim if (is_end_of_line[(unsigned char)*input_line_pointer]) 6449214571Sdim { 6450214571Sdim as_bad (_("missing alignment")); 6451214571Sdim return; 6452214571Sdim } 6453214571Sdim else 6454214571Sdim { 6455214571Sdim align = get_absolute_expression (); 6456214571Sdim needs_align = 1; 6457214571Sdim } 6458214571Sdim } 6459214571Sdim 6460214571Sdim if (!needs_align) 6461214571Sdim { 6462214571Sdim TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); 6463214571Sdim 6464214571Sdim /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ 6465214571Sdim if (align) 6466214571Sdim record_alignment (bss_seg, align); 6467214571Sdim } 6468214571Sdim 6469214571Sdim if (needs_align) 6470214571Sdim { 6471214571Sdim if (bytes_p) 6472214571Sdim { 6473214571Sdim /* Convert to a power of 2. */ 6474214571Sdim if (align != 0) 6475214571Sdim { 6476214571Sdim unsigned int i; 6477214571Sdim 6478214571Sdim for (i = 0; align != 0; align >>= 1, ++i) 6479214571Sdim ; 6480214571Sdim align = i - 1; 6481214571Sdim } 6482214571Sdim } 6483214571Sdim 6484214571Sdim if (align > max_alignment) 6485214571Sdim { 6486214571Sdim align = max_alignment; 6487214571Sdim as_warn (_("alignment too large; %d assumed"), align); 6488214571Sdim } 6489214571Sdim else if (align < 0) 6490214571Sdim { 6491214571Sdim align = 0; 6492214571Sdim as_warn (_("alignment negative; 0 assumed")); 6493214571Sdim } 6494214571Sdim 6495214571Sdim record_alignment (bss_seg, align); 6496214571Sdim } 6497214571Sdim else 6498214571Sdim { 6499214571Sdim /* Assume some objects may require alignment on some systems. */ 6500214571Sdim#if defined (TC_ALPHA) && ! defined (VMS) 6501214571Sdim if (temp > 1) 6502214571Sdim { 6503214571Sdim align = ffs (temp) - 1; 6504214571Sdim if (temp % (1 << align)) 6505214571Sdim abort (); 6506214571Sdim } 6507214571Sdim#endif 6508214571Sdim } 6509214571Sdim 6510214571Sdim *p = 0; 6511214571Sdim symbolP = symbol_find_or_make (name); 6512214571Sdim *p = c; 6513214571Sdim 6514214571Sdim if ( 6515214571Sdim#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ 6516214571Sdim || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) 6517214571Sdim#ifdef BFD_ASSEMBLER 6518214571Sdim (OUTPUT_FLAVOR != bfd_target_aout_flavour 6519214571Sdim || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && 6520214571Sdim#else 6521214571Sdim (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && 6522214571Sdim#endif 6523214571Sdim#endif 6524214571Sdim (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) 6525214571Sdim { 6526214571Sdim char *pfrag; 6527214571Sdim 6528214571Sdim subseg_set (bss_seg, 1); 6529214571Sdim 6530214571Sdim if (align) 6531214571Sdim frag_align (align, 0, 0); 6532214571Sdim 6533214571Sdim /* Detach from old frag. */ 6534214571Sdim if (S_GET_SEGMENT (symbolP) == bss_seg) 6535214571Sdim symbol_get_frag (symbolP)->fr_symbol = NULL; 6536214571Sdim 6537214571Sdim symbol_set_frag (symbolP, frag_now); 6538214571Sdim pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); 6539214571Sdim *pfrag = 0; 6540214571Sdim 6541214571Sdim 6542214571Sdim S_SET_SEGMENT (symbolP, bss_seg); 6543214571Sdim 6544214571Sdim#ifdef OBJ_COFF 6545214571Sdim /* The symbol may already have been created with a preceding 6546214571Sdim ".globl" directive -- be careful not to step on storage class 6547214571Sdim in that case. Otherwise, set it to static. */ 6548214571Sdim if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) 6549214571Sdim { 6550214571Sdim S_SET_STORAGE_CLASS (symbolP, C_STAT); 6551214571Sdim } 6552214571Sdim#endif /* OBJ_COFF */ 6553214571Sdim 6554214571Sdim#ifdef S_SET_SIZE 6555214571Sdim S_SET_SIZE (symbolP, temp); 6556214571Sdim#endif 6557214571Sdim } 6558214571Sdim else 6559214571Sdim as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); 6560214571Sdim 6561214571Sdim subseg_set (current_seg, current_subseg); 6562214571Sdim 6563214571Sdim demand_empty_rest_of_line (); 6564214571Sdim} 6565214571Sdim 6566214571Sdimstatic void 6567214571Sdiminsert_reg (const struct reg_entry *r, struct hash_control *htab) 6568214571Sdim{ 6569214571Sdim int i = 0; 6570214571Sdim int len = strlen (r->name) + 2; 6571214571Sdim char *buf = xmalloc (len); 6572214571Sdim char *buf2 = xmalloc (len); 6573214571Sdim 6574214571Sdim strcpy (buf + i, r->name); 6575214571Sdim for (i = 0; buf[i]; i++) 6576214571Sdim { 6577214571Sdim buf2[i] = TOUPPER (buf[i]); 6578214571Sdim } 6579214571Sdim buf2[i] = '\0'; 6580214571Sdim 6581214571Sdim hash_insert (htab, buf, (void *) r); 6582214571Sdim hash_insert (htab, buf2, (void *) r); 6583214571Sdim} 6584214571Sdim 6585214571Sdimstatic void 6586214571Sdimbuild_reg_hsh (struct reg_map *map) 6587214571Sdim{ 6588214571Sdim const struct reg_entry *r; 6589214571Sdim 6590214571Sdim if ((map->htab = hash_new ()) == NULL) 6591214571Sdim { 6592214571Sdim as_fatal (_("virtual memory exhausted")); 6593214571Sdim } 6594214571Sdim for (r = map->names; r->name != NULL; r++) 6595214571Sdim { 6596214571Sdim insert_reg (r, map->htab); 6597214571Sdim } 6598214571Sdim} 6599214571Sdim 6600214571Sdimvoid 6601214571Sdimmd_begin (void) 6602214571Sdim{ 6603214571Sdim unsigned int i; 6604214571Sdim segT seg; 6605214571Sdim subsegT subseg; 6606214571Sdim 6607214571Sdim if ((score_ops_hsh = hash_new ()) == NULL) 6608214571Sdim as_fatal (_("virtual memory exhausted")); 6609214571Sdim 6610214571Sdim build_score_ops_hsh (); 6611214571Sdim 6612214571Sdim if ((dependency_insn_hsh = hash_new ()) == NULL) 6613214571Sdim as_fatal (_("virtual memory exhausted")); 6614214571Sdim 6615214571Sdim build_dependency_insn_hsh (); 6616214571Sdim 6617214571Sdim for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++) 6618214571Sdim build_reg_hsh (all_reg_maps + i); 6619214571Sdim 6620214571Sdim /* Initialize dependency vector. */ 6621214571Sdim init_dependency_vector (); 6622214571Sdim 6623214571Sdim bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 6624214571Sdim seg = now_seg; 6625214571Sdim subseg = now_subseg; 6626214571Sdim pdr_seg = subseg_new (".pdr", (subsegT) 0); 6627214571Sdim (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); 6628214571Sdim (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2); 6629214571Sdim subseg_set (seg, subseg); 6630214571Sdim 6631214571Sdim if (USE_GLOBAL_POINTER_OPT) 6632214571Sdim bfd_set_gp_size (stdoutput, g_switch_value); 6633214571Sdim} 6634214571Sdim 6635214571Sdim 6636214571Sdimconst pseudo_typeS md_pseudo_table[] = 6637214571Sdim{ 6638214571Sdim {"bss", s_score_bss, 0}, 6639214571Sdim {"text", s_score_text, 0}, 6640214571Sdim {"word", cons, 4}, 6641214571Sdim {"long", cons, 4}, 6642214571Sdim {"extend", float_cons, 'x'}, 6643214571Sdim {"ldouble", float_cons, 'x'}, 6644214571Sdim {"packed", float_cons, 'p'}, 6645214571Sdim {"end", s_score_end, 0}, 6646214571Sdim {"ent", s_score_ent, 0}, 6647214571Sdim {"frame", s_score_frame, 0}, 6648214571Sdim {"rdata", s_change_sec, 'r'}, 6649214571Sdim {"sdata", s_change_sec, 's'}, 6650214571Sdim {"set", s_score_set, 0}, 6651214571Sdim {"mask", s_score_mask, 'R'}, 6652214571Sdim {"dword", cons, 8}, 6653214571Sdim {"lcomm", s_score_lcomm, 1}, 6654214571Sdim {"section", score_s_section, 0}, 6655214571Sdim {"cpload", s_score_cpload, 0}, 6656214571Sdim {"cprestore", s_score_cprestore, 0}, 6657214571Sdim {"gpword", s_score_gpword, 0}, 6658214571Sdim {"cpadd", s_score_cpadd, 0}, 6659214571Sdim {0, 0, 0} 6660214571Sdim}; 6661214571Sdim 6662