1 /* tc-score7.c -- Assembler for Score7
2 Copyright (C) 2009-2022 Free Software Foundation, Inc.
4 Brain.lin (brain.lin@sunplusct.com)
5 Mei Ligang (ligang@sunnorth.com.cn)
6 Pei-Lin Tsai (pltsai@sunplus.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
28 #include "safe-ctype.h"
29 #include "opcode/score-inst.h"
30 #include "libiberty.h"
33 #include "elf/score.h"
34 #include "dwarf2dbg.h"
37 static void s7_do_ldst_insn (char *);
38 static void s7_do_crdcrscrsimm5 (char *);
39 static void s7_do_ldst_unalign (char *);
40 static void s7_do_ldst_atomic (char *);
41 static void s7_do_ldst_cop (char *);
42 static void s7_do_macro_li_rdi32 (char *);
43 static void s7_do_macro_la_rdi32 (char *);
44 static void s7_do_macro_rdi32hi (char *);
45 static void s7_do_macro_rdi32lo (char *);
46 static void s7_do_macro_mul_rdrsrs (char *);
47 static void s7_do_macro_ldst_label (char *);
48 static void s7_do_branch (char *);
49 static void s7_do_jump (char *);
50 static void s7_do_empty (char *);
51 static void s7_do_rdrsrs (char *);
52 static void s7_do_rdsi16 (char *);
53 static void s7_do_rdrssi14 (char *);
54 static void s7_do_sub_rdsi16 (char *);
55 static void s7_do_sub_rdrssi14 (char *);
56 static void s7_do_rdrsi5 (char *);
57 static void s7_do_rdrsi14 (char *);
58 static void s7_do_rdi16 (char *);
59 static void s7_do_xrsi5 (char *);
60 static void s7_do_rdrs (char *);
61 static void s7_do_rdxrs (char *);
62 static void s7_do_rsrs (char *);
63 static void s7_do_rdcrs (char *);
64 static void s7_do_rdsrs (char *);
65 static void s7_do_rd (char *);
66 static void s7_do_rs (char *);
67 static void s7_do_i15 (char *);
68 static void s7_do_xi5x (char *);
69 static void s7_do_ceinst (char *);
70 static void s7_do_cache (char *);
71 static void s7_do16_rdrs (char *);
72 static void s7_do16_rs (char *);
73 static void s7_do16_xrs (char *);
74 static void s7_do16_mv_rdrs (char *);
75 static void s7_do16_hrdrs (char *);
76 static void s7_do16_rdhrs (char *);
77 static void s7_do16_rdi4 (char *);
78 static void s7_do16_rdi5 (char *);
79 static void s7_do16_xi5 (char *);
80 static void s7_do16_ldst_insn (char *);
81 static void s7_do16_ldst_imm_insn (char *);
82 static void s7_do16_push_pop (char *);
83 static void s7_do16_branch (char *);
84 static void s7_do16_jump (char *);
85 static void s7_do_rdi16_pic (char *);
86 static void s7_do_addi_s_pic (char *);
87 static void s7_do_addi_u_pic (char *);
88 static void s7_do_lw_pic (char *);
91 #define s7_PIC_CALL_REG 29
92 #define s7_MAX_LITERAL_POOL_SIZE 1024
93 #define s7_FAIL 0x80000000
95 #define s7_INSN_SIZE 4
96 #define s7_INSN16_SIZE 2
97 #define s7_RELAX_INST_NUM 3
99 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
100 #define s7_BAD_ARGS _("bad arguments to instruction")
101 #define s7_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
102 #define s7_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
103 #define s7_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
104 #define s7_BAD_SKIP_COMMA s7_BAD_ARGS
105 #define s7_BAD_GARBAGE _("garbage following instruction");
107 #define s7_skip_whitespace(str) while (*(str) == ' ') ++(str)
109 /* The name of the readonly data section. */
110 #define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
112 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
114 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
116 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
120 #define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
129 #define s7_RELAX_OLD(i) (((i) >> 23) & 0x7f)
130 #define s7_RELAX_NEW(i) (((i) >> 16) & 0x7f)
131 #define s7_RELAX_TYPE(i) (((i) >> 9) & 0x7f)
132 #define s7_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
133 #define s7_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
134 #define s7_RELAX_OPT(i) ((i) & 1)
135 #define s7_RELAX_OPT_CLEAR(i) ((i) & ~1)
137 #define s7_SET_INSN_ERROR(s) (s7_inst.error = (s))
138 #define s7_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
140 #define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type))
142 #define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \
143 ? s7_INSN16_SIZE : s7_INSN_SIZE)
145 #define s7_INSN_NAME_LEN 16
147 /* Relax will need some padding for alignment. */
148 #define s7_RELAX_PAD_BYTE 3
150 #define s7_USE_GLOBAL_POINTER_OPT 1
154 /* Enumeration matching entries in table above. */
155 enum s7_score_reg_type
157 s7_REG_TYPE_SCORE
= 0,
158 #define REG_TYPE_FIRST s7_REG_TYPE_SCORE
159 s7_REG_TYPE_SCORE_SR
= 1,
160 s7_REG_TYPE_SCORE_CR
= 2,
164 enum s7_score_pic_level
169 static enum s7_score_pic_level s7_score_pic
= s7_NO_PIC
;
171 enum s7_insn_type_for_dependency
190 struct s7_insn_to_dependency
192 const char *insn_name
;
193 enum s7_insn_type_for_dependency type
;
196 struct s7_data_dependency
198 enum s7_insn_type_for_dependency pre_insn_type
;
200 enum s7_insn_type_for_dependency cur_insn_type
;
204 int warn_or_error
; /* warning - 0; error - 1 */
207 static const struct s7_insn_to_dependency s7_insn_to_dependency_table
[] =
209 /* pce instruction. */
211 /* conditional branch instruction. */
212 {"bcs", s7_D_cond_br
},
213 {"bcc", s7_D_cond_br
},
214 {"bgtu", s7_D_cond_br
},
215 {"bleu", s7_D_cond_br
},
216 {"beq", s7_D_cond_br
},
217 {"bne", s7_D_cond_br
},
218 {"bgt", s7_D_cond_br
},
219 {"ble", s7_D_cond_br
},
220 {"bge", s7_D_cond_br
},
221 {"blt", s7_D_cond_br
},
222 {"bmi", s7_D_cond_br
},
223 {"bpl", s7_D_cond_br
},
224 {"bvs", s7_D_cond_br
},
225 {"bvc", s7_D_cond_br
},
226 {"bcsl", s7_D_cond_br
},
227 {"bccl", s7_D_cond_br
},
228 {"bgtul", s7_D_cond_br
},
229 {"bleul", s7_D_cond_br
},
230 {"beql", s7_D_cond_br
},
231 {"bnel", s7_D_cond_br
},
232 {"bgtl", s7_D_cond_br
},
233 {"blel", s7_D_cond_br
},
234 {"bgel", s7_D_cond_br
},
235 {"bltl", s7_D_cond_br
},
236 {"bmil", s7_D_cond_br
},
237 {"bpll", s7_D_cond_br
},
238 {"bvsl", s7_D_cond_br
},
239 {"bvcl", s7_D_cond_br
},
240 {"bcs!", s7_D_cond_br
},
241 {"bcc!", s7_D_cond_br
},
242 {"bgtu!", s7_D_cond_br
},
243 {"bleu!", s7_D_cond_br
},
244 {"beq!", s7_D_cond_br
},
245 {"bne!", s7_D_cond_br
},
246 {"bgt!", s7_D_cond_br
},
247 {"ble!", s7_D_cond_br
},
248 {"bge!", s7_D_cond_br
},
249 {"blt!", s7_D_cond_br
},
250 {"bmi!", s7_D_cond_br
},
251 {"bpl!", s7_D_cond_br
},
252 {"bvs!", s7_D_cond_br
},
253 {"bvc!", s7_D_cond_br
},
254 {"brcs", s7_D_cond_br
},
255 {"brcc", s7_D_cond_br
},
256 {"brgtu", s7_D_cond_br
},
257 {"brleu", s7_D_cond_br
},
258 {"breq", s7_D_cond_br
},
259 {"brne", s7_D_cond_br
},
260 {"brgt", s7_D_cond_br
},
261 {"brle", s7_D_cond_br
},
262 {"brge", s7_D_cond_br
},
263 {"brlt", s7_D_cond_br
},
264 {"brmi", s7_D_cond_br
},
265 {"brpl", s7_D_cond_br
},
266 {"brvs", s7_D_cond_br
},
267 {"brvc", s7_D_cond_br
},
268 {"brcsl", s7_D_cond_br
},
269 {"brccl", s7_D_cond_br
},
270 {"brgtul", s7_D_cond_br
},
271 {"brleul", s7_D_cond_br
},
272 {"breql", s7_D_cond_br
},
273 {"brnel", s7_D_cond_br
},
274 {"brgtl", s7_D_cond_br
},
275 {"brlel", s7_D_cond_br
},
276 {"brgel", s7_D_cond_br
},
277 {"brltl", s7_D_cond_br
},
278 {"brmil", s7_D_cond_br
},
279 {"brpll", s7_D_cond_br
},
280 {"brvsl", s7_D_cond_br
},
281 {"brvcl", s7_D_cond_br
},
282 {"brcs!", s7_D_cond_br
},
283 {"brcc!", s7_D_cond_br
},
284 {"brgtu!", s7_D_cond_br
},
285 {"brleu!", s7_D_cond_br
},
286 {"breq!", s7_D_cond_br
},
287 {"brne!", s7_D_cond_br
},
288 {"brgt!", s7_D_cond_br
},
289 {"brle!", s7_D_cond_br
},
290 {"brge!", s7_D_cond_br
},
291 {"brlt!", s7_D_cond_br
},
292 {"brmi!", s7_D_cond_br
},
293 {"brpl!", s7_D_cond_br
},
294 {"brvs!", s7_D_cond_br
},
295 {"brvc!", s7_D_cond_br
},
296 {"brcsl!", s7_D_cond_br
},
297 {"brccl!", s7_D_cond_br
},
298 {"brgtul!", s7_D_cond_br
},
299 {"brleul!", s7_D_cond_br
},
300 {"breql!", s7_D_cond_br
},
301 {"brnel!", s7_D_cond_br
},
302 {"brgtl!", s7_D_cond_br
},
303 {"brlel!", s7_D_cond_br
},
304 {"brgel!", s7_D_cond_br
},
305 {"brltl!", s7_D_cond_br
},
306 {"brmil!", s7_D_cond_br
},
307 {"brpll!", s7_D_cond_br
},
308 {"brvsl!", s7_D_cond_br
},
309 {"brvcl!", s7_D_cond_br
},
310 /* conditional move instruction. */
311 {"mvcs", s7_D_cond_mv
},
312 {"mvcc", s7_D_cond_mv
},
313 {"mvgtu", s7_D_cond_mv
},
314 {"mvleu", s7_D_cond_mv
},
315 {"mveq", s7_D_cond_mv
},
316 {"mvne", s7_D_cond_mv
},
317 {"mvgt", s7_D_cond_mv
},
318 {"mvle", s7_D_cond_mv
},
319 {"mvge", s7_D_cond_mv
},
320 {"mvlt", s7_D_cond_mv
},
321 {"mvmi", s7_D_cond_mv
},
322 {"mvpl", s7_D_cond_mv
},
323 {"mvvs", s7_D_cond_mv
},
324 {"mvvc", s7_D_cond_mv
},
325 /* move special instruction. */
327 {"mftlb", s7_D_mftlb
},
328 {"mtptlb", s7_D_mtptlb
},
329 {"mtrtlb", s7_D_mtrtlb
},
333 /* cache instruction. */
334 {"cache 8", s7_D_cached
},
335 {"cache 9", s7_D_cached
},
336 {"cache 10", s7_D_cached
},
337 {"cache 11", s7_D_cached
},
338 {"cache 12", s7_D_cached
},
339 {"cache 13", s7_D_cached
},
340 {"cache 14", s7_D_cached
},
341 {"cache 24", s7_D_cached
},
342 {"cache 26", s7_D_cached
},
343 {"cache 27", s7_D_cached
},
344 {"cache 29", s7_D_cached
},
345 {"cache 30", s7_D_cached
},
346 {"cache 31", s7_D_cached
},
347 {"cache 0", s7_D_cachei
},
348 {"cache 1", s7_D_cachei
},
349 {"cache 2", s7_D_cachei
},
350 {"cache 3", s7_D_cachei
},
351 {"cache 4", s7_D_cachei
},
352 {"cache 16", s7_D_cachei
},
353 {"cache 17", s7_D_cachei
},
354 /* load/store instruction. */
358 {"lbup!", s7_D_ldst
},
377 {"push!", s7_D_ldst
},
378 {"pushhi!", s7_D_ldst
},
380 {"pophi!", s7_D_ldst
},
390 /* load combine instruction. */
391 {"lcb", s7_D_ldcombine
},
392 {"lcw", s7_D_ldcombine
},
393 {"lce", s7_D_ldcombine
},
396 static const struct s7_data_dependency s7_data_dependency_table
[] =
398 /* Condition register. */
399 {s7_D_mtcr
, "cr1", s7_D_pce
, "", 2, 1, 0},
400 {s7_D_mtcr
, "cr1", s7_D_cond_br
, "", 1, 0, 1},
401 {s7_D_mtcr
, "cr1", s7_D_cond_mv
, "", 1, 0, 1},
402 /* Status register. */
403 {s7_D_mtcr
, "cr0", s7_D_all_insn
, "", 5, 4, 0},
405 {s7_D_mtcr
, "cr4", s7_D_all_insn
, "", 6, 5, 0},
406 /* EntryHi/EntryLo register. */
407 {s7_D_mftlb
, "", s7_D_mtptlb
, "", 1, 1, 1},
408 {s7_D_mftlb
, "", s7_D_mtrtlb
, "", 1, 1, 1},
409 {s7_D_mftlb
, "", s7_D_stlb
, "", 1, 1,1},
410 {s7_D_mftlb
, "", s7_D_mfcr
, "cr11", 1, 1, 1},
411 {s7_D_mftlb
, "", s7_D_mfcr
, "cr12", 1, 1, 1},
412 /* Index register. */
413 {s7_D_stlb
, "", s7_D_mtptlb
, "", 1, 1, 1},
414 {s7_D_stlb
, "", s7_D_mftlb
, "", 1, 1, 1},
415 {s7_D_stlb
, "", s7_D_mfcr
, "cr8", 2, 2, 1},
417 {s7_D_cached
, "", s7_D_ldst
, "", 1, 1, 0},
418 {s7_D_cached
, "", s7_D_ldcombine
, "", 1, 1, 0},
419 {s7_D_cachei
, "", s7_D_all_insn
, "", 5, 4, 0},
421 {s7_D_ldcombine
, "", s7_D_mfsr
, "sr1", 3, 3, 1},
426 /* Used to contain constructed error messages. */
427 static char s7_err_msg
[255];
428 static int s7_fix_data_dependency
= 0;
429 static int s7_warn_fix_data_dependency
= 1;
431 static int s7_in_my_get_expression
= 0;
433 /* Default, pop warning message when using r1. */
434 static int s7_nor1
= 1;
436 /* Default will do instruction relax, -O0 will set s7_g_opt = 0. */
437 static unsigned int s7_g_opt
= 1;
439 /* The size of the small data section. */
440 static unsigned int s7_g_switch_value
= 8;
442 static segT s7_pdr_seg
;
446 char name
[s7_INSN_NAME_LEN
];
447 unsigned long instruction
;
448 unsigned long relax_inst
;
451 enum score_insn_type type
;
452 char str
[s7_MAX_LITERAL_POOL_SIZE
];
455 char reg
[s7_INSN_NAME_LEN
];
458 bfd_reloc_code_real_type type
;
463 static struct s7_score_it s7_inst
;
468 unsigned long reg_mask
;
469 unsigned long reg_offset
;
470 unsigned long fpreg_mask
;
472 unsigned long frame_offset
;
473 unsigned long frame_reg
;
474 unsigned long pc_reg
;
476 static s7_procS s7_cur_proc
;
477 static s7_procS
*s7_cur_proc_ptr
;
478 static int s7_numprocs
;
480 /* Structure for a hash table entry for a register. */
487 static const struct s7_reg_entry s7_score_rn_table
[] =
489 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
490 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
491 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
492 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
493 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
494 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
495 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
496 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
500 static const struct s7_reg_entry s7_score_srn_table
[] =
502 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
506 static const struct s7_reg_entry s7_score_crn_table
[] =
508 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
509 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
510 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
511 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
512 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
513 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
514 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
515 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
521 const struct s7_reg_entry
*names
;
524 const char *expected
;
527 static struct s7_reg_map s7_all_reg_maps
[] =
529 {s7_score_rn_table
, 31, NULL
, N_("S+core register expected")},
530 {s7_score_srn_table
, 2, NULL
, N_("S+core special-register expected")},
531 {s7_score_crn_table
, 31, NULL
, N_("S+core co-processor register expected")},
534 static htab_t s7_score_ops_hsh
= NULL
;
535 static htab_t s7_dependency_insn_hsh
= NULL
;
538 struct s7_datafield_range
545 static struct s7_datafield_range s7_score_df_range
[] =
547 {_IMM4
, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */
548 {_IMM5
, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */
549 {_IMM8
, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */
550 {_IMM14
, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */
551 {_IMM15
, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
552 {_IMM16
, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
553 {_SIMM10
, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */
554 {_SIMM12
, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */
555 {_SIMM14
, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */
556 {_SIMM15
, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */
557 {_SIMM16
, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
558 {_SIMM14_NEG
, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */
559 {_IMM16_NEG
, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */
560 {_SIMM16_NEG
, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
561 {_IMM20
, 20, {0, (1 << 20) - 1}},
562 {_IMM25
, 25, {0, (1 << 25) - 1}},
563 {_DISP8div2
, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */
564 {_DISP11div2
, 11, {0, 0}},
565 {_DISP19div2
, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */
566 {_DISP24div2
, 24, {0, 0}},
567 {_VALUE
, 32, {0, ((unsigned int)1 << 31) - 1}},
568 {_VALUE_HI16
, 16, {0, (1 << 16) - 1}},
569 {_VALUE_LO16
, 16, {0, (1 << 16) - 1}},
570 {_VALUE_LDST_LO16
, 16, {0, (1 << 16) - 1}},
571 {_SIMM16_LA
, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
572 {_IMM5_RSHIFT_1
, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */
573 {_IMM5_RSHIFT_2
, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */
574 {_SIMM16_LA_POS
, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
575 {_IMM5_RANGE_8_31
, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */
576 {_IMM10_RSHIFT_2
, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */
577 {_SIMM10
, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */
578 {_SIMM12
, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */
579 {_SIMM14
, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */
580 {_SIMM15
, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */
581 {_SIMM16
, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */
582 {_SIMM14_NEG
, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */
583 {_IMM16_NEG
, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
584 {_SIMM16_NEG
, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
585 {_IMM20
, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */
586 {_IMM25
, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */
587 {_GP_IMM15
, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */
588 {_GP_IMM14
, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */
589 {_SIMM16_pic
, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
590 {_IMM16_LO16_pic
, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
591 {_IMM16_pic
, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
597 /* Instruction name. */
598 const char *template_name
;
600 /* Instruction Opcode. */
603 /* Instruction bit mask. */
606 /* Relax instruction opcode. 0x8000 imply no relaxation. */
609 /* Instruction type. */
610 enum score_insn_type type
;
612 /* Function to call to parse args. */
613 void (*parms
) (char *);
616 static const struct s7_asm_opcode s7_score_ldst_insns
[] =
618 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15
, s7_do_ldst_insn
},
619 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12
, s7_do_ldst_insn
},
620 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12
, s7_do_ldst_insn
},
621 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15
, s7_do_ldst_insn
},
622 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12
, s7_do_ldst_insn
},
623 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12
, s7_do_ldst_insn
},
624 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15
, s7_do_ldst_insn
},
625 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12
, s7_do_ldst_insn
},
626 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12
, s7_do_ldst_insn
},
627 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15
, s7_do_ldst_insn
},
628 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12
, s7_do_ldst_insn
},
629 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12
, s7_do_ldst_insn
},
630 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15
, s7_do_ldst_insn
},
631 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12
, s7_do_ldst_insn
},
632 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12
, s7_do_ldst_insn
},
633 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15
, s7_do_ldst_insn
},
634 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12
, s7_do_ldst_insn
},
635 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12
, s7_do_ldst_insn
},
636 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15
, s7_do_ldst_insn
},
637 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12
, s7_do_ldst_insn
},
638 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12
, s7_do_ldst_insn
},
639 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15
, s7_do_ldst_insn
},
640 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12
, s7_do_ldst_insn
},
641 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12
, s7_do_ldst_insn
},
644 static const struct s7_asm_opcode s7_score_insns
[] =
646 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
647 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
648 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
649 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs
, s7_do_rdrsrs
},
650 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
651 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
652 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs
, s7_do_rdrsrs
},
653 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_rdsi16
},
654 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_rdsi16
},
655 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_rdi16
},
656 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_rdi16
},
657 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14
, s7_do_rdrssi14
},
658 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14
, s7_do_rdrssi14
},
659 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs
, s7_do16_rdrs
},
660 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs
, s7_do16_rdrs
},
661 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4
, s7_do16_rdi4
},
662 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_sub_rdsi16
},
663 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_sub_rdsi16
},
664 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14
, s7_do_sub_rdrssi14
},
665 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14
, s7_do_sub_rdrssi14
},
666 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
667 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs
, s7_do_rdrsrs
},
668 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
669 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
670 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
671 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
672 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14
, s7_do_rdrsi14
},
673 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14
, s7_do_rdrsi14
},
674 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs
, s7_do16_rdrs
},
675 {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
676 {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
677 {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
678 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
679 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
680 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
681 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2
, s7_do16_branch
},
682 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2
, s7_do16_branch
},
683 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2
, s7_do16_branch
},
684 {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
685 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
686 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2
, s7_do16_branch
},
687 {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
688 {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
689 {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
690 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
691 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
692 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
693 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2
, s7_do16_branch
},
694 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2
, s7_do16_branch
},
695 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2
, s7_do16_branch
},
696 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5
, s7_do_rdrsi5
},
697 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
698 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5
, s7_do_rdrsi5
},
699 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5
, s7_do_xrsi5
},
700 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5
, s7_do_rdrsi5
},
701 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5
, s7_do16_rdi5
},
702 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5
, s7_do16_rdi5
},
703 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5
, s7_do16_rdi5
},
704 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5
, s7_do16_rdi5
},
705 {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
706 {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
707 {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
708 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
709 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
710 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
711 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
712 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2
, s7_do16_branch
},
713 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2
, s7_do16_branch
},
714 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2
, s7_do16_branch
},
715 {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
716 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
717 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2
, s7_do16_branch
},
718 {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
719 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
720 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2
, s7_do16_branch
},
721 {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
722 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
723 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2
, s7_do16_branch
},
724 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x
, s7_do_rs
},
725 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x
, s7_do_rs
},
726 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x
, s7_do_rs
},
727 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x
, s7_do_rs
},
728 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x
, s7_do_rs
},
729 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x
, s7_do_rs
},
730 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x
, s7_do_rs
},
731 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x
, s7_do_rs
},
732 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x
, s7_do_rs
},
733 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x
, s7_do_rs
},
734 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x
, s7_do_rs
},
735 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x
, s7_do_rs
},
736 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x
, s7_do_rs
},
737 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x
, s7_do_rs
},
738 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x
, s7_do_rs
},
739 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x
, s7_do_rs
},
740 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x
, s7_do_rs
},
741 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x
, s7_do_rs
},
742 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x
, s7_do_rs
},
743 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x
, s7_do_rs
},
744 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x
, s7_do_rs
},
745 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x
, s7_do_rs
},
746 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x
, s7_do_rs
},
747 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x
, s7_do_rs
},
748 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x
, s7_do_rs
},
749 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x
, s7_do_rs
},
750 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x
, s7_do_rs
},
751 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x
, s7_do_rs
},
752 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x
, s7_do_rs
},
753 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x
, s7_do_rs
},
754 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x
, s7_do_rs
},
755 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x
, s7_do_rs
},
756 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs
, s7_do16_xrs
},
757 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs
, s7_do16_xrs
},
758 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs
, s7_do16_xrs
},
759 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs
, s7_do16_xrs
},
760 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs
, s7_do16_xrs
},
761 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs
, s7_do16_xrs
},
762 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs
, s7_do16_xrs
},
763 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs
, s7_do16_xrs
},
764 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs
, s7_do16_xrs
},
765 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs
, s7_do16_xrs
},
766 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs
, s7_do16_xrs
},
767 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs
, s7_do16_xrs
},
768 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs
, s7_do16_xrs
},
769 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs
, s7_do16_xrs
},
770 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs
, s7_do16_xrs
},
771 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs
, s7_do16_xrs
},
772 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs
, s7_do16_xrs
},
773 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs
, s7_do16_xrs
},
774 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs
, s7_do16_xrs
},
775 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs
, s7_do16_xrs
},
776 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs
, s7_do16_xrs
},
777 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs
, s7_do16_xrs
},
778 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs
, s7_do16_xrs
},
779 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs
, s7_do16_xrs
},
780 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs
, s7_do16_xrs
},
781 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs
, s7_do16_xrs
},
782 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs
, s7_do16_xrs
},
783 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs
, s7_do16_xrs
},
784 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs
, s7_do16_xrs
},
785 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs
, s7_do16_xrs
},
786 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs
, s7_do16_xrs
},
787 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs
, s7_do16_xrs
},
788 {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
789 {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
790 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
791 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2
, s7_do_branch
},
792 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2
, s7_do16_branch
},
793 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2
, s7_do16_branch
},
794 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2
, s7_do16_branch
},
795 {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2
, s7_do_branch
},
796 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15
, s7_do_cache
},
797 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5
, s7_do_ceinst
},
798 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
799 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
800 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
801 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs
, s7_do_rsrs
},
802 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x
, s7_do_rs
},
803 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x
, s7_do_rs
},
804 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x
, s7_do_rs
},
805 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16
, s7_do_rdsi16
},
806 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs
, s7_do16_rdrs
},
807 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm
, s7_do_crdcrscrsimm5
},
808 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm
, s7_do_crdcrscrsimm5
},
809 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm
, s7_do_crdcrscrsimm5
},
810 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
811 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
812 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
813 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
814 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
815 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
816 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
817 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
818 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
819 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2
, s7_do_jump
},
820 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2
, s7_do16_jump
},
821 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2
, s7_do16_jump
},
822 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2
, s7_do_jump
},
823 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs
, s7_do16_ldst_insn
},
824 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5
, s7_do16_ldst_imm_insn
},
825 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs
, s7_do_ldst_atomic
},
826 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4
, s7_do_ldst_unalign
},
827 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4
, s7_do_ldst_unalign
},
828 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4
, s7_do_ldst_unalign
},
829 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10
, s7_do_ldst_cop
},
830 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10
, s7_do_ldst_cop
},
831 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10
, s7_do_ldst_cop
},
832 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs
, s7_do16_ldst_insn
},
833 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5
, s7_do16_ldst_imm_insn
},
834 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16
, s7_do_rdsi16
},
835 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16
, s7_do_rdi16
},
836 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8
, s7_do16_ldst_imm_insn
},
837 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs
, s7_do16_ldst_insn
},
838 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5
, s7_do16_ldst_imm_insn
},
839 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x
, s7_do_rd
},
840 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs
, s7_do16_rs
},
841 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
842 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs
, s7_do16_rdrs
},
843 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
844 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
845 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs
, s7_do16_rdrs
},
846 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
847 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
848 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs
, s7_do16_rdrs
},
849 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
850 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs
, s7_do16_rdrs
},
851 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
852 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
853 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
854 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
855 {"mazh.f!", 0x1009, 0x700f, 0x38000383, Rd_Rs
, s7_do16_rdrs
},
856 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
857 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
858 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs
, s7_do16_rdrs
},
859 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x
, s7_do_rd
},
860 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs
, s7_do16_rs
},
861 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
862 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5
, s7_do_rdsrs
},
863 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
864 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
865 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
866 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
867 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
868 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
869 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
870 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs
, s7_do16_hrdrs
},
871 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
872 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs
, s7_do16_rdhrs
},
873 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
874 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs
, s7_do16_rdrs
},
875 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
876 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
877 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs
, s7_do16_rdrs
},
878 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
879 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
880 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs
, s7_do16_rdrs
},
881 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
882 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs
, s7_do16_rdrs
},
883 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
884 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
885 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
886 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs
, s7_do16_rdrs
},
887 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
888 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs
, s7_do_rsrs
},
889 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs
, s7_do16_rdrs
},
890 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs
, s7_do16_rs
},
891 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x
, s7_do_rd
},
892 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x
, s7_do_rd
},
893 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs
, s7_do16_rs
},
894 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
895 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5
, s7_do_rdsrs
},
896 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
897 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
898 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
899 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
900 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
901 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
902 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x
, s7_do_rdcrs
},
903 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs
, s7_do16_rdrs
},
904 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs
, s7_do16_rdrs
},
905 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
906 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
907 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
908 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
909 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
910 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
911 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
912 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
913 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
914 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
915 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
916 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
917 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
918 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
919 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x
, s7_do_rdrs
},
920 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs
, s7_do16_mv_rdrs
},
921 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs
, s7_do_rdxrs
},
922 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs
, s7_do_rdxrs
},
923 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs
, s7_do16_rdrs
},
924 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD
, s7_do_empty
},
925 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x
, s7_do_rdrs
},
926 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x
, s7_do_rdrs
},
927 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD
, s7_do_empty
},
928 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs
, s7_do16_rdrs
},
929 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
930 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs
, s7_do_rdrsrs
},
931 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
932 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
933 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
934 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16
, s7_do_rdi16
},
935 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14
, s7_do_rdrsi14
},
936 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14
, s7_do_rdrsi14
},
937 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs
, s7_do16_rdrs
},
938 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
939 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs
, s7_do16_push_pop
},
940 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs
, s7_do16_push_pop
},
941 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
942 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
943 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
944 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
945 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
946 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
947 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
948 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
949 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
950 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
951 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
952 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
953 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
954 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs
, s7_do16_ldst_insn
},
955 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5
, s7_do16_ldst_imm_insn
},
956 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs
, s7_do_ldst_atomic
},
957 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4
, s7_do_ldst_unalign
},
958 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4
, s7_do_ldst_unalign
},
959 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4
, s7_do_ldst_unalign
},
960 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x
, s7_do_xi5x
},
961 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5
, s7_do16_xi5
},
962 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs
, s7_do16_ldst_insn
},
963 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5
, s7_do16_ldst_imm_insn
},
964 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
965 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
966 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs
, s7_do_rdrsrs
},
967 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
968 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
969 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5
, s7_do_rdrsi5
},
970 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs
, s7_do16_rdrs
},
971 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5
, s7_do16_rdi5
},
972 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
973 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs
, s7_do_rdrsrs
},
974 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
975 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs
, s7_do_rdrsrs
},
976 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
977 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5
, s7_do_rdrsi5
},
978 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
979 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5
, s7_do_rdrsi5
},
980 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs
, s7_do16_rdrs
},
981 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs
, s7_do16_rdrs
},
982 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs
, s7_do16_rdi5
},
983 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10
, s7_do_ldst_cop
},
984 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10
, s7_do_ldst_cop
},
985 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10
, s7_do_ldst_cop
},
986 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
987 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs
, s7_do_rdrsrs
},
988 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
989 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
990 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
991 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs
, s7_do16_rdrs
},
992 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4
, s7_do16_rdi4
},
993 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs
, s7_do16_ldst_insn
},
994 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5
, s7_do16_ldst_imm_insn
},
995 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15
, s7_do_i15
},
996 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD
, s7_do_empty
},
997 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD
, s7_do_empty
},
998 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD
, s7_do_empty
},
999 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD
, s7_do_empty
},
1000 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD
, s7_do_empty
},
1001 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD
, s7_do_empty
},
1002 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD
, s7_do_empty
},
1003 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD
, s7_do_empty
},
1004 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD
, s7_do_empty
},
1005 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD
, s7_do_empty
},
1006 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD
, s7_do_empty
},
1007 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD
, s7_do_empty
},
1008 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD
, s7_do_empty
},
1009 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD
, s7_do_empty
},
1010 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD
, s7_do_empty
},
1011 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD
, s7_do_empty
},
1012 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD
, s7_do_empty
},
1013 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
1014 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
1015 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
1016 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD
, s7_do_empty
},
1017 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD
, s7_do_empty
},
1018 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD
, s7_do_empty
},
1019 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD
, s7_do_empty
},
1020 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD
, s7_do_empty
},
1021 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD
, s7_do_empty
},
1022 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD
, s7_do_empty
},
1023 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD
, s7_do_empty
},
1024 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD
, s7_do_empty
},
1025 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD
, s7_do_empty
},
1026 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1027 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1028 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1029 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1030 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1031 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1032 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1033 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1034 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1035 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1036 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1037 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1038 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1039 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1040 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x
, s7_do_xi5x
},
1041 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD
, s7_do_empty
},
1042 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD
, s7_do_empty
},
1043 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD
, s7_do_empty
},
1044 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD
, s7_do_empty
},
1045 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD
, s7_do_empty
},
1046 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD
, s7_do_empty
},
1047 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs
, s7_do_rdrsrs
},
1048 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs
, s7_do_rdrsrs
},
1049 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs
, s7_do16_rdrs
},
1050 /* Macro instruction. */
1051 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN
, s7_do_macro_li_rdi32
},
1052 /* la reg, imm32 -->(1) ldi reg, simm16
1053 (2) ldis reg, %HI(imm32)
1056 la reg, symbol -->(1) lis reg, %HI(imm32)
1057 ori reg, %LO(imm32) */
1058 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN
, s7_do_macro_la_rdi32
},
1059 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1060 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1061 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1062 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1063 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1064 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1065 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1066 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1067 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1068 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN
, s7_do_macro_mul_rdrsrs
},
1069 {"lb", INSN_LB
, 0x00000000, 0x8000, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1070 {"lbu", INSN_LBU
, 0x00000000, 0x200b, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1071 {"lh", INSN_LH
, 0x00000000, 0x2009, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1072 {"lhu", INSN_LHU
, 0x00000000, 0x8000, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1073 {"lw", INSN_LW
, 0x00000000, 0x2008, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1074 {"sb", INSN_SB
, 0x00000000, 0x200f, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1075 {"sh", INSN_SH
, 0x00000000, 0x200d, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1076 {"sw", INSN_SW
, 0x00000000, 0x200c, Insn_Type_SYN
, s7_do_macro_ldst_label
},
1077 /* Assembler use internal. */
1078 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal
, s7_do_macro_rdi32hi
},
1079 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal
, s7_do_macro_rdi32lo
},
1080 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal
, s7_do_rdi16_pic
},
1081 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal
, s7_do_addi_s_pic
},
1082 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal
, s7_do_addi_u_pic
},
1083 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal
, s7_do_lw_pic
},
1086 #define s7_SCORE5_PIPELINE 5
1087 #define s7_SCORE7_PIPELINE 7
1089 static int s7_university_version
= 0;
1090 static int s7_vector_size
= s7_SCORE7_PIPELINE
;
1091 static struct s7_score_it s7_dependency_vector
[s7_SCORE7_PIPELINE
];
1093 static int s7_score7d
= 1;
1098 s7_end_of_line (char *str
)
1100 int retval
= s7_SUCCESS
;
1102 s7_skip_whitespace (str
);
1105 retval
= (int) s7_FAIL
;
1108 s7_inst
.error
= s7_BAD_GARBAGE
;
1115 s7_score_reg_parse (char **ccp
, htab_t htab
)
1120 struct s7_reg_entry
*reg
;
1123 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
1124 return (int) s7_FAIL
;
1128 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
1132 reg
= (struct s7_reg_entry
*) str_hash_find (htab
, start
);
1140 return (int) s7_FAIL
;
1143 /* If shift <= 0, only return reg. */
1145 s7_reg_required_here (char **str
, int shift
, enum s7_score_reg_type reg_type
)
1147 static char buff
[s7_MAX_LITERAL_POOL_SIZE
];
1148 int reg
= (int) s7_FAIL
;
1151 if ((reg
= s7_score_reg_parse (str
, s7_all_reg_maps
[reg_type
].htab
)) != (int) s7_FAIL
)
1153 if (reg_type
== s7_REG_TYPE_SCORE
)
1155 if ((reg
== 1) && (s7_nor1
== 1) && (s7_inst
.bwarn
== 0))
1157 as_warn (_("Using temp register(r1)"));
1163 if (reg_type
== s7_REG_TYPE_SCORE_CR
)
1164 strcpy (s7_inst
.reg
, s7_score_crn_table
[reg
].name
);
1165 else if (reg_type
== s7_REG_TYPE_SCORE_SR
)
1166 strcpy (s7_inst
.reg
, s7_score_srn_table
[reg
].name
);
1168 strcpy (s7_inst
.reg
, "");
1170 s7_inst
.instruction
|= reg
<< shift
;
1176 sprintf (buff
, _("register expected, not '%.100s'"), start
);
1177 s7_inst
.error
= buff
;
1184 s7_skip_past_comma (char **str
)
1190 while ((c
= *p
) == ' ' || c
== ',')
1193 if (c
== ',' && comma
++)
1195 s7_inst
.error
= s7_BAD_SKIP_COMMA
;
1196 return (int) s7_FAIL
;
1200 if ((c
== '\0') || (comma
== 0))
1202 s7_inst
.error
= s7_BAD_SKIP_COMMA
;
1203 return (int) s7_FAIL
;
1207 return comma
? s7_SUCCESS
: (int) s7_FAIL
;
1211 s7_do_rdrsrs (char *str
)
1213 s7_skip_whitespace (str
);
1215 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1216 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1217 || s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1218 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1219 || s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1220 || s7_end_of_line (str
) == (int) s7_FAIL
)
1226 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0)
1227 && (((s7_inst
.instruction
>> 10) & 0x10) == 0)
1228 && (((s7_inst
.instruction
>> 20) & 0x10) == 0)
1229 && (s7_inst
.relax_inst
!= 0x8000)
1230 && (((s7_inst
.instruction
>> 20) & 0xf) == ((s7_inst
.instruction
>> 15) & 0xf)))
1232 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0xf) << 4)
1233 | (((s7_inst
.instruction
>> 15) & 0xf) << 8);
1234 s7_inst
.relax_size
= 2;
1238 s7_inst
.relax_inst
= 0x8000;
1244 s7_walk_no_bignums (symbolS
* sp
)
1246 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
1249 if (symbol_get_value_expression (sp
)->X_add_symbol
)
1250 return (s7_walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
1251 || (symbol_get_value_expression (sp
)->X_op_symbol
1252 && s7_walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
1258 s7_my_get_expression (expressionS
* ep
, char **str
)
1262 save_in
= input_line_pointer
;
1263 input_line_pointer
= *str
;
1264 s7_in_my_get_expression
= 1;
1266 (void) expression (ep
);
1267 s7_in_my_get_expression
= 0;
1269 if (ep
->X_op
== O_illegal
)
1271 *str
= input_line_pointer
;
1272 input_line_pointer
= save_in
;
1273 s7_inst
.error
= _("illegal expression");
1274 return (int) s7_FAIL
;
1276 /* Get rid of any bignums now, so that we don't generate an error for which
1277 we can't establish a line number later on. Big numbers are never valid
1278 in instructions, which is where this routine is always called. */
1279 if (ep
->X_op
== O_big
1280 || (ep
->X_add_symbol
1281 && (s7_walk_no_bignums (ep
->X_add_symbol
)
1282 || (ep
->X_op_symbol
&& s7_walk_no_bignums (ep
->X_op_symbol
)))))
1284 s7_inst
.error
= _("invalid constant");
1285 *str
= input_line_pointer
;
1286 input_line_pointer
= save_in
;
1287 return (int) s7_FAIL
;
1290 if ((ep
->X_add_symbol
!= NULL
)
1291 && (s7_inst
.type
!= PC_DISP19div2
)
1292 && (s7_inst
.type
!= PC_DISP8div2
)
1293 && (s7_inst
.type
!= PC_DISP24div2
)
1294 && (s7_inst
.type
!= PC_DISP11div2
)
1295 && (s7_inst
.type
!= Insn_Type_SYN
)
1296 && (s7_inst
.type
!= Rd_rvalueRs_SI15
)
1297 && (s7_inst
.type
!= Rd_lvalueRs_SI15
)
1298 && (s7_inst
.type
!= Insn_internal
))
1300 s7_inst
.error
= s7_BAD_ARGS
;
1301 *str
= input_line_pointer
;
1302 input_line_pointer
= save_in
;
1303 return (int) s7_FAIL
;
1306 *str
= input_line_pointer
;
1307 input_line_pointer
= save_in
;
1311 /* Check if an immediate is valid. If so, convert it to the right format. */
1313 static bfd_signed_vma
1314 s7_validate_immediate (bfd_signed_vma val
, unsigned int data_type
, int hex_p
)
1320 int val_hi
= ((val
& 0xffff0000) >> 16);
1322 if (s7_score_df_range
[data_type
].range
[0] <= val_hi
1323 && val_hi
<= s7_score_df_range
[data_type
].range
[1])
1330 int val_lo
= (val
& 0xffff);
1332 if (s7_score_df_range
[data_type
].range
[0] <= val_lo
1333 && val_lo
<= s7_score_df_range
[data_type
].range
[1])
1341 if (!(val
>= -0x800 && val
<= 0xfff))
1343 return (int) s7_FAIL
;
1348 if (!(val
>= -2048 && val
<= 2047))
1350 return (int) s7_FAIL
;
1360 if (!(val
>= -0x2000 && val
<= 0x3fff))
1362 return (int) s7_FAIL
;
1367 if (!(val
>= -8192 && val
<= 8191))
1369 return (int) s7_FAIL
;
1379 if (!(val
>= -0x4000 && val
<= 0x7fff))
1381 return (int) s7_FAIL
;
1386 if (!(val
>= -16384 && val
<= 16383))
1388 return (int) s7_FAIL
;
1398 if (!(val
>= -0x8000 && val
<= 0xffff))
1400 return (int) s7_FAIL
;
1405 if (!(val
>= -32768 && val
<= 32767))
1407 return (int) s7_FAIL
;
1417 if (!(val
>= -0x7fff && val
<= 0xffff && val
!= 0x8000))
1419 return (int) s7_FAIL
;
1424 if (!(val
>= -32767 && val
<= 32768))
1426 return (int) s7_FAIL
;
1435 if (val
>= 0 && val
<= 0xffffffff)
1441 return (int) s7_FAIL
;
1445 if (data_type
== _SIMM14_NEG
|| data_type
== _IMM16_NEG
)
1448 if (s7_score_df_range
[data_type
].range
[0] <= val
1449 && val
<= s7_score_df_range
[data_type
].range
[1])
1455 return (int) s7_FAIL
;
1459 s7_data_op2 (char **str
, int shift
, enum score_data_type data_type
)
1462 char data_exp
[s7_MAX_LITERAL_POOL_SIZE
];
1467 s7_skip_whitespace (*str
);
1468 s7_inst
.error
= NULL
;
1471 /* Set hex_p to zero. */
1474 while ((*dataptr
!= '\0') && (*dataptr
!= '|') && (cnt
<= s7_MAX_LITERAL_POOL_SIZE
)) /* 0x7c = ='|' */
1476 data_exp
[cnt
] = *dataptr
;
1481 data_exp
[cnt
] = '\0';
1482 pp
= (char *)&data_exp
;
1484 if (*dataptr
== '|') /* process PCE */
1486 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &pp
) == (int) s7_FAIL
)
1487 return (int) s7_FAIL
;
1488 s7_end_of_line (pp
);
1489 if (s7_inst
.error
!= 0)
1490 return (int) s7_FAIL
; /* to ouptut_inst to printf out the error */
1493 else /* process 16 bit */
1495 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, str
) == (int) s7_FAIL
)
1497 return (int) s7_FAIL
;
1500 dataptr
= (char *) data_exp
;
1501 for (; *dataptr
!= '\0'; dataptr
++)
1503 *dataptr
= TOLOWER (*dataptr
);
1504 if (*dataptr
== '!' || *dataptr
== ' ')
1507 dataptr
= (char *) data_exp
;
1509 if ((dataptr
!= NULL
)
1510 && (((strstr (dataptr
, "0x")) != NULL
)
1511 || ((strstr (dataptr
, "0X")) != NULL
)))
1514 if ((data_type
!= _SIMM16_LA
)
1515 && (data_type
!= _VALUE_HI16
)
1516 && (data_type
!= _VALUE_LO16
)
1517 && (data_type
!= _IMM16
)
1518 && (data_type
!= _IMM15
)
1519 && (data_type
!= _IMM14
)
1520 && (data_type
!= _IMM4
)
1521 && (data_type
!= _IMM5
)
1522 && (data_type
!= _IMM8
)
1523 && (data_type
!= _IMM5_RSHIFT_1
)
1524 && (data_type
!= _IMM5_RSHIFT_2
)
1525 && (data_type
!= _SIMM14
)
1526 && (data_type
!= _SIMM16
)
1527 && (data_type
!= _SIMM14_NEG
)
1528 && (data_type
!= _SIMM16_NEG
)
1529 && (data_type
!= _IMM10_RSHIFT_2
)
1530 && (data_type
!= _GP_IMM15
))
1536 if ((s7_inst
.reloc
.exp
.X_add_number
== 0)
1537 /* for "addi r0,-((((((32*4)+4)+4)+4)+4)&0xf)". */
1538 && (s7_inst
.type
!= Rd_SI16
)
1539 && (s7_inst
.type
!= Insn_Type_SYN
)
1540 && (s7_inst
.type
!= Rd_rvalueRs_SI15
)
1541 && (s7_inst
.type
!= Rd_lvalueRs_SI15
)
1542 && (s7_inst
.type
!= Insn_internal
)
1543 && (((*dataptr
>= 'a') && (*dataptr
<= 'z'))
1544 || ((*dataptr
== '0') && (*(dataptr
+ 1) == 'x') && (*(dataptr
+ 2) != '0'))
1545 || ((*dataptr
== '+') && (*(dataptr
+ 1) != '0'))
1546 || ((*dataptr
== '-') && (*(dataptr
+ 1) != '0'))))
1548 s7_inst
.error
= s7_BAD_ARGS
;
1549 return (int) s7_FAIL
;
1553 if ((s7_inst
.reloc
.exp
.X_add_symbol
)
1554 && ((data_type
== _SIMM16
)
1555 || (data_type
== _SIMM16_NEG
)
1556 || (data_type
== _IMM16_NEG
)
1557 || (data_type
== _SIMM14
)
1558 || (data_type
== _SIMM14_NEG
)
1559 || (data_type
== _IMM5
)
1560 || (data_type
== _IMM14
)
1561 || (data_type
== _IMM20
)
1562 || (data_type
== _IMM16
)
1563 || (data_type
== _IMM15
)
1564 || (data_type
== _IMM4
)))
1566 s7_inst
.error
= s7_BAD_ARGS
;
1567 return (int) s7_FAIL
;
1570 if (s7_inst
.reloc
.exp
.X_add_symbol
)
1575 return (int) s7_FAIL
;
1577 s7_inst
.reloc
.type
= BFD_RELOC_HI16_S
;
1578 s7_inst
.reloc
.pc_rel
= 0;
1581 s7_inst
.reloc
.type
= BFD_RELOC_LO16
;
1582 s7_inst
.reloc
.pc_rel
= 0;
1585 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_GPREL15
;
1586 s7_inst
.reloc
.pc_rel
= 0;
1589 case _IMM16_LO16_pic
:
1590 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_GOT_LO16
;
1591 s7_inst
.reloc
.pc_rel
= 0;
1594 s7_inst
.reloc
.type
= BFD_RELOC_32
;
1595 s7_inst
.reloc
.pc_rel
= 0;
1601 if (data_type
== _IMM16_pic
)
1603 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_DUMMY_HI16
;
1604 s7_inst
.reloc
.pc_rel
= 0;
1607 if (data_type
== _SIMM16_LA
&& s7_inst
.reloc
.exp
.X_unsigned
== 1)
1609 value
= s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, _SIMM16_LA_POS
, hex_p
);
1610 if (value
== (int) s7_FAIL
) /* for advance to check if this is ldis */
1611 if ((s7_inst
.reloc
.exp
.X_add_number
& 0xffff) == 0)
1613 s7_inst
.instruction
|= 0x8000000;
1614 s7_inst
.instruction
|= ((s7_inst
.reloc
.exp
.X_add_number
>> 16) << 1) & 0x1fffe;
1620 value
= s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, data_type
, hex_p
);
1623 if (value
== (int) s7_FAIL
)
1625 if ((data_type
!= _SIMM14_NEG
) && (data_type
!= _SIMM16_NEG
) && (data_type
!= _IMM16_NEG
))
1627 sprintf (s7_err_msg
,
1628 _("invalid constant: %d bit expression not in range %d..%d"),
1629 s7_score_df_range
[data_type
].bits
,
1630 s7_score_df_range
[data_type
].range
[0], s7_score_df_range
[data_type
].range
[1]);
1634 sprintf (s7_err_msg
,
1635 _("invalid constant: %d bit expression not in range %d..%d"),
1636 s7_score_df_range
[data_type
].bits
,
1637 -s7_score_df_range
[data_type
].range
[1], -s7_score_df_range
[data_type
].range
[0]);
1640 s7_inst
.error
= s7_err_msg
;
1641 return (int) s7_FAIL
;
1644 if ((s7_score_df_range
[data_type
].range
[0] != 0) || (data_type
== _IMM5_RANGE_8_31
))
1646 value
&= (1 << s7_score_df_range
[data_type
].bits
) - 1;
1649 s7_inst
.instruction
|= value
<< shift
;
1652 if ((s7_inst
.instruction
& 0x3e000000) == 0x30000000)
1654 if ((((s7_inst
.instruction
>> 20) & 0x1F) != 0)
1655 && (((s7_inst
.instruction
>> 20) & 0x1F) != 1)
1656 && (((s7_inst
.instruction
>> 20) & 0x1F) != 2)
1657 && (((s7_inst
.instruction
>> 20) & 0x1F) != 3)
1658 && (((s7_inst
.instruction
>> 20) & 0x1F) != 4)
1659 && (((s7_inst
.instruction
>> 20) & 0x1F) != 8)
1660 && (((s7_inst
.instruction
>> 20) & 0x1F) != 9)
1661 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0xa)
1662 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0xb)
1663 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0xc)
1664 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0xd)
1665 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0xe)
1666 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x10)
1667 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x11)
1668 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x18)
1669 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x1A)
1670 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x1B)
1671 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x1d)
1672 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x1e)
1673 && (((s7_inst
.instruction
>> 20) & 0x1F) != 0x1f))
1675 s7_inst
.error
= _("invalid constant: bit expression not defined");
1676 return (int) s7_FAIL
;
1683 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1686 s7_do_rdsi16 (char *str
)
1688 s7_skip_whitespace (str
);
1690 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1691 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1692 || s7_data_op2 (&str
, 1, _SIMM16
) == (int) s7_FAIL
1693 || s7_end_of_line (str
) == (int) s7_FAIL
)
1697 if ((s7_inst
.instruction
& 0x20c0000) == 0x20c0000)
1699 if ((((s7_inst
.instruction
>> 20) & 0x10) == 0x10) || ((s7_inst
.instruction
& 0x1fe00) != 0))
1701 s7_inst
.relax_inst
= 0x8000;
1705 s7_inst
.relax_inst
|= (s7_inst
.instruction
>> 1) & 0xff;
1706 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 20) & 0xf) << 8);
1707 s7_inst
.relax_size
= 2;
1710 else if (((s7_inst
.instruction
>> 20) & 0x10) == 0x10)
1712 s7_inst
.relax_inst
= 0x8000;
1716 /* Handle subi/subi.c. */
1719 s7_do_sub_rdsi16 (char *str
)
1721 s7_skip_whitespace (str
);
1723 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1724 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1725 && s7_data_op2 (&str
, 1, _SIMM16_NEG
) != (int) s7_FAIL
)
1726 s7_end_of_line (str
);
1730 /* Handle addri/addri.c. */
1733 s7_do_rdrssi14 (char *str
) /* -(2^13)~((2^13)-1) */
1735 s7_skip_whitespace (str
);
1737 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1738 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1739 && s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1740 && s7_skip_past_comma (&str
) != (int) s7_FAIL
)
1741 s7_data_op2 (&str
, 1, _SIMM14
);
1744 /* Handle subri.c/subri. */
1747 s7_do_sub_rdrssi14 (char *str
) /* -(2^13)~((2^13)-1) */
1749 s7_skip_whitespace (str
);
1751 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1752 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1753 && s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1754 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1755 && s7_data_op2 (&str
, 1, _SIMM14_NEG
) != (int) s7_FAIL
)
1756 s7_end_of_line (str
);
1759 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1762 s7_do_rdrsi5 (char *str
) /* 0~((2^14)-1) */
1764 s7_skip_whitespace (str
);
1766 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1767 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1768 || s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1769 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1770 || s7_data_op2 (&str
, 10, _IMM5
) == (int) s7_FAIL
1771 || s7_end_of_line (str
) == (int) s7_FAIL
)
1774 if ((((s7_inst
.instruction
>> 20) & 0x1f) == ((s7_inst
.instruction
>> 15) & 0x1f))
1775 && (s7_inst
.relax_inst
!= 0x8000) && (((s7_inst
.instruction
>> 15) & 0x10) == 0))
1777 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0x1f) << 3) | (((s7_inst
.instruction
>> 15) & 0xf) << 8);
1778 s7_inst
.relax_size
= 2;
1781 s7_inst
.relax_inst
= 0x8000;
1784 /* Handle andri/orri/andri.c/orri.c. */
1787 s7_do_rdrsi14 (char *str
) /* 0 ~ ((2^14)-1) */
1789 s7_skip_whitespace (str
);
1791 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1792 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1793 && s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1794 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1795 && s7_data_op2 (&str
, 1, _IMM14
) != (int) s7_FAIL
)
1796 s7_end_of_line (str
);
1799 /* Handle bittst.c. */
1802 s7_do_xrsi5 (char *str
)
1804 s7_skip_whitespace (str
);
1806 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1807 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1808 || s7_data_op2 (&str
, 10, _IMM5
) == (int) s7_FAIL
1809 || s7_end_of_line (str
) == (int) s7_FAIL
)
1812 if ((s7_inst
.relax_inst
!= 0x8000) && (((s7_inst
.instruction
>> 15) & 0x10) == 0))
1814 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0x1f) << 3) | (((s7_inst
.instruction
>> 15) & 0xf) << 8);
1815 s7_inst
.relax_size
= 2;
1818 s7_inst
.relax_inst
= 0x8000;
1821 /* Handle addis/andi/ori/andis/oris/ldis. */
1824 s7_do_rdi16 (char *str
)
1826 s7_skip_whitespace (str
);
1828 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1829 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1830 || s7_data_op2 (&str
, 1, _IMM16
) == (int) s7_FAIL
1831 || s7_end_of_line (str
) == (int) s7_FAIL
)
1836 s7_do_macro_rdi32hi (char *str
)
1838 s7_skip_whitespace (str
);
1840 /* Do not handle s7_end_of_line(). */
1841 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1842 && s7_skip_past_comma (&str
) != (int) s7_FAIL
)
1843 s7_data_op2 (&str
, 1, _VALUE_HI16
);
1847 s7_do_macro_rdi32lo (char *str
)
1849 s7_skip_whitespace (str
);
1851 /* Do not handle s7_end_of_line(). */
1852 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1853 && s7_skip_past_comma (&str
) != (int) s7_FAIL
)
1854 s7_data_op2 (&str
, 1, _VALUE_LO16
);
1857 /* Handle ldis_pic. */
1860 s7_do_rdi16_pic (char *str
)
1862 s7_skip_whitespace (str
);
1864 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1865 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1866 && s7_data_op2 (&str
, 1, _IMM16_pic
) != (int) s7_FAIL
)
1867 s7_end_of_line (str
);
1870 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1873 s7_do_addi_s_pic (char *str
)
1875 s7_skip_whitespace (str
);
1877 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1878 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1879 && s7_data_op2 (&str
, 1, _SIMM16_pic
) != (int) s7_FAIL
)
1880 s7_end_of_line (str
);
1883 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1886 s7_do_addi_u_pic (char *str
)
1888 s7_skip_whitespace (str
);
1890 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
1891 && s7_skip_past_comma (&str
) != (int) s7_FAIL
1892 && s7_data_op2 (&str
, 1, _IMM16_LO16_pic
) != (int) s7_FAIL
)
1893 s7_end_of_line (str
);
1896 /* Handle mfceh/mfcel/mtceh/mtchl. */
1899 s7_do_rd (char *str
)
1901 s7_skip_whitespace (str
);
1903 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
)
1904 s7_end_of_line (str
);
1908 s7_do_rs (char *str
)
1910 s7_skip_whitespace (str
);
1912 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1913 || s7_end_of_line (str
) == (int) s7_FAIL
)
1916 if ((s7_inst
.relax_inst
!= 0x8000) && (((s7_inst
.instruction
>> 15) & 0x10) == 0))
1918 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0xf) << 8) | (((s7_inst
.instruction
>> 15) & 0xf) << 4);
1919 s7_inst
.relax_size
= 2;
1922 s7_inst
.relax_inst
= 0x8000;
1926 s7_do_i15 (char *str
)
1928 s7_skip_whitespace (str
);
1930 if (s7_data_op2 (&str
, 10, _IMM15
) != (int) s7_FAIL
)
1931 s7_end_of_line (str
);
1935 s7_do_xi5x (char *str
)
1937 s7_skip_whitespace (str
);
1939 if (s7_data_op2 (&str
, 15, _IMM5
) == (int) s7_FAIL
|| s7_end_of_line (str
) == (int) s7_FAIL
)
1942 if (s7_inst
.relax_inst
!= 0x8000)
1944 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0x1f) << 3);
1945 s7_inst
.relax_size
= 2;
1950 s7_do_rdrs (char *str
)
1952 s7_skip_whitespace (str
);
1954 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1955 || s7_skip_past_comma (&str
) == (int) s7_FAIL
1956 || s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
1957 || s7_end_of_line (str
) == (int) s7_FAIL
)
1960 if (s7_inst
.relax_inst
!= 0x8000)
1962 if (((s7_inst
.instruction
& 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1965 if ((((s7_inst
.instruction
>> 15) & 0x10) != 0x0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
1967 s7_inst
.relax_inst
= 0x00000001 | (((s7_inst
.instruction
>> 15) & 0xf) << 4)
1968 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
1969 s7_inst
.relax_size
= 2;
1972 else if ((((s7_inst
.instruction
>> 15) & 0x10) == 0x0) && ((s7_inst
.instruction
>> 20) & 0x10) != 0)
1974 s7_inst
.relax_inst
= 0x00000002 | (((s7_inst
.instruction
>> 15) & 0xf) << 4)
1975 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
1976 s7_inst
.relax_size
= 2;
1978 else if ((((s7_inst
.instruction
>> 15) & 0x10) == 0x0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
1980 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
1981 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
1982 s7_inst
.relax_size
= 2;
1986 s7_inst
.relax_inst
= 0x8000;
1989 else if ((((s7_inst
.instruction
>> 15) & 0x10) == 0x0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
1991 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
1992 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
1993 s7_inst
.relax_size
= 2;
1997 s7_inst
.relax_inst
= 0x8000;
2002 /* Handle mfcr/mtcr. */
2004 s7_do_rdcrs (char *str
)
2006 s7_skip_whitespace (str
);
2008 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
2009 && s7_skip_past_comma (&str
) != (int) s7_FAIL
2010 && s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE_CR
) != (int) s7_FAIL
)
2011 s7_end_of_line (str
);
2014 /* Handle mfsr/mtsr. */
2017 s7_do_rdsrs (char *str
)
2019 s7_skip_whitespace (str
);
2022 if ((s7_inst
.instruction
& 0xff) == 0x50)
2024 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
2025 && s7_skip_past_comma (&str
) != (int) s7_FAIL
2026 && s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE_SR
) != (int) s7_FAIL
)
2027 s7_end_of_line (str
);
2031 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) != (int) s7_FAIL
2032 && s7_skip_past_comma (&str
) != (int) s7_FAIL
)
2033 s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE_SR
);
2040 s7_do_rdxrs (char *str
)
2042 s7_skip_whitespace (str
);
2044 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2045 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2046 || s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2047 || s7_end_of_line (str
) == (int) s7_FAIL
)
2050 if ((s7_inst
.relax_inst
!= 0x8000) && (((s7_inst
.instruction
>> 10) & 0x10) == 0)
2051 && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
2053 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0xf) << 4) | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
2054 s7_inst
.relax_size
= 2;
2057 s7_inst
.relax_inst
= 0x8000;
2060 /* Handle cmp.c/cmp<cond>. */
2062 s7_do_rsrs (char *str
)
2064 s7_skip_whitespace (str
);
2066 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2067 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2068 || s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2069 || s7_end_of_line (str
) == (int) s7_FAIL
)
2072 if ((s7_inst
.relax_inst
!= 0x8000) && (((s7_inst
.instruction
>> 20) & 0x1f) == 3)
2073 && (((s7_inst
.instruction
>> 10) & 0x10) == 0) && (((s7_inst
.instruction
>> 15) & 0x10) == 0))
2075 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0xf) << 4) | (((s7_inst
.instruction
>> 15) & 0xf) << 8);
2076 s7_inst
.relax_size
= 2;
2079 s7_inst
.relax_inst
= 0x8000;
2083 s7_do_ceinst (char *str
)
2088 s7_skip_whitespace (str
);
2090 if (s7_data_op2 (&str
, 20, _IMM5
) == (int) s7_FAIL
2091 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2092 || s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2093 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2094 || s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
2095 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2096 || s7_data_op2 (&str
, 5, _IMM5
) == (int) s7_FAIL
2097 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2098 || s7_data_op2 (&str
, 0, _IMM5
) == (int) s7_FAIL
2099 || s7_end_of_line (str
) == (int) s7_FAIL
)
2106 if (s7_data_op2 (&str
, 0, _IMM25
) == (int) s7_FAIL
)
2112 s7_reglow_required_here (char **str
, int shift
)
2114 static char buff
[s7_MAX_LITERAL_POOL_SIZE
];
2118 if ((reg
= s7_score_reg_parse (str
, s7_all_reg_maps
[s7_REG_TYPE_SCORE
].htab
)) != (int) s7_FAIL
)
2120 if ((reg
== 1) && (s7_nor1
== 1) && (s7_inst
.bwarn
== 0))
2122 as_warn (_("Using temp register(r1)"));
2128 s7_inst
.instruction
|= reg
<< shift
;
2134 /* Restore the start point, we may have got a reg of the wrong class. */
2136 sprintf (buff
, _("low register(r0-r15)expected, not '%.100s'"), start
);
2137 s7_inst
.error
= buff
;
2138 return (int) s7_FAIL
;
2141 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
2144 s7_do16_rdrs (char *str
)
2146 s7_skip_whitespace (str
);
2148 if (s7_reglow_required_here (&str
, 8) == (int) s7_FAIL
2149 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2150 || s7_reglow_required_here (&str
, 4) == (int) s7_FAIL
2151 || s7_end_of_line (str
) == (int) s7_FAIL
)
2157 if ((s7_inst
.instruction
& 0x700f) == 0x2003) /* cmp! */
2159 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 15)
2160 | (((s7_inst
.instruction
>> 4) & 0xf) << 10);
2162 else if ((s7_inst
.instruction
& 0x700f) == 0x2006) /* not! */
2164 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2165 | (((s7_inst
.instruction
>> 4) & 0xf) << 15);
2167 else if ((s7_inst
.instruction
& 0x700f) == 0x1009) /* mazh.f! */
2169 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 15)
2170 | (((s7_inst
.instruction
>> 4) & 0xf) << 10);
2174 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2175 | (((s7_inst
.instruction
>> 8) & 0xf) << 15) | (((s7_inst
.instruction
>> 4) & 0xf) << 10);
2177 s7_inst
.relax_size
= 4;
2182 s7_do16_rs (char *str
)
2186 s7_skip_whitespace (str
);
2188 if ((rd
= s7_reglow_required_here (&str
, 4)) == (int) s7_FAIL
2189 || s7_end_of_line (str
) == (int) s7_FAIL
)
2195 s7_inst
.relax_inst
|= rd
<< 20;
2196 s7_inst
.relax_size
= 4;
2200 /* Handle br!/brl!. */
2203 s7_do16_xrs (char *str
)
2205 s7_skip_whitespace (str
);
2207 if (s7_reglow_required_here (&str
, 4) == (int) s7_FAIL
|| s7_end_of_line (str
) == (int) s7_FAIL
)
2213 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 10)
2214 | (((s7_inst
.instruction
>> 4) & 0xf) << 15);
2215 s7_inst
.relax_size
= 4;
2220 s7_reghigh_required_here (char **str
, int shift
)
2222 static char buff
[s7_MAX_LITERAL_POOL_SIZE
];
2226 if ((reg
= s7_score_reg_parse (str
, s7_all_reg_maps
[s7_REG_TYPE_SCORE
].htab
)) != (int) s7_FAIL
)
2228 if (15 < reg
&& reg
< 32)
2231 s7_inst
.instruction
|= (reg
& 0xf) << shift
;
2238 sprintf (buff
, _("high register(r16-r31)expected, not '%.100s'"), start
);
2239 s7_inst
.error
= buff
;
2240 return (int) s7_FAIL
;
2246 s7_do16_hrdrs (char *str
)
2248 s7_skip_whitespace (str
);
2250 if (s7_reghigh_required_here (&str
, 8) != (int) s7_FAIL
2251 && s7_skip_past_comma (&str
) != (int) s7_FAIL
2252 && s7_reglow_required_here (&str
, 4) != (int) s7_FAIL
2253 && s7_end_of_line (str
) != (int) s7_FAIL
)
2255 s7_inst
.relax_inst
|= ((((s7_inst
.instruction
>> 8) & 0xf) | 0x10) << 20)
2256 | (((s7_inst
.instruction
>> 4) & 0xf) << 15) | (0xf << 10);
2257 s7_inst
.relax_size
= 4;
2264 s7_do16_rdhrs (char *str
)
2266 s7_skip_whitespace (str
);
2268 if (s7_reglow_required_here (&str
, 8) != (int) s7_FAIL
2269 && s7_skip_past_comma (&str
) != (int) s7_FAIL
2270 && s7_reghigh_required_here (&str
, 4) != (int) s7_FAIL
2271 && s7_end_of_line (str
) != (int) s7_FAIL
)
2273 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2274 | ((((s7_inst
.instruction
>> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
2275 s7_inst
.relax_size
= 4;
2279 /* We need to be able to fix up arbitrary expressions in some statements.
2280 This is so that we can handle symbols that are an arbitrary distance from
2281 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
2282 which returns part of an address in a form which will be valid for
2283 a data instruction. We do this by pushing the expression into a symbol
2284 in the expr_section, and creating a fix for that. */
2287 s7_fix_new_score (fragS
* frag
, int where
, short int size
, expressionS
* exp
, int pc_rel
, int reloc
)
2297 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
2300 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0, pc_rel
, reloc
);
2307 s7_init_dependency_vector (void)
2311 for (i
= 0; i
< s7_vector_size
; i
++)
2312 memset (&s7_dependency_vector
[i
], '\0', sizeof (s7_dependency_vector
[i
]));
2317 static enum s7_insn_type_for_dependency
2318 s7_dependency_type_from_insn (char *insn_name
)
2320 char name
[s7_INSN_NAME_LEN
];
2321 const struct s7_insn_to_dependency
*tmp
;
2323 strcpy (name
, insn_name
);
2324 tmp
= (const struct s7_insn_to_dependency
*)
2325 str_hash_find (s7_dependency_insn_hsh
, name
);
2330 return s7_D_all_insn
;
2334 s7_check_dependency (char *pre_insn
, char *pre_reg
,
2335 char *cur_insn
, char *cur_reg
, int *warn_or_error
)
2339 enum s7_insn_type_for_dependency pre_insn_type
;
2340 enum s7_insn_type_for_dependency cur_insn_type
;
2342 pre_insn_type
= s7_dependency_type_from_insn (pre_insn
);
2343 cur_insn_type
= s7_dependency_type_from_insn (cur_insn
);
2345 for (i
= 0; i
< sizeof (s7_data_dependency_table
) / sizeof (s7_data_dependency_table
[0]); i
++)
2347 if ((pre_insn_type
== s7_data_dependency_table
[i
].pre_insn_type
)
2348 && (s7_D_all_insn
== s7_data_dependency_table
[i
].cur_insn_type
2349 || cur_insn_type
== s7_data_dependency_table
[i
].cur_insn_type
)
2350 && (strcmp (s7_data_dependency_table
[i
].pre_reg
, "") == 0
2351 || strcmp (s7_data_dependency_table
[i
].pre_reg
, pre_reg
) == 0)
2352 && (strcmp (s7_data_dependency_table
[i
].cur_reg
, "") == 0
2353 || strcmp (s7_data_dependency_table
[i
].cur_reg
, cur_reg
) == 0))
2355 if (s7_vector_size
== s7_SCORE5_PIPELINE
)
2356 bubbles
= s7_data_dependency_table
[i
].bubblenum_5
;
2358 bubbles
= s7_data_dependency_table
[i
].bubblenum_7
;
2359 *warn_or_error
= s7_data_dependency_table
[i
].warn_or_error
;
2367 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
2368 for use in the a.out file, and stores them in the array pointed to by buf.
2369 This knows about the endian-ness of the target machine and does
2370 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
2371 2 (short) and 4 (long) Floating numbers are put out as a series of
2372 LITTLENUMS (shorts, here at least). */
2375 s7_number_to_chars (char *buf
, valueT val
, int n
)
2377 if (target_big_endian
)
2378 number_to_chars_bigendian (buf
, val
, n
);
2380 number_to_chars_littleendian (buf
, val
, n
);
2384 s7_build_one_frag (struct s7_score_it one_inst
)
2387 int relaxable_p
= s7_g_opt
;
2390 /* Start a new frag if frag_now is not empty. */
2391 if (frag_now_fix () != 0)
2393 if (!frag_now
->tc_frag_data
.is_insn
)
2394 frag_wane (frag_now
);
2400 p
= frag_more (one_inst
.size
);
2401 s7_number_to_chars (p
, one_inst
.instruction
, one_inst
.size
);
2404 dwarf2_emit_insn (one_inst
.size
);
2407 relaxable_p
&= (one_inst
.relax_size
!= 0);
2408 relax_size
= relaxable_p
? one_inst
.relax_size
: 0;
2410 p
= frag_var (rs_machine_dependent
, relax_size
+ s7_RELAX_PAD_BYTE
, 0,
2411 s7_RELAX_ENCODE (one_inst
.size
, one_inst
.relax_size
,
2412 one_inst
.type
, 0, 0, relaxable_p
),
2416 s7_number_to_chars (p
, one_inst
.relax_inst
, relax_size
);
2420 s7_handle_dependency (struct s7_score_it
*theinst
)
2423 int warn_or_error
= 0; /* warn - 0; error - 1 */
2425 int remainder_bubbles
= 0;
2426 char cur_insn
[s7_INSN_NAME_LEN
];
2427 char pre_insn
[s7_INSN_NAME_LEN
];
2428 struct s7_score_it nop_inst
;
2429 struct s7_score_it pflush_inst
;
2431 nop_inst
.instruction
= 0x0000;
2433 nop_inst
.relax_inst
= 0x80008000;
2434 nop_inst
.relax_size
= 4;
2435 nop_inst
.type
= NO16_OPD
;
2437 pflush_inst
.instruction
= 0x8000800a;
2438 pflush_inst
.size
= 4;
2439 pflush_inst
.relax_inst
= 0x8000;
2440 pflush_inst
.relax_size
= 0;
2441 pflush_inst
.type
= NO_OPD
;
2443 /* pflush will clear all data dependency. */
2444 if (strcmp (theinst
->name
, "pflush") == 0)
2446 s7_init_dependency_vector ();
2450 /* Push current instruction to s7_dependency_vector[0]. */
2451 for (i
= s7_vector_size
- 1; i
> 0; i
--)
2452 memcpy (&s7_dependency_vector
[i
], &s7_dependency_vector
[i
- 1], sizeof (s7_dependency_vector
[i
]));
2454 memcpy (&s7_dependency_vector
[0], theinst
, sizeof (s7_dependency_vector
[i
]));
2456 /* There is no dependency between nop and any instruction. */
2457 if (strcmp (s7_dependency_vector
[0].name
, "nop") == 0
2458 || strcmp (s7_dependency_vector
[0].name
, "nop!") == 0)
2461 /* "pce" is defined in s7_insn_to_dependency_table. */
2462 #define PCE_NAME "pce"
2464 if (s7_dependency_vector
[0].type
== Insn_Type_PCE
)
2465 strcpy (cur_insn
, PCE_NAME
);
2467 strcpy (cur_insn
, s7_dependency_vector
[0].name
);
2469 for (i
= 1; i
< s7_vector_size
; i
++)
2471 /* The element of s7_dependency_vector is NULL. */
2472 if (s7_dependency_vector
[i
].name
[0] == '\0')
2475 if (s7_dependency_vector
[i
].type
== Insn_Type_PCE
)
2476 strcpy (pre_insn
, PCE_NAME
);
2478 strcpy (pre_insn
, s7_dependency_vector
[i
].name
);
2480 bubbles
= s7_check_dependency (pre_insn
, s7_dependency_vector
[i
].reg
,
2481 cur_insn
, s7_dependency_vector
[0].reg
, &warn_or_error
);
2482 remainder_bubbles
= bubbles
- i
+ 1;
2484 if (remainder_bubbles
> 0)
2488 if (s7_fix_data_dependency
== 1)
2490 if (remainder_bubbles
<= 2)
2492 if (s7_warn_fix_data_dependency
)
2493 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2494 s7_dependency_vector
[i
].name
, s7_dependency_vector
[i
].reg
,
2495 s7_dependency_vector
[0].name
, s7_dependency_vector
[0].reg
,
2496 remainder_bubbles
, bubbles
);
2498 for (j
= (s7_vector_size
- 1); (j
- remainder_bubbles
) > 0; j
--)
2499 memcpy (&s7_dependency_vector
[j
], &s7_dependency_vector
[j
- remainder_bubbles
],
2500 sizeof (s7_dependency_vector
[j
]));
2502 for (j
= 1; j
<= remainder_bubbles
; j
++)
2504 memset (&s7_dependency_vector
[j
], '\0', sizeof (s7_dependency_vector
[j
]));
2506 s7_build_one_frag (nop_inst
);
2511 if (s7_warn_fix_data_dependency
)
2512 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2513 s7_dependency_vector
[i
].name
, s7_dependency_vector
[i
].reg
,
2514 s7_dependency_vector
[0].name
, s7_dependency_vector
[0].reg
,
2517 for (j
= 1; j
< s7_vector_size
; j
++)
2518 memset (&s7_dependency_vector
[j
], '\0', sizeof (s7_dependency_vector
[j
]));
2520 /* Insert pflush. */
2521 s7_build_one_frag (pflush_inst
);
2528 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2529 s7_dependency_vector
[i
].name
, s7_dependency_vector
[i
].reg
,
2530 s7_dependency_vector
[0].name
, s7_dependency_vector
[0].reg
,
2531 remainder_bubbles
, bubbles
);
2535 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2536 s7_dependency_vector
[i
].name
, s7_dependency_vector
[i
].reg
,
2537 s7_dependency_vector
[0].name
, s7_dependency_vector
[0].reg
,
2538 remainder_bubbles
, bubbles
);
2545 static enum insn_class
2546 s7_get_insn_class_from_type (enum score_insn_type type
)
2548 enum insn_class retval
= (int) s7_FAIL
;
2554 case Rd_rvalueBP_I5
:
2555 case Rd_lvalueBP_I5
:
2566 retval
= INSN_CLASS_16
;
2575 case Rd_rvalueRs_SI10
:
2576 case Rd_lvalueRs_SI10
:
2577 case Rd_rvalueRs_preSI12
:
2578 case Rd_rvalueRs_postSI12
:
2579 case Rd_lvalueRs_preSI12
:
2580 case Rd_lvalueRs_postSI12
:
2582 case Rd_rvalueRs_SI15
:
2583 case Rd_lvalueRs_SI15
:
2592 case OP5_rvalueRs_SI15
:
2593 case I5_Rs_Rs_I5_OP5
:
2594 case x_rvalueRs_post4
:
2595 case Rd_rvalueRs_post4
:
2597 case Rd_lvalueRs_post4
:
2598 case x_lvalueRs_post4
:
2606 retval
= INSN_CLASS_32
;
2609 retval
= INSN_CLASS_PCE
;
2612 retval
= INSN_CLASS_SYN
;
2621 static unsigned long
2622 s7_adjust_paritybit (unsigned long m_code
, enum insn_class i_class
)
2624 unsigned long result
= 0;
2625 unsigned long m_code_high
= 0;
2626 unsigned long m_code_low
= 0;
2627 unsigned long pb_high
= 0;
2628 unsigned long pb_low
= 0;
2630 if (i_class
== INSN_CLASS_32
)
2632 pb_high
= 0x80000000;
2633 pb_low
= 0x00008000;
2635 else if (i_class
== INSN_CLASS_16
)
2640 else if (i_class
== INSN_CLASS_PCE
)
2643 pb_low
= 0x00008000;
2645 else if (i_class
== INSN_CLASS_SYN
)
2647 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2648 be changed if macro instruction has been expanded. */
2649 pb_high
= 0x80000000;
2650 pb_low
= 0x00008000;
2657 m_code_high
= m_code
& 0x3fff8000;
2658 m_code_low
= m_code
& 0x00007fff;
2659 result
= pb_high
| (m_code_high
<< 1) | pb_low
| m_code_low
;
2665 s7_gen_insn_frag (struct s7_score_it
*part_1
, struct s7_score_it
*part_2
)
2669 int relaxable_p
= s7_g_opt
;
2671 struct s7_score_it
*inst1
= part_1
;
2672 struct s7_score_it
*inst2
= part_2
;
2673 struct s7_score_it backup_inst1
;
2675 pce_p
= inst2
!= NULL
;
2676 memcpy (&backup_inst1
, inst1
, sizeof (struct s7_score_it
));
2678 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2681 backup_inst1
.instruction
= ((backup_inst1
.instruction
& 0x7FFF) << 15)
2682 | (inst2
->instruction
& 0x7FFF);
2683 backup_inst1
.instruction
= s7_adjust_paritybit (backup_inst1
.instruction
, INSN_CLASS_PCE
);
2684 if (!target_big_endian
)
2686 unsigned long tmp
= backup_inst1
.instruction
;
2687 backup_inst1
.instruction
= ((tmp
& 0xffff) << 16)
2690 backup_inst1
.relax_inst
= 0x8000;
2691 backup_inst1
.size
= s7_INSN_SIZE
;
2692 backup_inst1
.relax_size
= 0;
2693 backup_inst1
.type
= Insn_Type_PCE
;
2697 backup_inst1
.instruction
= s7_adjust_paritybit (backup_inst1
.instruction
,
2698 s7_GET_INSN_CLASS (backup_inst1
.type
));
2701 if (backup_inst1
.relax_size
!= 0)
2703 enum insn_class tmp
;
2705 tmp
= (backup_inst1
.size
== s7_INSN_SIZE
) ? INSN_CLASS_16
: INSN_CLASS_32
;
2706 backup_inst1
.relax_inst
= s7_adjust_paritybit (backup_inst1
.relax_inst
, tmp
);
2709 /* Check data dependency. */
2710 s7_handle_dependency (&backup_inst1
);
2712 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2713 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2714 if (frag_now_fix () != 0)
2716 if (!frag_now
->tc_frag_data
.is_insn
)
2717 frag_wane (frag_now
);
2722 /* Here, we must call frag_grow in order to keep the instruction frag type is
2723 rs_machine_dependent.
2724 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2725 actually will call frag_wane.
2726 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2730 p
= frag_more (backup_inst1
.size
);
2731 s7_number_to_chars (p
, backup_inst1
.instruction
, backup_inst1
.size
);
2734 dwarf2_emit_insn (backup_inst1
.size
);
2737 /* Generate fixup structure. */
2740 if (inst1
->reloc
.type
!= BFD_RELOC_NONE
)
2741 s7_fix_new_score (frag_now
, p
- frag_now
->fr_literal
,
2742 inst1
->size
, &inst1
->reloc
.exp
,
2743 inst1
->reloc
.pc_rel
, inst1
->reloc
.type
);
2745 if (inst2
->reloc
.type
!= BFD_RELOC_NONE
)
2746 s7_fix_new_score (frag_now
, p
- frag_now
->fr_literal
+ 2,
2747 inst2
->size
, &inst2
->reloc
.exp
, inst2
->reloc
.pc_rel
, inst2
->reloc
.type
);
2751 if (backup_inst1
.reloc
.type
!= BFD_RELOC_NONE
)
2752 s7_fix_new_score (frag_now
, p
- frag_now
->fr_literal
,
2753 backup_inst1
.size
, &backup_inst1
.reloc
.exp
,
2754 backup_inst1
.reloc
.pc_rel
, backup_inst1
.reloc
.type
);
2757 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2758 relaxable_p
&= (backup_inst1
.relax_size
!= 0);
2759 relax_size
= relaxable_p
? backup_inst1
.relax_size
: 0;
2761 p
= frag_var (rs_machine_dependent
, relax_size
+ s7_RELAX_PAD_BYTE
, 0,
2762 s7_RELAX_ENCODE (backup_inst1
.size
, backup_inst1
.relax_size
,
2763 backup_inst1
.type
, 0, 0, relaxable_p
),
2764 backup_inst1
.reloc
.exp
.X_add_symbol
, 0, NULL
);
2767 s7_number_to_chars (p
, backup_inst1
.relax_inst
, relax_size
);
2769 memcpy (inst1
, &backup_inst1
, sizeof (struct s7_score_it
));
2773 s7_parse_16_32_inst (char *insnstr
, bool gen_frag_p
)
2777 char *operator = insnstr
;
2778 const struct s7_asm_opcode
*opcode
;
2780 /* Parse operator and operands. */
2781 s7_skip_whitespace (operator);
2783 for (p
= operator; *p
!= '\0'; p
++)
2784 if ((*p
== ' ') || (*p
== '!'))
2793 opcode
= (const struct s7_asm_opcode
*) str_hash_find (s7_score_ops_hsh
,
2797 memset (&s7_inst
, '\0', sizeof (s7_inst
));
2798 strcpy (s7_inst
.str
, insnstr
);
2801 s7_inst
.instruction
= opcode
->value
;
2802 s7_inst
.relax_inst
= opcode
->relax_value
;
2803 s7_inst
.type
= opcode
->type
;
2804 s7_inst
.size
= s7_GET_INSN_SIZE (s7_inst
.type
);
2805 s7_inst
.relax_size
= 0;
2807 strcpy (s7_inst
.name
, opcode
->template_name
);
2808 strcpy (s7_inst
.reg
, "");
2809 s7_inst
.error
= NULL
;
2810 s7_inst
.reloc
.type
= BFD_RELOC_NONE
;
2812 (*opcode
->parms
) (p
);
2814 /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1. */
2815 if ((s7_inst
.bwarn
!= -1) && (!s7_inst
.error
) && (gen_frag_p
))
2816 s7_gen_insn_frag (&s7_inst
, NULL
);
2819 s7_inst
.error
= _("unrecognized opcode");
2823 s7_append_insn (char *str
, bool gen_frag_p
)
2825 int retval
= s7_SUCCESS
;
2827 s7_parse_16_32_inst (str
, gen_frag_p
);
2831 retval
= (int) s7_FAIL
;
2832 as_bad (_("%s -- `%s'"), s7_inst
.error
, s7_inst
.str
);
2833 s7_inst
.error
= NULL
;
2839 /* Handle mv! reg_high, reg_low;
2840 mv! reg_low, reg_high;
2841 mv! reg_low, reg_low; */
2843 s7_do16_mv_rdrs (char *str
)
2847 char *backupstr
= NULL
;
2850 s7_skip_whitespace (str
);
2852 if ((reg_rd
= s7_reg_required_here (&str
, 8, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
2853 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2854 || (reg_rs
= s7_reg_required_here (&str
, 4, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
2855 || s7_end_of_line (str
) == (int) s7_FAIL
)
2861 /* Case 1 : mv! or mlfh!. */
2866 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2867 | (((s7_inst
.instruction
>> 4) & 0xf) << 15) | (0xf << 10);
2868 s7_inst
.relax_size
= 4;
2872 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
2874 sprintf (append_str
, "mlfh! %s", backupstr
);
2875 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
2877 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2881 /* Case 2 : mhfl!. */
2886 s7_SET_INSN_ERROR (s7_BAD_ARGS
);
2891 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
2893 sprintf (append_str
, "mhfl! %s", backupstr
);
2894 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
2897 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2905 s7_do16_rdi4 (char *str
)
2907 s7_skip_whitespace (str
);
2909 if (s7_reglow_required_here (&str
, 8) == (int) s7_FAIL
2910 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2911 || s7_data_op2 (&str
, 3, _IMM4
) == (int) s7_FAIL
2912 || s7_end_of_line (str
) == (int) s7_FAIL
)
2918 if (((s7_inst
.instruction
>> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2920 if (((s7_inst
.instruction
>> 3) & 0xf) != 0xf)
2922 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2923 | ((1 << ((s7_inst
.instruction
>> 3) & 0xf)) << 1);
2924 s7_inst
.relax_size
= 4;
2928 s7_inst
.relax_inst
= 0x8000;
2933 if (((s7_inst
.instruction
>> 3) & 0xf) != 0xf)
2935 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2936 | (((-(1 << ((s7_inst
.instruction
>> 3) & 0xf))) & 0xffff) << 1);
2937 s7_inst
.relax_size
= 4;
2941 s7_inst
.relax_inst
= 0x8000;
2948 s7_do16_rdi5 (char *str
)
2950 s7_skip_whitespace (str
);
2952 if (s7_reglow_required_here (&str
, 8) == (int) s7_FAIL
2953 || s7_skip_past_comma (&str
) == (int) s7_FAIL
2954 || s7_data_op2 (&str
, 3, _IMM5
) == (int) s7_FAIL
2955 || s7_end_of_line (str
) == (int) s7_FAIL
)
2959 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
2960 | (((s7_inst
.instruction
>> 8) & 0xf) << 15) | (((s7_inst
.instruction
>> 3) & 0x1f) << 10);
2961 s7_inst
.relax_size
= 4;
2968 s7_do16_xi5 (char *str
)
2970 s7_skip_whitespace (str
);
2972 if (s7_data_op2 (&str
, 3, _IMM5
) == (int) s7_FAIL
|| s7_end_of_line (str
) == (int) s7_FAIL
)
2976 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 3) & 0x1f) << 15);
2977 s7_inst
.relax_size
= 4;
2981 /* Check that an immediate is word alignment or half word alignment.
2982 If so, convert it to the right format. */
2985 s7_validate_immediate_align (int val
, unsigned int data_type
)
2987 if (data_type
== _IMM5_RSHIFT_1
)
2991 s7_inst
.error
= _("address offset must be half word alignment");
2992 return (int) s7_FAIL
;
2995 else if ((data_type
== _IMM5_RSHIFT_2
) || (data_type
== _IMM10_RSHIFT_2
))
2999 s7_inst
.error
= _("address offset must be word alignment");
3000 return (int) s7_FAIL
;
3008 s7_exp_ldst_offset (char **str
, int shift
, unsigned int data_type
)
3015 if ((dataptr
!= NULL
)
3016 && (((strstr (dataptr
, "0x")) != NULL
)
3017 || ((strstr (dataptr
, "0X")) != NULL
)))
3020 if ((data_type
!= _SIMM16_LA
)
3021 && (data_type
!= _VALUE_HI16
)
3022 && (data_type
!= _VALUE_LO16
)
3023 && (data_type
!= _IMM16
)
3024 && (data_type
!= _IMM15
)
3025 && (data_type
!= _IMM14
)
3026 && (data_type
!= _IMM4
)
3027 && (data_type
!= _IMM5
)
3028 && (data_type
!= _IMM8
)
3029 && (data_type
!= _IMM5_RSHIFT_1
)
3030 && (data_type
!= _IMM5_RSHIFT_2
)
3031 && (data_type
!= _SIMM12
)
3032 && (data_type
!= _SIMM15
)
3033 && (data_type
!= _SIMM14_NEG
)
3034 && (data_type
!= _IMM10_RSHIFT_2
))
3040 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, str
) == (int) s7_FAIL
)
3041 return (int) s7_FAIL
;
3043 if (s7_inst
.reloc
.exp
.X_op
== O_constant
)
3045 /* Need to check the immediate align. */
3046 int value
= s7_validate_immediate_align (s7_inst
.reloc
.exp
.X_add_number
, data_type
);
3048 if (value
== (int) s7_FAIL
)
3049 return (int) s7_FAIL
;
3051 value
= s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, data_type
, hex_p
);
3052 if (value
== (int) s7_FAIL
)
3055 sprintf (s7_err_msg
,
3056 _("invalid constant: %d bit expression not in range %d..%d"),
3057 s7_score_df_range
[data_type
].bits
,
3058 s7_score_df_range
[data_type
].range
[0], s7_score_df_range
[data_type
].range
[1]);
3060 sprintf (s7_err_msg
,
3061 _("invalid constant: %d bit expression not in range %d..%d"),
3062 s7_score_df_range
[data_type
- 24].bits
,
3063 s7_score_df_range
[data_type
- 24].range
[0], s7_score_df_range
[data_type
- 24].range
[1]);
3064 s7_inst
.error
= s7_err_msg
;
3065 return (int) s7_FAIL
;
3068 if (data_type
== _IMM5_RSHIFT_1
)
3072 else if ((data_type
== _IMM5_RSHIFT_2
) || (data_type
== _IMM10_RSHIFT_2
))
3077 if (s7_score_df_range
[data_type
].range
[0] != 0)
3079 value
&= (1 << s7_score_df_range
[data_type
].bits
) - 1;
3082 s7_inst
.instruction
|= value
<< shift
;
3086 s7_inst
.reloc
.pc_rel
= 0;
3093 s7_do_ldst_insn (char *str
)
3105 s7_skip_whitespace (str
);
3107 if (((conflict_reg
= s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3108 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3111 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
3115 s7_skip_whitespace (str
);
3117 if ((reg
= s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3120 /* Conflicts can occur on stores as well as loads. */
3121 conflict_reg
= (conflict_reg
== reg
);
3122 s7_skip_whitespace (str
);
3123 temp
= str
+ 1; /* The latter will process decimal/hex expression. */
3125 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
3132 /* ld/sw rD, [rA]+, simm12. */
3133 if (s7_skip_past_comma (&str
) == s7_SUCCESS
)
3135 if ((s7_exp_ldst_offset (&str
, 3, _SIMM12
) == (int) s7_FAIL
)
3136 || (s7_end_of_line (str
) == (int) s7_FAIL
))
3141 unsigned int ldst_func
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3143 if ((ldst_func
== INSN_LH
)
3144 || (ldst_func
== INSN_LHU
)
3145 || (ldst_func
== INSN_LW
)
3146 || (ldst_func
== INSN_LB
)
3147 || (ldst_func
== INSN_LBU
))
3149 s7_inst
.error
= _("register same as write-back base");
3154 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3155 s7_inst
.instruction
&= ~OPC_PSEUDOLDST_MASK
;
3156 s7_inst
.instruction
|= s7_score_ldst_insns
[ldst_idx
* 3 + LDST_POST
].value
;
3158 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
3159 if ((s7_inst
.instruction
& 0x3e000007) == 0x0e000000)
3161 /* rs = r0-r7, offset = 4 */
3162 if ((((s7_inst
.instruction
>> 15) & 0x18) == 0)
3163 && (((s7_inst
.instruction
>> 3) & 0xfff) == 4))
3165 /* Relax to pophi. */
3166 if ((((s7_inst
.instruction
>> 20) & 0x10) == 0x10))
3168 s7_inst
.relax_inst
= 0x0000200a | (((s7_inst
.instruction
>> 20) & 0xf)
3170 (((s7_inst
.instruction
>> 15) & 0x7) << 4);
3175 s7_inst
.relax_inst
= 0x0000200a | (((s7_inst
.instruction
>> 20) & 0xf)
3177 (((s7_inst
.instruction
>> 15) & 0x7) << 4);
3179 s7_inst
.relax_size
= 2;
3184 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3187 s7_SET_INSN_ERROR (NULL
);
3188 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3194 value
= s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, _SIMM12
, 0);
3195 value
&= (1 << s7_score_df_range
[_SIMM12
].bits
) - 1;
3196 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3197 s7_inst
.instruction
&= ~OPC_PSEUDOLDST_MASK
;
3198 s7_inst
.instruction
|= s7_score_ldst_insns
[ldst_idx
* 3 + pre_inc
].value
;
3199 s7_inst
.instruction
|= value
<< 3;
3200 s7_inst
.relax_inst
= 0x8000;
3204 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3207 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3210 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3211 s7_inst
.instruction
&= ~OPC_PSEUDOLDST_MASK
;
3212 s7_inst
.instruction
|= s7_score_ldst_insns
[ldst_idx
* 3 + LDST_NOUPDATE
].value
;
3214 /* lbu rd, [rs] -> lbu! rd, [rs] */
3215 if (ldst_idx
== INSN_LBU
)
3217 s7_inst
.relax_inst
= INSN16_LBU
;
3219 else if (ldst_idx
== INSN_LH
)
3221 s7_inst
.relax_inst
= INSN16_LH
;
3223 else if (ldst_idx
== INSN_LW
)
3225 s7_inst
.relax_inst
= INSN16_LW
;
3227 else if (ldst_idx
== INSN_SB
)
3229 s7_inst
.relax_inst
= INSN16_SB
;
3231 else if (ldst_idx
== INSN_SH
)
3233 s7_inst
.relax_inst
= INSN16_SH
;
3235 else if (ldst_idx
== INSN_SW
)
3237 s7_inst
.relax_inst
= INSN16_SW
;
3241 s7_inst
.relax_inst
= 0x8000;
3244 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
3245 if ((ldst_idx
== INSN_LBU
)
3246 || (ldst_idx
== INSN_LH
)
3247 || (ldst_idx
== INSN_LW
)
3248 || (ldst_idx
== INSN_SB
) || (ldst_idx
== INSN_SH
) || (ldst_idx
== INSN_SW
))
3250 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3252 s7_inst
.relax_inst
|= (2 << 12) | (((s7_inst
.instruction
>> 20) & 0xf) << 8) |
3253 (((s7_inst
.instruction
>> 15) & 0xf) << 4);
3254 s7_inst
.relax_size
= 2;
3261 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3264 if (s7_skip_past_comma (&str
) == (int) s7_FAIL
)
3266 s7_inst
.error
= _("pre-indexed expression expected");
3270 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
)
3273 s7_skip_whitespace (str
);
3276 s7_inst
.error
= _("missing ]");
3280 s7_skip_whitespace (str
);
3281 /* ld/sw rD, [rA, simm12]+. */
3288 unsigned int ldst_func
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3290 if ((ldst_func
== INSN_LH
)
3291 || (ldst_func
== INSN_LHU
)
3292 || (ldst_func
== INSN_LW
)
3293 || (ldst_func
== INSN_LB
)
3294 || (ldst_func
== INSN_LBU
))
3296 s7_inst
.error
= _("register same as write-back base");
3302 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3305 if (s7_inst
.reloc
.exp
.X_op
== O_constant
)
3307 unsigned int data_type
;
3310 data_type
= _SIMM12
;
3312 data_type
= _SIMM15
;
3315 if ((dataptr
!= NULL
)
3316 && (((strstr (dataptr
, "0x")) != NULL
)
3317 || ((strstr (dataptr
, "0X")) != NULL
)))
3320 if ((data_type
!= _SIMM16_LA
)
3321 && (data_type
!= _VALUE_HI16
)
3322 && (data_type
!= _VALUE_LO16
)
3323 && (data_type
!= _IMM16
)
3324 && (data_type
!= _IMM15
)
3325 && (data_type
!= _IMM14
)
3326 && (data_type
!= _IMM4
)
3327 && (data_type
!= _IMM5
)
3328 && (data_type
!= _IMM8
)
3329 && (data_type
!= _SIMM12
)
3330 && (data_type
!= _SIMM15
)
3331 && (data_type
!= _IMM5_RSHIFT_1
)
3332 && (data_type
!= _IMM5_RSHIFT_2
)
3333 && (data_type
!= _SIMM14_NEG
)
3334 && (data_type
!= _IMM10_RSHIFT_2
))
3340 value
= s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, data_type
, hex_p
);
3341 if (value
== (int) s7_FAIL
)
3344 sprintf (s7_err_msg
,
3345 _("invalid constant: %d bit expression not in range %d..%d"),
3346 s7_score_df_range
[data_type
].bits
,
3347 s7_score_df_range
[data_type
].range
[0], s7_score_df_range
[data_type
].range
[1]);
3349 sprintf (s7_err_msg
,
3350 _("invalid constant: %d bit expression not in range %d..%d"),
3351 s7_score_df_range
[data_type
- 24].bits
,
3352 s7_score_df_range
[data_type
- 24].range
[0],
3353 s7_score_df_range
[data_type
- 24].range
[1]);
3354 s7_inst
.error
= s7_err_msg
;
3358 value
&= (1 << s7_score_df_range
[data_type
].bits
) - 1;
3359 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
3360 s7_inst
.instruction
&= ~OPC_PSEUDOLDST_MASK
;
3361 s7_inst
.instruction
|= s7_score_ldst_insns
[ldst_idx
* 3 + pre_inc
].value
;
3363 s7_inst
.instruction
|= value
<< 3;
3365 s7_inst
.instruction
|= value
;
3367 /* lw rD, [rA, simm15] */
3368 if ((s7_inst
.instruction
& 0x3e000000) == 0x20000000)
3370 /* Both rD and rA are in [r0 - r15]. */
3371 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0)
3372 && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3374 /* simm15 = 0, lw -> lw!. */
3375 if ((s7_inst
.instruction
& 0x7fff) == 0)
3377 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3378 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3379 s7_inst
.relax_size
= 2;
3381 /* rA = r2, lw -> lwp!. */
3382 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3383 && ((s7_inst
.instruction
& 0x3) == 0)
3384 && ((s7_inst
.instruction
& 0x7fff) < 128))
3386 s7_inst
.relax_inst
= 0x7000 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3387 | (((s7_inst
.instruction
& 0x7fff) >> 2) << 3);
3388 s7_inst
.relax_size
= 2;
3392 s7_inst
.relax_inst
= 0x8000;
3397 s7_inst
.relax_inst
= 0x8000;
3400 /* sw rD, [rA, simm15] */
3401 else if ((s7_inst
.instruction
& 0x3e000000) == 0x28000000)
3403 /* Both rD and rA are in [r0 - r15]. */
3404 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3406 /* simm15 = 0, sw -> sw!. */
3407 if ((s7_inst
.instruction
& 0x7fff) == 0)
3409 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3410 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3411 s7_inst
.relax_size
= 2;
3413 /* rA = r2, sw -> swp!. */
3414 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3415 && ((s7_inst
.instruction
& 0x3) == 0)
3416 && ((s7_inst
.instruction
& 0x7fff) < 128))
3418 s7_inst
.relax_inst
= 0x7004 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3419 | (((s7_inst
.instruction
& 0x7fff) >> 2) << 3);
3420 s7_inst
.relax_size
= 2;
3424 s7_inst
.relax_inst
= 0x8000;
3429 s7_inst
.relax_inst
= 0x8000;
3432 /* sw rD, [rA, simm15]+ sw pre. */
3433 else if ((s7_inst
.instruction
& 0x3e000007) == 0x06000004)
3435 /* rA is in [r0 - r7], and simm15 = -4. */
3436 if ((((s7_inst
.instruction
>> 15) & 0x18) == 0)
3437 && (((s7_inst
.instruction
>> 3) & 0xfff) == 0xffc))
3439 /* sw -> pushhi!. */
3440 if ((((s7_inst
.instruction
>> 20) & 0x10) == 0x10))
3442 s7_inst
.relax_inst
= 0x0000200e | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3443 | 1 << 7 | (((s7_inst
.instruction
>> 15) & 0x7) << 4);
3444 s7_inst
.relax_size
= 2;
3449 s7_inst
.relax_inst
= 0x0000200e | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3450 | 0 << 7 | (((s7_inst
.instruction
>> 15) & 0x7) << 4);
3451 s7_inst
.relax_size
= 2;
3456 s7_inst
.relax_inst
= 0x8000;
3459 /* lh rD, [rA, simm15] */
3460 else if ((s7_inst
.instruction
& 0x3e000000) == 0x22000000)
3462 /* Both rD and rA are in [r0 - r15]. */
3463 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3465 /* simm15 = 0, lh -> lh!. */
3466 if ((s7_inst
.instruction
& 0x7fff) == 0)
3468 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3469 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3470 s7_inst
.relax_size
= 2;
3472 /* rA = r2, lh -> lhp!. */
3473 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3474 && ((s7_inst
.instruction
& 0x1) == 0)
3475 && ((s7_inst
.instruction
& 0x7fff) < 64))
3477 s7_inst
.relax_inst
= 0x7001 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3478 | (((s7_inst
.instruction
& 0x7fff) >> 1) << 3);
3479 s7_inst
.relax_size
= 2;
3483 s7_inst
.relax_inst
= 0x8000;
3488 s7_inst
.relax_inst
= 0x8000;
3491 /* sh rD, [rA, simm15] */
3492 else if ((s7_inst
.instruction
& 0x3e000000) == 0x2a000000)
3494 /* Both rD and rA are in [r0 - r15]. */
3495 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3497 /* simm15 = 0, sh -> sh!. */
3498 if ((s7_inst
.instruction
& 0x7fff) == 0)
3500 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3501 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3502 s7_inst
.relax_size
= 2;
3504 /* rA = r2, sh -> shp!. */
3505 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3506 && ((s7_inst
.instruction
& 0x1) == 0)
3507 && ((s7_inst
.instruction
& 0x7fff) < 64))
3509 s7_inst
.relax_inst
= 0x7005 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3510 | (((s7_inst
.instruction
& 0x7fff) >> 1) << 3);
3511 s7_inst
.relax_size
= 2;
3515 s7_inst
.relax_inst
= 0x8000;
3520 s7_inst
.relax_inst
= 0x8000;
3523 /* lbu rD, [rA, simm15] */
3524 else if ((s7_inst
.instruction
& 0x3e000000) == 0x2c000000)
3526 /* Both rD and rA are in [r0 - r15]. */
3527 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3529 /* simm15 = 0, lbu -> lbu!. */
3530 if ((s7_inst
.instruction
& 0x7fff) == 0)
3532 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3533 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3534 s7_inst
.relax_size
= 2;
3536 /* rA = r2, lbu -> lbup!. */
3537 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3538 && ((s7_inst
.instruction
& 0x7fff) < 32))
3540 s7_inst
.relax_inst
= 0x7003 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3541 | ((s7_inst
.instruction
& 0x7fff) << 3);
3542 s7_inst
.relax_size
= 2;
3546 s7_inst
.relax_inst
= 0x8000;
3551 s7_inst
.relax_inst
= 0x8000;
3554 /* sb rD, [rA, simm15] */
3555 else if ((s7_inst
.instruction
& 0x3e000000) == 0x2e000000)
3557 /* Both rD and rA are in [r0 - r15]. */
3558 if ((((s7_inst
.instruction
>> 15) & 0x10) == 0) && (((s7_inst
.instruction
>> 20) & 0x10) == 0))
3560 /* simm15 = 0, sb -> sb!. */
3561 if ((s7_inst
.instruction
& 0x7fff) == 0)
3563 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 15) & 0xf) << 4)
3564 | (((s7_inst
.instruction
>> 20) & 0xf) << 8);
3565 s7_inst
.relax_size
= 2;
3567 /* rA = r2, sb -> sb!. */
3568 else if ((((s7_inst
.instruction
>> 15) & 0xf) == 2)
3569 && ((s7_inst
.instruction
& 0x7fff) < 32))
3571 s7_inst
.relax_inst
= 0x7007 | (((s7_inst
.instruction
>> 20) & 0xf) << 8)
3572 | ((s7_inst
.instruction
& 0x7fff) << 3);
3573 s7_inst
.relax_size
= 2;
3577 s7_inst
.relax_inst
= 0x8000;
3582 s7_inst
.relax_inst
= 0x8000;
3587 s7_inst
.relax_inst
= 0x8000;
3594 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3595 s7_inst
.reloc
.pc_rel
= 0;
3601 s7_inst
.error
= s7_BAD_ARGS
;
3607 s7_do_cache (char *str
)
3609 s7_skip_whitespace (str
);
3611 if ((s7_data_op2 (&str
, 20, _IMM5
) == (int) s7_FAIL
) || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3619 cache_op
= (s7_inst
.instruction
>> 20) & 0x1F;
3620 sprintf (s7_inst
.name
, "cache %d", cache_op
);
3626 s7_skip_whitespace (str
);
3628 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
)
3631 s7_skip_whitespace (str
);
3633 /* cache op, [rA] */
3634 if (s7_skip_past_comma (&str
) == (int) s7_FAIL
)
3636 s7_SET_INSN_ERROR (NULL
);
3639 s7_inst
.error
= _("missing ]");
3644 /* cache op, [rA, simm15] */
3647 if (s7_exp_ldst_offset (&str
, 0, _SIMM15
) == (int) s7_FAIL
)
3652 s7_skip_whitespace (str
);
3655 s7_inst
.error
= _("missing ]");
3660 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3665 s7_inst
.error
= s7_BAD_ARGS
;
3670 s7_do_crdcrscrsimm5 (char *str
)
3675 s7_skip_whitespace (str
);
3677 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE_CR
) == (int) s7_FAIL
3678 || s7_skip_past_comma (&str
) == (int) s7_FAIL
3679 || s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE_CR
) == (int) s7_FAIL
3680 || s7_skip_past_comma (&str
) == (int) s7_FAIL
3681 || s7_reg_required_here (&str
, 10, s7_REG_TYPE_SCORE_CR
) == (int) s7_FAIL
3682 || s7_skip_past_comma (&str
) == (int) s7_FAIL
)
3685 /* cop1 cop_code20. */
3686 if (s7_data_op2 (&str
, 5, _IMM20
) == (int) s7_FAIL
)
3691 if (s7_data_op2 (&str
, 5, _IMM5
) == (int) s7_FAIL
)
3695 s7_end_of_line (str
);
3698 /* Handle ldc/stc. */
3700 s7_do_ldst_cop (char *str
)
3702 s7_skip_whitespace (str
);
3704 if ((s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE_CR
) == (int) s7_FAIL
)
3705 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3711 s7_skip_whitespace (str
);
3713 if (s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
)
3716 s7_skip_whitespace (str
);
3720 if (s7_exp_ldst_offset (&str
, 5, _IMM10_RSHIFT_2
) == (int) s7_FAIL
)
3723 s7_skip_whitespace (str
);
3726 s7_inst
.error
= _("missing ]");
3731 s7_end_of_line (str
);
3734 s7_inst
.error
= s7_BAD_ARGS
;
3738 s7_do16_ldst_insn (char *str
)
3740 s7_skip_whitespace (str
);
3742 if ((s7_reglow_required_here (&str
, 8) == (int) s7_FAIL
) || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3750 s7_skip_whitespace (str
);
3752 if ((reg
= s7_reglow_required_here (&str
, 4)) == (int) s7_FAIL
)
3755 s7_skip_whitespace (str
);
3758 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3762 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
3763 | (((s7_inst
.instruction
>> 4) & 0xf) << 15);
3764 s7_inst
.relax_size
= 4;
3769 s7_inst
.error
= _("missing ]");
3774 s7_inst
.error
= s7_BAD_ARGS
;
3778 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3781 s7_do16_ldst_imm_insn (char *str
)
3783 char data_exp
[s7_MAX_LITERAL_POOL_SIZE
];
3785 char *dataptr
= NULL
, *pp
= NULL
;
3787 int assign_data
= (int) s7_FAIL
;
3788 unsigned int ldst_func
;
3790 s7_skip_whitespace (str
);
3792 if (((reg_rd
= s7_reglow_required_here (&str
, 8)) == (int) s7_FAIL
)
3793 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3796 s7_skip_whitespace (str
);
3799 while ((*dataptr
!= '\0') && (*dataptr
!= '|') && (cnt
<= s7_MAX_LITERAL_POOL_SIZE
))
3801 data_exp
[cnt
] = *dataptr
;
3806 data_exp
[cnt
] = '\0';
3811 ldst_func
= s7_inst
.instruction
& LDST16_RI_MASK
;
3812 if (ldst_func
== N16_LIU
)
3813 assign_data
= s7_exp_ldst_offset (&pp
, 0, _IMM8
);
3814 else if (ldst_func
== N16_LHP
|| ldst_func
== N16_SHP
)
3815 assign_data
= s7_exp_ldst_offset (&pp
, 3, _IMM5_RSHIFT_1
);
3816 else if (ldst_func
== N16_LWP
|| ldst_func
== N16_SWP
)
3817 assign_data
= s7_exp_ldst_offset (&pp
, 3, _IMM5_RSHIFT_2
);
3819 assign_data
= s7_exp_ldst_offset (&pp
, 3, _IMM5
);
3821 if ((assign_data
== (int) s7_FAIL
) || (s7_end_of_line (pp
) == (int) s7_FAIL
))
3825 if ((s7_inst
.instruction
& 0x7000) == N16_LIU
)
3827 s7_inst
.relax_inst
|= ((s7_inst
.instruction
>> 8) & 0xf) << 20
3828 | ((s7_inst
.instruction
& 0xff) << 1);
3830 else if (((s7_inst
.instruction
& 0x7007) == N16_LHP
)
3831 || ((s7_inst
.instruction
& 0x7007) == N16_SHP
))
3833 s7_inst
.relax_inst
|= ((s7_inst
.instruction
>> 8) & 0xf) << 20 | 2 << 15
3834 | (((s7_inst
.instruction
>> 3) & 0x1f) << 1);
3836 else if (((s7_inst
.instruction
& 0x7007) == N16_LWP
)
3837 || ((s7_inst
.instruction
& 0x7007) == N16_SWP
))
3839 s7_inst
.relax_inst
|= ((s7_inst
.instruction
>> 8) & 0xf) << 20 | 2 << 15
3840 | (((s7_inst
.instruction
>> 3) & 0x1f) << 2);
3842 else if (((s7_inst
.instruction
& 0x7007) == N16_LBUP
)
3843 || ((s7_inst
.instruction
& 0x7007) == N16_SBP
))
3845 s7_inst
.relax_inst
|= ((s7_inst
.instruction
>> 8) & 0xf) << 20 | 2 << 15
3846 | (((s7_inst
.instruction
>> 3) & 0x1f));
3849 s7_inst
.relax_size
= 4;
3854 s7_do16_push_pop (char *str
)
3859 s7_skip_whitespace (str
);
3860 if (((reg_rd
= s7_reg_required_here (&str
, 8, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3861 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3867 /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3868 s7_inst
.instruction
&= ~(1 << 12);
3870 s7_inst
.instruction
|= H_bit_mask
<< 7;
3877 s7_skip_whitespace (str
);
3878 if ((reg
= s7_reg_required_here (&str
, 4, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3883 s7_inst
.error
= _("base register nums are over 3 bit");
3888 s7_skip_whitespace (str
);
3889 if ((*str
++ != ']') || (s7_end_of_line (str
) == (int) s7_FAIL
))
3892 s7_inst
.error
= _("missing ]");
3898 if ((s7_inst
.instruction
& 0xf) == 0xa)
3902 s7_inst
.relax_inst
|= ((((s7_inst
.instruction
>> 8) & 0xf) | 0x10) << 20)
3903 | (((s7_inst
.instruction
>> 4) & 0x7) << 15) | (4 << 3);
3907 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
3908 | (((s7_inst
.instruction
>> 4) & 0x7) << 15) | (4 << 3);
3916 s7_inst
.relax_inst
|= ((((s7_inst
.instruction
>> 8) & 0xf) | 0x10) << 20)
3917 | (((s7_inst
.instruction
>> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3921 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 8) & 0xf) << 20)
3922 | (((s7_inst
.instruction
>> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3925 s7_inst
.relax_size
= 4;
3929 s7_inst
.error
= s7_BAD_ARGS
;
3933 /* Handle lcb/lcw/lce/scb/scw/sce. */
3935 s7_do_ldst_unalign (char *str
)
3939 if (s7_university_version
== 1)
3941 s7_inst
.error
= s7_ERR_FOR_SCORE5U_ATOMIC
;
3945 s7_skip_whitespace (str
);
3947 /* lcb/scb [rA]+. */
3951 s7_skip_whitespace (str
);
3953 if (s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
)
3960 s7_inst
.error
= _("missing +");
3966 s7_inst
.error
= _("missing ]");
3970 if (s7_end_of_line (str
) == (int) s7_FAIL
)
3973 /* lcw/lce/scb/sce rD, [rA]+. */
3976 if (((conflict_reg
= s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3977 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
3982 s7_skip_whitespace (str
);
3987 s7_skip_whitespace (str
);
3988 if ((reg
= s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
3993 /* Conflicts can occur on stores as well as loads. */
3994 conflict_reg
= (conflict_reg
== reg
);
3995 s7_skip_whitespace (str
);
3998 unsigned int ldst_func
= s7_inst
.instruction
& LDST_UNALIGN_MASK
;
4004 as_warn (_("%s register same as write-back base"),
4005 ((ldst_func
& UA_LCE
) || (ldst_func
& UA_LCW
)
4006 ? _("destination") : _("source")));
4011 s7_inst
.error
= _("missing +");
4015 if (s7_end_of_line (str
) == (int) s7_FAIL
)
4020 s7_inst
.error
= _("missing ]");
4026 s7_inst
.error
= s7_BAD_ARGS
;
4032 /* Handle alw/asw. */
4035 s7_do_ldst_atomic (char *str
)
4037 if (s7_university_version
== 1)
4039 s7_inst
.error
= s7_ERR_FOR_SCORE5U_ATOMIC
;
4043 s7_skip_whitespace (str
);
4045 if ((s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
) == (int) s7_FAIL
)
4046 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
))
4053 s7_skip_whitespace (str
);
4058 s7_skip_whitespace (str
);
4059 if ((reg
= s7_reg_required_here (&str
, 15, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4064 s7_skip_whitespace (str
);
4067 s7_inst
.error
= _("missing ]");
4071 s7_end_of_line (str
);
4074 s7_inst
.error
= s7_BAD_ARGS
;
4079 s7_build_relax_frag (struct s7_score_it fix_insts
[s7_RELAX_INST_NUM
],
4080 int fix_num ATTRIBUTE_UNUSED
,
4081 struct s7_score_it var_insts
[s7_RELAX_INST_NUM
], int var_num
,
4082 symbolS
*add_symbol
)
4087 fixS
*cur_fixp
= NULL
;
4089 struct s7_score_it inst_main
;
4091 memcpy (&inst_main
, &fix_insts
[0], sizeof (struct s7_score_it
));
4093 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4094 inst_main
.instruction
= s7_adjust_paritybit (inst_main
.instruction
, s7_GET_INSN_CLASS (inst_main
.type
));
4095 inst_main
.type
= Insn_PIC
;
4097 for (i
= 0; i
< var_num
; i
++)
4099 inst_main
.relax_size
+= var_insts
[i
].size
;
4100 var_insts
[i
].instruction
= s7_adjust_paritybit (var_insts
[i
].instruction
,
4101 s7_GET_INSN_CLASS (var_insts
[i
].type
));
4104 /* Check data dependency. */
4105 s7_handle_dependency (&inst_main
);
4107 /* Start a new frag if frag_now is not empty. */
4108 if (frag_now_fix () != 0)
4110 if (!frag_now
->tc_frag_data
.is_insn
)
4112 frag_wane (frag_now
);
4118 /* Write fr_fix part. */
4119 p
= frag_more (inst_main
.size
);
4120 s7_number_to_chars (p
, inst_main
.instruction
, inst_main
.size
);
4122 if (inst_main
.reloc
.type
!= BFD_RELOC_NONE
)
4123 fixp
= s7_fix_new_score (frag_now
, p
- frag_now
->fr_literal
, inst_main
.size
,
4124 &inst_main
.reloc
.exp
, inst_main
.reloc
.pc_rel
, inst_main
.reloc
.type
);
4126 frag_now
->tc_frag_data
.fixp
= fixp
;
4127 cur_fixp
= frag_now
->tc_frag_data
.fixp
;
4130 dwarf2_emit_insn (inst_main
.size
);
4133 where
= p
- frag_now
->fr_literal
+ inst_main
.size
;
4134 for (i
= 0; i
< var_num
; i
++)
4137 where
+= var_insts
[i
- 1].size
;
4139 if (var_insts
[i
].reloc
.type
!= BFD_RELOC_NONE
)
4141 fixp
= s7_fix_new_score (frag_now
, where
, var_insts
[i
].size
,
4142 &var_insts
[i
].reloc
.exp
, var_insts
[i
].reloc
.pc_rel
,
4143 var_insts
[i
].reloc
.type
);
4148 cur_fixp
->fx_next
= fixp
;
4149 cur_fixp
= cur_fixp
->fx_next
;
4153 frag_now
->tc_frag_data
.fixp
= fixp
;
4154 cur_fixp
= frag_now
->tc_frag_data
.fixp
;
4160 p
= frag_var (rs_machine_dependent
, inst_main
.relax_size
+ s7_RELAX_PAD_BYTE
, 0,
4161 s7_RELAX_ENCODE (inst_main
.size
, inst_main
.relax_size
, inst_main
.type
,
4162 0, inst_main
.size
, 0), add_symbol
, 0, NULL
);
4164 /* Write fr_var part.
4165 no calling s7_gen_insn_frag, no fixS will be generated. */
4166 for (i
= 0; i
< var_num
; i
++)
4168 s7_number_to_chars (p
, var_insts
[i
].instruction
, var_insts
[i
].size
);
4169 p
+= var_insts
[i
].size
;
4171 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4175 /* Build a relax frag for la instruction when generating s7_PIC,
4176 external symbol first and local symbol second. */
4179 s7_build_la_pic (int reg_rd
, expressionS exp
)
4181 symbolS
*add_symbol
= exp
.X_add_symbol
;
4182 offsetT add_number
= exp
.X_add_number
;
4183 struct s7_score_it fix_insts
[s7_RELAX_INST_NUM
];
4184 struct s7_score_it var_insts
[s7_RELAX_INST_NUM
];
4187 char tmp
[s7_MAX_LITERAL_POOL_SIZE
];
4193 if (add_number
== 0)
4198 /* For an external symbol, only one insn is generated;
4199 For a local symbol, two insns are generated. */
4201 For an external symbol: lw rD, <sym>($gp)
4202 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
4203 sprintf (tmp
, "lw_pic r%d, %s", reg_rd
, S_GET_NAME (add_symbol
));
4204 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4207 if (reg_rd
== s7_PIC_CALL_REG
)
4208 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_CALL15
;
4209 memcpy (&fix_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4212 For a local symbol :
4213 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4214 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4215 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_GOT15
;
4216 memcpy (&var_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4217 sprintf (tmp
, "addi_s_pic r%d, %s", reg_rd
, S_GET_NAME (add_symbol
));
4218 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4221 memcpy (&var_insts
[1], &s7_inst
, sizeof (struct s7_score_it
));
4222 s7_build_relax_frag (fix_insts
, fix_num
, var_insts
, var_num
, add_symbol
);
4224 else if (add_number
>= -0x8000 && add_number
<= 0x7fff)
4226 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4227 sprintf (tmp
, "lw_pic r%d, %s", reg_rd
, S_GET_NAME (add_symbol
));
4228 if (s7_append_insn (tmp
, true) == (int) s7_FAIL
)
4235 For an external symbol: addi rD, <constant> */
4236 sprintf (tmp
, "addi r%d, %d", reg_rd
, (int) add_number
);
4237 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4240 memcpy (&fix_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4243 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
4244 sprintf (tmp
, "addi_s_pic r%d, %s + %d", reg_rd
,
4245 S_GET_NAME (add_symbol
), (int) add_number
);
4246 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4249 memcpy (&var_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4250 s7_build_relax_frag (fix_insts
, fix_num
, var_insts
, var_num
, add_symbol
);
4254 int hi
= (add_number
>> 16) & 0x0000FFFF;
4255 int lo
= add_number
& 0x0000FFFF;
4257 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4258 sprintf (tmp
, "lw_pic r%d, %s", reg_rd
, S_GET_NAME (add_symbol
));
4259 if (s7_append_insn (tmp
, true) == (int) s7_FAIL
)
4266 For an external symbol: ldis r1, HI%<constant> */
4267 sprintf (tmp
, "ldis r1, %d", hi
);
4268 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4271 memcpy (&fix_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4274 For a local symbol: ldis r1, HI%<constant>
4275 but, if lo is out of 16 bit, make hi plus 1 */
4276 if ((lo
< -0x8000) || (lo
> 0x7fff))
4280 sprintf (tmp
, "ldis_pic r1, %d", hi
);
4281 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4284 memcpy (&var_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4285 s7_build_relax_frag (fix_insts
, fix_num
, var_insts
, var_num
, add_symbol
);
4291 For an external symbol: ori r1, LO%<constant> */
4292 sprintf (tmp
, "ori r1, %d", lo
);
4293 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4296 memcpy (&fix_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4299 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4300 sprintf (tmp
, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol
), lo
);
4301 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4304 memcpy (&var_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4305 s7_build_relax_frag (fix_insts
, fix_num
, var_insts
, var_num
, add_symbol
);
4307 /* Insn 4: add rD, rD, r1 */
4308 sprintf (tmp
, "add r%d, r%d, r1", reg_rd
, reg_rd
);
4309 if (s7_append_insn (tmp
, true) == (int) s7_FAIL
)
4312 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4322 s7_do_macro_la_rdi32 (char *str
)
4326 s7_skip_whitespace (str
);
4327 if ((reg_rd
= s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
4328 || s7_skip_past_comma (&str
) == (int) s7_FAIL
)
4334 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
4335 char *keep_data
= str
;
4337 /* Check immediate value. */
4338 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
)
4340 s7_inst
.error
= _("expression error");
4343 else if ((s7_inst
.reloc
.exp
.X_add_symbol
== NULL
)
4344 && (s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, _IMM32
, 0) == (int) s7_FAIL
))
4346 s7_inst
.error
= _("value not in range [0, 0xffffffff]");
4353 /* la rd, simm16. */
4354 if (s7_data_op2 (&str
, 1, _SIMM16_LA
) != (int) s7_FAIL
)
4356 s7_end_of_line (str
);
4359 /* la rd, imm32 or la rd, label. */
4362 s7_SET_INSN_ERROR (NULL
);
4364 if ((s7_data_op2 (&str
, 1, _VALUE_HI16
) == (int) s7_FAIL
)
4365 || (s7_end_of_line (str
) == (int) s7_FAIL
))
4371 if ((s7_score_pic
== s7_NO_PIC
) || (!s7_inst
.reloc
.exp
.X_add_symbol
))
4373 sprintf (append_str
, "ld_i32hi r%d, %s", reg_rd
, keep_data
);
4374 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
4377 sprintf (append_str
, "ld_i32lo r%d, %s", reg_rd
, keep_data
);
4378 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
4383 gas_assert (s7_inst
.reloc
.exp
.X_add_symbol
);
4384 s7_build_la_pic (reg_rd
, s7_inst
.reloc
.exp
);
4387 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4397 s7_do_macro_li_rdi32 (char *str
)
4401 s7_skip_whitespace (str
);
4402 if ((reg_rd
= s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
4403 || s7_skip_past_comma (&str
) == (int) s7_FAIL
)
4409 char *keep_data
= str
;
4411 /* Check immediate value. */
4412 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
)
4414 s7_inst
.error
= _("expression error");
4417 else if (!(s7_inst
.reloc
.exp
.X_add_number
>= -0xffffffffLL
4418 && s7_inst
.reloc
.exp
.X_add_number
<= 0xffffffffLL
))
4420 s7_inst
.error
= _("value not in range [-0xffffffff, 0xffffffff]");
4427 /* li rd, simm16. */
4428 if (s7_data_op2 (&str
, 1, _SIMM16_LA
) != (int) s7_FAIL
)
4430 s7_end_of_line (str
);
4436 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
4440 if ((s7_data_op2 (&str
, 1, _VALUE_HI16
) == (int) s7_FAIL
)
4441 || (s7_end_of_line (str
) == (int) s7_FAIL
))
4445 else if (s7_inst
.reloc
.exp
.X_add_symbol
)
4447 s7_inst
.error
= _("li rd label isn't correct instruction form");
4452 sprintf (append_str
, "ld_i32hi r%d, %s", reg_rd
, keep_data
);
4454 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
4458 sprintf (append_str
, "ld_i32lo r%d, %s", reg_rd
, keep_data
);
4459 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
4462 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4470 /* Handle mul/mulu/div/divu/rem/remu. */
4473 s7_do_macro_mul_rdrsrs (char *str
)
4479 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
4481 if (s7_university_version
== 1)
4482 as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV
);
4484 strcpy (append_str
, str
);
4485 backupstr
= append_str
;
4486 s7_skip_whitespace (backupstr
);
4487 if (((reg_rd
= s7_reg_required_here (&backupstr
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4488 || (s7_skip_past_comma (&backupstr
) == (int) s7_FAIL
)
4489 || ((reg_rs1
= s7_reg_required_here (&backupstr
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
))
4491 s7_inst
.error
= s7_BAD_ARGS
;
4495 if (s7_skip_past_comma (&backupstr
) == (int) s7_FAIL
)
4497 /* rem/remu rA, rB is error format. */
4498 if (strcmp (s7_inst
.name
, "rem") == 0 || strcmp (s7_inst
.name
, "remu") == 0)
4500 s7_SET_INSN_ERROR (s7_BAD_ARGS
);
4504 s7_SET_INSN_ERROR (NULL
);
4511 s7_SET_INSN_ERROR (NULL
);
4512 if (((reg_rs2
= s7_reg_required_here (&backupstr
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4513 || (s7_end_of_line (backupstr
) == (int) s7_FAIL
))
4519 char append_str1
[s7_MAX_LITERAL_POOL_SIZE
];
4521 if (strcmp (s7_inst
.name
, "rem") == 0)
4523 sprintf (append_str
, "mul r%d, r%d", reg_rs1
, reg_rs2
);
4524 sprintf (append_str1
, "mfceh r%d", reg_rd
);
4526 else if (strcmp (s7_inst
.name
, "remu") == 0)
4528 sprintf (append_str
, "mulu r%d, r%d", reg_rs1
, reg_rs2
);
4529 sprintf (append_str1
, "mfceh r%d", reg_rd
);
4533 sprintf (append_str
, "%s r%d, r%d", s7_inst
.name
, reg_rs1
, reg_rs2
);
4534 sprintf (append_str1
, "mfcel r%d", reg_rd
);
4537 /* Output mul/mulu or div/divu or rem/remu. */
4538 if (s7_append_insn (append_str
, true) == (int) s7_FAIL
)
4541 /* Output mfcel or mfceh. */
4542 if (s7_append_insn (append_str1
, true) == (int) s7_FAIL
)
4545 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4552 s7_exp_macro_ldst_abs (char *str
)
4555 char *backupstr
, *tmp
;
4556 char append_str
[s7_MAX_LITERAL_POOL_SIZE
];
4557 char verifystr
[s7_MAX_LITERAL_POOL_SIZE
];
4558 struct s7_score_it inst_backup
;
4563 memcpy (&inst_backup
, &s7_inst
, sizeof (struct s7_score_it
));
4565 strcpy (verifystr
, str
);
4566 backupstr
= verifystr
;
4567 s7_skip_whitespace (backupstr
);
4568 if ((reg_rd
= s7_reg_required_here (&backupstr
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4572 if (s7_skip_past_comma (&backupstr
) == (int) s7_FAIL
)
4576 sprintf (append_str
, "li r1 %s", backupstr
);
4577 s7_append_insn (append_str
, true);
4579 memcpy (&s7_inst
, &inst_backup
, sizeof (struct s7_score_it
));
4580 sprintf (append_str
, " r%d, [r1,0]", reg_rd
);
4581 s7_do_ldst_insn (append_str
);
4587 s7_nopic_need_relax (symbolS
* sym
, int before_relaxing
)
4591 else if (s7_USE_GLOBAL_POINTER_OPT
&& s7_g_switch_value
> 0)
4593 const char *symname
;
4594 const char *segname
;
4596 /* Find out whether this symbol can be referenced off the $gp
4597 register. It can be if it is smaller than the -G size or if
4598 it is in the .sdata or .sbss section. Certain symbols can
4599 not be referenced off the $gp, although it appears as though
4601 symname
= S_GET_NAME (sym
);
4603 && (strcmp (symname
, "eprol") == 0
4604 || strcmp (symname
, "etext") == 0
4605 || strcmp (symname
, "_gp") == 0
4606 || strcmp (symname
, "edata") == 0
4607 || strcmp (symname
, "_fbss") == 0
4608 || strcmp (symname
, "_fdata") == 0
4609 || strcmp (symname
, "_ftext") == 0
4610 || strcmp (symname
, "end") == 0
4611 || strcmp (symname
, GP_DISP_LABEL
) == 0))
4615 else if ((!S_IS_DEFINED (sym
) || S_IS_COMMON (sym
)) && (0
4616 /* We must defer this decision until after the whole file has been read,
4617 since there might be a .extern after the first use of this symbol. */
4619 && S_GET_VALUE (sym
) == 0)
4620 || (S_GET_VALUE (sym
) != 0
4621 && S_GET_VALUE (sym
) <= s7_g_switch_value
)))
4626 segname
= segment_name (S_GET_SEGMENT (sym
));
4627 return (strcmp (segname
, ".sdata") != 0
4628 && strcmp (segname
, ".sbss") != 0
4629 && !startswith (segname
, ".sdata.")
4630 && !startswith (segname
, ".gnu.linkonce.s."));
4632 /* We are not optimizing for the $gp register. */
4637 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4638 external symbol first and local symbol second. */
4641 s7_build_lwst_pic (int reg_rd
, expressionS exp
, const char *insn_name
)
4643 symbolS
*add_symbol
= exp
.X_add_symbol
;
4644 int add_number
= exp
.X_add_number
;
4645 struct s7_score_it fix_insts
[s7_RELAX_INST_NUM
];
4646 struct s7_score_it var_insts
[s7_RELAX_INST_NUM
];
4649 char tmp
[s7_MAX_LITERAL_POOL_SIZE
];
4655 if ((add_number
== 0) || (add_number
>= -0x8000 && add_number
<= 0x7fff))
4660 /* For an external symbol, two insns are generated;
4661 For a local symbol, three insns are generated. */
4663 For an external symbol: lw rD, <sym>($gp)
4664 (BFD_RELOC_SCORE_GOT15) */
4665 sprintf (tmp
, "lw_pic r1, %s", S_GET_NAME (add_symbol
));
4666 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4669 memcpy (&fix_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4672 For a local symbol :
4673 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4674 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4675 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_GOT15
;
4676 memcpy (&var_insts
[0], &s7_inst
, sizeof (struct s7_score_it
));
4677 sprintf (tmp
, "addi_s_pic r1, %s", S_GET_NAME (add_symbol
));
4678 if (s7_append_insn (tmp
, false) == (int) s7_FAIL
)
4681 memcpy (&var_insts
[1], &s7_inst
, sizeof (struct s7_score_it
));
4682 s7_build_relax_frag (fix_insts
, fix_num
, var_insts
, var_num
, add_symbol
);
4684 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4685 sprintf (tmp
, "%s r%d, [r1, %d]", insn_name
, reg_rd
, add_number
);
4686 if (s7_append_insn (tmp
, true) == (int) s7_FAIL
)
4689 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4694 s7_inst
.error
= _("PIC code offset overflow (max 16 signed bits)");
4702 s7_do_macro_ldst_label (char *str
)
4710 char *absolute_value
;
4711 char append_str
[3][s7_MAX_LITERAL_POOL_SIZE
];
4712 char verifystr
[s7_MAX_LITERAL_POOL_SIZE
];
4713 struct s7_score_it inst_backup
;
4714 struct s7_score_it inst_expand
[3];
4715 struct s7_score_it inst_main
;
4717 memcpy (&inst_backup
, &s7_inst
, sizeof (struct s7_score_it
));
4718 strcpy (verifystr
, str
);
4719 backup_str
= verifystr
;
4721 s7_skip_whitespace (backup_str
);
4722 if ((reg_rd
= s7_reg_required_here (&backup_str
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4725 if (s7_skip_past_comma (&backup_str
) == (int) s7_FAIL
)
4728 label_str
= backup_str
;
4730 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4731 if (*backup_str
== '[')
4733 s7_inst
.type
= Rd_rvalueRs_preSI12
;
4734 s7_do_ldst_insn (str
);
4738 /* Ld/st rD, imm. */
4739 absolute_value
= backup_str
;
4740 s7_inst
.type
= Rd_rvalueRs_SI15
;
4742 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &backup_str
) == (int) s7_FAIL
)
4744 s7_inst
.error
= _("expression error");
4747 else if ((s7_inst
.reloc
.exp
.X_add_symbol
== NULL
)
4748 && (s7_validate_immediate (s7_inst
.reloc
.exp
.X_add_number
, _VALUE
, 0) == (int) s7_FAIL
))
4750 s7_inst
.error
= _("value not in range [0, 0x7fffffff]");
4753 else if (s7_end_of_line (backup_str
) == (int) s7_FAIL
)
4755 s7_inst
.error
= _("end on line error");
4760 if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
4762 memcpy (&s7_inst
, &inst_backup
, sizeof (struct s7_score_it
));
4763 s7_exp_macro_ldst_abs (str
);
4768 /* Ld/st rD, label. */
4769 s7_inst
.type
= Rd_rvalueRs_SI15
;
4770 backup_str
= absolute_value
;
4771 if ((s7_data_op2 (&backup_str
, 1, _GP_IMM15
) == (int) s7_FAIL
)
4772 || (s7_end_of_line (backup_str
) == (int) s7_FAIL
))
4778 if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
4781 s7_inst
.error
= s7_BAD_ARGS
;
4786 if (s7_score_pic
== s7_PIC
)
4789 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
4790 s7_build_lwst_pic (reg_rd
, s7_inst
.reloc
.exp
,
4791 s7_score_ldst_insns
[ldst_idx
* 3 + 0].template_name
);
4796 if ((s7_inst
.reloc
.exp
.X_add_number
<= 0x3fff)
4797 && (s7_inst
.reloc
.exp
.X_add_number
>= -0x4000)
4798 && (!s7_nopic_need_relax (s7_inst
.reloc
.exp
.X_add_symbol
, 1)))
4802 /* Assign the real opcode. */
4803 ldst_idx
= s7_inst
.instruction
& OPC_PSEUDOLDST_MASK
;
4804 s7_inst
.instruction
&= ~OPC_PSEUDOLDST_MASK
;
4805 s7_inst
.instruction
|= s7_score_ldst_insns
[ldst_idx
* 3 + 0].value
;
4806 s7_inst
.instruction
|= reg_rd
<< 20;
4807 s7_inst
.instruction
|= s7_GP
<< 15;
4808 s7_inst
.relax_inst
= 0x8000;
4809 s7_inst
.relax_size
= 0;
4815 /* Backup s7_inst. */
4816 memcpy (&inst_main
, &s7_inst
, sizeof (struct s7_score_it
));
4820 /* Determine which instructions should be output. */
4821 sprintf (append_str
[0], "ld_i32hi r1, %s", label_str
);
4822 sprintf (append_str
[1], "ld_i32lo r1, %s", label_str
);
4823 sprintf (append_str
[2], "%s r%d, [r1, 0]", inst_backup
.name
, reg_rd
);
4825 /* Generate three instructions.
4827 ld/st rd, [r1, 0] */
4828 for (i
= 0; i
< 3; i
++)
4830 if (s7_append_insn (append_str
[i
], false) == (int) s7_FAIL
)
4833 memcpy (&inst_expand
[i
], &s7_inst
, sizeof (struct s7_score_it
));
4840 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4841 inst_main
.instruction
= s7_adjust_paritybit (inst_main
.instruction
, s7_GET_INSN_CLASS (inst_main
.type
));
4842 inst_main
.relax_size
= inst_expand
[0].size
+ inst_expand
[1].size
+ inst_expand
[2].size
;
4843 inst_main
.type
= Insn_GP
;
4845 for (i
= 0; i
< 3; i
++)
4846 inst_expand
[i
].instruction
= s7_adjust_paritybit (inst_expand
[i
].instruction
4847 , s7_GET_INSN_CLASS (inst_expand
[i
].type
));
4849 /* Check data dependency. */
4850 s7_handle_dependency (&inst_main
);
4852 /* Start a new frag if frag_now is not empty. */
4853 if (frag_now_fix () != 0)
4855 if (!frag_now
->tc_frag_data
.is_insn
)
4856 frag_wane (frag_now
);
4862 /* Write fr_fix part. */
4863 p
= frag_more (inst_main
.size
);
4864 s7_number_to_chars (p
, inst_main
.instruction
, inst_main
.size
);
4866 if (inst_main
.reloc
.type
!= BFD_RELOC_NONE
)
4868 s7_fix_new_score (frag_now
, p
- frag_now
->fr_literal
, inst_main
.size
,
4869 &inst_main
.reloc
.exp
, inst_main
.reloc
.pc_rel
, inst_main
.reloc
.type
);
4873 dwarf2_emit_insn (inst_main
.size
);
4876 /* s7_GP instruction can not do optimization, only can do relax between
4877 1 instruction and 3 instructions. */
4878 p
= frag_var (rs_machine_dependent
, inst_main
.relax_size
+ s7_RELAX_PAD_BYTE
, 0,
4879 s7_RELAX_ENCODE (inst_main
.size
, inst_main
.relax_size
, inst_main
.type
, 0, 4, 0),
4880 inst_main
.reloc
.exp
.X_add_symbol
, 0, NULL
);
4882 /* Write fr_var part.
4883 no calling s7_gen_insn_frag, no fixS will be generated. */
4884 s7_number_to_chars (p
, inst_expand
[0].instruction
, inst_expand
[0].size
);
4885 p
+= inst_expand
[0].size
;
4886 s7_number_to_chars (p
, inst_expand
[1].instruction
, inst_expand
[1].size
);
4887 p
+= inst_expand
[1].size
;
4888 s7_number_to_chars (p
, inst_expand
[2].instruction
, inst_expand
[2].size
);
4892 s7_gen_insn_frag (&inst_expand
[0], NULL
);
4893 s7_gen_insn_frag (&inst_expand
[1], NULL
);
4894 s7_gen_insn_frag (&inst_expand
[2], NULL
);
4898 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4903 s7_do_lw_pic (char *str
)
4907 s7_skip_whitespace (str
);
4908 if (((reg_rd
= s7_reg_required_here (&str
, 20, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
4909 || (s7_skip_past_comma (&str
) == (int) s7_FAIL
)
4910 || (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
)
4911 || (s7_end_of_line (str
) == (int) s7_FAIL
))
4917 if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
4920 s7_inst
.error
= s7_BAD_ARGS
;
4925 s7_inst
.instruction
|= s7_GP
<< 15;
4926 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_GOT15
;
4931 s7_do_empty (char *str
)
4934 if (s7_university_version
== 1)
4936 if (((s7_inst
.instruction
& 0x3e0003ff) == 0x0c000004)
4937 || ((s7_inst
.instruction
& 0x3e0003ff) == 0x0c000024)
4938 || ((s7_inst
.instruction
& 0x3e0003ff) == 0x0c000044)
4939 || ((s7_inst
.instruction
& 0x3e0003ff) == 0x0c000064))
4941 s7_inst
.error
= s7_ERR_FOR_SCORE5U_MMU
;
4945 if (s7_end_of_line (str
) == (int) s7_FAIL
)
4948 if (s7_inst
.relax_inst
!= 0x8000)
4950 if (s7_inst
.type
== NO_OPD
)
4952 s7_inst
.relax_size
= 2;
4956 s7_inst
.relax_size
= 4;
4962 s7_do_jump (char *str
)
4966 s7_skip_whitespace (str
);
4967 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
4968 || s7_end_of_line (str
) == (int) s7_FAIL
)
4971 if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
4973 s7_inst
.error
= _("lacking label ");
4977 if (!(s7_inst
.reloc
.exp
.X_add_number
>= -16777216
4978 && s7_inst
.reloc
.exp
.X_add_number
<= 16777215))
4980 s7_inst
.error
= _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4984 save_in
= input_line_pointer
;
4985 input_line_pointer
= str
;
4986 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_JMP
;
4987 s7_inst
.reloc
.pc_rel
= 1;
4988 input_line_pointer
= save_in
;
4992 s7_do16_jump (char *str
)
4994 s7_skip_whitespace (str
);
4995 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
4996 || s7_end_of_line (str
) == (int) s7_FAIL
)
5000 else if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
5002 s7_inst
.error
= _("lacking label ");
5005 else if (!(s7_inst
.reloc
.exp
.X_add_number
>= 0
5006 && s7_inst
.reloc
.exp
.X_add_number
<= 4095))
5008 s7_inst
.error
= _("invalid constant: 12 bit expression not in range [0, 4095]");
5012 s7_inst
.reloc
.type
= BFD_RELOC_SCORE16_JMP
;
5013 s7_inst
.reloc
.pc_rel
= 1;
5017 s7_do_branch (char *str
)
5019 unsigned long abs_value
= 0;
5021 if (s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
5022 || s7_end_of_line (str
) == (int) s7_FAIL
)
5026 else if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
5028 s7_inst
.error
= _("lacking label ");
5031 else if (!(s7_inst
.reloc
.exp
.X_add_number
>= -524288
5032 && s7_inst
.reloc
.exp
.X_add_number
<= 524287))
5034 s7_inst
.error
= _("invalid constant: 20 bit expression not in range -2^19..2^19");
5038 s7_inst
.reloc
.type
= BFD_RELOC_SCORE_BRANCH
;
5039 s7_inst
.reloc
.pc_rel
= 1;
5041 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
5042 s7_inst
.instruction
|= (s7_inst
.reloc
.exp
.X_add_number
& 0x3fe) | ((s7_inst
.reloc
.exp
.X_add_number
& 0xffc00) << 5);
5044 /* Compute 16 bit branch instruction. */
5045 if ((s7_inst
.relax_inst
!= 0x8000) && (abs_value
& 0xfffffe00) == 0)
5047 s7_inst
.relax_inst
|= (((s7_inst
.instruction
>> 10) & 0xf) << 8);
5048 s7_inst
.relax_inst
|= ((s7_inst
.reloc
.exp
.X_add_number
>> 1) & 0xff);
5049 s7_inst
.relax_size
= 2;
5053 s7_inst
.relax_inst
= 0x8000;
5058 s7_do16_branch (char *str
)
5060 if ((s7_my_get_expression (&s7_inst
.reloc
.exp
, &str
) == (int) s7_FAIL
5061 || s7_end_of_line (str
) == (int) s7_FAIL
))
5065 else if (s7_inst
.reloc
.exp
.X_add_symbol
== 0)
5067 s7_inst
.error
= _("lacking label");
5069 else if (!(s7_inst
.reloc
.exp
.X_add_number
>= -512
5070 && s7_inst
.reloc
.exp
.X_add_number
<= 511))
5072 s7_inst
.error
= _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5076 s7_inst
.reloc
.type
= BFD_RELOC_SCORE16_BRANCH
;
5077 s7_inst
.reloc
.pc_rel
= 1;
5078 s7_inst
.instruction
|= ((s7_inst
.reloc
.exp
.X_add_number
>> 1) & 0xff);
5082 /* Iterate over the base tables to create the instruction patterns. */
5085 s7_build_score_ops_hsh (void)
5088 static struct obstack insn_obstack
;
5090 obstack_begin (&insn_obstack
, 4000);
5091 for (i
= 0; i
< sizeof (s7_score_insns
) / sizeof (struct s7_asm_opcode
); i
++)
5093 const struct s7_asm_opcode
*insn
= s7_score_insns
+ i
;
5094 size_t len
= strlen (insn
->template_name
);
5095 struct s7_asm_opcode
*new_opcode
;
5096 char *template_name
;
5097 new_opcode
= (struct s7_asm_opcode
*)
5098 obstack_alloc (&insn_obstack
, sizeof (struct s7_asm_opcode
));
5099 template_name
= (char *) obstack_alloc (&insn_obstack
, len
+ 1);
5101 strcpy (template_name
, insn
->template_name
);
5102 new_opcode
->template_name
= template_name
;
5103 new_opcode
->parms
= insn
->parms
;
5104 new_opcode
->value
= insn
->value
;
5105 new_opcode
->relax_value
= insn
->relax_value
;
5106 new_opcode
->type
= insn
->type
;
5107 new_opcode
->bitmask
= insn
->bitmask
;
5108 str_hash_insert (s7_score_ops_hsh
, new_opcode
->template_name
,
5114 s7_build_dependency_insn_hsh (void)
5117 static struct obstack dependency_obstack
;
5119 obstack_begin (&dependency_obstack
, 4000);
5120 for (i
= 0; i
< ARRAY_SIZE (s7_insn_to_dependency_table
); i
++)
5122 const struct s7_insn_to_dependency
*tmp
= s7_insn_to_dependency_table
+ i
;
5123 size_t len
= strlen (tmp
->insn_name
);
5124 struct s7_insn_to_dependency
*new_i2d
;
5127 new_i2d
= (struct s7_insn_to_dependency
*)
5128 obstack_alloc (&dependency_obstack
,
5129 sizeof (struct s7_insn_to_dependency
));
5130 insn_name
= (char *) obstack_alloc (&dependency_obstack
, len
+ 1);
5132 strcpy (insn_name
, tmp
->insn_name
);
5133 new_i2d
->insn_name
= insn_name
;
5134 new_i2d
->type
= tmp
->type
;
5135 str_hash_insert (s7_dependency_insn_hsh
, new_i2d
->insn_name
, new_i2d
, 0);
5140 s7_md_chars_to_number (char *buf
, int n
)
5143 unsigned char *where
= (unsigned char *) buf
;
5145 if (target_big_endian
)
5150 result
|= (*where
++ & 255);
5158 result
|= (where
[n
] & 255);
5165 /* Return true if the given symbol should be considered local for s7_PIC. */
5168 s7_pic_need_relax (symbolS
*sym
, asection
*segtype
)
5173 /* Handle the case of a symbol equated to another symbol. */
5174 while (symbol_equated_reloc_p (sym
))
5178 /* It's possible to get a loop here in a badly written
5180 n
= symbol_get_value_expression (sym
)->X_add_symbol
;
5186 symsec
= S_GET_SEGMENT (sym
);
5188 /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5190 if (symsec
!= segtype
&& ! S_IS_LOCAL (sym
))
5192 if ((bfd_section_flags (symsec
) & SEC_LINK_ONCE
) != 0)
5195 /* The GNU toolchain uses an extension for ELF: a section
5196 beginning with the magic string .gnu.linkonce is a linkonce
5198 if (startswith (segment_name (symsec
), ".gnu.linkonce"))
5202 /* This must duplicate the test in adjust_reloc_syms. */
5203 return (!bfd_is_und_section (symsec
)
5204 && !bfd_is_abs_section (symsec
)
5205 && !bfd_is_com_section (symsec
)
5208 /* A global or weak symbol is treated as external. */
5209 && (OUTPUT_FLAVOR
!= bfd_target_elf_flavour
5210 || (! S_IS_WEAK (sym
) && ! S_IS_EXTERNAL (sym
)))
5216 s7_judge_size_before_relax (fragS
* fragp
, asection
*sec
)
5220 if (s7_score_pic
== s7_NO_PIC
)
5221 change
= s7_nopic_need_relax (fragp
->fr_symbol
, 0);
5223 change
= s7_pic_need_relax (fragp
->fr_symbol
, sec
);
5227 /* Only at the first time determining whether s7_GP instruction relax should be done,
5228 return the difference between instruction size and instruction relax size. */
5229 if (fragp
->fr_opcode
== NULL
)
5231 fragp
->fr_fix
= s7_RELAX_NEW (fragp
->fr_subtype
);
5232 fragp
->fr_opcode
= fragp
->fr_literal
+ s7_RELAX_RELOC1 (fragp
->fr_subtype
);
5233 return s7_RELAX_NEW (fragp
->fr_subtype
) - s7_RELAX_OLD (fragp
->fr_subtype
);
5241 s7_b32_relax_to_b16 (fragS
* fragp
)
5244 int relaxable_p
= 0;
5245 int frag_addr
= fragp
->fr_address
+ fragp
->insn_addr
;
5247 addressT symbol_address
= 0;
5250 unsigned long value
;
5251 unsigned long abs_value
;
5253 /* FIXME : here may be able to modify better .
5254 I don't know how to get the fragp's section ,
5255 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5256 is different from the symbol's. */
5258 relaxable_p
= s7_RELAX_OPT (fragp
->fr_subtype
);
5260 s
= fragp
->fr_symbol
;
5261 /* b/bl immediate */
5265 symbol_address
= (addressT
) symbol_get_frag (s
)->fr_address
;
5267 value
= s7_md_chars_to_number (fragp
->fr_literal
, s7_INSN_SIZE
);
5269 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
5270 offset
= ((value
& 0x3ff0000) >> 6) | (value
& 0x3fe);
5271 if ((offset
& 0x80000) == 0x80000)
5272 offset
|= 0xfff00000;
5274 abs_value
= offset
+ symbol_address
- frag_addr
;
5275 if ((abs_value
& 0x80000000) == 0x80000000)
5276 abs_value
= 0xffffffff - abs_value
+ 1;
5278 /* Relax branch 32 to branch 16. */
5279 if (relaxable_p
&& ((abs_value
& 0xffffff00) == 0)
5280 && (S_IS_DEFINED (s
) && !S_IS_COMMON (s
) && !S_IS_EXTERNAL (s
)))
5286 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
5287 fragp
->fr_opcode
= NULL
;
5288 fragp
->fr_subtype
= s7_RELAX_OPT_CLEAR (fragp
->fr_subtype
);
5295 s7_parse_pce_inst (char *insnstr
)
5300 char first
[s7_MAX_LITERAL_POOL_SIZE
];
5301 char second
[s7_MAX_LITERAL_POOL_SIZE
];
5302 struct s7_score_it pec_part_1
;
5304 /* Get first part string of PCE. */
5305 p
= strstr (insnstr
, "||");
5308 strcpy (first
, insnstr
);
5310 /* Get second part string of PCE. */
5315 s7_parse_16_32_inst (first
, false);
5319 memcpy (&pec_part_1
, &s7_inst
, sizeof (s7_inst
));
5328 s7_parse_16_32_inst (second
, false);
5332 if ( ((pec_part_1
.size
== s7_INSN_SIZE
) && (s7_inst
.size
== s7_INSN_SIZE
))
5333 || ((pec_part_1
.size
== s7_INSN_SIZE
) && (s7_inst
.size
== s7_INSN16_SIZE
))
5334 || ((pec_part_1
.size
== s7_INSN16_SIZE
) && (s7_inst
.size
== s7_INSN_SIZE
)))
5336 s7_inst
.error
= _("pce instruction error (16 bit || 16 bit)'");
5337 strcpy (s7_inst
.str
, insnstr
);
5342 s7_gen_insn_frag (&pec_part_1
, &s7_inst
);
5348 s7_insert_reg (const struct s7_reg_entry
*r
, htab_t htab
)
5351 int len
= strlen (r
->name
) + 2;
5352 char *buf
= XNEWVEC (char, len
);
5353 char *buf2
= XNEWVEC (char, len
);
5355 strcpy (buf
+ i
, r
->name
);
5356 for (i
= 0; buf
[i
]; i
++)
5358 buf2
[i
] = TOUPPER (buf
[i
]);
5362 str_hash_insert (htab
, buf
, r
, 0);
5363 str_hash_insert (htab
, buf2
, r
, 0);
5367 s7_build_reg_hsh (struct s7_reg_map
*map
)
5369 const struct s7_reg_entry
*r
;
5371 map
->htab
= str_htab_create ();
5372 for (r
= map
->names
; r
->name
!= NULL
; r
++)
5373 s7_insert_reg (r
, map
->htab
);
5378 /* If we change section we must dump the literal pool first. */
5380 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED
)
5382 subseg_set (bss_section
, (subsegT
) get_absolute_expression ());
5383 demand_empty_rest_of_line ();
5387 s7_s_score_text (int ignore
)
5389 obj_elf_text (ignore
);
5390 record_alignment (now_seg
, 2);
5394 s7_s_section (int ignore
)
5396 obj_elf_section (ignore
);
5397 if ((bfd_section_flags (now_seg
) & SEC_CODE
) != 0)
5398 record_alignment (now_seg
, 2);
5403 s7_s_change_sec (int sec
)
5408 /* The ELF backend needs to know that we are changing sections, so
5409 that .previous works correctly. We could do something like check
5410 for an obj_section_change_hook macro, but that might be confusing
5411 as it would not be appropriate to use it in the section changing
5412 functions in read.c, since obj-elf.c intercepts those. FIXME:
5413 This should be cleaner, somehow. */
5414 obj_elf_section_change_hook ();
5419 seg
= subseg_new (s7_RDATA_SECTION_NAME
, (subsegT
) get_absolute_expression ());
5420 bfd_set_section_flags (seg
, (SEC_ALLOC
| SEC_LOAD
| SEC_READONLY
5421 | SEC_RELOC
| SEC_DATA
));
5422 if (strcmp (TARGET_OS
, "elf") != 0)
5423 record_alignment (seg
, 4);
5424 demand_empty_rest_of_line ();
5427 seg
= subseg_new (".sdata", (subsegT
) get_absolute_expression ());
5428 bfd_set_section_flags (seg
, (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
5429 | SEC_DATA
| SEC_SMALL_DATA
));
5430 if (strcmp (TARGET_OS
, "elf") != 0)
5431 record_alignment (seg
, 4);
5432 demand_empty_rest_of_line ();
5438 s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED
)
5442 if (s7_cur_proc_ptr
== NULL
)
5444 as_warn (_(".mask outside of .ent"));
5445 demand_empty_rest_of_line ();
5448 if (get_absolute_expression_and_terminator (&mask
) != ',')
5450 as_warn (_("Bad .mask directive"));
5451 --input_line_pointer
;
5452 demand_empty_rest_of_line ();
5455 off
= get_absolute_expression ();
5456 s7_cur_proc_ptr
->reg_mask
= mask
;
5457 s7_cur_proc_ptr
->reg_offset
= off
;
5458 demand_empty_rest_of_line ();
5462 s7_get_symbol (void)
5468 c
= get_symbol_name (&name
);
5469 p
= (symbolS
*) symbol_find_or_make (name
);
5470 (void) restore_line_pointer (c
);
5475 s7_get_number (void)
5480 if (*input_line_pointer
== '-')
5482 ++input_line_pointer
;
5485 if (!ISDIGIT (*input_line_pointer
))
5486 as_bad (_("expected simple number"));
5487 if (input_line_pointer
[0] == '0')
5489 if (input_line_pointer
[1] == 'x')
5491 input_line_pointer
+= 2;
5492 while (ISXDIGIT (*input_line_pointer
))
5495 val
|= hex_value (*input_line_pointer
++);
5497 return negative
? -val
: val
;
5501 ++input_line_pointer
;
5502 while (ISDIGIT (*input_line_pointer
))
5505 val
|= *input_line_pointer
++ - '0';
5507 return negative
? -val
: val
;
5510 if (!ISDIGIT (*input_line_pointer
))
5512 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer
, *input_line_pointer
);
5513 as_warn (_("invalid number"));
5516 while (ISDIGIT (*input_line_pointer
))
5519 val
+= *input_line_pointer
++ - '0';
5521 return negative
? -val
: val
;
5524 /* The .aent and .ent directives. */
5527 s7_s_score_ent (int aent
)
5532 symbolP
= s7_get_symbol ();
5533 if (*input_line_pointer
== ',')
5534 ++input_line_pointer
;
5536 if (ISDIGIT (*input_line_pointer
) || *input_line_pointer
== '-')
5539 if ((bfd_section_flags (now_seg
) & SEC_CODE
) != 0)
5544 as_warn (_(".ent or .aent not in text section."));
5545 if (!aent
&& s7_cur_proc_ptr
)
5546 as_warn (_("missing .end"));
5549 s7_cur_proc_ptr
= &s7_cur_proc
;
5550 s7_cur_proc_ptr
->reg_mask
= 0xdeadbeaf;
5551 s7_cur_proc_ptr
->reg_offset
= 0xdeadbeaf;
5552 s7_cur_proc_ptr
->fpreg_mask
= 0xdeafbeaf;
5553 s7_cur_proc_ptr
->leaf
= 0xdeafbeaf;
5554 s7_cur_proc_ptr
->frame_offset
= 0xdeafbeaf;
5555 s7_cur_proc_ptr
->frame_reg
= 0xdeafbeaf;
5556 s7_cur_proc_ptr
->pc_reg
= 0xdeafbeaf;
5557 s7_cur_proc_ptr
->isym
= symbolP
;
5558 symbol_get_bfdsym (symbolP
)->flags
|= BSF_FUNCTION
;
5560 if (debug_type
== DEBUG_STABS
)
5561 stabs_generate_asm_func (S_GET_NAME (symbolP
), S_GET_NAME (symbolP
));
5563 demand_empty_rest_of_line ();
5567 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED
)
5574 backupstr
= input_line_pointer
;
5577 if (s7_cur_proc_ptr
== NULL
)
5579 as_warn (_(".frame outside of .ent"));
5580 demand_empty_rest_of_line ();
5583 s7_cur_proc_ptr
->frame_reg
= s7_reg_required_here ((&backupstr
), 0, s7_REG_TYPE_SCORE
);
5585 s7_skip_past_comma (&backupstr
);
5586 while (*backupstr
!= ',')
5588 str
[i
] = *backupstr
;
5596 s7_skip_past_comma (&backupstr
);
5597 s7_cur_proc_ptr
->frame_offset
= val
;
5598 s7_cur_proc_ptr
->pc_reg
= s7_reg_required_here ((&backupstr
), 0, s7_REG_TYPE_SCORE
);
5601 s7_skip_past_comma (&backupstr
);
5603 while (*backupstr
!= '\n')
5605 str
[i
] = *backupstr
;
5611 s7_cur_proc_ptr
->leaf
= val
;
5613 s7_skip_past_comma (&backupstr
);
5615 #endif /* OBJ_ELF */
5616 while (input_line_pointer
!= backupstr
)
5617 input_line_pointer
++;
5620 /* The .end directive. */
5623 s7_s_score_end (int x ATTRIBUTE_UNUSED
)
5628 /* Generate a .pdr section. */
5629 segT saved_seg
= now_seg
;
5630 subsegT saved_subseg
= now_subseg
;
5634 if (!is_end_of_line
[(unsigned char)*input_line_pointer
])
5636 p
= s7_get_symbol ();
5637 demand_empty_rest_of_line ();
5642 if ((bfd_section_flags (now_seg
) & SEC_CODE
) != 0)
5648 as_warn (_(".end not in text section"));
5649 if (!s7_cur_proc_ptr
)
5651 as_warn (_(".end directive without a preceding .ent directive."));
5652 demand_empty_rest_of_line ();
5657 gas_assert (S_GET_NAME (p
));
5658 if (strcmp (S_GET_NAME (p
), S_GET_NAME (s7_cur_proc_ptr
->isym
)))
5659 as_warn (_(".end symbol does not match .ent symbol."));
5660 if (debug_type
== DEBUG_STABS
)
5661 stabs_generate_asm_endfunc (S_GET_NAME (p
), S_GET_NAME (p
));
5664 as_warn (_(".end directive missing or unknown symbol"));
5666 if ((s7_cur_proc_ptr
->reg_mask
== 0xdeadbeaf) ||
5667 (s7_cur_proc_ptr
->reg_offset
== 0xdeadbeaf) ||
5668 (s7_cur_proc_ptr
->leaf
== 0xdeafbeaf) ||
5669 (s7_cur_proc_ptr
->frame_offset
== 0xdeafbeaf) ||
5670 (s7_cur_proc_ptr
->frame_reg
== 0xdeafbeaf) || (s7_cur_proc_ptr
->pc_reg
== 0xdeafbeaf));
5674 (void) frag_now_fix ();
5675 gas_assert (s7_pdr_seg
);
5676 subseg_set (s7_pdr_seg
, 0);
5677 /* Write the symbol. */
5678 exp
.X_op
= O_symbol
;
5679 exp
.X_add_symbol
= p
;
5680 exp
.X_add_number
= 0;
5681 emit_expr (&exp
, 4);
5682 fragp
= frag_more (7 * 4);
5683 s7_number_to_chars (fragp
, (valueT
) s7_cur_proc_ptr
->reg_mask
, 4);
5684 s7_number_to_chars (fragp
+ 4, (valueT
) s7_cur_proc_ptr
->reg_offset
, 4);
5685 s7_number_to_chars (fragp
+ 8, (valueT
) s7_cur_proc_ptr
->fpreg_mask
, 4);
5686 s7_number_to_chars (fragp
+ 12, (valueT
) s7_cur_proc_ptr
->leaf
, 4);
5687 s7_number_to_chars (fragp
+ 16, (valueT
) s7_cur_proc_ptr
->frame_offset
, 4);
5688 s7_number_to_chars (fragp
+ 20, (valueT
) s7_cur_proc_ptr
->frame_reg
, 4);
5689 s7_number_to_chars (fragp
+ 24, (valueT
) s7_cur_proc_ptr
->pc_reg
, 4);
5690 subseg_set (saved_seg
, saved_subseg
);
5693 s7_cur_proc_ptr
= NULL
;
5696 /* Handle the .set pseudo-op. */
5699 s7_s_score_set (int x ATTRIBUTE_UNUSED
)
5702 char name
[s7_MAX_LITERAL_POOL_SIZE
];
5703 char * orig_ilp
= input_line_pointer
;
5705 while (!is_end_of_line
[(unsigned char)*input_line_pointer
])
5707 name
[i
] = (char) * input_line_pointer
;
5709 ++input_line_pointer
;
5714 if (strcmp (name
, "nwarn") == 0)
5716 s7_warn_fix_data_dependency
= 0;
5718 else if (strcmp (name
, "fixdd") == 0)
5720 s7_fix_data_dependency
= 1;
5722 else if (strcmp (name
, "nofixdd") == 0)
5724 s7_fix_data_dependency
= 0;
5726 else if (strcmp (name
, "r1") == 0)
5730 else if (strcmp (name
, "nor1") == 0)
5734 else if (strcmp (name
, "optimize") == 0)
5738 else if (strcmp (name
, "volatile") == 0)
5742 else if (strcmp (name
, "pic") == 0)
5744 s7_score_pic
= s7_PIC
;
5748 input_line_pointer
= orig_ilp
;
5753 /* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the
5754 $gp register for the function based on the function address, which is in the register
5755 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5756 specially by the linker. The result is:
5757 ldis gp, %hi(GP_DISP_LABEL)
5758 ori gp, %low(GP_DISP_LABEL)
5759 add gp, gp, .cpload argument
5760 The .cpload argument is normally r29. */
5763 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED
)
5766 char insn_str
[s7_MAX_LITERAL_POOL_SIZE
];
5768 /* If we are not generating s7_PIC code, .cpload is ignored. */
5769 if (s7_score_pic
== s7_NO_PIC
)
5775 if ((reg
= s7_reg_required_here (&input_line_pointer
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
5778 demand_empty_rest_of_line ();
5780 sprintf (insn_str
, "ld_i32hi r%d, %s", s7_GP
, GP_DISP_LABEL
);
5781 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5784 sprintf (insn_str
, "ld_i32lo r%d, %s", s7_GP
, GP_DISP_LABEL
);
5785 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5788 sprintf (insn_str
, "add r%d, r%d, r%d", s7_GP
, s7_GP
, reg
);
5789 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5793 /* Handle the .cprestore pseudo-op. This stores $gp into a given
5794 offset from $sp. The offset is remembered, and after making a s7_PIC
5795 call $gp is restored from that location. */
5798 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED
)
5801 int cprestore_offset
;
5802 char insn_str
[s7_MAX_LITERAL_POOL_SIZE
];
5804 /* If we are not generating s7_PIC code, .cprestore is ignored. */
5805 if (s7_score_pic
== s7_NO_PIC
)
5811 if ((reg
= s7_reg_required_here (&input_line_pointer
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
5812 || s7_skip_past_comma (&input_line_pointer
) == (int) s7_FAIL
)
5817 cprestore_offset
= get_absolute_expression ();
5819 if (cprestore_offset
<= 0x3fff)
5821 sprintf (insn_str
, "sw r%d, [r%d, %d]", s7_GP
, reg
, cprestore_offset
);
5822 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5832 sprintf (insn_str
, "li r1, %d", cprestore_offset
);
5833 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5836 sprintf (insn_str
, "add r1, r1, r%d", reg
);
5837 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5840 sprintf (insn_str
, "sw r%d, [r1]", s7_GP
);
5841 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5847 demand_empty_rest_of_line ();
5850 /* Handle the .gpword pseudo-op. This is used when generating s7_PIC
5851 code. It generates a 32 bit s7_GP relative reloc. */
5854 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED
)
5859 /* When not generating s7_PIC code, this is treated as .word. */
5860 if (s7_score_pic
== s7_NO_PIC
)
5866 if (ex
.X_op
!= O_symbol
|| ex
.X_add_number
!= 0)
5868 as_bad (_("Unsupported use of .gpword"));
5869 ignore_rest_of_line ();
5872 s7_number_to_chars (p
, (valueT
) 0, 4);
5873 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, 4, &ex
, false, BFD_RELOC_GPREL32
);
5874 demand_empty_rest_of_line ();
5877 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
5878 tables in s7_PIC code. */
5881 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED
)
5884 char insn_str
[s7_MAX_LITERAL_POOL_SIZE
];
5886 /* If we are not generating s7_PIC code, .cpload is ignored. */
5887 if (s7_score_pic
== s7_NO_PIC
)
5893 if ((reg
= s7_reg_required_here (&input_line_pointer
, -1, s7_REG_TYPE_SCORE
)) == (int) s7_FAIL
)
5897 demand_empty_rest_of_line ();
5899 /* Add $gp to the register named as an argument. */
5900 sprintf (insn_str
, "add r%d, r%d, r%d", reg
, reg
, s7_GP
);
5901 if (s7_append_insn (insn_str
, true) == (int) s7_FAIL
)
5905 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5906 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
5911 else if ((SIZE) >= 4) \
5913 else if ((SIZE) >= 2) \
5922 s7_s_score_lcomm (int bytes_p
)
5929 segT current_seg
= now_seg
;
5930 subsegT current_subseg
= now_subseg
;
5931 const int max_alignment
= 15;
5933 segT bss_seg
= bss_section
;
5934 int needs_align
= 0;
5936 c
= get_symbol_name (&name
);
5937 p
= input_line_pointer
;
5942 as_bad (_("expected symbol name"));
5943 discard_rest_of_line ();
5947 SKIP_WHITESPACE_AFTER_NAME ();
5949 /* Accept an optional comma after the name. The comma used to be
5950 required, but Irix 5 cc does not generate it. */
5951 if (*input_line_pointer
== ',')
5953 ++input_line_pointer
;
5957 if (is_end_of_line
[(unsigned char)*input_line_pointer
])
5959 as_bad (_("missing size expression"));
5963 if ((temp
= get_absolute_expression ()) < 0)
5965 as_warn (_("BSS length (%d) < 0 ignored"), temp
);
5966 ignore_rest_of_line ();
5970 #if defined (TC_SCORE)
5971 if (OUTPUT_FLAVOR
== bfd_target_ecoff_flavour
|| OUTPUT_FLAVOR
== bfd_target_elf_flavour
)
5973 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
5974 if ((unsigned) temp
<= bfd_get_gp_size (stdoutput
))
5976 bss_seg
= subseg_new (".sbss", 1);
5977 seg_info (bss_seg
)->bss
= 1;
5978 if (!bfd_set_section_flags (bss_seg
, SEC_ALLOC
| SEC_SMALL_DATA
))
5979 as_warn (_("error setting flags for \".sbss\": %s"),
5980 bfd_errmsg (bfd_get_error ()));
5986 if (*input_line_pointer
== ',')
5988 ++input_line_pointer
;
5991 if (is_end_of_line
[(unsigned char)*input_line_pointer
])
5993 as_bad (_("missing alignment"));
5998 align
= get_absolute_expression ();
6005 TC_IMPLICIT_LCOMM_ALIGNMENT (temp
, align
);
6007 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6009 record_alignment (bss_seg
, align
);
6016 /* Convert to a power of 2. */
6021 for (i
= 0; align
!= 0; align
>>= 1, ++i
)
6027 if (align
> max_alignment
)
6029 align
= max_alignment
;
6030 as_warn (_("alignment too large; %d assumed"), align
);
6035 as_warn (_("alignment negative; 0 assumed"));
6038 record_alignment (bss_seg
, align
);
6042 /* Assume some objects may require alignment on some systems. */
6043 #if defined (TC_ALPHA) && ! defined (VMS)
6046 align
= ffs (temp
) - 1;
6047 if (temp
% (1 << align
))
6054 symbolP
= symbol_find_or_make (name
);
6058 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
6059 (OUTPUT_FLAVOR
!= bfd_target_aout_flavour
6060 || (S_GET_OTHER (symbolP
) == 0 && S_GET_DESC (symbolP
) == 0)) &&
6062 (S_GET_SEGMENT (symbolP
) == bss_seg
|| (!S_IS_DEFINED (symbolP
) && S_GET_VALUE (symbolP
) == 0)))
6066 subseg_set (bss_seg
, 1);
6069 frag_align (align
, 0, 0);
6071 /* Detach from old frag. */
6072 if (S_GET_SEGMENT (symbolP
) == bss_seg
)
6073 symbol_get_frag (symbolP
)->fr_symbol
= NULL
;
6075 symbol_set_frag (symbolP
, frag_now
);
6076 pfrag
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
, (offsetT
) temp
, NULL
);
6080 S_SET_SEGMENT (symbolP
, bss_seg
);
6083 /* The symbol may already have been created with a preceding
6084 ".globl" directive -- be careful not to step on storage class
6085 in that case. Otherwise, set it to static. */
6086 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
6088 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
6090 #endif /* OBJ_COFF */
6093 S_SET_SIZE (symbolP
, temp
);
6097 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP
));
6099 subseg_set (current_seg
, current_subseg
);
6101 demand_empty_rest_of_line ();
6113 s7_score_ops_hsh
= str_htab_create ();
6115 s7_build_score_ops_hsh ();
6117 s7_dependency_insn_hsh
= str_htab_create ();
6119 s7_build_dependency_insn_hsh ();
6121 for (i
= (int) REG_TYPE_FIRST
; i
< (int) s7_REG_TYPE_MAX
; i
++)
6122 s7_build_reg_hsh (s7_all_reg_maps
+ i
);
6124 /* Initialize dependency vector. */
6125 s7_init_dependency_vector ();
6127 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
6129 subseg
= now_subseg
;
6130 s7_pdr_seg
= subseg_new (".pdr", (subsegT
) 0);
6131 bfd_set_section_flags (s7_pdr_seg
, SEC_READONLY
| SEC_RELOC
| SEC_DEBUGGING
);
6132 bfd_set_section_alignment (s7_pdr_seg
, 2);
6133 subseg_set (seg
, subseg
);
6135 if (s7_USE_GLOBAL_POINTER_OPT
)
6136 bfd_set_gp_size (stdoutput
, s7_g_switch_value
);
6140 s7_assemble (char *str
)
6143 know (strlen (str
) < s7_MAX_LITERAL_POOL_SIZE
);
6145 memset (&s7_inst
, '\0', sizeof (s7_inst
));
6146 if (s7_INSN_IS_PCE_P (str
))
6147 s7_parse_pce_inst (str
);
6149 s7_parse_16_32_inst (str
, true);
6152 as_bad (_("%s -- `%s'"), s7_inst
.error
, s7_inst
.str
);
6155 /* We handle all bad expressions here, so that we can report the faulty
6156 instruction in the error message. */
6159 s7_operand (expressionS
* exp
)
6161 if (s7_in_my_get_expression
)
6163 exp
->X_op
= O_illegal
;
6164 if (s7_inst
.error
== NULL
)
6166 s7_inst
.error
= _("bad expression");
6171 /* Turn a string in input_line_pointer into a floating point constant
6172 of type TYPE, and store the appropriate bytes in *LITP. The number
6173 of LITTLENUMS emitted is stored in *SIZEP. An error message is
6174 returned, or NULL on OK.
6176 Note that fp constants aren't represent in the normal way on the ARM.
6177 In big endian mode, things are as expected. However, in little endian
6178 mode fp constants are big-endian word-wise, and little-endian byte-wise
6179 within the words. For example, (double) 1.1 in big endian mode is
6180 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6181 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6184 s7_atof (int type
, char *litP
, int *sizeP
)
6187 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6213 return _("bad call to MD_ATOF()");
6216 t
= atof_ieee (input_line_pointer
, type
, words
);
6218 input_line_pointer
= t
;
6221 if (target_big_endian
)
6223 for (i
= 0; i
< prec
; i
++)
6225 s7_number_to_chars (litP
, (valueT
) words
[i
], 2);
6231 for (i
= 0; i
< prec
; i
+= 2)
6233 s7_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
6234 s7_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
6242 /* Implementation of md_frag_check.
6243 Called after md_convert_frag(). */
6246 s7_frag_check (fragS
* fragp ATTRIBUTE_UNUSED
)
6248 know (fragp
->insn_addr
<= s7_RELAX_PAD_BYTE
);
6251 /* Implementation of TC_VALIDATE_FIX.
6252 Called before md_apply_fix() and after md_convert_frag(). */
6255 s7_validate_fix (fixS
*fixP
)
6257 fixP
->fx_where
+= fixP
->fx_frag
->insn_addr
;
6261 s7_force_relocation (struct fix
*fixp
)
6265 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
6266 || fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
6267 || fixp
->fx_r_type
== BFD_RELOC_SCORE_JMP
6268 || fixp
->fx_r_type
== BFD_RELOC_SCORE_BRANCH
6269 || fixp
->fx_r_type
== BFD_RELOC_SCORE16_JMP
6270 || fixp
->fx_r_type
== BFD_RELOC_SCORE16_BRANCH
)
6279 s7_fix_adjustable (fixS
* fixP
)
6281 if (fixP
->fx_addsy
== NULL
)
6285 else if (OUTPUT_FLAVOR
== bfd_target_elf_flavour
6286 && (S_IS_EXTERNAL (fixP
->fx_addsy
) || S_IS_WEAK (fixP
->fx_addsy
)))
6290 else if (fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
6291 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
6292 || fixP
->fx_r_type
== BFD_RELOC_SCORE_JMP
6293 || fixP
->fx_r_type
== BFD_RELOC_SCORE16_JMP
)
6302 s7_elf_final_processing (void)
6304 unsigned long val
= E_SCORE_MACH_SCORE7
;
6306 elf_elfheader (stdoutput
)->e_machine
= EM_SCORE
;
6307 elf_elfheader (stdoutput
)->e_flags
&= ~EF_SCORE_MACH
;
6308 elf_elfheader (stdoutput
)->e_flags
|= val
;
6310 if (s7_fix_data_dependency
== 1)
6312 elf_elfheader (stdoutput
)->e_flags
|= EF_SCORE_FIXDEP
;
6314 if (s7_score_pic
== s7_PIC
)
6316 elf_elfheader (stdoutput
)->e_flags
|= EF_SCORE_PIC
;
6320 /* In this function, we determine whether s7_GP instruction should do relaxation,
6321 for the label being against was known now.
6322 Doing this here but not in md_relax_frag() can induce iteration times
6323 in stage of doing relax. */
6326 s7_estimate_size_before_relax (fragS
* fragp
, asection
* sec
)
6328 if ((s7_RELAX_TYPE (fragp
->fr_subtype
) == Insn_GP
)
6329 || (s7_RELAX_TYPE (fragp
->fr_subtype
) == Insn_PIC
))
6330 return s7_judge_size_before_relax (fragp
, sec
);
6336 s7_relax_frag (asection
* sec ATTRIBUTE_UNUSED
,
6338 long stretch ATTRIBUTE_UNUSED
)
6342 int do_relax_p
= 0; /* Indicate doing relaxation for this frag. */
6343 int relaxable_p
= 0;
6344 bool word_align_p
= false;
6347 /* If the instruction address is odd, make it half word align first. */
6348 if ((fragp
->fr_address
) % 2 != 0)
6350 if ((fragp
->fr_address
+ fragp
->insn_addr
) % 2 != 0)
6352 fragp
->insn_addr
= 1;
6357 word_align_p
= (fragp
->fr_address
+ fragp
->insn_addr
) % 4 == 0;
6359 /* Get instruction size and relax size after the last relaxation. */
6360 if (fragp
->fr_opcode
)
6361 insn_size
= s7_RELAX_NEW (fragp
->fr_subtype
);
6363 insn_size
= s7_RELAX_OLD (fragp
->fr_subtype
);
6365 /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine
6366 whether the s7_GP instruction should do relax. */
6367 if ((s7_RELAX_TYPE (fragp
->fr_subtype
) == Insn_GP
)
6368 || (s7_RELAX_TYPE (fragp
->fr_subtype
) == Insn_PIC
))
6372 if (fragp
->insn_addr
< 2)
6374 fragp
->insn_addr
+= 2;
6379 fragp
->insn_addr
-= 2;
6384 if (fragp
->fr_opcode
)
6385 fragp
->fr_fix
= s7_RELAX_NEW (fragp
->fr_subtype
) + fragp
->insn_addr
;
6387 fragp
->fr_fix
= s7_RELAX_OLD (fragp
->fr_subtype
) + fragp
->insn_addr
;
6391 if (s7_RELAX_TYPE (fragp
->fr_subtype
) == PC_DISP19div2
)
6392 s7_b32_relax_to_b16 (fragp
);
6394 relaxable_p
= s7_RELAX_OPT (fragp
->fr_subtype
);
6395 next_fragp
= fragp
->fr_next
;
6396 while ((next_fragp
) && (next_fragp
->fr_type
!= rs_machine_dependent
))
6398 next_fragp
= next_fragp
->fr_next
;
6404 int n_relaxable_p
= 0;
6406 if (next_fragp
->fr_opcode
)
6408 n_insn_size
= s7_RELAX_NEW (next_fragp
->fr_subtype
);
6412 n_insn_size
= s7_RELAX_OLD (next_fragp
->fr_subtype
);
6415 if (s7_RELAX_TYPE (next_fragp
->fr_subtype
) == PC_DISP19div2
)
6416 s7_b32_relax_to_b16 (next_fragp
);
6417 n_relaxable_p
= s7_RELAX_OPT (next_fragp
->fr_subtype
);
6424 if (relaxable_p
&& ((n_insn_size
== 2) || n_relaxable_p
))
6430 else if (insn_size
== 2)
6433 if (relaxable_p
&& (((n_insn_size
== 4) && !n_relaxable_p
) || (n_insn_size
> 4)))
6454 /* Make the 32 bit instruction word align. */
6457 fragp
->insn_addr
+= 2;
6461 else if (insn_size
== 2)
6473 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
6476 if (insn_size
% 4 == 0)
6486 fragp
->insn_addr
+= 2;
6497 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6500 if (fragp
->fr_opcode
)
6502 fragp
->fr_opcode
= NULL
;
6503 /* Guarantee estimate stage is correct. */
6504 fragp
->fr_fix
= s7_RELAX_OLD (fragp
->fr_subtype
);
6505 fragp
->fr_fix
+= fragp
->insn_addr
;
6509 fragp
->fr_opcode
= fragp
->fr_literal
+ s7_RELAX_RELOC1 (fragp
->fr_subtype
);
6510 /* Guarantee estimate stage is correct. */
6511 fragp
->fr_fix
= s7_RELAX_NEW (fragp
->fr_subtype
);
6512 fragp
->fr_fix
+= fragp
->insn_addr
;
6517 if (fragp
->fr_opcode
)
6519 /* Guarantee estimate stage is correct. */
6520 fragp
->fr_fix
= s7_RELAX_NEW (fragp
->fr_subtype
);
6521 fragp
->fr_fix
+= fragp
->insn_addr
;
6525 /* Guarantee estimate stage is correct. */
6526 fragp
->fr_fix
= s7_RELAX_OLD (fragp
->fr_subtype
);
6527 fragp
->fr_fix
+= fragp
->insn_addr
;
6536 s7_convert_frag (bfd
* abfd ATTRIBUTE_UNUSED
,
6537 segT sec ATTRIBUTE_UNUSED
,
6545 r_old
= s7_RELAX_OLD (fragp
->fr_subtype
);
6546 r_new
= s7_RELAX_NEW (fragp
->fr_subtype
);
6548 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6549 if (fragp
->fr_opcode
== NULL
)
6551 memcpy (backup
, fragp
->fr_literal
, r_old
);
6552 fragp
->fr_fix
= r_old
;
6556 memcpy (backup
, fragp
->fr_literal
+ r_old
, r_new
);
6557 fragp
->fr_fix
= r_new
;
6560 fixp
= fragp
->tc_frag_data
.fixp
;
6561 while (fixp
&& fixp
->fx_frag
== fragp
&& fixp
->fx_where
< r_old
)
6563 if (fragp
->fr_opcode
)
6565 fixp
= fixp
->fx_next
;
6567 while (fixp
&& fixp
->fx_frag
== fragp
)
6569 if (fragp
->fr_opcode
)
6570 fixp
->fx_where
-= r_old
+ fragp
->insn_addr
;
6573 fixp
= fixp
->fx_next
;
6576 if (fragp
->insn_addr
)
6578 s7_number_to_chars (fragp
->fr_literal
, 0x0, fragp
->insn_addr
);
6580 memcpy (fragp
->fr_literal
+ fragp
->insn_addr
, backup
, fragp
->fr_fix
);
6581 fragp
->fr_fix
+= fragp
->insn_addr
;
6585 s7_pcrel_from (fixS
* fixP
)
6590 && (S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
)
6591 && (fixP
->fx_subsy
== NULL
))
6597 retval
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
6603 /* Round up a section size to the appropriate boundary. */
6605 s7_section_align (segT segment
, valueT size
)
6607 int align
= bfd_section_alignment (segment
);
6609 return ((size
+ (1 << align
) - 1) & -(1 << align
));
6613 s7_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
6615 valueT value
= *valP
;
6616 valueT abs_value
= 0;
6621 char *buf
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
6623 gas_assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
6624 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
6626 if (fixP
->fx_r_type
!= BFD_RELOC_SCORE_DUMMY_HI16
)
6630 /* If this symbol is in a different section then we need to leave it for
6631 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
6632 so we have to undo it's effects here. */
6635 if (fixP
->fx_addsy
!= NULL
6636 && S_IS_DEFINED (fixP
->fx_addsy
)
6637 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
6638 value
+= md_pcrel_from (fixP
);
6641 /* Remember value for emit_reloc. */
6642 fixP
->fx_addnumber
= value
;
6644 switch (fixP
->fx_r_type
)
6646 case BFD_RELOC_HI16_S
:
6648 { /* For la rd, imm32. */
6649 newval
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6650 HI
= value
>> 16; /* mul to 2, then take the hi 16 bit. */
6651 newval
|= (HI
& 0x3fff) << 1;
6652 newval
|= ((HI
>> 14) & 0x3) << 16;
6653 s7_number_to_chars (buf
, newval
, s7_INSN_SIZE
);
6656 case BFD_RELOC_LO16
:
6657 if (fixP
->fx_done
) /* For la rd, imm32. */
6659 newval
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6660 LO
= value
& 0xffff;
6661 newval
|= (LO
& 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
6662 newval
|= ((LO
>> 14) & 0x3) << 16;
6663 s7_number_to_chars (buf
, newval
, s7_INSN_SIZE
);
6666 case BFD_RELOC_SCORE_JMP
:
6668 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6669 value
= fixP
->fx_offset
;
6670 if (value
> 0x1ffffff)
6672 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6673 _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value
);
6676 content
= (content
& ~0x3ff7ffe) | ((value
<< 1) & 0x3ff0000) | (value
& 0x7fff);
6677 s7_number_to_chars (buf
, content
, s7_INSN_SIZE
);
6680 case BFD_RELOC_SCORE_BRANCH
:
6681 if ((S_GET_SEGMENT (fixP
->fx_addsy
) != seg
) || (fixP
->fx_addsy
!= NULL
&& S_IS_EXTERNAL (fixP
->fx_addsy
)))
6682 value
= fixP
->fx_offset
;
6686 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6687 if ((fixP
->fx_frag
->fr_opcode
!= 0) && ((content
& 0x80008000) != 0x80008000))
6689 if ((value
& 0x80000000) == 0x80000000)
6690 abs_value
= 0xffffffff - value
+ 1;
6691 if ((abs_value
& 0xffffff00) != 0)
6693 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6694 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value
);
6697 content
= s7_md_chars_to_number (buf
, s7_INSN16_SIZE
);
6699 content
= (content
& 0xff00) | ((value
>> 1) & 0xff);
6700 s7_number_to_chars (buf
, content
, s7_INSN16_SIZE
);
6701 fixP
->fx_r_type
= BFD_RELOC_SCORE16_BRANCH
;
6706 if ((value
& 0x80000000) == 0x80000000)
6707 abs_value
= 0xffffffff - value
+ 1;
6708 if ((abs_value
& 0xfff80000) != 0)
6710 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6711 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6712 (unsigned int) value
);
6715 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6716 content
&= 0xfc00fc01;
6717 content
= (content
& 0xfc00fc01) | (value
& 0x3fe) | ((value
<< 6) & 0x3ff0000);
6718 s7_number_to_chars (buf
, content
, s7_INSN_SIZE
);
6721 case BFD_RELOC_SCORE16_JMP
:
6722 content
= s7_md_chars_to_number (buf
, s7_INSN16_SIZE
);
6724 value
= fixP
->fx_offset
;
6727 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6728 _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value
);
6731 value
= fixP
->fx_offset
& 0xfff;
6732 content
= (content
& 0xfc01) | (value
& 0xffe);
6733 s7_number_to_chars (buf
, content
, s7_INSN16_SIZE
);
6735 case BFD_RELOC_SCORE16_BRANCH
:
6736 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6737 if ((fixP
->fx_frag
->fr_opcode
!= 0) && ((content
& 0x80008000) == 0x80008000))
6739 if ((S_GET_SEGMENT (fixP
->fx_addsy
) != seg
) ||
6740 (fixP
->fx_addsy
!= NULL
&& S_IS_EXTERNAL (fixP
->fx_addsy
)))
6741 value
= fixP
->fx_offset
;
6745 if ((value
& 0xfff80000) != 0 && (value
& 0xfff80000) != 0xfff80000)
6747 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6748 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6749 (unsigned int) value
);
6752 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6753 content
= (content
& 0xfc00fc01) | (value
& 0x3fe) | ((value
<< 6) & 0x3ff0000);
6754 s7_number_to_chars (buf
, content
, s7_INSN_SIZE
);
6755 fixP
->fx_r_type
= BFD_RELOC_SCORE_BRANCH
;
6761 /* In different section. */
6762 if ((S_GET_SEGMENT (fixP
->fx_addsy
) != seg
) ||
6763 (fixP
->fx_addsy
!= NULL
&& S_IS_EXTERNAL (fixP
->fx_addsy
)))
6764 value
= fixP
->fx_offset
;
6768 if ((value
& 0xffffff00) != 0 && (value
& 0xffffff00) != 0xffffff00)
6770 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
6771 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"),
6772 (unsigned int) value
);
6775 content
= s7_md_chars_to_number (buf
, s7_INSN16_SIZE
);
6776 content
= (content
& 0xff00) | ((value
>> 1) & 0xff);
6777 s7_number_to_chars (buf
, content
, s7_INSN16_SIZE
);
6781 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
6782 s7_number_to_chars (buf
, value
, 1);
6786 value
= fixP
->fx_offset
;
6787 s7_number_to_chars (buf
, value
, 1);
6793 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
6794 s7_number_to_chars (buf
, value
, 2);
6798 value
= fixP
->fx_offset
;
6799 s7_number_to_chars (buf
, value
, 2);
6805 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
6806 s7_number_to_chars (buf
, value
, 4);
6810 value
= fixP
->fx_offset
;
6811 s7_number_to_chars (buf
, value
, 4);
6815 case BFD_RELOC_VTABLE_INHERIT
:
6817 if (fixP
->fx_addsy
&& !S_IS_DEFINED (fixP
->fx_addsy
) && !S_IS_WEAK (fixP
->fx_addsy
))
6818 S_SET_WEAK (fixP
->fx_addsy
);
6820 case BFD_RELOC_VTABLE_ENTRY
:
6823 case BFD_RELOC_SCORE_GPREL15
:
6824 content
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6825 if ((fixP
->fx_frag
->fr_opcode
!= 0) && ((content
& 0xfc1c8000) != 0x94188000))
6826 fixP
->fx_r_type
= BFD_RELOC_NONE
;
6829 case BFD_RELOC_SCORE_GOT15
:
6830 case BFD_RELOC_SCORE_DUMMY_HI16
:
6831 case BFD_RELOC_SCORE_GOT_LO16
:
6832 case BFD_RELOC_SCORE_CALL15
:
6833 case BFD_RELOC_GPREL32
:
6835 case BFD_RELOC_NONE
:
6837 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
6841 /* Translate internal representation of relocation info to BFD target format. */
6844 s7_gen_reloc (asection
* section ATTRIBUTE_UNUSED
, fixS
* fixp
)
6846 static arelent
*retval
[MAX_RELOC_EXPANSION
+ 1]; /* MAX_RELOC_EXPANSION equals 2. */
6848 bfd_reloc_code_real_type code
;
6851 reloc
= retval
[0] = XNEW (arelent
);
6854 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
6855 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
6856 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
6857 reloc
->addend
= fixp
->fx_offset
;
6859 /* If this is a variant frag, we may need to adjust the existing
6860 reloc and generate a new one. */
6861 if (fixp
->fx_frag
->fr_opcode
!= NULL
&& (fixp
->fx_r_type
== BFD_RELOC_SCORE_GPREL15
))
6863 /* Update instruction imm bit. */
6868 buf
= fixp
->fx_frag
->fr_literal
+ fixp
->fx_frag
->insn_addr
;
6869 newval
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6870 off
= fixp
->fx_offset
>> 16;
6871 newval
|= (off
& 0x3fff) << 1;
6872 newval
|= ((off
>> 14) & 0x3) << 16;
6873 s7_number_to_chars (buf
, newval
, s7_INSN_SIZE
);
6875 buf
+= s7_INSN_SIZE
;
6876 newval
= s7_md_chars_to_number (buf
, s7_INSN_SIZE
);
6877 off
= fixp
->fx_offset
& 0xffff;
6878 newval
|= ((off
& 0x3fff) << 1);
6879 newval
|= (((off
>> 14) & 0x3) << 16);
6880 s7_number_to_chars (buf
, newval
, s7_INSN_SIZE
);
6882 retval
[1] = XNEW (arelent
);
6884 retval
[1]->sym_ptr_ptr
= XNEW (asymbol
*);
6885 *retval
[1]->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
6886 retval
[1]->address
= (reloc
->address
+ s7_RELAX_RELOC2 (fixp
->fx_frag
->fr_subtype
));
6888 retval
[1]->addend
= 0;
6889 retval
[1]->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_LO16
);
6890 gas_assert (retval
[1]->howto
!= NULL
);
6892 fixp
->fx_r_type
= BFD_RELOC_HI16_S
;
6895 code
= fixp
->fx_r_type
;
6896 switch (fixp
->fx_r_type
)
6901 code
= BFD_RELOC_32_PCREL
;
6905 case BFD_RELOC_HI16_S
:
6906 case BFD_RELOC_LO16
:
6907 case BFD_RELOC_SCORE_JMP
:
6908 case BFD_RELOC_SCORE_BRANCH
:
6909 case BFD_RELOC_SCORE16_JMP
:
6910 case BFD_RELOC_SCORE16_BRANCH
:
6911 case BFD_RELOC_VTABLE_ENTRY
:
6912 case BFD_RELOC_VTABLE_INHERIT
:
6913 case BFD_RELOC_SCORE_GPREL15
:
6914 case BFD_RELOC_SCORE_GOT15
:
6915 case BFD_RELOC_SCORE_DUMMY_HI16
:
6916 case BFD_RELOC_SCORE_GOT_LO16
:
6917 case BFD_RELOC_SCORE_CALL15
:
6918 case BFD_RELOC_GPREL32
:
6919 case BFD_RELOC_NONE
:
6920 code
= fixp
->fx_r_type
;
6923 type
= _("<unknown>");
6924 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
6925 _("cannot represent %s relocation in this object file format"), type
);
6929 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
6930 if (reloc
->howto
== NULL
)
6932 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
6933 _("cannot represent %s relocation in this object file format1"),
6934 bfd_get_reloc_code_name (code
));
6937 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6938 vtable entry to be used in the relocation's section offset. */
6939 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
6940 reloc
->address
= fixp
->fx_offset
;