ld/testsuite/
[binutils.git] / gas / config / tc-score.c
blob15fec2af1f4667270fddca86d62907532f88498c
1 /* tc-score.c -- Assembler for Score
2 Copyright 2006 Free Software Foundation, Inc.
3 Contributed by:
4 Mei Ligang (ligang@sunnorth.com.cn)
5 Pei-Lin Tsai (pltsai@sunplus.com)
7 This file is part of GAS, the GNU Assembler.
9 GAS is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GAS is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GAS; see the file COPYING. If not, write to the Free
21 Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 #include "as.h"
25 #include "config.h"
26 #include "subsegs.h"
27 #include "safe-ctype.h"
28 #include "opcode/score-inst.h"
29 #include "opcode/score-datadep.h"
30 #include "struc-symbol.h"
32 #ifdef OBJ_ELF
33 #include "elf/score.h"
34 #include "dwarf2dbg.h"
35 #endif
37 #define GP 28
38 #define PIC_CALL_REG 29
39 #define MAX_LITERAL_POOL_SIZE 1024
40 #define FAIL 0x80000000
41 #define SUCCESS 0
42 #define INSN_SIZE 4
43 #define INSN16_SIZE 2
44 #define RELAX_INST_NUM 3
45 #define Insn_PIC 123
47 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
48 #define BAD_ARGS _("bad arguments to instruction")
49 #define BAD_PC _("r15 not allowed here")
50 #define BAD_COND _("instruction is not conditional")
51 #define ERR_NO_ACCUM _("acc0 expected")
52 #define ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
53 #define ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
54 #define ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
55 #define LONG_LABEL_LEN _("the label length is longer than 1024");
56 #define BAD_SKIP_COMMA BAD_ARGS
57 #define BAD_GARBAGE _("garbage following instruction");
59 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
61 /* The name of the readonly data section. */
62 #define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
63 ? ".data" \
64 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
65 ? ".rdata" \
66 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
67 ? ".rdata" \
68 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
69 ? ".rodata" \
70 : (abort (), ""))
72 #define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
73 ((relax_substateT) \
74 (((old) << 23) \
75 | ((new) << 16) \
76 | ((type) << 9) \
77 | ((reloc1) << 5) \
78 | ((reloc2) << 1) \
79 | ((opt) ? 1 : 0)))
81 #define RELAX_OLD(i) (((i) >> 23) & 0x7f)
82 #define RELAX_NEW(i) (((i) >> 16) & 0x7f)
83 #define RELAX_TYPE(i) (((i) >> 9) & 0x7f)
84 #define RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
85 #define RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
86 #define RELAX_OPT(i) ((i) & 1)
87 #define RELAX_OPT_CLEAR(i) ((i) & ~1)
89 #define SET_INSN_ERROR(s) (inst.error = (s))
90 #define INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
92 #define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
94 #define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
95 ? INSN16_SIZE : INSN_SIZE)
97 /* This array holds the chars that always start a comment. If the
98 pre-processor is disabled, these aren't very useful. */
99 const char comment_chars[] = "#";
100 const char line_comment_chars[] = "#";
101 const char line_separator_chars[] = ";";
103 /* Chars that can be used to separate mant from exp in floating point numbers. */
104 const char EXP_CHARS[] = "eE";
105 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
107 fragS *score_fragp = 0;
108 static int fix_data_dependency = 0;
109 static int warn_fix_data_dependency = 1;
110 static int score7 = 1;
111 static int university_version = 0;
113 static int in_my_get_expression = 0;
115 #define USE_GLOBAL_POINTER_OPT 1
116 #define SCORE_BI_ENDIAN
118 /* Default, pop warning message when using r1. */
119 static int nor1 = 1;
121 /* Default will do instruction relax, -O0 will set g_opt = 0. */
122 static unsigned int g_opt = 1;
124 /* The size of the small data section. */
125 static unsigned int g_switch_value = 8;
127 #ifdef OBJ_ELF
128 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
129 symbolS *GOT_symbol;
130 #endif
131 static segT pdr_seg;
133 enum score_pic_level score_pic = NO_PIC;
135 #define INSN_NAME_LEN 16
136 struct score_it
138 char name[INSN_NAME_LEN];
139 unsigned long instruction;
140 unsigned long relax_inst;
141 int size;
142 int relax_size;
143 enum score_insn_type type;
144 char str[MAX_LITERAL_POOL_SIZE];
145 const char *error;
146 int bwarn;
147 char reg[INSN_NAME_LEN];
148 struct
150 bfd_reloc_code_real_type type;
151 expressionS exp;
152 int pc_rel;
153 }reloc;
155 struct score_it inst;
157 typedef struct proc
159 symbolS *isym;
160 unsigned long reg_mask;
161 unsigned long reg_offset;
162 unsigned long fpreg_mask;
163 unsigned long leaf;
164 unsigned long frame_offset;
165 unsigned long frame_reg;
166 unsigned long pc_reg;
168 procS;
170 static procS cur_proc;
171 static procS *cur_proc_ptr;
172 static int numprocs;
174 #define SCORE7_PIPELINE 7
175 #define SCORE5_PIPELINE 5
176 static int vector_size = SCORE7_PIPELINE;
177 struct score_it dependency_vector[SCORE7_PIPELINE];
179 /* Relax will need some padding for alignment. */
180 #define RELAX_PAD_BYTE 3
182 /* Number of littlenums required to hold an extended precision number. For md_atof. */
183 #define NUM_FLOAT_VALS 8
184 #define MAX_LITTLENUMS 6
185 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
187 /* Structure for a hash table entry for a register. */
188 struct reg_entry
190 const char *name;
191 int number;
194 static const struct reg_entry score_rn_table[] =
196 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
197 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
198 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
199 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
200 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
201 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
202 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
203 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
204 {NULL, 0}
207 static const struct reg_entry score_srn_table[] =
209 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
210 {NULL, 0}
213 static const struct reg_entry score_crn_table[] =
215 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
216 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
217 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
218 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
219 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
220 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
221 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
222 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
223 {NULL, 0}
226 struct reg_map
228 const struct reg_entry *names;
229 int max_regno;
230 struct hash_control *htab;
231 const char *expected;
234 struct reg_map all_reg_maps[] =
236 {score_rn_table, 31, NULL, N_("S+core register expected")},
237 {score_srn_table, 2, NULL, N_("S+core special-register expected")},
238 {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
241 static struct hash_control *score_ops_hsh = NULL;
243 static struct hash_control *dependency_insn_hsh = NULL;
245 /* Enumeration matching entries in table above. */
246 enum score_reg_type
248 REG_TYPE_SCORE = 0,
249 #define REG_TYPE_FIRST REG_TYPE_SCORE
250 REG_TYPE_SCORE_SR = 1,
251 REG_TYPE_SCORE_CR = 2,
252 REG_TYPE_MAX = 3
255 typedef struct literalS
257 struct expressionS exp;
258 struct score_it *inst;
260 literalT;
262 literalT literals[MAX_LITERAL_POOL_SIZE];
264 static void do_ldst_insn (char *);
265 static void do_crdcrscrsimm5 (char *);
266 static void do_ldst_unalign (char *);
267 static void do_ldst_atomic (char *);
268 static void do_ldst_cop (char *);
269 static void do_macro_li_rdi32 (char *);
270 static void do_macro_la_rdi32 (char *);
271 static void do_macro_rdi32hi (char *);
272 static void do_macro_rdi32lo (char *);
273 static void do_macro_mul_rdrsrs (char *);
274 static void do_macro_ldst_label (char *);
275 static void do_branch (char *);
276 static void do_jump (char *);
277 static void do_empty (char *);
278 static void do_rdrsrs (char *);
279 static void do_rdsi16 (char *);
280 static void do_rdrssi14 (char *);
281 static void do_sub_rdsi16 (char *);
282 static void do_sub_rdi16 (char *);
283 static void do_sub_rdrssi14 (char *);
284 static void do_rdrsi5 (char *);
285 static void do_rdrsi14 (char *);
286 static void do_rdi16 (char *);
287 static void do_xrsi5 (char *);
288 static void do_rdrs (char *);
289 static void do_rdxrs (char *);
290 static void do_rsrs (char *);
291 static void do_rdcrs (char *);
292 static void do_rdsrs (char *);
293 static void do_rd (char *);
294 static void do_rs (char *);
295 static void do_i15 (char *);
296 static void do_xi5x (char *);
297 static void do_ceinst (char *);
298 static void do_cache (char *);
299 static void do16_rdrs (char *);
300 static void do16_rs (char *);
301 static void do16_xrs (char *);
302 static void do16_mv_rdrs (char *);
303 static void do16_hrdrs (char *);
304 static void do16_rdhrs (char *);
305 static void do16_rdi4 (char *);
306 static void do16_rdi5 (char *);
307 static void do16_xi5 (char *);
308 static void do16_ldst_insn (char *);
309 static void do16_ldst_imm_insn (char *);
310 static void do16_push_pop (char *);
311 static void do16_branch (char *);
312 static void do16_jump (char *);
313 static void do_rdi16_pic (char *);
314 static void do_addi_s_pic (char *);
315 static void do_addi_u_pic (char *);
316 static void do_lw_pic (char *);
318 static const struct asm_opcode score_ldst_insns[] =
320 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_ldst_insn},
321 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
322 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, do_ldst_insn},
323 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, do_ldst_insn},
324 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
325 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
326 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
327 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
328 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
329 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
330 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
331 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
332 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, do_ldst_insn},
333 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, do_ldst_insn},
334 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
335 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, do_ldst_insn},
336 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
337 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
338 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, do_ldst_insn},
339 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
340 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
341 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, do_ldst_insn},
342 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
343 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
346 static const struct asm_opcode score_insns[] =
348 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
349 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
350 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
351 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, do_rdrsrs},
352 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
353 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
354 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, do_rdrsrs},
355 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
356 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
357 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
358 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
359 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
360 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
361 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, do16_rdrs},
362 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, do16_rdrs},
363 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, do16_rdi4},
364 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
365 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
366 {"subis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdi16},
367 {"subis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdi16},
368 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
369 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
370 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
371 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, do_rdrsrs},
372 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
373 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
374 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
375 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
376 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
377 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
378 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, do16_rdrs},
379 {"bcs", 0x08000000, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
380 {"bcc", 0x08000400, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
381 {"bcnz", 0x08003800, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
382 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
383 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
384 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
385 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, do16_branch},
386 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, do16_branch},
387 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, do16_branch},
388 {"beq", 0x08001000, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
389 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
390 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, do16_branch},
391 {"bgtu", 0x08000800, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
392 {"bgt", 0x08001800, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
393 {"bge", 0x08002000, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
394 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
395 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
396 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
397 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, do16_branch},
398 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, do16_branch},
399 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, do16_branch},
400 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, do_rdrsi5},
401 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
402 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, do_rdrsi5},
403 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, do_xrsi5},
404 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, do_rdrsi5},
405 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, do16_rdi5},
406 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, do16_rdi5},
407 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, do16_rdi5},
408 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, do16_rdi5},
409 {"bleu", 0x08000c00, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
410 {"ble", 0x08001c00, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
411 {"blt", 0x08002400, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
412 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
413 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
414 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
415 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
416 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, do16_branch},
417 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, do16_branch},
418 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, do16_branch},
419 {"bmi", 0x08002800, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
420 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
421 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, do16_branch},
422 {"bne", 0x08001400, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
423 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
424 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, do16_branch},
425 {"bpl", 0x08002c00, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
426 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
427 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, do16_branch},
428 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, do_rs},
429 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, do_rs},
430 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, do_rs},
431 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, do_rs},
432 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, do_rs},
433 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, do_rs},
434 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, do_rs},
435 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, do_rs},
436 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, do_rs},
437 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, do_rs},
438 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, do_rs},
439 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, do_rs},
440 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, do_rs},
441 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, do_rs},
442 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, do_rs},
443 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, do_rs},
444 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, do_rs},
445 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, do_rs},
446 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, do_rs},
447 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, do_rs},
448 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, do_rs},
449 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, do_rs},
450 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, do_rs},
451 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, do_rs},
452 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, do_rs},
453 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, do_rs},
454 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, do_rs},
455 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, do_rs},
456 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, do_rs},
457 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, do_rs},
458 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, do_rs},
459 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, do_rs},
460 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, do16_xrs},
461 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, do16_xrs},
462 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, do16_xrs},
463 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, do16_xrs},
464 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, do16_xrs},
465 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, do16_xrs},
466 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, do16_xrs},
467 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, do16_xrs},
468 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, do16_xrs},
469 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, do16_xrs},
470 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, do16_xrs},
471 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, do16_xrs},
472 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, do16_xrs},
473 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, do16_xrs},
474 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, do16_xrs},
475 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, do16_xrs},
476 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, do16_xrs},
477 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, do16_xrs},
478 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, do16_xrs},
479 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, do16_xrs},
480 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, do16_xrs},
481 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, do16_xrs},
482 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, do16_xrs},
483 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, do16_xrs},
484 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, do16_xrs},
485 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, do16_xrs},
486 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, do16_xrs},
487 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, do16_xrs},
488 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, do16_xrs},
489 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, do16_xrs},
490 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, do16_xrs},
491 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, do16_xrs},
492 {"bvs", 0x08003000, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
493 {"bvc", 0x08003400, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
494 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
495 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
496 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, do16_branch},
497 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, do16_branch},
498 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, do16_branch},
499 {"b", 0x08003c00, 0x3e007c01, 0x08003c00, PC_DISP19div2, do_branch},
500 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, do_cache},
501 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, do_ceinst},
502 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
503 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
504 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
505 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, do_rsrs},
506 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
507 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
508 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
509 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
510 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, do16_rdrs},
511 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
512 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
513 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
514 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
515 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
516 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
517 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
518 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
519 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
520 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
521 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
522 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
523 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
524 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, do16_jump},
525 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, do16_jump},
526 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
527 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, do16_ldst_insn},
528 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
529 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, do_ldst_atomic},
530 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, do_ldst_unalign},
531 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
532 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
533 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
534 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
535 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
536 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, do16_ldst_insn},
537 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
538 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, do_rdsi16},
539 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x5000, Rd_I16, do_rdi16},
540 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, do16_ldst_imm_insn},
541 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, do16_ldst_insn},
542 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
543 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
544 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, do16_rs},
545 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
546 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, do16_rdrs},
547 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
548 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
549 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, do16_rdrs},
550 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
551 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
552 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, do16_rdrs},
553 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
554 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, do16_rdrs},
555 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
556 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
557 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
558 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
559 {"mazh.f!", 0x1009, 0x700f, 0x3800038c, Rd_Rs, do16_rdrs},
560 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
561 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
562 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, do16_rdrs},
563 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
564 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, do16_rs},
565 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
566 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, do_rdsrs},
567 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
568 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
569 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
570 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
571 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
572 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
573 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
574 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, do16_hrdrs},
575 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
576 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, do16_rdhrs},
577 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
578 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, do16_rdrs},
579 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
580 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
581 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, do16_rdrs},
582 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
583 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
584 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, do16_rdrs},
585 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
586 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, do16_rdrs},
587 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
588 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
589 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
590 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, do16_rdrs},
591 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
592 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
593 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, do16_rdrs},
594 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, do16_rs},
595 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
596 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
597 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, do16_rs},
598 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
599 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, do_rdsrs},
600 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
601 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
602 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
603 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
604 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
605 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
606 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
607 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, do16_rdrs},
608 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, do16_rdrs},
609 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
610 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
611 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
612 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
613 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
614 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
615 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
616 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
617 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
618 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
619 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
620 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
621 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
622 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
623 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, do_rdrs},
624 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, do16_mv_rdrs},
625 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, do_rdxrs},
626 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, do_rdxrs},
627 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, do16_rdrs},
628 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, do_empty},
629 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
630 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, do_rdrs},
631 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, do_empty},
632 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, do16_rdrs},
633 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
634 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, do_rdrsrs},
635 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
636 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
637 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
638 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
639 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
640 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
641 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, do16_rdrs},
642 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
643 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, do16_push_pop},
644 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, do16_push_pop},
645 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
646 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
647 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
648 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
649 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
650 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
651 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
652 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
653 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
654 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
655 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
656 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
657 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
658 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, do16_ldst_insn},
659 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
660 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, do_ldst_atomic},
661 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
662 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
663 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, do_ldst_unalign},
664 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, do_xi5x},
665 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, do16_xi5},
666 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, do16_ldst_insn},
667 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
668 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
669 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
670 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, do_rdrsrs},
671 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
672 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
673 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, do_rdrsi5},
674 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, do16_rdrs},
675 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, do16_rdi5},
676 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
677 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, do_rdrsrs},
678 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
679 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, do_rdrsrs},
680 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
681 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, do_rdrsi5},
682 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
683 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
684 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, do16_rdrs},
685 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, do16_rdrs},
686 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, do16_rdi5},
687 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
688 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
689 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
690 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
691 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, do_rdrsrs},
692 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
693 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
694 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
695 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, do16_rdrs},
696 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, do16_rdi4},
697 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, do16_ldst_insn},
698 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
699 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, do_i15},
700 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, do_empty},
701 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, do_empty},
702 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, do_empty},
703 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, do_empty},
704 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, do_empty},
705 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, do_empty},
706 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, do_empty},
707 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, do_empty},
708 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, do_empty},
709 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, do_empty},
710 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, do_empty},
711 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, do_empty},
712 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, do_empty},
713 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, do_empty},
714 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, do_empty},
715 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, do_empty},
716 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, do_empty},
717 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
718 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
719 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
720 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
721 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, do_empty},
722 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, do_empty},
723 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, do_empty},
724 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, do_empty},
725 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, do_empty},
726 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, do_empty},
727 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, do_empty},
728 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, do_empty},
729 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, do_empty},
730 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
731 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
732 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
733 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
734 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
735 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
736 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
737 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
738 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
739 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
740 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
741 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
742 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
743 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
744 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
745 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, do_empty},
746 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, do_empty},
747 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, do_empty},
748 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, do_empty},
749 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, do_empty},
750 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, do_empty},
751 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
752 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, do_rdrsrs},
753 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, do16_rdrs},
754 /* Macro instruction. */
755 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_li_rdi32},
756 /* la reg, imm32 -->(1) ldi reg, simm16
757 (2) ldis reg, %HI(imm32)
758 ori reg, %LO(imm32)
760 la reg, symbol -->(1) lis reg, %HI(imm32)
761 ori reg, %LO(imm32) */
762 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_la_rdi32},
763 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
764 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
765 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
766 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
767 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
768 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
769 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
770 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
771 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
772 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
773 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
774 {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, do_macro_ldst_label},
775 {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, do_macro_ldst_label},
776 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
777 {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, do_macro_ldst_label},
778 {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, do_macro_ldst_label},
779 {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, do_macro_ldst_label},
780 {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, do_macro_ldst_label},
781 /* Assembler use internal. */
782 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, do_macro_rdi32hi},
783 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_macro_rdi32lo},
784 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Rd_I16, do_rdi16_pic},
785 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_addi_s_pic},
786 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_addi_u_pic},
787 {"lw_pic", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_lw_pic},
790 /* Next free entry in the pool. */
791 int next_literal_pool_place = 0;
793 /* Next literal pool number. */
794 int lit_pool_num = 1;
795 symbolS *current_poolP = NULL;
797 static int
798 end_of_line (char *str)
800 int retval = SUCCESS;
802 skip_whitespace (str);
803 if (*str != '\0')
805 retval = (int) FAIL;
807 if (!inst.error)
809 inst.error = BAD_GARBAGE}
812 return retval;
815 static int
816 score_reg_parse (char **ccp, struct hash_control *htab)
818 char *start = *ccp;
819 char c;
820 char *p;
821 struct reg_entry *reg;
823 p = start;
824 if (!ISALPHA (*p) || !is_name_beginner (*p))
825 return (int) FAIL;
827 c = *p++;
829 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
830 c = *p++;
832 *--p = 0;
833 reg = (struct reg_entry *) hash_find (htab, start);
834 *p = c;
836 if (reg)
838 *ccp = p;
839 return reg->number;
841 return (int) FAIL;
844 /* If shift <= 0, only return reg. */
846 static int
847 reg_required_here (char **str, int shift, enum score_reg_type reg_type)
849 static char buff[MAX_LITERAL_POOL_SIZE];
850 int reg = (int) FAIL;
851 char *start = *str;
853 if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
855 if (reg_type == REG_TYPE_SCORE)
857 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
859 as_warn ("Using temp register(r1)");
860 inst.bwarn = 1;
863 if (shift >= 0)
865 if (reg_type == REG_TYPE_SCORE_CR)
866 strcpy (inst.reg, score_crn_table[reg].name);
867 else if (reg_type == REG_TYPE_SCORE_SR)
868 strcpy (inst.reg, score_srn_table[reg].name);
869 else
870 strcpy (inst.reg, "");
872 inst.instruction |= reg << shift;
875 else
877 *str = start;
878 sprintf (buff, _("register expected, not '%.100s'"), start);
879 inst.error = buff;
882 return reg;
885 static int
886 skip_past_comma (char **str)
888 char *p = *str;
889 char c;
890 int comma = 0;
892 while ((c = *p) == ' ' || c == ',')
894 p++;
895 if (c == ',' && comma++)
897 inst.error = BAD_SKIP_COMMA;
898 return (int) FAIL;
902 if ((c == '\0') || (comma == 0))
904 inst.error = BAD_SKIP_COMMA;
905 return (int) FAIL;
908 *str = p;
909 return comma ? SUCCESS : (int) FAIL;
912 static void
913 do_rdrsrs (char *str)
915 skip_whitespace (str);
917 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
918 || skip_past_comma (&str) == (int) FAIL
919 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
920 || skip_past_comma (&str) == (int) FAIL
921 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
922 || end_of_line (str) == (int) FAIL)
924 return;
926 else
928 if ((((inst.instruction >> 15) & 0x10) == 0)
929 && (((inst.instruction >> 10) & 0x10) == 0)
930 && (((inst.instruction >> 20) & 0x10) == 0)
931 && (inst.relax_inst != 0x8000)
932 && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
934 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
935 | (((inst.instruction >> 15) & 0xf) << 8);
936 inst.relax_size = 2;
938 else
940 inst.relax_inst = 0x8000;
945 static int
946 walk_no_bignums (symbolS * sp)
948 if (symbol_get_value_expression (sp)->X_op == O_big)
949 return 1;
951 if (symbol_get_value_expression (sp)->X_add_symbol)
952 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
953 || (symbol_get_value_expression (sp)->X_op_symbol
954 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
956 return 0;
959 static int
960 my_get_expression (expressionS * ep, char **str)
962 char *save_in;
963 segT seg;
965 save_in = input_line_pointer;
966 input_line_pointer = *str;
967 in_my_get_expression = 1;
968 seg = expression (ep);
969 in_my_get_expression = 0;
971 if (ep->X_op == O_illegal)
973 *str = input_line_pointer;
974 input_line_pointer = save_in;
975 inst.error = _("illegal expression");
976 return (int) FAIL;
978 /* Get rid of any bignums now, so that we don't generate an error for which
979 we can't establish a line number later on. Big numbers are never valid
980 in instructions, which is where this routine is always called. */
981 if (ep->X_op == O_big
982 || (ep->X_add_symbol
983 && (walk_no_bignums (ep->X_add_symbol)
984 || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
986 inst.error = _("invalid constant");
987 *str = input_line_pointer;
988 input_line_pointer = save_in;
989 return (int) FAIL;
992 *str = input_line_pointer;
993 input_line_pointer = save_in;
994 return SUCCESS;
997 /* Check if an immediate is valid. If so, convert it to the right format. */
999 static int
1000 validate_immediate (int val, unsigned int data_type)
1002 switch (data_type)
1004 case _VALUE_HI16:
1006 int val_hi = ((val & 0xffff0000) >> 16);
1008 if (score_df_range[data_type].range[0] <= val_hi
1009 && val_hi <= score_df_range[data_type].range[1])
1010 return val_hi;
1012 break;
1014 case _VALUE_LO16:
1016 int val_lo = (val & 0xffff);
1018 if (score_df_range[data_type].range[0] <= val_lo
1019 && val_lo <= score_df_range[data_type].range[1])
1020 return val_lo;
1022 break;
1024 case _VALUE:
1025 return val;
1026 break;
1028 default:
1029 if (data_type == _SIMM14_NEG || data_type == _SIMM16_NEG || data_type == _IMM16_NEG)
1030 val = -val;
1032 if (score_df_range[data_type].range[0] <= val
1033 && val <= score_df_range[data_type].range[1])
1034 return val;
1036 break;
1039 return (int) FAIL;
1042 static int
1043 data_op2 (char **str, int shift, enum score_data_type data_type)
1045 int value;
1046 char data_exp[MAX_LITERAL_POOL_SIZE];
1047 char *dataptr;
1048 int cnt = 0;
1049 char *pp = NULL;
1051 skip_whitespace (*str);
1052 inst.error = NULL;
1053 dataptr = * str;
1055 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1057 data_exp[cnt] = *dataptr;
1058 dataptr++;
1059 cnt++;
1062 data_exp[cnt] = '\0';
1063 pp = (char *)&data_exp;
1065 if (*dataptr == '|') /* process PCE */
1067 if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
1068 return (int) FAIL;
1069 end_of_line (pp);
1070 if (inst.error != 0)
1071 return (int) FAIL; /* to ouptut_inst to printf out the error */
1072 *str = dataptr;
1074 else /* process 16 bit */
1076 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
1078 return (int) FAIL;
1081 dataptr = (char *)data_exp;
1082 for (; *dataptr != '\0'; dataptr++)
1084 *dataptr = TOLOWER (*dataptr);
1085 if (*dataptr == '!' || *dataptr == ' ')
1086 break;
1088 dataptr = (char *)data_exp;
1090 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
1091 && (data_type != _SIMM16_LA)
1092 && (data_type != _VALUE_HI16)
1093 && (data_type != _VALUE_LO16)
1094 && (data_type != _IMM16)
1095 && (data_type != _IMM15)
1096 && (data_type != _IMM14)
1097 && (data_type != _IMM4)
1098 && (data_type != _IMM5)
1099 && (data_type != _IMM8)
1100 && (data_type != _IMM5_RSHIFT_1)
1101 && (data_type != _IMM5_RSHIFT_2)
1102 && (data_type != _SIMM14_NEG)
1103 && (data_type != _IMM10_RSHIFT_2)
1104 && (data_type != _GP_IMM15))
1106 data_type += 24;
1110 if ((inst.reloc.exp.X_add_symbol)
1111 && ((data_type == _SIMM16)
1112 || (data_type == _SIMM16_NEG)
1113 || (data_type == _IMM16_NEG)
1114 || (data_type == _SIMM14)
1115 || (data_type == _SIMM14_NEG)
1116 || (data_type == _IMM5)
1117 || (data_type == _IMM14)
1118 || (data_type == _IMM20)
1119 || (data_type == _IMM16)
1120 || (data_type == _IMM15)
1121 || (data_type == _IMM4)))
1123 inst.error = BAD_ARGS;
1124 return (int) FAIL;
1127 if (inst.reloc.exp.X_add_symbol)
1129 switch (data_type)
1131 case _SIMM16_LA:
1132 return (int) FAIL;
1133 case _VALUE_HI16:
1134 inst.reloc.type = BFD_RELOC_HI16_S;
1135 inst.reloc.pc_rel = 0;
1136 break;
1137 case _VALUE_LO16:
1138 inst.reloc.type = BFD_RELOC_LO16;
1139 inst.reloc.pc_rel = 0;
1140 break;
1141 case _GP_IMM15:
1142 inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1143 inst.reloc.pc_rel = 0;
1144 break;
1145 case _SIMM16_pic:
1146 case _IMM16_LO16_pic:
1147 inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1148 inst.reloc.pc_rel = 0;
1149 break;
1150 default:
1151 inst.reloc.type = BFD_RELOC_32;
1152 inst.reloc.pc_rel = 0;
1153 break;
1156 else
1158 if (data_type == _IMM16_pic)
1160 inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1161 inst.reloc.pc_rel = 0;
1164 if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
1166 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS);
1167 if (value == (int) FAIL) /* for advance to check if this is ldis */
1168 if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
1170 inst.instruction |= 0x8000000;
1171 inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1172 return SUCCESS;
1175 else
1177 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
1180 if (value == (int) FAIL)
1182 char err_msg[100];
1184 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1186 sprintf (err_msg,
1187 "invalid constant: %d bit expression not in range %d..%d",
1188 score_df_range[data_type].bits,
1189 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
1191 else
1193 sprintf (err_msg,
1194 "invalid constant: %d bit expression not in range %d..%d",
1195 score_df_range[data_type].bits,
1196 -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
1199 inst.error = _(err_msg);
1200 return (int) FAIL;
1203 if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1205 value &= (1 << score_df_range[data_type].bits) - 1;
1208 inst.instruction |= value << shift;
1211 if ((inst.instruction & 0xf0000000) == 0x30000000)
1213 if ((((inst.instruction >> 20) & 0x1F) != 0)
1214 && (((inst.instruction >> 20) & 0x1F) != 1)
1215 && (((inst.instruction >> 20) & 0x1F) != 2)
1216 && (((inst.instruction >> 20) & 0x1F) != 3)
1217 && (((inst.instruction >> 20) & 0x1F) != 4)
1218 && (((inst.instruction >> 20) & 0x1F) != 8)
1219 && (((inst.instruction >> 20) & 0x1F) != 9)
1220 && (((inst.instruction >> 20) & 0x1F) != 0xa)
1221 && (((inst.instruction >> 20) & 0x1F) != 0xb)
1222 && (((inst.instruction >> 20) & 0x1F) != 0xc)
1223 && (((inst.instruction >> 20) & 0x1F) != 0xd)
1224 && (((inst.instruction >> 20) & 0x1F) != 0xe)
1225 && (((inst.instruction >> 20) & 0x1F) != 0x10)
1226 && (((inst.instruction >> 20) & 0x1F) != 0x11)
1227 && (((inst.instruction >> 20) & 0x1F) != 0x18)
1228 && (((inst.instruction >> 20) & 0x1F) != 0x1A)
1229 && (((inst.instruction >> 20) & 0x1F) != 0x1B)
1230 && (((inst.instruction >> 20) & 0x1F) != 0x1d)
1231 && (((inst.instruction >> 20) & 0x1F) != 0x1e)
1232 && (((inst.instruction >> 20) & 0x1F) != 0x1f))
1234 char err_msg[100];
1236 sprintf (err_msg, "invalid constant: bit expression not defined");
1237 inst.error = _(err_msg);
1238 return (int) FAIL;
1242 return SUCCESS;
1245 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1247 static void
1248 do_rdsi16 (char *str)
1250 skip_whitespace (str);
1252 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1253 || skip_past_comma (&str) == (int) FAIL
1254 || data_op2 (&str, 1, _SIMM16) == (int) FAIL
1255 || end_of_line (str) == (int) FAIL)
1256 return;
1258 /* ldi. */
1259 if ((inst.instruction & 0x20c0000) == 0x20c0000)
1261 if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
1263 inst.relax_inst = 0x8000;
1265 else
1267 inst.relax_inst |= (inst.instruction >> 1) & 0xff;
1268 inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
1269 inst.relax_size = 2;
1272 else if (((inst.instruction >> 20) & 0x10) == 0x10)
1274 inst.relax_inst = 0x8000;
1278 /* Handle subi/subi.c. */
1280 static void
1281 do_sub_rdsi16 (char *str)
1283 skip_whitespace (str);
1285 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1286 && skip_past_comma (&str) != (int) FAIL
1287 && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
1288 end_of_line (str);
1291 /* Handle subis/subis.c. */
1293 static void
1294 do_sub_rdi16 (char *str)
1296 skip_whitespace (str);
1298 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1299 && skip_past_comma (&str) != (int) FAIL
1300 && data_op2 (&str, 1, _IMM16_NEG) != (int) FAIL)
1301 end_of_line (str);
1304 /* Handle addri/addri.c. */
1306 static void
1307 do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1309 skip_whitespace (str);
1311 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1312 && skip_past_comma (&str) != (int) FAIL
1313 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1314 && skip_past_comma (&str) != (int) FAIL)
1315 data_op2 (&str, 1, _SIMM14);
1318 /* Handle subri.c/subri. */
1319 static void
1320 do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1322 skip_whitespace (str);
1324 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1325 && skip_past_comma (&str) != (int) FAIL
1326 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1327 && skip_past_comma (&str) != (int) FAIL
1328 && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
1329 end_of_line (str);
1332 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1333 static void
1334 do_rdrsi5 (char *str) /* 0~((2^14)-1) */
1336 skip_whitespace (str);
1338 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1339 || skip_past_comma (&str) == (int) FAIL
1340 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1341 || skip_past_comma (&str) == (int) FAIL
1342 || data_op2 (&str, 10, _IMM5) == (int) FAIL
1343 || end_of_line (str) == (int) FAIL)
1344 return;
1346 if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
1347 && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1349 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1350 inst.relax_size = 2;
1352 else
1353 inst.relax_inst = 0x8000;
1356 /* Handle andri/orri/andri.c/orri.c. */
1358 static void
1359 do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1361 skip_whitespace (str);
1363 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1364 && skip_past_comma (&str) != (int) FAIL
1365 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1366 && skip_past_comma (&str) != (int) FAIL
1367 && data_op2 (&str, 1, _IMM14) != (int) FAIL)
1368 end_of_line (str);
1371 /* Handle bittst.c. */
1372 static void
1373 do_xrsi5 (char *str)
1375 skip_whitespace (str);
1377 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1378 || skip_past_comma (&str) == (int) FAIL
1379 || data_op2 (&str, 10, _IMM5) == (int) FAIL
1380 || end_of_line (str) == (int) FAIL)
1381 return;
1383 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1385 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1386 inst.relax_size = 2;
1388 else
1389 inst.relax_inst = 0x8000;
1392 /* Handle andi/ori/andis/oris/ldis. */
1393 static void
1394 do_rdi16 (char *str)
1396 skip_whitespace (str);
1398 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1399 || skip_past_comma (&str) == (int) FAIL
1400 || data_op2 (&str, 1, _IMM16) == (int) FAIL
1401 || end_of_line (str) == (int) FAIL)
1402 return;
1404 if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
1405 inst.relax_inst = 0x8000;
1406 else
1407 inst.relax_size = 2;
1410 static void
1411 do_macro_rdi32hi (char *str)
1413 skip_whitespace (str);
1415 /* Do not handle end_of_line(). */
1416 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1417 && skip_past_comma (&str) != (int) FAIL)
1418 data_op2 (&str, 1, _VALUE_HI16);
1421 static void
1422 do_macro_rdi32lo (char *str)
1424 skip_whitespace (str);
1426 /* Do not handle end_of_line(). */
1427 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1428 && skip_past_comma (&str) != (int) FAIL)
1429 data_op2 (&str, 1, _VALUE_LO16);
1432 /* Handle ldis_pic. */
1434 static void
1435 do_rdi16_pic (char *str)
1437 skip_whitespace (str);
1439 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1440 && skip_past_comma (&str) != (int) FAIL
1441 && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
1442 end_of_line (str);
1445 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1447 static void
1448 do_addi_s_pic (char *str)
1450 skip_whitespace (str);
1452 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1453 && skip_past_comma (&str) != (int) FAIL
1454 && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
1455 end_of_line (str);
1458 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1460 static void
1461 do_addi_u_pic (char *str)
1463 skip_whitespace (str);
1465 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1466 && skip_past_comma (&str) != (int) FAIL
1467 && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
1468 end_of_line (str);
1471 /* Handle mfceh/mfcel/mtceh/mtchl. */
1473 static void
1474 do_rd (char *str)
1476 skip_whitespace (str);
1478 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
1479 end_of_line (str);
1482 static void
1483 do_rs (char *str)
1485 skip_whitespace (str);
1487 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1488 || end_of_line (str) == (int) FAIL)
1489 return;
1491 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1493 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
1494 inst.relax_size = 2;
1496 else
1497 inst.relax_inst = 0x8000;
1500 static void
1501 do_i15 (char *str)
1503 skip_whitespace (str);
1505 if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
1506 end_of_line (str);
1509 static void
1510 do_xi5x (char *str)
1512 skip_whitespace (str);
1514 if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
1515 return;
1517 if (inst.relax_inst != 0x8000)
1519 inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
1520 inst.relax_size = 2;
1524 static void
1525 do_rdrs (char *str)
1527 skip_whitespace (str);
1529 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1530 || skip_past_comma (&str) == (int) FAIL
1531 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1532 || end_of_line (str) == (int) FAIL)
1533 return;
1535 if (inst.relax_inst != 0x8000)
1537 if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1539 /* mlfh */
1540 if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1542 inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
1543 | (((inst.instruction >> 20) & 0xf) << 8);
1544 inst.relax_size = 2;
1546 /* mhfl */
1547 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
1549 inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
1550 | (((inst.instruction >> 20) & 0xf) << 8);
1551 inst.relax_size = 2;
1553 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1555 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1556 | (((inst.instruction >> 20) & 0xf) << 8);
1557 inst.relax_size = 2;
1559 else
1561 inst.relax_inst = 0x8000;
1564 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1566 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1567 | (((inst.instruction >> 20) & 0xf) << 8);
1568 inst.relax_size = 2;
1570 else
1572 inst.relax_inst = 0x8000;
1577 /* Handle mfcr/mtcr. */
1578 static void
1579 do_rdcrs (char *str)
1581 skip_whitespace (str);
1583 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1584 && skip_past_comma (&str) != (int) FAIL
1585 && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
1586 end_of_line (str);
1589 /* Handle mfsr/mtsr. */
1591 static void
1592 do_rdsrs (char *str)
1594 skip_whitespace (str);
1596 /* mfsr */
1597 if ((inst.instruction & 0xff) == 0x50)
1599 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1600 && skip_past_comma (&str) != (int) FAIL
1601 && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
1602 end_of_line (str);
1604 else
1606 if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1607 && skip_past_comma (&str) != (int) FAIL)
1608 reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
1612 /* Handle neg. */
1614 static void
1615 do_rdxrs (char *str)
1617 skip_whitespace (str);
1619 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1620 || skip_past_comma (&str) == (int) FAIL
1621 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1622 || end_of_line (str) == (int) FAIL)
1623 return;
1625 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
1626 && (((inst.instruction >> 20) & 0x10) == 0))
1628 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
1629 inst.relax_size = 2;
1631 else
1632 inst.relax_inst = 0x8000;
1635 /* Handle cmp.c/cmp<cond>. */
1636 static void
1637 do_rsrs (char *str)
1639 skip_whitespace (str);
1641 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1642 || skip_past_comma (&str) == (int) FAIL
1643 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1644 || end_of_line (str) == (int) FAIL)
1645 return;
1647 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
1648 && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
1650 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
1651 inst.relax_size = 2;
1653 else
1654 inst.relax_inst = 0x8000;
1657 static void
1658 do_ceinst (char *str)
1660 char *strbak;
1662 strbak = str;
1663 skip_whitespace (str);
1665 if (data_op2 (&str, 20, _IMM5) == (int) FAIL
1666 || skip_past_comma (&str) == (int) FAIL
1667 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1668 || skip_past_comma (&str) == (int) FAIL
1669 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1670 || skip_past_comma (&str) == (int) FAIL
1671 || data_op2 (&str, 5, _IMM5) == (int) FAIL
1672 || skip_past_comma (&str) == (int) FAIL
1673 || data_op2 (&str, 0, _IMM5) == (int) FAIL
1674 || end_of_line (str) == (int) FAIL)
1676 return;
1678 else
1680 str = strbak;
1681 if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
1682 return;
1686 static int
1687 reglow_required_here (char **str, int shift)
1689 static char buff[MAX_LITERAL_POOL_SIZE];
1690 int reg;
1691 char *start = *str;
1693 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1695 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
1697 as_warn ("Using temp register(r1)");
1698 inst.bwarn = 1;
1700 if (reg < 16)
1702 if (shift >= 0)
1703 inst.instruction |= reg << shift;
1705 return reg;
1709 /* Restore the start point, we may have got a reg of the wrong class. */
1710 *str = start;
1711 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
1712 inst.error = buff;
1713 return (int) FAIL;
1716 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
1717 static void
1718 do16_rdrs (char *str)
1720 skip_whitespace (str);
1722 if (reglow_required_here (&str, 8) == (int) FAIL
1723 || skip_past_comma (&str) == (int) FAIL
1724 || reglow_required_here (&str, 4) == (int) FAIL
1725 || end_of_line (str) == (int) FAIL)
1727 return;
1729 else
1731 if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */
1733 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
1734 | (((inst.instruction >> 4) & 0xf) << 10);
1736 else
1738 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1739 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
1741 inst.relax_size = 4;
1745 static void
1746 do16_rs (char *str)
1748 int rd = 0;
1750 skip_whitespace (str);
1752 if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
1753 || end_of_line (str) == (int) FAIL)
1755 return;
1757 else
1759 inst.relax_inst |= rd << 20;
1760 inst.relax_size = 4;
1764 /* Handle br!/brl!. */
1765 static void
1766 do16_xrs (char *str)
1768 skip_whitespace (str);
1770 if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
1772 return;
1774 else
1776 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
1777 | (((inst.instruction >> 4) & 0xf) << 15);
1778 inst.relax_size = 4;
1782 static int
1783 reghigh_required_here (char **str, int shift)
1785 static char buff[MAX_LITERAL_POOL_SIZE];
1786 int reg;
1787 char *start = *str;
1789 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1791 if (15 < reg && reg < 32)
1793 if (shift >= 0)
1794 inst.instruction |= (reg & 0xf) << shift;
1796 return reg;
1800 *str = start;
1801 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
1802 inst.error = buff;
1803 return (int) FAIL;
1806 /* Handle mhfl!. */
1807 static void
1808 do16_hrdrs (char *str)
1810 skip_whitespace (str);
1812 if (reghigh_required_here (&str, 8) != (int) FAIL
1813 && skip_past_comma (&str) != (int) FAIL
1814 && reglow_required_here (&str, 4) != (int) FAIL
1815 && end_of_line (str) != (int) FAIL)
1817 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
1818 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
1819 inst.relax_size = 4;
1823 /* Handle mlfh!. */
1824 static void
1825 do16_rdhrs (char *str)
1827 skip_whitespace (str);
1829 if (reglow_required_here (&str, 8) != (int) FAIL
1830 && skip_past_comma (&str) != (int) FAIL
1831 && reghigh_required_here (&str, 4) != (int) FAIL
1832 && end_of_line (str) != (int) FAIL)
1834 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1835 | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
1836 inst.relax_size = 4;
1840 /* We need to be able to fix up arbitrary expressions in some statements.
1841 This is so that we can handle symbols that are an arbitrary distance from
1842 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
1843 which returns part of an address in a form which will be valid for
1844 a data instruction. We do this by pushing the expression into a symbol
1845 in the expr_section, and creating a fix for that. */
1846 static fixS *
1847 fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1849 fixS *new_fix;
1851 switch (exp->X_op)
1853 case O_constant:
1854 case O_symbol:
1855 case O_add:
1856 case O_subtract:
1857 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
1858 break;
1859 default:
1860 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
1861 break;
1863 return new_fix;
1866 static void
1867 init_dependency_vector (void)
1869 int i;
1871 for (i = 0; i < vector_size; i++)
1872 memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
1874 return;
1877 static enum insn_type_for_dependency
1878 dependency_type_from_insn (char *insn_name)
1880 char name[INSN_NAME_LEN];
1881 const struct insn_to_dependency *tmp;
1883 strcpy (name, insn_name);
1884 tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
1886 if (tmp)
1887 return tmp->type;
1889 return D_all_insn;
1892 static int
1893 check_dependency (char *pre_insn, char *pre_reg,
1894 char *cur_insn, char *cur_reg, int *warn_or_error)
1896 int bubbles = 0;
1897 unsigned int i;
1898 enum insn_type_for_dependency pre_insn_type;
1899 enum insn_type_for_dependency cur_insn_type;
1901 pre_insn_type = dependency_type_from_insn (pre_insn);
1902 cur_insn_type = dependency_type_from_insn (cur_insn);
1904 for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
1906 if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
1907 && (D_all_insn == data_dependency_table[i].cur_insn_type
1908 || cur_insn_type == data_dependency_table[i].cur_insn_type)
1909 && (strcmp (data_dependency_table[i].pre_reg, "") == 0
1910 || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
1911 && (strcmp (data_dependency_table[i].cur_reg, "") == 0
1912 || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
1914 bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
1915 *warn_or_error = data_dependency_table[i].warn_or_error;
1916 break;
1920 return bubbles;
1923 static void
1924 build_one_frag (struct score_it one_inst)
1926 char *p;
1927 int relaxable_p = g_opt;
1928 int relax_size = 0;
1930 /* Start a new frag if frag_now is not empty. */
1931 if (frag_now_fix () != 0)
1933 if (!frag_now->tc_frag_data.is_insn)
1934 frag_wane (frag_now);
1936 frag_new (0);
1938 frag_grow (20);
1940 p = frag_more (one_inst.size);
1941 md_number_to_chars (p, one_inst.instruction, one_inst.size);
1943 #ifdef OBJ_ELF
1944 dwarf2_emit_insn (one_inst.size);
1945 #endif
1947 relaxable_p &= (one_inst.relax_size != 0);
1948 relax_size = relaxable_p ? one_inst.relax_size : 0;
1950 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
1951 RELAX_ENCODE (one_inst.size, one_inst.relax_size,
1952 one_inst.type, 0, 0, relaxable_p),
1953 NULL, 0, NULL);
1955 if (relaxable_p)
1956 md_number_to_chars (p, one_inst.relax_inst, relax_size);
1959 static void
1960 handle_dependency (struct score_it *theinst)
1962 int i;
1963 int warn_or_error = 0; /* warn - 0; error - 1 */
1964 int bubbles = 0;
1965 int remainder_bubbles = 0;
1966 char cur_insn[INSN_NAME_LEN];
1967 char pre_insn[INSN_NAME_LEN];
1968 struct score_it nop_inst;
1969 struct score_it pflush_inst;
1971 nop_inst.instruction = 0x0000;
1972 nop_inst.size = 2;
1973 nop_inst.relax_inst = 0x80008000;
1974 nop_inst.relax_size = 4;
1975 nop_inst.type = NO16_OPD;
1977 pflush_inst.instruction = 0x8000800a;
1978 pflush_inst.size = 4;
1979 pflush_inst.relax_inst = 0x8000;
1980 pflush_inst.relax_size = 0;
1981 pflush_inst.type = NO_OPD;
1983 /* pflush will clear all data dependency. */
1984 if (strcmp (theinst->name, "pflush") == 0)
1986 init_dependency_vector ();
1987 return;
1990 /* Push current instruction to dependency_vector[0]. */
1991 for (i = vector_size - 1; i > 0; i--)
1992 memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
1994 memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
1996 /* There is no dependency between nop and any instruction. */
1997 if (strcmp (dependency_vector[0].name, "nop") == 0
1998 || strcmp (dependency_vector[0].name, "nop!") == 0)
1999 return;
2001 /* "pce" is defined in insn_to_dependency_table. */
2002 #define PCE_NAME "pce"
2004 if (dependency_vector[0].type == Insn_Type_PCE)
2005 strcpy (cur_insn, PCE_NAME);
2006 else
2007 strcpy (cur_insn, dependency_vector[0].name);
2009 for (i = 1; i < vector_size; i++)
2011 /* The element of dependency_vector is NULL. */
2012 if (dependency_vector[i].name[0] == '\0')
2013 continue;
2015 if (dependency_vector[i].type == Insn_Type_PCE)
2016 strcpy (pre_insn, PCE_NAME);
2017 else
2018 strcpy (pre_insn, dependency_vector[i].name);
2020 bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
2021 cur_insn, dependency_vector[0].reg, &warn_or_error);
2022 remainder_bubbles = bubbles - i + 1;
2024 if (remainder_bubbles > 0)
2026 int j;
2028 if (fix_data_dependency == 1)
2030 if (remainder_bubbles <= 2)
2032 if (warn_fix_data_dependency)
2033 as_warn ("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)",
2034 dependency_vector[i].name, dependency_vector[i].reg,
2035 dependency_vector[0].name, dependency_vector[0].reg,
2036 remainder_bubbles, bubbles);
2038 for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
2039 memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
2040 sizeof (dependency_vector[j]));
2042 for (j = 1; j <= remainder_bubbles; j++)
2044 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2045 /* Insert nop!. */
2046 build_one_frag (nop_inst);
2049 else
2051 if (warn_fix_data_dependency)
2052 as_warn ("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)",
2053 dependency_vector[i].name, dependency_vector[i].reg,
2054 dependency_vector[0].name, dependency_vector[0].reg,
2055 bubbles);
2057 for (j = 1; j < vector_size; j++)
2058 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2060 /* Insert pflush. */
2061 build_one_frag (pflush_inst);
2064 else
2066 if (warn_or_error)
2068 as_bad ("data dependency: %s %s -- %s %s (%d/%d bubble)",
2069 dependency_vector[i].name, dependency_vector[i].reg,
2070 dependency_vector[0].name, dependency_vector[0].reg,
2071 remainder_bubbles, bubbles);
2073 else
2075 as_warn ("data dependency: %s %s -- %s %s (%d/%d bubble)",
2076 dependency_vector[i].name, dependency_vector[i].reg,
2077 dependency_vector[0].name, dependency_vector[0].reg,
2078 remainder_bubbles, bubbles);
2085 static enum insn_class
2086 get_insn_class_from_type (enum score_insn_type type)
2088 enum insn_class retval = (int) FAIL;
2090 switch (type)
2092 case Rd_I4:
2093 case Rd_I5:
2094 case Rd_rvalueBP_I5:
2095 case Rd_lvalueBP_I5:
2096 case Rd_I8:
2097 case PC_DISP8div2:
2098 case PC_DISP11div2:
2099 case Rd_Rs:
2100 case Rd_HighRs:
2101 case Rd_lvalueRs:
2102 case Rd_rvalueRs:
2103 case x_Rs:
2104 case Rd_LowRs:
2105 case NO16_OPD:
2106 retval = INSN_CLASS_16;
2107 break;
2108 case Rd_Rs_I5:
2109 case x_Rs_I5:
2110 case x_I5_x:
2111 case Rd_Rs_I14:
2112 case I15:
2113 case Rd_I16:
2114 case Rd_SI16:
2115 case Rd_rvalueRs_SI10:
2116 case Rd_lvalueRs_SI10:
2117 case Rd_rvalueRs_preSI12:
2118 case Rd_rvalueRs_postSI12:
2119 case Rd_lvalueRs_preSI12:
2120 case Rd_lvalueRs_postSI12:
2121 case Rd_Rs_SI14:
2122 case Rd_rvalueRs_SI15:
2123 case Rd_lvalueRs_SI15:
2124 case PC_DISP19div2:
2125 case PC_DISP24div2:
2126 case Rd_Rs_Rs:
2127 case x_Rs_x:
2128 case x_Rs_Rs:
2129 case Rd_Rs_x:
2130 case Rd_x_Rs:
2131 case Rd_x_x:
2132 case OP5_rvalueRs_SI15:
2133 case I5_Rs_Rs_I5_OP5:
2134 case x_rvalueRs_post4:
2135 case Rd_rvalueRs_post4:
2136 case Rd_x_I5:
2137 case Rd_lvalueRs_post4:
2138 case x_lvalueRs_post4:
2139 case Rd_Rs_Rs_imm:
2140 case NO_OPD:
2141 case Rd_lvalue32Rs:
2142 case Rd_rvalue32Rs:
2143 case Insn_GP:
2144 case Insn_PIC:
2145 retval = INSN_CLASS_32;
2146 break;
2147 case Insn_Type_PCE:
2148 retval = INSN_CLASS_PCE;
2149 break;
2150 case Insn_Type_SYN:
2151 retval = INSN_CLASS_SYN;
2152 break;
2153 default:
2154 abort ();
2155 break;
2157 return retval;
2160 static unsigned long
2161 adjust_paritybit (unsigned long m_code, enum insn_class class)
2163 unsigned long result = 0;
2164 unsigned long m_code_high = 0;
2165 unsigned long m_code_low = 0;
2166 unsigned long pb_high = 0;
2167 unsigned long pb_low = 0;
2169 if (class == INSN_CLASS_32)
2171 pb_high = 0x80000000;
2172 pb_low = 0x00008000;
2174 else if (class == INSN_CLASS_16)
2176 pb_high = 0;
2177 pb_low = 0;
2179 else if (class == INSN_CLASS_PCE)
2181 pb_high = 0;
2182 pb_low = 0x00008000;
2184 else if (class == INSN_CLASS_SYN)
2186 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2187 be changed if macro instruction has been expanded. */
2188 pb_high = 0x80000000;
2189 pb_low = 0x00008000;
2191 else
2193 abort ();
2196 m_code_high = m_code & 0x3fff8000;
2197 m_code_low = m_code & 0x00007fff;
2198 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2199 return result;
2203 static void
2204 gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
2206 char *p;
2207 bfd_boolean pce_p = FALSE;
2208 int relaxable_p = g_opt;
2209 int relax_size = 0;
2210 struct score_it *inst1 = part_1;
2211 struct score_it *inst2 = part_2;
2212 struct score_it backup_inst1;
2214 pce_p = (inst2) ? TRUE : FALSE;
2215 memcpy (&backup_inst1, inst1, sizeof (struct score_it));
2217 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2218 if (pce_p)
2220 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2221 | (inst2->instruction & 0x7FFF);
2222 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2223 backup_inst1.relax_inst = 0x8000;
2224 backup_inst1.size = INSN_SIZE;
2225 backup_inst1.relax_size = 0;
2226 backup_inst1.type = Insn_Type_PCE;
2228 else
2230 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
2231 GET_INSN_CLASS (backup_inst1.type));
2234 if (backup_inst1.relax_size != 0)
2236 enum insn_class tmp;
2238 tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2239 backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
2242 /* Check data dependency. */
2243 handle_dependency (&backup_inst1);
2245 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2246 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2247 if (frag_now_fix () != 0)
2249 if (!frag_now->tc_frag_data.is_insn)
2250 frag_wane (frag_now);
2252 frag_new (0);
2255 /* Here, we must call frag_grow in order to keep the instruction frag type is
2256 rs_machine_dependent.
2257 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2258 acturally will call frag_wane.
2259 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2260 for frag_var. */
2261 frag_grow (20);
2263 p = frag_more (backup_inst1.size);
2264 md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2266 #ifdef OBJ_ELF
2267 dwarf2_emit_insn (backup_inst1.size);
2268 #endif
2270 /* Generate fixup structure. */
2271 if (pce_p)
2273 if (inst1->reloc.type != BFD_RELOC_NONE)
2274 fix_new_score (frag_now, p - frag_now->fr_literal,
2275 inst1->size, &inst1->reloc.exp,
2276 inst1->reloc.pc_rel, inst1->reloc.type);
2278 if (inst2->reloc.type != BFD_RELOC_NONE)
2279 fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2280 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2282 else
2284 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2285 fix_new_score (frag_now, p - frag_now->fr_literal,
2286 backup_inst1.size, &backup_inst1.reloc.exp,
2287 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2290 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2291 relaxable_p &= (backup_inst1.relax_size != 0);
2292 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2294 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2295 RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2296 backup_inst1.type, 0, 0, relaxable_p),
2297 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2299 if (relaxable_p)
2300 md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2302 memcpy (inst1, &backup_inst1, sizeof (struct score_it));
2305 static void
2306 parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2308 char c;
2309 char *p;
2310 char *operator = insnstr;
2311 const struct asm_opcode *opcode;
2313 /* Parse operator and operands. */
2314 skip_whitespace (operator);
2316 for (p = operator; *p != '\0'; p++)
2317 if ((*p == ' ') || (*p == '!'))
2318 break;
2320 if (*p == '!')
2321 p++;
2323 c = *p;
2324 *p = '\0';
2326 opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
2327 *p = c;
2329 memset (&inst, '\0', sizeof (inst));
2330 sprintf (inst.str, "%s", insnstr);
2331 if (opcode)
2333 inst.instruction = opcode->value;
2334 inst.relax_inst = opcode->relax_value;
2335 inst.type = opcode->type;
2336 inst.size = GET_INSN_SIZE (inst.type);
2337 inst.relax_size = 0;
2338 inst.bwarn = 0;
2339 sprintf (inst.name, "%s", opcode->template);
2340 strcpy (inst.reg, "");
2341 inst.error = NULL;
2342 inst.reloc.type = BFD_RELOC_NONE;
2344 (*opcode->parms) (p);
2346 /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */
2347 if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
2348 gen_insn_frag (&inst, NULL);
2350 else
2351 inst.error = _("unrecognized opcode");
2354 static int
2355 append_insn (char *str, bfd_boolean gen_frag_p)
2357 int retval = SUCCESS;
2359 parse_16_32_inst (str, gen_frag_p);
2361 if (inst.error)
2363 retval = (int) FAIL;
2364 as_bad ("%s -- `%s'", inst.error, inst.str);
2365 inst.error = NULL;
2368 return retval;
2371 /* Handle mv! reg_high, reg_low;
2372 mv! reg_low, reg_high;
2373 mv! reg_low, reg_low; */
2374 static void
2375 do16_mv_rdrs (char *str)
2377 int reg_rd;
2378 int reg_rs;
2379 char *backupstr = NULL;
2381 backupstr = str;
2382 skip_whitespace (str);
2384 if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
2385 || skip_past_comma (&str) == (int) FAIL
2386 || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
2387 || end_of_line (str) == (int) FAIL)
2389 return;
2391 else
2393 /* Case 1 : mv! or mlfh!. */
2394 if (reg_rd < 16)
2396 if (reg_rs < 16)
2398 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2399 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2400 inst.relax_size = 4;
2402 else
2404 char append_str[MAX_LITERAL_POOL_SIZE];
2406 sprintf (append_str, "mlfh! %s", backupstr);
2407 if (append_insn (append_str, TRUE) == (int) FAIL)
2408 return;
2409 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2410 inst.bwarn = -1;
2413 /* Case 2 : mhfl!. */
2414 else
2416 if (reg_rs > 16)
2418 SET_INSN_ERROR (BAD_ARGS);
2419 return;
2421 else
2423 char append_str[MAX_LITERAL_POOL_SIZE];
2425 sprintf (append_str, "mhfl! %s", backupstr);
2426 if (append_insn (append_str, TRUE) == (int) FAIL)
2427 return;
2429 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2430 inst.bwarn = -1;
2436 static void
2437 do16_rdi4 (char *str)
2439 skip_whitespace (str);
2441 if (reglow_required_here (&str, 8) == (int) FAIL
2442 || skip_past_comma (&str) == (int) FAIL
2443 || data_op2 (&str, 3, _IMM4) == (int) FAIL
2444 || end_of_line (str) == (int) FAIL)
2446 return;
2448 else
2450 if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2452 if (((inst.instruction >> 3) & 0xf) != 0xf)
2454 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2455 | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
2456 inst.relax_size = 4;
2458 else
2460 inst.relax_inst = 0x8000;
2463 else
2465 if (((inst.instruction >> 3) & 0xf) != 0xf)
2467 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2468 | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2469 inst.relax_size = 4;
2471 else
2473 inst.relax_inst = 0x8000;
2479 static void
2480 do16_rdi5 (char *str)
2482 skip_whitespace (str);
2484 if (reglow_required_here (&str, 8) == (int) FAIL
2485 || skip_past_comma (&str) == (int) FAIL
2486 || data_op2 (&str, 3, _IMM5) == (int) FAIL
2487 || end_of_line (str) == (int) FAIL)
2488 return;
2489 else
2491 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2492 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
2493 inst.relax_size = 4;
2497 /* Handle sdbbp. */
2498 static void
2499 do16_xi5 (char *str)
2501 skip_whitespace (str);
2503 if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
2504 return;
2505 else
2507 inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
2508 inst.relax_size = 4;
2512 /* Check that an immediate is word alignment or half word alignment.
2513 If so, convert it to the right format. */
2514 static int
2515 validate_immediate_align (int val, unsigned int data_type)
2517 if (data_type == _IMM5_RSHIFT_1)
2519 if (val % 2)
2521 inst.error = _("address offset must be half word alignment");
2522 return (int) FAIL;
2525 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2527 if (val % 4)
2529 inst.error = _("address offset must be word alignment");
2530 return (int) FAIL;
2534 return SUCCESS;
2537 static int
2538 exp_ldst_offset (char **str, int shift, unsigned int data_type)
2540 char *dataptr;
2542 dataptr = * str;
2544 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2545 && (data_type != _SIMM16_LA)
2546 && (data_type != _VALUE_HI16)
2547 && (data_type != _VALUE_LO16)
2548 && (data_type != _IMM16)
2549 && (data_type != _IMM15)
2550 && (data_type != _IMM14)
2551 && (data_type != _IMM4)
2552 && (data_type != _IMM5)
2553 && (data_type != _IMM8)
2554 && (data_type != _IMM5_RSHIFT_1)
2555 && (data_type != _IMM5_RSHIFT_2)
2556 && (data_type != _SIMM14_NEG)
2557 && (data_type != _IMM10_RSHIFT_2))
2559 data_type += 24;
2562 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
2563 return (int) FAIL;
2565 if (inst.reloc.exp.X_op == O_constant)
2567 /* Need to check the immediate align. */
2568 int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
2570 if (value == (int) FAIL)
2571 return (int) FAIL;
2573 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2574 if (value == (int) FAIL)
2576 char err_msg[255];
2578 if (data_type < 30)
2579 sprintf (err_msg,
2580 "invalid constant: %d bit expression not in range %d..%d",
2581 score_df_range[data_type].bits,
2582 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2583 else
2584 sprintf (err_msg,
2585 "invalid constant: %d bit expression not in range %d..%d",
2586 score_df_range[data_type - 24].bits,
2587 score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
2588 inst.error = _(err_msg);
2589 return (int) FAIL;
2592 if (data_type == _IMM5_RSHIFT_1)
2594 value >>= 1;
2596 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2598 value >>= 2;
2601 if (score_df_range[data_type].range[0] != 0)
2603 value &= (1 << score_df_range[data_type].bits) - 1;
2606 inst.instruction |= value << shift;
2608 else
2610 inst.reloc.pc_rel = 0;
2613 return SUCCESS;
2616 static void
2617 do_ldst_insn (char *str)
2619 int pre_inc = 0;
2620 int conflict_reg;
2621 int value;
2622 char * temp;
2623 char *strbak;
2624 char *dataptr;
2625 int reg;
2626 int ldst_idx = 0;
2628 strbak = str;
2629 skip_whitespace (str);
2631 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
2632 || (skip_past_comma (&str) == (int) FAIL))
2633 return;
2635 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
2636 if (*str == '[')
2638 str++;
2639 skip_whitespace (str);
2641 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
2642 return;
2644 /* Conflicts can occur on stores as well as loads. */
2645 conflict_reg = (conflict_reg == reg);
2646 skip_whitespace (str);
2647 temp = str + 1; /* The latter will process decimal/hex expression. */
2649 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
2650 if (*str == ']')
2652 str++;
2653 if (*str == '+')
2655 str++;
2656 /* ld/sw rD, [rA]+, simm12. */
2657 if (skip_past_comma (&str) == SUCCESS)
2659 if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
2660 || (end_of_line (str) == (int) FAIL))
2661 return;
2663 if (conflict_reg)
2665 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2667 if ((ldst_func == INSN_LH)
2668 || (ldst_func == INSN_LHU)
2669 || (ldst_func == INSN_LW)
2670 || (ldst_func == INSN_LB)
2671 || (ldst_func == INSN_LBU))
2673 inst.error = _("register same as write-back base");
2674 return;
2678 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2679 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2680 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2682 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
2683 if ((inst.instruction & 0x3e000007) == 0x0e000000)
2685 /* rs = r0-r7, offset = 4 */
2686 if ((((inst.instruction >> 15) & 0x18) == 0)
2687 && (((inst.instruction >> 3) & 0xfff) == 4))
2689 /* Relax to pophi. */
2690 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2692 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2693 << 8) | 1 << 7 |
2694 (((inst.instruction >> 15) & 0x7) << 4);
2696 /* Relax to pop. */
2697 else
2699 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2700 << 8) | 0 << 7 |
2701 (((inst.instruction >> 15) & 0x7) << 4);
2703 inst.relax_size = 2;
2706 return;
2708 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
2709 else
2711 SET_INSN_ERROR (NULL);
2712 if (end_of_line (str) == (int) FAIL)
2714 return;
2717 pre_inc = 1;
2718 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12);
2719 value &= (1 << score_df_range[_SIMM12].bits) - 1;
2720 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2721 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2722 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2723 inst.instruction |= value << 3;
2724 inst.relax_inst = 0x8000;
2725 return;
2728 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
2729 else
2731 if (end_of_line (str) == (int) FAIL)
2732 return;
2734 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2735 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2736 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
2738 /* lbu rd, [rs] -> lbu! rd, [rs] */
2739 if (ldst_idx == INSN_LBU)
2741 inst.relax_inst = INSN16_LBU;
2743 else if (ldst_idx == INSN_LH)
2745 inst.relax_inst = INSN16_LH;
2747 else if (ldst_idx == INSN_LW)
2749 inst.relax_inst = INSN16_LW;
2751 else if (ldst_idx == INSN_SB)
2753 inst.relax_inst = INSN16_SB;
2755 else if (ldst_idx == INSN_SH)
2757 inst.relax_inst = INSN16_SH;
2759 else if (ldst_idx == INSN_SW)
2761 inst.relax_inst = INSN16_SW;
2763 else
2765 inst.relax_inst = 0x8000;
2768 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
2769 if ((ldst_idx == INSN_LBU)
2770 || (ldst_idx == INSN_LH)
2771 || (ldst_idx == INSN_LW)
2772 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
2774 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2776 inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
2777 (((inst.instruction >> 15) & 0xf) << 4);
2778 inst.relax_size = 2;
2782 return;
2785 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
2786 else
2788 if (skip_past_comma (&str) == (int) FAIL)
2790 inst.error = _("pre-indexed expression expected");
2791 return;
2794 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
2795 return;
2797 skip_whitespace (str);
2798 if (*str++ != ']')
2800 inst.error = _("missing ]");
2801 return;
2804 skip_whitespace (str);
2805 /* ld/sw rD, [rA, simm12]+. */
2806 if (*str == '+')
2808 str++;
2809 pre_inc = 1;
2810 if (conflict_reg)
2812 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2814 if ((ldst_func == INSN_LH)
2815 || (ldst_func == INSN_LHU)
2816 || (ldst_func == INSN_LW)
2817 || (ldst_func == INSN_LB)
2818 || (ldst_func == INSN_LBU))
2820 inst.error = _("register same as write-back base");
2821 return;
2826 if (end_of_line (str) == (int) FAIL)
2827 return;
2829 if (inst.reloc.exp.X_op == O_constant)
2831 int value;
2832 unsigned int data_type;
2834 if (pre_inc == 1)
2835 data_type = _SIMM12;
2836 else
2837 data_type = _SIMM15;
2838 dataptr = temp;
2840 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2841 && (data_type != _SIMM16_LA)
2842 && (data_type != _VALUE_HI16)
2843 && (data_type != _VALUE_LO16)
2844 && (data_type != _IMM16)
2845 && (data_type != _IMM15)
2846 && (data_type != _IMM14)
2847 && (data_type != _IMM4)
2848 && (data_type != _IMM5)
2849 && (data_type != _IMM8)
2850 && (data_type != _IMM5_RSHIFT_1)
2851 && (data_type != _IMM5_RSHIFT_2)
2852 && (data_type != _SIMM14_NEG)
2853 && (data_type != _IMM10_RSHIFT_2))
2855 data_type += 24;
2858 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2859 if (value == (int) FAIL)
2861 char err_msg[255];
2863 if (data_type < 27)
2864 sprintf (err_msg,
2865 "invalid constant: %d bit expression not in range %d..%d",
2866 score_df_range[data_type].bits,
2867 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2868 else
2869 sprintf (err_msg,
2870 "invalid constant: %d bit expression not in range %d..%d",
2871 score_df_range[data_type - 21].bits,
2872 score_df_range[data_type - 21].range[0],
2873 score_df_range[data_type - 21].range[1]);
2874 inst.error = _(err_msg);
2875 return;
2878 value &= (1 << score_df_range[data_type].bits) - 1;
2879 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2880 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2881 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2882 if (pre_inc == 1)
2883 inst.instruction |= value << 3;
2884 else
2885 inst.instruction |= value;
2887 /* lw rD, [rA, simm15] */
2888 if ((inst.instruction & 0x3e000000) == 0x20000000)
2890 /* Both rD and rA are in [r0 - r15]. */
2891 if ((((inst.instruction >> 15) & 0x10) == 0)
2892 && (((inst.instruction >> 20) & 0x10) == 0))
2894 /* simm15 = 0, lw -> lw!. */
2895 if ((inst.instruction & 0x7fff) == 0)
2897 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2898 | (((inst.instruction >> 20) & 0xf) << 8);
2899 inst.relax_size = 2;
2901 /* rA = r2, lw -> lwp!. */
2902 else if ((((inst.instruction >> 15) & 0xf) == 2)
2903 && ((inst.instruction & 0x3) == 0)
2904 && ((inst.instruction & 0x7fff) < 128))
2906 inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
2907 | (((inst.instruction & 0x7fff) >> 2) << 3);
2908 inst.relax_size = 2;
2910 else
2912 inst.relax_inst = 0x8000;
2915 else
2917 inst.relax_inst = 0x8000;
2920 /* sw rD, [rA, simm15] */
2921 else if ((inst.instruction & 0x3e000000) == 0x28000000)
2923 /* Both rD and rA are in [r0 - r15]. */
2924 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2926 /* simm15 = 0, sw -> sw!. */
2927 if ((inst.instruction & 0x7fff) == 0)
2929 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2930 | (((inst.instruction >> 20) & 0xf) << 8);
2931 inst.relax_size = 2;
2933 /* rA = r2, sw -> swp!. */
2934 else if ((((inst.instruction >> 15) & 0xf) == 2)
2935 && ((inst.instruction & 0x3) == 0)
2936 && ((inst.instruction & 0x7fff) < 128))
2938 inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
2939 | (((inst.instruction & 0x7fff) >> 2) << 3);
2940 inst.relax_size = 2;
2942 else
2944 inst.relax_inst = 0x8000;
2947 else
2949 inst.relax_inst = 0x8000;
2952 /* sw rD, [rA, simm15]+ sw pre. */
2953 else if ((inst.instruction & 0x3e000007) == 0x06000004)
2955 /* rA is in [r0 - r7], and simm15 = -4. */
2956 if ((((inst.instruction >> 15) & 0x18) == 0)
2957 && (((inst.instruction >> 3) & 0xfff) == 0xffc))
2959 /* sw -> pushhi!. */
2960 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2962 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
2963 | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
2964 inst.relax_size = 2;
2966 /* sw -> push!. */
2967 else
2969 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
2970 | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
2971 inst.relax_size = 2;
2974 else
2976 inst.relax_inst = 0x8000;
2979 /* lh rD, [rA, simm15] */
2980 else if ((inst.instruction & 0x3e000000) == 0x22000000)
2982 /* Both rD and rA are in [r0 - r15]. */
2983 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2985 /* simm15 = 0, lh -> lh!. */
2986 if ((inst.instruction & 0x7fff) == 0)
2988 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2989 | (((inst.instruction >> 20) & 0xf) << 8);
2990 inst.relax_size = 2;
2992 /* rA = r2, lh -> lhp!. */
2993 else if ((((inst.instruction >> 15) & 0xf) == 2)
2994 && ((inst.instruction & 0x1) == 0)
2995 && ((inst.instruction & 0x7fff) < 64))
2997 inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
2998 | (((inst.instruction & 0x7fff) >> 1) << 3);
2999 inst.relax_size = 2;
3001 else
3003 inst.relax_inst = 0x8000;
3006 else
3008 inst.relax_inst = 0x8000;
3011 /* sh rD, [rA, simm15] */
3012 else if ((inst.instruction & 0x3e000000) == 0x2a000000)
3014 /* Both rD and rA are in [r0 - r15]. */
3015 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3017 /* simm15 = 0, sh -> sh!. */
3018 if ((inst.instruction & 0x7fff) == 0)
3020 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3021 | (((inst.instruction >> 20) & 0xf) << 8);
3022 inst.relax_size = 2;
3024 /* rA = r2, sh -> shp!. */
3025 else if ((((inst.instruction >> 15) & 0xf) == 2)
3026 && ((inst.instruction & 0x1) == 0)
3027 && ((inst.instruction & 0x7fff) < 64))
3029 inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
3030 | (((inst.instruction & 0x7fff) >> 1) << 3);
3031 inst.relax_size = 2;
3033 else
3035 inst.relax_inst = 0x8000;
3038 else
3040 inst.relax_inst = 0x8000;
3043 /* lbu rD, [rA, simm15] */
3044 else if ((inst.instruction & 0x3e000000) == 0x2c000000)
3046 /* Both rD and rA are in [r0 - r15]. */
3047 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3049 /* simm15 = 0, lbu -> lbu!. */
3050 if ((inst.instruction & 0x7fff) == 0)
3052 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3053 | (((inst.instruction >> 20) & 0xf) << 8);
3054 inst.relax_size = 2;
3056 /* rA = r2, lbu -> lbup!. */
3057 else if ((((inst.instruction >> 15) & 0xf) == 2)
3058 && ((inst.instruction & 0x7fff) < 32))
3060 inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
3061 | ((inst.instruction & 0x7fff) << 3);
3062 inst.relax_size = 2;
3064 else
3066 inst.relax_inst = 0x8000;
3069 else
3071 inst.relax_inst = 0x8000;
3074 /* sb rD, [rA, simm15] */
3075 else if ((inst.instruction & 0x3e000000) == 0x2e000000)
3077 /* Both rD and rA are in [r0 - r15]. */
3078 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3080 /* simm15 = 0, sb -> sb!. */
3081 if ((inst.instruction & 0x7fff) == 0)
3083 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3084 | (((inst.instruction >> 20) & 0xf) << 8);
3085 inst.relax_size = 2;
3087 /* rA = r2, sb -> sb!. */
3088 else if ((((inst.instruction >> 15) & 0xf) == 2)
3089 && ((inst.instruction & 0x7fff) < 32))
3091 inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
3092 | ((inst.instruction & 0x7fff) << 3);
3093 inst.relax_size = 2;
3095 else
3097 inst.relax_inst = 0x8000;
3100 else
3102 inst.relax_inst = 0x8000;
3105 else
3107 inst.relax_inst = 0x8000;
3110 return;
3112 else
3114 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3115 inst.reloc.pc_rel = 0;
3119 else
3121 inst.error = BAD_ARGS;
3125 /* Handle cache. */
3127 static void
3128 do_cache (char *str)
3130 skip_whitespace (str);
3132 if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3134 return;
3136 else
3138 int cache_op;
3140 cache_op = (inst.instruction >> 20) & 0x1F;
3141 sprintf (inst.name, "cache %d", cache_op);
3144 if (*str == '[')
3146 str++;
3147 skip_whitespace (str);
3149 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3150 return;
3152 skip_whitespace (str);
3154 /* cache op, [rA] */
3155 if (skip_past_comma (&str) == (int) FAIL)
3157 SET_INSN_ERROR (NULL);
3158 if (*str != ']')
3160 inst.error = _("missing ]");
3161 return;
3163 str++;
3165 /* cache op, [rA, simm15] */
3166 else
3168 if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
3170 return;
3173 skip_whitespace (str);
3174 if (*str++ != ']')
3176 inst.error = _("missing ]");
3177 return;
3181 if (end_of_line (str) == (int) FAIL)
3182 return;
3184 else
3186 inst.error = BAD_ARGS;
3190 static void
3191 do_crdcrscrsimm5 (char *str)
3193 char *strbak;
3195 strbak = str;
3196 skip_whitespace (str);
3198 if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
3199 || skip_past_comma (&str) == (int) FAIL
3200 || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
3201 || skip_past_comma (&str) == (int) FAIL
3202 || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
3203 || skip_past_comma (&str) == (int) FAIL)
3205 str = strbak;
3206 /* cop1 cop_code20. */
3207 if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
3208 return;
3210 else
3212 if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
3213 return;
3216 end_of_line (str);
3219 /* Handle ldc/stc. */
3220 static void
3221 do_ldst_cop (char *str)
3223 skip_whitespace (str);
3225 if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
3226 || (skip_past_comma (&str) == (int) FAIL))
3227 return;
3229 if (*str == '[')
3231 str++;
3232 skip_whitespace (str);
3234 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3235 return;
3237 skip_whitespace (str);
3239 if (*str++ != ']')
3241 if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
3242 return;
3244 skip_whitespace (str);
3245 if (*str++ != ']')
3247 inst.error = _("missing ]");
3248 return;
3252 end_of_line (str);
3254 else
3255 inst.error = BAD_ARGS;
3258 static void
3259 do16_ldst_insn (char *str)
3261 skip_whitespace (str);
3263 if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3264 return;
3266 if (*str == '[')
3268 int reg;
3270 str++;
3271 skip_whitespace (str);
3273 if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
3274 return;
3276 skip_whitespace (str);
3277 if (*str++ == ']')
3279 if (end_of_line (str) == (int) FAIL)
3280 return;
3281 else
3283 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3284 | (((inst.instruction >> 4) & 0xf) << 15);
3285 inst.relax_size = 4;
3288 else
3290 inst.error = _("missing ]");
3293 else
3295 inst.error = BAD_ARGS;
3299 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3300 static void
3301 do16_ldst_imm_insn (char *str)
3303 char data_exp[MAX_LITERAL_POOL_SIZE];
3304 int reg_rd;
3305 char *dataptr = NULL, *pp = NULL;
3306 int cnt = 0;
3307 int assign_data = (int) FAIL;
3308 unsigned int ldst_func;
3310 skip_whitespace (str);
3312 if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
3313 || (skip_past_comma (&str) == (int) FAIL))
3314 return;
3316 skip_whitespace (str);
3317 dataptr = str;
3319 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
3321 data_exp[cnt] = *dataptr;
3322 dataptr++;
3323 cnt++;
3326 data_exp[cnt] = '\0';
3327 pp = &data_exp[0];
3329 str = dataptr;
3331 ldst_func = inst.instruction & LDST16_RI_MASK;
3332 if (ldst_func == N16_LIU)
3333 assign_data = exp_ldst_offset (&pp, 0, _IMM8);
3334 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3335 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3336 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3337 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3338 else
3339 assign_data = exp_ldst_offset (&pp, 3, _IMM5);
3341 if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
3342 return;
3343 else
3345 if ((inst.instruction & 0x7000) == N16_LIU)
3347 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
3348 | ((inst.instruction & 0xff) << 1);
3350 else if (((inst.instruction & 0x7007) == N16_LHP)
3351 || ((inst.instruction & 0x7007) == N16_SHP))
3353 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3354 | (((inst.instruction >> 3) & 0x1f) << 1);
3356 else if (((inst.instruction & 0x7007) == N16_LWP)
3357 || ((inst.instruction & 0x7007) == N16_SWP))
3359 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3360 | (((inst.instruction >> 3) & 0x1f) << 2);
3362 else if (((inst.instruction & 0x7007) == N16_LBUP)
3363 || ((inst.instruction & 0x7007) == N16_SBP))
3365 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3366 | (((inst.instruction >> 3) & 0x1f));
3369 inst.relax_size = 4;
3373 static void
3374 do16_push_pop (char *str)
3376 int reg_rd;
3377 int H_bit_mask = 0;
3379 skip_whitespace (str);
3380 if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
3381 || (skip_past_comma (&str) == (int) FAIL))
3382 return;
3384 if (reg_rd >= 16)
3385 H_bit_mask = 1;
3387 /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3388 inst.instruction &= ~(1 << 12);
3390 inst.instruction |= H_bit_mask << 7;
3392 if (*str == '[')
3394 int reg;
3396 str++;
3397 skip_whitespace (str);
3398 if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
3399 return;
3400 else if (reg > 7)
3402 if (!inst.error)
3403 inst.error = _("base register nums are over 3 bit");
3405 return;
3408 skip_whitespace (str);
3409 if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
3411 if (!inst.error)
3412 inst.error = _("missing ]");
3414 return;
3417 /* pop! */
3418 if ((inst.instruction & 0xf) == 0xa)
3420 if (H_bit_mask)
3422 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3423 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3425 else
3427 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3428 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3431 /* push! */
3432 else
3434 if (H_bit_mask)
3436 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3437 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3439 else
3441 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3442 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3445 inst.relax_size = 4;
3447 else
3449 inst.error = BAD_ARGS;
3453 /* Handle lcb/lcw/lce/scb/scw/sce. */
3454 static void
3455 do_ldst_unalign (char *str)
3457 int conflict_reg;
3459 if (university_version == 1)
3461 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3462 return;
3465 skip_whitespace (str);
3467 /* lcb/scb [rA]+. */
3468 if (*str == '[')
3470 str++;
3471 skip_whitespace (str);
3473 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3474 return;
3476 if (*str++ == ']')
3478 if (*str++ != '+')
3480 inst.error = _("missing +");
3481 return;
3484 else
3486 inst.error = _("missing ]");
3487 return;
3490 if (end_of_line (str) == (int) FAIL)
3491 return;
3493 /* lcw/lce/scb/sce rD, [rA]+. */
3494 else
3496 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
3497 || (skip_past_comma (&str) == (int) FAIL))
3499 return;
3502 skip_whitespace (str);
3503 if (*str++ == '[')
3505 int reg;
3507 skip_whitespace (str);
3508 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3510 return;
3513 /* Conflicts can occur on stores as well as loads. */
3514 conflict_reg = (conflict_reg == reg);
3515 skip_whitespace (str);
3516 if (*str++ == ']')
3518 unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
3520 if (*str++ == '+')
3522 if (conflict_reg)
3524 as_warn (_("%s register same as write-back base"),
3525 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3526 ? _("destination") : _("source")));
3529 else
3531 inst.error = _("missing +");
3532 return;
3535 if (end_of_line (str) == (int) FAIL)
3536 return;
3538 else
3540 inst.error = _("missing ]");
3541 return;
3544 else
3546 inst.error = BAD_ARGS;
3547 return;
3552 /* Handle alw/asw. */
3553 static void
3554 do_ldst_atomic (char *str)
3556 if (university_version == 1)
3558 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3559 return;
3562 skip_whitespace (str);
3564 if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3565 || (skip_past_comma (&str) == (int) FAIL))
3567 return;
3569 else
3572 skip_whitespace (str);
3573 if (*str++ == '[')
3575 int reg;
3577 skip_whitespace (str);
3578 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3580 return;
3583 skip_whitespace (str);
3584 if (*str++ != ']')
3586 inst.error = _("missing ]");
3587 return;
3590 end_of_line (str);
3592 else
3593 inst.error = BAD_ARGS;
3597 static void
3598 build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3599 struct score_it var_insts[RELAX_INST_NUM], int var_num,
3600 symbolS *add_symbol)
3602 int i;
3603 char *p;
3604 fixS *fixp = NULL;
3605 fixS *head_fixp = NULL;
3606 long where;
3607 struct score_it inst_main;
3609 memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
3611 /* Adjust instruction opcode and to be relaxed instruction opcode. */
3612 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
3613 inst_main.type = Insn_PIC;
3615 for (i = 0; i < var_num; i++)
3617 inst_main.relax_size += var_insts[i].size;
3618 var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
3619 GET_INSN_CLASS (var_insts[i].type));
3622 /* Check data dependency. */
3623 handle_dependency (&inst_main);
3625 /* Start a new frag if frag_now is not empty. */
3626 if (frag_now_fix () != 0)
3628 if (!frag_now->tc_frag_data.is_insn)
3630 frag_wane (frag_now);
3632 frag_new (0);
3634 frag_grow (20);
3636 /* Write fr_fix part. */
3637 p = frag_more (inst_main.size);
3638 md_number_to_chars (p, inst_main.instruction, inst_main.size);
3640 if (inst_main.reloc.type != BFD_RELOC_NONE)
3642 fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
3643 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
3646 head_fixp = xmalloc (sizeof (fixS *));
3647 frag_now->tc_frag_data.fixp = head_fixp;
3649 if (fixp)
3651 head_fixp->fx_next = fixp;
3652 head_fixp = head_fixp->fx_next;
3655 #ifdef OBJ_ELF
3656 dwarf2_emit_insn (inst_main.size);
3657 #endif
3659 where = p - frag_now->fr_literal + inst_main.size;
3660 for (i = 0; i < var_num; i++)
3662 if (i > 0)
3663 where += var_insts[i - 1].size;
3665 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
3667 fixp = fix_new_score (frag_now, where, var_insts[i].size,
3668 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
3669 var_insts[i].reloc.type);
3670 if (fixp)
3672 head_fixp->fx_next = fixp;
3673 head_fixp = head_fixp->fx_next;
3678 head_fixp = frag_now->tc_frag_data.fixp;
3679 frag_now->tc_frag_data.fixp = head_fixp->fx_next;
3680 free (head_fixp);
3682 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
3683 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
3684 0, inst_main.size, 0), add_symbol, 0, NULL);
3686 /* Write fr_var part.
3687 no calling gen_insn_frag, no fixS will be generated. */
3688 for (i = 0; i < var_num; i++)
3690 md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
3691 p += var_insts[i].size;
3693 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3694 inst.bwarn = -1;
3697 /* Build a relax frag for la instruction when generating PIC,
3698 external symbol first and local symbol second. */
3700 static void
3701 build_la_pic (int reg_rd, expressionS exp)
3703 symbolS *add_symbol = exp.X_add_symbol;
3704 offsetT add_number = exp.X_add_number;
3705 struct score_it fix_insts[RELAX_INST_NUM];
3706 struct score_it var_insts[RELAX_INST_NUM];
3707 int fix_num = 0;
3708 int var_num = 0;
3709 char tmp[MAX_LITERAL_POOL_SIZE];
3710 int r1_bak;
3712 r1_bak = nor1;
3713 nor1 = 0;
3715 if (add_number == 0)
3717 fix_num = 1;
3718 var_num = 2;
3720 /* Insn 1 and Insn 2 */
3721 /* Fix part
3722 For an external symbol: lw rD, <sym>($gp)
3723 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
3724 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3725 if (append_insn (tmp, FALSE) == (int) FAIL)
3726 return;
3728 if (reg_rd == PIC_CALL_REG)
3729 inst.reloc.type = BFD_RELOC_SCORE_CALL15;
3730 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3732 /* Var part
3733 For a local symbol :
3734 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
3735 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
3736 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
3737 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3738 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3739 if (append_insn (tmp, FALSE) == (int) FAIL)
3740 return;
3742 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
3743 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3745 else if (add_number >= -0x8000 && add_number <= 0x7fff)
3747 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3748 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3749 if (append_insn (tmp, TRUE) == (int) FAIL)
3750 return;
3752 /* Insn 2 */
3753 fix_num = 1;
3754 var_num = 1;
3755 /* Fix part
3756 For an external symbol: addi rD, <constant> */
3757 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
3758 if (append_insn (tmp, FALSE) == (int) FAIL)
3759 return;
3761 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3763 /* Var part
3764 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
3765 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
3766 if (append_insn (tmp, FALSE) == (int) FAIL)
3767 return;
3769 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3770 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3772 else
3774 int hi = (add_number >> 16) & 0x0000FFFF;
3775 int lo = add_number & 0x0000FFFF;
3777 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3778 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3779 if (append_insn (tmp, TRUE) == (int) FAIL)
3780 return;
3782 /* Insn 2 */
3783 fix_num = 1;
3784 var_num = 1;
3785 /* Fix part
3786 For an external symbol: ldis r1, HI%<constant> */
3787 sprintf (tmp, "ldis %s, %d", "r1", hi);
3788 if (append_insn (tmp, FALSE) == (int) FAIL)
3789 return;
3791 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3793 /* Var part
3794 For a local symbol: ldis r1, HI%<constant>
3795 but, if lo is outof 16 bit, make hi plus 1 */
3796 if ((lo < -0x8000) || (lo > 0x7fff))
3798 hi += 1;
3800 sprintf (tmp, "ldis_pic %s, %d", "r1", hi);
3801 if (append_insn (tmp, FALSE) == (int) FAIL)
3802 return;
3804 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3805 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3807 /* Insn 3 */
3808 fix_num = 1;
3809 var_num = 1;
3810 /* Fix part
3811 For an external symbol: ori r1, LO%<constant> */
3812 sprintf (tmp, "ori %s, %d", "r1", lo);
3813 if (append_insn (tmp, FALSE) == (int) FAIL)
3814 return;
3816 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3818 /* Var part
3819 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
3820 sprintf (tmp, "addi_u_pic %s, %s + %d", "r1", add_symbol->bsym->name, lo);
3821 if (append_insn (tmp, FALSE) == (int) FAIL)
3822 return;
3824 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3825 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3827 /* Insn 4: add rD, rD, r1 */
3828 sprintf (tmp, "add r%d, r%d, %s", reg_rd, reg_rd, "r1");
3829 if (append_insn (tmp, TRUE) == (int) FAIL)
3830 return;
3832 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3833 inst.bwarn = -1;
3836 nor1 = r1_bak;
3839 /* Handle la. */
3840 static void
3841 do_macro_la_rdi32 (char *str)
3843 int reg_rd;
3845 skip_whitespace (str);
3846 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3847 || skip_past_comma (&str) == (int) FAIL)
3849 return;
3851 else
3853 char append_str[MAX_LITERAL_POOL_SIZE];
3854 char *keep_data = str;
3856 /* la rd, simm16. */
3857 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3859 end_of_line (str);
3860 return;
3862 /* la rd, imm32 or la rd, label. */
3863 else
3865 SET_INSN_ERROR (NULL);
3866 str = keep_data;
3867 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3868 || (end_of_line (str) == (int) FAIL))
3870 return;
3872 else
3874 if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
3876 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3877 if (append_insn (append_str, TRUE) == (int) FAIL)
3878 return;
3880 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3881 if (append_insn (append_str, TRUE) == (int) FAIL)
3882 return;
3884 else
3886 assert (inst.reloc.exp.X_add_symbol);
3887 build_la_pic (reg_rd, inst.reloc.exp);
3890 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3891 inst.bwarn = -1;
3897 /* Handle li. */
3898 static void
3899 do_macro_li_rdi32 (char *str){
3901 int reg_rd;
3903 skip_whitespace (str);
3904 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3905 || skip_past_comma (&str) == (int) FAIL)
3907 return;
3909 else
3911 char *keep_data = str;
3913 /* li rd, simm16. */
3914 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3916 end_of_line (str);
3917 return;
3919 /* li rd, imm32. */
3920 else
3922 char append_str[MAX_LITERAL_POOL_SIZE];
3924 str = keep_data;
3926 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3927 || (end_of_line (str) == (int) FAIL))
3929 return;
3931 else if (inst.reloc.exp.X_add_symbol)
3933 inst.error = _("li rd label isn't correct instruction form");
3934 return;
3936 else
3938 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3940 if (append_insn (append_str, TRUE) == (int) FAIL)
3941 return;
3942 else
3944 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3945 if (append_insn (append_str, TRUE) == (int) FAIL)
3946 return;
3948 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3949 inst.bwarn = -1;
3956 /* Handle mul/mulu/div/divu/rem/remu. */
3957 static void
3958 do_macro_mul_rdrsrs (char *str)
3960 int reg_rd;
3961 int reg_rs1;
3962 int reg_rs2;
3963 char *backupstr;
3964 char append_str[MAX_LITERAL_POOL_SIZE];
3966 if (university_version == 1)
3967 as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
3969 strcpy (append_str, str);
3970 backupstr = append_str;
3971 skip_whitespace (backupstr);
3972 if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
3973 || (skip_past_comma (&backupstr) == (int) FAIL)
3974 || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
3976 inst.error = BAD_ARGS;
3977 return;
3980 if (skip_past_comma (&backupstr) == (int) FAIL)
3982 /* rem/remu rA, rB is error format. */
3983 if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
3985 SET_INSN_ERROR (BAD_ARGS);
3987 else
3989 SET_INSN_ERROR (NULL);
3990 do_rsrs (str);
3992 return;
3994 else
3996 SET_INSN_ERROR (NULL);
3997 if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
3998 || (end_of_line (backupstr) == (int) FAIL))
4000 return;
4002 else
4004 char append_str1[MAX_LITERAL_POOL_SIZE];
4006 if (strcmp (inst.name, "rem") == 0)
4008 sprintf (append_str, "%s r%d, r%d", "mul", reg_rs1, reg_rs2);
4009 sprintf (append_str1, "mfceh r%d", reg_rd);
4011 else if (strcmp (inst.name, "remu") == 0)
4013 sprintf (append_str, "%s r%d, r%d", "mulu", reg_rs1, reg_rs2);
4014 sprintf (append_str1, "mfceh r%d", reg_rd);
4016 else
4018 sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
4019 sprintf (append_str1, "mfcel r%d", reg_rd);
4022 /* Output mul/mulu or div/divu or rem/remu. */
4023 if (append_insn (append_str, TRUE) == (int) FAIL)
4024 return;
4026 /* Output mfcel or mfceh. */
4027 if (append_insn (append_str1, TRUE) == (int) FAIL)
4028 return;
4030 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4031 inst.bwarn = -1;
4036 static void
4037 exp_macro_ldst_abs (char *str)
4039 int reg_rd;
4040 char *backupstr, *tmp;
4041 char append_str[MAX_LITERAL_POOL_SIZE];
4042 char verifystr[MAX_LITERAL_POOL_SIZE];
4043 struct score_it inst_backup;
4044 int r1_bak = 0;
4046 r1_bak = nor1;
4047 nor1 = 0;
4048 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4050 strcpy (verifystr, str);
4051 backupstr = verifystr;
4052 skip_whitespace (backupstr);
4053 if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4054 return;
4056 tmp = backupstr;
4057 if (skip_past_comma (&backupstr) == (int) FAIL)
4058 return;
4060 backupstr = tmp;
4061 sprintf (append_str, "li r1 %s", backupstr);
4062 append_insn (append_str, TRUE);
4064 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4065 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4066 do_ldst_insn (append_str);
4068 nor1 = r1_bak;
4071 static int
4072 nopic_need_relax (symbolS * sym, int before_relaxing)
4074 if (sym == NULL)
4075 return 0;
4076 else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
4078 const char *symname;
4079 const char *segname;
4081 /* Find out whether this symbol can be referenced off the $gp
4082 register. It can be if it is smaller than the -G size or if
4083 it is in the .sdata or .sbss section. Certain symbols can
4084 not be referenced off the $gp, although it appears as though
4085 they can. */
4086 symname = S_GET_NAME (sym);
4087 if (symname != (const char *)NULL
4088 && (strcmp (symname, "eprol") == 0
4089 || strcmp (symname, "etext") == 0
4090 || strcmp (symname, "_gp") == 0
4091 || strcmp (symname, "edata") == 0
4092 || strcmp (symname, "_fbss") == 0
4093 || strcmp (symname, "_fdata") == 0
4094 || strcmp (symname, "_ftext") == 0
4095 || strcmp (symname, "end") == 0
4096 || strcmp (symname, GP_DISP_LABEL) == 0))
4098 return 1;
4100 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4101 /* We must defer this decision until after the whole file has been read,
4102 since there might be a .extern after the first use of this symbol. */
4103 || (before_relaxing
4104 && S_GET_VALUE (sym) == 0)
4105 || (S_GET_VALUE (sym) != 0
4106 && S_GET_VALUE (sym) <= g_switch_value)))
4108 return 0;
4111 segname = segment_name (S_GET_SEGMENT (sym));
4112 return (strcmp (segname, ".sdata") != 0
4113 && strcmp (segname, ".sbss") != 0
4114 && strncmp (segname, ".sdata.", 7) != 0
4115 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4117 /* We are not optimizing for the $gp register. */
4118 else
4119 return 1;
4122 /* Build a relax frag for lw instruction when generating PIC,
4123 external symbol first and local symbol second. */
4125 static void
4126 build_lw_pic (int reg_rd, expressionS exp)
4128 symbolS *add_symbol = exp.X_add_symbol;
4129 int add_number = exp.X_add_number;
4130 struct score_it fix_insts[RELAX_INST_NUM];
4131 struct score_it var_insts[RELAX_INST_NUM];
4132 int fix_num = 0;
4133 int var_num = 0;
4134 char tmp[MAX_LITERAL_POOL_SIZE];
4135 int r1_bak;
4137 r1_bak = nor1;
4138 nor1 = 0;
4140 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4142 fix_num = 1;
4143 var_num = 2;
4145 /* Insn 1 and Insn 2 */
4146 /* Fix part
4147 For an external symbol: lw rD, <sym>($gp)
4148 (BFD_RELOC_SCORE_GOT15) */
4149 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4150 if (append_insn (tmp, FALSE) == (int) FAIL)
4151 return;
4153 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4155 /* Var part
4156 For a local symbol :
4157 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4158 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4159 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4160 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4161 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4162 if (append_insn (tmp, FALSE) == (int) FAIL)
4163 return;
4165 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
4166 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4168 /* Insn 2: lw rD, [rD, constant] */
4169 sprintf (tmp, "lw r%d, [r%d, %d]", reg_rd, reg_rd, add_number);
4170 if (append_insn (tmp, TRUE) == (int) FAIL)
4171 return;
4173 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4174 inst.bwarn = -1;
4176 else
4178 int hi = (add_number >> 16) & 0x0000FFFF;
4179 int lo = add_number & 0x0000FFFF;
4181 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4182 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4183 if (append_insn (tmp, TRUE) == (int) FAIL)
4184 return;
4186 /* Insn 2 */
4187 fix_num = 1;
4188 var_num = 1;
4189 /* Fix part
4190 For an external symbol: ldis r1, HI%<constant> */
4191 sprintf (tmp, "ldis %s, %d", "r1", hi);
4192 if (append_insn (tmp, FALSE) == (int) FAIL)
4193 return;
4195 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4197 /* Var part
4198 For a local symbol: ldis r1, HI%<constant>
4199 but, if lo is outof 16 bit, make hi plus 1 */
4200 if ((lo < -0x8000) || (lo > 0x7fff))
4202 hi += 1;
4204 sprintf (tmp, "ldis_pic %s, %d", "r1", hi);
4205 if (append_insn (tmp, FALSE) == (int) FAIL)
4206 return;
4208 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4209 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4211 /* Insn 3 */
4212 fix_num = 1;
4213 var_num = 1;
4214 /* Fix part
4215 For an external symbol: ori r1, LO%<constant> */
4216 sprintf (tmp, "ori %s, %d", "r1", lo);
4217 if (append_insn (tmp, FALSE) == (int) FAIL)
4218 return;
4220 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4222 /* Var part
4223 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4224 sprintf (tmp, "addi_u_pic %s, %s + %d", "r1", add_symbol->bsym->name, lo);
4225 if (append_insn (tmp, FALSE) == (int) FAIL)
4226 return;
4228 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4229 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4231 /* Insn 4: add rD, rD, r1 */
4232 sprintf (tmp, "add r%d, r%d, %s", reg_rd, reg_rd, "r1");
4233 if (append_insn (tmp, TRUE) == (int) FAIL)
4234 return;
4236 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4237 inst.bwarn = -1;
4239 /* Insn 5: lw rD, [rD, 0] */
4240 sprintf (tmp, "lw r%d, [r%d, 0]", reg_rd, reg_rd);
4241 if (append_insn (tmp, TRUE) == (int) FAIL)
4242 return;
4244 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4245 inst.bwarn = -1;
4248 nor1 = r1_bak;
4251 static void
4252 do_macro_ldst_label (char *str)
4254 int i;
4255 int ldst_gp_p = 0;
4256 int reg_rd;
4257 int r1_bak;
4258 char *backup_str;
4259 char *label_str;
4260 char *absolute_value;
4261 char append_str[3][MAX_LITERAL_POOL_SIZE];
4262 char verifystr[MAX_LITERAL_POOL_SIZE];
4263 struct score_it inst_backup;
4264 struct score_it inst_expand[3];
4265 struct score_it inst_main;
4267 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4268 strcpy (verifystr, str);
4269 backup_str = verifystr;
4271 skip_whitespace (backup_str);
4272 if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
4273 return;
4275 if (skip_past_comma (&backup_str) == (int) FAIL)
4276 return;
4278 label_str = backup_str;
4280 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4281 if (*backup_str == '[')
4283 do_ldst_insn (str);
4284 return;
4287 /* Ld/st rD, imm. */
4288 absolute_value = backup_str;
4289 if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
4290 || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE) == (int) FAIL)
4291 || (end_of_line (backup_str) == (int) FAIL))
4293 return;
4295 else
4297 if (inst.reloc.exp.X_add_symbol == 0)
4299 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4300 exp_macro_ldst_abs (str);
4301 return;
4305 /* Ld/st rD, label. */
4306 backup_str = absolute_value;
4307 if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
4308 || (end_of_line (backup_str) == (int) FAIL))
4310 return;
4312 else
4314 if (inst.reloc.exp.X_add_symbol == 0)
4316 if (!inst.error)
4317 inst.error = BAD_ARGS;
4319 return;
4322 if (score_pic == PIC)
4324 build_lw_pic (reg_rd, inst.reloc.exp);
4325 return;
4327 else
4329 if ((inst.reloc.exp.X_add_number <= 0x3fff)
4330 && (inst.reloc.exp.X_add_number >= -0x4000)
4331 && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
4333 int ldst_idx = 0;
4335 /* Assign the real opcode. */
4336 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4337 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4338 inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
4339 inst.instruction |= reg_rd << 20;
4340 inst.instruction |= GP << 15;
4341 inst.relax_inst = 0x8000;
4342 inst.relax_size = 0;
4343 ldst_gp_p = 1;
4348 /* Backup inst. */
4349 memcpy (&inst_main, &inst, sizeof (struct score_it));
4350 r1_bak = nor1;
4351 nor1 = 0;
4353 /* Determine which instructions should be output. */
4354 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4355 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4356 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4358 /* Generate three instructions.
4359 la r1, label
4360 ld/st rd, [r1, 0] */
4361 for (i = 0; i < 3; i++)
4363 if (append_insn (append_str[i], FALSE) == (int) FAIL)
4364 return;
4366 memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
4369 if (ldst_gp_p)
4371 char *p;
4373 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4374 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
4375 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4376 inst_main.type = Insn_GP;
4378 for (i = 0; i < 3; i++)
4379 inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
4380 , GET_INSN_CLASS (inst_expand[i].type));
4382 /* Check data dependency. */
4383 handle_dependency (&inst_main);
4385 /* Start a new frag if frag_now is not empty. */
4386 if (frag_now_fix () != 0)
4388 if (!frag_now->tc_frag_data.is_insn)
4389 frag_wane (frag_now);
4391 frag_new (0);
4393 frag_grow (20);
4395 /* Write fr_fix part. */
4396 p = frag_more (inst_main.size);
4397 md_number_to_chars (p, inst_main.instruction, inst_main.size);
4399 if (inst_main.reloc.type != BFD_RELOC_NONE)
4401 fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4402 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4405 #ifdef OBJ_ELF
4406 dwarf2_emit_insn (inst_main.size);
4407 #endif
4409 /* GP instruction can not do optimization, only can do relax between
4410 1 instruction and 3 instructions. */
4411 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
4412 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4413 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4415 /* Write fr_var part.
4416 no calling gen_insn_frag, no fixS will be generated. */
4417 md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4418 p += inst_expand[0].size;
4419 md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4420 p += inst_expand[1].size;
4421 md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4423 else
4425 gen_insn_frag (&inst_expand[0], NULL);
4426 gen_insn_frag (&inst_expand[1], NULL);
4427 gen_insn_frag (&inst_expand[2], NULL);
4429 nor1 = r1_bak;
4431 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4432 inst.bwarn = -1;
4435 static void
4436 do_lw_pic (char *str)
4438 int reg_rd;
4440 skip_whitespace (str);
4441 if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
4442 || (skip_past_comma (&str) == (int) FAIL)
4443 || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
4444 || (end_of_line (str) == (int) FAIL))
4446 return;
4448 else
4450 if (inst.reloc.exp.X_add_symbol == 0)
4452 if (!inst.error)
4453 inst.error = BAD_ARGS;
4455 return;
4458 inst.instruction |= GP << 15;
4459 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4463 static void
4464 do_empty (char *str)
4466 str = str;
4467 if (university_version == 1)
4469 if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
4470 || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
4471 || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
4472 || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
4474 inst.error = ERR_FOR_SCORE5U_MMU;
4475 return;
4478 if (end_of_line (str) == (int) FAIL)
4479 return;
4481 if (inst.relax_inst != 0x8000)
4483 if (inst.type == NO_OPD)
4485 inst.relax_size = 2;
4487 else
4489 inst.relax_size = 4;
4494 static void
4495 do_jump (char *str)
4497 char *save_in;
4498 char err_msg[100];
4500 skip_whitespace (str);
4501 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4502 || end_of_line (str) == (int) FAIL)
4503 return;
4505 if (inst.reloc.exp.X_add_symbol == 0)
4507 inst.error = _("lacking label ");
4508 return;
4511 if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4512 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4514 sprintf (err_msg, "invalid constant: 25 bit expression not in range -2^24..2^24");
4515 inst.error = _(err_msg);
4516 return;
4519 save_in = input_line_pointer;
4520 input_line_pointer = str;
4521 inst.reloc.type = BFD_RELOC_SCORE_JMP;
4522 inst.reloc.pc_rel = 1;
4523 input_line_pointer = save_in;
4526 static void
4527 do16_jump (char *str)
4529 skip_whitespace (str);
4530 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4531 || end_of_line (str) == (int) FAIL)
4533 return;
4535 else if (inst.reloc.exp.X_add_symbol == 0)
4537 inst.error = _("lacking label ");
4538 return;
4540 else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
4541 && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
4543 inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
4544 return;
4547 inst.reloc.type = BFD_RELOC_SCORE16_JMP;
4548 inst.reloc.pc_rel = 1;
4551 static void
4552 do_branch (char *str)
4554 unsigned long abs_value = 0;
4556 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4557 || end_of_line (str) == (int) FAIL)
4559 return;
4561 else if (inst.reloc.exp.X_add_symbol == 0)
4563 inst.error = _("lacking label ");
4564 return;
4566 else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4567 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4569 inst.error = "invalid constant: 20 bit expression not in range -2^19..2^19";
4570 return;
4573 inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
4574 inst.reloc.pc_rel = 1;
4576 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
4577 inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
4579 /* Take the branch condition code. */
4580 inst.relax_inst = 0x4000 | (((inst.instruction >> 10) & 0xf) << 8);
4582 if ((abs_value & 0xfffffe00) == 0)
4584 inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4585 inst.relax_size = 2;
4587 else
4589 inst.relax_inst = 0x8000;
4592 if (inst.instruction & 1)
4593 inst.relax_inst = 0x8000;
4596 static void
4597 do16_branch (char *str)
4599 if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4600 || end_of_line (str) == (int) FAIL))
4604 else if (inst.reloc.exp.X_add_symbol == 0)
4606 inst.error = _("lacking label");
4608 else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
4609 && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
4611 inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
4613 else
4615 inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
4616 inst.reloc.pc_rel = 1;
4617 inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4621 /* Iterate over the base tables to create the instruction patterns. */
4622 static void
4623 build_score_ops_hsh (void)
4625 unsigned int i;
4626 static struct obstack insn_obstack;
4628 obstack_begin (&insn_obstack, 4000);
4629 for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
4631 const struct asm_opcode *insn = score_insns + i;
4632 unsigned len = strlen (insn->template);
4633 struct asm_opcode *new;
4634 char *template;
4635 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
4636 template = obstack_alloc (&insn_obstack, len + 1);
4638 strcpy (template, insn->template);
4639 new->template = template;
4640 new->parms = insn->parms;
4641 new->value = insn->value;
4642 new->relax_value = insn->relax_value;
4643 new->type = insn->type;
4644 new->bitmask = insn->bitmask;
4645 hash_insert (score_ops_hsh, new->template, (void *) new);
4649 static void
4650 build_dependency_insn_hsh (void)
4652 unsigned int i;
4653 static struct obstack dependency_obstack;
4655 obstack_begin (&dependency_obstack, 4000);
4656 for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
4658 const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
4659 unsigned len = strlen (tmp->insn_name);
4660 struct insn_to_dependency *new;
4662 new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
4663 new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
4665 strcpy (new->insn_name, tmp->insn_name);
4666 new->type = tmp->type;
4667 hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
4671 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4672 for use in the a.out file, and stores them in the array pointed to by buf.
4673 This knows about the endian-ness of the target machine and does
4674 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4675 2 (short) and 4 (long) Floating numbers are put out as a series of
4676 LITTLENUMS (shorts, here at least). */
4678 void
4679 md_number_to_chars (char *buf, valueT val, int n)
4681 if (target_big_endian)
4682 number_to_chars_bigendian (buf, val, n);
4683 else
4684 number_to_chars_littleendian (buf, val, n);
4687 static valueT
4688 md_chars_to_number (char *buf, int n)
4690 valueT result = 0;
4691 unsigned char *where = (unsigned char *)buf;
4693 if (target_big_endian)
4695 while (n--)
4697 result <<= 8;
4698 result |= (*where++ & 255);
4701 else
4703 while (n--)
4705 result <<= 8;
4706 result |= (where[n] & 255);
4710 return result;
4713 /* Turn a string in input_line_pointer into a floating point constant
4714 of type TYPE, and store the appropriate bytes in *LITP. The number
4715 of LITTLENUMS emitted is stored in *SIZEP. An error message is
4716 returned, or NULL on OK.
4718 Note that fp constants aren't represent in the normal way on the ARM.
4719 In big endian mode, things are as expected. However, in little endian
4720 mode fp constants are big-endian word-wise, and little-endian byte-wise
4721 within the words. For example, (double) 1.1 in big endian mode is
4722 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4723 the byte sequence 99 99 f1 3f 9a 99 99 99. */
4725 char *
4726 md_atof (int type, char *litP, int *sizeP)
4728 int prec;
4729 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4730 char *t;
4731 int i;
4733 switch (type)
4735 case 'f':
4736 case 'F':
4737 case 's':
4738 case 'S':
4739 prec = 2;
4740 break;
4741 case 'd':
4742 case 'D':
4743 case 'r':
4744 case 'R':
4745 prec = 4;
4746 break;
4747 case 'x':
4748 case 'X':
4749 case 'p':
4750 case 'P':
4751 prec = 6;
4752 break;
4753 default:
4754 *sizeP = 0;
4755 return _("bad call to MD_ATOF()");
4758 t = atof_ieee (input_line_pointer, type, words);
4759 if (t)
4760 input_line_pointer = t;
4761 *sizeP = prec * 2;
4763 if (target_big_endian)
4765 for (i = 0; i < prec; i++)
4767 md_number_to_chars (litP, (valueT) words[i], 2);
4768 litP += 2;
4771 else
4773 for (i = 0; i < prec; i += 2)
4775 md_number_to_chars (litP, (valueT) words[i + 1], 2);
4776 md_number_to_chars (litP + 2, (valueT) words[i], 2);
4777 litP += 4;
4781 return 0;
4784 /* Return true if the given symbol should be considered local for PIC. */
4786 static bfd_boolean
4787 pic_need_relax (symbolS *sym, asection *segtype)
4789 asection *symsec;
4790 bfd_boolean linkonce;
4792 /* Handle the case of a symbol equated to another symbol. */
4793 while (symbol_equated_reloc_p (sym))
4795 symbolS *n;
4797 /* It's possible to get a loop here in a badly written
4798 program. */
4799 n = symbol_get_value_expression (sym)->X_add_symbol;
4800 if (n == sym)
4801 break;
4802 sym = n;
4805 symsec = S_GET_SEGMENT (sym);
4807 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
4808 linkonce = FALSE;
4809 if (symsec != segtype && ! S_IS_LOCAL (sym))
4811 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
4812 linkonce = TRUE;
4814 /* The GNU toolchain uses an extension for ELF: a section
4815 beginning with the magic string .gnu.linkonce is a linkonce
4816 section. */
4817 if (strncmp (segment_name (symsec), ".gnu.linkonce",
4818 sizeof ".gnu.linkonce" - 1) == 0)
4819 linkonce = TRUE;
4822 /* This must duplicate the test in adjust_reloc_syms. */
4823 return (symsec != &bfd_und_section
4824 && symsec != &bfd_abs_section
4825 && ! bfd_is_com_section (symsec)
4826 && !linkonce
4827 #ifdef OBJ_ELF
4828 /* A global or weak symbol is treated as external. */
4829 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
4830 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
4831 #endif
4835 static int
4836 judge_size_before_relax (fragS * fragp, asection *sec)
4838 int change = 0;
4840 if (score_pic == NO_PIC)
4841 change = nopic_need_relax (fragp->fr_symbol, 0);
4842 else
4843 change = pic_need_relax (fragp->fr_symbol, sec);
4845 if (change == 1)
4847 /* Only at the first time determining whether GP instruction relax should be done,
4848 return the difference between insntruction size and instruction relax size. */
4849 if (fragp->fr_opcode == NULL)
4851 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
4852 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
4853 return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
4857 return 0;
4860 /* In this function, we determine whether GP instruction should do relaxation,
4861 for the label being against was known now.
4862 Doing this here but not in md_relax_frag() can induce iteration times
4863 in stage of doing relax. */
4865 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
4867 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4868 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4869 return judge_size_before_relax (fragp, sec);
4871 return 0;
4874 static int
4875 b32_relax_to_b16 (fragS * fragp)
4877 int grows = 0;
4878 int relaxable_p = 0;
4879 int old;
4880 int new;
4881 int frag_addr = fragp->fr_address + fragp->insn_addr;
4883 addressT symbol_address = 0;
4884 symbolS *s;
4885 offsetT offset;
4886 unsigned long value;
4887 unsigned long abs_value;
4889 /* FIXME : here may be able to modify better .
4890 I don't know how to get the fragp's section ,
4891 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
4892 is different from the symbol's. */
4894 old = RELAX_OLD (fragp->fr_subtype);
4895 new = RELAX_NEW (fragp->fr_subtype);
4896 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4898 s = fragp->fr_symbol;
4899 /* b/bl immediate */
4900 if (s == NULL)
4901 frag_addr = 0;
4902 else
4904 if (s->bsym != 0)
4905 symbol_address = (addressT) s->sy_frag->fr_address;
4908 value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
4910 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
4911 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
4912 if ((offset & 0x80000) == 0x80000)
4913 offset |= 0xfff00000;
4915 abs_value = offset + symbol_address - frag_addr;
4916 if ((abs_value & 0x80000000) == 0x80000000)
4917 abs_value = 0xffffffff - abs_value + 1;
4919 /* Relax branch 32 to branch 16. */
4920 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
4921 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
4923 /* do nothing. */
4925 else
4927 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
4928 fragp->fr_opcode = NULL;
4929 fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
4932 return grows;
4935 /* Main purpose is to determine whether one frag should do relax.
4936 frag->fr_opcode indicates this point. */
4939 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
4941 int grows = 0;
4942 int insn_size;
4943 int insn_relax_size;
4944 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
4945 int relaxable_p = 0;
4946 bfd_boolean word_align_p = FALSE;
4947 fragS *next_fragp;
4949 /* If the instruction address is odd, make it half word align first. */
4950 if ((fragp->fr_address) % 2 != 0)
4952 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
4954 fragp->insn_addr = 1;
4955 grows += 1;
4959 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
4961 /* Get instruction size and relax size after the last relaxation. */
4962 if (fragp->fr_opcode)
4964 insn_size = RELAX_NEW (fragp->fr_subtype);
4965 insn_relax_size = RELAX_OLD (fragp->fr_subtype);
4967 else
4969 insn_size = RELAX_OLD (fragp->fr_subtype);
4970 insn_relax_size = RELAX_NEW (fragp->fr_subtype);
4973 /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine
4974 whether the GP instruction should do relax. */
4975 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4976 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4978 if (!word_align_p)
4980 fragp->insn_addr += 2;
4981 grows += 2;
4984 if (fragp->fr_opcode)
4985 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
4986 else
4987 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
4989 else
4991 if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
4992 b32_relax_to_b16 (fragp);
4994 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4995 next_fragp = fragp->fr_next;
4996 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
4998 next_fragp = next_fragp->fr_next;
5001 if (next_fragp)
5003 int n_insn_size;
5004 int n_relaxable_p = 0;
5006 if (next_fragp->fr_opcode)
5008 n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
5010 else
5012 n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
5015 n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
5017 if (word_align_p)
5019 if (insn_size == 4)
5021 /* 32 -> 16. */
5022 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
5024 grows -= 2;
5025 do_relax_p = 1;
5028 else if (insn_size == 2)
5030 /* 16 -> 32. */
5031 if (relaxable_p && ((n_insn_size == 4) && !n_relaxable_p))
5033 grows += 2;
5034 do_relax_p = 1;
5037 else
5039 abort ();
5042 else
5044 if (insn_size == 4)
5046 /* 32 -> 16. */
5047 if (relaxable_p)
5049 grows -= 2;
5050 do_relax_p = 1;
5052 /* Make the 32 bit insturction word align. */
5053 else
5055 fragp->insn_addr += 2;
5056 grows += 2;
5059 else if (insn_size == 2)
5061 /* Do nothing. */
5063 else
5065 abort ();
5069 else
5071 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
5072 if (word_align_p == FALSE)
5074 if (insn_size % 4 == 0)
5076 /* 32 -> 16. */
5077 if (relaxable_p)
5079 grows -= 2;
5080 do_relax_p = 1;
5082 else
5084 fragp->insn_addr += 2;
5085 grows += 2;
5089 else
5091 /* Do nothing. */
5095 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5096 if (do_relax_p)
5098 if (fragp->fr_opcode)
5100 fragp->fr_opcode = NULL;
5101 /* Guarantee estimate stage is correct. */
5102 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5103 fragp->fr_fix += fragp->insn_addr;
5105 else
5107 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
5108 /* Guarantee estimate stage is correct. */
5109 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5110 fragp->fr_fix += fragp->insn_addr;
5113 else
5115 if (fragp->fr_opcode)
5117 /* Guarantee estimate stage is correct. */
5118 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5119 fragp->fr_fix += fragp->insn_addr;
5121 else
5123 /* Guarantee estimate stage is correct. */
5124 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5125 fragp->fr_fix += fragp->insn_addr;
5130 return grows;
5133 void
5134 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
5136 int old;
5137 int new;
5138 char backup[20];
5139 fixS *fixp;
5141 old = RELAX_OLD (fragp->fr_subtype);
5142 new = RELAX_NEW (fragp->fr_subtype);
5144 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5145 if (fragp->fr_opcode == NULL)
5147 memcpy (backup, fragp->fr_literal, old);
5148 fragp->fr_fix = old;
5150 else
5152 memcpy (backup, fragp->fr_literal + old, new);
5153 fragp->fr_fix = new;
5156 fixp = fragp->tc_frag_data.fixp;
5157 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
5159 if (fragp->fr_opcode)
5160 fixp->fx_done = 1;
5161 fixp = fixp->fx_next;
5163 while (fixp && fixp->fx_frag == fragp)
5165 if (fragp->fr_opcode)
5166 fixp->fx_where -= old + fragp->insn_addr;
5167 else
5168 fixp->fx_done = 1;
5169 fixp = fixp->fx_next;
5172 if (fragp->insn_addr)
5174 md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
5176 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
5177 fragp->fr_fix += fragp->insn_addr;
5180 /* Implementation of md_frag_check.
5181 Called after md_convert_frag(). */
5183 void
5184 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
5186 know (fragp->insn_addr <= RELAX_PAD_BYTE);
5189 bfd_boolean
5190 score_fix_adjustable (fixS * fixP)
5192 if (fixP->fx_addsy == NULL)
5194 return 1;
5196 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
5197 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
5199 return 0;
5201 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5202 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5204 return 0;
5207 return 1;
5210 /* Implementation of TC_VALIDATE_FIX.
5211 Called before md_apply_fix() and after md_convert_frag(). */
5212 void
5213 score_validate_fix (fixS *fixP)
5215 fixP->fx_where += fixP->fx_frag->insn_addr;
5218 long
5219 md_pcrel_from (fixS * fixP)
5221 long retval = 0;
5223 if (fixP->fx_addsy
5224 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
5225 && (fixP->fx_subsy == NULL))
5227 retval = 0;
5229 else
5231 retval = fixP->fx_where + fixP->fx_frag->fr_address;
5234 return retval;
5238 score_force_relocation (struct fix *fixp)
5240 int retval = 0;
5242 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5243 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
5244 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
5245 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
5246 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
5247 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
5249 retval = 1;
5252 return retval;
5255 /* Round up a section size to the appropriate boundary. */
5256 valueT
5257 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5259 int align = bfd_get_section_alignment (stdoutput, segment);
5261 #ifdef OBJ_ELF
5262 /* We don't need to align ELF sections to the full alignment.
5263 However, Irix 5 may prefer that we align them at least to a 16
5264 byte boundary. We don't bother to align the sections if we are
5265 targeted for an embedded system. */
5266 if (strcmp (TARGET_OS, "elf") == 0)
5267 return size;
5268 if (align > 4)
5269 align = 4;
5270 #endif
5272 return ((size + (1 << align) - 1) & (-1 << align));
5275 void
5276 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
5278 offsetT value = *valP;
5279 offsetT abs_value = 0;
5280 offsetT newval;
5281 offsetT content;
5282 unsigned short HI, LO;
5284 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
5286 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5287 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5289 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
5290 fixP->fx_done = 1;
5293 /* If this symbol is in a different section then we need to leave it for
5294 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5295 so we have to undo it's effects here. */
5296 if (fixP->fx_pcrel)
5298 if (fixP->fx_addsy != NULL
5299 && S_IS_DEFINED (fixP->fx_addsy)
5300 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5301 value += md_pcrel_from (fixP);
5304 /* Remember value for emit_reloc. */
5305 fixP->fx_addnumber = value;
5307 switch (fixP->fx_r_type)
5309 case BFD_RELOC_HI16_S:
5310 if (fixP->fx_done)
5311 { /* For la rd, imm32. */
5312 newval = md_chars_to_number (buf, INSN_SIZE);
5313 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
5314 newval |= (HI & 0x3fff) << 1;
5315 newval |= ((HI >> 14) & 0x3) << 16;
5316 md_number_to_chars (buf, newval, INSN_SIZE);
5318 break;
5319 case BFD_RELOC_LO16:
5320 if (fixP->fx_done) /* For la rd, imm32. */
5322 newval = md_chars_to_number (buf, INSN_SIZE);
5323 LO = (value) & 0xffff;
5324 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
5325 newval |= ((LO >> 14) & 0x3) << 16;
5326 md_number_to_chars (buf, newval, INSN_SIZE);
5328 break;
5329 case BFD_RELOC_SCORE_JMP:
5331 content = md_chars_to_number (buf, INSN_SIZE);
5332 value = fixP->fx_offset;
5333 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
5334 md_number_to_chars (buf, content, INSN_SIZE);
5336 break;
5337 case BFD_RELOC_SCORE_BRANCH:
5338 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5339 value = fixP->fx_offset;
5340 else
5341 fixP->fx_done = 1;
5343 content = md_chars_to_number (buf, INSN_SIZE);
5344 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
5346 if ((value & 0x80000000) == 0x80000000)
5347 abs_value = 0xffffffff - value + 1;
5348 if ((abs_value & 0xffffff00) != 0)
5350 as_bad_where (fixP->fx_file, fixP->fx_line,
5351 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5352 return;
5354 content = md_chars_to_number (buf, INSN16_SIZE);
5355 content &= 0xff00;
5356 content = (content & 0xff00) | ((value >> 1) & 0xff);
5357 md_number_to_chars (buf, content, INSN16_SIZE);
5358 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
5359 fixP->fx_size = 2;
5361 else
5363 if ((value & 0x80000000) == 0x80000000)
5364 abs_value = 0xffffffff - value + 1;
5365 if ((abs_value & 0xfff80000) != 0)
5367 as_bad_where (fixP->fx_file, fixP->fx_line,
5368 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5369 return;
5371 content = md_chars_to_number (buf, INSN_SIZE);
5372 content &= 0xfc00fc01;
5373 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5374 md_number_to_chars (buf, content, INSN_SIZE);
5376 break;
5377 case BFD_RELOC_SCORE16_JMP:
5378 content = md_chars_to_number (buf, INSN16_SIZE);
5379 content &= 0xf001;
5380 value = fixP->fx_offset & 0xfff;
5381 content = (content & 0xfc01) | (value & 0xffe);
5382 md_number_to_chars (buf, content, INSN16_SIZE);
5383 break;
5384 case BFD_RELOC_SCORE16_BRANCH:
5385 content = md_chars_to_number (buf, INSN_SIZE);
5386 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
5388 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5389 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5390 value = fixP->fx_offset;
5391 else
5392 fixP->fx_done = 1;
5393 if ((value & 0x80000000) == 0x80000000)
5394 abs_value = 0xffffffff - value + 1;
5395 if ((abs_value & 0xfff80000) != 0)
5397 as_bad_where (fixP->fx_file, fixP->fx_line,
5398 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5399 return;
5401 content = md_chars_to_number (buf, INSN_SIZE);
5402 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5403 md_number_to_chars (buf, content, INSN_SIZE);
5404 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
5405 fixP->fx_size = 4;
5406 break;
5408 else
5410 /* In differnt section. */
5411 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5412 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5413 value = fixP->fx_offset;
5414 else
5415 fixP->fx_done = 1;
5417 if ((value & 0x80000000) == 0x80000000)
5418 abs_value = 0xffffffff - value + 1;
5419 if ((abs_value & 0xffffff00) != 0)
5421 as_bad_where (fixP->fx_file, fixP->fx_line,
5422 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5423 return;
5425 content = md_chars_to_number (buf, INSN16_SIZE);
5426 content = (content & 0xff00) | ((value >> 1) & 0xff);
5427 md_number_to_chars (buf, content, INSN16_SIZE);
5428 break;
5430 case BFD_RELOC_8:
5431 if (fixP->fx_done || fixP->fx_pcrel)
5432 md_number_to_chars (buf, value, 1);
5433 #ifdef OBJ_ELF
5434 else
5436 value = fixP->fx_offset;
5437 md_number_to_chars (buf, value, 1);
5439 #endif
5440 break;
5442 case BFD_RELOC_16:
5443 if (fixP->fx_done || fixP->fx_pcrel)
5444 md_number_to_chars (buf, value, 2);
5445 #ifdef OBJ_ELF
5446 else
5448 value = fixP->fx_offset;
5449 md_number_to_chars (buf, value, 2);
5451 #endif
5452 break;
5453 case BFD_RELOC_RVA:
5454 case BFD_RELOC_32:
5455 if (fixP->fx_done || fixP->fx_pcrel)
5456 md_number_to_chars (buf, value, 4);
5457 #ifdef OBJ_ELF
5458 else
5460 value = fixP->fx_offset;
5461 md_number_to_chars (buf, value, 4);
5463 #endif
5464 break;
5465 case BFD_RELOC_VTABLE_INHERIT:
5466 fixP->fx_done = 0;
5467 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
5468 S_SET_WEAK (fixP->fx_addsy);
5469 break;
5470 case BFD_RELOC_VTABLE_ENTRY:
5471 fixP->fx_done = 0;
5472 break;
5473 case BFD_RELOC_SCORE_GPREL15:
5474 content = md_chars_to_number (buf, INSN_SIZE);
5475 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
5476 fixP->fx_r_type = BFD_RELOC_NONE;
5477 fixP->fx_done = 0;
5478 break;
5479 case BFD_RELOC_SCORE_GOT15:
5480 case BFD_RELOC_SCORE_DUMMY_HI16:
5481 case BFD_RELOC_SCORE_GOT_LO16:
5482 case BFD_RELOC_SCORE_CALL15:
5483 case BFD_RELOC_GPREL32:
5484 break;
5485 case BFD_RELOC_NONE:
5486 default:
5487 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
5491 /* Translate internal representation of relocation info to BFD target format. */
5492 arelent **
5493 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
5495 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
5496 arelent *reloc;
5497 bfd_reloc_code_real_type code;
5498 char *type;
5499 fragS *f;
5500 symbolS *s;
5501 expressionS e;
5503 reloc = retval[0] = xmalloc (sizeof (arelent));
5504 retval[1] = NULL;
5506 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5507 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5508 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5509 reloc->addend = fixp->fx_offset;
5511 /* If this is a variant frag, we may need to adjust the existing
5512 reloc and generate a new one. */
5513 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
5515 /* Update instruction imm bit. */
5516 offsetT newval;
5517 unsigned short off;
5518 char *buf;
5520 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
5521 newval = md_chars_to_number (buf, INSN_SIZE);
5522 off = fixp->fx_offset >> 16;
5523 newval |= (off & 0x3fff) << 1;
5524 newval |= ((off >> 14) & 0x3) << 16;
5525 md_number_to_chars (buf, newval, INSN_SIZE);
5527 buf += INSN_SIZE;
5528 newval = md_chars_to_number (buf, INSN_SIZE);
5529 off = fixp->fx_offset & 0xffff;
5530 newval |= ((off & 0x3fff) << 1);
5531 newval |= (((off >> 14) & 0x3) << 16);
5532 md_number_to_chars (buf, newval, INSN_SIZE);
5534 retval[1] = xmalloc (sizeof (arelent));
5535 retval[2] = NULL;
5536 retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5537 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5538 retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
5540 f = fixp->fx_frag;
5541 s = f->fr_symbol;
5542 e = s->sy_value;
5544 retval[1]->addend = 0;
5545 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
5546 assert (retval[1]->howto != NULL);
5548 fixp->fx_r_type = BFD_RELOC_HI16_S;
5551 code = fixp->fx_r_type;
5552 switch (fixp->fx_r_type)
5554 case BFD_RELOC_32:
5555 if (fixp->fx_pcrel)
5557 code = BFD_RELOC_32_PCREL;
5558 break;
5560 case BFD_RELOC_HI16_S:
5561 case BFD_RELOC_LO16:
5562 case BFD_RELOC_SCORE_JMP:
5563 case BFD_RELOC_SCORE_BRANCH:
5564 case BFD_RELOC_SCORE16_JMP:
5565 case BFD_RELOC_SCORE16_BRANCH:
5566 case BFD_RELOC_VTABLE_ENTRY:
5567 case BFD_RELOC_VTABLE_INHERIT:
5568 case BFD_RELOC_SCORE_GPREL15:
5569 case BFD_RELOC_SCORE_GOT15:
5570 case BFD_RELOC_SCORE_DUMMY_HI16:
5571 case BFD_RELOC_SCORE_GOT_LO16:
5572 case BFD_RELOC_SCORE_CALL15:
5573 case BFD_RELOC_GPREL32:
5574 case BFD_RELOC_NONE:
5575 code = fixp->fx_r_type;
5576 break;
5577 default:
5578 type = _("<unknown>");
5579 as_bad_where (fixp->fx_file, fixp->fx_line,
5580 _("cannot represent %s relocation in this object file format"), type);
5581 return NULL;
5584 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5585 if (reloc->howto == NULL)
5587 as_bad_where (fixp->fx_file, fixp->fx_line,
5588 _("cannot represent %s relocation in this object file format1"),
5589 bfd_get_reloc_code_name (code));
5590 return NULL;
5592 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5593 vtable entry to be used in the relocation's section offset. */
5594 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5595 reloc->address = fixp->fx_offset;
5597 return retval;
5600 void
5601 score_elf_final_processing (void)
5603 if (fix_data_dependency == 1)
5605 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
5607 if (score_pic == PIC)
5609 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
5613 static void
5614 parse_pce_inst (char *insnstr)
5616 char c;
5617 char *p;
5618 char first[MAX_LITERAL_POOL_SIZE];
5619 char second[MAX_LITERAL_POOL_SIZE];
5620 struct score_it pec_part_1;
5622 /* Get first part string of PCE. */
5623 p = strstr (insnstr, "||");
5624 c = *p;
5625 *p = '\0';
5626 sprintf (first, "%s", insnstr);
5628 /* Get second part string of PCE. */
5629 *p = c;
5630 p += 2;
5631 sprintf (second, "%s", p);
5633 parse_16_32_inst (first, FALSE);
5634 if (inst.error)
5635 return;
5637 memcpy (&pec_part_1, &inst, sizeof (inst));
5639 parse_16_32_inst (second, FALSE);
5640 if (inst.error)
5641 return;
5643 if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
5644 || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
5645 || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
5647 inst.error = _("pce instruction error (16 bit || 16 bit)'");
5648 sprintf (inst.str, "%s", insnstr);
5649 return;
5652 if (!inst.error)
5653 gen_insn_frag (&pec_part_1, &inst);
5656 void
5657 md_assemble (char *str)
5659 know (str);
5660 know (strlen (str) < MAX_LITERAL_POOL_SIZE);
5662 memset (&inst, '\0', sizeof (inst));
5663 if (INSN_IS_PCE_P (str))
5664 parse_pce_inst (str);
5665 else
5666 parse_16_32_inst (str, TRUE);
5668 if (inst.error)
5669 as_bad ("%s -- `%s'", inst.error, inst.str);
5672 /* We handle all bad expressions here, so that we can report the faulty
5673 instruction in the error message. */
5674 void
5675 md_operand (expressionS * expr)
5677 if (in_my_get_expression)
5679 expr->X_op = O_illegal;
5680 if (inst.error == NULL)
5682 inst.error = _("bad expression");
5687 const char *md_shortopts = "nO::g::G:";
5689 #ifdef SCORE_BI_ENDIAN
5690 #define OPTION_EB (OPTION_MD_BASE + 0)
5691 #define OPTION_EL (OPTION_MD_BASE + 1)
5692 #else
5693 #if TARGET_BYTES_BIG_ENDIAN
5694 #define OPTION_EB (OPTION_MD_BASE + 0)
5695 #else
5696 #define OPTION_EL (OPTION_MD_BASE + 1)
5697 #endif
5698 #endif
5699 #define OPTION_FIXDD (OPTION_MD_BASE + 2)
5700 #define OPTION_NWARN (OPTION_MD_BASE + 3)
5701 #define OPTION_SCORE5 (OPTION_MD_BASE + 4)
5702 #define OPTION_SCORE5U (OPTION_MD_BASE + 5)
5703 #define OPTION_SCORE7 (OPTION_MD_BASE + 6)
5704 #define OPTION_R1 (OPTION_MD_BASE + 7)
5705 #define OPTION_O0 (OPTION_MD_BASE + 8)
5706 #define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
5707 #define OPTION_PIC (OPTION_MD_BASE + 10)
5709 struct option md_longopts[] =
5711 #ifdef OPTION_EB
5712 {"EB" , no_argument, NULL, OPTION_EB},
5713 #endif
5714 #ifdef OPTION_EL
5715 {"EL" , no_argument, NULL, OPTION_EL},
5716 #endif
5717 {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
5718 {"NWARN" , no_argument, NULL, OPTION_NWARN},
5719 {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
5720 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
5721 {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
5722 {"USE_R1" , no_argument, NULL, OPTION_R1},
5723 {"O0" , no_argument, NULL, OPTION_O0},
5724 {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
5725 {"KPIC" , no_argument, NULL, OPTION_PIC},
5726 {NULL , no_argument, NULL, 0}
5729 size_t md_longopts_size = sizeof (md_longopts);
5732 md_parse_option (int c, char *arg)
5734 switch (c)
5736 #ifdef OPTION_EB
5737 case OPTION_EB:
5738 target_big_endian = 1;
5739 break;
5740 #endif
5741 #ifdef OPTION_EL
5742 case OPTION_EL:
5743 target_big_endian = 0;
5744 break;
5745 #endif
5746 case OPTION_FIXDD:
5747 fix_data_dependency = 1;
5748 break;
5749 case OPTION_NWARN:
5750 warn_fix_data_dependency = 0;
5751 break;
5752 case OPTION_SCORE5:
5753 score7 = 0;
5754 university_version = 0;
5755 vector_size = SCORE5_PIPELINE;
5756 break;
5757 case OPTION_SCORE5U:
5758 score7 = 0;
5759 university_version = 1;
5760 vector_size = SCORE5_PIPELINE;
5761 break;
5762 case OPTION_SCORE7:
5763 score7 = 1;
5764 university_version = 0;
5765 vector_size = SCORE7_PIPELINE;
5766 break;
5767 case OPTION_R1:
5768 nor1 = 0;
5769 break;
5770 case 'G':
5771 g_switch_value = atoi (arg);
5772 break;
5773 case OPTION_O0:
5774 g_opt = 0;
5775 break;
5776 case OPTION_SCORE_VERSION:
5777 printf (_("Sunplus-v2-0-0-20060510\n"));
5778 break;
5779 case OPTION_PIC:
5780 score_pic = PIC;
5781 g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */
5782 break;
5783 default:
5784 /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */
5785 return 0;
5787 return 1;
5790 void
5791 md_show_usage (FILE * fp)
5793 fprintf (fp, _(" Score-specific assembler options:\n"));
5794 #ifdef OPTION_EB
5795 fprintf (fp, _("\
5796 -EB\t\tassemble code for a big-endian cpu\n"));
5797 #endif
5799 #ifdef OPTION_EL
5800 fprintf (fp, _("\
5801 -EL\t\tassemble code for a little-endian cpu\n"));
5802 #endif
5804 fprintf (fp, _("\
5805 -FIXDD\t\tassemble code for fix data dependency\n"));
5806 fprintf (fp, _("\
5807 -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
5808 fprintf (fp, _("\
5809 -SCORE5\t\tassemble code for target is SCORE5\n"));
5810 fprintf (fp, _("\
5811 -SCORE5U\tassemble code for target is SCORE5U\n"));
5812 fprintf (fp, _("\
5813 -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
5814 fprintf (fp, _("\
5815 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
5816 fprintf (fp, _("\
5817 -KPIC\t\tassemble code for PIC\n"));
5818 fprintf (fp, _("\
5819 -O0\t\tassembler will not perform any optimizations\n"));
5820 fprintf (fp, _("\
5821 -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
5822 fprintf (fp, _("\
5823 -V \t\tSunplus release version \n"));
5827 /* Pesudo handling functions. */
5829 /* If we change section we must dump the literal pool first. */
5830 static void
5831 s_score_bss (int ignore ATTRIBUTE_UNUSED)
5833 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5834 demand_empty_rest_of_line ();
5837 static void
5838 s_score_text (int ignore)
5840 obj_elf_text (ignore);
5841 record_alignment (now_seg, 2);
5844 static void
5845 score_s_section (int ignore)
5847 obj_elf_section (ignore);
5848 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5849 record_alignment (now_seg, 2);
5853 static void
5854 s_change_sec (int sec)
5856 segT seg;
5858 #ifdef OBJ_ELF
5859 /* The ELF backend needs to know that we are changing sections, so
5860 that .previous works correctly. We could do something like check
5861 for an obj_section_change_hook macro, but that might be confusing
5862 as it would not be appropriate to use it in the section changing
5863 functions in read.c, since obj-elf.c intercepts those. FIXME:
5864 This should be cleaner, somehow. */
5865 obj_elf_section_change_hook ();
5866 #endif
5867 switch (sec)
5869 case 'r':
5870 seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5871 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5872 if (strcmp (TARGET_OS, "elf") != 0)
5873 record_alignment (seg, 4);
5874 demand_empty_rest_of_line ();
5875 break;
5876 case 's':
5877 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5878 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5879 if (strcmp (TARGET_OS, "elf") != 0)
5880 record_alignment (seg, 4);
5881 demand_empty_rest_of_line ();
5882 break;
5886 static void
5887 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5889 long mask, off;
5891 if (cur_proc_ptr == (procS *) NULL)
5893 as_warn (_(".mask outside of .ent"));
5894 demand_empty_rest_of_line ();
5895 return;
5897 if (get_absolute_expression_and_terminator (&mask) != ',')
5899 as_warn (_("Bad .mask directive"));
5900 --input_line_pointer;
5901 demand_empty_rest_of_line ();
5902 return;
5904 off = get_absolute_expression ();
5905 cur_proc_ptr->reg_mask = mask;
5906 cur_proc_ptr->reg_offset = off;
5907 demand_empty_rest_of_line ();
5910 static symbolS *
5911 get_symbol (void)
5913 int c;
5914 char *name;
5915 symbolS *p;
5917 name = input_line_pointer;
5918 c = get_symbol_end ();
5919 p = (symbolS *) symbol_find_or_make (name);
5920 *input_line_pointer = c;
5921 return p;
5924 static long
5925 get_number (void)
5927 int negative = 0;
5928 long val = 0;
5930 if (*input_line_pointer == '-')
5932 ++input_line_pointer;
5933 negative = 1;
5935 if (!ISDIGIT (*input_line_pointer))
5936 as_bad (_("expected simple number"));
5937 if (input_line_pointer[0] == '0')
5939 if (input_line_pointer[1] == 'x')
5941 input_line_pointer += 2;
5942 while (ISXDIGIT (*input_line_pointer))
5944 val <<= 4;
5945 val |= hex_value (*input_line_pointer++);
5947 return negative ? -val : val;
5949 else
5951 ++input_line_pointer;
5952 while (ISDIGIT (*input_line_pointer))
5954 val <<= 3;
5955 val |= *input_line_pointer++ - '0';
5957 return negative ? -val : val;
5960 if (!ISDIGIT (*input_line_pointer))
5962 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5963 as_warn (_("invalid number"));
5964 return -1;
5966 while (ISDIGIT (*input_line_pointer))
5968 val *= 10;
5969 val += *input_line_pointer++ - '0';
5971 return negative ? -val : val;
5974 /* The .aent and .ent directives. */
5976 static void
5977 s_score_ent (int aent)
5979 symbolS *symbolP;
5980 int maybe_text;
5982 symbolP = get_symbol ();
5983 if (*input_line_pointer == ',')
5984 ++input_line_pointer;
5985 SKIP_WHITESPACE ();
5986 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5987 get_number ();
5989 #ifdef BFD_ASSEMBLER
5990 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5991 maybe_text = 1;
5992 else
5993 maybe_text = 0;
5994 #else
5995 if (now_seg != data_section && now_seg != bss_section)
5996 maybe_text = 1;
5997 else
5998 maybe_text = 0;
5999 #endif
6000 if (!maybe_text)
6001 as_warn (_(".ent or .aent not in text section."));
6002 if (!aent && cur_proc_ptr)
6003 as_warn (_("missing .end"));
6004 if (!aent)
6006 cur_proc_ptr = &cur_proc;
6007 cur_proc_ptr->reg_mask = 0xdeadbeaf;
6008 cur_proc_ptr->reg_offset = 0xdeadbeaf;
6009 cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
6010 cur_proc_ptr->leaf = 0xdeafbeaf;
6011 cur_proc_ptr->frame_offset = 0xdeafbeaf;
6012 cur_proc_ptr->frame_reg = 0xdeafbeaf;
6013 cur_proc_ptr->pc_reg = 0xdeafbeaf;
6014 cur_proc_ptr->isym = symbolP;
6015 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
6016 ++numprocs;
6017 if (debug_type == DEBUG_STABS)
6018 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
6020 demand_empty_rest_of_line ();
6023 static void
6024 s_score_frame (int ignore ATTRIBUTE_UNUSED)
6026 char *backupstr;
6027 char str[30];
6028 long val;
6029 int i = 0;
6031 backupstr = input_line_pointer;
6033 #ifdef OBJ_ELF
6034 if (cur_proc_ptr == (procS *) NULL)
6036 as_warn (_(".frame outside of .ent"));
6037 demand_empty_rest_of_line ();
6038 return;
6040 cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6041 SKIP_WHITESPACE ();
6042 skip_past_comma (&backupstr);
6043 while (*backupstr != ',')
6045 str[i] = *backupstr;
6046 i++;
6047 backupstr++;
6049 str[i] = '\0';
6050 val = atoi (str);
6052 SKIP_WHITESPACE ();
6053 skip_past_comma (&backupstr);
6054 cur_proc_ptr->frame_offset = val;
6055 cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6057 SKIP_WHITESPACE ();
6058 skip_past_comma (&backupstr);
6059 i = 0;
6060 while (*backupstr != '\n')
6062 str[i] = *backupstr;
6063 i++;
6064 backupstr++;
6066 str[i] = '\0';
6067 val = atoi (str);
6068 cur_proc_ptr->leaf = val;
6069 SKIP_WHITESPACE ();
6070 skip_past_comma (&backupstr);
6072 #endif /* OBJ_ELF */
6073 while (input_line_pointer != backupstr)
6074 input_line_pointer++;
6077 /* The .end directive. */
6078 static void
6079 s_score_end (int x ATTRIBUTE_UNUSED)
6081 symbolS *p;
6082 int maybe_text;
6084 /* Generate a .pdr section. */
6085 segT saved_seg = now_seg;
6086 subsegT saved_subseg = now_subseg;
6087 valueT dot;
6088 expressionS exp;
6089 char *fragp;
6091 if (!is_end_of_line[(unsigned char)*input_line_pointer])
6093 p = get_symbol ();
6094 demand_empty_rest_of_line ();
6096 else
6097 p = NULL;
6099 #ifdef BFD_ASSEMBLER
6100 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
6101 maybe_text = 1;
6102 else
6103 maybe_text = 0;
6104 #else
6105 if (now_seg != data_section && now_seg != bss_section)
6106 maybe_text = 1;
6107 else
6108 maybe_text = 0;
6109 #endif
6111 if (!maybe_text)
6112 as_warn (_(".end not in text section"));
6113 if (!cur_proc_ptr)
6115 as_warn (_(".end directive without a preceding .ent directive."));
6116 demand_empty_rest_of_line ();
6117 return;
6119 if (p != NULL)
6121 assert (S_GET_NAME (p));
6122 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
6123 as_warn (_(".end symbol does not match .ent symbol."));
6124 if (debug_type == DEBUG_STABS)
6125 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
6127 else
6128 as_warn (_(".end directive missing or unknown symbol"));
6130 if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
6131 (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
6132 (cur_proc_ptr->leaf == 0xdeafbeaf) ||
6133 (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
6134 (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
6136 else
6138 dot = frag_now_fix ();
6139 assert (pdr_seg);
6140 subseg_set (pdr_seg, 0);
6141 /* Write the symbol. */
6142 exp.X_op = O_symbol;
6143 exp.X_add_symbol = p;
6144 exp.X_add_number = 0;
6145 emit_expr (&exp, 4);
6146 fragp = frag_more (7 * 4);
6147 md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
6148 md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
6149 md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
6150 md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
6151 md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
6152 md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
6153 md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
6154 subseg_set (saved_seg, saved_subseg);
6157 cur_proc_ptr = NULL;
6160 /* Handle the .set pseudo-op. */
6161 static void
6162 s_score_set (int x ATTRIBUTE_UNUSED)
6164 int i = 0;
6165 char name[MAX_LITERAL_POOL_SIZE];
6166 char * orig_ilp = input_line_pointer;
6168 while (!is_end_of_line[(unsigned char)*input_line_pointer])
6170 name[i] = (char) * input_line_pointer;
6171 i++;
6172 ++input_line_pointer;
6175 name[i] = '\0';
6177 if (strcmp (name, "nwarn") == 0)
6179 warn_fix_data_dependency = 0;
6181 else if (strcmp (name, "fixdd") == 0)
6183 fix_data_dependency = 1;
6185 else if (strcmp (name, "nofixdd") == 0)
6187 fix_data_dependency = 0;
6189 else if (strcmp (name, "r1") == 0)
6191 nor1 = 0;
6193 else if (strcmp (name, "nor1") == 0)
6195 nor1 = 1;
6197 else if (strcmp (name, "optimize") == 0)
6199 g_opt = 1;
6201 else if (strcmp (name, "volatile") == 0)
6203 g_opt = 0;
6205 else if (strcmp (name, "pic") == 0)
6207 score_pic = PIC;
6209 else
6211 input_line_pointer = orig_ilp;
6212 s_set (0);
6216 /* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the
6217 $gp register for the function based on the function address, which is in the register
6218 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
6219 specially by the linker. The result is:
6220 ldis gp, %hi(GP_DISP_LABEL)
6221 ori gp, %low(GP_DISP_LABEL)
6222 add gp, gp, .cpload argument
6223 The .cpload argument is normally r29. */
6225 static void
6226 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6228 int reg;
6229 char insn_str[MAX_LITERAL_POOL_SIZE];
6231 /* If we are not generating PIC code, .cpload is ignored. */
6232 if (score_pic == NO_PIC)
6234 s_ignore (0);
6235 return;
6238 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6239 return;
6241 demand_empty_rest_of_line ();
6243 sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
6244 if (append_insn (insn_str, TRUE) == (int) FAIL)
6245 return;
6247 sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
6248 if (append_insn (insn_str, TRUE) == (int) FAIL)
6249 return;
6251 sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
6252 if (append_insn (insn_str, TRUE) == (int) FAIL)
6253 return;
6256 /* Handle the .cprestore pseudo-op. This stores $gp into a given
6257 offset from $sp. The offset is remembered, and after making a PIC
6258 call $gp is restored from that location. */
6260 static void
6261 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6263 #define SCORE_BP_REG 2
6264 int cprestore_offset;
6265 char insn_str[MAX_LITERAL_POOL_SIZE];
6267 /* If we are not generating PIC code, .cprestore is ignored. */
6268 if (score_pic == NO_PIC)
6270 s_ignore (0);
6271 return;
6274 cprestore_offset = get_absolute_expression ();
6276 sprintf (insn_str, "sw r%d, [r%d, %d]", GP, SCORE_BP_REG, cprestore_offset);
6277 if (append_insn (insn_str, TRUE) == (int) FAIL)
6278 return;
6281 /* Handle the .gpword pseudo-op. This is used when generating PIC
6282 code. It generates a 32 bit GP relative reloc. */
6283 static void
6284 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6286 expressionS ex;
6287 char *p;
6289 /* When not generating PIC code, this is treated as .word. */
6290 if (score_pic == NO_PIC)
6292 cons (4);
6293 return;
6295 expression (&ex);
6296 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6298 as_bad (_("Unsupported use of .gpword"));
6299 ignore_rest_of_line ();
6301 p = frag_more (4);
6302 md_number_to_chars (p, (valueT) 0, 4);
6303 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6304 demand_empty_rest_of_line ();
6307 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
6308 tables in PIC code. */
6310 static void
6311 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6313 int reg;
6314 char insn_str[MAX_LITERAL_POOL_SIZE];
6316 /* If we are not generating PIC code, .cpload is ignored. */
6317 if (score_pic == NO_PIC)
6319 s_ignore (0);
6320 return;
6323 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6325 return;
6327 demand_empty_rest_of_line ();
6329 /* Add $gp to the register named as an argument. */
6330 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
6331 if (append_insn (insn_str, TRUE) == (int) FAIL)
6332 return;
6335 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6336 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6337 do \
6339 if ((SIZE) >= 8) \
6340 (P2VAR) = 3; \
6341 else if ((SIZE) >= 4) \
6342 (P2VAR) = 2; \
6343 else if ((SIZE) >= 2) \
6344 (P2VAR) = 1; \
6345 else \
6346 (P2VAR) = 0; \
6348 while (0)
6349 #endif
6351 static void
6352 s_score_lcomm (int bytes_p)
6354 char *name;
6355 char c;
6356 char *p;
6357 int temp;
6358 symbolS *symbolP;
6359 segT current_seg = now_seg;
6360 subsegT current_subseg = now_subseg;
6361 const int max_alignment = 15;
6362 int align = 0;
6363 segT bss_seg = bss_section;
6364 int needs_align = 0;
6366 name = input_line_pointer;
6367 c = get_symbol_end ();
6368 p = input_line_pointer;
6369 *p = c;
6371 if (name == p)
6373 as_bad (_("expected symbol name"));
6374 discard_rest_of_line ();
6375 return;
6378 SKIP_WHITESPACE ();
6380 /* Accept an optional comma after the name. The comma used to be
6381 required, but Irix 5 cc does not generate it. */
6382 if (*input_line_pointer == ',')
6384 ++input_line_pointer;
6385 SKIP_WHITESPACE ();
6388 if (is_end_of_line[(unsigned char)*input_line_pointer])
6390 as_bad (_("missing size expression"));
6391 return;
6394 if ((temp = get_absolute_expression ()) < 0)
6396 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6397 ignore_rest_of_line ();
6398 return;
6401 #if defined (TC_SCORE)
6402 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6404 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
6405 if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6407 bss_seg = subseg_new (".sbss", 1);
6408 seg_info (bss_seg)->bss = 1;
6409 #ifdef BFD_ASSEMBLER
6410 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6411 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6412 #endif
6415 #endif
6417 SKIP_WHITESPACE ();
6418 if (*input_line_pointer == ',')
6420 ++input_line_pointer;
6421 SKIP_WHITESPACE ();
6423 if (is_end_of_line[(unsigned char)*input_line_pointer])
6425 as_bad (_("missing alignment"));
6426 return;
6428 else
6430 align = get_absolute_expression ();
6431 needs_align = 1;
6435 if (!needs_align)
6437 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6439 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6440 if (align)
6441 record_alignment (bss_seg, align);
6444 if (needs_align)
6446 if (bytes_p)
6448 /* Convert to a power of 2. */
6449 if (align != 0)
6451 unsigned int i;
6453 for (i = 0; align != 0; align >>= 1, ++i)
6455 align = i - 1;
6459 if (align > max_alignment)
6461 align = max_alignment;
6462 as_warn (_("alignment too large; %d assumed"), align);
6464 else if (align < 0)
6466 align = 0;
6467 as_warn (_("alignment negative; 0 assumed"));
6470 record_alignment (bss_seg, align);
6472 else
6474 /* Assume some objects may require alignment on some systems. */
6475 #if defined (TC_ALPHA) && ! defined (VMS)
6476 if (temp > 1)
6478 align = ffs (temp) - 1;
6479 if (temp % (1 << align))
6480 abort ();
6482 #endif
6485 *p = 0;
6486 symbolP = symbol_find_or_make (name);
6487 *p = c;
6489 if (
6490 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6491 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6492 #ifdef BFD_ASSEMBLER
6493 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6494 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6495 #else
6496 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6497 #endif
6498 #endif
6499 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6501 char *pfrag;
6503 subseg_set (bss_seg, 1);
6505 if (align)
6506 frag_align (align, 0, 0);
6508 /* Detach from old frag. */
6509 if (S_GET_SEGMENT (symbolP) == bss_seg)
6510 symbol_get_frag (symbolP)->fr_symbol = NULL;
6512 symbol_set_frag (symbolP, frag_now);
6513 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6514 *pfrag = 0;
6517 S_SET_SEGMENT (symbolP, bss_seg);
6519 #ifdef OBJ_COFF
6520 /* The symbol may already have been created with a preceding
6521 ".globl" directive -- be careful not to step on storage class
6522 in that case. Otherwise, set it to static. */
6523 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6525 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6527 #endif /* OBJ_COFF */
6529 #ifdef S_SET_SIZE
6530 S_SET_SIZE (symbolP, temp);
6531 #endif
6533 else
6534 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6536 subseg_set (current_seg, current_subseg);
6538 demand_empty_rest_of_line ();
6541 static void
6542 insert_reg (const struct reg_entry *r, struct hash_control *htab)
6544 int i = 0;
6545 int len = strlen (r->name) + 2;
6546 char *buf = xmalloc (len);
6547 char *buf2 = xmalloc (len);
6549 strcpy (buf + i, r->name);
6550 for (i = 0; buf[i]; i++)
6552 buf2[i] = TOUPPER (buf[i]);
6554 buf2[i] = '\0';
6556 hash_insert (htab, buf, (void *) r);
6557 hash_insert (htab, buf2, (void *) r);
6560 static void
6561 build_reg_hsh (struct reg_map *map)
6563 const struct reg_entry *r;
6565 if ((map->htab = hash_new ()) == NULL)
6567 as_fatal (_("virtual memory exhausted"));
6569 for (r = map->names; r->name != NULL; r++)
6571 insert_reg (r, map->htab);
6575 void
6576 md_begin (void)
6578 unsigned int i;
6579 segT seg;
6580 subsegT subseg;
6582 if ((score_ops_hsh = hash_new ()) == NULL)
6583 as_fatal (_("virtual memory exhausted"));
6585 build_score_ops_hsh ();
6587 if ((dependency_insn_hsh = hash_new ()) == NULL)
6588 as_fatal (_("virtual memory exhausted"));
6590 build_dependency_insn_hsh ();
6592 for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
6593 build_reg_hsh (all_reg_maps + i);
6595 /* Initialize dependency vector. */
6596 init_dependency_vector ();
6598 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6599 seg = now_seg;
6600 subseg = now_subseg;
6601 pdr_seg = subseg_new (".pdr", (subsegT) 0);
6602 (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6603 (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
6604 subseg_set (seg, subseg);
6606 if (USE_GLOBAL_POINTER_OPT)
6607 bfd_set_gp_size (stdoutput, g_switch_value);
6611 const pseudo_typeS md_pseudo_table[] =
6613 {"bss", s_score_bss, 0},
6614 {"text", s_score_text, 0},
6615 {"word", cons, 4},
6616 {"long", cons, 4},
6617 {"extend", float_cons, 'x'},
6618 {"ldouble", float_cons, 'x'},
6619 {"packed", float_cons, 'p'},
6620 {"end", s_score_end, 0},
6621 {"ent", s_score_ent, 0},
6622 {"frame", s_score_frame, 0},
6623 {"rdata", s_change_sec, 'r'},
6624 {"sdata", s_change_sec, 's'},
6625 {"set", s_score_set, 0},
6626 {"mask", s_score_mask, 'R'},
6627 {"dword", cons, 8},
6628 {"lcomm", s_score_lcomm, 1},
6629 {"section", score_s_section, 0},
6630 {"cpload", s_score_cpload, 0},
6631 {"cprestore", s_score_cprestore, 0},
6632 {"gpword", s_score_gpword, 0},
6633 {"cpadd", s_score_cpadd, 0},
6634 {0, 0, 0}