2007-01-04 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / gas / config / tc-score.c
blob428ffcf1535b5dcc0a52b64a4176986f7ef38fb6
1 /* tc-score.c -- Assembler for Score
2 Copyright 2006 Free Software Foundation, Inc.
3 Contributed by:
4 Mei Ligang (ligang@sunnorth.com.cn)
5 Pei-Lin Tsai (pltsai@sunplus.com)
7 This file is part of GAS, the GNU Assembler.
9 GAS is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GAS is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GAS; see the file COPYING. If not, write to the Free
21 Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 #include "as.h"
25 #include "config.h"
26 #include "subsegs.h"
27 #include "safe-ctype.h"
28 #include "opcode/score-inst.h"
29 #include "opcode/score-datadep.h"
30 #include "struc-symbol.h"
32 #ifdef OBJ_ELF
33 #include "elf/score.h"
34 #include "dwarf2dbg.h"
35 #endif
37 #define GP 28
38 #define PIC_CALL_REG 29
39 #define MAX_LITERAL_POOL_SIZE 1024
40 #define FAIL 0x80000000
41 #define SUCCESS 0
42 #define INSN_SIZE 4
43 #define INSN16_SIZE 2
44 #define RELAX_INST_NUM 3
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 fragS *score_fragp = 0;
107 static int fix_data_dependency = 0;
108 static int warn_fix_data_dependency = 1;
109 static int score7 = 1;
110 static int university_version = 0;
112 static int in_my_get_expression = 0;
114 #define USE_GLOBAL_POINTER_OPT 1
115 #define SCORE_BI_ENDIAN
117 /* Default, pop warning message when using r1. */
118 static int nor1 = 1;
120 /* Default will do instruction relax, -O0 will set g_opt = 0. */
121 static unsigned int g_opt = 1;
123 /* The size of the small data section. */
124 static unsigned int g_switch_value = 8;
126 #ifdef OBJ_ELF
127 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
128 symbolS *GOT_symbol;
129 #endif
130 static segT pdr_seg;
132 enum score_pic_level score_pic = NO_PIC;
134 #define INSN_NAME_LEN 16
135 struct score_it
137 char name[INSN_NAME_LEN];
138 unsigned long instruction;
139 unsigned long relax_inst;
140 int size;
141 int relax_size;
142 enum score_insn_type type;
143 char str[MAX_LITERAL_POOL_SIZE];
144 const char *error;
145 int bwarn;
146 char reg[INSN_NAME_LEN];
147 struct
149 bfd_reloc_code_real_type type;
150 expressionS exp;
151 int pc_rel;
152 }reloc;
154 struct score_it inst;
156 typedef struct proc
158 symbolS *isym;
159 unsigned long reg_mask;
160 unsigned long reg_offset;
161 unsigned long fpreg_mask;
162 unsigned long leaf;
163 unsigned long frame_offset;
164 unsigned long frame_reg;
165 unsigned long pc_reg;
167 procS;
169 static procS cur_proc;
170 static procS *cur_proc_ptr;
171 static int numprocs;
173 #define SCORE7_PIPELINE 7
174 #define SCORE5_PIPELINE 5
175 static int vector_size = SCORE7_PIPELINE;
176 struct score_it dependency_vector[SCORE7_PIPELINE];
178 /* Relax will need some padding for alignment. */
179 #define RELAX_PAD_BYTE 3
181 /* Number of littlenums required to hold an extended precision number. For md_atof. */
182 #define NUM_FLOAT_VALS 8
183 #define MAX_LITTLENUMS 6
184 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
186 /* Structure for a hash table entry for a register. */
187 struct reg_entry
189 const char *name;
190 int number;
193 static const struct reg_entry score_rn_table[] =
195 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
196 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
197 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
198 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
199 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
200 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
201 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
202 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
203 {NULL, 0}
206 static const struct reg_entry score_srn_table[] =
208 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
209 {NULL, 0}
212 static const struct reg_entry score_crn_table[] =
214 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
215 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
216 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
217 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
218 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
219 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
220 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
221 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
222 {NULL, 0}
225 struct reg_map
227 const struct reg_entry *names;
228 int max_regno;
229 struct hash_control *htab;
230 const char *expected;
233 struct reg_map all_reg_maps[] =
235 {score_rn_table, 31, NULL, N_("S+core register expected")},
236 {score_srn_table, 2, NULL, N_("S+core special-register expected")},
237 {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
240 static struct hash_control *score_ops_hsh = NULL;
242 static struct hash_control *dependency_insn_hsh = NULL;
244 /* Enumeration matching entries in table above. */
245 enum score_reg_type
247 REG_TYPE_SCORE = 0,
248 #define REG_TYPE_FIRST REG_TYPE_SCORE
249 REG_TYPE_SCORE_SR = 1,
250 REG_TYPE_SCORE_CR = 2,
251 REG_TYPE_MAX = 3
254 typedef struct literalS
256 struct expressionS exp;
257 struct score_it *inst;
259 literalT;
261 literalT literals[MAX_LITERAL_POOL_SIZE];
263 static void do_ldst_insn (char *);
264 static void do_crdcrscrsimm5 (char *);
265 static void do_ldst_unalign (char *);
266 static void do_ldst_atomic (char *);
267 static void do_ldst_cop (char *);
268 static void do_macro_li_rdi32 (char *);
269 static void do_macro_la_rdi32 (char *);
270 static void do_macro_rdi32hi (char *);
271 static void do_macro_rdi32lo (char *);
272 static void do_macro_mul_rdrsrs (char *);
273 static void do_macro_ldst_label (char *);
274 static void do_branch (char *);
275 static void do_jump (char *);
276 static void do_empty (char *);
277 static void do_rdrsrs (char *);
278 static void do_rdsi16 (char *);
279 static void do_rdrssi14 (char *);
280 static void do_sub_rdsi16 (char *);
281 static void do_sub_rdi16 (char *);
282 static void do_sub_rdrssi14 (char *);
283 static void do_rdrsi5 (char *);
284 static void do_rdrsi14 (char *);
285 static void do_rdi16 (char *);
286 static void do_xrsi5 (char *);
287 static void do_rdrs (char *);
288 static void do_rdxrs (char *);
289 static void do_rsrs (char *);
290 static void do_rdcrs (char *);
291 static void do_rdsrs (char *);
292 static void do_rd (char *);
293 static void do_rs (char *);
294 static void do_i15 (char *);
295 static void do_xi5x (char *);
296 static void do_ceinst (char *);
297 static void do_cache (char *);
298 static void do16_rdrs (char *);
299 static void do16_rs (char *);
300 static void do16_xrs (char *);
301 static void do16_mv_rdrs (char *);
302 static void do16_hrdrs (char *);
303 static void do16_rdhrs (char *);
304 static void do16_rdi4 (char *);
305 static void do16_rdi5 (char *);
306 static void do16_xi5 (char *);
307 static void do16_ldst_insn (char *);
308 static void do16_ldst_imm_insn (char *);
309 static void do16_push_pop (char *);
310 static void do16_branch (char *);
311 static void do16_jump (char *);
312 static void do_rdi16_pic (char *);
313 static void do_addi_s_pic (char *);
314 static void do_addi_u_pic (char *);
315 static void do_lw_pic (char *);
317 static const struct asm_opcode score_ldst_insns[] =
319 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_ldst_insn},
320 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
321 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, do_ldst_insn},
322 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, do_ldst_insn},
323 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
324 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
325 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
326 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
327 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
328 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn},
329 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
330 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
331 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, do_ldst_insn},
332 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, do_ldst_insn},
333 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
334 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, do_ldst_insn},
335 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
336 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
337 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, do_ldst_insn},
338 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn},
339 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn},
340 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, do_ldst_insn},
341 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn},
342 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn},
345 static const struct asm_opcode score_insns[] =
347 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
348 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
349 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
350 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, do_rdrsrs},
351 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
352 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
353 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, do_rdrsrs},
354 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
355 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
356 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
357 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16},
358 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
359 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14},
360 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, do16_rdrs},
361 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, do16_rdrs},
362 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, do16_rdi4},
363 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
364 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16},
365 {"subis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdi16},
366 {"subis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdi16},
367 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
368 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14},
369 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
370 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, do_rdrsrs},
371 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
372 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
373 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
374 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
375 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
376 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
377 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, do16_rdrs},
378 {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
379 {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
380 {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
381 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
382 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
383 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
384 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, do16_branch},
385 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, do16_branch},
386 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, do16_branch},
387 {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
388 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
389 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, do16_branch},
390 {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
391 {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
392 {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
393 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
394 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
395 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
396 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, do16_branch},
397 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, do16_branch},
398 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, do16_branch},
399 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, do_rdrsi5},
400 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
401 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, do_rdrsi5},
402 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, do_xrsi5},
403 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, do_rdrsi5},
404 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, do16_rdi5},
405 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, do16_rdi5},
406 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, do16_rdi5},
407 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, do16_rdi5},
408 {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
409 {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
410 {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
411 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
412 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
413 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
414 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
415 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, do16_branch},
416 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, do16_branch},
417 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, do16_branch},
418 {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
419 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
420 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, do16_branch},
421 {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
422 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
423 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, do16_branch},
424 {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
425 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
426 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, do16_branch},
427 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, do_rs},
428 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, do_rs},
429 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, do_rs},
430 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, do_rs},
431 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, do_rs},
432 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, do_rs},
433 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, do_rs},
434 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, do_rs},
435 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, do_rs},
436 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, do_rs},
437 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, do_rs},
438 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, do_rs},
439 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, do_rs},
440 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, do_rs},
441 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, do_rs},
442 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, do_rs},
443 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, do_rs},
444 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, do_rs},
445 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, do_rs},
446 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, do_rs},
447 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, do_rs},
448 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, do_rs},
449 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, do_rs},
450 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, do_rs},
451 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, do_rs},
452 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, do_rs},
453 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, do_rs},
454 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, do_rs},
455 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, do_rs},
456 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, do_rs},
457 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, do_rs},
458 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, do_rs},
459 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, do16_xrs},
460 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, do16_xrs},
461 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, do16_xrs},
462 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, do16_xrs},
463 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, do16_xrs},
464 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, do16_xrs},
465 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, do16_xrs},
466 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, do16_xrs},
467 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, do16_xrs},
468 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, do16_xrs},
469 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, do16_xrs},
470 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, do16_xrs},
471 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, do16_xrs},
472 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, do16_xrs},
473 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, do16_xrs},
474 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, do16_xrs},
475 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, do16_xrs},
476 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, do16_xrs},
477 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, do16_xrs},
478 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, do16_xrs},
479 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, do16_xrs},
480 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, do16_xrs},
481 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, do16_xrs},
482 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, do16_xrs},
483 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, do16_xrs},
484 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, do16_xrs},
485 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, do16_xrs},
486 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, do16_xrs},
487 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, do16_xrs},
488 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, do16_xrs},
489 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, do16_xrs},
490 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, do16_xrs},
491 {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
492 {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
493 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
494 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch},
495 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, do16_branch},
496 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, do16_branch},
497 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, do16_branch},
498 {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch},
499 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, do_cache},
500 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, do_ceinst},
501 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
502 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
503 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
504 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, do_rsrs},
505 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
506 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
507 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs},
508 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16},
509 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, do16_rdrs},
510 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
511 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
512 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5},
513 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
514 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
515 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
516 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
517 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
518 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
519 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
520 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
521 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
522 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
523 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, do16_jump},
524 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, do16_jump},
525 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, do_jump},
526 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, do16_ldst_insn},
527 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
528 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, do_ldst_atomic},
529 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, do_ldst_unalign},
530 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
531 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign},
532 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
533 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
534 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop},
535 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, do16_ldst_insn},
536 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
537 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, do_rdsi16},
538 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x5000, Rd_I16, do_rdi16},
539 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, do16_ldst_imm_insn},
540 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, do16_ldst_insn},
541 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, do16_ldst_imm_insn},
542 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
543 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, do16_rs},
544 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
545 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, do16_rdrs},
546 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
547 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
548 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, do16_rdrs},
549 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
550 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
551 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, do16_rdrs},
552 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
553 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, do16_rdrs},
554 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
555 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
556 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
557 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
558 {"mazh.f!", 0x1009, 0x700f, 0x3800038c, Rd_Rs, do16_rdrs},
559 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
560 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
561 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, do16_rdrs},
562 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
563 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, do16_rs},
564 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
565 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, do_rdsrs},
566 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
567 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
568 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
569 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
570 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
571 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
572 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
573 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, do16_hrdrs},
574 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
575 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, do16_rdhrs},
576 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
577 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, do16_rdrs},
578 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
579 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
580 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, do16_rdrs},
581 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
582 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
583 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, do16_rdrs},
584 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
585 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, do16_rdrs},
586 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
587 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
588 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
589 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, do16_rdrs},
590 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
591 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs},
592 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, do16_rdrs},
593 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, do16_rs},
594 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
595 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, do_rd},
596 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, do16_rs},
597 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
598 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, do_rdsrs},
599 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
600 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
601 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
602 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
603 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
604 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
605 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs},
606 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, do16_rdrs},
607 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, do16_rdrs},
608 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
609 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
610 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
611 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
612 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
613 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
614 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
615 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
616 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
617 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
618 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
619 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
620 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
621 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs},
622 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, do_rdrs},
623 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, do16_mv_rdrs},
624 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, do_rdxrs},
625 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, do_rdxrs},
626 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, do16_rdrs},
627 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, do_empty},
628 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs},
629 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, do_rdrs},
630 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, do_empty},
631 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, do16_rdrs},
632 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
633 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, do_rdrsrs},
634 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
635 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
636 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
637 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16},
638 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
639 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14},
640 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, do16_rdrs},
641 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
642 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, do16_push_pop},
643 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, do16_push_pop},
644 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
645 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
646 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
647 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
648 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
649 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
650 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
651 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
652 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
653 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
654 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
655 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
656 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
657 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, do16_ldst_insn},
658 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
659 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, do_ldst_atomic},
660 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
661 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign},
662 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, do_ldst_unalign},
663 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, do_xi5x},
664 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, do16_xi5},
665 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, do16_ldst_insn},
666 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
667 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
668 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
669 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, do_rdrsrs},
670 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
671 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
672 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, do_rdrsi5},
673 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, do16_rdrs},
674 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, do16_rdi5},
675 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
676 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, do_rdrsrs},
677 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
678 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, do_rdrsrs},
679 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
680 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, do_rdrsi5},
681 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
682 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5},
683 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, do16_rdrs},
684 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, do16_rdrs},
685 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, do16_rdi5},
686 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
687 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
688 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop},
689 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
690 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, do_rdrsrs},
691 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
692 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
693 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
694 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, do16_rdrs},
695 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, do16_rdi4},
696 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, do16_ldst_insn},
697 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, do16_ldst_imm_insn},
698 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, do_i15},
699 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, do_empty},
700 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, do_empty},
701 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, do_empty},
702 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, do_empty},
703 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, do_empty},
704 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, do_empty},
705 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, do_empty},
706 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, do_empty},
707 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, do_empty},
708 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, do_empty},
709 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, do_empty},
710 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, do_empty},
711 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, do_empty},
712 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, do_empty},
713 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, do_empty},
714 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, do_empty},
715 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, do_empty},
716 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
717 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
718 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
719 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, do_empty},
720 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, do_empty},
721 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, do_empty},
722 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, do_empty},
723 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, do_empty},
724 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, do_empty},
725 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, do_empty},
726 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, do_empty},
727 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, do_empty},
728 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, do_empty},
729 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
730 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
731 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
732 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
733 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
734 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
735 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
736 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
737 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
738 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
739 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
740 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
741 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
742 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
743 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x},
744 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, do_empty},
745 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, do_empty},
746 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, do_empty},
747 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, do_empty},
748 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, do_empty},
749 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, do_empty},
750 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs},
751 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, do_rdrsrs},
752 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, do16_rdrs},
753 /* Macro instruction. */
754 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_li_rdi32},
755 /* la reg, imm32 -->(1) ldi reg, simm16
756 (2) ldis reg, %HI(imm32)
757 ori reg, %LO(imm32)
759 la reg, symbol -->(1) lis reg, %HI(imm32)
760 ori reg, %LO(imm32) */
761 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_la_rdi32},
762 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
763 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
764 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
765 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
766 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
767 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
768 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
769 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
770 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
771 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs},
772 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
773 {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, do_macro_ldst_label},
774 {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, do_macro_ldst_label},
775 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label},
776 {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, do_macro_ldst_label},
777 {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, do_macro_ldst_label},
778 {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, do_macro_ldst_label},
779 {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, do_macro_ldst_label},
780 /* Assembler use internal. */
781 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, do_macro_rdi32hi},
782 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, do_macro_rdi32lo},
783 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, do_rdi16_pic},
784 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_s_pic},
785 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_u_pic},
786 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, do_lw_pic},
789 /* Next free entry in the pool. */
790 int next_literal_pool_place = 0;
792 /* Next literal pool number. */
793 int lit_pool_num = 1;
794 symbolS *current_poolP = NULL;
796 static int
797 end_of_line (char *str)
799 int retval = SUCCESS;
801 skip_whitespace (str);
802 if (*str != '\0')
804 retval = (int) FAIL;
806 if (!inst.error)
807 inst.error = BAD_GARBAGE;
810 return retval;
813 static int
814 score_reg_parse (char **ccp, struct hash_control *htab)
816 char *start = *ccp;
817 char c;
818 char *p;
819 struct reg_entry *reg;
821 p = start;
822 if (!ISALPHA (*p) || !is_name_beginner (*p))
823 return (int) FAIL;
825 c = *p++;
827 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
828 c = *p++;
830 *--p = 0;
831 reg = (struct reg_entry *) hash_find (htab, start);
832 *p = c;
834 if (reg)
836 *ccp = p;
837 return reg->number;
839 return (int) FAIL;
842 /* If shift <= 0, only return reg. */
844 static int
845 reg_required_here (char **str, int shift, enum score_reg_type reg_type)
847 static char buff[MAX_LITERAL_POOL_SIZE];
848 int reg = (int) FAIL;
849 char *start = *str;
851 if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
853 if (reg_type == REG_TYPE_SCORE)
855 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
857 as_warn ("Using temp register(r1)");
858 inst.bwarn = 1;
861 if (shift >= 0)
863 if (reg_type == REG_TYPE_SCORE_CR)
864 strcpy (inst.reg, score_crn_table[reg].name);
865 else if (reg_type == REG_TYPE_SCORE_SR)
866 strcpy (inst.reg, score_srn_table[reg].name);
867 else
868 strcpy (inst.reg, "");
870 inst.instruction |= reg << shift;
873 else
875 *str = start;
876 sprintf (buff, _("register expected, not '%.100s'"), start);
877 inst.error = buff;
880 return reg;
883 static int
884 skip_past_comma (char **str)
886 char *p = *str;
887 char c;
888 int comma = 0;
890 while ((c = *p) == ' ' || c == ',')
892 p++;
893 if (c == ',' && comma++)
895 inst.error = BAD_SKIP_COMMA;
896 return (int) FAIL;
900 if ((c == '\0') || (comma == 0))
902 inst.error = BAD_SKIP_COMMA;
903 return (int) FAIL;
906 *str = p;
907 return comma ? SUCCESS : (int) FAIL;
910 static void
911 do_rdrsrs (char *str)
913 skip_whitespace (str);
915 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
916 || skip_past_comma (&str) == (int) FAIL
917 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
918 || skip_past_comma (&str) == (int) FAIL
919 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
920 || end_of_line (str) == (int) FAIL)
922 return;
924 else
926 if ((((inst.instruction >> 15) & 0x10) == 0)
927 && (((inst.instruction >> 10) & 0x10) == 0)
928 && (((inst.instruction >> 20) & 0x10) == 0)
929 && (inst.relax_inst != 0x8000)
930 && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
932 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
933 | (((inst.instruction >> 15) & 0xf) << 8);
934 inst.relax_size = 2;
936 else
938 inst.relax_inst = 0x8000;
943 static int
944 walk_no_bignums (symbolS * sp)
946 if (symbol_get_value_expression (sp)->X_op == O_big)
947 return 1;
949 if (symbol_get_value_expression (sp)->X_add_symbol)
950 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
951 || (symbol_get_value_expression (sp)->X_op_symbol
952 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
954 return 0;
957 static int
958 my_get_expression (expressionS * ep, char **str)
960 char *save_in;
961 segT seg;
963 save_in = input_line_pointer;
964 input_line_pointer = *str;
965 in_my_get_expression = 1;
966 seg = expression (ep);
967 in_my_get_expression = 0;
969 if (ep->X_op == O_illegal)
971 *str = input_line_pointer;
972 input_line_pointer = save_in;
973 inst.error = _("illegal expression");
974 return (int) FAIL;
976 /* Get rid of any bignums now, so that we don't generate an error for which
977 we can't establish a line number later on. Big numbers are never valid
978 in instructions, which is where this routine is always called. */
979 if (ep->X_op == O_big
980 || (ep->X_add_symbol
981 && (walk_no_bignums (ep->X_add_symbol)
982 || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
984 inst.error = _("invalid constant");
985 *str = input_line_pointer;
986 input_line_pointer = save_in;
987 return (int) FAIL;
990 if ((ep->X_add_symbol != NULL)
991 && (inst.type != PC_DISP19div2)
992 && (inst.type != PC_DISP8div2)
993 && (inst.type != PC_DISP24div2)
994 && (inst.type != PC_DISP11div2)
995 && (inst.type != Insn_Type_SYN)
996 && (inst.type != Rd_rvalueRs_SI15)
997 && (inst.type != Rd_lvalueRs_SI15)
998 && (inst.type != Insn_internal))
1000 inst.error = BAD_ARGS;
1001 *str = input_line_pointer;
1002 input_line_pointer = save_in;
1003 return (int) FAIL;
1006 *str = input_line_pointer;
1007 input_line_pointer = save_in;
1008 return SUCCESS;
1011 /* Check if an immediate is valid. If so, convert it to the right format. */
1013 static int
1014 validate_immediate (int val, unsigned int data_type)
1016 switch (data_type)
1018 case _VALUE_HI16:
1020 int val_hi = ((val & 0xffff0000) >> 16);
1022 if (score_df_range[data_type].range[0] <= val_hi
1023 && val_hi <= score_df_range[data_type].range[1])
1024 return val_hi;
1026 break;
1028 case _VALUE_LO16:
1030 int val_lo = (val & 0xffff);
1032 if (score_df_range[data_type].range[0] <= val_lo
1033 && val_lo <= score_df_range[data_type].range[1])
1034 return val_lo;
1036 break;
1038 case _VALUE:
1039 return val;
1040 break;
1042 default:
1043 if (data_type == _SIMM14_NEG || data_type == _SIMM16_NEG || data_type == _IMM16_NEG)
1044 val = -val;
1046 if (score_df_range[data_type].range[0] <= val
1047 && val <= score_df_range[data_type].range[1])
1048 return val;
1050 break;
1053 return (int) FAIL;
1056 static int
1057 data_op2 (char **str, int shift, enum score_data_type data_type)
1059 int value;
1060 char data_exp[MAX_LITERAL_POOL_SIZE];
1061 char *dataptr;
1062 int cnt = 0;
1063 char *pp = NULL;
1065 skip_whitespace (*str);
1066 inst.error = NULL;
1067 dataptr = * str;
1069 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1071 data_exp[cnt] = *dataptr;
1072 dataptr++;
1073 cnt++;
1076 data_exp[cnt] = '\0';
1077 pp = (char *)&data_exp;
1079 if (*dataptr == '|') /* process PCE */
1081 if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
1082 return (int) FAIL;
1083 end_of_line (pp);
1084 if (inst.error != 0)
1085 return (int) FAIL; /* to ouptut_inst to printf out the error */
1086 *str = dataptr;
1088 else /* process 16 bit */
1090 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
1092 return (int) FAIL;
1095 dataptr = (char *)data_exp;
1096 for (; *dataptr != '\0'; dataptr++)
1098 *dataptr = TOLOWER (*dataptr);
1099 if (*dataptr == '!' || *dataptr == ' ')
1100 break;
1102 dataptr = (char *)data_exp;
1104 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
1105 && (data_type != _SIMM16_LA)
1106 && (data_type != _VALUE_HI16)
1107 && (data_type != _VALUE_LO16)
1108 && (data_type != _IMM16)
1109 && (data_type != _IMM15)
1110 && (data_type != _IMM14)
1111 && (data_type != _IMM4)
1112 && (data_type != _IMM5)
1113 && (data_type != _IMM8)
1114 && (data_type != _IMM5_RSHIFT_1)
1115 && (data_type != _IMM5_RSHIFT_2)
1116 && (data_type != _SIMM14_NEG)
1117 && (data_type != _IMM10_RSHIFT_2)
1118 && (data_type != _GP_IMM15))
1120 data_type += 24;
1123 if ((inst.reloc.exp.X_add_number == 0)
1124 && (inst.type != Insn_Type_SYN)
1125 && (inst.type != Rd_rvalueRs_SI15)
1126 && (inst.type != Rd_lvalueRs_SI15)
1127 && (inst.type != Insn_internal)
1128 && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1129 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1130 || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1131 || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1133 inst.error = BAD_ARGS;
1134 return (int) FAIL;
1138 if ((inst.reloc.exp.X_add_symbol)
1139 && ((data_type == _SIMM16)
1140 || (data_type == _SIMM16_NEG)
1141 || (data_type == _IMM16_NEG)
1142 || (data_type == _SIMM14)
1143 || (data_type == _SIMM14_NEG)
1144 || (data_type == _IMM5)
1145 || (data_type == _IMM14)
1146 || (data_type == _IMM20)
1147 || (data_type == _IMM16)
1148 || (data_type == _IMM15)
1149 || (data_type == _IMM4)))
1151 inst.error = BAD_ARGS;
1152 return (int) FAIL;
1155 if (inst.reloc.exp.X_add_symbol)
1157 switch (data_type)
1159 case _SIMM16_LA:
1160 return (int) FAIL;
1161 case _VALUE_HI16:
1162 inst.reloc.type = BFD_RELOC_HI16_S;
1163 inst.reloc.pc_rel = 0;
1164 break;
1165 case _VALUE_LO16:
1166 inst.reloc.type = BFD_RELOC_LO16;
1167 inst.reloc.pc_rel = 0;
1168 break;
1169 case _GP_IMM15:
1170 inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1171 inst.reloc.pc_rel = 0;
1172 break;
1173 case _SIMM16_pic:
1174 case _IMM16_LO16_pic:
1175 inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1176 inst.reloc.pc_rel = 0;
1177 break;
1178 default:
1179 inst.reloc.type = BFD_RELOC_32;
1180 inst.reloc.pc_rel = 0;
1181 break;
1184 else
1186 if (data_type == _IMM16_pic)
1188 inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1189 inst.reloc.pc_rel = 0;
1192 if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
1194 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS);
1195 if (value == (int) FAIL) /* for advance to check if this is ldis */
1196 if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
1198 inst.instruction |= 0x8000000;
1199 inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1200 return SUCCESS;
1203 else
1205 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
1208 if (value == (int) FAIL)
1210 char err_msg[100];
1212 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1214 sprintf (err_msg,
1215 "invalid constant: %d bit expression not in range %d..%d",
1216 score_df_range[data_type].bits,
1217 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
1219 else
1221 sprintf (err_msg,
1222 "invalid constant: %d bit expression not in range %d..%d",
1223 score_df_range[data_type].bits,
1224 -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
1227 inst.error = _(err_msg);
1228 return (int) FAIL;
1231 if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1233 value &= (1 << score_df_range[data_type].bits) - 1;
1236 inst.instruction |= value << shift;
1239 if ((inst.instruction & 0xf0000000) == 0x30000000)
1241 if ((((inst.instruction >> 20) & 0x1F) != 0)
1242 && (((inst.instruction >> 20) & 0x1F) != 1)
1243 && (((inst.instruction >> 20) & 0x1F) != 2)
1244 && (((inst.instruction >> 20) & 0x1F) != 3)
1245 && (((inst.instruction >> 20) & 0x1F) != 4)
1246 && (((inst.instruction >> 20) & 0x1F) != 8)
1247 && (((inst.instruction >> 20) & 0x1F) != 9)
1248 && (((inst.instruction >> 20) & 0x1F) != 0xa)
1249 && (((inst.instruction >> 20) & 0x1F) != 0xb)
1250 && (((inst.instruction >> 20) & 0x1F) != 0xc)
1251 && (((inst.instruction >> 20) & 0x1F) != 0xd)
1252 && (((inst.instruction >> 20) & 0x1F) != 0xe)
1253 && (((inst.instruction >> 20) & 0x1F) != 0x10)
1254 && (((inst.instruction >> 20) & 0x1F) != 0x11)
1255 && (((inst.instruction >> 20) & 0x1F) != 0x18)
1256 && (((inst.instruction >> 20) & 0x1F) != 0x1A)
1257 && (((inst.instruction >> 20) & 0x1F) != 0x1B)
1258 && (((inst.instruction >> 20) & 0x1F) != 0x1d)
1259 && (((inst.instruction >> 20) & 0x1F) != 0x1e)
1260 && (((inst.instruction >> 20) & 0x1F) != 0x1f))
1262 char err_msg[100];
1264 sprintf (err_msg, "invalid constant: bit expression not defined");
1265 inst.error = _(err_msg);
1266 return (int) FAIL;
1270 return SUCCESS;
1273 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1275 static void
1276 do_rdsi16 (char *str)
1278 skip_whitespace (str);
1280 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1281 || skip_past_comma (&str) == (int) FAIL
1282 || data_op2 (&str, 1, _SIMM16) == (int) FAIL
1283 || end_of_line (str) == (int) FAIL)
1284 return;
1286 /* ldi. */
1287 if ((inst.instruction & 0x20c0000) == 0x20c0000)
1289 if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
1291 inst.relax_inst = 0x8000;
1293 else
1295 inst.relax_inst |= (inst.instruction >> 1) & 0xff;
1296 inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
1297 inst.relax_size = 2;
1300 else if (((inst.instruction >> 20) & 0x10) == 0x10)
1302 inst.relax_inst = 0x8000;
1306 /* Handle subi/subi.c. */
1308 static void
1309 do_sub_rdsi16 (char *str)
1311 skip_whitespace (str);
1313 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1314 && skip_past_comma (&str) != (int) FAIL
1315 && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
1316 end_of_line (str);
1319 /* Handle subis/subis.c. */
1321 static void
1322 do_sub_rdi16 (char *str)
1324 skip_whitespace (str);
1326 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1327 && skip_past_comma (&str) != (int) FAIL
1328 && data_op2 (&str, 1, _IMM16_NEG) != (int) FAIL)
1329 end_of_line (str);
1332 /* Handle addri/addri.c. */
1334 static void
1335 do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1337 skip_whitespace (str);
1339 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1340 && skip_past_comma (&str) != (int) FAIL
1341 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1342 && skip_past_comma (&str) != (int) FAIL)
1343 data_op2 (&str, 1, _SIMM14);
1346 /* Handle subri.c/subri. */
1347 static void
1348 do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1350 skip_whitespace (str);
1352 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1353 && skip_past_comma (&str) != (int) FAIL
1354 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1355 && skip_past_comma (&str) != (int) FAIL
1356 && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
1357 end_of_line (str);
1360 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1361 static void
1362 do_rdrsi5 (char *str) /* 0~((2^14)-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, 10, _IMM5) == (int) FAIL
1371 || end_of_line (str) == (int) FAIL)
1372 return;
1374 if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
1375 && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1377 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1378 inst.relax_size = 2;
1380 else
1381 inst.relax_inst = 0x8000;
1384 /* Handle andri/orri/andri.c/orri.c. */
1386 static void
1387 do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1389 skip_whitespace (str);
1391 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1392 && skip_past_comma (&str) != (int) FAIL
1393 && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1394 && skip_past_comma (&str) != (int) FAIL
1395 && data_op2 (&str, 1, _IMM14) != (int) FAIL)
1396 end_of_line (str);
1399 /* Handle bittst.c. */
1400 static void
1401 do_xrsi5 (char *str)
1403 skip_whitespace (str);
1405 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1406 || skip_past_comma (&str) == (int) FAIL
1407 || data_op2 (&str, 10, _IMM5) == (int) FAIL
1408 || end_of_line (str) == (int) FAIL)
1409 return;
1411 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1413 inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1414 inst.relax_size = 2;
1416 else
1417 inst.relax_inst = 0x8000;
1420 /* Handle andi/ori/andis/oris/ldis. */
1421 static void
1422 do_rdi16 (char *str)
1424 skip_whitespace (str);
1426 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1427 || skip_past_comma (&str) == (int) FAIL
1428 || data_op2 (&str, 1, _IMM16) == (int) FAIL
1429 || end_of_line (str) == (int) FAIL)
1430 return;
1432 if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
1433 inst.relax_inst = 0x8000;
1434 else
1435 inst.relax_size = 2;
1438 static void
1439 do_macro_rdi32hi (char *str)
1441 skip_whitespace (str);
1443 /* Do not handle end_of_line(). */
1444 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1445 && skip_past_comma (&str) != (int) FAIL)
1446 data_op2 (&str, 1, _VALUE_HI16);
1449 static void
1450 do_macro_rdi32lo (char *str)
1452 skip_whitespace (str);
1454 /* Do not handle end_of_line(). */
1455 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1456 && skip_past_comma (&str) != (int) FAIL)
1457 data_op2 (&str, 1, _VALUE_LO16);
1460 /* Handle ldis_pic. */
1462 static void
1463 do_rdi16_pic (char *str)
1465 skip_whitespace (str);
1467 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1468 && skip_past_comma (&str) != (int) FAIL
1469 && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
1470 end_of_line (str);
1473 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1475 static void
1476 do_addi_s_pic (char *str)
1478 skip_whitespace (str);
1480 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1481 && skip_past_comma (&str) != (int) FAIL
1482 && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
1483 end_of_line (str);
1486 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1488 static void
1489 do_addi_u_pic (char *str)
1491 skip_whitespace (str);
1493 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1494 && skip_past_comma (&str) != (int) FAIL
1495 && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
1496 end_of_line (str);
1499 /* Handle mfceh/mfcel/mtceh/mtchl. */
1501 static void
1502 do_rd (char *str)
1504 skip_whitespace (str);
1506 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
1507 end_of_line (str);
1510 static void
1511 do_rs (char *str)
1513 skip_whitespace (str);
1515 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1516 || end_of_line (str) == (int) FAIL)
1517 return;
1519 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1521 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
1522 inst.relax_size = 2;
1524 else
1525 inst.relax_inst = 0x8000;
1528 static void
1529 do_i15 (char *str)
1531 skip_whitespace (str);
1533 if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
1534 end_of_line (str);
1537 static void
1538 do_xi5x (char *str)
1540 skip_whitespace (str);
1542 if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
1543 return;
1545 if (inst.relax_inst != 0x8000)
1547 inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
1548 inst.relax_size = 2;
1552 static void
1553 do_rdrs (char *str)
1555 skip_whitespace (str);
1557 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1558 || skip_past_comma (&str) == (int) FAIL
1559 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1560 || end_of_line (str) == (int) FAIL)
1561 return;
1563 if (inst.relax_inst != 0x8000)
1565 if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1567 /* mlfh */
1568 if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1570 inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
1571 | (((inst.instruction >> 20) & 0xf) << 8);
1572 inst.relax_size = 2;
1574 /* mhfl */
1575 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
1577 inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
1578 | (((inst.instruction >> 20) & 0xf) << 8);
1579 inst.relax_size = 2;
1581 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1583 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1584 | (((inst.instruction >> 20) & 0xf) << 8);
1585 inst.relax_size = 2;
1587 else
1589 inst.relax_inst = 0x8000;
1592 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1594 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1595 | (((inst.instruction >> 20) & 0xf) << 8);
1596 inst.relax_size = 2;
1598 else
1600 inst.relax_inst = 0x8000;
1605 /* Handle mfcr/mtcr. */
1606 static void
1607 do_rdcrs (char *str)
1609 skip_whitespace (str);
1611 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1612 && skip_past_comma (&str) != (int) FAIL
1613 && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
1614 end_of_line (str);
1617 /* Handle mfsr/mtsr. */
1619 static void
1620 do_rdsrs (char *str)
1622 skip_whitespace (str);
1624 /* mfsr */
1625 if ((inst.instruction & 0xff) == 0x50)
1627 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1628 && skip_past_comma (&str) != (int) FAIL
1629 && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
1630 end_of_line (str);
1632 else
1634 if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1635 && skip_past_comma (&str) != (int) FAIL)
1636 reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
1640 /* Handle neg. */
1642 static void
1643 do_rdxrs (char *str)
1645 skip_whitespace (str);
1647 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1648 || skip_past_comma (&str) == (int) FAIL
1649 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1650 || end_of_line (str) == (int) FAIL)
1651 return;
1653 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
1654 && (((inst.instruction >> 20) & 0x10) == 0))
1656 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
1657 inst.relax_size = 2;
1659 else
1660 inst.relax_inst = 0x8000;
1663 /* Handle cmp.c/cmp<cond>. */
1664 static void
1665 do_rsrs (char *str)
1667 skip_whitespace (str);
1669 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1670 || skip_past_comma (&str) == (int) FAIL
1671 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1672 || end_of_line (str) == (int) FAIL)
1673 return;
1675 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
1676 && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
1678 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
1679 inst.relax_size = 2;
1681 else
1682 inst.relax_inst = 0x8000;
1685 static void
1686 do_ceinst (char *str)
1688 char *strbak;
1690 strbak = str;
1691 skip_whitespace (str);
1693 if (data_op2 (&str, 20, _IMM5) == (int) FAIL
1694 || skip_past_comma (&str) == (int) FAIL
1695 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1696 || skip_past_comma (&str) == (int) FAIL
1697 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1698 || skip_past_comma (&str) == (int) FAIL
1699 || data_op2 (&str, 5, _IMM5) == (int) FAIL
1700 || skip_past_comma (&str) == (int) FAIL
1701 || data_op2 (&str, 0, _IMM5) == (int) FAIL
1702 || end_of_line (str) == (int) FAIL)
1704 return;
1706 else
1708 str = strbak;
1709 if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
1710 return;
1714 static int
1715 reglow_required_here (char **str, int shift)
1717 static char buff[MAX_LITERAL_POOL_SIZE];
1718 int reg;
1719 char *start = *str;
1721 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1723 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
1725 as_warn ("Using temp register(r1)");
1726 inst.bwarn = 1;
1728 if (reg < 16)
1730 if (shift >= 0)
1731 inst.instruction |= reg << shift;
1733 return reg;
1737 /* Restore the start point, we may have got a reg of the wrong class. */
1738 *str = start;
1739 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
1740 inst.error = buff;
1741 return (int) FAIL;
1744 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
1745 static void
1746 do16_rdrs (char *str)
1748 skip_whitespace (str);
1750 if (reglow_required_here (&str, 8) == (int) FAIL
1751 || skip_past_comma (&str) == (int) FAIL
1752 || reglow_required_here (&str, 4) == (int) FAIL
1753 || end_of_line (str) == (int) FAIL)
1755 return;
1757 else
1759 if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */
1761 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
1762 | (((inst.instruction >> 4) & 0xf) << 10);
1764 else if ((inst.instruction & 0x700f) == 0x2006) /* not! */
1766 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1767 | (((inst.instruction >> 4) & 0xf) << 15);
1769 else
1771 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1772 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
1774 inst.relax_size = 4;
1778 static void
1779 do16_rs (char *str)
1781 int rd = 0;
1783 skip_whitespace (str);
1785 if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
1786 || end_of_line (str) == (int) FAIL)
1788 return;
1790 else
1792 inst.relax_inst |= rd << 20;
1793 inst.relax_size = 4;
1797 /* Handle br!/brl!. */
1798 static void
1799 do16_xrs (char *str)
1801 skip_whitespace (str);
1803 if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
1805 return;
1807 else
1809 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
1810 | (((inst.instruction >> 4) & 0xf) << 15);
1811 inst.relax_size = 4;
1815 static int
1816 reghigh_required_here (char **str, int shift)
1818 static char buff[MAX_LITERAL_POOL_SIZE];
1819 int reg;
1820 char *start = *str;
1822 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1824 if (15 < reg && reg < 32)
1826 if (shift >= 0)
1827 inst.instruction |= (reg & 0xf) << shift;
1829 return reg;
1833 *str = start;
1834 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
1835 inst.error = buff;
1836 return (int) FAIL;
1839 /* Handle mhfl!. */
1840 static void
1841 do16_hrdrs (char *str)
1843 skip_whitespace (str);
1845 if (reghigh_required_here (&str, 8) != (int) FAIL
1846 && skip_past_comma (&str) != (int) FAIL
1847 && reglow_required_here (&str, 4) != (int) FAIL
1848 && end_of_line (str) != (int) FAIL)
1850 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
1851 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
1852 inst.relax_size = 4;
1856 /* Handle mlfh!. */
1857 static void
1858 do16_rdhrs (char *str)
1860 skip_whitespace (str);
1862 if (reglow_required_here (&str, 8) != (int) FAIL
1863 && skip_past_comma (&str) != (int) FAIL
1864 && reghigh_required_here (&str, 4) != (int) FAIL
1865 && end_of_line (str) != (int) FAIL)
1867 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1868 | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
1869 inst.relax_size = 4;
1873 /* We need to be able to fix up arbitrary expressions in some statements.
1874 This is so that we can handle symbols that are an arbitrary distance from
1875 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
1876 which returns part of an address in a form which will be valid for
1877 a data instruction. We do this by pushing the expression into a symbol
1878 in the expr_section, and creating a fix for that. */
1879 static fixS *
1880 fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1882 fixS *new_fix;
1884 switch (exp->X_op)
1886 case O_constant:
1887 case O_symbol:
1888 case O_add:
1889 case O_subtract:
1890 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
1891 break;
1892 default:
1893 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
1894 break;
1896 return new_fix;
1899 static void
1900 init_dependency_vector (void)
1902 int i;
1904 for (i = 0; i < vector_size; i++)
1905 memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
1907 return;
1910 static enum insn_type_for_dependency
1911 dependency_type_from_insn (char *insn_name)
1913 char name[INSN_NAME_LEN];
1914 const struct insn_to_dependency *tmp;
1916 strcpy (name, insn_name);
1917 tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
1919 if (tmp)
1920 return tmp->type;
1922 return D_all_insn;
1925 static int
1926 check_dependency (char *pre_insn, char *pre_reg,
1927 char *cur_insn, char *cur_reg, int *warn_or_error)
1929 int bubbles = 0;
1930 unsigned int i;
1931 enum insn_type_for_dependency pre_insn_type;
1932 enum insn_type_for_dependency cur_insn_type;
1934 pre_insn_type = dependency_type_from_insn (pre_insn);
1935 cur_insn_type = dependency_type_from_insn (cur_insn);
1937 for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
1939 if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
1940 && (D_all_insn == data_dependency_table[i].cur_insn_type
1941 || cur_insn_type == data_dependency_table[i].cur_insn_type)
1942 && (strcmp (data_dependency_table[i].pre_reg, "") == 0
1943 || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
1944 && (strcmp (data_dependency_table[i].cur_reg, "") == 0
1945 || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
1947 bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
1948 *warn_or_error = data_dependency_table[i].warn_or_error;
1949 break;
1953 return bubbles;
1956 static void
1957 build_one_frag (struct score_it one_inst)
1959 char *p;
1960 int relaxable_p = g_opt;
1961 int relax_size = 0;
1963 /* Start a new frag if frag_now is not empty. */
1964 if (frag_now_fix () != 0)
1966 if (!frag_now->tc_frag_data.is_insn)
1967 frag_wane (frag_now);
1969 frag_new (0);
1971 frag_grow (20);
1973 p = frag_more (one_inst.size);
1974 md_number_to_chars (p, one_inst.instruction, one_inst.size);
1976 #ifdef OBJ_ELF
1977 dwarf2_emit_insn (one_inst.size);
1978 #endif
1980 relaxable_p &= (one_inst.relax_size != 0);
1981 relax_size = relaxable_p ? one_inst.relax_size : 0;
1983 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
1984 RELAX_ENCODE (one_inst.size, one_inst.relax_size,
1985 one_inst.type, 0, 0, relaxable_p),
1986 NULL, 0, NULL);
1988 if (relaxable_p)
1989 md_number_to_chars (p, one_inst.relax_inst, relax_size);
1992 static void
1993 handle_dependency (struct score_it *theinst)
1995 int i;
1996 int warn_or_error = 0; /* warn - 0; error - 1 */
1997 int bubbles = 0;
1998 int remainder_bubbles = 0;
1999 char cur_insn[INSN_NAME_LEN];
2000 char pre_insn[INSN_NAME_LEN];
2001 struct score_it nop_inst;
2002 struct score_it pflush_inst;
2004 nop_inst.instruction = 0x0000;
2005 nop_inst.size = 2;
2006 nop_inst.relax_inst = 0x80008000;
2007 nop_inst.relax_size = 4;
2008 nop_inst.type = NO16_OPD;
2010 pflush_inst.instruction = 0x8000800a;
2011 pflush_inst.size = 4;
2012 pflush_inst.relax_inst = 0x8000;
2013 pflush_inst.relax_size = 0;
2014 pflush_inst.type = NO_OPD;
2016 /* pflush will clear all data dependency. */
2017 if (strcmp (theinst->name, "pflush") == 0)
2019 init_dependency_vector ();
2020 return;
2023 /* Push current instruction to dependency_vector[0]. */
2024 for (i = vector_size - 1; i > 0; i--)
2025 memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
2027 memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
2029 /* There is no dependency between nop and any instruction. */
2030 if (strcmp (dependency_vector[0].name, "nop") == 0
2031 || strcmp (dependency_vector[0].name, "nop!") == 0)
2032 return;
2034 /* "pce" is defined in insn_to_dependency_table. */
2035 #define PCE_NAME "pce"
2037 if (dependency_vector[0].type == Insn_Type_PCE)
2038 strcpy (cur_insn, PCE_NAME);
2039 else
2040 strcpy (cur_insn, dependency_vector[0].name);
2042 for (i = 1; i < vector_size; i++)
2044 /* The element of dependency_vector is NULL. */
2045 if (dependency_vector[i].name[0] == '\0')
2046 continue;
2048 if (dependency_vector[i].type == Insn_Type_PCE)
2049 strcpy (pre_insn, PCE_NAME);
2050 else
2051 strcpy (pre_insn, dependency_vector[i].name);
2053 bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
2054 cur_insn, dependency_vector[0].reg, &warn_or_error);
2055 remainder_bubbles = bubbles - i + 1;
2057 if (remainder_bubbles > 0)
2059 int j;
2061 if (fix_data_dependency == 1)
2063 if (remainder_bubbles <= 2)
2065 if (warn_fix_data_dependency)
2066 as_warn ("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)",
2067 dependency_vector[i].name, dependency_vector[i].reg,
2068 dependency_vector[0].name, dependency_vector[0].reg,
2069 remainder_bubbles, bubbles);
2071 for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
2072 memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
2073 sizeof (dependency_vector[j]));
2075 for (j = 1; j <= remainder_bubbles; j++)
2077 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2078 /* Insert nop!. */
2079 build_one_frag (nop_inst);
2082 else
2084 if (warn_fix_data_dependency)
2085 as_warn ("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)",
2086 dependency_vector[i].name, dependency_vector[i].reg,
2087 dependency_vector[0].name, dependency_vector[0].reg,
2088 bubbles);
2090 for (j = 1; j < vector_size; j++)
2091 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2093 /* Insert pflush. */
2094 build_one_frag (pflush_inst);
2097 else
2099 if (warn_or_error)
2101 as_bad ("data dependency: %s %s -- %s %s (%d/%d bubble)",
2102 dependency_vector[i].name, dependency_vector[i].reg,
2103 dependency_vector[0].name, dependency_vector[0].reg,
2104 remainder_bubbles, bubbles);
2106 else
2108 as_warn ("data dependency: %s %s -- %s %s (%d/%d bubble)",
2109 dependency_vector[i].name, dependency_vector[i].reg,
2110 dependency_vector[0].name, dependency_vector[0].reg,
2111 remainder_bubbles, bubbles);
2118 static enum insn_class
2119 get_insn_class_from_type (enum score_insn_type type)
2121 enum insn_class retval = (int) FAIL;
2123 switch (type)
2125 case Rd_I4:
2126 case Rd_I5:
2127 case Rd_rvalueBP_I5:
2128 case Rd_lvalueBP_I5:
2129 case Rd_I8:
2130 case PC_DISP8div2:
2131 case PC_DISP11div2:
2132 case Rd_Rs:
2133 case Rd_HighRs:
2134 case Rd_lvalueRs:
2135 case Rd_rvalueRs:
2136 case x_Rs:
2137 case Rd_LowRs:
2138 case NO16_OPD:
2139 retval = INSN_CLASS_16;
2140 break;
2141 case Rd_Rs_I5:
2142 case x_Rs_I5:
2143 case x_I5_x:
2144 case Rd_Rs_I14:
2145 case I15:
2146 case Rd_I16:
2147 case Rd_SI16:
2148 case Rd_rvalueRs_SI10:
2149 case Rd_lvalueRs_SI10:
2150 case Rd_rvalueRs_preSI12:
2151 case Rd_rvalueRs_postSI12:
2152 case Rd_lvalueRs_preSI12:
2153 case Rd_lvalueRs_postSI12:
2154 case Rd_Rs_SI14:
2155 case Rd_rvalueRs_SI15:
2156 case Rd_lvalueRs_SI15:
2157 case PC_DISP19div2:
2158 case PC_DISP24div2:
2159 case Rd_Rs_Rs:
2160 case x_Rs_x:
2161 case x_Rs_Rs:
2162 case Rd_Rs_x:
2163 case Rd_x_Rs:
2164 case Rd_x_x:
2165 case OP5_rvalueRs_SI15:
2166 case I5_Rs_Rs_I5_OP5:
2167 case x_rvalueRs_post4:
2168 case Rd_rvalueRs_post4:
2169 case Rd_x_I5:
2170 case Rd_lvalueRs_post4:
2171 case x_lvalueRs_post4:
2172 case Rd_Rs_Rs_imm:
2173 case NO_OPD:
2174 case Rd_lvalue32Rs:
2175 case Rd_rvalue32Rs:
2176 case Insn_GP:
2177 case Insn_PIC:
2178 case Insn_internal:
2179 retval = INSN_CLASS_32;
2180 break;
2181 case Insn_Type_PCE:
2182 retval = INSN_CLASS_PCE;
2183 break;
2184 case Insn_Type_SYN:
2185 retval = INSN_CLASS_SYN;
2186 break;
2187 default:
2188 abort ();
2189 break;
2191 return retval;
2194 static unsigned long
2195 adjust_paritybit (unsigned long m_code, enum insn_class class)
2197 unsigned long result = 0;
2198 unsigned long m_code_high = 0;
2199 unsigned long m_code_low = 0;
2200 unsigned long pb_high = 0;
2201 unsigned long pb_low = 0;
2203 if (class == INSN_CLASS_32)
2205 pb_high = 0x80000000;
2206 pb_low = 0x00008000;
2208 else if (class == INSN_CLASS_16)
2210 pb_high = 0;
2211 pb_low = 0;
2213 else if (class == INSN_CLASS_PCE)
2215 pb_high = 0;
2216 pb_low = 0x00008000;
2218 else if (class == INSN_CLASS_SYN)
2220 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2221 be changed if macro instruction has been expanded. */
2222 pb_high = 0x80000000;
2223 pb_low = 0x00008000;
2225 else
2227 abort ();
2230 m_code_high = m_code & 0x3fff8000;
2231 m_code_low = m_code & 0x00007fff;
2232 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2233 return result;
2237 static void
2238 gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
2240 char *p;
2241 bfd_boolean pce_p = FALSE;
2242 int relaxable_p = g_opt;
2243 int relax_size = 0;
2244 struct score_it *inst1 = part_1;
2245 struct score_it *inst2 = part_2;
2246 struct score_it backup_inst1;
2248 pce_p = (inst2) ? TRUE : FALSE;
2249 memcpy (&backup_inst1, inst1, sizeof (struct score_it));
2251 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2252 if (pce_p)
2254 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2255 | (inst2->instruction & 0x7FFF);
2256 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2257 backup_inst1.relax_inst = 0x8000;
2258 backup_inst1.size = INSN_SIZE;
2259 backup_inst1.relax_size = 0;
2260 backup_inst1.type = Insn_Type_PCE;
2262 else
2264 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
2265 GET_INSN_CLASS (backup_inst1.type));
2268 if (backup_inst1.relax_size != 0)
2270 enum insn_class tmp;
2272 tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2273 backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
2276 /* Check data dependency. */
2277 handle_dependency (&backup_inst1);
2279 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2280 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2281 if (frag_now_fix () != 0)
2283 if (!frag_now->tc_frag_data.is_insn)
2284 frag_wane (frag_now);
2286 frag_new (0);
2289 /* Here, we must call frag_grow in order to keep the instruction frag type is
2290 rs_machine_dependent.
2291 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2292 acturally will call frag_wane.
2293 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2294 for frag_var. */
2295 frag_grow (20);
2297 p = frag_more (backup_inst1.size);
2298 md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2300 #ifdef OBJ_ELF
2301 dwarf2_emit_insn (backup_inst1.size);
2302 #endif
2304 /* Generate fixup structure. */
2305 if (pce_p)
2307 if (inst1->reloc.type != BFD_RELOC_NONE)
2308 fix_new_score (frag_now, p - frag_now->fr_literal,
2309 inst1->size, &inst1->reloc.exp,
2310 inst1->reloc.pc_rel, inst1->reloc.type);
2312 if (inst2->reloc.type != BFD_RELOC_NONE)
2313 fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2314 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2316 else
2318 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2319 fix_new_score (frag_now, p - frag_now->fr_literal,
2320 backup_inst1.size, &backup_inst1.reloc.exp,
2321 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2324 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2325 relaxable_p &= (backup_inst1.relax_size != 0);
2326 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2328 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2329 RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2330 backup_inst1.type, 0, 0, relaxable_p),
2331 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2333 if (relaxable_p)
2334 md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2336 memcpy (inst1, &backup_inst1, sizeof (struct score_it));
2339 static void
2340 parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2342 char c;
2343 char *p;
2344 char *operator = insnstr;
2345 const struct asm_opcode *opcode;
2347 /* Parse operator and operands. */
2348 skip_whitespace (operator);
2350 for (p = operator; *p != '\0'; p++)
2351 if ((*p == ' ') || (*p == '!'))
2352 break;
2354 if (*p == '!')
2355 p++;
2357 c = *p;
2358 *p = '\0';
2360 opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
2361 *p = c;
2363 memset (&inst, '\0', sizeof (inst));
2364 sprintf (inst.str, "%s", insnstr);
2365 if (opcode)
2367 inst.instruction = opcode->value;
2368 inst.relax_inst = opcode->relax_value;
2369 inst.type = opcode->type;
2370 inst.size = GET_INSN_SIZE (inst.type);
2371 inst.relax_size = 0;
2372 inst.bwarn = 0;
2373 sprintf (inst.name, "%s", opcode->template);
2374 strcpy (inst.reg, "");
2375 inst.error = NULL;
2376 inst.reloc.type = BFD_RELOC_NONE;
2378 (*opcode->parms) (p);
2380 /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */
2381 if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
2382 gen_insn_frag (&inst, NULL);
2384 else
2385 inst.error = _("unrecognized opcode");
2388 static int
2389 append_insn (char *str, bfd_boolean gen_frag_p)
2391 int retval = SUCCESS;
2393 parse_16_32_inst (str, gen_frag_p);
2395 if (inst.error)
2397 retval = (int) FAIL;
2398 as_bad ("%s -- `%s'", inst.error, inst.str);
2399 inst.error = NULL;
2402 return retval;
2405 /* Handle mv! reg_high, reg_low;
2406 mv! reg_low, reg_high;
2407 mv! reg_low, reg_low; */
2408 static void
2409 do16_mv_rdrs (char *str)
2411 int reg_rd;
2412 int reg_rs;
2413 char *backupstr = NULL;
2415 backupstr = str;
2416 skip_whitespace (str);
2418 if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
2419 || skip_past_comma (&str) == (int) FAIL
2420 || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
2421 || end_of_line (str) == (int) FAIL)
2423 return;
2425 else
2427 /* Case 1 : mv! or mlfh!. */
2428 if (reg_rd < 16)
2430 if (reg_rs < 16)
2432 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2433 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2434 inst.relax_size = 4;
2436 else
2438 char append_str[MAX_LITERAL_POOL_SIZE];
2440 sprintf (append_str, "mlfh! %s", backupstr);
2441 if (append_insn (append_str, TRUE) == (int) FAIL)
2442 return;
2443 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2444 inst.bwarn = -1;
2447 /* Case 2 : mhfl!. */
2448 else
2450 if (reg_rs > 16)
2452 SET_INSN_ERROR (BAD_ARGS);
2453 return;
2455 else
2457 char append_str[MAX_LITERAL_POOL_SIZE];
2459 sprintf (append_str, "mhfl! %s", backupstr);
2460 if (append_insn (append_str, TRUE) == (int) FAIL)
2461 return;
2463 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2464 inst.bwarn = -1;
2470 static void
2471 do16_rdi4 (char *str)
2473 skip_whitespace (str);
2475 if (reglow_required_here (&str, 8) == (int) FAIL
2476 || skip_past_comma (&str) == (int) FAIL
2477 || data_op2 (&str, 3, _IMM4) == (int) FAIL
2478 || end_of_line (str) == (int) FAIL)
2480 return;
2482 else
2484 if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2486 if (((inst.instruction >> 3) & 0xf) != 0xf)
2488 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2489 | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
2490 inst.relax_size = 4;
2492 else
2494 inst.relax_inst = 0x8000;
2497 else
2499 if (((inst.instruction >> 3) & 0xf) != 0xf)
2501 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2502 | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2503 inst.relax_size = 4;
2505 else
2507 inst.relax_inst = 0x8000;
2513 static void
2514 do16_rdi5 (char *str)
2516 skip_whitespace (str);
2518 if (reglow_required_here (&str, 8) == (int) FAIL
2519 || skip_past_comma (&str) == (int) FAIL
2520 || data_op2 (&str, 3, _IMM5) == (int) FAIL
2521 || end_of_line (str) == (int) FAIL)
2522 return;
2523 else
2525 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2526 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
2527 inst.relax_size = 4;
2531 /* Handle sdbbp. */
2532 static void
2533 do16_xi5 (char *str)
2535 skip_whitespace (str);
2537 if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
2538 return;
2539 else
2541 inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
2542 inst.relax_size = 4;
2546 /* Check that an immediate is word alignment or half word alignment.
2547 If so, convert it to the right format. */
2548 static int
2549 validate_immediate_align (int val, unsigned int data_type)
2551 if (data_type == _IMM5_RSHIFT_1)
2553 if (val % 2)
2555 inst.error = _("address offset must be half word alignment");
2556 return (int) FAIL;
2559 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2561 if (val % 4)
2563 inst.error = _("address offset must be word alignment");
2564 return (int) FAIL;
2568 return SUCCESS;
2571 static int
2572 exp_ldst_offset (char **str, int shift, unsigned int data_type)
2574 char *dataptr;
2576 dataptr = * str;
2578 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2579 && (data_type != _SIMM16_LA)
2580 && (data_type != _VALUE_HI16)
2581 && (data_type != _VALUE_LO16)
2582 && (data_type != _IMM16)
2583 && (data_type != _IMM15)
2584 && (data_type != _IMM14)
2585 && (data_type != _IMM4)
2586 && (data_type != _IMM5)
2587 && (data_type != _IMM8)
2588 && (data_type != _IMM5_RSHIFT_1)
2589 && (data_type != _IMM5_RSHIFT_2)
2590 && (data_type != _SIMM14_NEG)
2591 && (data_type != _IMM10_RSHIFT_2))
2593 data_type += 24;
2596 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
2597 return (int) FAIL;
2599 if (inst.reloc.exp.X_op == O_constant)
2601 /* Need to check the immediate align. */
2602 int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
2604 if (value == (int) FAIL)
2605 return (int) FAIL;
2607 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2608 if (value == (int) FAIL)
2610 char err_msg[255];
2612 if (data_type < 30)
2613 sprintf (err_msg,
2614 "invalid constant: %d bit expression not in range %d..%d",
2615 score_df_range[data_type].bits,
2616 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2617 else
2618 sprintf (err_msg,
2619 "invalid constant: %d bit expression not in range %d..%d",
2620 score_df_range[data_type - 24].bits,
2621 score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
2622 inst.error = _(err_msg);
2623 return (int) FAIL;
2626 if (data_type == _IMM5_RSHIFT_1)
2628 value >>= 1;
2630 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2632 value >>= 2;
2635 if (score_df_range[data_type].range[0] != 0)
2637 value &= (1 << score_df_range[data_type].bits) - 1;
2640 inst.instruction |= value << shift;
2642 else
2644 inst.reloc.pc_rel = 0;
2647 return SUCCESS;
2650 static void
2651 do_ldst_insn (char *str)
2653 int pre_inc = 0;
2654 int conflict_reg;
2655 int value;
2656 char * temp;
2657 char *strbak;
2658 char *dataptr;
2659 int reg;
2660 int ldst_idx = 0;
2662 strbak = str;
2663 skip_whitespace (str);
2665 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
2666 || (skip_past_comma (&str) == (int) FAIL))
2667 return;
2669 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
2670 if (*str == '[')
2672 str++;
2673 skip_whitespace (str);
2675 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
2676 return;
2678 /* Conflicts can occur on stores as well as loads. */
2679 conflict_reg = (conflict_reg == reg);
2680 skip_whitespace (str);
2681 temp = str + 1; /* The latter will process decimal/hex expression. */
2683 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
2684 if (*str == ']')
2686 str++;
2687 if (*str == '+')
2689 str++;
2690 /* ld/sw rD, [rA]+, simm12. */
2691 if (skip_past_comma (&str) == SUCCESS)
2693 if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
2694 || (end_of_line (str) == (int) FAIL))
2695 return;
2697 if (conflict_reg)
2699 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2701 if ((ldst_func == INSN_LH)
2702 || (ldst_func == INSN_LHU)
2703 || (ldst_func == INSN_LW)
2704 || (ldst_func == INSN_LB)
2705 || (ldst_func == INSN_LBU))
2707 inst.error = _("register same as write-back base");
2708 return;
2712 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2713 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2714 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2716 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
2717 if ((inst.instruction & 0x3e000007) == 0x0e000000)
2719 /* rs = r0-r7, offset = 4 */
2720 if ((((inst.instruction >> 15) & 0x18) == 0)
2721 && (((inst.instruction >> 3) & 0xfff) == 4))
2723 /* Relax to pophi. */
2724 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2726 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2727 << 8) | 1 << 7 |
2728 (((inst.instruction >> 15) & 0x7) << 4);
2730 /* Relax to pop. */
2731 else
2733 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2734 << 8) | 0 << 7 |
2735 (((inst.instruction >> 15) & 0x7) << 4);
2737 inst.relax_size = 2;
2740 return;
2742 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
2743 else
2745 SET_INSN_ERROR (NULL);
2746 if (end_of_line (str) == (int) FAIL)
2748 return;
2751 pre_inc = 1;
2752 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12);
2753 value &= (1 << score_df_range[_SIMM12].bits) - 1;
2754 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2755 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2756 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2757 inst.instruction |= value << 3;
2758 inst.relax_inst = 0x8000;
2759 return;
2762 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
2763 else
2765 if (end_of_line (str) == (int) FAIL)
2766 return;
2768 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2769 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2770 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
2772 /* lbu rd, [rs] -> lbu! rd, [rs] */
2773 if (ldst_idx == INSN_LBU)
2775 inst.relax_inst = INSN16_LBU;
2777 else if (ldst_idx == INSN_LH)
2779 inst.relax_inst = INSN16_LH;
2781 else if (ldst_idx == INSN_LW)
2783 inst.relax_inst = INSN16_LW;
2785 else if (ldst_idx == INSN_SB)
2787 inst.relax_inst = INSN16_SB;
2789 else if (ldst_idx == INSN_SH)
2791 inst.relax_inst = INSN16_SH;
2793 else if (ldst_idx == INSN_SW)
2795 inst.relax_inst = INSN16_SW;
2797 else
2799 inst.relax_inst = 0x8000;
2802 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
2803 if ((ldst_idx == INSN_LBU)
2804 || (ldst_idx == INSN_LH)
2805 || (ldst_idx == INSN_LW)
2806 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
2808 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2810 inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
2811 (((inst.instruction >> 15) & 0xf) << 4);
2812 inst.relax_size = 2;
2816 return;
2819 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
2820 else
2822 if (skip_past_comma (&str) == (int) FAIL)
2824 inst.error = _("pre-indexed expression expected");
2825 return;
2828 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
2829 return;
2831 skip_whitespace (str);
2832 if (*str++ != ']')
2834 inst.error = _("missing ]");
2835 return;
2838 skip_whitespace (str);
2839 /* ld/sw rD, [rA, simm12]+. */
2840 if (*str == '+')
2842 str++;
2843 pre_inc = 1;
2844 if (conflict_reg)
2846 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2848 if ((ldst_func == INSN_LH)
2849 || (ldst_func == INSN_LHU)
2850 || (ldst_func == INSN_LW)
2851 || (ldst_func == INSN_LB)
2852 || (ldst_func == INSN_LBU))
2854 inst.error = _("register same as write-back base");
2855 return;
2860 if (end_of_line (str) == (int) FAIL)
2861 return;
2863 if (inst.reloc.exp.X_op == O_constant)
2865 int value;
2866 unsigned int data_type;
2868 if (pre_inc == 1)
2869 data_type = _SIMM12;
2870 else
2871 data_type = _SIMM15;
2872 dataptr = temp;
2874 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2875 && (data_type != _SIMM16_LA)
2876 && (data_type != _VALUE_HI16)
2877 && (data_type != _VALUE_LO16)
2878 && (data_type != _IMM16)
2879 && (data_type != _IMM15)
2880 && (data_type != _IMM14)
2881 && (data_type != _IMM4)
2882 && (data_type != _IMM5)
2883 && (data_type != _IMM8)
2884 && (data_type != _IMM5_RSHIFT_1)
2885 && (data_type != _IMM5_RSHIFT_2)
2886 && (data_type != _SIMM14_NEG)
2887 && (data_type != _IMM10_RSHIFT_2))
2889 data_type += 24;
2892 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2893 if (value == (int) FAIL)
2895 char err_msg[255];
2897 if (data_type < 30)
2898 sprintf (err_msg,
2899 "invalid constant: %d bit expression not in range %d..%d",
2900 score_df_range[data_type].bits,
2901 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2902 else
2903 sprintf (err_msg,
2904 "invalid constant: %d bit expression not in range %d..%d",
2905 score_df_range[data_type - 24].bits,
2906 score_df_range[data_type - 24].range[0],
2907 score_df_range[data_type - 24].range[1]);
2908 inst.error = _(err_msg);
2909 return;
2912 value &= (1 << score_df_range[data_type].bits) - 1;
2913 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2914 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2915 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2916 if (pre_inc == 1)
2917 inst.instruction |= value << 3;
2918 else
2919 inst.instruction |= value;
2921 /* lw rD, [rA, simm15] */
2922 if ((inst.instruction & 0x3e000000) == 0x20000000)
2924 /* Both rD and rA are in [r0 - r15]. */
2925 if ((((inst.instruction >> 15) & 0x10) == 0)
2926 && (((inst.instruction >> 20) & 0x10) == 0))
2928 /* simm15 = 0, lw -> lw!. */
2929 if ((inst.instruction & 0x7fff) == 0)
2931 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2932 | (((inst.instruction >> 20) & 0xf) << 8);
2933 inst.relax_size = 2;
2935 /* rA = r2, lw -> lwp!. */
2936 else if ((((inst.instruction >> 15) & 0xf) == 2)
2937 && ((inst.instruction & 0x3) == 0)
2938 && ((inst.instruction & 0x7fff) < 128))
2940 inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
2941 | (((inst.instruction & 0x7fff) >> 2) << 3);
2942 inst.relax_size = 2;
2944 else
2946 inst.relax_inst = 0x8000;
2949 else
2951 inst.relax_inst = 0x8000;
2954 /* sw rD, [rA, simm15] */
2955 else if ((inst.instruction & 0x3e000000) == 0x28000000)
2957 /* Both rD and rA are in [r0 - r15]. */
2958 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2960 /* simm15 = 0, sw -> sw!. */
2961 if ((inst.instruction & 0x7fff) == 0)
2963 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2964 | (((inst.instruction >> 20) & 0xf) << 8);
2965 inst.relax_size = 2;
2967 /* rA = r2, sw -> swp!. */
2968 else if ((((inst.instruction >> 15) & 0xf) == 2)
2969 && ((inst.instruction & 0x3) == 0)
2970 && ((inst.instruction & 0x7fff) < 128))
2972 inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
2973 | (((inst.instruction & 0x7fff) >> 2) << 3);
2974 inst.relax_size = 2;
2976 else
2978 inst.relax_inst = 0x8000;
2981 else
2983 inst.relax_inst = 0x8000;
2986 /* sw rD, [rA, simm15]+ sw pre. */
2987 else if ((inst.instruction & 0x3e000007) == 0x06000004)
2989 /* rA is in [r0 - r7], and simm15 = -4. */
2990 if ((((inst.instruction >> 15) & 0x18) == 0)
2991 && (((inst.instruction >> 3) & 0xfff) == 0xffc))
2993 /* sw -> pushhi!. */
2994 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2996 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
2997 | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
2998 inst.relax_size = 2;
3000 /* sw -> push!. */
3001 else
3003 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3004 | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3005 inst.relax_size = 2;
3008 else
3010 inst.relax_inst = 0x8000;
3013 /* lh rD, [rA, simm15] */
3014 else if ((inst.instruction & 0x3e000000) == 0x22000000)
3016 /* Both rD and rA are in [r0 - r15]. */
3017 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3019 /* simm15 = 0, lh -> lh!. */
3020 if ((inst.instruction & 0x7fff) == 0)
3022 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3023 | (((inst.instruction >> 20) & 0xf) << 8);
3024 inst.relax_size = 2;
3026 /* rA = r2, lh -> lhp!. */
3027 else if ((((inst.instruction >> 15) & 0xf) == 2)
3028 && ((inst.instruction & 0x1) == 0)
3029 && ((inst.instruction & 0x7fff) < 64))
3031 inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
3032 | (((inst.instruction & 0x7fff) >> 1) << 3);
3033 inst.relax_size = 2;
3035 else
3037 inst.relax_inst = 0x8000;
3040 else
3042 inst.relax_inst = 0x8000;
3045 /* sh rD, [rA, simm15] */
3046 else if ((inst.instruction & 0x3e000000) == 0x2a000000)
3048 /* Both rD and rA are in [r0 - r15]. */
3049 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3051 /* simm15 = 0, sh -> sh!. */
3052 if ((inst.instruction & 0x7fff) == 0)
3054 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3055 | (((inst.instruction >> 20) & 0xf) << 8);
3056 inst.relax_size = 2;
3058 /* rA = r2, sh -> shp!. */
3059 else if ((((inst.instruction >> 15) & 0xf) == 2)
3060 && ((inst.instruction & 0x1) == 0)
3061 && ((inst.instruction & 0x7fff) < 64))
3063 inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
3064 | (((inst.instruction & 0x7fff) >> 1) << 3);
3065 inst.relax_size = 2;
3067 else
3069 inst.relax_inst = 0x8000;
3072 else
3074 inst.relax_inst = 0x8000;
3077 /* lbu rD, [rA, simm15] */
3078 else if ((inst.instruction & 0x3e000000) == 0x2c000000)
3080 /* Both rD and rA are in [r0 - r15]. */
3081 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3083 /* simm15 = 0, lbu -> lbu!. */
3084 if ((inst.instruction & 0x7fff) == 0)
3086 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3087 | (((inst.instruction >> 20) & 0xf) << 8);
3088 inst.relax_size = 2;
3090 /* rA = r2, lbu -> lbup!. */
3091 else if ((((inst.instruction >> 15) & 0xf) == 2)
3092 && ((inst.instruction & 0x7fff) < 32))
3094 inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
3095 | ((inst.instruction & 0x7fff) << 3);
3096 inst.relax_size = 2;
3098 else
3100 inst.relax_inst = 0x8000;
3103 else
3105 inst.relax_inst = 0x8000;
3108 /* sb rD, [rA, simm15] */
3109 else if ((inst.instruction & 0x3e000000) == 0x2e000000)
3111 /* Both rD and rA are in [r0 - r15]. */
3112 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3114 /* simm15 = 0, sb -> sb!. */
3115 if ((inst.instruction & 0x7fff) == 0)
3117 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3118 | (((inst.instruction >> 20) & 0xf) << 8);
3119 inst.relax_size = 2;
3121 /* rA = r2, sb -> sb!. */
3122 else if ((((inst.instruction >> 15) & 0xf) == 2)
3123 && ((inst.instruction & 0x7fff) < 32))
3125 inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
3126 | ((inst.instruction & 0x7fff) << 3);
3127 inst.relax_size = 2;
3129 else
3131 inst.relax_inst = 0x8000;
3134 else
3136 inst.relax_inst = 0x8000;
3139 else
3141 inst.relax_inst = 0x8000;
3144 return;
3146 else
3148 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3149 inst.reloc.pc_rel = 0;
3153 else
3155 inst.error = BAD_ARGS;
3159 /* Handle cache. */
3161 static void
3162 do_cache (char *str)
3164 skip_whitespace (str);
3166 if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3168 return;
3170 else
3172 int cache_op;
3174 cache_op = (inst.instruction >> 20) & 0x1F;
3175 sprintf (inst.name, "cache %d", cache_op);
3178 if (*str == '[')
3180 str++;
3181 skip_whitespace (str);
3183 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3184 return;
3186 skip_whitespace (str);
3188 /* cache op, [rA] */
3189 if (skip_past_comma (&str) == (int) FAIL)
3191 SET_INSN_ERROR (NULL);
3192 if (*str != ']')
3194 inst.error = _("missing ]");
3195 return;
3197 str++;
3199 /* cache op, [rA, simm15] */
3200 else
3202 if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
3204 return;
3207 skip_whitespace (str);
3208 if (*str++ != ']')
3210 inst.error = _("missing ]");
3211 return;
3215 if (end_of_line (str) == (int) FAIL)
3216 return;
3218 else
3220 inst.error = BAD_ARGS;
3224 static void
3225 do_crdcrscrsimm5 (char *str)
3227 char *strbak;
3229 strbak = str;
3230 skip_whitespace (str);
3232 if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
3233 || skip_past_comma (&str) == (int) FAIL
3234 || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
3235 || skip_past_comma (&str) == (int) FAIL
3236 || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
3237 || skip_past_comma (&str) == (int) FAIL)
3239 str = strbak;
3240 /* cop1 cop_code20. */
3241 if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
3242 return;
3244 else
3246 if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
3247 return;
3250 end_of_line (str);
3253 /* Handle ldc/stc. */
3254 static void
3255 do_ldst_cop (char *str)
3257 skip_whitespace (str);
3259 if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
3260 || (skip_past_comma (&str) == (int) FAIL))
3261 return;
3263 if (*str == '[')
3265 str++;
3266 skip_whitespace (str);
3268 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3269 return;
3271 skip_whitespace (str);
3273 if (*str++ != ']')
3275 if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
3276 return;
3278 skip_whitespace (str);
3279 if (*str++ != ']')
3281 inst.error = _("missing ]");
3282 return;
3286 end_of_line (str);
3288 else
3289 inst.error = BAD_ARGS;
3292 static void
3293 do16_ldst_insn (char *str)
3295 skip_whitespace (str);
3297 if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3298 return;
3300 if (*str == '[')
3302 int reg;
3304 str++;
3305 skip_whitespace (str);
3307 if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
3308 return;
3310 skip_whitespace (str);
3311 if (*str++ == ']')
3313 if (end_of_line (str) == (int) FAIL)
3314 return;
3315 else
3317 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3318 | (((inst.instruction >> 4) & 0xf) << 15);
3319 inst.relax_size = 4;
3322 else
3324 inst.error = _("missing ]");
3327 else
3329 inst.error = BAD_ARGS;
3333 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3334 static void
3335 do16_ldst_imm_insn (char *str)
3337 char data_exp[MAX_LITERAL_POOL_SIZE];
3338 int reg_rd;
3339 char *dataptr = NULL, *pp = NULL;
3340 int cnt = 0;
3341 int assign_data = (int) FAIL;
3342 unsigned int ldst_func;
3344 skip_whitespace (str);
3346 if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
3347 || (skip_past_comma (&str) == (int) FAIL))
3348 return;
3350 skip_whitespace (str);
3351 dataptr = str;
3353 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
3355 data_exp[cnt] = *dataptr;
3356 dataptr++;
3357 cnt++;
3360 data_exp[cnt] = '\0';
3361 pp = &data_exp[0];
3363 str = dataptr;
3365 ldst_func = inst.instruction & LDST16_RI_MASK;
3366 if (ldst_func == N16_LIU)
3367 assign_data = exp_ldst_offset (&pp, 0, _IMM8);
3368 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3369 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3370 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3371 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3372 else
3373 assign_data = exp_ldst_offset (&pp, 3, _IMM5);
3375 if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
3376 return;
3377 else
3379 if ((inst.instruction & 0x7000) == N16_LIU)
3381 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
3382 | ((inst.instruction & 0xff) << 1);
3384 else if (((inst.instruction & 0x7007) == N16_LHP)
3385 || ((inst.instruction & 0x7007) == N16_SHP))
3387 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3388 | (((inst.instruction >> 3) & 0x1f) << 1);
3390 else if (((inst.instruction & 0x7007) == N16_LWP)
3391 || ((inst.instruction & 0x7007) == N16_SWP))
3393 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3394 | (((inst.instruction >> 3) & 0x1f) << 2);
3396 else if (((inst.instruction & 0x7007) == N16_LBUP)
3397 || ((inst.instruction & 0x7007) == N16_SBP))
3399 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3400 | (((inst.instruction >> 3) & 0x1f));
3403 inst.relax_size = 4;
3407 static void
3408 do16_push_pop (char *str)
3410 int reg_rd;
3411 int H_bit_mask = 0;
3413 skip_whitespace (str);
3414 if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
3415 || (skip_past_comma (&str) == (int) FAIL))
3416 return;
3418 if (reg_rd >= 16)
3419 H_bit_mask = 1;
3421 /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3422 inst.instruction &= ~(1 << 12);
3424 inst.instruction |= H_bit_mask << 7;
3426 if (*str == '[')
3428 int reg;
3430 str++;
3431 skip_whitespace (str);
3432 if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
3433 return;
3434 else if (reg > 7)
3436 if (!inst.error)
3437 inst.error = _("base register nums are over 3 bit");
3439 return;
3442 skip_whitespace (str);
3443 if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
3445 if (!inst.error)
3446 inst.error = _("missing ]");
3448 return;
3451 /* pop! */
3452 if ((inst.instruction & 0xf) == 0xa)
3454 if (H_bit_mask)
3456 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3457 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3459 else
3461 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3462 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3465 /* push! */
3466 else
3468 if (H_bit_mask)
3470 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3471 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3473 else
3475 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3476 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3479 inst.relax_size = 4;
3481 else
3483 inst.error = BAD_ARGS;
3487 /* Handle lcb/lcw/lce/scb/scw/sce. */
3488 static void
3489 do_ldst_unalign (char *str)
3491 int conflict_reg;
3493 if (university_version == 1)
3495 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3496 return;
3499 skip_whitespace (str);
3501 /* lcb/scb [rA]+. */
3502 if (*str == '[')
3504 str++;
3505 skip_whitespace (str);
3507 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3508 return;
3510 if (*str++ == ']')
3512 if (*str++ != '+')
3514 inst.error = _("missing +");
3515 return;
3518 else
3520 inst.error = _("missing ]");
3521 return;
3524 if (end_of_line (str) == (int) FAIL)
3525 return;
3527 /* lcw/lce/scb/sce rD, [rA]+. */
3528 else
3530 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
3531 || (skip_past_comma (&str) == (int) FAIL))
3533 return;
3536 skip_whitespace (str);
3537 if (*str++ == '[')
3539 int reg;
3541 skip_whitespace (str);
3542 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3544 return;
3547 /* Conflicts can occur on stores as well as loads. */
3548 conflict_reg = (conflict_reg == reg);
3549 skip_whitespace (str);
3550 if (*str++ == ']')
3552 unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
3554 if (*str++ == '+')
3556 if (conflict_reg)
3558 as_warn (_("%s register same as write-back base"),
3559 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3560 ? _("destination") : _("source")));
3563 else
3565 inst.error = _("missing +");
3566 return;
3569 if (end_of_line (str) == (int) FAIL)
3570 return;
3572 else
3574 inst.error = _("missing ]");
3575 return;
3578 else
3580 inst.error = BAD_ARGS;
3581 return;
3586 /* Handle alw/asw. */
3587 static void
3588 do_ldst_atomic (char *str)
3590 if (university_version == 1)
3592 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3593 return;
3596 skip_whitespace (str);
3598 if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3599 || (skip_past_comma (&str) == (int) FAIL))
3601 return;
3603 else
3606 skip_whitespace (str);
3607 if (*str++ == '[')
3609 int reg;
3611 skip_whitespace (str);
3612 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3614 return;
3617 skip_whitespace (str);
3618 if (*str++ != ']')
3620 inst.error = _("missing ]");
3621 return;
3624 end_of_line (str);
3626 else
3627 inst.error = BAD_ARGS;
3631 static void
3632 build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3633 struct score_it var_insts[RELAX_INST_NUM], int var_num,
3634 symbolS *add_symbol)
3636 int i;
3637 char *p;
3638 fixS *fixp = NULL;
3639 fixS *cur_fixp = NULL;
3640 long where;
3641 struct score_it inst_main;
3643 memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
3645 /* Adjust instruction opcode and to be relaxed instruction opcode. */
3646 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
3647 inst_main.type = Insn_PIC;
3649 for (i = 0; i < var_num; i++)
3651 inst_main.relax_size += var_insts[i].size;
3652 var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
3653 GET_INSN_CLASS (var_insts[i].type));
3656 /* Check data dependency. */
3657 handle_dependency (&inst_main);
3659 /* Start a new frag if frag_now is not empty. */
3660 if (frag_now_fix () != 0)
3662 if (!frag_now->tc_frag_data.is_insn)
3664 frag_wane (frag_now);
3666 frag_new (0);
3668 frag_grow (20);
3670 /* Write fr_fix part. */
3671 p = frag_more (inst_main.size);
3672 md_number_to_chars (p, inst_main.instruction, inst_main.size);
3674 if (inst_main.reloc.type != BFD_RELOC_NONE)
3675 fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
3676 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
3678 frag_now->tc_frag_data.fixp = fixp;
3679 cur_fixp = frag_now->tc_frag_data.fixp;
3681 #ifdef OBJ_ELF
3682 dwarf2_emit_insn (inst_main.size);
3683 #endif
3685 where = p - frag_now->fr_literal + inst_main.size;
3686 for (i = 0; i < var_num; i++)
3688 if (i > 0)
3689 where += var_insts[i - 1].size;
3691 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
3693 fixp = fix_new_score (frag_now, where, var_insts[i].size,
3694 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
3695 var_insts[i].reloc.type);
3696 if (fixp)
3698 if (cur_fixp)
3700 cur_fixp->fx_next = fixp;
3701 cur_fixp = cur_fixp->fx_next;
3703 else
3705 frag_now->tc_frag_data.fixp = fixp;
3706 cur_fixp = frag_now->tc_frag_data.fixp;
3712 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
3713 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
3714 0, inst_main.size, 0), add_symbol, 0, NULL);
3716 /* Write fr_var part.
3717 no calling gen_insn_frag, no fixS will be generated. */
3718 for (i = 0; i < var_num; i++)
3720 md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
3721 p += var_insts[i].size;
3723 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3724 inst.bwarn = -1;
3727 /* Build a relax frag for la instruction when generating PIC,
3728 external symbol first and local symbol second. */
3730 static void
3731 build_la_pic (int reg_rd, expressionS exp)
3733 symbolS *add_symbol = exp.X_add_symbol;
3734 offsetT add_number = exp.X_add_number;
3735 struct score_it fix_insts[RELAX_INST_NUM];
3736 struct score_it var_insts[RELAX_INST_NUM];
3737 int fix_num = 0;
3738 int var_num = 0;
3739 char tmp[MAX_LITERAL_POOL_SIZE];
3740 int r1_bak;
3742 r1_bak = nor1;
3743 nor1 = 0;
3745 if (add_number == 0)
3747 fix_num = 1;
3748 var_num = 2;
3750 /* For an external symbol, only one insn is generated;
3751 For a local symbol, two insns are generated. */
3752 /* Fix part
3753 For an external symbol: lw rD, <sym>($gp)
3754 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
3755 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3756 if (append_insn (tmp, FALSE) == (int) FAIL)
3757 return;
3759 if (reg_rd == PIC_CALL_REG)
3760 inst.reloc.type = BFD_RELOC_SCORE_CALL15;
3761 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3763 /* Var part
3764 For a local symbol :
3765 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
3766 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
3767 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
3768 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3769 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3770 if (append_insn (tmp, FALSE) == (int) FAIL)
3771 return;
3773 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
3774 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3776 else if (add_number >= -0x8000 && add_number <= 0x7fff)
3778 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3779 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3780 if (append_insn (tmp, TRUE) == (int) FAIL)
3781 return;
3783 /* Insn 2 */
3784 fix_num = 1;
3785 var_num = 1;
3786 /* Fix part
3787 For an external symbol: addi rD, <constant> */
3788 sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
3789 if (append_insn (tmp, FALSE) == (int) FAIL)
3790 return;
3792 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3794 /* Var part
3795 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
3796 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
3797 if (append_insn (tmp, FALSE) == (int) FAIL)
3798 return;
3800 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3801 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3803 else
3805 int hi = (add_number >> 16) & 0x0000FFFF;
3806 int lo = add_number & 0x0000FFFF;
3808 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
3809 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3810 if (append_insn (tmp, TRUE) == (int) FAIL)
3811 return;
3813 /* Insn 2 */
3814 fix_num = 1;
3815 var_num = 1;
3816 /* Fix part
3817 For an external symbol: ldis r1, HI%<constant> */
3818 sprintf (tmp, "ldis %s, %d", "r1", hi);
3819 if (append_insn (tmp, FALSE) == (int) FAIL)
3820 return;
3822 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3824 /* Var part
3825 For a local symbol: ldis r1, HI%<constant>
3826 but, if lo is outof 16 bit, make hi plus 1 */
3827 if ((lo < -0x8000) || (lo > 0x7fff))
3829 hi += 1;
3831 sprintf (tmp, "ldis_pic %s, %d", "r1", hi);
3832 if (append_insn (tmp, FALSE) == (int) FAIL)
3833 return;
3835 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3836 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3838 /* Insn 3 */
3839 fix_num = 1;
3840 var_num = 1;
3841 /* Fix part
3842 For an external symbol: ori r1, LO%<constant> */
3843 sprintf (tmp, "ori %s, %d", "r1", lo);
3844 if (append_insn (tmp, FALSE) == (int) FAIL)
3845 return;
3847 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3849 /* Var part
3850 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
3851 sprintf (tmp, "addi_u_pic %s, %s + %d", "r1", add_symbol->bsym->name, lo);
3852 if (append_insn (tmp, FALSE) == (int) FAIL)
3853 return;
3855 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3856 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3858 /* Insn 4: add rD, rD, r1 */
3859 sprintf (tmp, "add r%d, r%d, %s", reg_rd, reg_rd, "r1");
3860 if (append_insn (tmp, TRUE) == (int) FAIL)
3861 return;
3863 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3864 inst.bwarn = -1;
3867 nor1 = r1_bak;
3870 /* Handle la. */
3871 static void
3872 do_macro_la_rdi32 (char *str)
3874 int reg_rd;
3876 skip_whitespace (str);
3877 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3878 || skip_past_comma (&str) == (int) FAIL)
3880 return;
3882 else
3884 char append_str[MAX_LITERAL_POOL_SIZE];
3885 char *keep_data = str;
3887 /* la rd, simm16. */
3888 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3890 end_of_line (str);
3891 return;
3893 /* la rd, imm32 or la rd, label. */
3894 else
3896 SET_INSN_ERROR (NULL);
3897 str = keep_data;
3898 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3899 || (end_of_line (str) == (int) FAIL))
3901 return;
3903 else
3905 if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
3907 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3908 if (append_insn (append_str, TRUE) == (int) FAIL)
3909 return;
3911 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3912 if (append_insn (append_str, TRUE) == (int) FAIL)
3913 return;
3915 else
3917 assert (inst.reloc.exp.X_add_symbol);
3918 build_la_pic (reg_rd, inst.reloc.exp);
3921 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3922 inst.bwarn = -1;
3928 /* Handle li. */
3929 static void
3930 do_macro_li_rdi32 (char *str){
3932 int reg_rd;
3934 skip_whitespace (str);
3935 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3936 || skip_past_comma (&str) == (int) FAIL)
3938 return;
3940 else
3942 char *keep_data = str;
3944 /* li rd, simm16. */
3945 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3947 end_of_line (str);
3948 return;
3950 /* li rd, imm32. */
3951 else
3953 char append_str[MAX_LITERAL_POOL_SIZE];
3955 str = keep_data;
3957 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3958 || (end_of_line (str) == (int) FAIL))
3960 return;
3962 else if (inst.reloc.exp.X_add_symbol)
3964 inst.error = _("li rd label isn't correct instruction form");
3965 return;
3967 else
3969 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3971 if (append_insn (append_str, TRUE) == (int) FAIL)
3972 return;
3973 else
3975 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3976 if (append_insn (append_str, TRUE) == (int) FAIL)
3977 return;
3979 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3980 inst.bwarn = -1;
3987 /* Handle mul/mulu/div/divu/rem/remu. */
3988 static void
3989 do_macro_mul_rdrsrs (char *str)
3991 int reg_rd;
3992 int reg_rs1;
3993 int reg_rs2;
3994 char *backupstr;
3995 char append_str[MAX_LITERAL_POOL_SIZE];
3997 if (university_version == 1)
3998 as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
4000 strcpy (append_str, str);
4001 backupstr = append_str;
4002 skip_whitespace (backupstr);
4003 if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4004 || (skip_past_comma (&backupstr) == (int) FAIL)
4005 || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
4007 inst.error = BAD_ARGS;
4008 return;
4011 if (skip_past_comma (&backupstr) == (int) FAIL)
4013 /* rem/remu rA, rB is error format. */
4014 if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
4016 SET_INSN_ERROR (BAD_ARGS);
4018 else
4020 SET_INSN_ERROR (NULL);
4021 do_rsrs (str);
4023 return;
4025 else
4027 SET_INSN_ERROR (NULL);
4028 if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4029 || (end_of_line (backupstr) == (int) FAIL))
4031 return;
4033 else
4035 char append_str1[MAX_LITERAL_POOL_SIZE];
4037 if (strcmp (inst.name, "rem") == 0)
4039 sprintf (append_str, "%s r%d, r%d", "mul", reg_rs1, reg_rs2);
4040 sprintf (append_str1, "mfceh r%d", reg_rd);
4042 else if (strcmp (inst.name, "remu") == 0)
4044 sprintf (append_str, "%s r%d, r%d", "mulu", reg_rs1, reg_rs2);
4045 sprintf (append_str1, "mfceh r%d", reg_rd);
4047 else
4049 sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
4050 sprintf (append_str1, "mfcel r%d", reg_rd);
4053 /* Output mul/mulu or div/divu or rem/remu. */
4054 if (append_insn (append_str, TRUE) == (int) FAIL)
4055 return;
4057 /* Output mfcel or mfceh. */
4058 if (append_insn (append_str1, TRUE) == (int) FAIL)
4059 return;
4061 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4062 inst.bwarn = -1;
4067 static void
4068 exp_macro_ldst_abs (char *str)
4070 int reg_rd;
4071 char *backupstr, *tmp;
4072 char append_str[MAX_LITERAL_POOL_SIZE];
4073 char verifystr[MAX_LITERAL_POOL_SIZE];
4074 struct score_it inst_backup;
4075 int r1_bak = 0;
4077 r1_bak = nor1;
4078 nor1 = 0;
4079 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4081 strcpy (verifystr, str);
4082 backupstr = verifystr;
4083 skip_whitespace (backupstr);
4084 if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4085 return;
4087 tmp = backupstr;
4088 if (skip_past_comma (&backupstr) == (int) FAIL)
4089 return;
4091 backupstr = tmp;
4092 sprintf (append_str, "li r1 %s", backupstr);
4093 append_insn (append_str, TRUE);
4095 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4096 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4097 do_ldst_insn (append_str);
4099 nor1 = r1_bak;
4102 static int
4103 nopic_need_relax (symbolS * sym, int before_relaxing)
4105 if (sym == NULL)
4106 return 0;
4107 else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
4109 const char *symname;
4110 const char *segname;
4112 /* Find out whether this symbol can be referenced off the $gp
4113 register. It can be if it is smaller than the -G size or if
4114 it is in the .sdata or .sbss section. Certain symbols can
4115 not be referenced off the $gp, although it appears as though
4116 they can. */
4117 symname = S_GET_NAME (sym);
4118 if (symname != (const char *)NULL
4119 && (strcmp (symname, "eprol") == 0
4120 || strcmp (symname, "etext") == 0
4121 || strcmp (symname, "_gp") == 0
4122 || strcmp (symname, "edata") == 0
4123 || strcmp (symname, "_fbss") == 0
4124 || strcmp (symname, "_fdata") == 0
4125 || strcmp (symname, "_ftext") == 0
4126 || strcmp (symname, "end") == 0
4127 || strcmp (symname, GP_DISP_LABEL) == 0))
4129 return 1;
4131 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4132 /* We must defer this decision until after the whole file has been read,
4133 since there might be a .extern after the first use of this symbol. */
4134 || (before_relaxing
4135 && S_GET_VALUE (sym) == 0)
4136 || (S_GET_VALUE (sym) != 0
4137 && S_GET_VALUE (sym) <= g_switch_value)))
4139 return 0;
4142 segname = segment_name (S_GET_SEGMENT (sym));
4143 return (strcmp (segname, ".sdata") != 0
4144 && strcmp (segname, ".sbss") != 0
4145 && strncmp (segname, ".sdata.", 7) != 0
4146 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4148 /* We are not optimizing for the $gp register. */
4149 else
4150 return 1;
4153 /* Build a relax frag for lw/st instruction when generating PIC,
4154 external symbol first and local symbol second. */
4156 static void
4157 build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4159 symbolS *add_symbol = exp.X_add_symbol;
4160 int add_number = exp.X_add_number;
4161 struct score_it fix_insts[RELAX_INST_NUM];
4162 struct score_it var_insts[RELAX_INST_NUM];
4163 int fix_num = 0;
4164 int var_num = 0;
4165 char tmp[MAX_LITERAL_POOL_SIZE];
4166 int r1_bak;
4168 r1_bak = nor1;
4169 nor1 = 0;
4171 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4173 fix_num = 1;
4174 var_num = 2;
4176 /* For an external symbol, two insns are generated;
4177 For a local symbol, three insns are generated. */
4178 /* Fix part
4179 For an external symbol: lw rD, <sym>($gp)
4180 (BFD_RELOC_SCORE_GOT15) */
4181 sprintf (tmp, "lw_pic %s, %s", "r1", add_symbol->bsym->name);
4182 if (append_insn (tmp, FALSE) == (int) FAIL)
4183 return;
4185 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4187 /* Var part
4188 For a local symbol :
4189 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4190 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4191 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4192 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4193 sprintf (tmp, "addi_s_pic %s, %s", "r1", add_symbol->bsym->name);
4194 if (append_insn (tmp, FALSE) == (int) FAIL)
4195 return;
4197 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
4198 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4200 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4201 sprintf (tmp, "%s r%d, [%s, %d]", insn_name, reg_rd, "r1", add_number);
4202 if (append_insn (tmp, TRUE) == (int) FAIL)
4203 return;
4205 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4206 inst.bwarn = -1;
4208 else
4210 inst.error = _("PIC code offset overflow (max 16 signed bits)");
4211 return;
4214 nor1 = r1_bak;
4217 static void
4218 do_macro_ldst_label (char *str)
4220 int i;
4221 int ldst_gp_p = 0;
4222 int reg_rd;
4223 int r1_bak;
4224 char *backup_str;
4225 char *label_str;
4226 char *absolute_value;
4227 char append_str[3][MAX_LITERAL_POOL_SIZE];
4228 char verifystr[MAX_LITERAL_POOL_SIZE];
4229 struct score_it inst_backup;
4230 struct score_it inst_expand[3];
4231 struct score_it inst_main;
4233 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4234 strcpy (verifystr, str);
4235 backup_str = verifystr;
4237 skip_whitespace (backup_str);
4238 if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
4239 return;
4241 if (skip_past_comma (&backup_str) == (int) FAIL)
4242 return;
4244 label_str = backup_str;
4246 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4247 if (*backup_str == '[')
4249 inst.type = Rd_rvalueRs_preSI12;
4250 do_ldst_insn (str);
4251 return;
4254 /* Ld/st rD, imm. */
4255 absolute_value = backup_str;
4256 inst.type = Rd_rvalueRs_SI15;
4257 if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
4258 || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE) == (int) FAIL)
4259 || (end_of_line (backup_str) == (int) FAIL))
4261 return;
4263 else
4265 if (inst.reloc.exp.X_add_symbol == 0)
4267 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4268 exp_macro_ldst_abs (str);
4269 return;
4273 /* Ld/st rD, label. */
4274 inst.type = Rd_rvalueRs_SI15;
4275 backup_str = absolute_value;
4276 if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
4277 || (end_of_line (backup_str) == (int) FAIL))
4279 return;
4281 else
4283 if (inst.reloc.exp.X_add_symbol == 0)
4285 if (!inst.error)
4286 inst.error = BAD_ARGS;
4288 return;
4291 if (score_pic == PIC)
4293 int ldst_idx = 0;
4294 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4295 build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
4296 return;
4298 else
4300 if ((inst.reloc.exp.X_add_number <= 0x3fff)
4301 && (inst.reloc.exp.X_add_number >= -0x4000)
4302 && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
4304 int ldst_idx = 0;
4306 /* Assign the real opcode. */
4307 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4308 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4309 inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
4310 inst.instruction |= reg_rd << 20;
4311 inst.instruction |= GP << 15;
4312 inst.relax_inst = 0x8000;
4313 inst.relax_size = 0;
4314 ldst_gp_p = 1;
4319 /* Backup inst. */
4320 memcpy (&inst_main, &inst, sizeof (struct score_it));
4321 r1_bak = nor1;
4322 nor1 = 0;
4324 /* Determine which instructions should be output. */
4325 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4326 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4327 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4329 /* Generate three instructions.
4330 la r1, label
4331 ld/st rd, [r1, 0] */
4332 for (i = 0; i < 3; i++)
4334 if (append_insn (append_str[i], FALSE) == (int) FAIL)
4335 return;
4337 memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
4340 if (ldst_gp_p)
4342 char *p;
4344 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4345 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
4346 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4347 inst_main.type = Insn_GP;
4349 for (i = 0; i < 3; i++)
4350 inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
4351 , GET_INSN_CLASS (inst_expand[i].type));
4353 /* Check data dependency. */
4354 handle_dependency (&inst_main);
4356 /* Start a new frag if frag_now is not empty. */
4357 if (frag_now_fix () != 0)
4359 if (!frag_now->tc_frag_data.is_insn)
4360 frag_wane (frag_now);
4362 frag_new (0);
4364 frag_grow (20);
4366 /* Write fr_fix part. */
4367 p = frag_more (inst_main.size);
4368 md_number_to_chars (p, inst_main.instruction, inst_main.size);
4370 if (inst_main.reloc.type != BFD_RELOC_NONE)
4372 fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4373 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4376 #ifdef OBJ_ELF
4377 dwarf2_emit_insn (inst_main.size);
4378 #endif
4380 /* GP instruction can not do optimization, only can do relax between
4381 1 instruction and 3 instructions. */
4382 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
4383 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4384 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4386 /* Write fr_var part.
4387 no calling gen_insn_frag, no fixS will be generated. */
4388 md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4389 p += inst_expand[0].size;
4390 md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4391 p += inst_expand[1].size;
4392 md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4394 else
4396 gen_insn_frag (&inst_expand[0], NULL);
4397 gen_insn_frag (&inst_expand[1], NULL);
4398 gen_insn_frag (&inst_expand[2], NULL);
4400 nor1 = r1_bak;
4402 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4403 inst.bwarn = -1;
4406 static void
4407 do_lw_pic (char *str)
4409 int reg_rd;
4411 skip_whitespace (str);
4412 if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
4413 || (skip_past_comma (&str) == (int) FAIL)
4414 || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
4415 || (end_of_line (str) == (int) FAIL))
4417 return;
4419 else
4421 if (inst.reloc.exp.X_add_symbol == 0)
4423 if (!inst.error)
4424 inst.error = BAD_ARGS;
4426 return;
4429 inst.instruction |= GP << 15;
4430 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4434 static void
4435 do_empty (char *str)
4437 str = str;
4438 if (university_version == 1)
4440 if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
4441 || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
4442 || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
4443 || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
4445 inst.error = ERR_FOR_SCORE5U_MMU;
4446 return;
4449 if (end_of_line (str) == (int) FAIL)
4450 return;
4452 if (inst.relax_inst != 0x8000)
4454 if (inst.type == NO_OPD)
4456 inst.relax_size = 2;
4458 else
4460 inst.relax_size = 4;
4465 static void
4466 do_jump (char *str)
4468 char *save_in;
4469 char err_msg[100];
4471 skip_whitespace (str);
4472 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4473 || end_of_line (str) == (int) FAIL)
4474 return;
4476 if (inst.reloc.exp.X_add_symbol == 0)
4478 inst.error = _("lacking label ");
4479 return;
4482 if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4483 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4485 sprintf (err_msg, "invalid constant: 25 bit expression not in range -2^24..2^24");
4486 inst.error = _(err_msg);
4487 return;
4490 save_in = input_line_pointer;
4491 input_line_pointer = str;
4492 inst.reloc.type = BFD_RELOC_SCORE_JMP;
4493 inst.reloc.pc_rel = 1;
4494 input_line_pointer = save_in;
4497 static void
4498 do16_jump (char *str)
4500 skip_whitespace (str);
4501 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4502 || end_of_line (str) == (int) FAIL)
4504 return;
4506 else if (inst.reloc.exp.X_add_symbol == 0)
4508 inst.error = _("lacking label ");
4509 return;
4511 else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
4512 && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
4514 inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
4515 return;
4518 inst.reloc.type = BFD_RELOC_SCORE16_JMP;
4519 inst.reloc.pc_rel = 1;
4522 static void
4523 do_branch (char *str)
4525 unsigned long abs_value = 0;
4527 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4528 || end_of_line (str) == (int) FAIL)
4530 return;
4532 else if (inst.reloc.exp.X_add_symbol == 0)
4534 inst.error = _("lacking label ");
4535 return;
4537 else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4538 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4540 inst.error = "invalid constant: 20 bit expression not in range -2^19..2^19";
4541 return;
4544 inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
4545 inst.reloc.pc_rel = 1;
4547 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
4548 inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
4550 /* Compute 16 bit branch instruction. */
4551 if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
4553 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
4554 inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4555 inst.relax_size = 2;
4557 else
4559 inst.relax_inst = 0x8000;
4563 static void
4564 do16_branch (char *str)
4566 if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4567 || end_of_line (str) == (int) FAIL))
4571 else if (inst.reloc.exp.X_add_symbol == 0)
4573 inst.error = _("lacking label");
4575 else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
4576 && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
4578 inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
4580 else
4582 inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
4583 inst.reloc.pc_rel = 1;
4584 inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4588 /* Iterate over the base tables to create the instruction patterns. */
4589 static void
4590 build_score_ops_hsh (void)
4592 unsigned int i;
4593 static struct obstack insn_obstack;
4595 obstack_begin (&insn_obstack, 4000);
4596 for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
4598 const struct asm_opcode *insn = score_insns + i;
4599 unsigned len = strlen (insn->template);
4600 struct asm_opcode *new;
4601 char *template;
4602 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
4603 template = obstack_alloc (&insn_obstack, len + 1);
4605 strcpy (template, insn->template);
4606 new->template = template;
4607 new->parms = insn->parms;
4608 new->value = insn->value;
4609 new->relax_value = insn->relax_value;
4610 new->type = insn->type;
4611 new->bitmask = insn->bitmask;
4612 hash_insert (score_ops_hsh, new->template, (void *) new);
4616 static void
4617 build_dependency_insn_hsh (void)
4619 unsigned int i;
4620 static struct obstack dependency_obstack;
4622 obstack_begin (&dependency_obstack, 4000);
4623 for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
4625 const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
4626 unsigned len = strlen (tmp->insn_name);
4627 struct insn_to_dependency *new;
4629 new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
4630 new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
4632 strcpy (new->insn_name, tmp->insn_name);
4633 new->type = tmp->type;
4634 hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
4638 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4639 for use in the a.out file, and stores them in the array pointed to by buf.
4640 This knows about the endian-ness of the target machine and does
4641 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4642 2 (short) and 4 (long) Floating numbers are put out as a series of
4643 LITTLENUMS (shorts, here at least). */
4645 void
4646 md_number_to_chars (char *buf, valueT val, int n)
4648 if (target_big_endian)
4649 number_to_chars_bigendian (buf, val, n);
4650 else
4651 number_to_chars_littleendian (buf, val, n);
4654 static valueT
4655 md_chars_to_number (char *buf, int n)
4657 valueT result = 0;
4658 unsigned char *where = (unsigned char *)buf;
4660 if (target_big_endian)
4662 while (n--)
4664 result <<= 8;
4665 result |= (*where++ & 255);
4668 else
4670 while (n--)
4672 result <<= 8;
4673 result |= (where[n] & 255);
4677 return result;
4680 /* Turn a string in input_line_pointer into a floating point constant
4681 of type TYPE, and store the appropriate bytes in *LITP. The number
4682 of LITTLENUMS emitted is stored in *SIZEP. An error message is
4683 returned, or NULL on OK.
4685 Note that fp constants aren't represent in the normal way on the ARM.
4686 In big endian mode, things are as expected. However, in little endian
4687 mode fp constants are big-endian word-wise, and little-endian byte-wise
4688 within the words. For example, (double) 1.1 in big endian mode is
4689 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4690 the byte sequence 99 99 f1 3f 9a 99 99 99. */
4692 char *
4693 md_atof (int type, char *litP, int *sizeP)
4695 int prec;
4696 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4697 char *t;
4698 int i;
4700 switch (type)
4702 case 'f':
4703 case 'F':
4704 case 's':
4705 case 'S':
4706 prec = 2;
4707 break;
4708 case 'd':
4709 case 'D':
4710 case 'r':
4711 case 'R':
4712 prec = 4;
4713 break;
4714 case 'x':
4715 case 'X':
4716 case 'p':
4717 case 'P':
4718 prec = 6;
4719 break;
4720 default:
4721 *sizeP = 0;
4722 return _("bad call to MD_ATOF()");
4725 t = atof_ieee (input_line_pointer, type, words);
4726 if (t)
4727 input_line_pointer = t;
4728 *sizeP = prec * 2;
4730 if (target_big_endian)
4732 for (i = 0; i < prec; i++)
4734 md_number_to_chars (litP, (valueT) words[i], 2);
4735 litP += 2;
4738 else
4740 for (i = 0; i < prec; i += 2)
4742 md_number_to_chars (litP, (valueT) words[i + 1], 2);
4743 md_number_to_chars (litP + 2, (valueT) words[i], 2);
4744 litP += 4;
4748 return 0;
4751 /* Return true if the given symbol should be considered local for PIC. */
4753 static bfd_boolean
4754 pic_need_relax (symbolS *sym, asection *segtype)
4756 asection *symsec;
4757 bfd_boolean linkonce;
4759 /* Handle the case of a symbol equated to another symbol. */
4760 while (symbol_equated_reloc_p (sym))
4762 symbolS *n;
4764 /* It's possible to get a loop here in a badly written
4765 program. */
4766 n = symbol_get_value_expression (sym)->X_add_symbol;
4767 if (n == sym)
4768 break;
4769 sym = n;
4772 symsec = S_GET_SEGMENT (sym);
4774 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
4775 linkonce = FALSE;
4776 if (symsec != segtype && ! S_IS_LOCAL (sym))
4778 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
4779 linkonce = TRUE;
4781 /* The GNU toolchain uses an extension for ELF: a section
4782 beginning with the magic string .gnu.linkonce is a linkonce
4783 section. */
4784 if (strncmp (segment_name (symsec), ".gnu.linkonce",
4785 sizeof ".gnu.linkonce" - 1) == 0)
4786 linkonce = TRUE;
4789 /* This must duplicate the test in adjust_reloc_syms. */
4790 return (symsec != &bfd_und_section
4791 && symsec != &bfd_abs_section
4792 && ! bfd_is_com_section (symsec)
4793 && !linkonce
4794 #ifdef OBJ_ELF
4795 /* A global or weak symbol is treated as external. */
4796 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
4797 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
4798 #endif
4802 static int
4803 judge_size_before_relax (fragS * fragp, asection *sec)
4805 int change = 0;
4807 if (score_pic == NO_PIC)
4808 change = nopic_need_relax (fragp->fr_symbol, 0);
4809 else
4810 change = pic_need_relax (fragp->fr_symbol, sec);
4812 if (change == 1)
4814 /* Only at the first time determining whether GP instruction relax should be done,
4815 return the difference between insntruction size and instruction relax size. */
4816 if (fragp->fr_opcode == NULL)
4818 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
4819 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
4820 return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
4824 return 0;
4827 /* In this function, we determine whether GP instruction should do relaxation,
4828 for the label being against was known now.
4829 Doing this here but not in md_relax_frag() can induce iteration times
4830 in stage of doing relax. */
4832 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
4834 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4835 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4836 return judge_size_before_relax (fragp, sec);
4838 return 0;
4841 static int
4842 b32_relax_to_b16 (fragS * fragp)
4844 int grows = 0;
4845 int relaxable_p = 0;
4846 int old;
4847 int new;
4848 int frag_addr = fragp->fr_address + fragp->insn_addr;
4850 addressT symbol_address = 0;
4851 symbolS *s;
4852 offsetT offset;
4853 unsigned long value;
4854 unsigned long abs_value;
4856 /* FIXME : here may be able to modify better .
4857 I don't know how to get the fragp's section ,
4858 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
4859 is different from the symbol's. */
4861 old = RELAX_OLD (fragp->fr_subtype);
4862 new = RELAX_NEW (fragp->fr_subtype);
4863 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4865 s = fragp->fr_symbol;
4866 /* b/bl immediate */
4867 if (s == NULL)
4868 frag_addr = 0;
4869 else
4871 if (s->bsym != 0)
4872 symbol_address = (addressT) s->sy_frag->fr_address;
4875 value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
4877 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
4878 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
4879 if ((offset & 0x80000) == 0x80000)
4880 offset |= 0xfff00000;
4882 abs_value = offset + symbol_address - frag_addr;
4883 if ((abs_value & 0x80000000) == 0x80000000)
4884 abs_value = 0xffffffff - abs_value + 1;
4886 /* Relax branch 32 to branch 16. */
4887 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
4888 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
4890 /* do nothing. */
4892 else
4894 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
4895 fragp->fr_opcode = NULL;
4896 fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
4899 return grows;
4902 /* Main purpose is to determine whether one frag should do relax.
4903 frag->fr_opcode indicates this point. */
4906 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
4908 int grows = 0;
4909 int insn_size;
4910 int insn_relax_size;
4911 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
4912 int relaxable_p = 0;
4913 bfd_boolean word_align_p = FALSE;
4914 fragS *next_fragp;
4916 /* If the instruction address is odd, make it half word align first. */
4917 if ((fragp->fr_address) % 2 != 0)
4919 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
4921 fragp->insn_addr = 1;
4922 grows += 1;
4926 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
4928 /* Get instruction size and relax size after the last relaxation. */
4929 if (fragp->fr_opcode)
4931 insn_size = RELAX_NEW (fragp->fr_subtype);
4932 insn_relax_size = RELAX_OLD (fragp->fr_subtype);
4934 else
4936 insn_size = RELAX_OLD (fragp->fr_subtype);
4937 insn_relax_size = RELAX_NEW (fragp->fr_subtype);
4940 /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine
4941 whether the GP instruction should do relax. */
4942 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4943 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4945 if (!word_align_p)
4947 if (fragp->insn_addr < 2)
4949 fragp->insn_addr += 2;
4950 grows += 2;
4952 else
4954 fragp->insn_addr -= 2;
4955 grows -= 2;
4959 if (fragp->fr_opcode)
4960 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
4961 else
4962 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
4964 else
4966 if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
4967 b32_relax_to_b16 (fragp);
4969 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4970 next_fragp = fragp->fr_next;
4971 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
4973 next_fragp = next_fragp->fr_next;
4976 if (next_fragp)
4978 int n_insn_size;
4979 int n_relaxable_p = 0;
4981 if (next_fragp->fr_opcode)
4983 n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
4985 else
4987 n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
4990 if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
4991 b32_relax_to_b16 (next_fragp);
4992 n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
4994 if (word_align_p)
4996 if (insn_size == 4)
4998 /* 32 -> 16. */
4999 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
5001 grows -= 2;
5002 do_relax_p = 1;
5005 else if (insn_size == 2)
5007 /* 16 -> 32. */
5008 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
5010 grows += 2;
5011 do_relax_p = 1;
5014 else
5016 abort ();
5019 else
5021 if (insn_size == 4)
5023 /* 32 -> 16. */
5024 if (relaxable_p)
5026 grows -= 2;
5027 do_relax_p = 1;
5029 /* Make the 32 bit insturction word align. */
5030 else
5032 fragp->insn_addr += 2;
5033 grows += 2;
5036 else if (insn_size == 2)
5038 /* Do nothing. */
5040 else
5042 abort ();
5046 else
5048 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
5049 if (word_align_p == FALSE)
5051 if (insn_size % 4 == 0)
5053 /* 32 -> 16. */
5054 if (relaxable_p)
5056 grows -= 2;
5057 do_relax_p = 1;
5059 else
5061 fragp->insn_addr += 2;
5062 grows += 2;
5066 else
5068 /* Do nothing. */
5072 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5073 if (do_relax_p)
5075 if (fragp->fr_opcode)
5077 fragp->fr_opcode = NULL;
5078 /* Guarantee estimate stage is correct. */
5079 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5080 fragp->fr_fix += fragp->insn_addr;
5082 else
5084 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
5085 /* Guarantee estimate stage is correct. */
5086 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5087 fragp->fr_fix += fragp->insn_addr;
5090 else
5092 if (fragp->fr_opcode)
5094 /* Guarantee estimate stage is correct. */
5095 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5096 fragp->fr_fix += fragp->insn_addr;
5098 else
5100 /* Guarantee estimate stage is correct. */
5101 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5102 fragp->fr_fix += fragp->insn_addr;
5107 return grows;
5110 void
5111 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
5113 int old;
5114 int new;
5115 char backup[20];
5116 fixS *fixp;
5118 old = RELAX_OLD (fragp->fr_subtype);
5119 new = RELAX_NEW (fragp->fr_subtype);
5121 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5122 if (fragp->fr_opcode == NULL)
5124 memcpy (backup, fragp->fr_literal, old);
5125 fragp->fr_fix = old;
5127 else
5129 memcpy (backup, fragp->fr_literal + old, new);
5130 fragp->fr_fix = new;
5133 fixp = fragp->tc_frag_data.fixp;
5134 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
5136 if (fragp->fr_opcode)
5137 fixp->fx_done = 1;
5138 fixp = fixp->fx_next;
5140 while (fixp && fixp->fx_frag == fragp)
5142 if (fragp->fr_opcode)
5143 fixp->fx_where -= old + fragp->insn_addr;
5144 else
5145 fixp->fx_done = 1;
5146 fixp = fixp->fx_next;
5149 if (fragp->insn_addr)
5151 md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
5153 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
5154 fragp->fr_fix += fragp->insn_addr;
5157 /* Implementation of md_frag_check.
5158 Called after md_convert_frag(). */
5160 void
5161 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
5163 know (fragp->insn_addr <= RELAX_PAD_BYTE);
5166 bfd_boolean
5167 score_fix_adjustable (fixS * fixP)
5169 if (fixP->fx_addsy == NULL)
5171 return 1;
5173 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
5174 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
5176 return 0;
5178 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5179 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5181 return 0;
5184 return 1;
5187 /* Implementation of TC_VALIDATE_FIX.
5188 Called before md_apply_fix() and after md_convert_frag(). */
5189 void
5190 score_validate_fix (fixS *fixP)
5192 fixP->fx_where += fixP->fx_frag->insn_addr;
5195 long
5196 md_pcrel_from (fixS * fixP)
5198 long retval = 0;
5200 if (fixP->fx_addsy
5201 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
5202 && (fixP->fx_subsy == NULL))
5204 retval = 0;
5206 else
5208 retval = fixP->fx_where + fixP->fx_frag->fr_address;
5211 return retval;
5215 score_force_relocation (struct fix *fixp)
5217 int retval = 0;
5219 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5220 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
5221 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
5222 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
5223 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
5224 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
5226 retval = 1;
5229 return retval;
5232 /* Round up a section size to the appropriate boundary. */
5233 valueT
5234 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5236 int align = bfd_get_section_alignment (stdoutput, segment);
5238 #ifdef OBJ_ELF
5239 /* We don't need to align ELF sections to the full alignment.
5240 However, Irix 5 may prefer that we align them at least to a 16
5241 byte boundary. We don't bother to align the sections if we are
5242 targeted for an embedded system. */
5243 if (strcmp (TARGET_OS, "elf") == 0)
5244 return size;
5245 if (align > 4)
5246 align = 4;
5247 #endif
5249 return ((size + (1 << align) - 1) & (-1 << align));
5252 void
5253 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
5255 offsetT value = *valP;
5256 offsetT abs_value = 0;
5257 offsetT newval;
5258 offsetT content;
5259 unsigned short HI, LO;
5261 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
5263 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5264 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5266 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
5267 fixP->fx_done = 1;
5270 /* If this symbol is in a different section then we need to leave it for
5271 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5272 so we have to undo it's effects here. */
5273 if (fixP->fx_pcrel)
5275 if (fixP->fx_addsy != NULL
5276 && S_IS_DEFINED (fixP->fx_addsy)
5277 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5278 value += md_pcrel_from (fixP);
5281 /* Remember value for emit_reloc. */
5282 fixP->fx_addnumber = value;
5284 switch (fixP->fx_r_type)
5286 case BFD_RELOC_HI16_S:
5287 if (fixP->fx_done)
5288 { /* For la rd, imm32. */
5289 newval = md_chars_to_number (buf, INSN_SIZE);
5290 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
5291 newval |= (HI & 0x3fff) << 1;
5292 newval |= ((HI >> 14) & 0x3) << 16;
5293 md_number_to_chars (buf, newval, INSN_SIZE);
5295 break;
5296 case BFD_RELOC_LO16:
5297 if (fixP->fx_done) /* For la rd, imm32. */
5299 newval = md_chars_to_number (buf, INSN_SIZE);
5300 LO = (value) & 0xffff;
5301 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
5302 newval |= ((LO >> 14) & 0x3) << 16;
5303 md_number_to_chars (buf, newval, INSN_SIZE);
5305 break;
5306 case BFD_RELOC_SCORE_JMP:
5308 content = md_chars_to_number (buf, INSN_SIZE);
5309 value = fixP->fx_offset;
5310 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
5311 md_number_to_chars (buf, content, INSN_SIZE);
5313 break;
5314 case BFD_RELOC_SCORE_BRANCH:
5315 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5316 value = fixP->fx_offset;
5317 else
5318 fixP->fx_done = 1;
5320 content = md_chars_to_number (buf, INSN_SIZE);
5321 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
5323 if ((value & 0x80000000) == 0x80000000)
5324 abs_value = 0xffffffff - value + 1;
5325 if ((abs_value & 0xffffff00) != 0)
5327 as_bad_where (fixP->fx_file, fixP->fx_line,
5328 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5329 return;
5331 content = md_chars_to_number (buf, INSN16_SIZE);
5332 content &= 0xff00;
5333 content = (content & 0xff00) | ((value >> 1) & 0xff);
5334 md_number_to_chars (buf, content, INSN16_SIZE);
5335 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
5336 fixP->fx_size = 2;
5338 else
5340 if ((value & 0x80000000) == 0x80000000)
5341 abs_value = 0xffffffff - value + 1;
5342 if ((abs_value & 0xfff80000) != 0)
5344 as_bad_where (fixP->fx_file, fixP->fx_line,
5345 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5346 return;
5348 content = md_chars_to_number (buf, INSN_SIZE);
5349 content &= 0xfc00fc01;
5350 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5351 md_number_to_chars (buf, content, INSN_SIZE);
5353 break;
5354 case BFD_RELOC_SCORE16_JMP:
5355 content = md_chars_to_number (buf, INSN16_SIZE);
5356 content &= 0xf001;
5357 value = fixP->fx_offset & 0xfff;
5358 content = (content & 0xfc01) | (value & 0xffe);
5359 md_number_to_chars (buf, content, INSN16_SIZE);
5360 break;
5361 case BFD_RELOC_SCORE16_BRANCH:
5362 content = md_chars_to_number (buf, INSN_SIZE);
5363 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
5365 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5366 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5367 value = fixP->fx_offset;
5368 else
5369 fixP->fx_done = 1;
5370 if ((value & 0x80000000) == 0x80000000)
5371 abs_value = 0xffffffff - value + 1;
5372 if ((abs_value & 0xfff80000) != 0)
5374 as_bad_where (fixP->fx_file, fixP->fx_line,
5375 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5376 return;
5378 content = md_chars_to_number (buf, INSN_SIZE);
5379 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5380 md_number_to_chars (buf, content, INSN_SIZE);
5381 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
5382 fixP->fx_size = 4;
5383 break;
5385 else
5387 /* In differnt section. */
5388 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5389 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5390 value = fixP->fx_offset;
5391 else
5392 fixP->fx_done = 1;
5394 if ((value & 0x80000000) == 0x80000000)
5395 abs_value = 0xffffffff - value + 1;
5396 if ((abs_value & 0xffffff00) != 0)
5398 as_bad_where (fixP->fx_file, fixP->fx_line,
5399 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5400 return;
5402 content = md_chars_to_number (buf, INSN16_SIZE);
5403 content = (content & 0xff00) | ((value >> 1) & 0xff);
5404 md_number_to_chars (buf, content, INSN16_SIZE);
5405 break;
5407 case BFD_RELOC_8:
5408 if (fixP->fx_done || fixP->fx_pcrel)
5409 md_number_to_chars (buf, value, 1);
5410 #ifdef OBJ_ELF
5411 else
5413 value = fixP->fx_offset;
5414 md_number_to_chars (buf, value, 1);
5416 #endif
5417 break;
5419 case BFD_RELOC_16:
5420 if (fixP->fx_done || fixP->fx_pcrel)
5421 md_number_to_chars (buf, value, 2);
5422 #ifdef OBJ_ELF
5423 else
5425 value = fixP->fx_offset;
5426 md_number_to_chars (buf, value, 2);
5428 #endif
5429 break;
5430 case BFD_RELOC_RVA:
5431 case BFD_RELOC_32:
5432 if (fixP->fx_done || fixP->fx_pcrel)
5433 md_number_to_chars (buf, value, 4);
5434 #ifdef OBJ_ELF
5435 else
5437 value = fixP->fx_offset;
5438 md_number_to_chars (buf, value, 4);
5440 #endif
5441 break;
5442 case BFD_RELOC_VTABLE_INHERIT:
5443 fixP->fx_done = 0;
5444 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
5445 S_SET_WEAK (fixP->fx_addsy);
5446 break;
5447 case BFD_RELOC_VTABLE_ENTRY:
5448 fixP->fx_done = 0;
5449 break;
5450 case BFD_RELOC_SCORE_GPREL15:
5451 content = md_chars_to_number (buf, INSN_SIZE);
5452 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
5453 fixP->fx_r_type = BFD_RELOC_NONE;
5454 fixP->fx_done = 0;
5455 break;
5456 case BFD_RELOC_SCORE_GOT15:
5457 case BFD_RELOC_SCORE_DUMMY_HI16:
5458 case BFD_RELOC_SCORE_GOT_LO16:
5459 case BFD_RELOC_SCORE_CALL15:
5460 case BFD_RELOC_GPREL32:
5461 break;
5462 case BFD_RELOC_NONE:
5463 default:
5464 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
5468 /* Translate internal representation of relocation info to BFD target format. */
5469 arelent **
5470 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
5472 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
5473 arelent *reloc;
5474 bfd_reloc_code_real_type code;
5475 char *type;
5476 fragS *f;
5477 symbolS *s;
5478 expressionS e;
5480 reloc = retval[0] = xmalloc (sizeof (arelent));
5481 retval[1] = NULL;
5483 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5484 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5485 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5486 reloc->addend = fixp->fx_offset;
5488 /* If this is a variant frag, we may need to adjust the existing
5489 reloc and generate a new one. */
5490 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
5492 /* Update instruction imm bit. */
5493 offsetT newval;
5494 unsigned short off;
5495 char *buf;
5497 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
5498 newval = md_chars_to_number (buf, INSN_SIZE);
5499 off = fixp->fx_offset >> 16;
5500 newval |= (off & 0x3fff) << 1;
5501 newval |= ((off >> 14) & 0x3) << 16;
5502 md_number_to_chars (buf, newval, INSN_SIZE);
5504 buf += INSN_SIZE;
5505 newval = md_chars_to_number (buf, INSN_SIZE);
5506 off = fixp->fx_offset & 0xffff;
5507 newval |= ((off & 0x3fff) << 1);
5508 newval |= (((off >> 14) & 0x3) << 16);
5509 md_number_to_chars (buf, newval, INSN_SIZE);
5511 retval[1] = xmalloc (sizeof (arelent));
5512 retval[2] = NULL;
5513 retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5514 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5515 retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
5517 f = fixp->fx_frag;
5518 s = f->fr_symbol;
5519 e = s->sy_value;
5521 retval[1]->addend = 0;
5522 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
5523 assert (retval[1]->howto != NULL);
5525 fixp->fx_r_type = BFD_RELOC_HI16_S;
5528 code = fixp->fx_r_type;
5529 switch (fixp->fx_r_type)
5531 case BFD_RELOC_32:
5532 if (fixp->fx_pcrel)
5534 code = BFD_RELOC_32_PCREL;
5535 break;
5537 case BFD_RELOC_HI16_S:
5538 case BFD_RELOC_LO16:
5539 case BFD_RELOC_SCORE_JMP:
5540 case BFD_RELOC_SCORE_BRANCH:
5541 case BFD_RELOC_SCORE16_JMP:
5542 case BFD_RELOC_SCORE16_BRANCH:
5543 case BFD_RELOC_VTABLE_ENTRY:
5544 case BFD_RELOC_VTABLE_INHERIT:
5545 case BFD_RELOC_SCORE_GPREL15:
5546 case BFD_RELOC_SCORE_GOT15:
5547 case BFD_RELOC_SCORE_DUMMY_HI16:
5548 case BFD_RELOC_SCORE_GOT_LO16:
5549 case BFD_RELOC_SCORE_CALL15:
5550 case BFD_RELOC_GPREL32:
5551 case BFD_RELOC_NONE:
5552 code = fixp->fx_r_type;
5553 break;
5554 default:
5555 type = _("<unknown>");
5556 as_bad_where (fixp->fx_file, fixp->fx_line,
5557 _("cannot represent %s relocation in this object file format"), type);
5558 return NULL;
5561 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5562 if (reloc->howto == NULL)
5564 as_bad_where (fixp->fx_file, fixp->fx_line,
5565 _("cannot represent %s relocation in this object file format1"),
5566 bfd_get_reloc_code_name (code));
5567 return NULL;
5569 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5570 vtable entry to be used in the relocation's section offset. */
5571 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5572 reloc->address = fixp->fx_offset;
5574 return retval;
5577 void
5578 score_elf_final_processing (void)
5580 if (fix_data_dependency == 1)
5582 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
5584 if (score_pic == PIC)
5586 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
5590 static void
5591 parse_pce_inst (char *insnstr)
5593 char c;
5594 char *p;
5595 char first[MAX_LITERAL_POOL_SIZE];
5596 char second[MAX_LITERAL_POOL_SIZE];
5597 struct score_it pec_part_1;
5599 /* Get first part string of PCE. */
5600 p = strstr (insnstr, "||");
5601 c = *p;
5602 *p = '\0';
5603 sprintf (first, "%s", insnstr);
5605 /* Get second part string of PCE. */
5606 *p = c;
5607 p += 2;
5608 sprintf (second, "%s", p);
5610 parse_16_32_inst (first, FALSE);
5611 if (inst.error)
5612 return;
5614 memcpy (&pec_part_1, &inst, sizeof (inst));
5616 parse_16_32_inst (second, FALSE);
5617 if (inst.error)
5618 return;
5620 if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
5621 || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
5622 || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
5624 inst.error = _("pce instruction error (16 bit || 16 bit)'");
5625 sprintf (inst.str, "%s", insnstr);
5626 return;
5629 if (!inst.error)
5630 gen_insn_frag (&pec_part_1, &inst);
5633 void
5634 md_assemble (char *str)
5636 know (str);
5637 know (strlen (str) < MAX_LITERAL_POOL_SIZE);
5639 memset (&inst, '\0', sizeof (inst));
5640 if (INSN_IS_PCE_P (str))
5641 parse_pce_inst (str);
5642 else
5643 parse_16_32_inst (str, TRUE);
5645 if (inst.error)
5646 as_bad ("%s -- `%s'", inst.error, inst.str);
5649 /* We handle all bad expressions here, so that we can report the faulty
5650 instruction in the error message. */
5651 void
5652 md_operand (expressionS * expr)
5654 if (in_my_get_expression)
5656 expr->X_op = O_illegal;
5657 if (inst.error == NULL)
5659 inst.error = _("bad expression");
5664 const char *md_shortopts = "nO::g::G:";
5666 #ifdef SCORE_BI_ENDIAN
5667 #define OPTION_EB (OPTION_MD_BASE + 0)
5668 #define OPTION_EL (OPTION_MD_BASE + 1)
5669 #else
5670 #if TARGET_BYTES_BIG_ENDIAN
5671 #define OPTION_EB (OPTION_MD_BASE + 0)
5672 #else
5673 #define OPTION_EL (OPTION_MD_BASE + 1)
5674 #endif
5675 #endif
5676 #define OPTION_FIXDD (OPTION_MD_BASE + 2)
5677 #define OPTION_NWARN (OPTION_MD_BASE + 3)
5678 #define OPTION_SCORE5 (OPTION_MD_BASE + 4)
5679 #define OPTION_SCORE5U (OPTION_MD_BASE + 5)
5680 #define OPTION_SCORE7 (OPTION_MD_BASE + 6)
5681 #define OPTION_R1 (OPTION_MD_BASE + 7)
5682 #define OPTION_O0 (OPTION_MD_BASE + 8)
5683 #define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
5684 #define OPTION_PIC (OPTION_MD_BASE + 10)
5686 struct option md_longopts[] =
5688 #ifdef OPTION_EB
5689 {"EB" , no_argument, NULL, OPTION_EB},
5690 #endif
5691 #ifdef OPTION_EL
5692 {"EL" , no_argument, NULL, OPTION_EL},
5693 #endif
5694 {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
5695 {"NWARN" , no_argument, NULL, OPTION_NWARN},
5696 {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
5697 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
5698 {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
5699 {"USE_R1" , no_argument, NULL, OPTION_R1},
5700 {"O0" , no_argument, NULL, OPTION_O0},
5701 {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
5702 {"KPIC" , no_argument, NULL, OPTION_PIC},
5703 {NULL , no_argument, NULL, 0}
5706 size_t md_longopts_size = sizeof (md_longopts);
5709 md_parse_option (int c, char *arg)
5711 switch (c)
5713 #ifdef OPTION_EB
5714 case OPTION_EB:
5715 target_big_endian = 1;
5716 break;
5717 #endif
5718 #ifdef OPTION_EL
5719 case OPTION_EL:
5720 target_big_endian = 0;
5721 break;
5722 #endif
5723 case OPTION_FIXDD:
5724 fix_data_dependency = 1;
5725 break;
5726 case OPTION_NWARN:
5727 warn_fix_data_dependency = 0;
5728 break;
5729 case OPTION_SCORE5:
5730 score7 = 0;
5731 university_version = 0;
5732 vector_size = SCORE5_PIPELINE;
5733 break;
5734 case OPTION_SCORE5U:
5735 score7 = 0;
5736 university_version = 1;
5737 vector_size = SCORE5_PIPELINE;
5738 break;
5739 case OPTION_SCORE7:
5740 score7 = 1;
5741 university_version = 0;
5742 vector_size = SCORE7_PIPELINE;
5743 break;
5744 case OPTION_R1:
5745 nor1 = 0;
5746 break;
5747 case 'G':
5748 g_switch_value = atoi (arg);
5749 break;
5750 case OPTION_O0:
5751 g_opt = 0;
5752 break;
5753 case OPTION_SCORE_VERSION:
5754 printf (_("Sunplus-v2-0-0-20060510\n"));
5755 break;
5756 case OPTION_PIC:
5757 score_pic = PIC;
5758 g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */
5759 break;
5760 default:
5761 /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */
5762 return 0;
5764 return 1;
5767 void
5768 md_show_usage (FILE * fp)
5770 fprintf (fp, _(" Score-specific assembler options:\n"));
5771 #ifdef OPTION_EB
5772 fprintf (fp, _("\
5773 -EB\t\tassemble code for a big-endian cpu\n"));
5774 #endif
5776 #ifdef OPTION_EL
5777 fprintf (fp, _("\
5778 -EL\t\tassemble code for a little-endian cpu\n"));
5779 #endif
5781 fprintf (fp, _("\
5782 -FIXDD\t\tassemble code for fix data dependency\n"));
5783 fprintf (fp, _("\
5784 -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
5785 fprintf (fp, _("\
5786 -SCORE5\t\tassemble code for target is SCORE5\n"));
5787 fprintf (fp, _("\
5788 -SCORE5U\tassemble code for target is SCORE5U\n"));
5789 fprintf (fp, _("\
5790 -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
5791 fprintf (fp, _("\
5792 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
5793 fprintf (fp, _("\
5794 -KPIC\t\tassemble code for PIC\n"));
5795 fprintf (fp, _("\
5796 -O0\t\tassembler will not perform any optimizations\n"));
5797 fprintf (fp, _("\
5798 -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
5799 fprintf (fp, _("\
5800 -V \t\tSunplus release version \n"));
5804 /* Pesudo handling functions. */
5806 /* If we change section we must dump the literal pool first. */
5807 static void
5808 s_score_bss (int ignore ATTRIBUTE_UNUSED)
5810 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5811 demand_empty_rest_of_line ();
5814 static void
5815 s_score_text (int ignore)
5817 obj_elf_text (ignore);
5818 record_alignment (now_seg, 2);
5821 static void
5822 score_s_section (int ignore)
5824 obj_elf_section (ignore);
5825 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5826 record_alignment (now_seg, 2);
5830 static void
5831 s_change_sec (int sec)
5833 segT seg;
5835 #ifdef OBJ_ELF
5836 /* The ELF backend needs to know that we are changing sections, so
5837 that .previous works correctly. We could do something like check
5838 for an obj_section_change_hook macro, but that might be confusing
5839 as it would not be appropriate to use it in the section changing
5840 functions in read.c, since obj-elf.c intercepts those. FIXME:
5841 This should be cleaner, somehow. */
5842 obj_elf_section_change_hook ();
5843 #endif
5844 switch (sec)
5846 case 'r':
5847 seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5848 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5849 if (strcmp (TARGET_OS, "elf") != 0)
5850 record_alignment (seg, 4);
5851 demand_empty_rest_of_line ();
5852 break;
5853 case 's':
5854 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5855 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5856 if (strcmp (TARGET_OS, "elf") != 0)
5857 record_alignment (seg, 4);
5858 demand_empty_rest_of_line ();
5859 break;
5863 static void
5864 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5866 long mask, off;
5868 if (cur_proc_ptr == (procS *) NULL)
5870 as_warn (_(".mask outside of .ent"));
5871 demand_empty_rest_of_line ();
5872 return;
5874 if (get_absolute_expression_and_terminator (&mask) != ',')
5876 as_warn (_("Bad .mask directive"));
5877 --input_line_pointer;
5878 demand_empty_rest_of_line ();
5879 return;
5881 off = get_absolute_expression ();
5882 cur_proc_ptr->reg_mask = mask;
5883 cur_proc_ptr->reg_offset = off;
5884 demand_empty_rest_of_line ();
5887 static symbolS *
5888 get_symbol (void)
5890 int c;
5891 char *name;
5892 symbolS *p;
5894 name = input_line_pointer;
5895 c = get_symbol_end ();
5896 p = (symbolS *) symbol_find_or_make (name);
5897 *input_line_pointer = c;
5898 return p;
5901 static long
5902 get_number (void)
5904 int negative = 0;
5905 long val = 0;
5907 if (*input_line_pointer == '-')
5909 ++input_line_pointer;
5910 negative = 1;
5912 if (!ISDIGIT (*input_line_pointer))
5913 as_bad (_("expected simple number"));
5914 if (input_line_pointer[0] == '0')
5916 if (input_line_pointer[1] == 'x')
5918 input_line_pointer += 2;
5919 while (ISXDIGIT (*input_line_pointer))
5921 val <<= 4;
5922 val |= hex_value (*input_line_pointer++);
5924 return negative ? -val : val;
5926 else
5928 ++input_line_pointer;
5929 while (ISDIGIT (*input_line_pointer))
5931 val <<= 3;
5932 val |= *input_line_pointer++ - '0';
5934 return negative ? -val : val;
5937 if (!ISDIGIT (*input_line_pointer))
5939 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5940 as_warn (_("invalid number"));
5941 return -1;
5943 while (ISDIGIT (*input_line_pointer))
5945 val *= 10;
5946 val += *input_line_pointer++ - '0';
5948 return negative ? -val : val;
5951 /* The .aent and .ent directives. */
5953 static void
5954 s_score_ent (int aent)
5956 symbolS *symbolP;
5957 int maybe_text;
5959 symbolP = get_symbol ();
5960 if (*input_line_pointer == ',')
5961 ++input_line_pointer;
5962 SKIP_WHITESPACE ();
5963 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5964 get_number ();
5966 #ifdef BFD_ASSEMBLER
5967 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5968 maybe_text = 1;
5969 else
5970 maybe_text = 0;
5971 #else
5972 if (now_seg != data_section && now_seg != bss_section)
5973 maybe_text = 1;
5974 else
5975 maybe_text = 0;
5976 #endif
5977 if (!maybe_text)
5978 as_warn (_(".ent or .aent not in text section."));
5979 if (!aent && cur_proc_ptr)
5980 as_warn (_("missing .end"));
5981 if (!aent)
5983 cur_proc_ptr = &cur_proc;
5984 cur_proc_ptr->reg_mask = 0xdeadbeaf;
5985 cur_proc_ptr->reg_offset = 0xdeadbeaf;
5986 cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5987 cur_proc_ptr->leaf = 0xdeafbeaf;
5988 cur_proc_ptr->frame_offset = 0xdeafbeaf;
5989 cur_proc_ptr->frame_reg = 0xdeafbeaf;
5990 cur_proc_ptr->pc_reg = 0xdeafbeaf;
5991 cur_proc_ptr->isym = symbolP;
5992 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5993 ++numprocs;
5994 if (debug_type == DEBUG_STABS)
5995 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5997 demand_empty_rest_of_line ();
6000 static void
6001 s_score_frame (int ignore ATTRIBUTE_UNUSED)
6003 char *backupstr;
6004 char str[30];
6005 long val;
6006 int i = 0;
6008 backupstr = input_line_pointer;
6010 #ifdef OBJ_ELF
6011 if (cur_proc_ptr == (procS *) NULL)
6013 as_warn (_(".frame outside of .ent"));
6014 demand_empty_rest_of_line ();
6015 return;
6017 cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6018 SKIP_WHITESPACE ();
6019 skip_past_comma (&backupstr);
6020 while (*backupstr != ',')
6022 str[i] = *backupstr;
6023 i++;
6024 backupstr++;
6026 str[i] = '\0';
6027 val = atoi (str);
6029 SKIP_WHITESPACE ();
6030 skip_past_comma (&backupstr);
6031 cur_proc_ptr->frame_offset = val;
6032 cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6034 SKIP_WHITESPACE ();
6035 skip_past_comma (&backupstr);
6036 i = 0;
6037 while (*backupstr != '\n')
6039 str[i] = *backupstr;
6040 i++;
6041 backupstr++;
6043 str[i] = '\0';
6044 val = atoi (str);
6045 cur_proc_ptr->leaf = val;
6046 SKIP_WHITESPACE ();
6047 skip_past_comma (&backupstr);
6049 #endif /* OBJ_ELF */
6050 while (input_line_pointer != backupstr)
6051 input_line_pointer++;
6054 /* The .end directive. */
6055 static void
6056 s_score_end (int x ATTRIBUTE_UNUSED)
6058 symbolS *p;
6059 int maybe_text;
6061 /* Generate a .pdr section. */
6062 segT saved_seg = now_seg;
6063 subsegT saved_subseg = now_subseg;
6064 valueT dot;
6065 expressionS exp;
6066 char *fragp;
6068 if (!is_end_of_line[(unsigned char)*input_line_pointer])
6070 p = get_symbol ();
6071 demand_empty_rest_of_line ();
6073 else
6074 p = NULL;
6076 #ifdef BFD_ASSEMBLER
6077 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
6078 maybe_text = 1;
6079 else
6080 maybe_text = 0;
6081 #else
6082 if (now_seg != data_section && now_seg != bss_section)
6083 maybe_text = 1;
6084 else
6085 maybe_text = 0;
6086 #endif
6088 if (!maybe_text)
6089 as_warn (_(".end not in text section"));
6090 if (!cur_proc_ptr)
6092 as_warn (_(".end directive without a preceding .ent directive."));
6093 demand_empty_rest_of_line ();
6094 return;
6096 if (p != NULL)
6098 assert (S_GET_NAME (p));
6099 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
6100 as_warn (_(".end symbol does not match .ent symbol."));
6101 if (debug_type == DEBUG_STABS)
6102 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
6104 else
6105 as_warn (_(".end directive missing or unknown symbol"));
6107 if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
6108 (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
6109 (cur_proc_ptr->leaf == 0xdeafbeaf) ||
6110 (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
6111 (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
6113 else
6115 dot = frag_now_fix ();
6116 assert (pdr_seg);
6117 subseg_set (pdr_seg, 0);
6118 /* Write the symbol. */
6119 exp.X_op = O_symbol;
6120 exp.X_add_symbol = p;
6121 exp.X_add_number = 0;
6122 emit_expr (&exp, 4);
6123 fragp = frag_more (7 * 4);
6124 md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
6125 md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
6126 md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
6127 md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
6128 md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
6129 md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
6130 md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
6131 subseg_set (saved_seg, saved_subseg);
6134 cur_proc_ptr = NULL;
6137 /* Handle the .set pseudo-op. */
6138 static void
6139 s_score_set (int x ATTRIBUTE_UNUSED)
6141 int i = 0;
6142 char name[MAX_LITERAL_POOL_SIZE];
6143 char * orig_ilp = input_line_pointer;
6145 while (!is_end_of_line[(unsigned char)*input_line_pointer])
6147 name[i] = (char) * input_line_pointer;
6148 i++;
6149 ++input_line_pointer;
6152 name[i] = '\0';
6154 if (strcmp (name, "nwarn") == 0)
6156 warn_fix_data_dependency = 0;
6158 else if (strcmp (name, "fixdd") == 0)
6160 fix_data_dependency = 1;
6162 else if (strcmp (name, "nofixdd") == 0)
6164 fix_data_dependency = 0;
6166 else if (strcmp (name, "r1") == 0)
6168 nor1 = 0;
6170 else if (strcmp (name, "nor1") == 0)
6172 nor1 = 1;
6174 else if (strcmp (name, "optimize") == 0)
6176 g_opt = 1;
6178 else if (strcmp (name, "volatile") == 0)
6180 g_opt = 0;
6182 else if (strcmp (name, "pic") == 0)
6184 score_pic = PIC;
6186 else
6188 input_line_pointer = orig_ilp;
6189 s_set (0);
6193 /* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the
6194 $gp register for the function based on the function address, which is in the register
6195 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
6196 specially by the linker. The result is:
6197 ldis gp, %hi(GP_DISP_LABEL)
6198 ori gp, %low(GP_DISP_LABEL)
6199 add gp, gp, .cpload argument
6200 The .cpload argument is normally r29. */
6202 static void
6203 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6205 int reg;
6206 char insn_str[MAX_LITERAL_POOL_SIZE];
6208 /* If we are not generating PIC code, .cpload is ignored. */
6209 if (score_pic == NO_PIC)
6211 s_ignore (0);
6212 return;
6215 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6216 return;
6218 demand_empty_rest_of_line ();
6220 sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
6221 if (append_insn (insn_str, TRUE) == (int) FAIL)
6222 return;
6224 sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
6225 if (append_insn (insn_str, TRUE) == (int) FAIL)
6226 return;
6228 sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
6229 if (append_insn (insn_str, TRUE) == (int) FAIL)
6230 return;
6233 /* Handle the .cprestore pseudo-op. This stores $gp into a given
6234 offset from $sp. The offset is remembered, and after making a PIC
6235 call $gp is restored from that location. */
6237 static void
6238 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6240 int reg;
6241 int cprestore_offset;
6242 char insn_str[MAX_LITERAL_POOL_SIZE];
6244 /* If we are not generating PIC code, .cprestore is ignored. */
6245 if (score_pic == NO_PIC)
6247 s_ignore (0);
6248 return;
6251 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
6252 || skip_past_comma (&input_line_pointer) == (int) FAIL)
6254 return;
6257 cprestore_offset = get_absolute_expression ();
6259 if (cprestore_offset <= 0x3fff)
6261 sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
6262 if (append_insn (insn_str, TRUE) == (int) FAIL)
6263 return;
6265 else
6267 int r1_bak;
6269 r1_bak = nor1;
6270 nor1 = 0;
6272 sprintf (insn_str, "li r1, %d", cprestore_offset);
6273 if (append_insn (insn_str, TRUE) == (int) FAIL)
6274 return;
6276 sprintf (insn_str, "add r1, r1, r%d", reg);
6277 if (append_insn (insn_str, TRUE) == (int) FAIL)
6278 return;
6280 sprintf (insn_str, "sw r%d, [r1]", GP);
6281 if (append_insn (insn_str, TRUE) == (int) FAIL)
6282 return;
6284 nor1 = r1_bak;
6287 demand_empty_rest_of_line ();
6290 /* Handle the .gpword pseudo-op. This is used when generating PIC
6291 code. It generates a 32 bit GP relative reloc. */
6292 static void
6293 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6295 expressionS ex;
6296 char *p;
6298 /* When not generating PIC code, this is treated as .word. */
6299 if (score_pic == NO_PIC)
6301 cons (4);
6302 return;
6304 expression (&ex);
6305 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6307 as_bad (_("Unsupported use of .gpword"));
6308 ignore_rest_of_line ();
6310 p = frag_more (4);
6311 md_number_to_chars (p, (valueT) 0, 4);
6312 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6313 demand_empty_rest_of_line ();
6316 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
6317 tables in PIC code. */
6319 static void
6320 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6322 int reg;
6323 char insn_str[MAX_LITERAL_POOL_SIZE];
6325 /* If we are not generating PIC code, .cpload is ignored. */
6326 if (score_pic == NO_PIC)
6328 s_ignore (0);
6329 return;
6332 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6334 return;
6336 demand_empty_rest_of_line ();
6338 /* Add $gp to the register named as an argument. */
6339 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
6340 if (append_insn (insn_str, TRUE) == (int) FAIL)
6341 return;
6344 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6345 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6346 do \
6348 if ((SIZE) >= 8) \
6349 (P2VAR) = 3; \
6350 else if ((SIZE) >= 4) \
6351 (P2VAR) = 2; \
6352 else if ((SIZE) >= 2) \
6353 (P2VAR) = 1; \
6354 else \
6355 (P2VAR) = 0; \
6357 while (0)
6358 #endif
6360 static void
6361 s_score_lcomm (int bytes_p)
6363 char *name;
6364 char c;
6365 char *p;
6366 int temp;
6367 symbolS *symbolP;
6368 segT current_seg = now_seg;
6369 subsegT current_subseg = now_subseg;
6370 const int max_alignment = 15;
6371 int align = 0;
6372 segT bss_seg = bss_section;
6373 int needs_align = 0;
6375 name = input_line_pointer;
6376 c = get_symbol_end ();
6377 p = input_line_pointer;
6378 *p = c;
6380 if (name == p)
6382 as_bad (_("expected symbol name"));
6383 discard_rest_of_line ();
6384 return;
6387 SKIP_WHITESPACE ();
6389 /* Accept an optional comma after the name. The comma used to be
6390 required, but Irix 5 cc does not generate it. */
6391 if (*input_line_pointer == ',')
6393 ++input_line_pointer;
6394 SKIP_WHITESPACE ();
6397 if (is_end_of_line[(unsigned char)*input_line_pointer])
6399 as_bad (_("missing size expression"));
6400 return;
6403 if ((temp = get_absolute_expression ()) < 0)
6405 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6406 ignore_rest_of_line ();
6407 return;
6410 #if defined (TC_SCORE)
6411 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6413 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
6414 if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6416 bss_seg = subseg_new (".sbss", 1);
6417 seg_info (bss_seg)->bss = 1;
6418 #ifdef BFD_ASSEMBLER
6419 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6420 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6421 #endif
6424 #endif
6426 SKIP_WHITESPACE ();
6427 if (*input_line_pointer == ',')
6429 ++input_line_pointer;
6430 SKIP_WHITESPACE ();
6432 if (is_end_of_line[(unsigned char)*input_line_pointer])
6434 as_bad (_("missing alignment"));
6435 return;
6437 else
6439 align = get_absolute_expression ();
6440 needs_align = 1;
6444 if (!needs_align)
6446 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6448 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6449 if (align)
6450 record_alignment (bss_seg, align);
6453 if (needs_align)
6455 if (bytes_p)
6457 /* Convert to a power of 2. */
6458 if (align != 0)
6460 unsigned int i;
6462 for (i = 0; align != 0; align >>= 1, ++i)
6464 align = i - 1;
6468 if (align > max_alignment)
6470 align = max_alignment;
6471 as_warn (_("alignment too large; %d assumed"), align);
6473 else if (align < 0)
6475 align = 0;
6476 as_warn (_("alignment negative; 0 assumed"));
6479 record_alignment (bss_seg, align);
6481 else
6483 /* Assume some objects may require alignment on some systems. */
6484 #if defined (TC_ALPHA) && ! defined (VMS)
6485 if (temp > 1)
6487 align = ffs (temp) - 1;
6488 if (temp % (1 << align))
6489 abort ();
6491 #endif
6494 *p = 0;
6495 symbolP = symbol_find_or_make (name);
6496 *p = c;
6498 if (
6499 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6500 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6501 #ifdef BFD_ASSEMBLER
6502 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6503 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6504 #else
6505 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6506 #endif
6507 #endif
6508 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6510 char *pfrag;
6512 subseg_set (bss_seg, 1);
6514 if (align)
6515 frag_align (align, 0, 0);
6517 /* Detach from old frag. */
6518 if (S_GET_SEGMENT (symbolP) == bss_seg)
6519 symbol_get_frag (symbolP)->fr_symbol = NULL;
6521 symbol_set_frag (symbolP, frag_now);
6522 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6523 *pfrag = 0;
6526 S_SET_SEGMENT (symbolP, bss_seg);
6528 #ifdef OBJ_COFF
6529 /* The symbol may already have been created with a preceding
6530 ".globl" directive -- be careful not to step on storage class
6531 in that case. Otherwise, set it to static. */
6532 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6534 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6536 #endif /* OBJ_COFF */
6538 #ifdef S_SET_SIZE
6539 S_SET_SIZE (symbolP, temp);
6540 #endif
6542 else
6543 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6545 subseg_set (current_seg, current_subseg);
6547 demand_empty_rest_of_line ();
6550 static void
6551 insert_reg (const struct reg_entry *r, struct hash_control *htab)
6553 int i = 0;
6554 int len = strlen (r->name) + 2;
6555 char *buf = xmalloc (len);
6556 char *buf2 = xmalloc (len);
6558 strcpy (buf + i, r->name);
6559 for (i = 0; buf[i]; i++)
6561 buf2[i] = TOUPPER (buf[i]);
6563 buf2[i] = '\0';
6565 hash_insert (htab, buf, (void *) r);
6566 hash_insert (htab, buf2, (void *) r);
6569 static void
6570 build_reg_hsh (struct reg_map *map)
6572 const struct reg_entry *r;
6574 if ((map->htab = hash_new ()) == NULL)
6576 as_fatal (_("virtual memory exhausted"));
6578 for (r = map->names; r->name != NULL; r++)
6580 insert_reg (r, map->htab);
6584 void
6585 md_begin (void)
6587 unsigned int i;
6588 segT seg;
6589 subsegT subseg;
6591 if ((score_ops_hsh = hash_new ()) == NULL)
6592 as_fatal (_("virtual memory exhausted"));
6594 build_score_ops_hsh ();
6596 if ((dependency_insn_hsh = hash_new ()) == NULL)
6597 as_fatal (_("virtual memory exhausted"));
6599 build_dependency_insn_hsh ();
6601 for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
6602 build_reg_hsh (all_reg_maps + i);
6604 /* Initialize dependency vector. */
6605 init_dependency_vector ();
6607 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6608 seg = now_seg;
6609 subseg = now_subseg;
6610 pdr_seg = subseg_new (".pdr", (subsegT) 0);
6611 (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6612 (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
6613 subseg_set (seg, subseg);
6615 if (USE_GLOBAL_POINTER_OPT)
6616 bfd_set_gp_size (stdoutput, g_switch_value);
6620 const pseudo_typeS md_pseudo_table[] =
6622 {"bss", s_score_bss, 0},
6623 {"text", s_score_text, 0},
6624 {"word", cons, 4},
6625 {"long", cons, 4},
6626 {"extend", float_cons, 'x'},
6627 {"ldouble", float_cons, 'x'},
6628 {"packed", float_cons, 'p'},
6629 {"end", s_score_end, 0},
6630 {"ent", s_score_ent, 0},
6631 {"frame", s_score_frame, 0},
6632 {"rdata", s_change_sec, 'r'},
6633 {"sdata", s_change_sec, 's'},
6634 {"set", s_score_set, 0},
6635 {"mask", s_score_mask, 'R'},
6636 {"dword", cons, 8},
6637 {"lcomm", s_score_lcomm, 1},
6638 {"section", score_s_section, 0},
6639 {"cpload", s_score_cpload, 0},
6640 {"cprestore", s_score_cprestore, 0},
6641 {"gpword", s_score_gpword, 0},
6642 {"cpadd", s_score_cpadd, 0},
6643 {0, 0, 0}