Banish PARAMS and PTR. Convert to ISO C.
[binutils.git] / gas / config / tc-score.c
blob5c12bd56726c6974b979e2bca7d4342a8b71cc3c
1 /* tc-score.c -- Assembler for Score
2 Copyright 2006, 2007 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 3, 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
46 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
47 #define BAD_ARGS _("bad arguments to instruction")
48 #define BAD_PC _("r15 not allowed here")
49 #define BAD_COND _("instruction is not conditional")
50 #define ERR_NO_ACCUM _("acc0 expected")
51 #define ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
52 #define ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
53 #define ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
54 #define LONG_LABEL_LEN _("the label length is longer than 1024");
55 #define BAD_SKIP_COMMA BAD_ARGS
56 #define BAD_GARBAGE _("garbage following instruction");
58 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
60 /* The name of the readonly data section. */
61 #define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
62 ? ".data" \
63 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
64 ? ".rdata" \
65 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
66 ? ".rdata" \
67 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
68 ? ".rodata" \
69 : (abort (), ""))
71 #define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
72 ((relax_substateT) \
73 (((old) << 23) \
74 | ((new) << 16) \
75 | ((type) << 9) \
76 | ((reloc1) << 5) \
77 | ((reloc2) << 1) \
78 | ((opt) ? 1 : 0)))
80 #define RELAX_OLD(i) (((i) >> 23) & 0x7f)
81 #define RELAX_NEW(i) (((i) >> 16) & 0x7f)
82 #define RELAX_TYPE(i) (((i) >> 9) & 0x7f)
83 #define RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
84 #define RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
85 #define RELAX_OPT(i) ((i) & 1)
86 #define RELAX_OPT_CLEAR(i) ((i) & ~1)
88 #define SET_INSN_ERROR(s) (inst.error = (s))
89 #define INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
91 #define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
93 #define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
94 ? INSN16_SIZE : INSN_SIZE)
96 /* This array holds the chars that always start a comment. If the
97 pre-processor is disabled, these aren't very useful. */
98 const char comment_chars[] = "#";
99 const char line_comment_chars[] = "#";
100 const char line_separator_chars[] = ";";
102 /* Chars that can be used to separate mant from exp in floating point numbers. */
103 const char EXP_CHARS[] = "eE";
104 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
106 /* Used to contain constructed error messages. */
107 static char err_msg[255];
109 fragS *score_fragp = 0;
110 static int fix_data_dependency = 0;
111 static int warn_fix_data_dependency = 1;
112 static int score7 = 1;
113 static int university_version = 0;
115 static int in_my_get_expression = 0;
117 #define USE_GLOBAL_POINTER_OPT 1
118 #define SCORE_BI_ENDIAN
120 /* Default, pop warning message when using r1. */
121 static int nor1 = 1;
123 /* Default will do instruction relax, -O0 will set g_opt = 0. */
124 static unsigned int g_opt = 1;
126 /* The size of the small data section. */
127 static unsigned int g_switch_value = 8;
129 #ifdef OBJ_ELF
130 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
131 symbolS *GOT_symbol;
132 #endif
133 static segT pdr_seg;
135 enum score_pic_level score_pic = NO_PIC;
137 #define INSN_NAME_LEN 16
138 struct score_it
140 char name[INSN_NAME_LEN];
141 unsigned long instruction;
142 unsigned long relax_inst;
143 int size;
144 int relax_size;
145 enum score_insn_type type;
146 char str[MAX_LITERAL_POOL_SIZE];
147 const char *error;
148 int bwarn;
149 char reg[INSN_NAME_LEN];
150 struct
152 bfd_reloc_code_real_type type;
153 expressionS exp;
154 int pc_rel;
155 }reloc;
157 struct score_it inst;
159 typedef struct proc
161 symbolS *isym;
162 unsigned long reg_mask;
163 unsigned long reg_offset;
164 unsigned long fpreg_mask;
165 unsigned long leaf;
166 unsigned long frame_offset;
167 unsigned long frame_reg;
168 unsigned long pc_reg;
170 procS;
172 static procS cur_proc;
173 static procS *cur_proc_ptr;
174 static int numprocs;
176 #define SCORE7_PIPELINE 7
177 #define SCORE5_PIPELINE 5
178 static int vector_size = SCORE7_PIPELINE;
179 struct score_it dependency_vector[SCORE7_PIPELINE];
181 /* Relax will need some padding for alignment. */
182 #define RELAX_PAD_BYTE 3
184 /* Structure for a hash table entry for a register. */
185 struct reg_entry
187 const char *name;
188 int number;
191 static const struct reg_entry score_rn_table[] =
193 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
194 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
195 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
196 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
197 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
198 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
199 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
200 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
201 {NULL, 0}
204 static const struct reg_entry score_srn_table[] =
206 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
207 {NULL, 0}
210 static const struct reg_entry score_crn_table[] =
212 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
213 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
214 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
215 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
216 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
217 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
218 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
219 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
220 {NULL, 0}
223 struct reg_map
225 const struct reg_entry *names;
226 int max_regno;
227 struct hash_control *htab;
228 const char *expected;
231 struct reg_map all_reg_maps[] =
233 {score_rn_table, 31, NULL, N_("S+core register expected")},
234 {score_srn_table, 2, NULL, N_("S+core special-register expected")},
235 {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
238 static struct hash_control *score_ops_hsh = NULL;
240 static struct hash_control *dependency_insn_hsh = NULL;
242 /* Enumeration matching entries in table above. */
243 enum score_reg_type
245 REG_TYPE_SCORE = 0,
246 #define REG_TYPE_FIRST REG_TYPE_SCORE
247 REG_TYPE_SCORE_SR = 1,
248 REG_TYPE_SCORE_CR = 2,
249 REG_TYPE_MAX = 3
252 typedef struct literalS
254 struct expressionS exp;
255 struct score_it *inst;
257 literalT;
259 literalT literals[MAX_LITERAL_POOL_SIZE];
261 static void do_ldst_insn (char *);
262 static void do_crdcrscrsimm5 (char *);
263 static void do_ldst_unalign (char *);
264 static void do_ldst_atomic (char *);
265 static void do_ldst_cop (char *);
266 static void do_macro_li_rdi32 (char *);
267 static void do_macro_la_rdi32 (char *);
268 static void do_macro_rdi32hi (char *);
269 static void do_macro_rdi32lo (char *);
270 static void do_macro_mul_rdrsrs (char *);
271 static void do_macro_ldst_label (char *);
272 static void do_branch (char *);
273 static void do_jump (char *);
274 static void do_empty (char *);
275 static void do_rdrsrs (char *);
276 static void do_rdsi16 (char *);
277 static void do_rdrssi14 (char *);
278 static void do_sub_rdsi16 (char *);
279 static void do_sub_rdrssi14 (char *);
280 static void do_rdrsi5 (char *);
281 static void do_rdrsi14 (char *);
282 static void do_rdi16 (char *);
283 static void do_xrsi5 (char *);
284 static void do_rdrs (char *);
285 static void do_rdxrs (char *);
286 static void do_rsrs (char *);
287 static void do_rdcrs (char *);
288 static void do_rdsrs (char *);
289 static void do_rd (char *);
290 static void do_rs (char *);
291 static void do_i15 (char *);
292 static void do_xi5x (char *);
293 static void do_ceinst (char *);
294 static void do_cache (char *);
295 static void do16_rdrs (char *);
296 static void do16_rs (char *);
297 static void do16_xrs (char *);
298 static void do16_mv_rdrs (char *);
299 static void do16_hrdrs (char *);
300 static void do16_rdhrs (char *);
301 static void do16_rdi4 (char *);
302 static void do16_rdi5 (char *);
303 static void do16_xi5 (char *);
304 static void do16_ldst_insn (char *);
305 static void do16_ldst_imm_insn (char *);
306 static void do16_push_pop (char *);
307 static void do16_branch (char *);
308 static void do16_jump (char *);
309 static void do_rdi16_pic (char *);
310 static void do_addi_s_pic (char *);
311 static void do_addi_u_pic (char *);
312 static void do_lw_pic (char *);
314 static const struct asm_opcode score_ldst_insns[] =
316 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_ldst_insn},
317 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
318 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, do_ldst_insn},
319 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, do_ldst_insn},
320 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
321 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
322 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
323 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
324 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
325 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
326 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
327 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
328 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, do_ldst_insn},
329 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, do_ldst_insn},
330 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
331 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, do_ldst_insn},
332 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
333 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
334 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, do_ldst_insn},
335 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
336 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
337 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, do_ldst_insn},
338 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
339 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
342 static const struct asm_opcode score_insns[] =
344 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
345 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
346 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
347 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, do_rdrsrs},
348 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
349 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
350 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, do_rdrsrs},
351 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
352 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
353 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
354 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
355 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
356 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
357 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, do16_rdrs},
358 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, do16_rdrs},
359 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, do16_rdi4},
360 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
361 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
362 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
363 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
364 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
365 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, do_rdrsrs},
366 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
367 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
368 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
369 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
370 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
371 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
372 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, do16_rdrs},
373 {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
374 {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
375 {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
376 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
377 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
378 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
379 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, do16_branch},
380 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, do16_branch},
381 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, do16_branch},
382 {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
383 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
384 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, do16_branch},
385 {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
386 {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
387 {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
388 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
389 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
390 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
391 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, do16_branch},
392 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, do16_branch},
393 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, do16_branch},
394 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, do_rdrsi5},
395 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
396 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, do_rdrsi5},
397 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, do_xrsi5},
398 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, do_rdrsi5},
399 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, do16_rdi5},
400 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, do16_rdi5},
401 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, do16_rdi5},
402 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, do16_rdi5},
403 {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
404 {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
405 {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
406 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
407 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
408 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
409 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
410 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, do16_branch},
411 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, do16_branch},
412 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, do16_branch},
413 {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
414 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
415 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, do16_branch},
416 {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
417 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
418 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, do16_branch},
419 {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
420 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
421 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, do16_branch},
422 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, do_rs},
423 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, do_rs},
424 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, do_rs},
425 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, do_rs},
426 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, do_rs},
427 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, do_rs},
428 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, do_rs},
429 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, do_rs},
430 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, do_rs},
431 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, do_rs},
432 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, do_rs},
433 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, do_rs},
434 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, do_rs},
435 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, do_rs},
436 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, do_rs},
437 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, do_rs},
438 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, do_rs},
439 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, do_rs},
440 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, do_rs},
441 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, do_rs},
442 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, do_rs},
443 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, do_rs},
444 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, do_rs},
445 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, do_rs},
446 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, do_rs},
447 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, do_rs},
448 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, do_rs},
449 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, do_rs},
450 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, do_rs},
451 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, do_rs},
452 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, do_rs},
453 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, do_rs},
454 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, do16_xrs},
455 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, do16_xrs},
456 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, do16_xrs},
457 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, do16_xrs},
458 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, do16_xrs},
459 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, do16_xrs},
460 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, do16_xrs},
461 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, do16_xrs},
462 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, do16_xrs},
463 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, do16_xrs},
464 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, do16_xrs},
465 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, do16_xrs},
466 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, do16_xrs},
467 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, do16_xrs},
468 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, do16_xrs},
469 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, do16_xrs},
470 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, do16_xrs},
471 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, do16_xrs},
472 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, do16_xrs},
473 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, do16_xrs},
474 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, do16_xrs},
475 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, do16_xrs},
476 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, do16_xrs},
477 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, do16_xrs},
478 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, do16_xrs},
479 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, do16_xrs},
480 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, do16_xrs},
481 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, do16_xrs},
482 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, do16_xrs},
483 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, do16_xrs},
484 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, do16_xrs},
485 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, do16_xrs},
486 {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
487 {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
488 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
489 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
490 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, do16_branch},
491 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, do16_branch},
492 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, do16_branch},
493 {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
494 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, do_cache},
495 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, do_ceinst},
496 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
497 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
498 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
499 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, do_rsrs},
500 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
501 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
502 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
503 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
504 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, do16_rdrs},
505 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
506 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
507 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
508 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
509 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
510 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
511 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
512 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
513 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
514 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
515 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
516 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
517 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
518 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, do16_jump},
519 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, do16_jump},
520 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
521 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, do16_ldst_insn},
522 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
523 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, do_ldst_atomic},
524 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, do_ldst_unalign},
525 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
526 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
527 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
528 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
529 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
530 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, do16_ldst_insn},
531 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
532 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, do_rdsi16},
533 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, do_rdi16},
534 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, do16_ldst_imm_insn},
535 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, do16_ldst_insn},
536 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
537 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
538 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, do16_rs},
539 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
540 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, do16_rdrs},
541 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
542 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
543 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, do16_rdrs},
544 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
545 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
546 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, do16_rdrs},
547 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
548 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, do16_rdrs},
549 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
550 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
551 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
552 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
553 {"mazh.f!", 0x1009, 0x700f, 0x3800038c, Rd_Rs, do16_rdrs},
554 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
555 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
556 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, do16_rdrs},
557 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
558 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, do16_rs},
559 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
560 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, do_rdsrs},
561 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
562 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
563 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
564 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
565 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
566 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
567 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
568 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, do16_hrdrs},
569 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
570 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, do16_rdhrs},
571 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
572 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, do16_rdrs},
573 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
574 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
575 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, do16_rdrs},
576 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
577 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
578 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, do16_rdrs},
579 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
580 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, do16_rdrs},
581 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
582 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
583 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
584 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, do16_rdrs},
585 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
586 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
587 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, do16_rdrs},
588 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, do16_rs},
589 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
590 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
591 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, do16_rs},
592 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
593 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, do_rdsrs},
594 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
595 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
596 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
597 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
598 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
599 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
600 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
601 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, do16_rdrs},
602 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, do16_rdrs},
603 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
604 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
605 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
606 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
607 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
608 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
609 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
610 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
611 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
612 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
613 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
614 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
615 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
616 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
617 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, do_rdrs},
618 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, do16_mv_rdrs},
619 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, do_rdxrs},
620 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, do_rdxrs},
621 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, do16_rdrs},
622 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, do_empty},
623 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
624 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, do_rdrs},
625 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, do_empty},
626 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, do16_rdrs},
627 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
628 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, do_rdrsrs},
629 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
630 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
631 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
632 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
633 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
634 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
635 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, do16_rdrs},
636 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
637 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, do16_push_pop},
638 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, do16_push_pop},
639 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
640 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
641 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
642 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
643 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
644 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
645 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
646 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
647 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
648 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
649 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
650 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
651 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
652 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, do16_ldst_insn},
653 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
654 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, do_ldst_atomic},
655 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
656 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
657 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, do_ldst_unalign},
658 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, do_xi5x},
659 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, do16_xi5},
660 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, do16_ldst_insn},
661 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
662 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
663 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
664 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, do_rdrsrs},
665 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
666 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
667 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, do_rdrsi5},
668 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, do16_rdrs},
669 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, do16_rdi5},
670 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
671 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, do_rdrsrs},
672 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
673 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, do_rdrsrs},
674 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
675 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, do_rdrsi5},
676 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
677 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
678 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, do16_rdrs},
679 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, do16_rdrs},
680 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, do16_rdi5},
681 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
682 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
683 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
684 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
685 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, do_rdrsrs},
686 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
687 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
688 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
689 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, do16_rdrs},
690 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, do16_rdi4},
691 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, do16_ldst_insn},
692 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
693 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, do_i15},
694 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, do_empty},
695 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, do_empty},
696 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, do_empty},
697 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, do_empty},
698 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, do_empty},
699 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, do_empty},
700 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, do_empty},
701 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, do_empty},
702 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, do_empty},
703 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, do_empty},
704 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, do_empty},
705 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, do_empty},
706 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, do_empty},
707 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, do_empty},
708 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, do_empty},
709 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, do_empty},
710 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, do_empty},
711 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
712 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
713 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
714 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
715 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, do_empty},
716 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, do_empty},
717 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, do_empty},
718 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, do_empty},
719 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, do_empty},
720 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, do_empty},
721 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, do_empty},
722 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, do_empty},
723 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, do_empty},
724 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
725 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
726 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
727 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
728 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
729 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
730 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
731 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
732 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
733 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
734 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
735 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
736 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
737 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
738 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
739 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, do_empty},
740 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, do_empty},
741 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, do_empty},
742 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, do_empty},
743 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, do_empty},
744 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, do_empty},
745 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
746 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, do_rdrsrs},
747 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, do16_rdrs},
748 /* Macro instruction. */
749 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_li_rdi32},
750 /* la reg, imm32 -->(1) ldi reg, simm16
751 (2) ldis reg, %HI(imm32)
752 ori reg, %LO(imm32)
754 la reg, symbol -->(1) lis reg, %HI(imm32)
755 ori reg, %LO(imm32) */
756 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_la_rdi32},
757 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
758 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
759 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
760 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
761 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
762 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
763 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
764 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
765 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
766 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
767 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
768 {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, do_macro_ldst_label},
769 {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, do_macro_ldst_label},
770 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
771 {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, do_macro_ldst_label},
772 {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, do_macro_ldst_label},
773 {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, do_macro_ldst_label},
774 {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, do_macro_ldst_label},
775 /* Assembler use internal. */
776 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, do_macro_rdi32hi},
777 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, do_macro_rdi32lo},
778 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, do_rdi16_pic},
779 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_s_pic},
780 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_u_pic},
781 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, do_lw_pic},
784 /* Next free entry in the pool. */
785 int next_literal_pool_place = 0;
787 /* Next literal pool number. */
788 int lit_pool_num = 1;
789 symbolS *current_poolP = NULL;
792 static int
793 end_of_line (char *str)
795 int retval = SUCCESS;
797 skip_whitespace (str);
798 if (*str != '\0')
800 retval = (int) FAIL;
802 if (!inst.error)
803 inst.error = BAD_GARBAGE;
806 return retval;
809 static int
810 score_reg_parse (char **ccp, struct hash_control *htab)
812 char *start = *ccp;
813 char c;
814 char *p;
815 struct reg_entry *reg;
817 p = start;
818 if (!ISALPHA (*p) || !is_name_beginner (*p))
819 return (int) FAIL;
821 c = *p++;
823 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
824 c = *p++;
826 *--p = 0;
827 reg = (struct reg_entry *) hash_find (htab, start);
828 *p = c;
830 if (reg)
832 *ccp = p;
833 return reg->number;
835 return (int) FAIL;
838 /* If shift <= 0, only return reg. */
840 static int
841 reg_required_here (char **str, int shift, enum score_reg_type reg_type)
843 static char buff[MAX_LITERAL_POOL_SIZE];
844 int reg = (int) FAIL;
845 char *start = *str;
847 if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
849 if (reg_type == REG_TYPE_SCORE)
851 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
853 as_warn (_("Using temp register(r1)"));
854 inst.bwarn = 1;
857 if (shift >= 0)
859 if (reg_type == REG_TYPE_SCORE_CR)
860 strcpy (inst.reg, score_crn_table[reg].name);
861 else if (reg_type == REG_TYPE_SCORE_SR)
862 strcpy (inst.reg, score_srn_table[reg].name);
863 else
864 strcpy (inst.reg, "");
866 inst.instruction |= reg << shift;
869 else
871 *str = start;
872 sprintf (buff, _("register expected, not '%.100s'"), start);
873 inst.error = buff;
876 return reg;
879 static int
880 skip_past_comma (char **str)
882 char *p = *str;
883 char c;
884 int comma = 0;
886 while ((c = *p) == ' ' || c == ',')
888 p++;
889 if (c == ',' && comma++)
891 inst.error = BAD_SKIP_COMMA;
892 return (int) FAIL;
896 if ((c == '\0') || (comma == 0))
898 inst.error = BAD_SKIP_COMMA;
899 return (int) FAIL;
902 *str = p;
903 return comma ? SUCCESS : (int) FAIL;
906 static void
907 do_rdrsrs (char *str)
909 skip_whitespace (str);
911 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
912 || skip_past_comma (&str) == (int) FAIL
913 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
914 || skip_past_comma (&str) == (int) FAIL
915 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
916 || end_of_line (str) == (int) FAIL)
918 return;
920 else
922 if ((((inst.instruction >> 15) & 0x10) == 0)
923 && (((inst.instruction >> 10) & 0x10) == 0)
924 && (((inst.instruction >> 20) & 0x10) == 0)
925 && (inst.relax_inst != 0x8000)
926 && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
928 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
929 | (((inst.instruction >> 15) & 0xf) << 8);
930 inst.relax_size = 2;
932 else
934 inst.relax_inst = 0x8000;
939 static int
940 walk_no_bignums (symbolS * sp)
942 if (symbol_get_value_expression (sp)->X_op == O_big)
943 return 1;
945 if (symbol_get_value_expression (sp)->X_add_symbol)
946 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
947 || (symbol_get_value_expression (sp)->X_op_symbol
948 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
950 return 0;
953 static int
954 my_get_expression (expressionS * ep, char **str)
956 char *save_in;
957 segT seg;
959 save_in = input_line_pointer;
960 input_line_pointer = *str;
961 in_my_get_expression = 1;
962 seg = expression (ep);
963 in_my_get_expression = 0;
965 if (ep->X_op == O_illegal)
967 *str = input_line_pointer;
968 input_line_pointer = save_in;
969 inst.error = _("illegal expression");
970 return (int) FAIL;
972 /* Get rid of any bignums now, so that we don't generate an error for which
973 we can't establish a line number later on. Big numbers are never valid
974 in instructions, which is where this routine is always called. */
975 if (ep->X_op == O_big
976 || (ep->X_add_symbol
977 && (walk_no_bignums (ep->X_add_symbol)
978 || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
980 inst.error = _("invalid constant");
981 *str = input_line_pointer;
982 input_line_pointer = save_in;
983 return (int) FAIL;
986 if ((ep->X_add_symbol != NULL)
987 && (inst.type != PC_DISP19div2)
988 && (inst.type != PC_DISP8div2)
989 && (inst.type != PC_DISP24div2)
990 && (inst.type != PC_DISP11div2)
991 && (inst.type != Insn_Type_SYN)
992 && (inst.type != Rd_rvalueRs_SI15)
993 && (inst.type != Rd_lvalueRs_SI15)
994 && (inst.type != Insn_internal))
996 inst.error = BAD_ARGS;
997 *str = input_line_pointer;
998 input_line_pointer = save_in;
999 return (int) FAIL;
1002 *str = input_line_pointer;
1003 input_line_pointer = save_in;
1004 return SUCCESS;
1007 /* Check if an immediate is valid. If so, convert it to the right format. */
1009 static int
1010 validate_immediate (int val, unsigned int data_type, int hex_p)
1012 switch (data_type)
1014 case _VALUE_HI16:
1016 int val_hi = ((val & 0xffff0000) >> 16);
1018 if (score_df_range[data_type].range[0] <= val_hi
1019 && val_hi <= score_df_range[data_type].range[1])
1020 return val_hi;
1022 break;
1024 case _VALUE_LO16:
1026 int val_lo = (val & 0xffff);
1028 if (score_df_range[data_type].range[0] <= val_lo
1029 && val_lo <= score_df_range[data_type].range[1])
1030 return val_lo;
1032 break;
1034 case _VALUE:
1035 return val;
1036 break;
1038 case _SIMM14:
1039 if (hex_p == 1)
1041 if (!(val >= -0x2000 && val <= 0x3fff))
1043 return (int) FAIL;
1046 else
1048 if (!(val >= -8192 && val <= 8191))
1050 return (int) FAIL;
1054 return val;
1055 break;
1057 case _SIMM16_NEG:
1058 if (hex_p == 1)
1060 if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1062 return (int) FAIL;
1065 else
1067 if (!(val >= -32767 && val <= 32768))
1069 return (int) FAIL;
1073 val = -val;
1074 return val;
1075 break;
1077 default:
1078 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1079 val = -val;
1081 if (score_df_range[data_type].range[0] <= val
1082 && val <= score_df_range[data_type].range[1])
1083 return val;
1085 break;
1088 return (int) FAIL;
1091 static int
1092 data_op2 (char **str, int shift, enum score_data_type data_type)
1094 int value;
1095 char data_exp[MAX_LITERAL_POOL_SIZE];
1096 char *dataptr;
1097 int cnt = 0;
1098 char *pp = NULL;
1100 skip_whitespace (*str);
1101 inst.error = NULL;
1102 dataptr = * str;
1104 /* Set hex_p to zero. */
1105 int hex_p = 0;
1107 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1109 data_exp[cnt] = *dataptr;
1110 dataptr++;
1111 cnt++;
1114 data_exp[cnt] = '\0';
1115 pp = (char *)&data_exp;
1117 if (*dataptr == '|') /* process PCE */
1119 if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
1120 return (int) FAIL;
1121 end_of_line (pp);
1122 if (inst.error != 0)
1123 return (int) FAIL; /* to ouptut_inst to printf out the error */
1124 *str = dataptr;
1126 else /* process 16 bit */
1128 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
1130 return (int) FAIL;
1133 dataptr = (char *)data_exp;
1134 for (; *dataptr != '\0'; dataptr++)
1136 *dataptr = TOLOWER (*dataptr);
1137 if (*dataptr == '!' || *dataptr == ' ')
1138 break;
1140 dataptr = (char *)data_exp;
1142 if ((dataptr != NULL)
1143 && (((strstr (dataptr, "0x")) != NULL)
1144 || ((strstr (dataptr, "0X")) != NULL)))
1146 hex_p = 1;
1147 if ((data_type != _SIMM16_LA)
1148 && (data_type != _VALUE_HI16)
1149 && (data_type != _VALUE_LO16)
1150 && (data_type != _IMM16)
1151 && (data_type != _IMM15)
1152 && (data_type != _IMM14)
1153 && (data_type != _IMM4)
1154 && (data_type != _IMM5)
1155 && (data_type != _IMM8)
1156 && (data_type != _IMM5_RSHIFT_1)
1157 && (data_type != _IMM5_RSHIFT_2)
1158 && (data_type != _SIMM14)
1159 && (data_type != _SIMM14_NEG)
1160 && (data_type != _SIMM16_NEG)
1161 && (data_type != _IMM10_RSHIFT_2)
1162 && (data_type != _GP_IMM15))
1164 data_type += 24;
1168 if ((inst.reloc.exp.X_add_number == 0)
1169 && (inst.type != Insn_Type_SYN)
1170 && (inst.type != Rd_rvalueRs_SI15)
1171 && (inst.type != Rd_lvalueRs_SI15)
1172 && (inst.type != Insn_internal)
1173 && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1174 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1175 || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1176 || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1178 inst.error = BAD_ARGS;
1179 return (int) FAIL;
1183 if ((inst.reloc.exp.X_add_symbol)
1184 && ((data_type == _SIMM16)
1185 || (data_type == _SIMM16_NEG)
1186 || (data_type == _IMM16_NEG)
1187 || (data_type == _SIMM14)
1188 || (data_type == _SIMM14_NEG)
1189 || (data_type == _IMM5)
1190 || (data_type == _IMM14)
1191 || (data_type == _IMM20)
1192 || (data_type == _IMM16)
1193 || (data_type == _IMM15)
1194 || (data_type == _IMM4)))
1196 inst.error = BAD_ARGS;
1197 return (int) FAIL;
1200 if (inst.reloc.exp.X_add_symbol)
1202 switch (data_type)
1204 case _SIMM16_LA:
1205 return (int) FAIL;
1206 case _VALUE_HI16:
1207 inst.reloc.type = BFD_RELOC_HI16_S;
1208 inst.reloc.pc_rel = 0;
1209 break;
1210 case _VALUE_LO16:
1211 inst.reloc.type = BFD_RELOC_LO16;
1212 inst.reloc.pc_rel = 0;
1213 break;
1214 case _GP_IMM15:
1215 inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1216 inst.reloc.pc_rel = 0;
1217 break;
1218 case _SIMM16_pic:
1219 case _IMM16_LO16_pic:
1220 inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1221 inst.reloc.pc_rel = 0;
1222 break;
1223 default:
1224 inst.reloc.type = BFD_RELOC_32;
1225 inst.reloc.pc_rel = 0;
1226 break;
1229 else
1231 if (data_type == _IMM16_pic)
1233 inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1234 inst.reloc.pc_rel = 0;
1237 if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
1239 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
1240 if (value == (int) FAIL) /* for advance to check if this is ldis */
1241 if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
1243 inst.instruction |= 0x8000000;
1244 inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1245 return SUCCESS;
1248 else
1250 value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p);
1253 if (value == (int) FAIL)
1255 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1257 sprintf (err_msg,
1258 _("invalid constant: %d bit expression not in range %d..%d"),
1259 score_df_range[data_type].bits,
1260 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
1262 else
1264 sprintf (err_msg,
1265 _("invalid constant: %d bit expression not in range %d..%d"),
1266 score_df_range[data_type].bits,
1267 -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
1270 inst.error = err_msg;
1271 return (int) FAIL;
1274 if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1276 value &= (1 << score_df_range[data_type].bits) - 1;
1279 inst.instruction |= value << shift;
1282 if ((inst.instruction & 0xf0000000) == 0x30000000)
1284 if ((((inst.instruction >> 20) & 0x1F) != 0)
1285 && (((inst.instruction >> 20) & 0x1F) != 1)
1286 && (((inst.instruction >> 20) & 0x1F) != 2)
1287 && (((inst.instruction >> 20) & 0x1F) != 3)
1288 && (((inst.instruction >> 20) & 0x1F) != 4)
1289 && (((inst.instruction >> 20) & 0x1F) != 8)
1290 && (((inst.instruction >> 20) & 0x1F) != 9)
1291 && (((inst.instruction >> 20) & 0x1F) != 0xa)
1292 && (((inst.instruction >> 20) & 0x1F) != 0xb)
1293 && (((inst.instruction >> 20) & 0x1F) != 0xc)
1294 && (((inst.instruction >> 20) & 0x1F) != 0xd)
1295 && (((inst.instruction >> 20) & 0x1F) != 0xe)
1296 && (((inst.instruction >> 20) & 0x1F) != 0x10)
1297 && (((inst.instruction >> 20) & 0x1F) != 0x11)
1298 && (((inst.instruction >> 20) & 0x1F) != 0x18)
1299 && (((inst.instruction >> 20) & 0x1F) != 0x1A)
1300 && (((inst.instruction >> 20) & 0x1F) != 0x1B)
1301 && (((inst.instruction >> 20) & 0x1F) != 0x1d)
1302 && (((inst.instruction >> 20) & 0x1F) != 0x1e)
1303 && (((inst.instruction >> 20) & 0x1F) != 0x1f))
1305 inst.error = _("invalid constant: bit expression not defined");
1306 return (int) FAIL;
1310 return SUCCESS;
1313 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1315 static void
1316 do_rdsi16 (char *str)
1318 skip_whitespace (str);
1320 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1321 || skip_past_comma (&str) == (int) FAIL
1322 || data_op2 (&str, 1, _SIMM16) == (int) FAIL
1323 || end_of_line (str) == (int) FAIL)
1324 return;
1326 /* ldi. */
1327 if ((inst.instruction & 0x20c0000) == 0x20c0000)
1329 if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
1331 inst.relax_inst = 0x8000;
1333 else
1335 inst.relax_inst |= (inst.instruction >> 1) & 0xff;
1336 inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
1337 inst.relax_size = 2;
1340 else if (((inst.instruction >> 20) & 0x10) == 0x10)
1342 inst.relax_inst = 0x8000;
1346 /* Handle subi/subi.c. */
1348 static void
1349 do_sub_rdsi16 (char *str)
1351 skip_whitespace (str);
1353 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1354 && skip_past_comma (&str) != (int) FAIL
1355 && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
1356 end_of_line (str);
1359 /* Handle addri/addri.c. */
1361 static void
1362 do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1364 skip_whitespace (str);
1366 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1367 && skip_past_comma (&str) != (int) FAIL
1368 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1369 && skip_past_comma (&str) != (int) FAIL)
1370 data_op2 (&str, 1, _SIMM14);
1373 /* Handle subri.c/subri. */
1374 static void
1375 do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1377 skip_whitespace (str);
1379 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1380 && skip_past_comma (&str) != (int) FAIL
1381 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1382 && skip_past_comma (&str) != (int) FAIL
1383 && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
1384 end_of_line (str);
1387 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1388 static void
1389 do_rdrsi5 (char *str) /* 0~((2^14)-1) */
1391 skip_whitespace (str);
1393 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1394 || skip_past_comma (&str) == (int) FAIL
1395 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1396 || skip_past_comma (&str) == (int) FAIL
1397 || data_op2 (&str, 10, _IMM5) == (int) FAIL
1398 || end_of_line (str) == (int) FAIL)
1399 return;
1401 if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
1402 && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1404 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1405 inst.relax_size = 2;
1407 else
1408 inst.relax_inst = 0x8000;
1411 /* Handle andri/orri/andri.c/orri.c. */
1413 static void
1414 do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1416 skip_whitespace (str);
1418 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1419 && skip_past_comma (&str) != (int) FAIL
1420 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1421 && skip_past_comma (&str) != (int) FAIL
1422 && data_op2 (&str, 1, _IMM14) != (int) FAIL)
1423 end_of_line (str);
1426 /* Handle bittst.c. */
1427 static void
1428 do_xrsi5 (char *str)
1430 skip_whitespace (str);
1432 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1433 || skip_past_comma (&str) == (int) FAIL
1434 || data_op2 (&str, 10, _IMM5) == (int) FAIL
1435 || end_of_line (str) == (int) FAIL)
1436 return;
1438 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1440 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1441 inst.relax_size = 2;
1443 else
1444 inst.relax_inst = 0x8000;
1447 /* Handle addis/andi/ori/andis/oris/ldis. */
1448 static void
1449 do_rdi16 (char *str)
1451 skip_whitespace (str);
1453 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1454 || skip_past_comma (&str) == (int) FAIL
1455 || data_op2 (&str, 1, _IMM16) == (int) FAIL
1456 || end_of_line (str) == (int) FAIL)
1457 return;
1459 if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
1460 inst.relax_inst = 0x8000;
1461 else
1462 inst.relax_size = 2;
1466 static void
1467 do_macro_rdi32hi (char *str)
1469 skip_whitespace (str);
1471 /* Do not handle end_of_line(). */
1472 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1473 && skip_past_comma (&str) != (int) FAIL)
1474 data_op2 (&str, 1, _VALUE_HI16);
1477 static void
1478 do_macro_rdi32lo (char *str)
1480 skip_whitespace (str);
1482 /* Do not handle end_of_line(). */
1483 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1484 && skip_past_comma (&str) != (int) FAIL)
1485 data_op2 (&str, 1, _VALUE_LO16);
1488 /* Handle ldis_pic. */
1490 static void
1491 do_rdi16_pic (char *str)
1493 skip_whitespace (str);
1495 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1496 && skip_past_comma (&str) != (int) FAIL
1497 && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
1498 end_of_line (str);
1501 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1503 static void
1504 do_addi_s_pic (char *str)
1506 skip_whitespace (str);
1508 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1509 && skip_past_comma (&str) != (int) FAIL
1510 && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
1511 end_of_line (str);
1514 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1516 static void
1517 do_addi_u_pic (char *str)
1519 skip_whitespace (str);
1521 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1522 && skip_past_comma (&str) != (int) FAIL
1523 && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
1524 end_of_line (str);
1527 /* Handle mfceh/mfcel/mtceh/mtchl. */
1529 static void
1530 do_rd (char *str)
1532 skip_whitespace (str);
1534 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
1535 end_of_line (str);
1538 static void
1539 do_rs (char *str)
1541 skip_whitespace (str);
1543 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1544 || end_of_line (str) == (int) FAIL)
1545 return;
1547 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1549 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
1550 inst.relax_size = 2;
1552 else
1553 inst.relax_inst = 0x8000;
1556 static void
1557 do_i15 (char *str)
1559 skip_whitespace (str);
1561 if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
1562 end_of_line (str);
1565 static void
1566 do_xi5x (char *str)
1568 skip_whitespace (str);
1570 if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
1571 return;
1573 if (inst.relax_inst != 0x8000)
1575 inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
1576 inst.relax_size = 2;
1580 static void
1581 do_rdrs (char *str)
1583 skip_whitespace (str);
1585 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1586 || skip_past_comma (&str) == (int) FAIL
1587 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1588 || end_of_line (str) == (int) FAIL)
1589 return;
1591 if (inst.relax_inst != 0x8000)
1593 if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1595 /* mlfh */
1596 if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1598 inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
1599 | (((inst.instruction >> 20) & 0xf) << 8);
1600 inst.relax_size = 2;
1602 /* mhfl */
1603 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
1605 inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
1606 | (((inst.instruction >> 20) & 0xf) << 8);
1607 inst.relax_size = 2;
1609 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1611 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1612 | (((inst.instruction >> 20) & 0xf) << 8);
1613 inst.relax_size = 2;
1615 else
1617 inst.relax_inst = 0x8000;
1620 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1622 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1623 | (((inst.instruction >> 20) & 0xf) << 8);
1624 inst.relax_size = 2;
1626 else
1628 inst.relax_inst = 0x8000;
1633 /* Handle mfcr/mtcr. */
1634 static void
1635 do_rdcrs (char *str)
1637 skip_whitespace (str);
1639 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1640 && skip_past_comma (&str) != (int) FAIL
1641 && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
1642 end_of_line (str);
1645 /* Handle mfsr/mtsr. */
1647 static void
1648 do_rdsrs (char *str)
1650 skip_whitespace (str);
1652 /* mfsr */
1653 if ((inst.instruction & 0xff) == 0x50)
1655 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1656 && skip_past_comma (&str) != (int) FAIL
1657 && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
1658 end_of_line (str);
1660 else
1662 if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1663 && skip_past_comma (&str) != (int) FAIL)
1664 reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
1668 /* Handle neg. */
1670 static void
1671 do_rdxrs (char *str)
1673 skip_whitespace (str);
1675 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1676 || skip_past_comma (&str) == (int) FAIL
1677 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1678 || end_of_line (str) == (int) FAIL)
1679 return;
1681 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
1682 && (((inst.instruction >> 20) & 0x10) == 0))
1684 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
1685 inst.relax_size = 2;
1687 else
1688 inst.relax_inst = 0x8000;
1691 /* Handle cmp.c/cmp<cond>. */
1692 static void
1693 do_rsrs (char *str)
1695 skip_whitespace (str);
1697 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1698 || skip_past_comma (&str) == (int) FAIL
1699 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1700 || end_of_line (str) == (int) FAIL)
1701 return;
1703 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
1704 && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
1706 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
1707 inst.relax_size = 2;
1709 else
1710 inst.relax_inst = 0x8000;
1713 static void
1714 do_ceinst (char *str)
1716 char *strbak;
1718 strbak = str;
1719 skip_whitespace (str);
1721 if (data_op2 (&str, 20, _IMM5) == (int) FAIL
1722 || skip_past_comma (&str) == (int) FAIL
1723 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1724 || skip_past_comma (&str) == (int) FAIL
1725 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1726 || skip_past_comma (&str) == (int) FAIL
1727 || data_op2 (&str, 5, _IMM5) == (int) FAIL
1728 || skip_past_comma (&str) == (int) FAIL
1729 || data_op2 (&str, 0, _IMM5) == (int) FAIL
1730 || end_of_line (str) == (int) FAIL)
1732 return;
1734 else
1736 str = strbak;
1737 if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
1738 return;
1742 static int
1743 reglow_required_here (char **str, int shift)
1745 static char buff[MAX_LITERAL_POOL_SIZE];
1746 int reg;
1747 char *start = *str;
1749 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1751 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
1753 as_warn (_("Using temp register(r1)"));
1754 inst.bwarn = 1;
1756 if (reg < 16)
1758 if (shift >= 0)
1759 inst.instruction |= reg << shift;
1761 return reg;
1765 /* Restore the start point, we may have got a reg of the wrong class. */
1766 *str = start;
1767 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
1768 inst.error = buff;
1769 return (int) FAIL;
1772 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
1773 static void
1774 do16_rdrs (char *str)
1776 skip_whitespace (str);
1778 if (reglow_required_here (&str, 8) == (int) FAIL
1779 || skip_past_comma (&str) == (int) FAIL
1780 || reglow_required_here (&str, 4) == (int) FAIL
1781 || end_of_line (str) == (int) FAIL)
1783 return;
1785 else
1787 if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */
1789 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
1790 | (((inst.instruction >> 4) & 0xf) << 10);
1792 else if ((inst.instruction & 0x700f) == 0x2006) /* not! */
1794 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1795 | (((inst.instruction >> 4) & 0xf) << 15);
1797 else
1799 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1800 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
1802 inst.relax_size = 4;
1806 static void
1807 do16_rs (char *str)
1809 int rd = 0;
1811 skip_whitespace (str);
1813 if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
1814 || end_of_line (str) == (int) FAIL)
1816 return;
1818 else
1820 inst.relax_inst |= rd << 20;
1821 inst.relax_size = 4;
1825 /* Handle br!/brl!. */
1826 static void
1827 do16_xrs (char *str)
1829 skip_whitespace (str);
1831 if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
1833 return;
1835 else
1837 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
1838 | (((inst.instruction >> 4) & 0xf) << 15);
1839 inst.relax_size = 4;
1843 static int
1844 reghigh_required_here (char **str, int shift)
1846 static char buff[MAX_LITERAL_POOL_SIZE];
1847 int reg;
1848 char *start = *str;
1850 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1852 if (15 < reg && reg < 32)
1854 if (shift >= 0)
1855 inst.instruction |= (reg & 0xf) << shift;
1857 return reg;
1861 *str = start;
1862 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
1863 inst.error = buff;
1864 return (int) FAIL;
1867 /* Handle mhfl!. */
1868 static void
1869 do16_hrdrs (char *str)
1871 skip_whitespace (str);
1873 if (reghigh_required_here (&str, 8) != (int) FAIL
1874 && skip_past_comma (&str) != (int) FAIL
1875 && reglow_required_here (&str, 4) != (int) FAIL
1876 && end_of_line (str) != (int) FAIL)
1878 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
1879 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
1880 inst.relax_size = 4;
1884 /* Handle mlfh!. */
1885 static void
1886 do16_rdhrs (char *str)
1888 skip_whitespace (str);
1890 if (reglow_required_here (&str, 8) != (int) FAIL
1891 && skip_past_comma (&str) != (int) FAIL
1892 && reghigh_required_here (&str, 4) != (int) FAIL
1893 && end_of_line (str) != (int) FAIL)
1895 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1896 | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
1897 inst.relax_size = 4;
1901 /* We need to be able to fix up arbitrary expressions in some statements.
1902 This is so that we can handle symbols that are an arbitrary distance from
1903 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
1904 which returns part of an address in a form which will be valid for
1905 a data instruction. We do this by pushing the expression into a symbol
1906 in the expr_section, and creating a fix for that. */
1907 static fixS *
1908 fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1910 fixS *new_fix;
1912 switch (exp->X_op)
1914 case O_constant:
1915 case O_symbol:
1916 case O_add:
1917 case O_subtract:
1918 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
1919 break;
1920 default:
1921 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
1922 break;
1924 return new_fix;
1927 static void
1928 init_dependency_vector (void)
1930 int i;
1932 for (i = 0; i < vector_size; i++)
1933 memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
1935 return;
1938 static enum insn_type_for_dependency
1939 dependency_type_from_insn (char *insn_name)
1941 char name[INSN_NAME_LEN];
1942 const struct insn_to_dependency *tmp;
1944 strcpy (name, insn_name);
1945 tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
1947 if (tmp)
1948 return tmp->type;
1950 return D_all_insn;
1953 static int
1954 check_dependency (char *pre_insn, char *pre_reg,
1955 char *cur_insn, char *cur_reg, int *warn_or_error)
1957 int bubbles = 0;
1958 unsigned int i;
1959 enum insn_type_for_dependency pre_insn_type;
1960 enum insn_type_for_dependency cur_insn_type;
1962 pre_insn_type = dependency_type_from_insn (pre_insn);
1963 cur_insn_type = dependency_type_from_insn (cur_insn);
1965 for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
1967 if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
1968 && (D_all_insn == data_dependency_table[i].cur_insn_type
1969 || cur_insn_type == data_dependency_table[i].cur_insn_type)
1970 && (strcmp (data_dependency_table[i].pre_reg, "") == 0
1971 || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
1972 && (strcmp (data_dependency_table[i].cur_reg, "") == 0
1973 || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
1975 bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
1976 *warn_or_error = data_dependency_table[i].warn_or_error;
1977 break;
1981 return bubbles;
1984 static void
1985 build_one_frag (struct score_it one_inst)
1987 char *p;
1988 int relaxable_p = g_opt;
1989 int relax_size = 0;
1991 /* Start a new frag if frag_now is not empty. */
1992 if (frag_now_fix () != 0)
1994 if (!frag_now->tc_frag_data.is_insn)
1995 frag_wane (frag_now);
1997 frag_new (0);
1999 frag_grow (20);
2001 p = frag_more (one_inst.size);
2002 md_number_to_chars (p, one_inst.instruction, one_inst.size);
2004 #ifdef OBJ_ELF
2005 dwarf2_emit_insn (one_inst.size);
2006 #endif
2008 relaxable_p &= (one_inst.relax_size != 0);
2009 relax_size = relaxable_p ? one_inst.relax_size : 0;
2011 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2012 RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2013 one_inst.type, 0, 0, relaxable_p),
2014 NULL, 0, NULL);
2016 if (relaxable_p)
2017 md_number_to_chars (p, one_inst.relax_inst, relax_size);
2020 static void
2021 handle_dependency (struct score_it *theinst)
2023 int i;
2024 int warn_or_error = 0; /* warn - 0; error - 1 */
2025 int bubbles = 0;
2026 int remainder_bubbles = 0;
2027 char cur_insn[INSN_NAME_LEN];
2028 char pre_insn[INSN_NAME_LEN];
2029 struct score_it nop_inst;
2030 struct score_it pflush_inst;
2032 nop_inst.instruction = 0x0000;
2033 nop_inst.size = 2;
2034 nop_inst.relax_inst = 0x80008000;
2035 nop_inst.relax_size = 4;
2036 nop_inst.type = NO16_OPD;
2038 pflush_inst.instruction = 0x8000800a;
2039 pflush_inst.size = 4;
2040 pflush_inst.relax_inst = 0x8000;
2041 pflush_inst.relax_size = 0;
2042 pflush_inst.type = NO_OPD;
2044 /* pflush will clear all data dependency. */
2045 if (strcmp (theinst->name, "pflush") == 0)
2047 init_dependency_vector ();
2048 return;
2051 /* Push current instruction to dependency_vector[0]. */
2052 for (i = vector_size - 1; i > 0; i--)
2053 memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
2055 memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
2057 /* There is no dependency between nop and any instruction. */
2058 if (strcmp (dependency_vector[0].name, "nop") == 0
2059 || strcmp (dependency_vector[0].name, "nop!") == 0)
2060 return;
2062 /* "pce" is defined in insn_to_dependency_table. */
2063 #define PCE_NAME "pce"
2065 if (dependency_vector[0].type == Insn_Type_PCE)
2066 strcpy (cur_insn, PCE_NAME);
2067 else
2068 strcpy (cur_insn, dependency_vector[0].name);
2070 for (i = 1; i < vector_size; i++)
2072 /* The element of dependency_vector is NULL. */
2073 if (dependency_vector[i].name[0] == '\0')
2074 continue;
2076 if (dependency_vector[i].type == Insn_Type_PCE)
2077 strcpy (pre_insn, PCE_NAME);
2078 else
2079 strcpy (pre_insn, dependency_vector[i].name);
2081 bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
2082 cur_insn, dependency_vector[0].reg, &warn_or_error);
2083 remainder_bubbles = bubbles - i + 1;
2085 if (remainder_bubbles > 0)
2087 int j;
2089 if (fix_data_dependency == 1)
2091 if (remainder_bubbles <= 2)
2093 if (warn_fix_data_dependency)
2094 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2095 dependency_vector[i].name, dependency_vector[i].reg,
2096 dependency_vector[0].name, dependency_vector[0].reg,
2097 remainder_bubbles, bubbles);
2099 for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
2100 memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
2101 sizeof (dependency_vector[j]));
2103 for (j = 1; j <= remainder_bubbles; j++)
2105 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2106 /* Insert nop!. */
2107 build_one_frag (nop_inst);
2110 else
2112 if (warn_fix_data_dependency)
2113 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2114 dependency_vector[i].name, dependency_vector[i].reg,
2115 dependency_vector[0].name, dependency_vector[0].reg,
2116 bubbles);
2118 for (j = 1; j < vector_size; j++)
2119 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2121 /* Insert pflush. */
2122 build_one_frag (pflush_inst);
2125 else
2127 if (warn_or_error)
2129 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2130 dependency_vector[i].name, dependency_vector[i].reg,
2131 dependency_vector[0].name, dependency_vector[0].reg,
2132 remainder_bubbles, bubbles);
2134 else
2136 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2137 dependency_vector[i].name, dependency_vector[i].reg,
2138 dependency_vector[0].name, dependency_vector[0].reg,
2139 remainder_bubbles, bubbles);
2146 static enum insn_class
2147 get_insn_class_from_type (enum score_insn_type type)
2149 enum insn_class retval = (int) FAIL;
2151 switch (type)
2153 case Rd_I4:
2154 case Rd_I5:
2155 case Rd_rvalueBP_I5:
2156 case Rd_lvalueBP_I5:
2157 case Rd_I8:
2158 case PC_DISP8div2:
2159 case PC_DISP11div2:
2160 case Rd_Rs:
2161 case Rd_HighRs:
2162 case Rd_lvalueRs:
2163 case Rd_rvalueRs:
2164 case x_Rs:
2165 case Rd_LowRs:
2166 case NO16_OPD:
2167 retval = INSN_CLASS_16;
2168 break;
2169 case Rd_Rs_I5:
2170 case x_Rs_I5:
2171 case x_I5_x:
2172 case Rd_Rs_I14:
2173 case I15:
2174 case Rd_I16:
2175 case Rd_SI16:
2176 case Rd_rvalueRs_SI10:
2177 case Rd_lvalueRs_SI10:
2178 case Rd_rvalueRs_preSI12:
2179 case Rd_rvalueRs_postSI12:
2180 case Rd_lvalueRs_preSI12:
2181 case Rd_lvalueRs_postSI12:
2182 case Rd_Rs_SI14:
2183 case Rd_rvalueRs_SI15:
2184 case Rd_lvalueRs_SI15:
2185 case PC_DISP19div2:
2186 case PC_DISP24div2:
2187 case Rd_Rs_Rs:
2188 case x_Rs_x:
2189 case x_Rs_Rs:
2190 case Rd_Rs_x:
2191 case Rd_x_Rs:
2192 case Rd_x_x:
2193 case OP5_rvalueRs_SI15:
2194 case I5_Rs_Rs_I5_OP5:
2195 case x_rvalueRs_post4:
2196 case Rd_rvalueRs_post4:
2197 case Rd_x_I5:
2198 case Rd_lvalueRs_post4:
2199 case x_lvalueRs_post4:
2200 case Rd_Rs_Rs_imm:
2201 case NO_OPD:
2202 case Rd_lvalue32Rs:
2203 case Rd_rvalue32Rs:
2204 case Insn_GP:
2205 case Insn_PIC:
2206 case Insn_internal:
2207 retval = INSN_CLASS_32;
2208 break;
2209 case Insn_Type_PCE:
2210 retval = INSN_CLASS_PCE;
2211 break;
2212 case Insn_Type_SYN:
2213 retval = INSN_CLASS_SYN;
2214 break;
2215 default:
2216 abort ();
2217 break;
2219 return retval;
2222 static unsigned long
2223 adjust_paritybit (unsigned long m_code, enum insn_class class)
2225 unsigned long result = 0;
2226 unsigned long m_code_high = 0;
2227 unsigned long m_code_low = 0;
2228 unsigned long pb_high = 0;
2229 unsigned long pb_low = 0;
2231 if (class == INSN_CLASS_32)
2233 pb_high = 0x80000000;
2234 pb_low = 0x00008000;
2236 else if (class == INSN_CLASS_16)
2238 pb_high = 0;
2239 pb_low = 0;
2241 else if (class == INSN_CLASS_PCE)
2243 pb_high = 0;
2244 pb_low = 0x00008000;
2246 else if (class == INSN_CLASS_SYN)
2248 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2249 be changed if macro instruction has been expanded. */
2250 pb_high = 0x80000000;
2251 pb_low = 0x00008000;
2253 else
2255 abort ();
2258 m_code_high = m_code & 0x3fff8000;
2259 m_code_low = m_code & 0x00007fff;
2260 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2261 return result;
2265 static void
2266 gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
2268 char *p;
2269 bfd_boolean pce_p = FALSE;
2270 int relaxable_p = g_opt;
2271 int relax_size = 0;
2272 struct score_it *inst1 = part_1;
2273 struct score_it *inst2 = part_2;
2274 struct score_it backup_inst1;
2276 pce_p = (inst2) ? TRUE : FALSE;
2277 memcpy (&backup_inst1, inst1, sizeof (struct score_it));
2279 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2280 if (pce_p)
2282 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2283 | (inst2->instruction & 0x7FFF);
2284 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2285 backup_inst1.relax_inst = 0x8000;
2286 backup_inst1.size = INSN_SIZE;
2287 backup_inst1.relax_size = 0;
2288 backup_inst1.type = Insn_Type_PCE;
2290 else
2292 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
2293 GET_INSN_CLASS (backup_inst1.type));
2296 if (backup_inst1.relax_size != 0)
2298 enum insn_class tmp;
2300 tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2301 backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
2304 /* Check data dependency. */
2305 handle_dependency (&backup_inst1);
2307 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2308 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2309 if (frag_now_fix () != 0)
2311 if (!frag_now->tc_frag_data.is_insn)
2312 frag_wane (frag_now);
2314 frag_new (0);
2317 /* Here, we must call frag_grow in order to keep the instruction frag type is
2318 rs_machine_dependent.
2319 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2320 acturally will call frag_wane.
2321 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2322 for frag_var. */
2323 frag_grow (20);
2325 p = frag_more (backup_inst1.size);
2326 md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2328 #ifdef OBJ_ELF
2329 dwarf2_emit_insn (backup_inst1.size);
2330 #endif
2332 /* Generate fixup structure. */
2333 if (pce_p)
2335 if (inst1->reloc.type != BFD_RELOC_NONE)
2336 fix_new_score (frag_now, p - frag_now->fr_literal,
2337 inst1->size, &inst1->reloc.exp,
2338 inst1->reloc.pc_rel, inst1->reloc.type);
2340 if (inst2->reloc.type != BFD_RELOC_NONE)
2341 fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2342 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2344 else
2346 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2347 fix_new_score (frag_now, p - frag_now->fr_literal,
2348 backup_inst1.size, &backup_inst1.reloc.exp,
2349 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2352 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2353 relaxable_p &= (backup_inst1.relax_size != 0);
2354 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2356 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2357 RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2358 backup_inst1.type, 0, 0, relaxable_p),
2359 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2361 if (relaxable_p)
2362 md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2364 memcpy (inst1, &backup_inst1, sizeof (struct score_it));
2367 static void
2368 parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2370 char c;
2371 char *p;
2372 char *operator = insnstr;
2373 const struct asm_opcode *opcode;
2375 /* Parse operator and operands. */
2376 skip_whitespace (operator);
2378 for (p = operator; *p != '\0'; p++)
2379 if ((*p == ' ') || (*p == '!'))
2380 break;
2382 if (*p == '!')
2383 p++;
2385 c = *p;
2386 *p = '\0';
2388 opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
2389 *p = c;
2391 memset (&inst, '\0', sizeof (inst));
2392 sprintf (inst.str, "%s", insnstr);
2393 if (opcode)
2395 inst.instruction = opcode->value;
2396 inst.relax_inst = opcode->relax_value;
2397 inst.type = opcode->type;
2398 inst.size = GET_INSN_SIZE (inst.type);
2399 inst.relax_size = 0;
2400 inst.bwarn = 0;
2401 sprintf (inst.name, "%s", opcode->template);
2402 strcpy (inst.reg, "");
2403 inst.error = NULL;
2404 inst.reloc.type = BFD_RELOC_NONE;
2406 (*opcode->parms) (p);
2408 /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */
2409 if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
2410 gen_insn_frag (&inst, NULL);
2412 else
2413 inst.error = _("unrecognized opcode");
2416 static int
2417 append_insn (char *str, bfd_boolean gen_frag_p)
2419 int retval = SUCCESS;
2421 parse_16_32_inst (str, gen_frag_p);
2423 if (inst.error)
2425 retval = (int) FAIL;
2426 as_bad (_("%s -- `%s'"), inst.error, inst.str);
2427 inst.error = NULL;
2430 return retval;
2433 /* Handle mv! reg_high, reg_low;
2434 mv! reg_low, reg_high;
2435 mv! reg_low, reg_low; */
2436 static void
2437 do16_mv_rdrs (char *str)
2439 int reg_rd;
2440 int reg_rs;
2441 char *backupstr = NULL;
2443 backupstr = str;
2444 skip_whitespace (str);
2446 if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
2447 || skip_past_comma (&str) == (int) FAIL
2448 || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
2449 || end_of_line (str) == (int) FAIL)
2451 return;
2453 else
2455 /* Case 1 : mv! or mlfh!. */
2456 if (reg_rd < 16)
2458 if (reg_rs < 16)
2460 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2461 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2462 inst.relax_size = 4;
2464 else
2466 char append_str[MAX_LITERAL_POOL_SIZE];
2468 sprintf (append_str, "mlfh! %s", backupstr);
2469 if (append_insn (append_str, TRUE) == (int) FAIL)
2470 return;
2471 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2472 inst.bwarn = -1;
2475 /* Case 2 : mhfl!. */
2476 else
2478 if (reg_rs > 16)
2480 SET_INSN_ERROR (BAD_ARGS);
2481 return;
2483 else
2485 char append_str[MAX_LITERAL_POOL_SIZE];
2487 sprintf (append_str, "mhfl! %s", backupstr);
2488 if (append_insn (append_str, TRUE) == (int) FAIL)
2489 return;
2491 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2492 inst.bwarn = -1;
2498 static void
2499 do16_rdi4 (char *str)
2501 skip_whitespace (str);
2503 if (reglow_required_here (&str, 8) == (int) FAIL
2504 || skip_past_comma (&str) == (int) FAIL
2505 || data_op2 (&str, 3, _IMM4) == (int) FAIL
2506 || end_of_line (str) == (int) FAIL)
2508 return;
2510 else
2512 if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2514 if (((inst.instruction >> 3) & 0xf) != 0xf)
2516 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2517 | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
2518 inst.relax_size = 4;
2520 else
2522 inst.relax_inst = 0x8000;
2525 else
2527 if (((inst.instruction >> 3) & 0xf) != 0xf)
2529 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2530 | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2531 inst.relax_size = 4;
2533 else
2535 inst.relax_inst = 0x8000;
2541 static void
2542 do16_rdi5 (char *str)
2544 skip_whitespace (str);
2546 if (reglow_required_here (&str, 8) == (int) FAIL
2547 || skip_past_comma (&str) == (int) FAIL
2548 || data_op2 (&str, 3, _IMM5) == (int) FAIL
2549 || end_of_line (str) == (int) FAIL)
2550 return;
2551 else
2553 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2554 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
2555 inst.relax_size = 4;
2559 /* Handle sdbbp. */
2560 static void
2561 do16_xi5 (char *str)
2563 skip_whitespace (str);
2565 if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
2566 return;
2567 else
2569 inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
2570 inst.relax_size = 4;
2574 /* Check that an immediate is word alignment or half word alignment.
2575 If so, convert it to the right format. */
2576 static int
2577 validate_immediate_align (int val, unsigned int data_type)
2579 if (data_type == _IMM5_RSHIFT_1)
2581 if (val % 2)
2583 inst.error = _("address offset must be half word alignment");
2584 return (int) FAIL;
2587 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2589 if (val % 4)
2591 inst.error = _("address offset must be word alignment");
2592 return (int) FAIL;
2596 return SUCCESS;
2599 static int
2600 exp_ldst_offset (char **str, int shift, unsigned int data_type)
2602 char *dataptr;
2604 dataptr = * str;
2606 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2607 && (data_type != _SIMM16_LA)
2608 && (data_type != _VALUE_HI16)
2609 && (data_type != _VALUE_LO16)
2610 && (data_type != _IMM16)
2611 && (data_type != _IMM15)
2612 && (data_type != _IMM14)
2613 && (data_type != _IMM4)
2614 && (data_type != _IMM5)
2615 && (data_type != _IMM8)
2616 && (data_type != _IMM5_RSHIFT_1)
2617 && (data_type != _IMM5_RSHIFT_2)
2618 && (data_type != _SIMM14_NEG)
2619 && (data_type != _IMM10_RSHIFT_2))
2621 data_type += 24;
2624 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
2625 return (int) FAIL;
2627 if (inst.reloc.exp.X_op == O_constant)
2629 /* Need to check the immediate align. */
2630 int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
2632 if (value == (int) FAIL)
2633 return (int) FAIL;
2635 value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
2636 if (value == (int) FAIL)
2638 if (data_type < 30)
2639 sprintf (err_msg,
2640 _("invalid constant: %d bit expression not in range %d..%d"),
2641 score_df_range[data_type].bits,
2642 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2643 else
2644 sprintf (err_msg,
2645 _("invalid constant: %d bit expression not in range %d..%d"),
2646 score_df_range[data_type - 24].bits,
2647 score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
2648 inst.error = err_msg;
2649 return (int) FAIL;
2652 if (data_type == _IMM5_RSHIFT_1)
2654 value >>= 1;
2656 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2658 value >>= 2;
2661 if (score_df_range[data_type].range[0] != 0)
2663 value &= (1 << score_df_range[data_type].bits) - 1;
2666 inst.instruction |= value << shift;
2668 else
2670 inst.reloc.pc_rel = 0;
2673 return SUCCESS;
2676 static void
2677 do_ldst_insn (char *str)
2679 int pre_inc = 0;
2680 int conflict_reg;
2681 int value;
2682 char * temp;
2683 char *strbak;
2684 char *dataptr;
2685 int reg;
2686 int ldst_idx = 0;
2688 strbak = str;
2689 skip_whitespace (str);
2691 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
2692 || (skip_past_comma (&str) == (int) FAIL))
2693 return;
2695 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
2696 if (*str == '[')
2698 str++;
2699 skip_whitespace (str);
2701 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
2702 return;
2704 /* Conflicts can occur on stores as well as loads. */
2705 conflict_reg = (conflict_reg == reg);
2706 skip_whitespace (str);
2707 temp = str + 1; /* The latter will process decimal/hex expression. */
2709 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
2710 if (*str == ']')
2712 str++;
2713 if (*str == '+')
2715 str++;
2716 /* ld/sw rD, [rA]+, simm12. */
2717 if (skip_past_comma (&str) == SUCCESS)
2719 if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
2720 || (end_of_line (str) == (int) FAIL))
2721 return;
2723 if (conflict_reg)
2725 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2727 if ((ldst_func == INSN_LH)
2728 || (ldst_func == INSN_LHU)
2729 || (ldst_func == INSN_LW)
2730 || (ldst_func == INSN_LB)
2731 || (ldst_func == INSN_LBU))
2733 inst.error = _("register same as write-back base");
2734 return;
2738 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2739 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2740 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2742 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
2743 if ((inst.instruction & 0x3e000007) == 0x0e000000)
2745 /* rs = r0-r7, offset = 4 */
2746 if ((((inst.instruction >> 15) & 0x18) == 0)
2747 && (((inst.instruction >> 3) & 0xfff) == 4))
2749 /* Relax to pophi. */
2750 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2752 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2753 << 8) | 1 << 7 |
2754 (((inst.instruction >> 15) & 0x7) << 4);
2756 /* Relax to pop. */
2757 else
2759 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2760 << 8) | 0 << 7 |
2761 (((inst.instruction >> 15) & 0x7) << 4);
2763 inst.relax_size = 2;
2766 return;
2768 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
2769 else
2771 SET_INSN_ERROR (NULL);
2772 if (end_of_line (str) == (int) FAIL)
2774 return;
2777 pre_inc = 1;
2778 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0);
2779 value &= (1 << score_df_range[_SIMM12].bits) - 1;
2780 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2781 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2782 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2783 inst.instruction |= value << 3;
2784 inst.relax_inst = 0x8000;
2785 return;
2788 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
2789 else
2791 if (end_of_line (str) == (int) FAIL)
2792 return;
2794 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2795 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2796 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
2798 /* lbu rd, [rs] -> lbu! rd, [rs] */
2799 if (ldst_idx == INSN_LBU)
2801 inst.relax_inst = INSN16_LBU;
2803 else if (ldst_idx == INSN_LH)
2805 inst.relax_inst = INSN16_LH;
2807 else if (ldst_idx == INSN_LW)
2809 inst.relax_inst = INSN16_LW;
2811 else if (ldst_idx == INSN_SB)
2813 inst.relax_inst = INSN16_SB;
2815 else if (ldst_idx == INSN_SH)
2817 inst.relax_inst = INSN16_SH;
2819 else if (ldst_idx == INSN_SW)
2821 inst.relax_inst = INSN16_SW;
2823 else
2825 inst.relax_inst = 0x8000;
2828 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
2829 if ((ldst_idx == INSN_LBU)
2830 || (ldst_idx == INSN_LH)
2831 || (ldst_idx == INSN_LW)
2832 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
2834 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2836 inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
2837 (((inst.instruction >> 15) & 0xf) << 4);
2838 inst.relax_size = 2;
2842 return;
2845 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
2846 else
2848 if (skip_past_comma (&str) == (int) FAIL)
2850 inst.error = _("pre-indexed expression expected");
2851 return;
2854 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
2855 return;
2857 skip_whitespace (str);
2858 if (*str++ != ']')
2860 inst.error = _("missing ]");
2861 return;
2864 skip_whitespace (str);
2865 /* ld/sw rD, [rA, simm12]+. */
2866 if (*str == '+')
2868 str++;
2869 pre_inc = 1;
2870 if (conflict_reg)
2872 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2874 if ((ldst_func == INSN_LH)
2875 || (ldst_func == INSN_LHU)
2876 || (ldst_func == INSN_LW)
2877 || (ldst_func == INSN_LB)
2878 || (ldst_func == INSN_LBU))
2880 inst.error = _("register same as write-back base");
2881 return;
2886 if (end_of_line (str) == (int) FAIL)
2887 return;
2889 if (inst.reloc.exp.X_op == O_constant)
2891 int value;
2892 unsigned int data_type;
2894 if (pre_inc == 1)
2895 data_type = _SIMM12;
2896 else
2897 data_type = _SIMM15;
2898 dataptr = temp;
2900 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2901 && (data_type != _SIMM16_LA)
2902 && (data_type != _VALUE_HI16)
2903 && (data_type != _VALUE_LO16)
2904 && (data_type != _IMM16)
2905 && (data_type != _IMM15)
2906 && (data_type != _IMM14)
2907 && (data_type != _IMM4)
2908 && (data_type != _IMM5)
2909 && (data_type != _IMM8)
2910 && (data_type != _IMM5_RSHIFT_1)
2911 && (data_type != _IMM5_RSHIFT_2)
2912 && (data_type != _SIMM14_NEG)
2913 && (data_type != _IMM10_RSHIFT_2))
2915 data_type += 24;
2918 value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
2919 if (value == (int) FAIL)
2921 if (data_type < 30)
2922 sprintf (err_msg,
2923 _("invalid constant: %d bit expression not in range %d..%d"),
2924 score_df_range[data_type].bits,
2925 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2926 else
2927 sprintf (err_msg,
2928 _("invalid constant: %d bit expression not in range %d..%d"),
2929 score_df_range[data_type - 24].bits,
2930 score_df_range[data_type - 24].range[0],
2931 score_df_range[data_type - 24].range[1]);
2932 inst.error = err_msg;
2933 return;
2936 value &= (1 << score_df_range[data_type].bits) - 1;
2937 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2938 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2939 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2940 if (pre_inc == 1)
2941 inst.instruction |= value << 3;
2942 else
2943 inst.instruction |= value;
2945 /* lw rD, [rA, simm15] */
2946 if ((inst.instruction & 0x3e000000) == 0x20000000)
2948 /* Both rD and rA are in [r0 - r15]. */
2949 if ((((inst.instruction >> 15) & 0x10) == 0)
2950 && (((inst.instruction >> 20) & 0x10) == 0))
2952 /* simm15 = 0, lw -> lw!. */
2953 if ((inst.instruction & 0x7fff) == 0)
2955 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2956 | (((inst.instruction >> 20) & 0xf) << 8);
2957 inst.relax_size = 2;
2959 /* rA = r2, lw -> lwp!. */
2960 else if ((((inst.instruction >> 15) & 0xf) == 2)
2961 && ((inst.instruction & 0x3) == 0)
2962 && ((inst.instruction & 0x7fff) < 128))
2964 inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
2965 | (((inst.instruction & 0x7fff) >> 2) << 3);
2966 inst.relax_size = 2;
2968 else
2970 inst.relax_inst = 0x8000;
2973 else
2975 inst.relax_inst = 0x8000;
2978 /* sw rD, [rA, simm15] */
2979 else if ((inst.instruction & 0x3e000000) == 0x28000000)
2981 /* Both rD and rA are in [r0 - r15]. */
2982 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2984 /* simm15 = 0, sw -> sw!. */
2985 if ((inst.instruction & 0x7fff) == 0)
2987 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2988 | (((inst.instruction >> 20) & 0xf) << 8);
2989 inst.relax_size = 2;
2991 /* rA = r2, sw -> swp!. */
2992 else if ((((inst.instruction >> 15) & 0xf) == 2)
2993 && ((inst.instruction & 0x3) == 0)
2994 && ((inst.instruction & 0x7fff) < 128))
2996 inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
2997 | (((inst.instruction & 0x7fff) >> 2) << 3);
2998 inst.relax_size = 2;
3000 else
3002 inst.relax_inst = 0x8000;
3005 else
3007 inst.relax_inst = 0x8000;
3010 /* sw rD, [rA, simm15]+ sw pre. */
3011 else if ((inst.instruction & 0x3e000007) == 0x06000004)
3013 /* rA is in [r0 - r7], and simm15 = -4. */
3014 if ((((inst.instruction >> 15) & 0x18) == 0)
3015 && (((inst.instruction >> 3) & 0xfff) == 0xffc))
3017 /* sw -> pushhi!. */
3018 if ((((inst.instruction >> 20) & 0x10) == 0x10))
3020 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3021 | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3022 inst.relax_size = 2;
3024 /* sw -> push!. */
3025 else
3027 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3028 | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3029 inst.relax_size = 2;
3032 else
3034 inst.relax_inst = 0x8000;
3037 /* lh rD, [rA, simm15] */
3038 else if ((inst.instruction & 0x3e000000) == 0x22000000)
3040 /* Both rD and rA are in [r0 - r15]. */
3041 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3043 /* simm15 = 0, lh -> lh!. */
3044 if ((inst.instruction & 0x7fff) == 0)
3046 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3047 | (((inst.instruction >> 20) & 0xf) << 8);
3048 inst.relax_size = 2;
3050 /* rA = r2, lh -> lhp!. */
3051 else if ((((inst.instruction >> 15) & 0xf) == 2)
3052 && ((inst.instruction & 0x1) == 0)
3053 && ((inst.instruction & 0x7fff) < 64))
3055 inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
3056 | (((inst.instruction & 0x7fff) >> 1) << 3);
3057 inst.relax_size = 2;
3059 else
3061 inst.relax_inst = 0x8000;
3064 else
3066 inst.relax_inst = 0x8000;
3069 /* sh rD, [rA, simm15] */
3070 else if ((inst.instruction & 0x3e000000) == 0x2a000000)
3072 /* Both rD and rA are in [r0 - r15]. */
3073 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3075 /* simm15 = 0, sh -> sh!. */
3076 if ((inst.instruction & 0x7fff) == 0)
3078 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3079 | (((inst.instruction >> 20) & 0xf) << 8);
3080 inst.relax_size = 2;
3082 /* rA = r2, sh -> shp!. */
3083 else if ((((inst.instruction >> 15) & 0xf) == 2)
3084 && ((inst.instruction & 0x1) == 0)
3085 && ((inst.instruction & 0x7fff) < 64))
3087 inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
3088 | (((inst.instruction & 0x7fff) >> 1) << 3);
3089 inst.relax_size = 2;
3091 else
3093 inst.relax_inst = 0x8000;
3096 else
3098 inst.relax_inst = 0x8000;
3101 /* lbu rD, [rA, simm15] */
3102 else if ((inst.instruction & 0x3e000000) == 0x2c000000)
3104 /* Both rD and rA are in [r0 - r15]. */
3105 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3107 /* simm15 = 0, lbu -> lbu!. */
3108 if ((inst.instruction & 0x7fff) == 0)
3110 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3111 | (((inst.instruction >> 20) & 0xf) << 8);
3112 inst.relax_size = 2;
3114 /* rA = r2, lbu -> lbup!. */
3115 else if ((((inst.instruction >> 15) & 0xf) == 2)
3116 && ((inst.instruction & 0x7fff) < 32))
3118 inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
3119 | ((inst.instruction & 0x7fff) << 3);
3120 inst.relax_size = 2;
3122 else
3124 inst.relax_inst = 0x8000;
3127 else
3129 inst.relax_inst = 0x8000;
3132 /* sb rD, [rA, simm15] */
3133 else if ((inst.instruction & 0x3e000000) == 0x2e000000)
3135 /* Both rD and rA are in [r0 - r15]. */
3136 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3138 /* simm15 = 0, sb -> sb!. */
3139 if ((inst.instruction & 0x7fff) == 0)
3141 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3142 | (((inst.instruction >> 20) & 0xf) << 8);
3143 inst.relax_size = 2;
3145 /* rA = r2, sb -> sb!. */
3146 else if ((((inst.instruction >> 15) & 0xf) == 2)
3147 && ((inst.instruction & 0x7fff) < 32))
3149 inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
3150 | ((inst.instruction & 0x7fff) << 3);
3151 inst.relax_size = 2;
3153 else
3155 inst.relax_inst = 0x8000;
3158 else
3160 inst.relax_inst = 0x8000;
3163 else
3165 inst.relax_inst = 0x8000;
3168 return;
3170 else
3172 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3173 inst.reloc.pc_rel = 0;
3177 else
3179 inst.error = BAD_ARGS;
3183 /* Handle cache. */
3185 static void
3186 do_cache (char *str)
3188 skip_whitespace (str);
3190 if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3192 return;
3194 else
3196 int cache_op;
3198 cache_op = (inst.instruction >> 20) & 0x1F;
3199 sprintf (inst.name, "cache %d", cache_op);
3202 if (*str == '[')
3204 str++;
3205 skip_whitespace (str);
3207 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3208 return;
3210 skip_whitespace (str);
3212 /* cache op, [rA] */
3213 if (skip_past_comma (&str) == (int) FAIL)
3215 SET_INSN_ERROR (NULL);
3216 if (*str != ']')
3218 inst.error = _("missing ]");
3219 return;
3221 str++;
3223 /* cache op, [rA, simm15] */
3224 else
3226 if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
3228 return;
3231 skip_whitespace (str);
3232 if (*str++ != ']')
3234 inst.error = _("missing ]");
3235 return;
3239 if (end_of_line (str) == (int) FAIL)
3240 return;
3242 else
3244 inst.error = BAD_ARGS;
3248 static void
3249 do_crdcrscrsimm5 (char *str)
3251 char *strbak;
3253 strbak = str;
3254 skip_whitespace (str);
3256 if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
3257 || skip_past_comma (&str) == (int) FAIL
3258 || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
3259 || skip_past_comma (&str) == (int) FAIL
3260 || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
3261 || skip_past_comma (&str) == (int) FAIL)
3263 str = strbak;
3264 /* cop1 cop_code20. */
3265 if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
3266 return;
3268 else
3270 if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
3271 return;
3274 end_of_line (str);
3277 /* Handle ldc/stc. */
3278 static void
3279 do_ldst_cop (char *str)
3281 skip_whitespace (str);
3283 if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
3284 || (skip_past_comma (&str) == (int) FAIL))
3285 return;
3287 if (*str == '[')
3289 str++;
3290 skip_whitespace (str);
3292 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3293 return;
3295 skip_whitespace (str);
3297 if (*str++ != ']')
3299 if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
3300 return;
3302 skip_whitespace (str);
3303 if (*str++ != ']')
3305 inst.error = _("missing ]");
3306 return;
3310 end_of_line (str);
3312 else
3313 inst.error = BAD_ARGS;
3316 static void
3317 do16_ldst_insn (char *str)
3319 skip_whitespace (str);
3321 if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3322 return;
3324 if (*str == '[')
3326 int reg;
3328 str++;
3329 skip_whitespace (str);
3331 if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
3332 return;
3334 skip_whitespace (str);
3335 if (*str++ == ']')
3337 if (end_of_line (str) == (int) FAIL)
3338 return;
3339 else
3341 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3342 | (((inst.instruction >> 4) & 0xf) << 15);
3343 inst.relax_size = 4;
3346 else
3348 inst.error = _("missing ]");
3351 else
3353 inst.error = BAD_ARGS;
3357 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3358 static void
3359 do16_ldst_imm_insn (char *str)
3361 char data_exp[MAX_LITERAL_POOL_SIZE];
3362 int reg_rd;
3363 char *dataptr = NULL, *pp = NULL;
3364 int cnt = 0;
3365 int assign_data = (int) FAIL;
3366 unsigned int ldst_func;
3368 skip_whitespace (str);
3370 if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
3371 || (skip_past_comma (&str) == (int) FAIL))
3372 return;
3374 skip_whitespace (str);
3375 dataptr = str;
3377 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
3379 data_exp[cnt] = *dataptr;
3380 dataptr++;
3381 cnt++;
3384 data_exp[cnt] = '\0';
3385 pp = &data_exp[0];
3387 str = dataptr;
3389 ldst_func = inst.instruction & LDST16_RI_MASK;
3390 if (ldst_func == N16_LIU)
3391 assign_data = exp_ldst_offset (&pp, 0, _IMM8);
3392 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3393 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3394 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3395 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3396 else
3397 assign_data = exp_ldst_offset (&pp, 3, _IMM5);
3399 if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
3400 return;
3401 else
3403 if ((inst.instruction & 0x7000) == N16_LIU)
3405 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
3406 | ((inst.instruction & 0xff) << 1);
3408 else if (((inst.instruction & 0x7007) == N16_LHP)
3409 || ((inst.instruction & 0x7007) == N16_SHP))
3411 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3412 | (((inst.instruction >> 3) & 0x1f) << 1);
3414 else if (((inst.instruction & 0x7007) == N16_LWP)
3415 || ((inst.instruction & 0x7007) == N16_SWP))
3417 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3418 | (((inst.instruction >> 3) & 0x1f) << 2);
3420 else if (((inst.instruction & 0x7007) == N16_LBUP)
3421 || ((inst.instruction & 0x7007) == N16_SBP))
3423 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3424 | (((inst.instruction >> 3) & 0x1f));
3427 inst.relax_size = 4;
3431 static void
3432 do16_push_pop (char *str)
3434 int reg_rd;
3435 int H_bit_mask = 0;
3437 skip_whitespace (str);
3438 if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
3439 || (skip_past_comma (&str) == (int) FAIL))
3440 return;
3442 if (reg_rd >= 16)
3443 H_bit_mask = 1;
3445 /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3446 inst.instruction &= ~(1 << 12);
3448 inst.instruction |= H_bit_mask << 7;
3450 if (*str == '[')
3452 int reg;
3454 str++;
3455 skip_whitespace (str);
3456 if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
3457 return;
3458 else if (reg > 7)
3460 if (!inst.error)
3461 inst.error = _("base register nums are over 3 bit");
3463 return;
3466 skip_whitespace (str);
3467 if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
3469 if (!inst.error)
3470 inst.error = _("missing ]");
3472 return;
3475 /* pop! */
3476 if ((inst.instruction & 0xf) == 0xa)
3478 if (H_bit_mask)
3480 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3481 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3483 else
3485 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3486 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3489 /* push! */
3490 else
3492 if (H_bit_mask)
3494 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3495 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3497 else
3499 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3500 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3503 inst.relax_size = 4;
3505 else
3507 inst.error = BAD_ARGS;
3511 /* Handle lcb/lcw/lce/scb/scw/sce. */
3512 static void
3513 do_ldst_unalign (char *str)
3515 int conflict_reg;
3517 if (university_version == 1)
3519 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3520 return;
3523 skip_whitespace (str);
3525 /* lcb/scb [rA]+. */
3526 if (*str == '[')
3528 str++;
3529 skip_whitespace (str);
3531 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3532 return;
3534 if (*str++ == ']')
3536 if (*str++ != '+')
3538 inst.error = _("missing +");
3539 return;
3542 else
3544 inst.error = _("missing ]");
3545 return;
3548 if (end_of_line (str) == (int) FAIL)
3549 return;
3551 /* lcw/lce/scb/sce rD, [rA]+. */
3552 else
3554 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
3555 || (skip_past_comma (&str) == (int) FAIL))
3557 return;
3560 skip_whitespace (str);
3561 if (*str++ == '[')
3563 int reg;
3565 skip_whitespace (str);
3566 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3568 return;
3571 /* Conflicts can occur on stores as well as loads. */
3572 conflict_reg = (conflict_reg == reg);
3573 skip_whitespace (str);
3574 if (*str++ == ']')
3576 unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
3578 if (*str++ == '+')
3580 if (conflict_reg)
3582 as_warn (_("%s register same as write-back base"),
3583 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3584 ? _("destination") : _("source")));
3587 else
3589 inst.error = _("missing +");
3590 return;
3593 if (end_of_line (str) == (int) FAIL)
3594 return;
3596 else
3598 inst.error = _("missing ]");
3599 return;
3602 else
3604 inst.error = BAD_ARGS;
3605 return;
3610 /* Handle alw/asw. */
3611 static void
3612 do_ldst_atomic (char *str)
3614 if (university_version == 1)
3616 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3617 return;
3620 skip_whitespace (str);
3622 if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3623 || (skip_past_comma (&str) == (int) FAIL))
3625 return;
3627 else
3630 skip_whitespace (str);
3631 if (*str++ == '[')
3633 int reg;
3635 skip_whitespace (str);
3636 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3638 return;
3641 skip_whitespace (str);
3642 if (*str++ != ']')
3644 inst.error = _("missing ]");
3645 return;
3648 end_of_line (str);
3650 else
3651 inst.error = BAD_ARGS;
3655 static void
3656 build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3657 struct score_it var_insts[RELAX_INST_NUM], int var_num,
3658 symbolS *add_symbol)
3660 int i;
3661 char *p;
3662 fixS *fixp = NULL;
3663 fixS *cur_fixp = NULL;
3664 long where;
3665 struct score_it inst_main;
3667 memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
3669 /* Adjust instruction opcode and to be relaxed instruction opcode. */
3670 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
3671 inst_main.type = Insn_PIC;
3673 for (i = 0; i < var_num; i++)
3675 inst_main.relax_size += var_insts[i].size;
3676 var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
3677 GET_INSN_CLASS (var_insts[i].type));
3680 /* Check data dependency. */
3681 handle_dependency (&inst_main);
3683 /* Start a new frag if frag_now is not empty. */
3684 if (frag_now_fix () != 0)
3686 if (!frag_now->tc_frag_data.is_insn)
3688 frag_wane (frag_now);
3690 frag_new (0);
3692 frag_grow (20);
3694 /* Write fr_fix part. */
3695 p = frag_more (inst_main.size);
3696 md_number_to_chars (p, inst_main.instruction, inst_main.size);
3698 if (inst_main.reloc.type != BFD_RELOC_NONE)
3699 fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
3700 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
3702 frag_now->tc_frag_data.fixp = fixp;
3703 cur_fixp = frag_now->tc_frag_data.fixp;
3705 #ifdef OBJ_ELF
3706 dwarf2_emit_insn (inst_main.size);
3707 #endif
3709 where = p - frag_now->fr_literal + inst_main.size;
3710 for (i = 0; i < var_num; i++)
3712 if (i > 0)
3713 where += var_insts[i - 1].size;
3715 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
3717 fixp = fix_new_score (frag_now, where, var_insts[i].size,
3718 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
3719 var_insts[i].reloc.type);
3720 if (fixp)
3722 if (cur_fixp)
3724 cur_fixp->fx_next = fixp;
3725 cur_fixp = cur_fixp->fx_next;
3727 else
3729 frag_now->tc_frag_data.fixp = fixp;
3730 cur_fixp = frag_now->tc_frag_data.fixp;
3736 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
3737 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
3738 0, inst_main.size, 0), add_symbol, 0, NULL);
3740 /* Write fr_var part.
3741 no calling gen_insn_frag, no fixS will be generated. */
3742 for (i = 0; i < var_num; i++)
3744 md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
3745 p += var_insts[i].size;
3747 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3748 inst.bwarn = -1;
3751 /* Build a relax frag for la instruction when generating PIC,
3752 external symbol first and local symbol second. */
3754 static void
3755 build_la_pic (int reg_rd, expressionS exp)
3757 symbolS *add_symbol = exp.X_add_symbol;
3758 offsetT add_number = exp.X_add_number;
3759 struct score_it fix_insts[RELAX_INST_NUM];
3760 struct score_it var_insts[RELAX_INST_NUM];
3761 int fix_num = 0;
3762 int var_num = 0;
3763 char tmp[MAX_LITERAL_POOL_SIZE];
3764 int r1_bak;
3766 r1_bak = nor1;
3767 nor1 = 0;
3769 if (add_number == 0)
3771 fix_num = 1;
3772 var_num = 2;
3774 /* For an external symbol, only one insn is generated;
3775 For a local symbol, two insns are generated. */
3776 /* Fix part
3777 For an external symbol: lw rD, <sym>($gp)
3778 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
3779 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3780 if (append_insn (tmp, FALSE) == (int) FAIL)
3781 return;
3783 if (reg_rd == PIC_CALL_REG)
3784 inst.reloc.type = BFD_RELOC_SCORE_CALL15;
3785 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3787 /* Var part
3788 For a local symbol :
3789 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
3790 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
3791 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
3792 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3793 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3794 if (append_insn (tmp, FALSE) == (int) FAIL)
3795 return;
3797 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
3798 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3800 else if (add_number >= -0x8000 && add_number <= 0x7fff)
3802 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3803 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3804 if (append_insn (tmp, TRUE) == (int) FAIL)
3805 return;
3807 /* Insn 2 */
3808 fix_num = 1;
3809 var_num = 1;
3810 /* Fix part
3811 For an external symbol: addi rD, <constant> */
3812 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
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 rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
3820 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
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 else
3829 int hi = (add_number >> 16) & 0x0000FFFF;
3830 int lo = add_number & 0x0000FFFF;
3832 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3833 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3834 if (append_insn (tmp, TRUE) == (int) FAIL)
3835 return;
3837 /* Insn 2 */
3838 fix_num = 1;
3839 var_num = 1;
3840 /* Fix part
3841 For an external symbol: ldis r1, HI%<constant> */
3842 sprintf (tmp, "ldis r1, %d", hi);
3843 if (append_insn (tmp, FALSE) == (int) FAIL)
3844 return;
3846 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3848 /* Var part
3849 For a local symbol: ldis r1, HI%<constant>
3850 but, if lo is outof 16 bit, make hi plus 1 */
3851 if ((lo < -0x8000) || (lo > 0x7fff))
3853 hi += 1;
3855 sprintf (tmp, "ldis_pic r1, %d", hi);
3856 if (append_insn (tmp, FALSE) == (int) FAIL)
3857 return;
3859 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3860 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3862 /* Insn 3 */
3863 fix_num = 1;
3864 var_num = 1;
3865 /* Fix part
3866 For an external symbol: ori r1, LO%<constant> */
3867 sprintf (tmp, "ori r1, %d", lo);
3868 if (append_insn (tmp, FALSE) == (int) FAIL)
3869 return;
3871 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3873 /* Var part
3874 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
3875 sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
3876 if (append_insn (tmp, FALSE) == (int) FAIL)
3877 return;
3879 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3880 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3882 /* Insn 4: add rD, rD, r1 */
3883 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
3884 if (append_insn (tmp, TRUE) == (int) FAIL)
3885 return;
3887 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3888 inst.bwarn = -1;
3891 nor1 = r1_bak;
3894 /* Handle la. */
3895 static void
3896 do_macro_la_rdi32 (char *str)
3898 int reg_rd;
3900 skip_whitespace (str);
3901 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3902 || skip_past_comma (&str) == (int) FAIL)
3904 return;
3906 else
3908 char append_str[MAX_LITERAL_POOL_SIZE];
3909 char *keep_data = str;
3911 /* la rd, simm16. */
3912 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3914 end_of_line (str);
3915 return;
3917 /* la rd, imm32 or la rd, label. */
3918 else
3920 SET_INSN_ERROR (NULL);
3921 str = keep_data;
3922 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3923 || (end_of_line (str) == (int) FAIL))
3925 return;
3927 else
3929 if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
3931 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3932 if (append_insn (append_str, TRUE) == (int) FAIL)
3933 return;
3935 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3936 if (append_insn (append_str, TRUE) == (int) FAIL)
3937 return;
3939 else
3941 assert (inst.reloc.exp.X_add_symbol);
3942 build_la_pic (reg_rd, inst.reloc.exp);
3945 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3946 inst.bwarn = -1;
3952 /* Handle li. */
3953 static void
3954 do_macro_li_rdi32 (char *str){
3956 int reg_rd;
3958 skip_whitespace (str);
3959 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3960 || skip_past_comma (&str) == (int) FAIL)
3962 return;
3964 else
3966 char *keep_data = str;
3968 /* li rd, simm16. */
3969 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3971 end_of_line (str);
3972 return;
3974 /* li rd, imm32. */
3975 else
3977 char append_str[MAX_LITERAL_POOL_SIZE];
3979 str = keep_data;
3981 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3982 || (end_of_line (str) == (int) FAIL))
3984 return;
3986 else if (inst.reloc.exp.X_add_symbol)
3988 inst.error = _("li rd label isn't correct instruction form");
3989 return;
3991 else
3993 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3995 if (append_insn (append_str, TRUE) == (int) FAIL)
3996 return;
3997 else
3999 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4000 if (append_insn (append_str, TRUE) == (int) FAIL)
4001 return;
4003 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4004 inst.bwarn = -1;
4011 /* Handle mul/mulu/div/divu/rem/remu. */
4012 static void
4013 do_macro_mul_rdrsrs (char *str)
4015 int reg_rd;
4016 int reg_rs1;
4017 int reg_rs2;
4018 char *backupstr;
4019 char append_str[MAX_LITERAL_POOL_SIZE];
4021 if (university_version == 1)
4022 as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
4024 strcpy (append_str, str);
4025 backupstr = append_str;
4026 skip_whitespace (backupstr);
4027 if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4028 || (skip_past_comma (&backupstr) == (int) FAIL)
4029 || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
4031 inst.error = BAD_ARGS;
4032 return;
4035 if (skip_past_comma (&backupstr) == (int) FAIL)
4037 /* rem/remu rA, rB is error format. */
4038 if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
4040 SET_INSN_ERROR (BAD_ARGS);
4042 else
4044 SET_INSN_ERROR (NULL);
4045 do_rsrs (str);
4047 return;
4049 else
4051 SET_INSN_ERROR (NULL);
4052 if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4053 || (end_of_line (backupstr) == (int) FAIL))
4055 return;
4057 else
4059 char append_str1[MAX_LITERAL_POOL_SIZE];
4061 if (strcmp (inst.name, "rem") == 0)
4063 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4064 sprintf (append_str1, "mfceh r%d", reg_rd);
4066 else if (strcmp (inst.name, "remu") == 0)
4068 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4069 sprintf (append_str1, "mfceh r%d", reg_rd);
4071 else
4073 sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
4074 sprintf (append_str1, "mfcel r%d", reg_rd);
4077 /* Output mul/mulu or div/divu or rem/remu. */
4078 if (append_insn (append_str, TRUE) == (int) FAIL)
4079 return;
4081 /* Output mfcel or mfceh. */
4082 if (append_insn (append_str1, TRUE) == (int) FAIL)
4083 return;
4085 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4086 inst.bwarn = -1;
4091 static void
4092 exp_macro_ldst_abs (char *str)
4094 int reg_rd;
4095 char *backupstr, *tmp;
4096 char append_str[MAX_LITERAL_POOL_SIZE];
4097 char verifystr[MAX_LITERAL_POOL_SIZE];
4098 struct score_it inst_backup;
4099 int r1_bak = 0;
4101 r1_bak = nor1;
4102 nor1 = 0;
4103 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4105 strcpy (verifystr, str);
4106 backupstr = verifystr;
4107 skip_whitespace (backupstr);
4108 if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4109 return;
4111 tmp = backupstr;
4112 if (skip_past_comma (&backupstr) == (int) FAIL)
4113 return;
4115 backupstr = tmp;
4116 sprintf (append_str, "li r1 %s", backupstr);
4117 append_insn (append_str, TRUE);
4119 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4120 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4121 do_ldst_insn (append_str);
4123 nor1 = r1_bak;
4126 static int
4127 nopic_need_relax (symbolS * sym, int before_relaxing)
4129 if (sym == NULL)
4130 return 0;
4131 else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
4133 const char *symname;
4134 const char *segname;
4136 /* Find out whether this symbol can be referenced off the $gp
4137 register. It can be if it is smaller than the -G size or if
4138 it is in the .sdata or .sbss section. Certain symbols can
4139 not be referenced off the $gp, although it appears as though
4140 they can. */
4141 symname = S_GET_NAME (sym);
4142 if (symname != (const char *)NULL
4143 && (strcmp (symname, "eprol") == 0
4144 || strcmp (symname, "etext") == 0
4145 || strcmp (symname, "_gp") == 0
4146 || strcmp (symname, "edata") == 0
4147 || strcmp (symname, "_fbss") == 0
4148 || strcmp (symname, "_fdata") == 0
4149 || strcmp (symname, "_ftext") == 0
4150 || strcmp (symname, "end") == 0
4151 || strcmp (symname, GP_DISP_LABEL) == 0))
4153 return 1;
4155 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4156 /* We must defer this decision until after the whole file has been read,
4157 since there might be a .extern after the first use of this symbol. */
4158 || (before_relaxing
4159 && S_GET_VALUE (sym) == 0)
4160 || (S_GET_VALUE (sym) != 0
4161 && S_GET_VALUE (sym) <= g_switch_value)))
4163 return 0;
4166 segname = segment_name (S_GET_SEGMENT (sym));
4167 return (strcmp (segname, ".sdata") != 0
4168 && strcmp (segname, ".sbss") != 0
4169 && strncmp (segname, ".sdata.", 7) != 0
4170 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4172 /* We are not optimizing for the $gp register. */
4173 else
4174 return 1;
4177 /* Build a relax frag for lw/st instruction when generating PIC,
4178 external symbol first and local symbol second. */
4180 static void
4181 build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4183 symbolS *add_symbol = exp.X_add_symbol;
4184 int add_number = exp.X_add_number;
4185 struct score_it fix_insts[RELAX_INST_NUM];
4186 struct score_it var_insts[RELAX_INST_NUM];
4187 int fix_num = 0;
4188 int var_num = 0;
4189 char tmp[MAX_LITERAL_POOL_SIZE];
4190 int r1_bak;
4192 r1_bak = nor1;
4193 nor1 = 0;
4195 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4197 fix_num = 1;
4198 var_num = 2;
4200 /* For an external symbol, two insns are generated;
4201 For a local symbol, three insns are generated. */
4202 /* Fix part
4203 For an external symbol: lw rD, <sym>($gp)
4204 (BFD_RELOC_SCORE_GOT15) */
4205 sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4206 if (append_insn (tmp, FALSE) == (int) FAIL)
4207 return;
4209 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4211 /* Var part
4212 For a local symbol :
4213 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4214 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4215 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4216 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4217 sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4218 if (append_insn (tmp, FALSE) == (int) FAIL)
4219 return;
4221 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
4222 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4224 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4225 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4226 if (append_insn (tmp, TRUE) == (int) FAIL)
4227 return;
4229 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4230 inst.bwarn = -1;
4232 else
4234 inst.error = _("PIC code offset overflow (max 16 signed bits)");
4235 return;
4238 nor1 = r1_bak;
4241 static void
4242 do_macro_ldst_label (char *str)
4244 int i;
4245 int ldst_gp_p = 0;
4246 int reg_rd;
4247 int r1_bak;
4248 char *backup_str;
4249 char *label_str;
4250 char *absolute_value;
4251 char append_str[3][MAX_LITERAL_POOL_SIZE];
4252 char verifystr[MAX_LITERAL_POOL_SIZE];
4253 struct score_it inst_backup;
4254 struct score_it inst_expand[3];
4255 struct score_it inst_main;
4257 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4258 strcpy (verifystr, str);
4259 backup_str = verifystr;
4261 skip_whitespace (backup_str);
4262 if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
4263 return;
4265 if (skip_past_comma (&backup_str) == (int) FAIL)
4266 return;
4268 label_str = backup_str;
4270 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4271 if (*backup_str == '[')
4273 inst.type = Rd_rvalueRs_preSI12;
4274 do_ldst_insn (str);
4275 return;
4278 /* Ld/st rD, imm. */
4279 absolute_value = backup_str;
4280 inst.type = Rd_rvalueRs_SI15;
4281 if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
4282 || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL)
4283 || (end_of_line (backup_str) == (int) FAIL))
4285 return;
4287 else
4289 if (inst.reloc.exp.X_add_symbol == 0)
4291 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4292 exp_macro_ldst_abs (str);
4293 return;
4297 /* Ld/st rD, label. */
4298 inst.type = Rd_rvalueRs_SI15;
4299 backup_str = absolute_value;
4300 if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
4301 || (end_of_line (backup_str) == (int) FAIL))
4303 return;
4305 else
4307 if (inst.reloc.exp.X_add_symbol == 0)
4309 if (!inst.error)
4310 inst.error = BAD_ARGS;
4312 return;
4315 if (score_pic == PIC)
4317 int ldst_idx = 0;
4318 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4319 build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
4320 return;
4322 else
4324 if ((inst.reloc.exp.X_add_number <= 0x3fff)
4325 && (inst.reloc.exp.X_add_number >= -0x4000)
4326 && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
4328 int ldst_idx = 0;
4330 /* Assign the real opcode. */
4331 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4332 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4333 inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
4334 inst.instruction |= reg_rd << 20;
4335 inst.instruction |= GP << 15;
4336 inst.relax_inst = 0x8000;
4337 inst.relax_size = 0;
4338 ldst_gp_p = 1;
4343 /* Backup inst. */
4344 memcpy (&inst_main, &inst, sizeof (struct score_it));
4345 r1_bak = nor1;
4346 nor1 = 0;
4348 /* Determine which instructions should be output. */
4349 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4350 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4351 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4353 /* Generate three instructions.
4354 la r1, label
4355 ld/st rd, [r1, 0] */
4356 for (i = 0; i < 3; i++)
4358 if (append_insn (append_str[i], FALSE) == (int) FAIL)
4359 return;
4361 memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
4364 if (ldst_gp_p)
4366 char *p;
4368 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4369 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
4370 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4371 inst_main.type = Insn_GP;
4373 for (i = 0; i < 3; i++)
4374 inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
4375 , GET_INSN_CLASS (inst_expand[i].type));
4377 /* Check data dependency. */
4378 handle_dependency (&inst_main);
4380 /* Start a new frag if frag_now is not empty. */
4381 if (frag_now_fix () != 0)
4383 if (!frag_now->tc_frag_data.is_insn)
4384 frag_wane (frag_now);
4386 frag_new (0);
4388 frag_grow (20);
4390 /* Write fr_fix part. */
4391 p = frag_more (inst_main.size);
4392 md_number_to_chars (p, inst_main.instruction, inst_main.size);
4394 if (inst_main.reloc.type != BFD_RELOC_NONE)
4396 fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4397 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4400 #ifdef OBJ_ELF
4401 dwarf2_emit_insn (inst_main.size);
4402 #endif
4404 /* GP instruction can not do optimization, only can do relax between
4405 1 instruction and 3 instructions. */
4406 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
4407 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4408 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4410 /* Write fr_var part.
4411 no calling gen_insn_frag, no fixS will be generated. */
4412 md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4413 p += inst_expand[0].size;
4414 md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4415 p += inst_expand[1].size;
4416 md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4418 else
4420 gen_insn_frag (&inst_expand[0], NULL);
4421 gen_insn_frag (&inst_expand[1], NULL);
4422 gen_insn_frag (&inst_expand[2], NULL);
4424 nor1 = r1_bak;
4426 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4427 inst.bwarn = -1;
4430 static void
4431 do_lw_pic (char *str)
4433 int reg_rd;
4435 skip_whitespace (str);
4436 if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
4437 || (skip_past_comma (&str) == (int) FAIL)
4438 || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
4439 || (end_of_line (str) == (int) FAIL))
4441 return;
4443 else
4445 if (inst.reloc.exp.X_add_symbol == 0)
4447 if (!inst.error)
4448 inst.error = BAD_ARGS;
4450 return;
4453 inst.instruction |= GP << 15;
4454 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4458 static void
4459 do_empty (char *str)
4461 str = str;
4462 if (university_version == 1)
4464 if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
4465 || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
4466 || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
4467 || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
4469 inst.error = ERR_FOR_SCORE5U_MMU;
4470 return;
4473 if (end_of_line (str) == (int) FAIL)
4474 return;
4476 if (inst.relax_inst != 0x8000)
4478 if (inst.type == NO_OPD)
4480 inst.relax_size = 2;
4482 else
4484 inst.relax_size = 4;
4489 static void
4490 do_jump (char *str)
4492 char *save_in;
4494 skip_whitespace (str);
4495 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4496 || end_of_line (str) == (int) FAIL)
4497 return;
4499 if (inst.reloc.exp.X_add_symbol == 0)
4501 inst.error = _("lacking label ");
4502 return;
4505 if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4506 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4508 inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24");
4509 return;
4512 save_in = input_line_pointer;
4513 input_line_pointer = str;
4514 inst.reloc.type = BFD_RELOC_SCORE_JMP;
4515 inst.reloc.pc_rel = 1;
4516 input_line_pointer = save_in;
4519 static void
4520 do16_jump (char *str)
4522 skip_whitespace (str);
4523 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4524 || end_of_line (str) == (int) FAIL)
4526 return;
4528 else if (inst.reloc.exp.X_add_symbol == 0)
4530 inst.error = _("lacking label ");
4531 return;
4533 else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
4534 && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
4536 inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
4537 return;
4540 inst.reloc.type = BFD_RELOC_SCORE16_JMP;
4541 inst.reloc.pc_rel = 1;
4544 static void
4545 do_branch (char *str)
4547 unsigned long abs_value = 0;
4549 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4550 || end_of_line (str) == (int) FAIL)
4552 return;
4554 else if (inst.reloc.exp.X_add_symbol == 0)
4556 inst.error = _("lacking label ");
4557 return;
4559 else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4560 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4562 inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
4563 return;
4566 inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
4567 inst.reloc.pc_rel = 1;
4569 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
4570 inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
4572 /* Compute 16 bit branch instruction. */
4573 if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
4575 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
4576 inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4577 inst.relax_size = 2;
4579 else
4581 inst.relax_inst = 0x8000;
4585 static void
4586 do16_branch (char *str)
4588 if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4589 || end_of_line (str) == (int) FAIL))
4593 else if (inst.reloc.exp.X_add_symbol == 0)
4595 inst.error = _("lacking label");
4597 else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
4598 && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
4600 inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
4602 else
4604 inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
4605 inst.reloc.pc_rel = 1;
4606 inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4610 /* Iterate over the base tables to create the instruction patterns. */
4611 static void
4612 build_score_ops_hsh (void)
4614 unsigned int i;
4615 static struct obstack insn_obstack;
4617 obstack_begin (&insn_obstack, 4000);
4618 for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
4620 const struct asm_opcode *insn = score_insns + i;
4621 unsigned len = strlen (insn->template);
4622 struct asm_opcode *new;
4623 char *template;
4624 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
4625 template = obstack_alloc (&insn_obstack, len + 1);
4627 strcpy (template, insn->template);
4628 new->template = template;
4629 new->parms = insn->parms;
4630 new->value = insn->value;
4631 new->relax_value = insn->relax_value;
4632 new->type = insn->type;
4633 new->bitmask = insn->bitmask;
4634 hash_insert (score_ops_hsh, new->template, (void *) new);
4638 static void
4639 build_dependency_insn_hsh (void)
4641 unsigned int i;
4642 static struct obstack dependency_obstack;
4644 obstack_begin (&dependency_obstack, 4000);
4645 for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
4647 const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
4648 unsigned len = strlen (tmp->insn_name);
4649 struct insn_to_dependency *new;
4651 new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
4652 new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
4654 strcpy (new->insn_name, tmp->insn_name);
4655 new->type = tmp->type;
4656 hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
4660 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4661 for use in the a.out file, and stores them in the array pointed to by buf.
4662 This knows about the endian-ness of the target machine and does
4663 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4664 2 (short) and 4 (long) Floating numbers are put out as a series of
4665 LITTLENUMS (shorts, here at least). */
4667 void
4668 md_number_to_chars (char *buf, valueT val, int n)
4670 if (target_big_endian)
4671 number_to_chars_bigendian (buf, val, n);
4672 else
4673 number_to_chars_littleendian (buf, val, n);
4676 static valueT
4677 md_chars_to_number (char *buf, int n)
4679 valueT result = 0;
4680 unsigned char *where = (unsigned char *)buf;
4682 if (target_big_endian)
4684 while (n--)
4686 result <<= 8;
4687 result |= (*where++ & 255);
4690 else
4692 while (n--)
4694 result <<= 8;
4695 result |= (where[n] & 255);
4699 return result;
4702 char *
4703 md_atof (int type, char *litP, int *sizeP)
4705 return ieee_md_atof (type, litP, sizeP, target_big_endian);
4708 /* Return true if the given symbol should be considered local for PIC. */
4710 static bfd_boolean
4711 pic_need_relax (symbolS *sym, asection *segtype)
4713 asection *symsec;
4714 bfd_boolean linkonce;
4716 /* Handle the case of a symbol equated to another symbol. */
4717 while (symbol_equated_reloc_p (sym))
4719 symbolS *n;
4721 /* It's possible to get a loop here in a badly written
4722 program. */
4723 n = symbol_get_value_expression (sym)->X_add_symbol;
4724 if (n == sym)
4725 break;
4726 sym = n;
4729 symsec = S_GET_SEGMENT (sym);
4731 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
4732 linkonce = FALSE;
4733 if (symsec != segtype && ! S_IS_LOCAL (sym))
4735 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
4736 linkonce = TRUE;
4738 /* The GNU toolchain uses an extension for ELF: a section
4739 beginning with the magic string .gnu.linkonce is a linkonce
4740 section. */
4741 if (strncmp (segment_name (symsec), ".gnu.linkonce",
4742 sizeof ".gnu.linkonce" - 1) == 0)
4743 linkonce = TRUE;
4746 /* This must duplicate the test in adjust_reloc_syms. */
4747 return (symsec != &bfd_und_section
4748 && symsec != &bfd_abs_section
4749 && ! bfd_is_com_section (symsec)
4750 && !linkonce
4751 #ifdef OBJ_ELF
4752 /* A global or weak symbol is treated as external. */
4753 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
4754 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
4755 #endif
4759 static int
4760 judge_size_before_relax (fragS * fragp, asection *sec)
4762 int change = 0;
4764 if (score_pic == NO_PIC)
4765 change = nopic_need_relax (fragp->fr_symbol, 0);
4766 else
4767 change = pic_need_relax (fragp->fr_symbol, sec);
4769 if (change == 1)
4771 /* Only at the first time determining whether GP instruction relax should be done,
4772 return the difference between insntruction size and instruction relax size. */
4773 if (fragp->fr_opcode == NULL)
4775 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
4776 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
4777 return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
4781 return 0;
4784 /* In this function, we determine whether GP instruction should do relaxation,
4785 for the label being against was known now.
4786 Doing this here but not in md_relax_frag() can induce iteration times
4787 in stage of doing relax. */
4789 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
4791 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4792 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4793 return judge_size_before_relax (fragp, sec);
4795 return 0;
4798 static int
4799 b32_relax_to_b16 (fragS * fragp)
4801 int grows = 0;
4802 int relaxable_p = 0;
4803 int old;
4804 int new;
4805 int frag_addr = fragp->fr_address + fragp->insn_addr;
4807 addressT symbol_address = 0;
4808 symbolS *s;
4809 offsetT offset;
4810 unsigned long value;
4811 unsigned long abs_value;
4813 /* FIXME : here may be able to modify better .
4814 I don't know how to get the fragp's section ,
4815 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
4816 is different from the symbol's. */
4818 old = RELAX_OLD (fragp->fr_subtype);
4819 new = RELAX_NEW (fragp->fr_subtype);
4820 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4822 s = fragp->fr_symbol;
4823 /* b/bl immediate */
4824 if (s == NULL)
4825 frag_addr = 0;
4826 else
4828 if (s->bsym != 0)
4829 symbol_address = (addressT) s->sy_frag->fr_address;
4832 value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
4834 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
4835 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
4836 if ((offset & 0x80000) == 0x80000)
4837 offset |= 0xfff00000;
4839 abs_value = offset + symbol_address - frag_addr;
4840 if ((abs_value & 0x80000000) == 0x80000000)
4841 abs_value = 0xffffffff - abs_value + 1;
4843 /* Relax branch 32 to branch 16. */
4844 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
4845 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
4847 /* do nothing. */
4849 else
4851 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
4852 fragp->fr_opcode = NULL;
4853 fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
4856 return grows;
4859 /* Main purpose is to determine whether one frag should do relax.
4860 frag->fr_opcode indicates this point. */
4863 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
4865 int grows = 0;
4866 int insn_size;
4867 int insn_relax_size;
4868 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
4869 int relaxable_p = 0;
4870 bfd_boolean word_align_p = FALSE;
4871 fragS *next_fragp;
4873 /* If the instruction address is odd, make it half word align first. */
4874 if ((fragp->fr_address) % 2 != 0)
4876 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
4878 fragp->insn_addr = 1;
4879 grows += 1;
4883 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
4885 /* Get instruction size and relax size after the last relaxation. */
4886 if (fragp->fr_opcode)
4888 insn_size = RELAX_NEW (fragp->fr_subtype);
4889 insn_relax_size = RELAX_OLD (fragp->fr_subtype);
4891 else
4893 insn_size = RELAX_OLD (fragp->fr_subtype);
4894 insn_relax_size = RELAX_NEW (fragp->fr_subtype);
4897 /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine
4898 whether the GP instruction should do relax. */
4899 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4900 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4902 if (!word_align_p)
4904 if (fragp->insn_addr < 2)
4906 fragp->insn_addr += 2;
4907 grows += 2;
4909 else
4911 fragp->insn_addr -= 2;
4912 grows -= 2;
4916 if (fragp->fr_opcode)
4917 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
4918 else
4919 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
4921 else
4923 if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
4924 b32_relax_to_b16 (fragp);
4926 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4927 next_fragp = fragp->fr_next;
4928 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
4930 next_fragp = next_fragp->fr_next;
4933 if (next_fragp)
4935 int n_insn_size;
4936 int n_relaxable_p = 0;
4938 if (next_fragp->fr_opcode)
4940 n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
4942 else
4944 n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
4947 if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
4948 b32_relax_to_b16 (next_fragp);
4949 n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
4951 if (word_align_p)
4953 if (insn_size == 4)
4955 /* 32 -> 16. */
4956 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
4958 grows -= 2;
4959 do_relax_p = 1;
4962 else if (insn_size == 2)
4964 /* 16 -> 32. */
4965 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
4967 grows += 2;
4968 do_relax_p = 1;
4971 else
4973 abort ();
4976 else
4978 if (insn_size == 4)
4980 /* 32 -> 16. */
4981 if (relaxable_p)
4983 grows -= 2;
4984 do_relax_p = 1;
4986 /* Make the 32 bit insturction word align. */
4987 else
4989 fragp->insn_addr += 2;
4990 grows += 2;
4993 else if (insn_size == 2)
4995 /* Do nothing. */
4997 else
4999 abort ();
5003 else
5005 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
5006 if (word_align_p == FALSE)
5008 if (insn_size % 4 == 0)
5010 /* 32 -> 16. */
5011 if (relaxable_p)
5013 grows -= 2;
5014 do_relax_p = 1;
5016 else
5018 fragp->insn_addr += 2;
5019 grows += 2;
5023 else
5025 /* Do nothing. */
5029 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5030 if (do_relax_p)
5032 if (fragp->fr_opcode)
5034 fragp->fr_opcode = NULL;
5035 /* Guarantee estimate stage is correct. */
5036 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5037 fragp->fr_fix += fragp->insn_addr;
5039 else
5041 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
5042 /* Guarantee estimate stage is correct. */
5043 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5044 fragp->fr_fix += fragp->insn_addr;
5047 else
5049 if (fragp->fr_opcode)
5051 /* Guarantee estimate stage is correct. */
5052 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5053 fragp->fr_fix += fragp->insn_addr;
5055 else
5057 /* Guarantee estimate stage is correct. */
5058 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5059 fragp->fr_fix += fragp->insn_addr;
5064 return grows;
5067 void
5068 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
5070 int old;
5071 int new;
5072 char backup[20];
5073 fixS *fixp;
5075 old = RELAX_OLD (fragp->fr_subtype);
5076 new = RELAX_NEW (fragp->fr_subtype);
5078 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5079 if (fragp->fr_opcode == NULL)
5081 memcpy (backup, fragp->fr_literal, old);
5082 fragp->fr_fix = old;
5084 else
5086 memcpy (backup, fragp->fr_literal + old, new);
5087 fragp->fr_fix = new;
5090 fixp = fragp->tc_frag_data.fixp;
5091 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
5093 if (fragp->fr_opcode)
5094 fixp->fx_done = 1;
5095 fixp = fixp->fx_next;
5097 while (fixp && fixp->fx_frag == fragp)
5099 if (fragp->fr_opcode)
5100 fixp->fx_where -= old + fragp->insn_addr;
5101 else
5102 fixp->fx_done = 1;
5103 fixp = fixp->fx_next;
5106 if (fragp->insn_addr)
5108 md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
5110 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
5111 fragp->fr_fix += fragp->insn_addr;
5114 /* Implementation of md_frag_check.
5115 Called after md_convert_frag(). */
5117 void
5118 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
5120 know (fragp->insn_addr <= RELAX_PAD_BYTE);
5123 bfd_boolean
5124 score_fix_adjustable (fixS * fixP)
5126 if (fixP->fx_addsy == NULL)
5128 return 1;
5130 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
5131 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
5133 return 0;
5135 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5136 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5138 return 0;
5141 return 1;
5144 /* Implementation of TC_VALIDATE_FIX.
5145 Called before md_apply_fix() and after md_convert_frag(). */
5146 void
5147 score_validate_fix (fixS *fixP)
5149 fixP->fx_where += fixP->fx_frag->insn_addr;
5152 long
5153 md_pcrel_from (fixS * fixP)
5155 long retval = 0;
5157 if (fixP->fx_addsy
5158 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
5159 && (fixP->fx_subsy == NULL))
5161 retval = 0;
5163 else
5165 retval = fixP->fx_where + fixP->fx_frag->fr_address;
5168 return retval;
5172 score_force_relocation (struct fix *fixp)
5174 int retval = 0;
5176 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5177 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
5178 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
5179 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
5180 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
5181 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
5183 retval = 1;
5186 return retval;
5189 /* Round up a section size to the appropriate boundary. */
5190 valueT
5191 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5193 int align = bfd_get_section_alignment (stdoutput, segment);
5195 return ((size + (1 << align) - 1) & (-1 << align));
5198 void
5199 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
5201 offsetT value = *valP;
5202 offsetT abs_value = 0;
5203 offsetT newval;
5204 offsetT content;
5205 unsigned short HI, LO;
5207 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
5209 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5210 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5212 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
5213 fixP->fx_done = 1;
5216 /* If this symbol is in a different section then we need to leave it for
5217 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5218 so we have to undo it's effects here. */
5219 if (fixP->fx_pcrel)
5221 if (fixP->fx_addsy != NULL
5222 && S_IS_DEFINED (fixP->fx_addsy)
5223 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5224 value += md_pcrel_from (fixP);
5227 /* Remember value for emit_reloc. */
5228 fixP->fx_addnumber = value;
5230 switch (fixP->fx_r_type)
5232 case BFD_RELOC_HI16_S:
5233 if (fixP->fx_done)
5234 { /* For la rd, imm32. */
5235 newval = md_chars_to_number (buf, INSN_SIZE);
5236 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
5237 newval |= (HI & 0x3fff) << 1;
5238 newval |= ((HI >> 14) & 0x3) << 16;
5239 md_number_to_chars (buf, newval, INSN_SIZE);
5241 break;
5242 case BFD_RELOC_LO16:
5243 if (fixP->fx_done) /* For la rd, imm32. */
5245 newval = md_chars_to_number (buf, INSN_SIZE);
5246 LO = (value) & 0xffff;
5247 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
5248 newval |= ((LO >> 14) & 0x3) << 16;
5249 md_number_to_chars (buf, newval, INSN_SIZE);
5251 break;
5252 case BFD_RELOC_SCORE_JMP:
5254 content = md_chars_to_number (buf, INSN_SIZE);
5255 value = fixP->fx_offset;
5256 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
5257 md_number_to_chars (buf, content, INSN_SIZE);
5259 break;
5260 case BFD_RELOC_SCORE_BRANCH:
5261 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5262 value = fixP->fx_offset;
5263 else
5264 fixP->fx_done = 1;
5266 content = md_chars_to_number (buf, INSN_SIZE);
5267 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
5269 if ((value & 0x80000000) == 0x80000000)
5270 abs_value = 0xffffffff - value + 1;
5271 if ((abs_value & 0xffffff00) != 0)
5273 as_bad_where (fixP->fx_file, fixP->fx_line,
5274 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5275 return;
5277 content = md_chars_to_number (buf, INSN16_SIZE);
5278 content &= 0xff00;
5279 content = (content & 0xff00) | ((value >> 1) & 0xff);
5280 md_number_to_chars (buf, content, INSN16_SIZE);
5281 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
5282 fixP->fx_size = 2;
5284 else
5286 if ((value & 0x80000000) == 0x80000000)
5287 abs_value = 0xffffffff - value + 1;
5288 if ((abs_value & 0xfff80000) != 0)
5290 as_bad_where (fixP->fx_file, fixP->fx_line,
5291 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5292 return;
5294 content = md_chars_to_number (buf, INSN_SIZE);
5295 content &= 0xfc00fc01;
5296 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5297 md_number_to_chars (buf, content, INSN_SIZE);
5299 break;
5300 case BFD_RELOC_SCORE16_JMP:
5301 content = md_chars_to_number (buf, INSN16_SIZE);
5302 content &= 0xf001;
5303 value = fixP->fx_offset & 0xfff;
5304 content = (content & 0xfc01) | (value & 0xffe);
5305 md_number_to_chars (buf, content, INSN16_SIZE);
5306 break;
5307 case BFD_RELOC_SCORE16_BRANCH:
5308 content = md_chars_to_number (buf, INSN_SIZE);
5309 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
5311 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5312 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5313 value = fixP->fx_offset;
5314 else
5315 fixP->fx_done = 1;
5316 if ((value & 0x80000000) == 0x80000000)
5317 abs_value = 0xffffffff - value + 1;
5318 if ((abs_value & 0xfff80000) != 0)
5320 as_bad_where (fixP->fx_file, fixP->fx_line,
5321 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5322 return;
5324 content = md_chars_to_number (buf, INSN_SIZE);
5325 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5326 md_number_to_chars (buf, content, INSN_SIZE);
5327 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
5328 fixP->fx_size = 4;
5329 break;
5331 else
5333 /* In differnt section. */
5334 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5335 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5336 value = fixP->fx_offset;
5337 else
5338 fixP->fx_done = 1;
5340 if ((value & 0x80000000) == 0x80000000)
5341 abs_value = 0xffffffff - value + 1;
5342 if ((abs_value & 0xffffff00) != 0)
5344 as_bad_where (fixP->fx_file, fixP->fx_line,
5345 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5346 return;
5348 content = md_chars_to_number (buf, INSN16_SIZE);
5349 content = (content & 0xff00) | ((value >> 1) & 0xff);
5350 md_number_to_chars (buf, content, INSN16_SIZE);
5351 break;
5353 case BFD_RELOC_8:
5354 if (fixP->fx_done || fixP->fx_pcrel)
5355 md_number_to_chars (buf, value, 1);
5356 #ifdef OBJ_ELF
5357 else
5359 value = fixP->fx_offset;
5360 md_number_to_chars (buf, value, 1);
5362 #endif
5363 break;
5365 case BFD_RELOC_16:
5366 if (fixP->fx_done || fixP->fx_pcrel)
5367 md_number_to_chars (buf, value, 2);
5368 #ifdef OBJ_ELF
5369 else
5371 value = fixP->fx_offset;
5372 md_number_to_chars (buf, value, 2);
5374 #endif
5375 break;
5376 case BFD_RELOC_RVA:
5377 case BFD_RELOC_32:
5378 if (fixP->fx_done || fixP->fx_pcrel)
5379 md_number_to_chars (buf, value, 4);
5380 #ifdef OBJ_ELF
5381 else
5383 value = fixP->fx_offset;
5384 md_number_to_chars (buf, value, 4);
5386 #endif
5387 break;
5388 case BFD_RELOC_VTABLE_INHERIT:
5389 fixP->fx_done = 0;
5390 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
5391 S_SET_WEAK (fixP->fx_addsy);
5392 break;
5393 case BFD_RELOC_VTABLE_ENTRY:
5394 fixP->fx_done = 0;
5395 break;
5396 case BFD_RELOC_SCORE_GPREL15:
5397 content = md_chars_to_number (buf, INSN_SIZE);
5398 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
5399 fixP->fx_r_type = BFD_RELOC_NONE;
5400 fixP->fx_done = 0;
5401 break;
5402 case BFD_RELOC_SCORE_GOT15:
5403 case BFD_RELOC_SCORE_DUMMY_HI16:
5404 case BFD_RELOC_SCORE_GOT_LO16:
5405 case BFD_RELOC_SCORE_CALL15:
5406 case BFD_RELOC_GPREL32:
5407 break;
5408 case BFD_RELOC_NONE:
5409 default:
5410 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
5414 /* Translate internal representation of relocation info to BFD target format. */
5415 arelent **
5416 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
5418 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
5419 arelent *reloc;
5420 bfd_reloc_code_real_type code;
5421 char *type;
5422 fragS *f;
5423 symbolS *s;
5424 expressionS e;
5426 reloc = retval[0] = xmalloc (sizeof (arelent));
5427 retval[1] = NULL;
5429 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5430 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5431 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5432 reloc->addend = fixp->fx_offset;
5434 /* If this is a variant frag, we may need to adjust the existing
5435 reloc and generate a new one. */
5436 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
5438 /* Update instruction imm bit. */
5439 offsetT newval;
5440 unsigned short off;
5441 char *buf;
5443 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
5444 newval = md_chars_to_number (buf, INSN_SIZE);
5445 off = fixp->fx_offset >> 16;
5446 newval |= (off & 0x3fff) << 1;
5447 newval |= ((off >> 14) & 0x3) << 16;
5448 md_number_to_chars (buf, newval, INSN_SIZE);
5450 buf += INSN_SIZE;
5451 newval = md_chars_to_number (buf, INSN_SIZE);
5452 off = fixp->fx_offset & 0xffff;
5453 newval |= ((off & 0x3fff) << 1);
5454 newval |= (((off >> 14) & 0x3) << 16);
5455 md_number_to_chars (buf, newval, INSN_SIZE);
5457 retval[1] = xmalloc (sizeof (arelent));
5458 retval[2] = NULL;
5459 retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5460 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5461 retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
5463 f = fixp->fx_frag;
5464 s = f->fr_symbol;
5465 e = s->sy_value;
5467 retval[1]->addend = 0;
5468 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
5469 assert (retval[1]->howto != NULL);
5471 fixp->fx_r_type = BFD_RELOC_HI16_S;
5474 code = fixp->fx_r_type;
5475 switch (fixp->fx_r_type)
5477 case BFD_RELOC_32:
5478 if (fixp->fx_pcrel)
5480 code = BFD_RELOC_32_PCREL;
5481 break;
5483 case BFD_RELOC_HI16_S:
5484 case BFD_RELOC_LO16:
5485 case BFD_RELOC_SCORE_JMP:
5486 case BFD_RELOC_SCORE_BRANCH:
5487 case BFD_RELOC_SCORE16_JMP:
5488 case BFD_RELOC_SCORE16_BRANCH:
5489 case BFD_RELOC_VTABLE_ENTRY:
5490 case BFD_RELOC_VTABLE_INHERIT:
5491 case BFD_RELOC_SCORE_GPREL15:
5492 case BFD_RELOC_SCORE_GOT15:
5493 case BFD_RELOC_SCORE_DUMMY_HI16:
5494 case BFD_RELOC_SCORE_GOT_LO16:
5495 case BFD_RELOC_SCORE_CALL15:
5496 case BFD_RELOC_GPREL32:
5497 case BFD_RELOC_NONE:
5498 code = fixp->fx_r_type;
5499 break;
5500 default:
5501 type = _("<unknown>");
5502 as_bad_where (fixp->fx_file, fixp->fx_line,
5503 _("cannot represent %s relocation in this object file format"), type);
5504 return NULL;
5507 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5508 if (reloc->howto == NULL)
5510 as_bad_where (fixp->fx_file, fixp->fx_line,
5511 _("cannot represent %s relocation in this object file format1"),
5512 bfd_get_reloc_code_name (code));
5513 return NULL;
5515 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5516 vtable entry to be used in the relocation's section offset. */
5517 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5518 reloc->address = fixp->fx_offset;
5520 return retval;
5523 void
5524 score_elf_final_processing (void)
5526 if (fix_data_dependency == 1)
5528 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
5530 if (score_pic == PIC)
5532 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
5536 static void
5537 parse_pce_inst (char *insnstr)
5539 char c;
5540 char *p;
5541 char first[MAX_LITERAL_POOL_SIZE];
5542 char second[MAX_LITERAL_POOL_SIZE];
5543 struct score_it pec_part_1;
5545 /* Get first part string of PCE. */
5546 p = strstr (insnstr, "||");
5547 c = *p;
5548 *p = '\0';
5549 sprintf (first, "%s", insnstr);
5551 /* Get second part string of PCE. */
5552 *p = c;
5553 p += 2;
5554 sprintf (second, "%s", p);
5556 parse_16_32_inst (first, FALSE);
5557 if (inst.error)
5558 return;
5560 memcpy (&pec_part_1, &inst, sizeof (inst));
5562 parse_16_32_inst (second, FALSE);
5563 if (inst.error)
5564 return;
5566 if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
5567 || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
5568 || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
5570 inst.error = _("pce instruction error (16 bit || 16 bit)'");
5571 sprintf (inst.str, insnstr);
5572 return;
5575 if (!inst.error)
5576 gen_insn_frag (&pec_part_1, &inst);
5579 void
5580 md_assemble (char *str)
5582 know (str);
5583 know (strlen (str) < MAX_LITERAL_POOL_SIZE);
5585 memset (&inst, '\0', sizeof (inst));
5586 if (INSN_IS_PCE_P (str))
5587 parse_pce_inst (str);
5588 else
5589 parse_16_32_inst (str, TRUE);
5591 if (inst.error)
5592 as_bad (_("%s -- `%s'"), inst.error, inst.str);
5595 /* We handle all bad expressions here, so that we can report the faulty
5596 instruction in the error message. */
5597 void
5598 md_operand (expressionS * expr)
5600 if (in_my_get_expression)
5602 expr->X_op = O_illegal;
5603 if (inst.error == NULL)
5605 inst.error = _("bad expression");
5610 const char *md_shortopts = "nO::g::G:";
5612 #ifdef SCORE_BI_ENDIAN
5613 #define OPTION_EB (OPTION_MD_BASE + 0)
5614 #define OPTION_EL (OPTION_MD_BASE + 1)
5615 #else
5616 #if TARGET_BYTES_BIG_ENDIAN
5617 #define OPTION_EB (OPTION_MD_BASE + 0)
5618 #else
5619 #define OPTION_EL (OPTION_MD_BASE + 1)
5620 #endif
5621 #endif
5622 #define OPTION_FIXDD (OPTION_MD_BASE + 2)
5623 #define OPTION_NWARN (OPTION_MD_BASE + 3)
5624 #define OPTION_SCORE5 (OPTION_MD_BASE + 4)
5625 #define OPTION_SCORE5U (OPTION_MD_BASE + 5)
5626 #define OPTION_SCORE7 (OPTION_MD_BASE + 6)
5627 #define OPTION_R1 (OPTION_MD_BASE + 7)
5628 #define OPTION_O0 (OPTION_MD_BASE + 8)
5629 #define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
5630 #define OPTION_PIC (OPTION_MD_BASE + 10)
5632 struct option md_longopts[] =
5634 #ifdef OPTION_EB
5635 {"EB" , no_argument, NULL, OPTION_EB},
5636 #endif
5637 #ifdef OPTION_EL
5638 {"EL" , no_argument, NULL, OPTION_EL},
5639 #endif
5640 {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
5641 {"NWARN" , no_argument, NULL, OPTION_NWARN},
5642 {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
5643 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
5644 {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
5645 {"USE_R1" , no_argument, NULL, OPTION_R1},
5646 {"O0" , no_argument, NULL, OPTION_O0},
5647 {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
5648 {"KPIC" , no_argument, NULL, OPTION_PIC},
5649 {NULL , no_argument, NULL, 0}
5652 size_t md_longopts_size = sizeof (md_longopts);
5655 md_parse_option (int c, char *arg)
5657 switch (c)
5659 #ifdef OPTION_EB
5660 case OPTION_EB:
5661 target_big_endian = 1;
5662 break;
5663 #endif
5664 #ifdef OPTION_EL
5665 case OPTION_EL:
5666 target_big_endian = 0;
5667 break;
5668 #endif
5669 case OPTION_FIXDD:
5670 fix_data_dependency = 1;
5671 break;
5672 case OPTION_NWARN:
5673 warn_fix_data_dependency = 0;
5674 break;
5675 case OPTION_SCORE5:
5676 score7 = 0;
5677 university_version = 0;
5678 vector_size = SCORE5_PIPELINE;
5679 break;
5680 case OPTION_SCORE5U:
5681 score7 = 0;
5682 university_version = 1;
5683 vector_size = SCORE5_PIPELINE;
5684 break;
5685 case OPTION_SCORE7:
5686 score7 = 1;
5687 university_version = 0;
5688 vector_size = SCORE7_PIPELINE;
5689 break;
5690 case OPTION_R1:
5691 nor1 = 0;
5692 break;
5693 case 'G':
5694 g_switch_value = atoi (arg);
5695 break;
5696 case OPTION_O0:
5697 g_opt = 0;
5698 break;
5699 case OPTION_SCORE_VERSION:
5700 printf (_("Sunplus-v2-0-0-20060510\n"));
5701 break;
5702 case OPTION_PIC:
5703 score_pic = PIC;
5704 g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */
5705 break;
5706 default:
5707 /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */
5708 return 0;
5710 return 1;
5713 void
5714 md_show_usage (FILE * fp)
5716 fprintf (fp, _(" Score-specific assembler options:\n"));
5717 #ifdef OPTION_EB
5718 fprintf (fp, _("\
5719 -EB\t\tassemble code for a big-endian cpu\n"));
5720 #endif
5722 #ifdef OPTION_EL
5723 fprintf (fp, _("\
5724 -EL\t\tassemble code for a little-endian cpu\n"));
5725 #endif
5727 fprintf (fp, _("\
5728 -FIXDD\t\tassemble code for fix data dependency\n"));
5729 fprintf (fp, _("\
5730 -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
5731 fprintf (fp, _("\
5732 -SCORE5\t\tassemble code for target is SCORE5\n"));
5733 fprintf (fp, _("\
5734 -SCORE5U\tassemble code for target is SCORE5U\n"));
5735 fprintf (fp, _("\
5736 -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
5737 fprintf (fp, _("\
5738 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
5739 fprintf (fp, _("\
5740 -KPIC\t\tassemble code for PIC\n"));
5741 fprintf (fp, _("\
5742 -O0\t\tassembler will not perform any optimizations\n"));
5743 fprintf (fp, _("\
5744 -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
5745 fprintf (fp, _("\
5746 -V \t\tSunplus release version \n"));
5750 /* Pesudo handling functions. */
5752 /* If we change section we must dump the literal pool first. */
5753 static void
5754 s_score_bss (int ignore ATTRIBUTE_UNUSED)
5756 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5757 demand_empty_rest_of_line ();
5760 static void
5761 s_score_text (int ignore)
5763 obj_elf_text (ignore);
5764 record_alignment (now_seg, 2);
5767 static void
5768 score_s_section (int ignore)
5770 obj_elf_section (ignore);
5771 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5772 record_alignment (now_seg, 2);
5776 static void
5777 s_change_sec (int sec)
5779 segT seg;
5781 #ifdef OBJ_ELF
5782 /* The ELF backend needs to know that we are changing sections, so
5783 that .previous works correctly. We could do something like check
5784 for an obj_section_change_hook macro, but that might be confusing
5785 as it would not be appropriate to use it in the section changing
5786 functions in read.c, since obj-elf.c intercepts those. FIXME:
5787 This should be cleaner, somehow. */
5788 obj_elf_section_change_hook ();
5789 #endif
5790 switch (sec)
5792 case 'r':
5793 seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5794 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5795 if (strcmp (TARGET_OS, "elf") != 0)
5796 record_alignment (seg, 4);
5797 demand_empty_rest_of_line ();
5798 break;
5799 case 's':
5800 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5801 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5802 if (strcmp (TARGET_OS, "elf") != 0)
5803 record_alignment (seg, 4);
5804 demand_empty_rest_of_line ();
5805 break;
5809 static void
5810 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5812 long mask, off;
5814 if (cur_proc_ptr == (procS *) NULL)
5816 as_warn (_(".mask outside of .ent"));
5817 demand_empty_rest_of_line ();
5818 return;
5820 if (get_absolute_expression_and_terminator (&mask) != ',')
5822 as_warn (_("Bad .mask directive"));
5823 --input_line_pointer;
5824 demand_empty_rest_of_line ();
5825 return;
5827 off = get_absolute_expression ();
5828 cur_proc_ptr->reg_mask = mask;
5829 cur_proc_ptr->reg_offset = off;
5830 demand_empty_rest_of_line ();
5833 static symbolS *
5834 get_symbol (void)
5836 int c;
5837 char *name;
5838 symbolS *p;
5840 name = input_line_pointer;
5841 c = get_symbol_end ();
5842 p = (symbolS *) symbol_find_or_make (name);
5843 *input_line_pointer = c;
5844 return p;
5847 static long
5848 get_number (void)
5850 int negative = 0;
5851 long val = 0;
5853 if (*input_line_pointer == '-')
5855 ++input_line_pointer;
5856 negative = 1;
5858 if (!ISDIGIT (*input_line_pointer))
5859 as_bad (_("expected simple number"));
5860 if (input_line_pointer[0] == '0')
5862 if (input_line_pointer[1] == 'x')
5864 input_line_pointer += 2;
5865 while (ISXDIGIT (*input_line_pointer))
5867 val <<= 4;
5868 val |= hex_value (*input_line_pointer++);
5870 return negative ? -val : val;
5872 else
5874 ++input_line_pointer;
5875 while (ISDIGIT (*input_line_pointer))
5877 val <<= 3;
5878 val |= *input_line_pointer++ - '0';
5880 return negative ? -val : val;
5883 if (!ISDIGIT (*input_line_pointer))
5885 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5886 as_warn (_("invalid number"));
5887 return -1;
5889 while (ISDIGIT (*input_line_pointer))
5891 val *= 10;
5892 val += *input_line_pointer++ - '0';
5894 return negative ? -val : val;
5897 /* The .aent and .ent directives. */
5899 static void
5900 s_score_ent (int aent)
5902 symbolS *symbolP;
5903 int maybe_text;
5905 symbolP = get_symbol ();
5906 if (*input_line_pointer == ',')
5907 ++input_line_pointer;
5908 SKIP_WHITESPACE ();
5909 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5910 get_number ();
5912 #ifdef BFD_ASSEMBLER
5913 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5914 maybe_text = 1;
5915 else
5916 maybe_text = 0;
5917 #else
5918 if (now_seg != data_section && now_seg != bss_section)
5919 maybe_text = 1;
5920 else
5921 maybe_text = 0;
5922 #endif
5923 if (!maybe_text)
5924 as_warn (_(".ent or .aent not in text section."));
5925 if (!aent && cur_proc_ptr)
5926 as_warn (_("missing .end"));
5927 if (!aent)
5929 cur_proc_ptr = &cur_proc;
5930 cur_proc_ptr->reg_mask = 0xdeadbeaf;
5931 cur_proc_ptr->reg_offset = 0xdeadbeaf;
5932 cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5933 cur_proc_ptr->leaf = 0xdeafbeaf;
5934 cur_proc_ptr->frame_offset = 0xdeafbeaf;
5935 cur_proc_ptr->frame_reg = 0xdeafbeaf;
5936 cur_proc_ptr->pc_reg = 0xdeafbeaf;
5937 cur_proc_ptr->isym = symbolP;
5938 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5939 ++numprocs;
5940 if (debug_type == DEBUG_STABS)
5941 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5943 demand_empty_rest_of_line ();
5946 static void
5947 s_score_frame (int ignore ATTRIBUTE_UNUSED)
5949 char *backupstr;
5950 char str[30];
5951 long val;
5952 int i = 0;
5954 backupstr = input_line_pointer;
5956 #ifdef OBJ_ELF
5957 if (cur_proc_ptr == (procS *) NULL)
5959 as_warn (_(".frame outside of .ent"));
5960 demand_empty_rest_of_line ();
5961 return;
5963 cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
5964 SKIP_WHITESPACE ();
5965 skip_past_comma (&backupstr);
5966 while (*backupstr != ',')
5968 str[i] = *backupstr;
5969 i++;
5970 backupstr++;
5972 str[i] = '\0';
5973 val = atoi (str);
5975 SKIP_WHITESPACE ();
5976 skip_past_comma (&backupstr);
5977 cur_proc_ptr->frame_offset = val;
5978 cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
5980 SKIP_WHITESPACE ();
5981 skip_past_comma (&backupstr);
5982 i = 0;
5983 while (*backupstr != '\n')
5985 str[i] = *backupstr;
5986 i++;
5987 backupstr++;
5989 str[i] = '\0';
5990 val = atoi (str);
5991 cur_proc_ptr->leaf = val;
5992 SKIP_WHITESPACE ();
5993 skip_past_comma (&backupstr);
5995 #endif /* OBJ_ELF */
5996 while (input_line_pointer != backupstr)
5997 input_line_pointer++;
6000 /* The .end directive. */
6001 static void
6002 s_score_end (int x ATTRIBUTE_UNUSED)
6004 symbolS *p;
6005 int maybe_text;
6007 /* Generate a .pdr section. */
6008 segT saved_seg = now_seg;
6009 subsegT saved_subseg = now_subseg;
6010 valueT dot;
6011 expressionS exp;
6012 char *fragp;
6014 if (!is_end_of_line[(unsigned char)*input_line_pointer])
6016 p = get_symbol ();
6017 demand_empty_rest_of_line ();
6019 else
6020 p = NULL;
6022 #ifdef BFD_ASSEMBLER
6023 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
6024 maybe_text = 1;
6025 else
6026 maybe_text = 0;
6027 #else
6028 if (now_seg != data_section && now_seg != bss_section)
6029 maybe_text = 1;
6030 else
6031 maybe_text = 0;
6032 #endif
6034 if (!maybe_text)
6035 as_warn (_(".end not in text section"));
6036 if (!cur_proc_ptr)
6038 as_warn (_(".end directive without a preceding .ent directive."));
6039 demand_empty_rest_of_line ();
6040 return;
6042 if (p != NULL)
6044 assert (S_GET_NAME (p));
6045 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
6046 as_warn (_(".end symbol does not match .ent symbol."));
6047 if (debug_type == DEBUG_STABS)
6048 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
6050 else
6051 as_warn (_(".end directive missing or unknown symbol"));
6053 if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
6054 (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
6055 (cur_proc_ptr->leaf == 0xdeafbeaf) ||
6056 (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
6057 (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
6059 else
6061 dot = frag_now_fix ();
6062 assert (pdr_seg);
6063 subseg_set (pdr_seg, 0);
6064 /* Write the symbol. */
6065 exp.X_op = O_symbol;
6066 exp.X_add_symbol = p;
6067 exp.X_add_number = 0;
6068 emit_expr (&exp, 4);
6069 fragp = frag_more (7 * 4);
6070 md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
6071 md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
6072 md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
6073 md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
6074 md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
6075 md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
6076 md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
6077 subseg_set (saved_seg, saved_subseg);
6080 cur_proc_ptr = NULL;
6083 /* Handle the .set pseudo-op. */
6084 static void
6085 s_score_set (int x ATTRIBUTE_UNUSED)
6087 int i = 0;
6088 char name[MAX_LITERAL_POOL_SIZE];
6089 char * orig_ilp = input_line_pointer;
6091 while (!is_end_of_line[(unsigned char)*input_line_pointer])
6093 name[i] = (char) * input_line_pointer;
6094 i++;
6095 ++input_line_pointer;
6098 name[i] = '\0';
6100 if (strcmp (name, "nwarn") == 0)
6102 warn_fix_data_dependency = 0;
6104 else if (strcmp (name, "fixdd") == 0)
6106 fix_data_dependency = 1;
6108 else if (strcmp (name, "nofixdd") == 0)
6110 fix_data_dependency = 0;
6112 else if (strcmp (name, "r1") == 0)
6114 nor1 = 0;
6116 else if (strcmp (name, "nor1") == 0)
6118 nor1 = 1;
6120 else if (strcmp (name, "optimize") == 0)
6122 g_opt = 1;
6124 else if (strcmp (name, "volatile") == 0)
6126 g_opt = 0;
6128 else if (strcmp (name, "pic") == 0)
6130 score_pic = PIC;
6132 else
6134 input_line_pointer = orig_ilp;
6135 s_set (0);
6139 /* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the
6140 $gp register for the function based on the function address, which is in the register
6141 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
6142 specially by the linker. The result is:
6143 ldis gp, %hi(GP_DISP_LABEL)
6144 ori gp, %low(GP_DISP_LABEL)
6145 add gp, gp, .cpload argument
6146 The .cpload argument is normally r29. */
6148 static void
6149 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6151 int reg;
6152 char insn_str[MAX_LITERAL_POOL_SIZE];
6154 /* If we are not generating PIC code, .cpload is ignored. */
6155 if (score_pic == NO_PIC)
6157 s_ignore (0);
6158 return;
6161 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6162 return;
6164 demand_empty_rest_of_line ();
6166 sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
6167 if (append_insn (insn_str, TRUE) == (int) FAIL)
6168 return;
6170 sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
6171 if (append_insn (insn_str, TRUE) == (int) FAIL)
6172 return;
6174 sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
6175 if (append_insn (insn_str, TRUE) == (int) FAIL)
6176 return;
6179 /* Handle the .cprestore pseudo-op. This stores $gp into a given
6180 offset from $sp. The offset is remembered, and after making a PIC
6181 call $gp is restored from that location. */
6183 static void
6184 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6186 int reg;
6187 int cprestore_offset;
6188 char insn_str[MAX_LITERAL_POOL_SIZE];
6190 /* If we are not generating PIC code, .cprestore is ignored. */
6191 if (score_pic == NO_PIC)
6193 s_ignore (0);
6194 return;
6197 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
6198 || skip_past_comma (&input_line_pointer) == (int) FAIL)
6200 return;
6203 cprestore_offset = get_absolute_expression ();
6205 if (cprestore_offset <= 0x3fff)
6207 sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
6208 if (append_insn (insn_str, TRUE) == (int) FAIL)
6209 return;
6211 else
6213 int r1_bak;
6215 r1_bak = nor1;
6216 nor1 = 0;
6218 sprintf (insn_str, "li r1, %d", cprestore_offset);
6219 if (append_insn (insn_str, TRUE) == (int) FAIL)
6220 return;
6222 sprintf (insn_str, "add r1, r1, r%d", reg);
6223 if (append_insn (insn_str, TRUE) == (int) FAIL)
6224 return;
6226 sprintf (insn_str, "sw r%d, [r1]", GP);
6227 if (append_insn (insn_str, TRUE) == (int) FAIL)
6228 return;
6230 nor1 = r1_bak;
6233 demand_empty_rest_of_line ();
6236 /* Handle the .gpword pseudo-op. This is used when generating PIC
6237 code. It generates a 32 bit GP relative reloc. */
6238 static void
6239 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6241 expressionS ex;
6242 char *p;
6244 /* When not generating PIC code, this is treated as .word. */
6245 if (score_pic == NO_PIC)
6247 cons (4);
6248 return;
6250 expression (&ex);
6251 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6253 as_bad (_("Unsupported use of .gpword"));
6254 ignore_rest_of_line ();
6256 p = frag_more (4);
6257 md_number_to_chars (p, (valueT) 0, 4);
6258 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6259 demand_empty_rest_of_line ();
6262 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
6263 tables in PIC code. */
6265 static void
6266 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6268 int reg;
6269 char insn_str[MAX_LITERAL_POOL_SIZE];
6271 /* If we are not generating PIC code, .cpload is ignored. */
6272 if (score_pic == NO_PIC)
6274 s_ignore (0);
6275 return;
6278 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6280 return;
6282 demand_empty_rest_of_line ();
6284 /* Add $gp to the register named as an argument. */
6285 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
6286 if (append_insn (insn_str, TRUE) == (int) FAIL)
6287 return;
6290 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6291 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6292 do \
6294 if ((SIZE) >= 8) \
6295 (P2VAR) = 3; \
6296 else if ((SIZE) >= 4) \
6297 (P2VAR) = 2; \
6298 else if ((SIZE) >= 2) \
6299 (P2VAR) = 1; \
6300 else \
6301 (P2VAR) = 0; \
6303 while (0)
6304 #endif
6306 static void
6307 s_score_lcomm (int bytes_p)
6309 char *name;
6310 char c;
6311 char *p;
6312 int temp;
6313 symbolS *symbolP;
6314 segT current_seg = now_seg;
6315 subsegT current_subseg = now_subseg;
6316 const int max_alignment = 15;
6317 int align = 0;
6318 segT bss_seg = bss_section;
6319 int needs_align = 0;
6321 name = input_line_pointer;
6322 c = get_symbol_end ();
6323 p = input_line_pointer;
6324 *p = c;
6326 if (name == p)
6328 as_bad (_("expected symbol name"));
6329 discard_rest_of_line ();
6330 return;
6333 SKIP_WHITESPACE ();
6335 /* Accept an optional comma after the name. The comma used to be
6336 required, but Irix 5 cc does not generate it. */
6337 if (*input_line_pointer == ',')
6339 ++input_line_pointer;
6340 SKIP_WHITESPACE ();
6343 if (is_end_of_line[(unsigned char)*input_line_pointer])
6345 as_bad (_("missing size expression"));
6346 return;
6349 if ((temp = get_absolute_expression ()) < 0)
6351 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6352 ignore_rest_of_line ();
6353 return;
6356 #if defined (TC_SCORE)
6357 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6359 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
6360 if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6362 bss_seg = subseg_new (".sbss", 1);
6363 seg_info (bss_seg)->bss = 1;
6364 #ifdef BFD_ASSEMBLER
6365 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6366 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6367 #endif
6370 #endif
6372 SKIP_WHITESPACE ();
6373 if (*input_line_pointer == ',')
6375 ++input_line_pointer;
6376 SKIP_WHITESPACE ();
6378 if (is_end_of_line[(unsigned char)*input_line_pointer])
6380 as_bad (_("missing alignment"));
6381 return;
6383 else
6385 align = get_absolute_expression ();
6386 needs_align = 1;
6390 if (!needs_align)
6392 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6394 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6395 if (align)
6396 record_alignment (bss_seg, align);
6399 if (needs_align)
6401 if (bytes_p)
6403 /* Convert to a power of 2. */
6404 if (align != 0)
6406 unsigned int i;
6408 for (i = 0; align != 0; align >>= 1, ++i)
6410 align = i - 1;
6414 if (align > max_alignment)
6416 align = max_alignment;
6417 as_warn (_("alignment too large; %d assumed"), align);
6419 else if (align < 0)
6421 align = 0;
6422 as_warn (_("alignment negative; 0 assumed"));
6425 record_alignment (bss_seg, align);
6427 else
6429 /* Assume some objects may require alignment on some systems. */
6430 #if defined (TC_ALPHA) && ! defined (VMS)
6431 if (temp > 1)
6433 align = ffs (temp) - 1;
6434 if (temp % (1 << align))
6435 abort ();
6437 #endif
6440 *p = 0;
6441 symbolP = symbol_find_or_make (name);
6442 *p = c;
6444 if (
6445 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6446 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6447 #ifdef BFD_ASSEMBLER
6448 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6449 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6450 #else
6451 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6452 #endif
6453 #endif
6454 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6456 char *pfrag;
6458 subseg_set (bss_seg, 1);
6460 if (align)
6461 frag_align (align, 0, 0);
6463 /* Detach from old frag. */
6464 if (S_GET_SEGMENT (symbolP) == bss_seg)
6465 symbol_get_frag (symbolP)->fr_symbol = NULL;
6467 symbol_set_frag (symbolP, frag_now);
6468 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6469 *pfrag = 0;
6472 S_SET_SEGMENT (symbolP, bss_seg);
6474 #ifdef OBJ_COFF
6475 /* The symbol may already have been created with a preceding
6476 ".globl" directive -- be careful not to step on storage class
6477 in that case. Otherwise, set it to static. */
6478 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6480 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6482 #endif /* OBJ_COFF */
6484 #ifdef S_SET_SIZE
6485 S_SET_SIZE (symbolP, temp);
6486 #endif
6488 else
6489 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6491 subseg_set (current_seg, current_subseg);
6493 demand_empty_rest_of_line ();
6496 static void
6497 insert_reg (const struct reg_entry *r, struct hash_control *htab)
6499 int i = 0;
6500 int len = strlen (r->name) + 2;
6501 char *buf = xmalloc (len);
6502 char *buf2 = xmalloc (len);
6504 strcpy (buf + i, r->name);
6505 for (i = 0; buf[i]; i++)
6507 buf2[i] = TOUPPER (buf[i]);
6509 buf2[i] = '\0';
6511 hash_insert (htab, buf, (void *) r);
6512 hash_insert (htab, buf2, (void *) r);
6515 static void
6516 build_reg_hsh (struct reg_map *map)
6518 const struct reg_entry *r;
6520 if ((map->htab = hash_new ()) == NULL)
6522 as_fatal (_("virtual memory exhausted"));
6524 for (r = map->names; r->name != NULL; r++)
6526 insert_reg (r, map->htab);
6530 void
6531 md_begin (void)
6533 unsigned int i;
6534 segT seg;
6535 subsegT subseg;
6537 if ((score_ops_hsh = hash_new ()) == NULL)
6538 as_fatal (_("virtual memory exhausted"));
6540 build_score_ops_hsh ();
6542 if ((dependency_insn_hsh = hash_new ()) == NULL)
6543 as_fatal (_("virtual memory exhausted"));
6545 build_dependency_insn_hsh ();
6547 for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
6548 build_reg_hsh (all_reg_maps + i);
6550 /* Initialize dependency vector. */
6551 init_dependency_vector ();
6553 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6554 seg = now_seg;
6555 subseg = now_subseg;
6556 pdr_seg = subseg_new (".pdr", (subsegT) 0);
6557 (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6558 (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
6559 subseg_set (seg, subseg);
6561 if (USE_GLOBAL_POINTER_OPT)
6562 bfd_set_gp_size (stdoutput, g_switch_value);
6566 const pseudo_typeS md_pseudo_table[] =
6568 {"bss", s_score_bss, 0},
6569 {"text", s_score_text, 0},
6570 {"word", cons, 4},
6571 {"long", cons, 4},
6572 {"extend", float_cons, 'x'},
6573 {"ldouble", float_cons, 'x'},
6574 {"packed", float_cons, 'p'},
6575 {"end", s_score_end, 0},
6576 {"ent", s_score_ent, 0},
6577 {"frame", s_score_frame, 0},
6578 {"rdata", s_change_sec, 'r'},
6579 {"sdata", s_change_sec, 's'},
6580 {"set", s_score_set, 0},
6581 {"mask", s_score_mask, 'R'},
6582 {"dword", cons, 8},
6583 {"lcomm", s_score_lcomm, 1},
6584 {"section", score_s_section, 0},
6585 {"cpload", s_score_cpload, 0},
6586 {"cprestore", s_score_cprestore, 0},
6587 {"gpword", s_score_gpword, 0},
6588 {"cpadd", s_score_cpadd, 0},
6589 {0, 0, 0}