]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-score7.c
bfd_section_* macros
[thirdparty/binutils-gdb.git] / gas / config / tc-score7.c
1 /* tc-score7.c -- Assembler for Score7
2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
3 Contributed by:
4 Brain.lin (brain.lin@sunplusct.com)
5 Mei Ligang (ligang@sunnorth.com.cn)
6 Pei-Lin Tsai (pltsai@sunplus.com)
7
8 This file is part of GAS, the GNU Assembler.
9
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)
13 any later version.
14
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.
19
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. */
24
25 #include "as.h"
26 #include "config.h"
27 #include "subsegs.h"
28 #include "safe-ctype.h"
29 #include "opcode/score-inst.h"
30 #include "libiberty.h"
31
32 #ifdef OBJ_ELF
33 #include "elf/score.h"
34 #include "dwarf2dbg.h"
35 #endif
36
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 *);
89
90 #define s7_GP 28
91 #define s7_PIC_CALL_REG 29
92 #define s7_MAX_LITERAL_POOL_SIZE 1024
93 #define s7_FAIL 0x80000000
94 #define s7_SUCCESS 0
95 #define s7_INSN_SIZE 4
96 #define s7_INSN16_SIZE 2
97 #define s7_RELAX_INST_NUM 3
98
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");
106
107 #define s7_skip_whitespace(str) while (*(str) == ' ') ++(str)
108
109 /* The name of the readonly data section. */
110 #define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
111 ? ".data" \
112 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
113 ? ".rdata" \
114 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
115 ? ".rdata" \
116 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
117 ? ".rodata" \
118 : (abort (), ""))
119
120 #define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
121 ((relax_substateT) \
122 (((old) << 23) \
123 | ((new) << 16) \
124 | ((type) << 9) \
125 | ((reloc1) << 5) \
126 | ((reloc2) << 1) \
127 | ((opt) ? 1 : 0)))
128
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)
136
137 #define s7_SET_INSN_ERROR(s) (s7_inst.error = (s))
138 #define s7_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
139
140 #define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type))
141
142 #define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \
143 ? s7_INSN16_SIZE : s7_INSN_SIZE)
144
145 #define s7_INSN_NAME_LEN 16
146
147 /* Relax will need some padding for alignment. */
148 #define s7_RELAX_PAD_BYTE 3
149
150 #define s7_USE_GLOBAL_POINTER_OPT 1
151
152 \f
153
154 /* Enumeration matching entries in table above. */
155 enum s7_score_reg_type
156 {
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,
161 s7_REG_TYPE_MAX = 3
162 };
163
164 enum s7_score_pic_level
165 {
166 s7_NO_PIC,
167 s7_PIC
168 };
169 static enum s7_score_pic_level s7_score_pic = s7_NO_PIC;
170
171 enum s7_insn_type_for_dependency
172 {
173 s7_D_pce,
174 s7_D_cond_br,
175 s7_D_cond_mv,
176 s7_D_cached,
177 s7_D_cachei,
178 s7_D_ldst,
179 s7_D_ldcombine,
180 s7_D_mtcr,
181 s7_D_mfcr,
182 s7_D_mfsr,
183 s7_D_mftlb,
184 s7_D_mtptlb,
185 s7_D_mtrtlb,
186 s7_D_stlb,
187 s7_D_all_insn
188 };
189
190 struct s7_insn_to_dependency
191 {
192 const char *insn_name;
193 enum s7_insn_type_for_dependency type;
194 };
195
196 struct s7_data_dependency
197 {
198 enum s7_insn_type_for_dependency pre_insn_type;
199 char pre_reg[6];
200 enum s7_insn_type_for_dependency cur_insn_type;
201 char cur_reg[6];
202 int bubblenum_7;
203 int bubblenum_5;
204 int warn_or_error; /* warning - 0; error - 1 */
205 };
206
207 static const struct s7_insn_to_dependency s7_insn_to_dependency_table[] =
208 {
209 /* pce instruction. */
210 {"pce", s7_D_pce},
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. */
326 {"mtcr", s7_D_mtcr},
327 {"mftlb", s7_D_mftlb},
328 {"mtptlb", s7_D_mtptlb},
329 {"mtrtlb", s7_D_mtrtlb},
330 {"stlb", s7_D_stlb},
331 {"mfcr", s7_D_mfcr},
332 {"mfsr", s7_D_mfsr},
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. */
355 {"lb", s7_D_ldst},
356 {"lbu", s7_D_ldst},
357 {"lbu!", s7_D_ldst},
358 {"lbup!", s7_D_ldst},
359 {"lh", s7_D_ldst},
360 {"lhu", s7_D_ldst},
361 {"lh!", s7_D_ldst},
362 {"lhp!", s7_D_ldst},
363 {"lw", s7_D_ldst},
364 {"lw!", s7_D_ldst},
365 {"lwp!", s7_D_ldst},
366 {"sb", s7_D_ldst},
367 {"sb!", s7_D_ldst},
368 {"sbp!", s7_D_ldst},
369 {"sh", s7_D_ldst},
370 {"sh!", s7_D_ldst},
371 {"shp!", s7_D_ldst},
372 {"sw", s7_D_ldst},
373 {"sw!", s7_D_ldst},
374 {"swp!", s7_D_ldst},
375 {"alw", s7_D_ldst},
376 {"asw", s7_D_ldst},
377 {"push!", s7_D_ldst},
378 {"pushhi!", s7_D_ldst},
379 {"pop!", s7_D_ldst},
380 {"pophi!", s7_D_ldst},
381 {"ldc1", s7_D_ldst},
382 {"ldc2", s7_D_ldst},
383 {"ldc3", s7_D_ldst},
384 {"stc1", s7_D_ldst},
385 {"stc2", s7_D_ldst},
386 {"stc3", s7_D_ldst},
387 {"scb", s7_D_ldst},
388 {"scw", s7_D_ldst},
389 {"sce", s7_D_ldst},
390 /* load combine instruction. */
391 {"lcb", s7_D_ldcombine},
392 {"lcw", s7_D_ldcombine},
393 {"lce", s7_D_ldcombine},
394 };
395
396 static const struct s7_data_dependency s7_data_dependency_table[] =
397 {
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},
404 /* CCR register. */
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},
416 /* Cache. */
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},
420 /* Load combine. */
421 {s7_D_ldcombine, "", s7_D_mfsr, "sr1", 3, 3, 1},
422 };
423
424 \f
425
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;
430
431 static int s7_in_my_get_expression = 0;
432
433 /* Default, pop warning message when using r1. */
434 static int s7_nor1 = 1;
435
436 /* Default will do instruction relax, -O0 will set s7_g_opt = 0. */
437 static unsigned int s7_g_opt = 1;
438
439 /* The size of the small data section. */
440 static unsigned int s7_g_switch_value = 8;
441
442 static segT s7_pdr_seg;
443
444 struct s7_score_it
445 {
446 char name[s7_INSN_NAME_LEN];
447 unsigned long instruction;
448 unsigned long relax_inst;
449 int size;
450 int relax_size;
451 enum score_insn_type type;
452 char str[s7_MAX_LITERAL_POOL_SIZE];
453 const char *error;
454 int bwarn;
455 char reg[s7_INSN_NAME_LEN];
456 struct
457 {
458 bfd_reloc_code_real_type type;
459 expressionS exp;
460 int pc_rel;
461 }reloc;
462 };
463 static struct s7_score_it s7_inst;
464
465 typedef struct proc
466 {
467 symbolS *isym;
468 unsigned long reg_mask;
469 unsigned long reg_offset;
470 unsigned long fpreg_mask;
471 unsigned long leaf;
472 unsigned long frame_offset;
473 unsigned long frame_reg;
474 unsigned long pc_reg;
475 } s7_procS;
476 static s7_procS s7_cur_proc;
477 static s7_procS *s7_cur_proc_ptr;
478 static int s7_numprocs;
479
480 /* Structure for a hash table entry for a register. */
481 struct s7_reg_entry
482 {
483 const char *name;
484 int number;
485 };
486
487 static const struct s7_reg_entry s7_score_rn_table[] =
488 {
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},
497 {NULL, 0}
498 };
499
500 static const struct s7_reg_entry s7_score_srn_table[] =
501 {
502 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
503 {NULL, 0}
504 };
505
506 static const struct s7_reg_entry s7_score_crn_table[] =
507 {
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},
516 {NULL, 0}
517 };
518
519 struct s7_reg_map
520 {
521 const struct s7_reg_entry *names;
522 int max_regno;
523 struct hash_control *htab;
524 const char *expected;
525 };
526
527 static struct s7_reg_map s7_all_reg_maps[] =
528 {
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")},
532 };
533
534 static struct hash_control *s7_score_ops_hsh = NULL;
535 static struct hash_control *s7_dependency_insn_hsh = NULL;
536
537 \f
538 struct s7_datafield_range
539 {
540 int data_type;
541 int bits;
542 int range[2];
543 };
544
545 static struct s7_datafield_range s7_score_df_range[] =
546 {
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) */
592 };
593
594 \f
595 struct s7_asm_opcode
596 {
597 /* Instruction name. */
598 const char *template_name;
599
600 /* Instruction Opcode. */
601 bfd_vma value;
602
603 /* Instruction bit mask. */
604 bfd_vma bitmask;
605
606 /* Relax instruction opcode. 0x8000 imply no relaxation. */
607 bfd_vma relax_value;
608
609 /* Instruction type. */
610 enum score_insn_type type;
611
612 /* Function to call to parse args. */
613 void (*parms) (char *);
614 };
615
616 static const struct s7_asm_opcode s7_score_ldst_insns[] =
617 {
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},
642 };
643
644 static const struct s7_asm_opcode s7_score_insns[] =
645 {
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)
1054 ori reg, %LO(imm32)
1055
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},
1084 };
1085
1086 #define s7_SCORE5_PIPELINE 5
1087 #define s7_SCORE7_PIPELINE 7
1088
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];
1092
1093 static int s7_score7d = 1;
1094
1095 \f
1096
1097 static int
1098 s7_end_of_line (char *str)
1099 {
1100 int retval = s7_SUCCESS;
1101
1102 s7_skip_whitespace (str);
1103 if (*str != '\0')
1104 {
1105 retval = (int) s7_FAIL;
1106
1107 if (!s7_inst.error)
1108 s7_inst.error = s7_BAD_GARBAGE;
1109 }
1110
1111 return retval;
1112 }
1113
1114 static int
1115 s7_score_reg_parse (char **ccp, struct hash_control *htab)
1116 {
1117 char *start = *ccp;
1118 char c;
1119 char *p;
1120 struct s7_reg_entry *reg;
1121
1122 p = start;
1123 if (!ISALPHA (*p) || !is_name_beginner (*p))
1124 return (int) s7_FAIL;
1125
1126 c = *p++;
1127
1128 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1129 c = *p++;
1130
1131 *--p = 0;
1132 reg = (struct s7_reg_entry *) hash_find (htab, start);
1133 *p = c;
1134
1135 if (reg)
1136 {
1137 *ccp = p;
1138 return reg->number;
1139 }
1140 return (int) s7_FAIL;
1141 }
1142
1143 /* If shift <= 0, only return reg. */
1144 static int
1145 s7_reg_required_here (char **str, int shift, enum s7_score_reg_type reg_type)
1146 {
1147 static char buff[s7_MAX_LITERAL_POOL_SIZE];
1148 int reg = (int) s7_FAIL;
1149 char *start = *str;
1150
1151 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[reg_type].htab)) != (int) s7_FAIL)
1152 {
1153 if (reg_type == s7_REG_TYPE_SCORE)
1154 {
1155 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
1156 {
1157 as_warn (_("Using temp register(r1)"));
1158 s7_inst.bwarn = 1;
1159 }
1160 }
1161 if (shift >= 0)
1162 {
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);
1167 else
1168 strcpy (s7_inst.reg, "");
1169
1170 s7_inst.instruction |= reg << shift;
1171 }
1172 }
1173 else
1174 {
1175 *str = start;
1176 sprintf (buff, _("register expected, not '%.100s'"), start);
1177 s7_inst.error = buff;
1178 }
1179
1180 return reg;
1181 }
1182
1183 static int
1184 s7_skip_past_comma (char **str)
1185 {
1186 char *p = *str;
1187 char c;
1188 int comma = 0;
1189
1190 while ((c = *p) == ' ' || c == ',')
1191 {
1192 p++;
1193 if (c == ',' && comma++)
1194 {
1195 s7_inst.error = s7_BAD_SKIP_COMMA;
1196 return (int) s7_FAIL;
1197 }
1198 }
1199
1200 if ((c == '\0') || (comma == 0))
1201 {
1202 s7_inst.error = s7_BAD_SKIP_COMMA;
1203 return (int) s7_FAIL;
1204 }
1205
1206 *str = p;
1207 return comma ? s7_SUCCESS : (int) s7_FAIL;
1208 }
1209
1210 static void
1211 s7_do_rdrsrs (char *str)
1212 {
1213 s7_skip_whitespace (str);
1214
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)
1221 {
1222 return;
1223 }
1224 else
1225 {
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)))
1231 {
1232 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4)
1233 | (((s7_inst.instruction >> 15) & 0xf) << 8);
1234 s7_inst.relax_size = 2;
1235 }
1236 else
1237 {
1238 s7_inst.relax_inst = 0x8000;
1239 }
1240 }
1241 }
1242
1243 static int
1244 s7_walk_no_bignums (symbolS * sp)
1245 {
1246 if (symbol_get_value_expression (sp)->X_op == O_big)
1247 return 1;
1248
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)));
1253
1254 return 0;
1255 }
1256
1257 static int
1258 s7_my_get_expression (expressionS * ep, char **str)
1259 {
1260 char *save_in;
1261
1262 save_in = input_line_pointer;
1263 input_line_pointer = *str;
1264 s7_in_my_get_expression = 1;
1265
1266 (void) expression (ep);
1267 s7_in_my_get_expression = 0;
1268
1269 if (ep->X_op == O_illegal)
1270 {
1271 *str = input_line_pointer;
1272 input_line_pointer = save_in;
1273 s7_inst.error = _("illegal expression");
1274 return (int) s7_FAIL;
1275 }
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)))))
1283 {
1284 s7_inst.error = _("invalid constant");
1285 *str = input_line_pointer;
1286 input_line_pointer = save_in;
1287 return (int) s7_FAIL;
1288 }
1289
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))
1299 {
1300 s7_inst.error = s7_BAD_ARGS;
1301 *str = input_line_pointer;
1302 input_line_pointer = save_in;
1303 return (int) s7_FAIL;
1304 }
1305
1306 *str = input_line_pointer;
1307 input_line_pointer = save_in;
1308 return s7_SUCCESS;
1309 }
1310
1311 /* Check if an immediate is valid. If so, convert it to the right format. */
1312
1313 static bfd_signed_vma
1314 s7_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
1315 {
1316 switch (data_type)
1317 {
1318 case _VALUE_HI16:
1319 {
1320 int val_hi = ((val & 0xffff0000) >> 16);
1321
1322 if (s7_score_df_range[data_type].range[0] <= val_hi
1323 && val_hi <= s7_score_df_range[data_type].range[1])
1324 return val_hi;
1325 }
1326 break;
1327
1328 case _VALUE_LO16:
1329 {
1330 int val_lo = (val & 0xffff);
1331
1332 if (s7_score_df_range[data_type].range[0] <= val_lo
1333 && val_lo <= s7_score_df_range[data_type].range[1])
1334 return val_lo;
1335 }
1336 break;
1337
1338 case _SIMM12:
1339 if (hex_p == 1)
1340 {
1341 if (!(val >= -0x800 && val <= 0xfff))
1342 {
1343 return (int) s7_FAIL;
1344 }
1345 }
1346 else
1347 {
1348 if (!(val >= -2048 && val <= 2047))
1349 {
1350 return (int) s7_FAIL;
1351 }
1352 }
1353
1354 return val;
1355 break;
1356
1357 case _SIMM14:
1358 if (hex_p == 1)
1359 {
1360 if (!(val >= -0x2000 && val <= 0x3fff))
1361 {
1362 return (int) s7_FAIL;
1363 }
1364 }
1365 else
1366 {
1367 if (!(val >= -8192 && val <= 8191))
1368 {
1369 return (int) s7_FAIL;
1370 }
1371 }
1372
1373 return val;
1374 break;
1375
1376 case _SIMM15:
1377 if (hex_p == 1)
1378 {
1379 if (!(val >= -0x4000 && val <= 0x7fff))
1380 {
1381 return (int) s7_FAIL;
1382 }
1383 }
1384 else
1385 {
1386 if (!(val >= -16384 && val <= 16383))
1387 {
1388 return (int) s7_FAIL;
1389 }
1390 }
1391
1392 return val;
1393 break;
1394
1395 case _SIMM16:
1396 if (hex_p == 1)
1397 {
1398 if (!(val >= -0x8000 && val <= 0xffff))
1399 {
1400 return (int) s7_FAIL;
1401 }
1402 }
1403 else
1404 {
1405 if (!(val >= -32768 && val <= 32767))
1406 {
1407 return (int) s7_FAIL;
1408 }
1409 }
1410
1411 return val;
1412 break;
1413
1414 case _SIMM16_NEG:
1415 if (hex_p == 1)
1416 {
1417 if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1418 {
1419 return (int) s7_FAIL;
1420 }
1421 }
1422 else
1423 {
1424 if (!(val >= -32767 && val <= 32768))
1425 {
1426 return (int) s7_FAIL;
1427 }
1428 }
1429
1430 val = -val;
1431 return val;
1432 break;
1433
1434 case _IMM32:
1435 if (val >= 0 && val <= 0xffffffff)
1436 {
1437 return val;
1438 }
1439 else
1440 {
1441 return (int) s7_FAIL;
1442 }
1443
1444 default:
1445 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1446 val = -val;
1447
1448 if (s7_score_df_range[data_type].range[0] <= val
1449 && val <= s7_score_df_range[data_type].range[1])
1450 return val;
1451
1452 break;
1453 }
1454
1455 return (int) s7_FAIL;
1456 }
1457
1458 static int
1459 s7_data_op2 (char **str, int shift, enum score_data_type data_type)
1460 {
1461 int value;
1462 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
1463 char *dataptr;
1464 int cnt = 0;
1465 char *pp = NULL;
1466
1467 s7_skip_whitespace (*str);
1468 s7_inst.error = NULL;
1469 dataptr = * str;
1470
1471 /* Set hex_p to zero. */
1472 int hex_p = 0;
1473
1474 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1475 {
1476 data_exp[cnt] = *dataptr;
1477 dataptr++;
1478 cnt++;
1479 }
1480
1481 data_exp[cnt] = '\0';
1482 pp = (char *)&data_exp;
1483
1484 if (*dataptr == '|') /* process PCE */
1485 {
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 */
1491 *str = dataptr;
1492 }
1493 else /* process 16 bit */
1494 {
1495 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
1496 {
1497 return (int) s7_FAIL;
1498 }
1499
1500 dataptr = (char *) data_exp;
1501 for (; *dataptr != '\0'; dataptr++)
1502 {
1503 *dataptr = TOLOWER (*dataptr);
1504 if (*dataptr == '!' || *dataptr == ' ')
1505 break;
1506 }
1507 dataptr = (char *) data_exp;
1508
1509 if ((dataptr != NULL)
1510 && (((strstr (dataptr, "0x")) != NULL)
1511 || ((strstr (dataptr, "0X")) != NULL)))
1512 {
1513 hex_p = 1;
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))
1531 {
1532 data_type += 24;
1533 }
1534 }
1535
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'))))
1547 {
1548 s7_inst.error = s7_BAD_ARGS;
1549 return (int) s7_FAIL;
1550 }
1551 }
1552
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)))
1565 {
1566 s7_inst.error = s7_BAD_ARGS;
1567 return (int) s7_FAIL;
1568 }
1569
1570 if (s7_inst.reloc.exp.X_add_symbol)
1571 {
1572 switch (data_type)
1573 {
1574 case _SIMM16_LA:
1575 return (int) s7_FAIL;
1576 case _VALUE_HI16:
1577 s7_inst.reloc.type = BFD_RELOC_HI16_S;
1578 s7_inst.reloc.pc_rel = 0;
1579 break;
1580 case _VALUE_LO16:
1581 s7_inst.reloc.type = BFD_RELOC_LO16;
1582 s7_inst.reloc.pc_rel = 0;
1583 break;
1584 case _GP_IMM15:
1585 s7_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1586 s7_inst.reloc.pc_rel = 0;
1587 break;
1588 case _SIMM16_pic:
1589 case _IMM16_LO16_pic:
1590 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1591 s7_inst.reloc.pc_rel = 0;
1592 break;
1593 default:
1594 s7_inst.reloc.type = BFD_RELOC_32;
1595 s7_inst.reloc.pc_rel = 0;
1596 break;
1597 }
1598 }
1599 else
1600 {
1601 if (data_type == _IMM16_pic)
1602 {
1603 s7_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1604 s7_inst.reloc.pc_rel = 0;
1605 }
1606
1607 if (data_type == _SIMM16_LA && s7_inst.reloc.exp.X_unsigned == 1)
1608 {
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)
1612 {
1613 s7_inst.instruction |= 0x8000000;
1614 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1615 return s7_SUCCESS;
1616 }
1617 }
1618 else
1619 {
1620 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
1621 }
1622
1623 if (value == (int) s7_FAIL)
1624 {
1625 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1626 {
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]);
1631 }
1632 else
1633 {
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]);
1638 }
1639
1640 s7_inst.error = s7_err_msg;
1641 return (int) s7_FAIL;
1642 }
1643
1644 if ((s7_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1645 {
1646 value &= (1 << s7_score_df_range[data_type].bits) - 1;
1647 }
1648
1649 s7_inst.instruction |= value << shift;
1650 }
1651
1652 if ((s7_inst.instruction & 0x3e000000) == 0x30000000)
1653 {
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))
1674 {
1675 s7_inst.error = _("invalid constant: bit expression not defined");
1676 return (int) s7_FAIL;
1677 }
1678 }
1679
1680 return s7_SUCCESS;
1681 }
1682
1683 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1684
1685 static void
1686 s7_do_rdsi16 (char *str)
1687 {
1688 s7_skip_whitespace (str);
1689
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)
1694 return;
1695
1696 /* ldi. */
1697 if ((s7_inst.instruction & 0x20c0000) == 0x20c0000)
1698 {
1699 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10) || ((s7_inst.instruction & 0x1fe00) != 0))
1700 {
1701 s7_inst.relax_inst = 0x8000;
1702 }
1703 else
1704 {
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;
1708 }
1709 }
1710 else if (((s7_inst.instruction >> 20) & 0x10) == 0x10)
1711 {
1712 s7_inst.relax_inst = 0x8000;
1713 }
1714 }
1715
1716 /* Handle subi/subi.c. */
1717
1718 static void
1719 s7_do_sub_rdsi16 (char *str)
1720 {
1721 s7_skip_whitespace (str);
1722
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);
1727 }
1728
1729
1730 /* Handle addri/addri.c. */
1731
1732 static void
1733 s7_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1734 {
1735 s7_skip_whitespace (str);
1736
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);
1742 }
1743
1744 /* Handle subri.c/subri. */
1745
1746 static void
1747 s7_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1748 {
1749 s7_skip_whitespace (str);
1750
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);
1757 }
1758
1759 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1760
1761 static void
1762 s7_do_rdrsi5 (char *str) /* 0~((2^14)-1) */
1763 {
1764 s7_skip_whitespace (str);
1765
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)
1772 return;
1773
1774 if ((((s7_inst.instruction >> 20) & 0x1f) == ((s7_inst.instruction >> 15) & 0x1f))
1775 && (s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1776 {
1777 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1778 s7_inst.relax_size = 2;
1779 }
1780 else
1781 s7_inst.relax_inst = 0x8000;
1782 }
1783
1784 /* Handle andri/orri/andri.c/orri.c. */
1785
1786 static void
1787 s7_do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1788 {
1789 s7_skip_whitespace (str);
1790
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);
1797 }
1798
1799 /* Handle bittst.c. */
1800
1801 static void
1802 s7_do_xrsi5 (char *str)
1803 {
1804 s7_skip_whitespace (str);
1805
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)
1810 return;
1811
1812 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1813 {
1814 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1815 s7_inst.relax_size = 2;
1816 }
1817 else
1818 s7_inst.relax_inst = 0x8000;
1819 }
1820
1821 /* Handle addis/andi/ori/andis/oris/ldis. */
1822
1823 static void
1824 s7_do_rdi16 (char *str)
1825 {
1826 s7_skip_whitespace (str);
1827
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)
1832 return;
1833 }
1834
1835 static void
1836 s7_do_macro_rdi32hi (char *str)
1837 {
1838 s7_skip_whitespace (str);
1839
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);
1844 }
1845
1846 static void
1847 s7_do_macro_rdi32lo (char *str)
1848 {
1849 s7_skip_whitespace (str);
1850
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);
1855 }
1856
1857 /* Handle ldis_pic. */
1858
1859 static void
1860 s7_do_rdi16_pic (char *str)
1861 {
1862 s7_skip_whitespace (str);
1863
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);
1868 }
1869
1870 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1871
1872 static void
1873 s7_do_addi_s_pic (char *str)
1874 {
1875 s7_skip_whitespace (str);
1876
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);
1881 }
1882
1883 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1884
1885 static void
1886 s7_do_addi_u_pic (char *str)
1887 {
1888 s7_skip_whitespace (str);
1889
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);
1894 }
1895
1896 /* Handle mfceh/mfcel/mtceh/mtchl. */
1897
1898 static void
1899 s7_do_rd (char *str)
1900 {
1901 s7_skip_whitespace (str);
1902
1903 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL)
1904 s7_end_of_line (str);
1905 }
1906
1907 static void
1908 s7_do_rs (char *str)
1909 {
1910 s7_skip_whitespace (str);
1911
1912 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1913 || s7_end_of_line (str) == (int) s7_FAIL)
1914 return;
1915
1916 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1917 {
1918 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8) | (((s7_inst.instruction >> 15) & 0xf) << 4);
1919 s7_inst.relax_size = 2;
1920 }
1921 else
1922 s7_inst.relax_inst = 0x8000;
1923 }
1924
1925 static void
1926 s7_do_i15 (char *str)
1927 {
1928 s7_skip_whitespace (str);
1929
1930 if (s7_data_op2 (&str, 10, _IMM15) != (int) s7_FAIL)
1931 s7_end_of_line (str);
1932 }
1933
1934 static void
1935 s7_do_xi5x (char *str)
1936 {
1937 s7_skip_whitespace (str);
1938
1939 if (s7_data_op2 (&str, 15, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
1940 return;
1941
1942 if (s7_inst.relax_inst != 0x8000)
1943 {
1944 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0x1f) << 3);
1945 s7_inst.relax_size = 2;
1946 }
1947 }
1948
1949 static void
1950 s7_do_rdrs (char *str)
1951 {
1952 s7_skip_whitespace (str);
1953
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)
1958 return;
1959
1960 if (s7_inst.relax_inst != 0x8000)
1961 {
1962 if (((s7_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1963 {
1964 /* mlfh */
1965 if ((((s7_inst.instruction >> 15) & 0x10) != 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1966 {
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;
1970 }
1971 /* mhfl */
1972 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && ((s7_inst.instruction >> 20) & 0x10) != 0)
1973 {
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;
1977 }
1978 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1979 {
1980 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1981 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1982 s7_inst.relax_size = 2;
1983 }
1984 else
1985 {
1986 s7_inst.relax_inst = 0x8000;
1987 }
1988 }
1989 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1990 {
1991 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1992 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1993 s7_inst.relax_size = 2;
1994 }
1995 else
1996 {
1997 s7_inst.relax_inst = 0x8000;
1998 }
1999 }
2000 }
2001
2002 /* Handle mfcr/mtcr. */
2003 static void
2004 s7_do_rdcrs (char *str)
2005 {
2006 s7_skip_whitespace (str);
2007
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);
2012 }
2013
2014 /* Handle mfsr/mtsr. */
2015
2016 static void
2017 s7_do_rdsrs (char *str)
2018 {
2019 s7_skip_whitespace (str);
2020
2021 /* mfsr */
2022 if ((s7_inst.instruction & 0xff) == 0x50)
2023 {
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);
2028 }
2029 else
2030 {
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);
2034 }
2035 }
2036
2037 /* Handle neg. */
2038
2039 static void
2040 s7_do_rdxrs (char *str)
2041 {
2042 s7_skip_whitespace (str);
2043
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)
2048 return;
2049
2050 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 10) & 0x10) == 0)
2051 && (((s7_inst.instruction >> 20) & 0x10) == 0))
2052 {
2053 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 20) & 0xf) << 8);
2054 s7_inst.relax_size = 2;
2055 }
2056 else
2057 s7_inst.relax_inst = 0x8000;
2058 }
2059
2060 /* Handle cmp.c/cmp<cond>. */
2061 static void
2062 s7_do_rsrs (char *str)
2063 {
2064 s7_skip_whitespace (str);
2065
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)
2070 return;
2071
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))
2074 {
2075 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 15) & 0xf) << 8);
2076 s7_inst.relax_size = 2;
2077 }
2078 else
2079 s7_inst.relax_inst = 0x8000;
2080 }
2081
2082 static void
2083 s7_do_ceinst (char *str)
2084 {
2085 char *strbak;
2086
2087 strbak = str;
2088 s7_skip_whitespace (str);
2089
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)
2100 {
2101 return;
2102 }
2103 else
2104 {
2105 str = strbak;
2106 if (s7_data_op2 (&str, 0, _IMM25) == (int) s7_FAIL)
2107 return;
2108 }
2109 }
2110
2111 static int
2112 s7_reglow_required_here (char **str, int shift)
2113 {
2114 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2115 int reg;
2116 char *start = *str;
2117
2118 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2119 {
2120 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
2121 {
2122 as_warn (_("Using temp register(r1)"));
2123 s7_inst.bwarn = 1;
2124 }
2125 if (reg < 16)
2126 {
2127 if (shift >= 0)
2128 s7_inst.instruction |= reg << shift;
2129
2130 return reg;
2131 }
2132 }
2133
2134 /* Restore the start point, we may have got a reg of the wrong class. */
2135 *str = start;
2136 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
2137 s7_inst.error = buff;
2138 return (int) s7_FAIL;
2139 }
2140
2141 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
2142
2143 static void
2144 s7_do16_rdrs (char *str)
2145 {
2146 s7_skip_whitespace (str);
2147
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)
2152 {
2153 return;
2154 }
2155 else
2156 {
2157 if ((s7_inst.instruction & 0x700f) == 0x2003) /* cmp! */
2158 {
2159 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2160 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2161 }
2162 else if ((s7_inst.instruction & 0x700f) == 0x2006) /* not! */
2163 {
2164 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2165 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2166 }
2167 else if ((s7_inst.instruction & 0x700f) == 0x1009) /* mazh.f! */
2168 {
2169 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2170 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2171 }
2172 else
2173 {
2174 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2175 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 4) & 0xf) << 10);
2176 }
2177 s7_inst.relax_size = 4;
2178 }
2179 }
2180
2181 static void
2182 s7_do16_rs (char *str)
2183 {
2184 int rd = 0;
2185
2186 s7_skip_whitespace (str);
2187
2188 if ((rd = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL
2189 || s7_end_of_line (str) == (int) s7_FAIL)
2190 {
2191 return;
2192 }
2193 else
2194 {
2195 s7_inst.relax_inst |= rd << 20;
2196 s7_inst.relax_size = 4;
2197 }
2198 }
2199
2200 /* Handle br!/brl!. */
2201
2202 static void
2203 s7_do16_xrs (char *str)
2204 {
2205 s7_skip_whitespace (str);
2206
2207 if (s7_reglow_required_here (&str, 4) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2208 {
2209 return;
2210 }
2211 else
2212 {
2213 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 10)
2214 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2215 s7_inst.relax_size = 4;
2216 }
2217 }
2218
2219 static int
2220 s7_reghigh_required_here (char **str, int shift)
2221 {
2222 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2223 int reg;
2224 char *start = *str;
2225
2226 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2227 {
2228 if (15 < reg && reg < 32)
2229 {
2230 if (shift >= 0)
2231 s7_inst.instruction |= (reg & 0xf) << shift;
2232
2233 return reg;
2234 }
2235 }
2236
2237 *str = start;
2238 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
2239 s7_inst.error = buff;
2240 return (int) s7_FAIL;
2241 }
2242
2243 /* Handle mhfl!. */
2244
2245 static void
2246 s7_do16_hrdrs (char *str)
2247 {
2248 s7_skip_whitespace (str);
2249
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)
2254 {
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;
2258 }
2259 }
2260
2261 /* Handle mlfh!. */
2262
2263 static void
2264 s7_do16_rdhrs (char *str)
2265 {
2266 s7_skip_whitespace (str);
2267
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)
2272 {
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;
2276 }
2277 }
2278
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. */
2285
2286 static fixS *
2287 s7_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
2288 {
2289 fixS *new_fix;
2290
2291 switch (exp->X_op)
2292 {
2293 case O_constant:
2294 case O_symbol:
2295 case O_add:
2296 case O_subtract:
2297 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
2298 break;
2299 default:
2300 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
2301 break;
2302 }
2303 return new_fix;
2304 }
2305
2306 static void
2307 s7_init_dependency_vector (void)
2308 {
2309 int i;
2310
2311 for (i = 0; i < s7_vector_size; i++)
2312 memset (&s7_dependency_vector[i], '\0', sizeof (s7_dependency_vector[i]));
2313
2314 return;
2315 }
2316
2317 static enum s7_insn_type_for_dependency
2318 s7_dependency_type_from_insn (char *insn_name)
2319 {
2320 char name[s7_INSN_NAME_LEN];
2321 const struct s7_insn_to_dependency *tmp;
2322
2323 strcpy (name, insn_name);
2324 tmp = (const struct s7_insn_to_dependency *) hash_find (s7_dependency_insn_hsh, name);
2325
2326 if (tmp)
2327 return tmp->type;
2328
2329 return s7_D_all_insn;
2330 }
2331
2332 static int
2333 s7_check_dependency (char *pre_insn, char *pre_reg,
2334 char *cur_insn, char *cur_reg, int *warn_or_error)
2335 {
2336 int bubbles = 0;
2337 unsigned int i;
2338 enum s7_insn_type_for_dependency pre_insn_type;
2339 enum s7_insn_type_for_dependency cur_insn_type;
2340
2341 pre_insn_type = s7_dependency_type_from_insn (pre_insn);
2342 cur_insn_type = s7_dependency_type_from_insn (cur_insn);
2343
2344 for (i = 0; i < sizeof (s7_data_dependency_table) / sizeof (s7_data_dependency_table[0]); i++)
2345 {
2346 if ((pre_insn_type == s7_data_dependency_table[i].pre_insn_type)
2347 && (s7_D_all_insn == s7_data_dependency_table[i].cur_insn_type
2348 || cur_insn_type == s7_data_dependency_table[i].cur_insn_type)
2349 && (strcmp (s7_data_dependency_table[i].pre_reg, "") == 0
2350 || strcmp (s7_data_dependency_table[i].pre_reg, pre_reg) == 0)
2351 && (strcmp (s7_data_dependency_table[i].cur_reg, "") == 0
2352 || strcmp (s7_data_dependency_table[i].cur_reg, cur_reg) == 0))
2353 {
2354 if (s7_vector_size == s7_SCORE5_PIPELINE)
2355 bubbles = s7_data_dependency_table[i].bubblenum_5;
2356 else
2357 bubbles = s7_data_dependency_table[i].bubblenum_7;
2358 *warn_or_error = s7_data_dependency_table[i].warn_or_error;
2359 break;
2360 }
2361 }
2362
2363 return bubbles;
2364 }
2365
2366 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
2367 for use in the a.out file, and stores them in the array pointed to by buf.
2368 This knows about the endian-ness of the target machine and does
2369 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
2370 2 (short) and 4 (long) Floating numbers are put out as a series of
2371 LITTLENUMS (shorts, here at least). */
2372
2373 static void
2374 s7_number_to_chars (char *buf, valueT val, int n)
2375 {
2376 if (target_big_endian)
2377 number_to_chars_bigendian (buf, val, n);
2378 else
2379 number_to_chars_littleendian (buf, val, n);
2380 }
2381
2382 static void
2383 s7_build_one_frag (struct s7_score_it one_inst)
2384 {
2385 char *p;
2386 int relaxable_p = s7_g_opt;
2387 int relax_size = 0;
2388
2389 /* Start a new frag if frag_now is not empty. */
2390 if (frag_now_fix () != 0)
2391 {
2392 if (!frag_now->tc_frag_data.is_insn)
2393 frag_wane (frag_now);
2394
2395 frag_new (0);
2396 }
2397 frag_grow (20);
2398
2399 p = frag_more (one_inst.size);
2400 s7_number_to_chars (p, one_inst.instruction, one_inst.size);
2401
2402 #ifdef OBJ_ELF
2403 dwarf2_emit_insn (one_inst.size);
2404 #endif
2405
2406 relaxable_p &= (one_inst.relax_size != 0);
2407 relax_size = relaxable_p ? one_inst.relax_size : 0;
2408
2409 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2410 s7_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2411 one_inst.type, 0, 0, relaxable_p),
2412 NULL, 0, NULL);
2413
2414 if (relaxable_p)
2415 s7_number_to_chars (p, one_inst.relax_inst, relax_size);
2416 }
2417
2418 static void
2419 s7_handle_dependency (struct s7_score_it *theinst)
2420 {
2421 int i;
2422 int warn_or_error = 0; /* warn - 0; error - 1 */
2423 int bubbles = 0;
2424 int remainder_bubbles = 0;
2425 char cur_insn[s7_INSN_NAME_LEN];
2426 char pre_insn[s7_INSN_NAME_LEN];
2427 struct s7_score_it nop_inst;
2428 struct s7_score_it pflush_inst;
2429
2430 nop_inst.instruction = 0x0000;
2431 nop_inst.size = 2;
2432 nop_inst.relax_inst = 0x80008000;
2433 nop_inst.relax_size = 4;
2434 nop_inst.type = NO16_OPD;
2435
2436 pflush_inst.instruction = 0x8000800a;
2437 pflush_inst.size = 4;
2438 pflush_inst.relax_inst = 0x8000;
2439 pflush_inst.relax_size = 0;
2440 pflush_inst.type = NO_OPD;
2441
2442 /* pflush will clear all data dependency. */
2443 if (strcmp (theinst->name, "pflush") == 0)
2444 {
2445 s7_init_dependency_vector ();
2446 return;
2447 }
2448
2449 /* Push current instruction to s7_dependency_vector[0]. */
2450 for (i = s7_vector_size - 1; i > 0; i--)
2451 memcpy (&s7_dependency_vector[i], &s7_dependency_vector[i - 1], sizeof (s7_dependency_vector[i]));
2452
2453 memcpy (&s7_dependency_vector[0], theinst, sizeof (s7_dependency_vector[i]));
2454
2455 /* There is no dependency between nop and any instruction. */
2456 if (strcmp (s7_dependency_vector[0].name, "nop") == 0
2457 || strcmp (s7_dependency_vector[0].name, "nop!") == 0)
2458 return;
2459
2460 /* "pce" is defined in s7_insn_to_dependency_table. */
2461 #define PCE_NAME "pce"
2462
2463 if (s7_dependency_vector[0].type == Insn_Type_PCE)
2464 strcpy (cur_insn, PCE_NAME);
2465 else
2466 strcpy (cur_insn, s7_dependency_vector[0].name);
2467
2468 for (i = 1; i < s7_vector_size; i++)
2469 {
2470 /* The element of s7_dependency_vector is NULL. */
2471 if (s7_dependency_vector[i].name[0] == '\0')
2472 continue;
2473
2474 if (s7_dependency_vector[i].type == Insn_Type_PCE)
2475 strcpy (pre_insn, PCE_NAME);
2476 else
2477 strcpy (pre_insn, s7_dependency_vector[i].name);
2478
2479 bubbles = s7_check_dependency (pre_insn, s7_dependency_vector[i].reg,
2480 cur_insn, s7_dependency_vector[0].reg, &warn_or_error);
2481 remainder_bubbles = bubbles - i + 1;
2482
2483 if (remainder_bubbles > 0)
2484 {
2485 int j;
2486
2487 if (s7_fix_data_dependency == 1)
2488 {
2489 if (remainder_bubbles <= 2)
2490 {
2491 if (s7_warn_fix_data_dependency)
2492 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2493 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2494 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2495 remainder_bubbles, bubbles);
2496
2497 for (j = (s7_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2498 memcpy (&s7_dependency_vector[j], &s7_dependency_vector[j - remainder_bubbles],
2499 sizeof (s7_dependency_vector[j]));
2500
2501 for (j = 1; j <= remainder_bubbles; j++)
2502 {
2503 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2504 /* Insert nop!. */
2505 s7_build_one_frag (nop_inst);
2506 }
2507 }
2508 else
2509 {
2510 if (s7_warn_fix_data_dependency)
2511 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2512 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2513 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2514 bubbles);
2515
2516 for (j = 1; j < s7_vector_size; j++)
2517 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2518
2519 /* Insert pflush. */
2520 s7_build_one_frag (pflush_inst);
2521 }
2522 }
2523 else
2524 {
2525 if (warn_or_error)
2526 {
2527 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2528 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2529 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2530 remainder_bubbles, bubbles);
2531 }
2532 else
2533 {
2534 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2535 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2536 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2537 remainder_bubbles, bubbles);
2538 }
2539 }
2540 }
2541 }
2542 }
2543
2544 static enum insn_class
2545 s7_get_insn_class_from_type (enum score_insn_type type)
2546 {
2547 enum insn_class retval = (int) s7_FAIL;
2548
2549 switch (type)
2550 {
2551 case Rd_I4:
2552 case Rd_I5:
2553 case Rd_rvalueBP_I5:
2554 case Rd_lvalueBP_I5:
2555 case Rd_I8:
2556 case PC_DISP8div2:
2557 case PC_DISP11div2:
2558 case Rd_Rs:
2559 case Rd_HighRs:
2560 case Rd_lvalueRs:
2561 case Rd_rvalueRs:
2562 case x_Rs:
2563 case Rd_LowRs:
2564 case NO16_OPD:
2565 retval = INSN_CLASS_16;
2566 break;
2567 case Rd_Rs_I5:
2568 case x_Rs_I5:
2569 case x_I5_x:
2570 case Rd_Rs_I14:
2571 case I15:
2572 case Rd_I16:
2573 case Rd_SI16:
2574 case Rd_rvalueRs_SI10:
2575 case Rd_lvalueRs_SI10:
2576 case Rd_rvalueRs_preSI12:
2577 case Rd_rvalueRs_postSI12:
2578 case Rd_lvalueRs_preSI12:
2579 case Rd_lvalueRs_postSI12:
2580 case Rd_Rs_SI14:
2581 case Rd_rvalueRs_SI15:
2582 case Rd_lvalueRs_SI15:
2583 case PC_DISP19div2:
2584 case PC_DISP24div2:
2585 case Rd_Rs_Rs:
2586 case x_Rs_x:
2587 case x_Rs_Rs:
2588 case Rd_Rs_x:
2589 case Rd_x_Rs:
2590 case Rd_x_x:
2591 case OP5_rvalueRs_SI15:
2592 case I5_Rs_Rs_I5_OP5:
2593 case x_rvalueRs_post4:
2594 case Rd_rvalueRs_post4:
2595 case Rd_x_I5:
2596 case Rd_lvalueRs_post4:
2597 case x_lvalueRs_post4:
2598 case Rd_Rs_Rs_imm:
2599 case NO_OPD:
2600 case Rd_lvalue32Rs:
2601 case Rd_rvalue32Rs:
2602 case Insn_GP:
2603 case Insn_PIC:
2604 case Insn_internal:
2605 retval = INSN_CLASS_32;
2606 break;
2607 case Insn_Type_PCE:
2608 retval = INSN_CLASS_PCE;
2609 break;
2610 case Insn_Type_SYN:
2611 retval = INSN_CLASS_SYN;
2612 break;
2613 default:
2614 abort ();
2615 break;
2616 }
2617 return retval;
2618 }
2619
2620 static unsigned long
2621 s7_adjust_paritybit (unsigned long m_code, enum insn_class i_class)
2622 {
2623 unsigned long result = 0;
2624 unsigned long m_code_high = 0;
2625 unsigned long m_code_low = 0;
2626 unsigned long pb_high = 0;
2627 unsigned long pb_low = 0;
2628
2629 if (i_class == INSN_CLASS_32)
2630 {
2631 pb_high = 0x80000000;
2632 pb_low = 0x00008000;
2633 }
2634 else if (i_class == INSN_CLASS_16)
2635 {
2636 pb_high = 0;
2637 pb_low = 0;
2638 }
2639 else if (i_class == INSN_CLASS_PCE)
2640 {
2641 pb_high = 0;
2642 pb_low = 0x00008000;
2643 }
2644 else if (i_class == INSN_CLASS_SYN)
2645 {
2646 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2647 be changed if macro instruction has been expanded. */
2648 pb_high = 0x80000000;
2649 pb_low = 0x00008000;
2650 }
2651 else
2652 {
2653 abort ();
2654 }
2655
2656 m_code_high = m_code & 0x3fff8000;
2657 m_code_low = m_code & 0x00007fff;
2658 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2659 return result;
2660
2661 }
2662
2663 static void
2664 s7_gen_insn_frag (struct s7_score_it *part_1, struct s7_score_it *part_2)
2665 {
2666 char *p;
2667 bfd_boolean pce_p = FALSE;
2668 int relaxable_p = s7_g_opt;
2669 int relax_size = 0;
2670 struct s7_score_it *inst1 = part_1;
2671 struct s7_score_it *inst2 = part_2;
2672 struct s7_score_it backup_inst1;
2673
2674 pce_p = (inst2) ? TRUE : FALSE;
2675 memcpy (&backup_inst1, inst1, sizeof (struct s7_score_it));
2676
2677 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2678 if (pce_p)
2679 {
2680 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2681 | (inst2->instruction & 0x7FFF);
2682 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2683 if (!target_big_endian)
2684 {
2685 unsigned long tmp = backup_inst1.instruction;
2686 backup_inst1.instruction = ((tmp & 0xffff) << 16)
2687 | (tmp >> 16);
2688 }
2689 backup_inst1.relax_inst = 0x8000;
2690 backup_inst1.size = s7_INSN_SIZE;
2691 backup_inst1.relax_size = 0;
2692 backup_inst1.type = Insn_Type_PCE;
2693 }
2694 else
2695 {
2696 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction,
2697 s7_GET_INSN_CLASS (backup_inst1.type));
2698 }
2699
2700 if (backup_inst1.relax_size != 0)
2701 {
2702 enum insn_class tmp;
2703
2704 tmp = (backup_inst1.size == s7_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2705 backup_inst1.relax_inst = s7_adjust_paritybit (backup_inst1.relax_inst, tmp);
2706 }
2707
2708 /* Check data dependency. */
2709 s7_handle_dependency (&backup_inst1);
2710
2711 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2712 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2713 if (frag_now_fix () != 0)
2714 {
2715 if (!frag_now->tc_frag_data.is_insn)
2716 frag_wane (frag_now);
2717
2718 frag_new (0);
2719 }
2720
2721 /* Here, we must call frag_grow in order to keep the instruction frag type is
2722 rs_machine_dependent.
2723 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2724 actually will call frag_wane.
2725 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2726 for frag_var. */
2727 frag_grow (20);
2728
2729 p = frag_more (backup_inst1.size);
2730 s7_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2731
2732 #ifdef OBJ_ELF
2733 dwarf2_emit_insn (backup_inst1.size);
2734 #endif
2735
2736 /* Generate fixup structure. */
2737 if (pce_p)
2738 {
2739 if (inst1->reloc.type != BFD_RELOC_NONE)
2740 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2741 inst1->size, &inst1->reloc.exp,
2742 inst1->reloc.pc_rel, inst1->reloc.type);
2743
2744 if (inst2->reloc.type != BFD_RELOC_NONE)
2745 s7_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2746 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2747 }
2748 else
2749 {
2750 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2751 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2752 backup_inst1.size, &backup_inst1.reloc.exp,
2753 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2754 }
2755
2756 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2757 relaxable_p &= (backup_inst1.relax_size != 0);
2758 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2759
2760 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2761 s7_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2762 backup_inst1.type, 0, 0, relaxable_p),
2763 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2764
2765 if (relaxable_p)
2766 s7_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2767
2768 memcpy (inst1, &backup_inst1, sizeof (struct s7_score_it));
2769 }
2770
2771 static void
2772 s7_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2773 {
2774 char c;
2775 char *p;
2776 char *operator = insnstr;
2777 const struct s7_asm_opcode *opcode;
2778
2779 /* Parse operator and operands. */
2780 s7_skip_whitespace (operator);
2781
2782 for (p = operator; *p != '\0'; p++)
2783 if ((*p == ' ') || (*p == '!'))
2784 break;
2785
2786 if (*p == '!')
2787 p++;
2788
2789 c = *p;
2790 *p = '\0';
2791
2792 opcode = (const struct s7_asm_opcode *) hash_find (s7_score_ops_hsh, operator);
2793 *p = c;
2794
2795 memset (&s7_inst, '\0', sizeof (s7_inst));
2796 strcpy (s7_inst.str, insnstr);
2797 if (opcode)
2798 {
2799 s7_inst.instruction = opcode->value;
2800 s7_inst.relax_inst = opcode->relax_value;
2801 s7_inst.type = opcode->type;
2802 s7_inst.size = s7_GET_INSN_SIZE (s7_inst.type);
2803 s7_inst.relax_size = 0;
2804 s7_inst.bwarn = 0;
2805 strcpy (s7_inst.name, opcode->template_name);
2806 strcpy (s7_inst.reg, "");
2807 s7_inst.error = NULL;
2808 s7_inst.reloc.type = BFD_RELOC_NONE;
2809
2810 (*opcode->parms) (p);
2811
2812 /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1. */
2813 if ((s7_inst.bwarn != -1) && (!s7_inst.error) && (gen_frag_p))
2814 s7_gen_insn_frag (&s7_inst, NULL);
2815 }
2816 else
2817 s7_inst.error = _("unrecognized opcode");
2818 }
2819
2820 static int
2821 s7_append_insn (char *str, bfd_boolean gen_frag_p)
2822 {
2823 int retval = s7_SUCCESS;
2824
2825 s7_parse_16_32_inst (str, gen_frag_p);
2826
2827 if (s7_inst.error)
2828 {
2829 retval = (int) s7_FAIL;
2830 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
2831 s7_inst.error = NULL;
2832 }
2833
2834 return retval;
2835 }
2836
2837 /* Handle mv! reg_high, reg_low;
2838 mv! reg_low, reg_high;
2839 mv! reg_low, reg_low; */
2840 static void
2841 s7_do16_mv_rdrs (char *str)
2842 {
2843 int reg_rd;
2844 int reg_rs;
2845 char *backupstr = NULL;
2846
2847 backupstr = str;
2848 s7_skip_whitespace (str);
2849
2850 if ((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2851 || s7_skip_past_comma (&str) == (int) s7_FAIL
2852 || (reg_rs = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2853 || s7_end_of_line (str) == (int) s7_FAIL)
2854 {
2855 return;
2856 }
2857 else
2858 {
2859 /* Case 1 : mv! or mlfh!. */
2860 if (reg_rd < 16)
2861 {
2862 if (reg_rs < 16)
2863 {
2864 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2865 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2866 s7_inst.relax_size = 4;
2867 }
2868 else
2869 {
2870 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2871
2872 sprintf (append_str, "mlfh! %s", backupstr);
2873 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2874 return;
2875 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2876 s7_inst.bwarn = -1;
2877 }
2878 }
2879 /* Case 2 : mhfl!. */
2880 else
2881 {
2882 if (reg_rs > 16)
2883 {
2884 s7_SET_INSN_ERROR (s7_BAD_ARGS);
2885 return;
2886 }
2887 else
2888 {
2889 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2890
2891 sprintf (append_str, "mhfl! %s", backupstr);
2892 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2893 return;
2894
2895 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2896 s7_inst.bwarn = -1;
2897 }
2898 }
2899 }
2900 }
2901
2902 static void
2903 s7_do16_rdi4 (char *str)
2904 {
2905 s7_skip_whitespace (str);
2906
2907 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2908 || s7_skip_past_comma (&str) == (int) s7_FAIL
2909 || s7_data_op2 (&str, 3, _IMM4) == (int) s7_FAIL
2910 || s7_end_of_line (str) == (int) s7_FAIL)
2911 {
2912 return;
2913 }
2914 else
2915 {
2916 if (((s7_inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2917 {
2918 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2919 {
2920 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2921 | ((1 << ((s7_inst.instruction >> 3) & 0xf)) << 1);
2922 s7_inst.relax_size = 4;
2923 }
2924 else
2925 {
2926 s7_inst.relax_inst = 0x8000;
2927 }
2928 }
2929 else
2930 {
2931 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2932 {
2933 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2934 | (((-(1 << ((s7_inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2935 s7_inst.relax_size = 4;
2936 }
2937 else
2938 {
2939 s7_inst.relax_inst = 0x8000;
2940 }
2941 }
2942 }
2943 }
2944
2945 static void
2946 s7_do16_rdi5 (char *str)
2947 {
2948 s7_skip_whitespace (str);
2949
2950 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2951 || s7_skip_past_comma (&str) == (int) s7_FAIL
2952 || s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL
2953 || s7_end_of_line (str) == (int) s7_FAIL)
2954 return;
2955 else
2956 {
2957 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2958 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 3) & 0x1f) << 10);
2959 s7_inst.relax_size = 4;
2960 }
2961 }
2962
2963 /* Handle sdbbp. */
2964
2965 static void
2966 s7_do16_xi5 (char *str)
2967 {
2968 s7_skip_whitespace (str);
2969
2970 if (s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2971 return;
2972 else
2973 {
2974 s7_inst.relax_inst |= (((s7_inst.instruction >> 3) & 0x1f) << 15);
2975 s7_inst.relax_size = 4;
2976 }
2977 }
2978
2979 /* Check that an immediate is word alignment or half word alignment.
2980 If so, convert it to the right format. */
2981
2982 static int
2983 s7_validate_immediate_align (int val, unsigned int data_type)
2984 {
2985 if (data_type == _IMM5_RSHIFT_1)
2986 {
2987 if (val % 2)
2988 {
2989 s7_inst.error = _("address offset must be half word alignment");
2990 return (int) s7_FAIL;
2991 }
2992 }
2993 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2994 {
2995 if (val % 4)
2996 {
2997 s7_inst.error = _("address offset must be word alignment");
2998 return (int) s7_FAIL;
2999 }
3000 }
3001
3002 return s7_SUCCESS;
3003 }
3004
3005 static int
3006 s7_exp_ldst_offset (char **str, int shift, unsigned int data_type)
3007 {
3008 char *dataptr;
3009 int hex_p = 0;
3010
3011 dataptr = * str;
3012
3013 if ((dataptr != NULL)
3014 && (((strstr (dataptr, "0x")) != NULL)
3015 || ((strstr (dataptr, "0X")) != NULL)))
3016 {
3017 hex_p = 1;
3018 if ((data_type != _SIMM16_LA)
3019 && (data_type != _VALUE_HI16)
3020 && (data_type != _VALUE_LO16)
3021 && (data_type != _IMM16)
3022 && (data_type != _IMM15)
3023 && (data_type != _IMM14)
3024 && (data_type != _IMM4)
3025 && (data_type != _IMM5)
3026 && (data_type != _IMM8)
3027 && (data_type != _IMM5_RSHIFT_1)
3028 && (data_type != _IMM5_RSHIFT_2)
3029 && (data_type != _SIMM12)
3030 && (data_type != _SIMM15)
3031 && (data_type != _SIMM14_NEG)
3032 && (data_type != _IMM10_RSHIFT_2))
3033 {
3034 data_type += 24;
3035 }
3036 }
3037
3038 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
3039 return (int) s7_FAIL;
3040
3041 if (s7_inst.reloc.exp.X_op == O_constant)
3042 {
3043 /* Need to check the immediate align. */
3044 int value = s7_validate_immediate_align (s7_inst.reloc.exp.X_add_number, data_type);
3045
3046 if (value == (int) s7_FAIL)
3047 return (int) s7_FAIL;
3048
3049 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3050 if (value == (int) s7_FAIL)
3051 {
3052 if (data_type < 30)
3053 sprintf (s7_err_msg,
3054 _("invalid constant: %d bit expression not in range %d..%d"),
3055 s7_score_df_range[data_type].bits,
3056 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3057 else
3058 sprintf (s7_err_msg,
3059 _("invalid constant: %d bit expression not in range %d..%d"),
3060 s7_score_df_range[data_type - 24].bits,
3061 s7_score_df_range[data_type - 24].range[0], s7_score_df_range[data_type - 24].range[1]);
3062 s7_inst.error = s7_err_msg;
3063 return (int) s7_FAIL;
3064 }
3065
3066 if (data_type == _IMM5_RSHIFT_1)
3067 {
3068 value >>= 1;
3069 }
3070 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
3071 {
3072 value >>= 2;
3073 }
3074
3075 if (s7_score_df_range[data_type].range[0] != 0)
3076 {
3077 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3078 }
3079
3080 s7_inst.instruction |= value << shift;
3081 }
3082 else
3083 {
3084 s7_inst.reloc.pc_rel = 0;
3085 }
3086
3087 return s7_SUCCESS;
3088 }
3089
3090 static void
3091 s7_do_ldst_insn (char *str)
3092 {
3093 int pre_inc = 0;
3094 int conflict_reg;
3095 int value;
3096 char * temp;
3097 char *dataptr;
3098 int reg;
3099 int ldst_idx = 0;
3100
3101 int hex_p = 0;
3102
3103 s7_skip_whitespace (str);
3104
3105 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3106 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3107 return;
3108
3109 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
3110 if (*str == '[')
3111 {
3112 str++;
3113 s7_skip_whitespace (str);
3114
3115 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3116 return;
3117
3118 /* Conflicts can occur on stores as well as loads. */
3119 conflict_reg = (conflict_reg == reg);
3120 s7_skip_whitespace (str);
3121 temp = str + 1; /* The latter will process decimal/hex expression. */
3122
3123 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
3124 if (*str == ']')
3125 {
3126 str++;
3127 if (*str == '+')
3128 {
3129 str++;
3130 /* ld/sw rD, [rA]+, simm12. */
3131 if (s7_skip_past_comma (&str) == s7_SUCCESS)
3132 {
3133 if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
3134 || (s7_end_of_line (str) == (int) s7_FAIL))
3135 return;
3136
3137 if (conflict_reg)
3138 {
3139 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3140
3141 if ((ldst_func == INSN_LH)
3142 || (ldst_func == INSN_LHU)
3143 || (ldst_func == INSN_LW)
3144 || (ldst_func == INSN_LB)
3145 || (ldst_func == INSN_LBU))
3146 {
3147 s7_inst.error = _("register same as write-back base");
3148 return;
3149 }
3150 }
3151
3152 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3153 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3154 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
3155
3156 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
3157 if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
3158 {
3159 /* rs = r0-r7, offset = 4 */
3160 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3161 && (((s7_inst.instruction >> 3) & 0xfff) == 4))
3162 {
3163 /* Relax to pophi. */
3164 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3165 {
3166 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3167 << 8) | 1 << 7 |
3168 (((s7_inst.instruction >> 15) & 0x7) << 4);
3169 }
3170 /* Relax to pop. */
3171 else
3172 {
3173 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3174 << 8) | 0 << 7 |
3175 (((s7_inst.instruction >> 15) & 0x7) << 4);
3176 }
3177 s7_inst.relax_size = 2;
3178 }
3179 }
3180 return;
3181 }
3182 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3183 else
3184 {
3185 s7_SET_INSN_ERROR (NULL);
3186 if (s7_end_of_line (str) == (int) s7_FAIL)
3187 {
3188 return;
3189 }
3190
3191 pre_inc = 1;
3192 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
3193 value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
3194 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3195 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3196 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3197 s7_inst.instruction |= value << 3;
3198 s7_inst.relax_inst = 0x8000;
3199 return;
3200 }
3201 }
3202 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3203 else
3204 {
3205 if (s7_end_of_line (str) == (int) s7_FAIL)
3206 return;
3207
3208 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3209 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3210 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3211
3212 /* lbu rd, [rs] -> lbu! rd, [rs] */
3213 if (ldst_idx == INSN_LBU)
3214 {
3215 s7_inst.relax_inst = INSN16_LBU;
3216 }
3217 else if (ldst_idx == INSN_LH)
3218 {
3219 s7_inst.relax_inst = INSN16_LH;
3220 }
3221 else if (ldst_idx == INSN_LW)
3222 {
3223 s7_inst.relax_inst = INSN16_LW;
3224 }
3225 else if (ldst_idx == INSN_SB)
3226 {
3227 s7_inst.relax_inst = INSN16_SB;
3228 }
3229 else if (ldst_idx == INSN_SH)
3230 {
3231 s7_inst.relax_inst = INSN16_SH;
3232 }
3233 else if (ldst_idx == INSN_SW)
3234 {
3235 s7_inst.relax_inst = INSN16_SW;
3236 }
3237 else
3238 {
3239 s7_inst.relax_inst = 0x8000;
3240 }
3241
3242 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
3243 if ((ldst_idx == INSN_LBU)
3244 || (ldst_idx == INSN_LH)
3245 || (ldst_idx == INSN_LW)
3246 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
3247 {
3248 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3249 {
3250 s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
3251 (((s7_inst.instruction >> 15) & 0xf) << 4);
3252 s7_inst.relax_size = 2;
3253 }
3254 }
3255
3256 return;
3257 }
3258 }
3259 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3260 else
3261 {
3262 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3263 {
3264 s7_inst.error = _("pre-indexed expression expected");
3265 return;
3266 }
3267
3268 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
3269 return;
3270
3271 s7_skip_whitespace (str);
3272 if (*str++ != ']')
3273 {
3274 s7_inst.error = _("missing ]");
3275 return;
3276 }
3277
3278 s7_skip_whitespace (str);
3279 /* ld/sw rD, [rA, simm12]+. */
3280 if (*str == '+')
3281 {
3282 str++;
3283 pre_inc = 1;
3284 if (conflict_reg)
3285 {
3286 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3287
3288 if ((ldst_func == INSN_LH)
3289 || (ldst_func == INSN_LHU)
3290 || (ldst_func == INSN_LW)
3291 || (ldst_func == INSN_LB)
3292 || (ldst_func == INSN_LBU))
3293 {
3294 s7_inst.error = _("register same as write-back base");
3295 return;
3296 }
3297 }
3298 }
3299
3300 if (s7_end_of_line (str) == (int) s7_FAIL)
3301 return;
3302
3303 if (s7_inst.reloc.exp.X_op == O_constant)
3304 {
3305 unsigned int data_type;
3306
3307 if (pre_inc == 1)
3308 data_type = _SIMM12;
3309 else
3310 data_type = _SIMM15;
3311 dataptr = temp;
3312
3313 if ((dataptr != NULL)
3314 && (((strstr (dataptr, "0x")) != NULL)
3315 || ((strstr (dataptr, "0X")) != NULL)))
3316 {
3317 hex_p = 1;
3318 if ((data_type != _SIMM16_LA)
3319 && (data_type != _VALUE_HI16)
3320 && (data_type != _VALUE_LO16)
3321 && (data_type != _IMM16)
3322 && (data_type != _IMM15)
3323 && (data_type != _IMM14)
3324 && (data_type != _IMM4)
3325 && (data_type != _IMM5)
3326 && (data_type != _IMM8)
3327 && (data_type != _SIMM12)
3328 && (data_type != _SIMM15)
3329 && (data_type != _IMM5_RSHIFT_1)
3330 && (data_type != _IMM5_RSHIFT_2)
3331 && (data_type != _SIMM14_NEG)
3332 && (data_type != _IMM10_RSHIFT_2))
3333 {
3334 data_type += 24;
3335 }
3336 }
3337
3338 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3339 if (value == (int) s7_FAIL)
3340 {
3341 if (data_type < 30)
3342 sprintf (s7_err_msg,
3343 _("invalid constant: %d bit expression not in range %d..%d"),
3344 s7_score_df_range[data_type].bits,
3345 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3346 else
3347 sprintf (s7_err_msg,
3348 _("invalid constant: %d bit expression not in range %d..%d"),
3349 s7_score_df_range[data_type - 24].bits,
3350 s7_score_df_range[data_type - 24].range[0],
3351 s7_score_df_range[data_type - 24].range[1]);
3352 s7_inst.error = s7_err_msg;
3353 return;
3354 }
3355
3356 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3357 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3358 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3359 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3360 if (pre_inc == 1)
3361 s7_inst.instruction |= value << 3;
3362 else
3363 s7_inst.instruction |= value;
3364
3365 /* lw rD, [rA, simm15] */
3366 if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3367 {
3368 /* Both rD and rA are in [r0 - r15]. */
3369 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3370 && (((s7_inst.instruction >> 20) & 0x10) == 0))
3371 {
3372 /* simm15 = 0, lw -> lw!. */
3373 if ((s7_inst.instruction & 0x7fff) == 0)
3374 {
3375 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3376 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3377 s7_inst.relax_size = 2;
3378 }
3379 /* rA = r2, lw -> lwp!. */
3380 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3381 && ((s7_inst.instruction & 0x3) == 0)
3382 && ((s7_inst.instruction & 0x7fff) < 128))
3383 {
3384 s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3385 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3386 s7_inst.relax_size = 2;
3387 }
3388 else
3389 {
3390 s7_inst.relax_inst = 0x8000;
3391 }
3392 }
3393 else
3394 {
3395 s7_inst.relax_inst = 0x8000;
3396 }
3397 }
3398 /* sw rD, [rA, simm15] */
3399 else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3400 {
3401 /* Both rD and rA are in [r0 - r15]. */
3402 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3403 {
3404 /* simm15 = 0, sw -> sw!. */
3405 if ((s7_inst.instruction & 0x7fff) == 0)
3406 {
3407 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3408 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3409 s7_inst.relax_size = 2;
3410 }
3411 /* rA = r2, sw -> swp!. */
3412 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3413 && ((s7_inst.instruction & 0x3) == 0)
3414 && ((s7_inst.instruction & 0x7fff) < 128))
3415 {
3416 s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3417 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3418 s7_inst.relax_size = 2;
3419 }
3420 else
3421 {
3422 s7_inst.relax_inst = 0x8000;
3423 }
3424 }
3425 else
3426 {
3427 s7_inst.relax_inst = 0x8000;
3428 }
3429 }
3430 /* sw rD, [rA, simm15]+ sw pre. */
3431 else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3432 {
3433 /* rA is in [r0 - r7], and simm15 = -4. */
3434 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3435 && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3436 {
3437 /* sw -> pushhi!. */
3438 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3439 {
3440 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3441 | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3442 s7_inst.relax_size = 2;
3443 }
3444 /* sw -> push!. */
3445 else
3446 {
3447 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3448 | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3449 s7_inst.relax_size = 2;
3450 }
3451 }
3452 else
3453 {
3454 s7_inst.relax_inst = 0x8000;
3455 }
3456 }
3457 /* lh rD, [rA, simm15] */
3458 else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3459 {
3460 /* Both rD and rA are in [r0 - r15]. */
3461 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3462 {
3463 /* simm15 = 0, lh -> lh!. */
3464 if ((s7_inst.instruction & 0x7fff) == 0)
3465 {
3466 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3467 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3468 s7_inst.relax_size = 2;
3469 }
3470 /* rA = r2, lh -> lhp!. */
3471 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3472 && ((s7_inst.instruction & 0x1) == 0)
3473 && ((s7_inst.instruction & 0x7fff) < 64))
3474 {
3475 s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3476 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3477 s7_inst.relax_size = 2;
3478 }
3479 else
3480 {
3481 s7_inst.relax_inst = 0x8000;
3482 }
3483 }
3484 else
3485 {
3486 s7_inst.relax_inst = 0x8000;
3487 }
3488 }
3489 /* sh rD, [rA, simm15] */
3490 else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3491 {
3492 /* Both rD and rA are in [r0 - r15]. */
3493 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3494 {
3495 /* simm15 = 0, sh -> sh!. */
3496 if ((s7_inst.instruction & 0x7fff) == 0)
3497 {
3498 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3499 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3500 s7_inst.relax_size = 2;
3501 }
3502 /* rA = r2, sh -> shp!. */
3503 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3504 && ((s7_inst.instruction & 0x1) == 0)
3505 && ((s7_inst.instruction & 0x7fff) < 64))
3506 {
3507 s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3508 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3509 s7_inst.relax_size = 2;
3510 }
3511 else
3512 {
3513 s7_inst.relax_inst = 0x8000;
3514 }
3515 }
3516 else
3517 {
3518 s7_inst.relax_inst = 0x8000;
3519 }
3520 }
3521 /* lbu rD, [rA, simm15] */
3522 else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3523 {
3524 /* Both rD and rA are in [r0 - r15]. */
3525 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3526 {
3527 /* simm15 = 0, lbu -> lbu!. */
3528 if ((s7_inst.instruction & 0x7fff) == 0)
3529 {
3530 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3531 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3532 s7_inst.relax_size = 2;
3533 }
3534 /* rA = r2, lbu -> lbup!. */
3535 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3536 && ((s7_inst.instruction & 0x7fff) < 32))
3537 {
3538 s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3539 | ((s7_inst.instruction & 0x7fff) << 3);
3540 s7_inst.relax_size = 2;
3541 }
3542 else
3543 {
3544 s7_inst.relax_inst = 0x8000;
3545 }
3546 }
3547 else
3548 {
3549 s7_inst.relax_inst = 0x8000;
3550 }
3551 }
3552 /* sb rD, [rA, simm15] */
3553 else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3554 {
3555 /* Both rD and rA are in [r0 - r15]. */
3556 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3557 {
3558 /* simm15 = 0, sb -> sb!. */
3559 if ((s7_inst.instruction & 0x7fff) == 0)
3560 {
3561 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3562 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3563 s7_inst.relax_size = 2;
3564 }
3565 /* rA = r2, sb -> sb!. */
3566 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3567 && ((s7_inst.instruction & 0x7fff) < 32))
3568 {
3569 s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3570 | ((s7_inst.instruction & 0x7fff) << 3);
3571 s7_inst.relax_size = 2;
3572 }
3573 else
3574 {
3575 s7_inst.relax_inst = 0x8000;
3576 }
3577 }
3578 else
3579 {
3580 s7_inst.relax_inst = 0x8000;
3581 }
3582 }
3583 else
3584 {
3585 s7_inst.relax_inst = 0x8000;
3586 }
3587
3588 return;
3589 }
3590 else
3591 {
3592 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3593 s7_inst.reloc.pc_rel = 0;
3594 }
3595 }
3596 }
3597 else
3598 {
3599 s7_inst.error = s7_BAD_ARGS;
3600 }
3601 }
3602
3603 /* Handle cache. */
3604 static void
3605 s7_do_cache (char *str)
3606 {
3607 s7_skip_whitespace (str);
3608
3609 if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3610 {
3611 return;
3612 }
3613 else
3614 {
3615 int cache_op;
3616
3617 cache_op = (s7_inst.instruction >> 20) & 0x1F;
3618 sprintf (s7_inst.name, "cache %d", cache_op);
3619 }
3620
3621 if (*str == '[')
3622 {
3623 str++;
3624 s7_skip_whitespace (str);
3625
3626 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3627 return;
3628
3629 s7_skip_whitespace (str);
3630
3631 /* cache op, [rA] */
3632 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3633 {
3634 s7_SET_INSN_ERROR (NULL);
3635 if (*str != ']')
3636 {
3637 s7_inst.error = _("missing ]");
3638 return;
3639 }
3640 str++;
3641 }
3642 /* cache op, [rA, simm15] */
3643 else
3644 {
3645 if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3646 {
3647 return;
3648 }
3649
3650 s7_skip_whitespace (str);
3651 if (*str++ != ']')
3652 {
3653 s7_inst.error = _("missing ]");
3654 return;
3655 }
3656 }
3657
3658 if (s7_end_of_line (str) == (int) s7_FAIL)
3659 return;
3660 }
3661 else
3662 {
3663 s7_inst.error = s7_BAD_ARGS;
3664 }
3665 }
3666
3667 static void
3668 s7_do_crdcrscrsimm5 (char *str)
3669 {
3670 char *strbak;
3671
3672 strbak = str;
3673 s7_skip_whitespace (str);
3674
3675 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3676 || s7_skip_past_comma (&str) == (int) s7_FAIL
3677 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3678 || s7_skip_past_comma (&str) == (int) s7_FAIL
3679 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3680 || s7_skip_past_comma (&str) == (int) s7_FAIL)
3681 {
3682 str = strbak;
3683 /* cop1 cop_code20. */
3684 if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3685 return;
3686 }
3687 else
3688 {
3689 if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3690 return;
3691 }
3692
3693 s7_end_of_line (str);
3694 }
3695
3696 /* Handle ldc/stc. */
3697 static void
3698 s7_do_ldst_cop (char *str)
3699 {
3700 s7_skip_whitespace (str);
3701
3702 if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3703 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3704 return;
3705
3706 if (*str == '[')
3707 {
3708 str++;
3709 s7_skip_whitespace (str);
3710
3711 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3712 return;
3713
3714 s7_skip_whitespace (str);
3715
3716 if (*str++ != ']')
3717 {
3718 if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3719 return;
3720
3721 s7_skip_whitespace (str);
3722 if (*str++ != ']')
3723 {
3724 s7_inst.error = _("missing ]");
3725 return;
3726 }
3727 }
3728
3729 s7_end_of_line (str);
3730 }
3731 else
3732 s7_inst.error = s7_BAD_ARGS;
3733 }
3734
3735 static void
3736 s7_do16_ldst_insn (char *str)
3737 {
3738 s7_skip_whitespace (str);
3739
3740 if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3741 return;
3742
3743 if (*str == '[')
3744 {
3745 int reg;
3746
3747 str++;
3748 s7_skip_whitespace (str);
3749
3750 if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3751 return;
3752
3753 s7_skip_whitespace (str);
3754 if (*str++ == ']')
3755 {
3756 if (s7_end_of_line (str) == (int) s7_FAIL)
3757 return;
3758 else
3759 {
3760 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3761 | (((s7_inst.instruction >> 4) & 0xf) << 15);
3762 s7_inst.relax_size = 4;
3763 }
3764 }
3765 else
3766 {
3767 s7_inst.error = _("missing ]");
3768 }
3769 }
3770 else
3771 {
3772 s7_inst.error = s7_BAD_ARGS;
3773 }
3774 }
3775
3776 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3777
3778 static void
3779 s7_do16_ldst_imm_insn (char *str)
3780 {
3781 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3782 int reg_rd;
3783 char *dataptr = NULL, *pp = NULL;
3784 int cnt = 0;
3785 int assign_data = (int) s7_FAIL;
3786 unsigned int ldst_func;
3787
3788 s7_skip_whitespace (str);
3789
3790 if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3791 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3792 return;
3793
3794 s7_skip_whitespace (str);
3795 dataptr = str;
3796
3797 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3798 {
3799 data_exp[cnt] = *dataptr;
3800 dataptr++;
3801 cnt++;
3802 }
3803
3804 data_exp[cnt] = '\0';
3805 pp = &data_exp[0];
3806
3807 str = dataptr;
3808
3809 ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3810 if (ldst_func == N16_LIU)
3811 assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3812 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3813 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3814 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3815 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3816 else
3817 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3818
3819 if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3820 return;
3821 else
3822 {
3823 if ((s7_inst.instruction & 0x7000) == N16_LIU)
3824 {
3825 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3826 | ((s7_inst.instruction & 0xff) << 1);
3827 }
3828 else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3829 || ((s7_inst.instruction & 0x7007) == N16_SHP))
3830 {
3831 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3832 | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3833 }
3834 else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3835 || ((s7_inst.instruction & 0x7007) == N16_SWP))
3836 {
3837 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3838 | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3839 }
3840 else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3841 || ((s7_inst.instruction & 0x7007) == N16_SBP))
3842 {
3843 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3844 | (((s7_inst.instruction >> 3) & 0x1f));
3845 }
3846
3847 s7_inst.relax_size = 4;
3848 }
3849 }
3850
3851 static void
3852 s7_do16_push_pop (char *str)
3853 {
3854 int reg_rd;
3855 int H_bit_mask = 0;
3856
3857 s7_skip_whitespace (str);
3858 if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3859 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3860 return;
3861
3862 if (reg_rd >= 16)
3863 H_bit_mask = 1;
3864
3865 /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3866 s7_inst.instruction &= ~(1 << 12);
3867
3868 s7_inst.instruction |= H_bit_mask << 7;
3869
3870 if (*str == '[')
3871 {
3872 int reg;
3873
3874 str++;
3875 s7_skip_whitespace (str);
3876 if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3877 return;
3878 else if (reg > 7)
3879 {
3880 if (!s7_inst.error)
3881 s7_inst.error = _("base register nums are over 3 bit");
3882
3883 return;
3884 }
3885
3886 s7_skip_whitespace (str);
3887 if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3888 {
3889 if (!s7_inst.error)
3890 s7_inst.error = _("missing ]");
3891
3892 return;
3893 }
3894
3895 /* pop! */
3896 if ((s7_inst.instruction & 0xf) == 0xa)
3897 {
3898 if (H_bit_mask)
3899 {
3900 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3901 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3902 }
3903 else
3904 {
3905 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3906 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3907 }
3908 }
3909 /* push! */
3910 else
3911 {
3912 if (H_bit_mask)
3913 {
3914 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3915 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3916 }
3917 else
3918 {
3919 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3920 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3921 }
3922 }
3923 s7_inst.relax_size = 4;
3924 }
3925 else
3926 {
3927 s7_inst.error = s7_BAD_ARGS;
3928 }
3929 }
3930
3931 /* Handle lcb/lcw/lce/scb/scw/sce. */
3932 static void
3933 s7_do_ldst_unalign (char *str)
3934 {
3935 int conflict_reg;
3936
3937 if (s7_university_version == 1)
3938 {
3939 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3940 return;
3941 }
3942
3943 s7_skip_whitespace (str);
3944
3945 /* lcb/scb [rA]+. */
3946 if (*str == '[')
3947 {
3948 str++;
3949 s7_skip_whitespace (str);
3950
3951 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3952 return;
3953
3954 if (*str++ == ']')
3955 {
3956 if (*str++ != '+')
3957 {
3958 s7_inst.error = _("missing +");
3959 return;
3960 }
3961 }
3962 else
3963 {
3964 s7_inst.error = _("missing ]");
3965 return;
3966 }
3967
3968 if (s7_end_of_line (str) == (int) s7_FAIL)
3969 return;
3970 }
3971 /* lcw/lce/scb/sce rD, [rA]+. */
3972 else
3973 {
3974 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3975 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3976 {
3977 return;
3978 }
3979
3980 s7_skip_whitespace (str);
3981 if (*str++ == '[')
3982 {
3983 int reg;
3984
3985 s7_skip_whitespace (str);
3986 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3987 {
3988 return;
3989 }
3990
3991 /* Conflicts can occur on stores as well as loads. */
3992 conflict_reg = (conflict_reg == reg);
3993 s7_skip_whitespace (str);
3994 if (*str++ == ']')
3995 {
3996 unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
3997
3998 if (*str++ == '+')
3999 {
4000 if (conflict_reg)
4001 {
4002 as_warn (_("%s register same as write-back base"),
4003 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4004 ? _("destination") : _("source")));
4005 }
4006 }
4007 else
4008 {
4009 s7_inst.error = _("missing +");
4010 return;
4011 }
4012
4013 if (s7_end_of_line (str) == (int) s7_FAIL)
4014 return;
4015 }
4016 else
4017 {
4018 s7_inst.error = _("missing ]");
4019 return;
4020 }
4021 }
4022 else
4023 {
4024 s7_inst.error = s7_BAD_ARGS;
4025 return;
4026 }
4027 }
4028 }
4029
4030 /* Handle alw/asw. */
4031
4032 static void
4033 s7_do_ldst_atomic (char *str)
4034 {
4035 if (s7_university_version == 1)
4036 {
4037 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4038 return;
4039 }
4040
4041 s7_skip_whitespace (str);
4042
4043 if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4044 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4045 {
4046 return;
4047 }
4048 else
4049 {
4050
4051 s7_skip_whitespace (str);
4052 if (*str++ == '[')
4053 {
4054 int reg;
4055
4056 s7_skip_whitespace (str);
4057 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4058 {
4059 return;
4060 }
4061
4062 s7_skip_whitespace (str);
4063 if (*str++ != ']')
4064 {
4065 s7_inst.error = _("missing ]");
4066 return;
4067 }
4068
4069 s7_end_of_line (str);
4070 }
4071 else
4072 s7_inst.error = s7_BAD_ARGS;
4073 }
4074 }
4075
4076 static void
4077 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4078 int fix_num ATTRIBUTE_UNUSED,
4079 struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4080 symbolS *add_symbol)
4081 {
4082 int i;
4083 char *p;
4084 fixS *fixp = NULL;
4085 fixS *cur_fixp = NULL;
4086 long where;
4087 struct s7_score_it inst_main;
4088
4089 memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4090
4091 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4092 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4093 inst_main.type = Insn_PIC;
4094
4095 for (i = 0; i < var_num; i++)
4096 {
4097 inst_main.relax_size += var_insts[i].size;
4098 var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4099 s7_GET_INSN_CLASS (var_insts[i].type));
4100 }
4101
4102 /* Check data dependency. */
4103 s7_handle_dependency (&inst_main);
4104
4105 /* Start a new frag if frag_now is not empty. */
4106 if (frag_now_fix () != 0)
4107 {
4108 if (!frag_now->tc_frag_data.is_insn)
4109 {
4110 frag_wane (frag_now);
4111 }
4112 frag_new (0);
4113 }
4114 frag_grow (20);
4115
4116 /* Write fr_fix part. */
4117 p = frag_more (inst_main.size);
4118 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4119
4120 if (inst_main.reloc.type != BFD_RELOC_NONE)
4121 fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4122 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4123
4124 frag_now->tc_frag_data.fixp = fixp;
4125 cur_fixp = frag_now->tc_frag_data.fixp;
4126
4127 #ifdef OBJ_ELF
4128 dwarf2_emit_insn (inst_main.size);
4129 #endif
4130
4131 where = p - frag_now->fr_literal + inst_main.size;
4132 for (i = 0; i < var_num; i++)
4133 {
4134 if (i > 0)
4135 where += var_insts[i - 1].size;
4136
4137 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4138 {
4139 fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4140 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4141 var_insts[i].reloc.type);
4142 if (fixp)
4143 {
4144 if (cur_fixp)
4145 {
4146 cur_fixp->fx_next = fixp;
4147 cur_fixp = cur_fixp->fx_next;
4148 }
4149 else
4150 {
4151 frag_now->tc_frag_data.fixp = fixp;
4152 cur_fixp = frag_now->tc_frag_data.fixp;
4153 }
4154 }
4155 }
4156 }
4157
4158 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4159 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4160 0, inst_main.size, 0), add_symbol, 0, NULL);
4161
4162 /* Write fr_var part.
4163 no calling s7_gen_insn_frag, no fixS will be generated. */
4164 for (i = 0; i < var_num; i++)
4165 {
4166 s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4167 p += var_insts[i].size;
4168 }
4169 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4170 s7_inst.bwarn = -1;
4171 }
4172
4173 /* Build a relax frag for la instruction when generating s7_PIC,
4174 external symbol first and local symbol second. */
4175
4176 static void
4177 s7_build_la_pic (int reg_rd, expressionS exp)
4178 {
4179 symbolS *add_symbol = exp.X_add_symbol;
4180 offsetT add_number = exp.X_add_number;
4181 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4182 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4183 int fix_num = 0;
4184 int var_num = 0;
4185 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4186 int r1_bak;
4187
4188 r1_bak = s7_nor1;
4189 s7_nor1 = 0;
4190
4191 if (add_number == 0)
4192 {
4193 fix_num = 1;
4194 var_num = 2;
4195
4196 /* For an external symbol, only one insn is generated;
4197 For a local symbol, two insns are generated. */
4198 /* Fix part
4199 For an external symbol: lw rD, <sym>($gp)
4200 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
4201 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4202 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4203 return;
4204
4205 if (reg_rd == s7_PIC_CALL_REG)
4206 s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4207 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4208
4209 /* Var part
4210 For a local symbol :
4211 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4212 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4213 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4214 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4215 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4216 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4217 return;
4218
4219 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4220 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4221 }
4222 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4223 {
4224 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4225 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4226 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4227 return;
4228
4229 /* Insn 2 */
4230 fix_num = 1;
4231 var_num = 1;
4232 /* Fix part
4233 For an external symbol: addi rD, <constant> */
4234 sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4235 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4236 return;
4237
4238 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4239
4240 /* Var part
4241 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
4242 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd,
4243 S_GET_NAME (add_symbol), (int) add_number);
4244 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4245 return;
4246
4247 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4248 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4249 }
4250 else
4251 {
4252 int hi = (add_number >> 16) & 0x0000FFFF;
4253 int lo = add_number & 0x0000FFFF;
4254
4255 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4256 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4257 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4258 return;
4259
4260 /* Insn 2 */
4261 fix_num = 1;
4262 var_num = 1;
4263 /* Fix part
4264 For an external symbol: ldis r1, HI%<constant> */
4265 sprintf (tmp, "ldis r1, %d", hi);
4266 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4267 return;
4268
4269 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4270
4271 /* Var part
4272 For a local symbol: ldis r1, HI%<constant>
4273 but, if lo is out of 16 bit, make hi plus 1 */
4274 if ((lo < -0x8000) || (lo > 0x7fff))
4275 {
4276 hi += 1;
4277 }
4278 sprintf (tmp, "ldis_pic r1, %d", hi);
4279 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4280 return;
4281
4282 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4283 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4284
4285 /* Insn 3 */
4286 fix_num = 1;
4287 var_num = 1;
4288 /* Fix part
4289 For an external symbol: ori r1, LO%<constant> */
4290 sprintf (tmp, "ori r1, %d", lo);
4291 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4292 return;
4293
4294 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4295
4296 /* Var part
4297 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4298 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo);
4299 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4300 return;
4301
4302 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4303 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4304
4305 /* Insn 4: add rD, rD, r1 */
4306 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4307 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4308 return;
4309
4310 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4311 s7_inst.bwarn = -1;
4312 }
4313
4314 s7_nor1 = r1_bak;
4315 }
4316
4317 /* Handle la. */
4318
4319 static void
4320 s7_do_macro_la_rdi32 (char *str)
4321 {
4322 int reg_rd;
4323
4324 s7_skip_whitespace (str);
4325 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4326 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4327 {
4328 return;
4329 }
4330 else
4331 {
4332 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4333 char *keep_data = str;
4334
4335 /* Check immediate value. */
4336 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4337 {
4338 s7_inst.error = _("expression error");
4339 return;
4340 }
4341 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4342 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4343 {
4344 s7_inst.error = _("value not in range [0, 0xffffffff]");
4345 return;
4346 }
4347
4348 /* Reset str. */
4349 str = keep_data;
4350
4351 /* la rd, simm16. */
4352 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4353 {
4354 s7_end_of_line (str);
4355 return;
4356 }
4357 /* la rd, imm32 or la rd, label. */
4358 else
4359 {
4360 s7_SET_INSN_ERROR (NULL);
4361 str = keep_data;
4362 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4363 || (s7_end_of_line (str) == (int) s7_FAIL))
4364 {
4365 return;
4366 }
4367 else
4368 {
4369 if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4370 {
4371 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4372 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4373 return;
4374
4375 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4376 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4377 return;
4378 }
4379 else
4380 {
4381 gas_assert (s7_inst.reloc.exp.X_add_symbol);
4382 s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4383 }
4384
4385 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4386 s7_inst.bwarn = -1;
4387 }
4388 }
4389 }
4390 }
4391
4392 /* Handle li. */
4393
4394 static void
4395 s7_do_macro_li_rdi32 (char *str)
4396 {
4397 int reg_rd;
4398
4399 s7_skip_whitespace (str);
4400 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4401 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4402 {
4403 return;
4404 }
4405 else
4406 {
4407 char *keep_data = str;
4408
4409 /* Check immediate value. */
4410 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4411 {
4412 s7_inst.error = _("expression error");
4413 return;
4414 }
4415 else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4416 && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4417 {
4418 s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4419 return;
4420 }
4421
4422 /* Reset str. */
4423 str = keep_data;
4424
4425 /* li rd, simm16. */
4426 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4427 {
4428 s7_end_of_line (str);
4429 return;
4430 }
4431 /* li rd, imm32. */
4432 else
4433 {
4434 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4435
4436 str = keep_data;
4437
4438 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4439 || (s7_end_of_line (str) == (int) s7_FAIL))
4440 {
4441 return;
4442 }
4443 else if (s7_inst.reloc.exp.X_add_symbol)
4444 {
4445 s7_inst.error = _("li rd label isn't correct instruction form");
4446 return;
4447 }
4448 else
4449 {
4450 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4451
4452 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4453 return;
4454 else
4455 {
4456 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4457 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4458 return;
4459
4460 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4461 s7_inst.bwarn = -1;
4462 }
4463 }
4464 }
4465 }
4466 }
4467
4468 /* Handle mul/mulu/div/divu/rem/remu. */
4469
4470 static void
4471 s7_do_macro_mul_rdrsrs (char *str)
4472 {
4473 int reg_rd;
4474 int reg_rs1;
4475 int reg_rs2;
4476 char *backupstr;
4477 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4478
4479 if (s7_university_version == 1)
4480 as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4481
4482 strcpy (append_str, str);
4483 backupstr = append_str;
4484 s7_skip_whitespace (backupstr);
4485 if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4486 || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4487 || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4488 {
4489 s7_inst.error = s7_BAD_ARGS;
4490 return;
4491 }
4492
4493 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4494 {
4495 /* rem/remu rA, rB is error format. */
4496 if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4497 {
4498 s7_SET_INSN_ERROR (s7_BAD_ARGS);
4499 }
4500 else
4501 {
4502 s7_SET_INSN_ERROR (NULL);
4503 s7_do_rsrs (str);
4504 }
4505 return;
4506 }
4507 else
4508 {
4509 s7_SET_INSN_ERROR (NULL);
4510 if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4511 || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4512 {
4513 return;
4514 }
4515 else
4516 {
4517 char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4518
4519 if (strcmp (s7_inst.name, "rem") == 0)
4520 {
4521 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4522 sprintf (append_str1, "mfceh r%d", reg_rd);
4523 }
4524 else if (strcmp (s7_inst.name, "remu") == 0)
4525 {
4526 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4527 sprintf (append_str1, "mfceh r%d", reg_rd);
4528 }
4529 else
4530 {
4531 sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4532 sprintf (append_str1, "mfcel r%d", reg_rd);
4533 }
4534
4535 /* Output mul/mulu or div/divu or rem/remu. */
4536 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4537 return;
4538
4539 /* Output mfcel or mfceh. */
4540 if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4541 return;
4542
4543 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4544 s7_inst.bwarn = -1;
4545 }
4546 }
4547 }
4548
4549 static void
4550 s7_exp_macro_ldst_abs (char *str)
4551 {
4552 int reg_rd;
4553 char *backupstr, *tmp;
4554 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4555 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4556 struct s7_score_it inst_backup;
4557 int r1_bak = 0;
4558
4559 r1_bak = s7_nor1;
4560 s7_nor1 = 0;
4561 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4562
4563 strcpy (verifystr, str);
4564 backupstr = verifystr;
4565 s7_skip_whitespace (backupstr);
4566 if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4567 return;
4568
4569 tmp = backupstr;
4570 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4571 return;
4572
4573 backupstr = tmp;
4574 sprintf (append_str, "li r1 %s", backupstr);
4575 s7_append_insn (append_str, TRUE);
4576
4577 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4578 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4579 s7_do_ldst_insn (append_str);
4580
4581 s7_nor1 = r1_bak;
4582 }
4583
4584 static int
4585 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4586 {
4587 if (sym == NULL)
4588 return 0;
4589 else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4590 {
4591 const char *symname;
4592 const char *segname;
4593
4594 /* Find out whether this symbol can be referenced off the $gp
4595 register. It can be if it is smaller than the -G size or if
4596 it is in the .sdata or .sbss section. Certain symbols can
4597 not be referenced off the $gp, although it appears as though
4598 they can. */
4599 symname = S_GET_NAME (sym);
4600 if (symname != NULL
4601 && (strcmp (symname, "eprol") == 0
4602 || strcmp (symname, "etext") == 0
4603 || strcmp (symname, "_gp") == 0
4604 || strcmp (symname, "edata") == 0
4605 || strcmp (symname, "_fbss") == 0
4606 || strcmp (symname, "_fdata") == 0
4607 || strcmp (symname, "_ftext") == 0
4608 || strcmp (symname, "end") == 0
4609 || strcmp (symname, GP_DISP_LABEL) == 0))
4610 {
4611 return 1;
4612 }
4613 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4614 /* We must defer this decision until after the whole file has been read,
4615 since there might be a .extern after the first use of this symbol. */
4616 || (before_relaxing
4617 && S_GET_VALUE (sym) == 0)
4618 || (S_GET_VALUE (sym) != 0
4619 && S_GET_VALUE (sym) <= s7_g_switch_value)))
4620 {
4621 return 0;
4622 }
4623
4624 segname = segment_name (S_GET_SEGMENT (sym));
4625 return (strcmp (segname, ".sdata") != 0
4626 && strcmp (segname, ".sbss") != 0
4627 && strncmp (segname, ".sdata.", 7) != 0
4628 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4629 }
4630 /* We are not optimizing for the $gp register. */
4631 else
4632 return 1;
4633 }
4634
4635 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4636 external symbol first and local symbol second. */
4637
4638 static void
4639 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4640 {
4641 symbolS *add_symbol = exp.X_add_symbol;
4642 int add_number = exp.X_add_number;
4643 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4644 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4645 int fix_num = 0;
4646 int var_num = 0;
4647 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4648 int r1_bak;
4649
4650 r1_bak = s7_nor1;
4651 s7_nor1 = 0;
4652
4653 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4654 {
4655 fix_num = 1;
4656 var_num = 2;
4657
4658 /* For an external symbol, two insns are generated;
4659 For a local symbol, three insns are generated. */
4660 /* Fix part
4661 For an external symbol: lw rD, <sym>($gp)
4662 (BFD_RELOC_SCORE_GOT15) */
4663 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol));
4664 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4665 return;
4666
4667 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4668
4669 /* Var part
4670 For a local symbol :
4671 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4672 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4673 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4674 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4675 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol));
4676 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4677 return;
4678
4679 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4680 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4681
4682 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4683 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4684 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4685 return;
4686
4687 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4688 s7_inst.bwarn = -1;
4689 }
4690 else
4691 {
4692 s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4693 return;
4694 }
4695
4696 s7_nor1 = r1_bak;
4697 }
4698
4699 static void
4700 s7_do_macro_ldst_label (char *str)
4701 {
4702 int i;
4703 int ldst_gp_p = 0;
4704 int reg_rd;
4705 int r1_bak;
4706 char *backup_str;
4707 char *label_str;
4708 char *absolute_value;
4709 char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4710 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4711 struct s7_score_it inst_backup;
4712 struct s7_score_it inst_expand[3];
4713 struct s7_score_it inst_main;
4714
4715 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4716 strcpy (verifystr, str);
4717 backup_str = verifystr;
4718
4719 s7_skip_whitespace (backup_str);
4720 if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4721 return;
4722
4723 if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4724 return;
4725
4726 label_str = backup_str;
4727
4728 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4729 if (*backup_str == '[')
4730 {
4731 s7_inst.type = Rd_rvalueRs_preSI12;
4732 s7_do_ldst_insn (str);
4733 return;
4734 }
4735
4736 /* Ld/st rD, imm. */
4737 absolute_value = backup_str;
4738 s7_inst.type = Rd_rvalueRs_SI15;
4739
4740 if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4741 {
4742 s7_inst.error = _("expression error");
4743 return;
4744 }
4745 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4746 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4747 {
4748 s7_inst.error = _("value not in range [0, 0x7fffffff]");
4749 return;
4750 }
4751 else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4752 {
4753 s7_inst.error = _("end on line error");
4754 return;
4755 }
4756 else
4757 {
4758 if (s7_inst.reloc.exp.X_add_symbol == 0)
4759 {
4760 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4761 s7_exp_macro_ldst_abs (str);
4762 return;
4763 }
4764 }
4765
4766 /* Ld/st rD, label. */
4767 s7_inst.type = Rd_rvalueRs_SI15;
4768 backup_str = absolute_value;
4769 if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4770 || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4771 {
4772 return;
4773 }
4774 else
4775 {
4776 if (s7_inst.reloc.exp.X_add_symbol == 0)
4777 {
4778 if (!s7_inst.error)
4779 s7_inst.error = s7_BAD_ARGS;
4780
4781 return;
4782 }
4783
4784 if (s7_score_pic == s7_PIC)
4785 {
4786 int ldst_idx = 0;
4787 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4788 s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4789 s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4790 return;
4791 }
4792 else
4793 {
4794 if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4795 && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4796 && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4797 {
4798 int ldst_idx = 0;
4799
4800 /* Assign the real opcode. */
4801 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4802 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4803 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4804 s7_inst.instruction |= reg_rd << 20;
4805 s7_inst.instruction |= s7_GP << 15;
4806 s7_inst.relax_inst = 0x8000;
4807 s7_inst.relax_size = 0;
4808 ldst_gp_p = 1;
4809 }
4810 }
4811 }
4812
4813 /* Backup s7_inst. */
4814 memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4815 r1_bak = s7_nor1;
4816 s7_nor1 = 0;
4817
4818 /* Determine which instructions should be output. */
4819 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4820 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4821 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4822
4823 /* Generate three instructions.
4824 la r1, label
4825 ld/st rd, [r1, 0] */
4826 for (i = 0; i < 3; i++)
4827 {
4828 if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4829 return;
4830
4831 memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4832 }
4833
4834 if (ldst_gp_p)
4835 {
4836 char *p;
4837
4838 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4839 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4840 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4841 inst_main.type = Insn_GP;
4842
4843 for (i = 0; i < 3; i++)
4844 inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4845 , s7_GET_INSN_CLASS (inst_expand[i].type));
4846
4847 /* Check data dependency. */
4848 s7_handle_dependency (&inst_main);
4849
4850 /* Start a new frag if frag_now is not empty. */
4851 if (frag_now_fix () != 0)
4852 {
4853 if (!frag_now->tc_frag_data.is_insn)
4854 frag_wane (frag_now);
4855
4856 frag_new (0);
4857 }
4858 frag_grow (20);
4859
4860 /* Write fr_fix part. */
4861 p = frag_more (inst_main.size);
4862 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4863
4864 if (inst_main.reloc.type != BFD_RELOC_NONE)
4865 {
4866 s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4867 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4868 }
4869
4870 #ifdef OBJ_ELF
4871 dwarf2_emit_insn (inst_main.size);
4872 #endif
4873
4874 /* s7_GP instruction can not do optimization, only can do relax between
4875 1 instruction and 3 instructions. */
4876 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4877 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4878 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4879
4880 /* Write fr_var part.
4881 no calling s7_gen_insn_frag, no fixS will be generated. */
4882 s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4883 p += inst_expand[0].size;
4884 s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4885 p += inst_expand[1].size;
4886 s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4887 }
4888 else
4889 {
4890 s7_gen_insn_frag (&inst_expand[0], NULL);
4891 s7_gen_insn_frag (&inst_expand[1], NULL);
4892 s7_gen_insn_frag (&inst_expand[2], NULL);
4893 }
4894 s7_nor1 = r1_bak;
4895
4896 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4897 s7_inst.bwarn = -1;
4898 }
4899
4900 static void
4901 s7_do_lw_pic (char *str)
4902 {
4903 int reg_rd;
4904
4905 s7_skip_whitespace (str);
4906 if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4907 || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4908 || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4909 || (s7_end_of_line (str) == (int) s7_FAIL))
4910 {
4911 return;
4912 }
4913 else
4914 {
4915 if (s7_inst.reloc.exp.X_add_symbol == 0)
4916 {
4917 if (!s7_inst.error)
4918 s7_inst.error = s7_BAD_ARGS;
4919
4920 return;
4921 }
4922
4923 s7_inst.instruction |= s7_GP << 15;
4924 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4925 }
4926 }
4927
4928 static void
4929 s7_do_empty (char *str)
4930 {
4931 str = str;
4932 if (s7_university_version == 1)
4933 {
4934 if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4935 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4936 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4937 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4938 {
4939 s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4940 return;
4941 }
4942 }
4943 if (s7_end_of_line (str) == (int) s7_FAIL)
4944 return;
4945
4946 if (s7_inst.relax_inst != 0x8000)
4947 {
4948 if (s7_inst.type == NO_OPD)
4949 {
4950 s7_inst.relax_size = 2;
4951 }
4952 else
4953 {
4954 s7_inst.relax_size = 4;
4955 }
4956 }
4957 }
4958
4959 static void
4960 s7_do_jump (char *str)
4961 {
4962 char *save_in;
4963
4964 s7_skip_whitespace (str);
4965 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4966 || s7_end_of_line (str) == (int) s7_FAIL)
4967 return;
4968
4969 if (s7_inst.reloc.exp.X_add_symbol == 0)
4970 {
4971 s7_inst.error = _("lacking label ");
4972 return;
4973 }
4974
4975 if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4976 && s7_inst.reloc.exp.X_add_number <= 16777215))
4977 {
4978 s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4979 return;
4980 }
4981
4982 save_in = input_line_pointer;
4983 input_line_pointer = str;
4984 s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4985 s7_inst.reloc.pc_rel = 1;
4986 input_line_pointer = save_in;
4987 }
4988
4989 static void
4990 s7_do16_jump (char *str)
4991 {
4992 s7_skip_whitespace (str);
4993 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4994 || s7_end_of_line (str) == (int) s7_FAIL)
4995 {
4996 return;
4997 }
4998 else if (s7_inst.reloc.exp.X_add_symbol == 0)
4999 {
5000 s7_inst.error = _("lacking label ");
5001 return;
5002 }
5003 else if (!(s7_inst.reloc.exp.X_add_number >= 0
5004 && s7_inst.reloc.exp.X_add_number <= 4095))
5005 {
5006 s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5007 return;
5008 }
5009
5010 s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5011 s7_inst.reloc.pc_rel = 1;
5012 }
5013
5014 static void
5015 s7_do_branch (char *str)
5016 {
5017 unsigned long abs_value = 0;
5018
5019 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5020 || s7_end_of_line (str) == (int) s7_FAIL)
5021 {
5022 return;
5023 }
5024 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5025 {
5026 s7_inst.error = _("lacking label ");
5027 return;
5028 }
5029 else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5030 && s7_inst.reloc.exp.X_add_number <= 524287))
5031 {
5032 s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5033 return;
5034 }
5035
5036 s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5037 s7_inst.reloc.pc_rel = 1;
5038
5039 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
5040 s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5041
5042 /* Compute 16 bit branch instruction. */
5043 if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5044 {
5045 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5046 s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5047 s7_inst.relax_size = 2;
5048 }
5049 else
5050 {
5051 s7_inst.relax_inst = 0x8000;
5052 }
5053 }
5054
5055 static void
5056 s7_do16_branch (char *str)
5057 {
5058 if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5059 || s7_end_of_line (str) == (int) s7_FAIL))
5060 {
5061 ;
5062 }
5063 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5064 {
5065 s7_inst.error = _("lacking label");
5066 }
5067 else if (!(s7_inst.reloc.exp.X_add_number >= -512
5068 && s7_inst.reloc.exp.X_add_number <= 511))
5069 {
5070 s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5071 }
5072 else
5073 {
5074 s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5075 s7_inst.reloc.pc_rel = 1;
5076 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5077 }
5078 }
5079
5080 /* Iterate over the base tables to create the instruction patterns. */
5081
5082 static void
5083 s7_build_score_ops_hsh (void)
5084 {
5085 unsigned int i;
5086 static struct obstack insn_obstack;
5087
5088 obstack_begin (&insn_obstack, 4000);
5089 for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5090 {
5091 const struct s7_asm_opcode *insn = s7_score_insns + i;
5092 size_t len = strlen (insn->template_name);
5093 struct s7_asm_opcode *new_opcode;
5094 char *template_name;
5095 new_opcode = (struct s7_asm_opcode *)
5096 obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5097 template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5098
5099 strcpy (template_name, insn->template_name);
5100 new_opcode->template_name = template_name;
5101 new_opcode->parms = insn->parms;
5102 new_opcode->value = insn->value;
5103 new_opcode->relax_value = insn->relax_value;
5104 new_opcode->type = insn->type;
5105 new_opcode->bitmask = insn->bitmask;
5106 hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5107 (void *) new_opcode);
5108 }
5109 }
5110
5111 static void
5112 s7_build_dependency_insn_hsh (void)
5113 {
5114 unsigned int i;
5115 static struct obstack dependency_obstack;
5116
5117 obstack_begin (&dependency_obstack, 4000);
5118 for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5119 {
5120 const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5121 size_t len = strlen (tmp->insn_name);
5122 struct s7_insn_to_dependency *new_i2d;
5123 char *insn_name;
5124
5125 new_i2d = (struct s7_insn_to_dependency *)
5126 obstack_alloc (&dependency_obstack,
5127 sizeof (struct s7_insn_to_dependency));
5128 insn_name = (char *) obstack_alloc (&dependency_obstack, len + 1);
5129
5130 strcpy (insn_name, tmp->insn_name);
5131 new_i2d->insn_name = insn_name;
5132 new_i2d->type = tmp->type;
5133 hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5134 (void *) new_i2d);
5135 }
5136 }
5137
5138 static valueT
5139 s7_md_chars_to_number (char *buf, int n)
5140 {
5141 valueT result = 0;
5142 unsigned char *where = (unsigned char *) buf;
5143
5144 if (target_big_endian)
5145 {
5146 while (n--)
5147 {
5148 result <<= 8;
5149 result |= (*where++ & 255);
5150 }
5151 }
5152 else
5153 {
5154 while (n--)
5155 {
5156 result <<= 8;
5157 result |= (where[n] & 255);
5158 }
5159 }
5160
5161 return result;
5162 }
5163
5164 /* Return true if the given symbol should be considered local for s7_PIC. */
5165
5166 static bfd_boolean
5167 s7_pic_need_relax (symbolS *sym, asection *segtype)
5168 {
5169 asection *symsec;
5170 bfd_boolean linkonce;
5171
5172 /* Handle the case of a symbol equated to another symbol. */
5173 while (symbol_equated_reloc_p (sym))
5174 {
5175 symbolS *n;
5176
5177 /* It's possible to get a loop here in a badly written
5178 program. */
5179 n = symbol_get_value_expression (sym)->X_add_symbol;
5180 if (n == sym)
5181 break;
5182 sym = n;
5183 }
5184
5185 symsec = S_GET_SEGMENT (sym);
5186
5187 /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5188 linkonce = FALSE;
5189 if (symsec != segtype && ! S_IS_LOCAL (sym))
5190 {
5191 if ((bfd_section_flags (symsec) & SEC_LINK_ONCE) != 0)
5192 linkonce = TRUE;
5193
5194 /* The GNU toolchain uses an extension for ELF: a section
5195 beginning with the magic string .gnu.linkonce is a linkonce
5196 section. */
5197 if (strncmp (segment_name (symsec), ".gnu.linkonce",
5198 sizeof ".gnu.linkonce" - 1) == 0)
5199 linkonce = TRUE;
5200 }
5201
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)
5206 && !linkonce
5207 #ifdef OBJ_ELF
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)))
5211 #endif
5212 );
5213 }
5214
5215 static int
5216 s7_judge_size_before_relax (fragS * fragp, asection *sec)
5217 {
5218 int change = 0;
5219
5220 if (s7_score_pic == s7_NO_PIC)
5221 change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5222 else
5223 change = s7_pic_need_relax (fragp->fr_symbol, sec);
5224
5225 if (change == 1)
5226 {
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)
5230 {
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);
5234 }
5235 }
5236
5237 return 0;
5238 }
5239
5240 static int
5241 s7_b32_relax_to_b16 (fragS * fragp)
5242 {
5243 int grows = 0;
5244 int relaxable_p = 0;
5245 int frag_addr = fragp->fr_address + fragp->insn_addr;
5246
5247 addressT symbol_address = 0;
5248 symbolS *s;
5249 offsetT offset;
5250 unsigned long value;
5251 unsigned long abs_value;
5252
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. */
5257
5258 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5259
5260 s = fragp->fr_symbol;
5261 /* b/bl immediate */
5262 if (s == NULL)
5263 frag_addr = 0;
5264 else
5265 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
5266
5267 value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5268
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;
5273
5274 abs_value = offset + symbol_address - frag_addr;
5275 if ((abs_value & 0x80000000) == 0x80000000)
5276 abs_value = 0xffffffff - abs_value + 1;
5277
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)))
5281 {
5282 /* do nothing. */
5283 }
5284 else
5285 {
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);
5289 }
5290
5291 return grows;
5292 }
5293
5294 static void
5295 s7_parse_pce_inst (char *insnstr)
5296 {
5297 char c;
5298 char *p;
5299 char *q;
5300 char first[s7_MAX_LITERAL_POOL_SIZE];
5301 char second[s7_MAX_LITERAL_POOL_SIZE];
5302 struct s7_score_it pec_part_1;
5303
5304 /* Get first part string of PCE. */
5305 p = strstr (insnstr, "||");
5306 c = *p;
5307 *p = '\0';
5308 strcpy (first, insnstr);
5309
5310 /* Get second part string of PCE. */
5311 *p = c;
5312 p += 2;
5313 strcpy (second, p);
5314
5315 s7_parse_16_32_inst (first, FALSE);
5316 if (s7_inst.error)
5317 return;
5318
5319 memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5320
5321 q = second;
5322 while (q && *q)
5323 {
5324 *q = TOLOWER (*q);
5325 q++;
5326 }
5327
5328 s7_parse_16_32_inst (second, FALSE);
5329 if (s7_inst.error)
5330 return;
5331
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)))
5335 {
5336 s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5337 strcpy (s7_inst.str, insnstr);
5338 return;
5339 }
5340
5341 if (!s7_inst.error)
5342 s7_gen_insn_frag (&pec_part_1, &s7_inst);
5343 }
5344
5345 \f
5346
5347 static void
5348 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5349 {
5350 int i = 0;
5351 int len = strlen (r->name) + 2;
5352 char *buf = XNEWVEC (char, len);
5353 char *buf2 = XNEWVEC (char, len);
5354
5355 strcpy (buf + i, r->name);
5356 for (i = 0; buf[i]; i++)
5357 {
5358 buf2[i] = TOUPPER (buf[i]);
5359 }
5360 buf2[i] = '\0';
5361
5362 hash_insert (htab, buf, (void *) r);
5363 hash_insert (htab, buf2, (void *) r);
5364 }
5365
5366 static void
5367 s7_build_reg_hsh (struct s7_reg_map *map)
5368 {
5369 const struct s7_reg_entry *r;
5370
5371 if ((map->htab = hash_new ()) == NULL)
5372 {
5373 as_fatal (_("virtual memory exhausted"));
5374 }
5375 for (r = map->names; r->name != NULL; r++)
5376 {
5377 s7_insert_reg (r, map->htab);
5378 }
5379 }
5380
5381 \f
5382
5383 /* If we change section we must dump the literal pool first. */
5384 static void
5385 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5386 {
5387 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5388 demand_empty_rest_of_line ();
5389 }
5390
5391 static void
5392 s7_s_score_text (int ignore)
5393 {
5394 obj_elf_text (ignore);
5395 record_alignment (now_seg, 2);
5396 }
5397
5398 static void
5399 s7_s_section (int ignore)
5400 {
5401 obj_elf_section (ignore);
5402 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5403 record_alignment (now_seg, 2);
5404
5405 }
5406
5407 static void
5408 s7_s_change_sec (int sec)
5409 {
5410 segT seg;
5411
5412 #ifdef OBJ_ELF
5413 /* The ELF backend needs to know that we are changing sections, so
5414 that .previous works correctly. We could do something like check
5415 for an obj_section_change_hook macro, but that might be confusing
5416 as it would not be appropriate to use it in the section changing
5417 functions in read.c, since obj-elf.c intercepts those. FIXME:
5418 This should be cleaner, somehow. */
5419 obj_elf_section_change_hook ();
5420 #endif
5421 switch (sec)
5422 {
5423 case 'r':
5424 seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5425 bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5426 if (strcmp (TARGET_OS, "elf") != 0)
5427 record_alignment (seg, 4);
5428 demand_empty_rest_of_line ();
5429 break;
5430 case 's':
5431 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5432 bfd_set_section_flags (seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5433 if (strcmp (TARGET_OS, "elf") != 0)
5434 record_alignment (seg, 4);
5435 demand_empty_rest_of_line ();
5436 break;
5437 }
5438 }
5439
5440 static void
5441 s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5442 {
5443 long mask, off;
5444
5445 if (s7_cur_proc_ptr == NULL)
5446 {
5447 as_warn (_(".mask outside of .ent"));
5448 demand_empty_rest_of_line ();
5449 return;
5450 }
5451 if (get_absolute_expression_and_terminator (&mask) != ',')
5452 {
5453 as_warn (_("Bad .mask directive"));
5454 --input_line_pointer;
5455 demand_empty_rest_of_line ();
5456 return;
5457 }
5458 off = get_absolute_expression ();
5459 s7_cur_proc_ptr->reg_mask = mask;
5460 s7_cur_proc_ptr->reg_offset = off;
5461 demand_empty_rest_of_line ();
5462 }
5463
5464 static symbolS *
5465 s7_get_symbol (void)
5466 {
5467 int c;
5468 char *name;
5469 symbolS *p;
5470
5471 c = get_symbol_name (&name);
5472 p = (symbolS *) symbol_find_or_make (name);
5473 (void) restore_line_pointer (c);
5474 return p;
5475 }
5476
5477 static long
5478 s7_get_number (void)
5479 {
5480 int negative = 0;
5481 long val = 0;
5482
5483 if (*input_line_pointer == '-')
5484 {
5485 ++input_line_pointer;
5486 negative = 1;
5487 }
5488 if (!ISDIGIT (*input_line_pointer))
5489 as_bad (_("expected simple number"));
5490 if (input_line_pointer[0] == '0')
5491 {
5492 if (input_line_pointer[1] == 'x')
5493 {
5494 input_line_pointer += 2;
5495 while (ISXDIGIT (*input_line_pointer))
5496 {
5497 val <<= 4;
5498 val |= hex_value (*input_line_pointer++);
5499 }
5500 return negative ? -val : val;
5501 }
5502 else
5503 {
5504 ++input_line_pointer;
5505 while (ISDIGIT (*input_line_pointer))
5506 {
5507 val <<= 3;
5508 val |= *input_line_pointer++ - '0';
5509 }
5510 return negative ? -val : val;
5511 }
5512 }
5513 if (!ISDIGIT (*input_line_pointer))
5514 {
5515 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5516 as_warn (_("invalid number"));
5517 return -1;
5518 }
5519 while (ISDIGIT (*input_line_pointer))
5520 {
5521 val *= 10;
5522 val += *input_line_pointer++ - '0';
5523 }
5524 return negative ? -val : val;
5525 }
5526
5527 /* The .aent and .ent directives. */
5528
5529 static void
5530 s7_s_score_ent (int aent)
5531 {
5532 symbolS *symbolP;
5533 int maybe_text;
5534
5535 symbolP = s7_get_symbol ();
5536 if (*input_line_pointer == ',')
5537 ++input_line_pointer;
5538 SKIP_WHITESPACE ();
5539 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5540 s7_get_number ();
5541
5542 #ifdef BFD_ASSEMBLER
5543 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5544 maybe_text = 1;
5545 else
5546 maybe_text = 0;
5547 #else
5548 if (now_seg != data_section && now_seg != bss_section)
5549 maybe_text = 1;
5550 else
5551 maybe_text = 0;
5552 #endif
5553 if (!maybe_text)
5554 as_warn (_(".ent or .aent not in text section."));
5555 if (!aent && s7_cur_proc_ptr)
5556 as_warn (_("missing .end"));
5557 if (!aent)
5558 {
5559 s7_cur_proc_ptr = &s7_cur_proc;
5560 s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5561 s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5562 s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5563 s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5564 s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5565 s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5566 s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5567 s7_cur_proc_ptr->isym = symbolP;
5568 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5569 ++s7_numprocs;
5570 if (debug_type == DEBUG_STABS)
5571 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5572 }
5573 demand_empty_rest_of_line ();
5574 }
5575
5576 static void
5577 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5578 {
5579 char *backupstr;
5580 char str[30];
5581 long val;
5582 int i = 0;
5583
5584 backupstr = input_line_pointer;
5585
5586 #ifdef OBJ_ELF
5587 if (s7_cur_proc_ptr == NULL)
5588 {
5589 as_warn (_(".frame outside of .ent"));
5590 demand_empty_rest_of_line ();
5591 return;
5592 }
5593 s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5594 SKIP_WHITESPACE ();
5595 s7_skip_past_comma (&backupstr);
5596 while (*backupstr != ',')
5597 {
5598 str[i] = *backupstr;
5599 i++;
5600 backupstr++;
5601 }
5602 str[i] = '\0';
5603 val = atoi (str);
5604
5605 SKIP_WHITESPACE ();
5606 s7_skip_past_comma (&backupstr);
5607 s7_cur_proc_ptr->frame_offset = val;
5608 s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5609
5610 SKIP_WHITESPACE ();
5611 s7_skip_past_comma (&backupstr);
5612 i = 0;
5613 while (*backupstr != '\n')
5614 {
5615 str[i] = *backupstr;
5616 i++;
5617 backupstr++;
5618 }
5619 str[i] = '\0';
5620 val = atoi (str);
5621 s7_cur_proc_ptr->leaf = val;
5622 SKIP_WHITESPACE ();
5623 s7_skip_past_comma (&backupstr);
5624
5625 #endif /* OBJ_ELF */
5626 while (input_line_pointer != backupstr)
5627 input_line_pointer++;
5628 }
5629
5630 /* The .end directive. */
5631
5632 static void
5633 s7_s_score_end (int x ATTRIBUTE_UNUSED)
5634 {
5635 symbolS *p;
5636 int maybe_text;
5637
5638 /* Generate a .pdr section. */
5639 segT saved_seg = now_seg;
5640 subsegT saved_subseg = now_subseg;
5641 expressionS exp;
5642 char *fragp;
5643
5644 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5645 {
5646 p = s7_get_symbol ();
5647 demand_empty_rest_of_line ();
5648 }
5649 else
5650 p = NULL;
5651
5652 #ifdef BFD_ASSEMBLER
5653 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5654 maybe_text = 1;
5655 else
5656 maybe_text = 0;
5657 #else
5658 if (now_seg != data_section && now_seg != bss_section)
5659 maybe_text = 1;
5660 else
5661 maybe_text = 0;
5662 #endif
5663
5664 if (!maybe_text)
5665 as_warn (_(".end not in text section"));
5666 if (!s7_cur_proc_ptr)
5667 {
5668 as_warn (_(".end directive without a preceding .ent directive."));
5669 demand_empty_rest_of_line ();
5670 return;
5671 }
5672 if (p != NULL)
5673 {
5674 gas_assert (S_GET_NAME (p));
5675 if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5676 as_warn (_(".end symbol does not match .ent symbol."));
5677 if (debug_type == DEBUG_STABS)
5678 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5679 }
5680 else
5681 as_warn (_(".end directive missing or unknown symbol"));
5682
5683 if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5684 (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5685 (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5686 (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5687 (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5688
5689 else
5690 {
5691 (void) frag_now_fix ();
5692 gas_assert (s7_pdr_seg);
5693 subseg_set (s7_pdr_seg, 0);
5694 /* Write the symbol. */
5695 exp.X_op = O_symbol;
5696 exp.X_add_symbol = p;
5697 exp.X_add_number = 0;
5698 emit_expr (&exp, 4);
5699 fragp = frag_more (7 * 4);
5700 s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5701 s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5702 s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5703 s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5704 s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5705 s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5706 s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5707 subseg_set (saved_seg, saved_subseg);
5708
5709 }
5710 s7_cur_proc_ptr = NULL;
5711 }
5712
5713 /* Handle the .set pseudo-op. */
5714
5715 static void
5716 s7_s_score_set (int x ATTRIBUTE_UNUSED)
5717 {
5718 int i = 0;
5719 char name[s7_MAX_LITERAL_POOL_SIZE];
5720 char * orig_ilp = input_line_pointer;
5721
5722 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5723 {
5724 name[i] = (char) * input_line_pointer;
5725 i++;
5726 ++input_line_pointer;
5727 }
5728
5729 name[i] = '\0';
5730
5731 if (strcmp (name, "nwarn") == 0)
5732 {
5733 s7_warn_fix_data_dependency = 0;
5734 }
5735 else if (strcmp (name, "fixdd") == 0)
5736 {
5737 s7_fix_data_dependency = 1;
5738 }
5739 else if (strcmp (name, "nofixdd") == 0)
5740 {
5741 s7_fix_data_dependency = 0;
5742 }
5743 else if (strcmp (name, "r1") == 0)
5744 {
5745 s7_nor1 = 0;
5746 }
5747 else if (strcmp (name, "nor1") == 0)
5748 {
5749 s7_nor1 = 1;
5750 }
5751 else if (strcmp (name, "optimize") == 0)
5752 {
5753 s7_g_opt = 1;
5754 }
5755 else if (strcmp (name, "volatile") == 0)
5756 {
5757 s7_g_opt = 0;
5758 }
5759 else if (strcmp (name, "pic") == 0)
5760 {
5761 s7_score_pic = s7_PIC;
5762 }
5763 else
5764 {
5765 input_line_pointer = orig_ilp;
5766 s_set (0);
5767 }
5768 }
5769
5770 /* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the
5771 $gp register for the function based on the function address, which is in the register
5772 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5773 specially by the linker. The result is:
5774 ldis gp, %hi(GP_DISP_LABEL)
5775 ori gp, %low(GP_DISP_LABEL)
5776 add gp, gp, .cpload argument
5777 The .cpload argument is normally r29. */
5778
5779 static void
5780 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5781 {
5782 int reg;
5783 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5784
5785 /* If we are not generating s7_PIC code, .cpload is ignored. */
5786 if (s7_score_pic == s7_NO_PIC)
5787 {
5788 s_ignore (0);
5789 return;
5790 }
5791
5792 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5793 return;
5794
5795 demand_empty_rest_of_line ();
5796
5797 sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5798 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5799 return;
5800
5801 sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5802 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5803 return;
5804
5805 sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5806 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5807 return;
5808 }
5809
5810 /* Handle the .cprestore pseudo-op. This stores $gp into a given
5811 offset from $sp. The offset is remembered, and after making a s7_PIC
5812 call $gp is restored from that location. */
5813
5814 static void
5815 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5816 {
5817 int reg;
5818 int cprestore_offset;
5819 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5820
5821 /* If we are not generating s7_PIC code, .cprestore is ignored. */
5822 if (s7_score_pic == s7_NO_PIC)
5823 {
5824 s_ignore (0);
5825 return;
5826 }
5827
5828 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5829 || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5830 {
5831 return;
5832 }
5833
5834 cprestore_offset = get_absolute_expression ();
5835
5836 if (cprestore_offset <= 0x3fff)
5837 {
5838 sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5839 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5840 return;
5841 }
5842 else
5843 {
5844 int r1_bak;
5845
5846 r1_bak = s7_nor1;
5847 s7_nor1 = 0;
5848
5849 sprintf (insn_str, "li r1, %d", cprestore_offset);
5850 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5851 return;
5852
5853 sprintf (insn_str, "add r1, r1, r%d", reg);
5854 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5855 return;
5856
5857 sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5858 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5859 return;
5860
5861 s7_nor1 = r1_bak;
5862 }
5863
5864 demand_empty_rest_of_line ();
5865 }
5866
5867 /* Handle the .gpword pseudo-op. This is used when generating s7_PIC
5868 code. It generates a 32 bit s7_GP relative reloc. */
5869
5870 static void
5871 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5872 {
5873 expressionS ex;
5874 char *p;
5875
5876 /* When not generating s7_PIC code, this is treated as .word. */
5877 if (s7_score_pic == s7_NO_PIC)
5878 {
5879 cons (4);
5880 return;
5881 }
5882 expression (&ex);
5883 if (ex.X_op != O_symbol || ex.X_add_number != 0)
5884 {
5885 as_bad (_("Unsupported use of .gpword"));
5886 ignore_rest_of_line ();
5887 }
5888 p = frag_more (4);
5889 s7_number_to_chars (p, (valueT) 0, 4);
5890 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5891 demand_empty_rest_of_line ();
5892 }
5893
5894 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
5895 tables in s7_PIC code. */
5896
5897 static void
5898 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5899 {
5900 int reg;
5901 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5902
5903 /* If we are not generating s7_PIC code, .cpload is ignored. */
5904 if (s7_score_pic == s7_NO_PIC)
5905 {
5906 s_ignore (0);
5907 return;
5908 }
5909
5910 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5911 {
5912 return;
5913 }
5914 demand_empty_rest_of_line ();
5915
5916 /* Add $gp to the register named as an argument. */
5917 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5918 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5919 return;
5920 }
5921
5922 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5923 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
5924 do \
5925 { \
5926 if ((SIZE) >= 8) \
5927 (P2VAR) = 3; \
5928 else if ((SIZE) >= 4) \
5929 (P2VAR) = 2; \
5930 else if ((SIZE) >= 2) \
5931 (P2VAR) = 1; \
5932 else \
5933 (P2VAR) = 0; \
5934 } \
5935 while (0)
5936 #endif
5937
5938 static void
5939 s7_s_score_lcomm (int bytes_p)
5940 {
5941 char *name;
5942 char c;
5943 char *p;
5944 int temp;
5945 symbolS *symbolP;
5946 segT current_seg = now_seg;
5947 subsegT current_subseg = now_subseg;
5948 const int max_alignment = 15;
5949 int align = 0;
5950 segT bss_seg = bss_section;
5951 int needs_align = 0;
5952
5953 c = get_symbol_name (&name);
5954 p = input_line_pointer;
5955 *p = c;
5956
5957 if (name == p)
5958 {
5959 as_bad (_("expected symbol name"));
5960 discard_rest_of_line ();
5961 return;
5962 }
5963
5964 SKIP_WHITESPACE_AFTER_NAME ();
5965
5966 /* Accept an optional comma after the name. The comma used to be
5967 required, but Irix 5 cc does not generate it. */
5968 if (*input_line_pointer == ',')
5969 {
5970 ++input_line_pointer;
5971 SKIP_WHITESPACE ();
5972 }
5973
5974 if (is_end_of_line[(unsigned char)*input_line_pointer])
5975 {
5976 as_bad (_("missing size expression"));
5977 return;
5978 }
5979
5980 if ((temp = get_absolute_expression ()) < 0)
5981 {
5982 as_warn (_("BSS length (%d) < 0 ignored"), temp);
5983 ignore_rest_of_line ();
5984 return;
5985 }
5986
5987 #if defined (TC_SCORE)
5988 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
5989 {
5990 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
5991 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
5992 {
5993 bss_seg = subseg_new (".sbss", 1);
5994 seg_info (bss_seg)->bss = 1;
5995 #ifdef BFD_ASSEMBLER
5996 if (!bfd_set_section_flags (bss_seg, SEC_ALLOC))
5997 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
5998 #endif
5999 }
6000 }
6001 #endif
6002
6003 SKIP_WHITESPACE ();
6004 if (*input_line_pointer == ',')
6005 {
6006 ++input_line_pointer;
6007 SKIP_WHITESPACE ();
6008
6009 if (is_end_of_line[(unsigned char)*input_line_pointer])
6010 {
6011 as_bad (_("missing alignment"));
6012 return;
6013 }
6014 else
6015 {
6016 align = get_absolute_expression ();
6017 needs_align = 1;
6018 }
6019 }
6020
6021 if (!needs_align)
6022 {
6023 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6024
6025 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6026 if (align)
6027 record_alignment (bss_seg, align);
6028 }
6029
6030 if (needs_align)
6031 {
6032 if (bytes_p)
6033 {
6034 /* Convert to a power of 2. */
6035 if (align != 0)
6036 {
6037 unsigned int i;
6038
6039 for (i = 0; align != 0; align >>= 1, ++i)
6040 ;
6041 align = i - 1;
6042 }
6043 }
6044
6045 if (align > max_alignment)
6046 {
6047 align = max_alignment;
6048 as_warn (_("alignment too large; %d assumed"), align);
6049 }
6050 else if (align < 0)
6051 {
6052 align = 0;
6053 as_warn (_("alignment negative; 0 assumed"));
6054 }
6055
6056 record_alignment (bss_seg, align);
6057 }
6058 else
6059 {
6060 /* Assume some objects may require alignment on some systems. */
6061 #if defined (TC_ALPHA) && ! defined (VMS)
6062 if (temp > 1)
6063 {
6064 align = ffs (temp) - 1;
6065 if (temp % (1 << align))
6066 abort ();
6067 }
6068 #endif
6069 }
6070
6071 *p = 0;
6072 symbolP = symbol_find_or_make (name);
6073 *p = c;
6074
6075 if (
6076 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
6077 #ifdef BFD_ASSEMBLER
6078 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6079 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6080 #else
6081 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6082 #endif
6083 #endif
6084 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6085 {
6086 char *pfrag;
6087
6088 subseg_set (bss_seg, 1);
6089
6090 if (align)
6091 frag_align (align, 0, 0);
6092
6093 /* Detach from old frag. */
6094 if (S_GET_SEGMENT (symbolP) == bss_seg)
6095 symbol_get_frag (symbolP)->fr_symbol = NULL;
6096
6097 symbol_set_frag (symbolP, frag_now);
6098 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6099 *pfrag = 0;
6100
6101
6102 S_SET_SEGMENT (symbolP, bss_seg);
6103
6104 #ifdef OBJ_COFF
6105 /* The symbol may already have been created with a preceding
6106 ".globl" directive -- be careful not to step on storage class
6107 in that case. Otherwise, set it to static. */
6108 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6109 {
6110 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6111 }
6112 #endif /* OBJ_COFF */
6113
6114 #ifdef S_SET_SIZE
6115 S_SET_SIZE (symbolP, temp);
6116 #endif
6117 }
6118 else
6119 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6120
6121 subseg_set (current_seg, current_subseg);
6122
6123 demand_empty_rest_of_line ();
6124 }
6125
6126 \f
6127
6128 static void
6129 s7_begin (void)
6130 {
6131 unsigned int i;
6132 segT seg;
6133 subsegT subseg;
6134
6135 if ((s7_score_ops_hsh = hash_new ()) == NULL)
6136 as_fatal (_("virtual memory exhausted"));
6137
6138 s7_build_score_ops_hsh ();
6139
6140 if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6141 as_fatal (_("virtual memory exhausted"));
6142
6143 s7_build_dependency_insn_hsh ();
6144
6145 for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6146 s7_build_reg_hsh (s7_all_reg_maps + i);
6147
6148 /* Initialize dependency vector. */
6149 s7_init_dependency_vector ();
6150
6151 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6152 seg = now_seg;
6153 subseg = now_subseg;
6154 s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6155 bfd_set_section_flags (s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6156 bfd_set_section_alignment (s7_pdr_seg, 2);
6157 subseg_set (seg, subseg);
6158
6159 if (s7_USE_GLOBAL_POINTER_OPT)
6160 bfd_set_gp_size (stdoutput, s7_g_switch_value);
6161 }
6162
6163 static void
6164 s7_assemble (char *str)
6165 {
6166 know (str);
6167 know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6168
6169 memset (&s7_inst, '\0', sizeof (s7_inst));
6170 if (s7_INSN_IS_PCE_P (str))
6171 s7_parse_pce_inst (str);
6172 else
6173 s7_parse_16_32_inst (str, TRUE);
6174
6175 if (s7_inst.error)
6176 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6177 }
6178
6179 /* We handle all bad expressions here, so that we can report the faulty
6180 instruction in the error message. */
6181
6182 static void
6183 s7_operand (expressionS * exp)
6184 {
6185 if (s7_in_my_get_expression)
6186 {
6187 exp->X_op = O_illegal;
6188 if (s7_inst.error == NULL)
6189 {
6190 s7_inst.error = _("bad expression");
6191 }
6192 }
6193 }
6194
6195 /* Turn a string in input_line_pointer into a floating point constant
6196 of type TYPE, and store the appropriate bytes in *LITP. The number
6197 of LITTLENUMS emitted is stored in *SIZEP. An error message is
6198 returned, or NULL on OK.
6199
6200 Note that fp constants aren't represent in the normal way on the ARM.
6201 In big endian mode, things are as expected. However, in little endian
6202 mode fp constants are big-endian word-wise, and little-endian byte-wise
6203 within the words. For example, (double) 1.1 in big endian mode is
6204 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6205 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6206
6207 static const char *
6208 s7_atof (int type, char *litP, int *sizeP)
6209 {
6210 int prec;
6211 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6212 char *t;
6213 int i;
6214
6215 switch (type)
6216 {
6217 case 'f':
6218 case 'F':
6219 case 's':
6220 case 'S':
6221 prec = 2;
6222 break;
6223 case 'd':
6224 case 'D':
6225 case 'r':
6226 case 'R':
6227 prec = 4;
6228 break;
6229 case 'x':
6230 case 'X':
6231 case 'p':
6232 case 'P':
6233 prec = 6;
6234 break;
6235 default:
6236 *sizeP = 0;
6237 return _("bad call to MD_ATOF()");
6238 }
6239
6240 t = atof_ieee (input_line_pointer, type, words);
6241 if (t)
6242 input_line_pointer = t;
6243 *sizeP = prec * 2;
6244
6245 if (target_big_endian)
6246 {
6247 for (i = 0; i < prec; i++)
6248 {
6249 s7_number_to_chars (litP, (valueT) words[i], 2);
6250 litP += 2;
6251 }
6252 }
6253 else
6254 {
6255 for (i = 0; i < prec; i += 2)
6256 {
6257 s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6258 s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6259 litP += 4;
6260 }
6261 }
6262
6263 return 0;
6264 }
6265
6266 /* Implementation of md_frag_check.
6267 Called after md_convert_frag(). */
6268
6269 static void
6270 s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6271 {
6272 know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6273 }
6274
6275 /* Implementation of TC_VALIDATE_FIX.
6276 Called before md_apply_fix() and after md_convert_frag(). */
6277
6278 static void
6279 s7_validate_fix (fixS *fixP)
6280 {
6281 fixP->fx_where += fixP->fx_frag->insn_addr;
6282 }
6283
6284 static int
6285 s7_force_relocation (struct fix *fixp)
6286 {
6287 int retval = 0;
6288
6289 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6290 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6291 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6292 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6293 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6294 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6295 {
6296 retval = 1;
6297 }
6298
6299 return retval;
6300 }
6301
6302 static bfd_boolean
6303 s7_fix_adjustable (fixS * fixP)
6304 {
6305 if (fixP->fx_addsy == NULL)
6306 {
6307 return 1;
6308 }
6309 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6310 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6311 {
6312 return 0;
6313 }
6314 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6315 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6316 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6317 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6318 {
6319 return 0;
6320 }
6321
6322 return 1;
6323 }
6324
6325 static void
6326 s7_elf_final_processing (void)
6327 {
6328 unsigned long val = E_SCORE_MACH_SCORE7;
6329
6330 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6331 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6332 elf_elfheader (stdoutput)->e_flags |= val;
6333
6334 if (s7_fix_data_dependency == 1)
6335 {
6336 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6337 }
6338 if (s7_score_pic == s7_PIC)
6339 {
6340 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6341 }
6342 }
6343
6344 /* In this function, we determine whether s7_GP instruction should do relaxation,
6345 for the label being against was known now.
6346 Doing this here but not in md_relax_frag() can induce iteration times
6347 in stage of doing relax. */
6348
6349 static int
6350 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6351 {
6352 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6353 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6354 return s7_judge_size_before_relax (fragp, sec);
6355
6356 return 0;
6357 }
6358
6359 static int
6360 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6361 fragS * fragp,
6362 long stretch ATTRIBUTE_UNUSED)
6363 {
6364 int grows = 0;
6365 int insn_size;
6366 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
6367 int relaxable_p = 0;
6368 bfd_boolean word_align_p = FALSE;
6369 fragS *next_fragp;
6370
6371 /* If the instruction address is odd, make it half word align first. */
6372 if ((fragp->fr_address) % 2 != 0)
6373 {
6374 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6375 {
6376 fragp->insn_addr = 1;
6377 grows += 1;
6378 }
6379 }
6380
6381 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6382
6383 /* Get instruction size and relax size after the last relaxation. */
6384 if (fragp->fr_opcode)
6385 insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6386 else
6387 insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6388
6389 /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine
6390 whether the s7_GP instruction should do relax. */
6391 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6392 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6393 {
6394 if (!word_align_p)
6395 {
6396 if (fragp->insn_addr < 2)
6397 {
6398 fragp->insn_addr += 2;
6399 grows += 2;
6400 }
6401 else
6402 {
6403 fragp->insn_addr -= 2;
6404 grows -= 2;
6405 }
6406 }
6407
6408 if (fragp->fr_opcode)
6409 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6410 else
6411 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6412 }
6413 else
6414 {
6415 if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6416 s7_b32_relax_to_b16 (fragp);
6417
6418 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6419 next_fragp = fragp->fr_next;
6420 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6421 {
6422 next_fragp = next_fragp->fr_next;
6423 }
6424
6425 if (next_fragp)
6426 {
6427 int n_insn_size;
6428 int n_relaxable_p = 0;
6429
6430 if (next_fragp->fr_opcode)
6431 {
6432 n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6433 }
6434 else
6435 {
6436 n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6437 }
6438
6439 if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6440 s7_b32_relax_to_b16 (next_fragp);
6441 n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6442
6443 if (word_align_p)
6444 {
6445 if (insn_size == 4)
6446 {
6447 /* 32 -> 16. */
6448 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6449 {
6450 grows -= 2;
6451 do_relax_p = 1;
6452 }
6453 }
6454 else if (insn_size == 2)
6455 {
6456 /* 16 -> 32. */
6457 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6458 {
6459 grows += 2;
6460 do_relax_p = 1;
6461 }
6462 }
6463 else
6464 {
6465 abort ();
6466 }
6467 }
6468 else
6469 {
6470 if (insn_size == 4)
6471 {
6472 /* 32 -> 16. */
6473 if (relaxable_p)
6474 {
6475 grows -= 2;
6476 do_relax_p = 1;
6477 }
6478 /* Make the 32 bit instruction word align. */
6479 else
6480 {
6481 fragp->insn_addr += 2;
6482 grows += 2;
6483 }
6484 }
6485 else if (insn_size == 2)
6486 {
6487 /* Do nothing. */
6488 }
6489 else
6490 {
6491 abort ();
6492 }
6493 }
6494 }
6495 else
6496 {
6497 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
6498 if (!word_align_p)
6499 {
6500 if (insn_size % 4 == 0)
6501 {
6502 /* 32 -> 16. */
6503 if (relaxable_p)
6504 {
6505 grows -= 2;
6506 do_relax_p = 1;
6507 }
6508 else
6509 {
6510 fragp->insn_addr += 2;
6511 grows += 2;
6512 }
6513 }
6514 }
6515 else
6516 {
6517 /* Do nothing. */
6518 }
6519 }
6520
6521 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6522 if (do_relax_p)
6523 {
6524 if (fragp->fr_opcode)
6525 {
6526 fragp->fr_opcode = NULL;
6527 /* Guarantee estimate stage is correct. */
6528 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6529 fragp->fr_fix += fragp->insn_addr;
6530 }
6531 else
6532 {
6533 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6534 /* Guarantee estimate stage is correct. */
6535 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6536 fragp->fr_fix += fragp->insn_addr;
6537 }
6538 }
6539 else
6540 {
6541 if (fragp->fr_opcode)
6542 {
6543 /* Guarantee estimate stage is correct. */
6544 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6545 fragp->fr_fix += fragp->insn_addr;
6546 }
6547 else
6548 {
6549 /* Guarantee estimate stage is correct. */
6550 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6551 fragp->fr_fix += fragp->insn_addr;
6552 }
6553 }
6554 }
6555
6556 return grows;
6557 }
6558
6559 static void
6560 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6561 segT sec ATTRIBUTE_UNUSED,
6562 fragS * fragp)
6563 {
6564 unsigned int r_old;
6565 unsigned int r_new;
6566 char backup[20];
6567 fixS *fixp;
6568
6569 r_old = s7_RELAX_OLD (fragp->fr_subtype);
6570 r_new = s7_RELAX_NEW (fragp->fr_subtype);
6571
6572 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6573 if (fragp->fr_opcode == NULL)
6574 {
6575 memcpy (backup, fragp->fr_literal, r_old);
6576 fragp->fr_fix = r_old;
6577 }
6578 else
6579 {
6580 memcpy (backup, fragp->fr_literal + r_old, r_new);
6581 fragp->fr_fix = r_new;
6582 }
6583
6584 fixp = fragp->tc_frag_data.fixp;
6585 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6586 {
6587 if (fragp->fr_opcode)
6588 fixp->fx_done = 1;
6589 fixp = fixp->fx_next;
6590 }
6591 while (fixp && fixp->fx_frag == fragp)
6592 {
6593 if (fragp->fr_opcode)
6594 fixp->fx_where -= r_old + fragp->insn_addr;
6595 else
6596 fixp->fx_done = 1;
6597 fixp = fixp->fx_next;
6598 }
6599
6600 if (fragp->insn_addr)
6601 {
6602 s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6603 }
6604 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6605 fragp->fr_fix += fragp->insn_addr;
6606 }
6607
6608 static long
6609 s7_pcrel_from (fixS * fixP)
6610 {
6611 long retval = 0;
6612
6613 if (fixP->fx_addsy
6614 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6615 && (fixP->fx_subsy == NULL))
6616 {
6617 retval = 0;
6618 }
6619 else
6620 {
6621 retval = fixP->fx_where + fixP->fx_frag->fr_address;
6622 }
6623
6624 return retval;
6625 }
6626
6627 /* Round up a section size to the appropriate boundary. */
6628 static valueT
6629 s7_section_align (segT segment, valueT size)
6630 {
6631 int align = bfd_section_alignment (segment);
6632
6633 return ((size + (1 << align) - 1) & -(1 << align));
6634 }
6635
6636 static void
6637 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6638 {
6639 offsetT value = *valP;
6640 offsetT abs_value = 0;
6641 offsetT newval;
6642 offsetT content;
6643 unsigned short HI, LO;
6644
6645 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6646
6647 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6648 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6649 {
6650 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6651 fixP->fx_done = 1;
6652 }
6653
6654 /* If this symbol is in a different section then we need to leave it for
6655 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
6656 so we have to undo it's effects here. */
6657 if (fixP->fx_pcrel)
6658 {
6659 if (fixP->fx_addsy != NULL
6660 && S_IS_DEFINED (fixP->fx_addsy)
6661 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6662 value += md_pcrel_from (fixP);
6663 }
6664
6665 /* Remember value for emit_reloc. */
6666 fixP->fx_addnumber = value;
6667
6668 switch (fixP->fx_r_type)
6669 {
6670 case BFD_RELOC_HI16_S:
6671 if (fixP->fx_done)
6672 { /* For la rd, imm32. */
6673 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6674 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
6675 newval |= (HI & 0x3fff) << 1;
6676 newval |= ((HI >> 14) & 0x3) << 16;
6677 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6678 }
6679 break;
6680 case BFD_RELOC_LO16:
6681 if (fixP->fx_done) /* For la rd, imm32. */
6682 {
6683 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6684 LO = (value) & 0xffff;
6685 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
6686 newval |= ((LO >> 14) & 0x3) << 16;
6687 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6688 }
6689 break;
6690 case BFD_RELOC_SCORE_JMP:
6691 {
6692 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6693 value = fixP->fx_offset;
6694 if (!(value >= 0 && value <= 0x1ffffff))
6695 {
6696 as_bad_where (fixP->fx_file, fixP->fx_line,
6697 _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value);
6698 return;
6699 }
6700 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6701 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6702 }
6703 break;
6704 case BFD_RELOC_SCORE_BRANCH:
6705 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6706 value = fixP->fx_offset;
6707 else
6708 fixP->fx_done = 1;
6709
6710 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6711 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6712 {
6713 if ((value & 0x80000000) == 0x80000000)
6714 abs_value = 0xffffffff - value + 1;
6715 if ((abs_value & 0xffffff00) != 0)
6716 {
6717 as_bad_where (fixP->fx_file, fixP->fx_line,
6718 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6719 return;
6720 }
6721 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6722 content &= 0xff00;
6723 content = (content & 0xff00) | ((value >> 1) & 0xff);
6724 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6725 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6726 fixP->fx_size = 2;
6727 }
6728 else
6729 {
6730 if ((value & 0x80000000) == 0x80000000)
6731 abs_value = 0xffffffff - value + 1;
6732 if ((abs_value & 0xfff80000) != 0)
6733 {
6734 as_bad_where (fixP->fx_file, fixP->fx_line,
6735 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6736 (unsigned int) value);
6737 return;
6738 }
6739 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6740 content &= 0xfc00fc01;
6741 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6742 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6743 }
6744 break;
6745 case BFD_RELOC_SCORE16_JMP:
6746 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6747 content &= 0xf001;
6748 value = fixP->fx_offset;
6749 if (!(value >= 0 && value <= 0xfff))
6750 {
6751 as_bad_where (fixP->fx_file, fixP->fx_line,
6752 _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value);
6753 return;
6754 }
6755 value = fixP->fx_offset & 0xfff;
6756 content = (content & 0xfc01) | (value & 0xffe);
6757 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6758 break;
6759 case BFD_RELOC_SCORE16_BRANCH:
6760 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6761 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6762 {
6763 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6764 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6765 value = fixP->fx_offset;
6766 else
6767 fixP->fx_done = 1;
6768
6769 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6770 {
6771 as_bad_where (fixP->fx_file, fixP->fx_line,
6772 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6773 (unsigned int) value);
6774 return;
6775 }
6776 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6777 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6778 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6779 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6780 fixP->fx_size = 4;
6781 break;
6782 }
6783 else
6784 {
6785 /* In different section. */
6786 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6787 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6788 value = fixP->fx_offset;
6789 else
6790 fixP->fx_done = 1;
6791
6792 if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6793 {
6794 as_bad_where (fixP->fx_file, fixP->fx_line,
6795 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"),
6796 (unsigned int) value);
6797 return;
6798 }
6799 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6800 content = (content & 0xff00) | ((value >> 1) & 0xff);
6801 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6802 break;
6803 }
6804 case BFD_RELOC_8:
6805 if (fixP->fx_done || fixP->fx_pcrel)
6806 s7_number_to_chars (buf, value, 1);
6807 #ifdef OBJ_ELF
6808 else
6809 {
6810 value = fixP->fx_offset;
6811 s7_number_to_chars (buf, value, 1);
6812 }
6813 #endif
6814 break;
6815
6816 case BFD_RELOC_16:
6817 if (fixP->fx_done || fixP->fx_pcrel)
6818 s7_number_to_chars (buf, value, 2);
6819 #ifdef OBJ_ELF
6820 else
6821 {
6822 value = fixP->fx_offset;
6823 s7_number_to_chars (buf, value, 2);
6824 }
6825 #endif
6826 break;
6827 case BFD_RELOC_RVA:
6828 case BFD_RELOC_32:
6829 if (fixP->fx_done || fixP->fx_pcrel)
6830 s7_number_to_chars (buf, value, 4);
6831 #ifdef OBJ_ELF
6832 else
6833 {
6834 value = fixP->fx_offset;
6835 s7_number_to_chars (buf, value, 4);
6836 }
6837 #endif
6838 break;
6839 case BFD_RELOC_VTABLE_INHERIT:
6840 fixP->fx_done = 0;
6841 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6842 S_SET_WEAK (fixP->fx_addsy);
6843 break;
6844 case BFD_RELOC_VTABLE_ENTRY:
6845 fixP->fx_done = 0;
6846 break;
6847 case BFD_RELOC_SCORE_GPREL15:
6848 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6849 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6850 fixP->fx_r_type = BFD_RELOC_NONE;
6851 fixP->fx_done = 0;
6852 break;
6853 case BFD_RELOC_SCORE_GOT15:
6854 case BFD_RELOC_SCORE_DUMMY_HI16:
6855 case BFD_RELOC_SCORE_GOT_LO16:
6856 case BFD_RELOC_SCORE_CALL15:
6857 case BFD_RELOC_GPREL32:
6858 break;
6859 case BFD_RELOC_NONE:
6860 default:
6861 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6862 }
6863 }
6864
6865 /* Translate internal representation of relocation info to BFD target format. */
6866
6867 static arelent **
6868 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6869 {
6870 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
6871 arelent *reloc;
6872 bfd_reloc_code_real_type code;
6873 const char *type;
6874
6875 reloc = retval[0] = XNEW (arelent);
6876 retval[1] = NULL;
6877
6878 reloc->sym_ptr_ptr = XNEW (asymbol *);
6879 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6880 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6881 reloc->addend = fixp->fx_offset;
6882
6883 /* If this is a variant frag, we may need to adjust the existing
6884 reloc and generate a new one. */
6885 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6886 {
6887 /* Update instruction imm bit. */
6888 offsetT newval;
6889 unsigned short off;
6890 char *buf;
6891
6892 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6893 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6894 off = fixp->fx_offset >> 16;
6895 newval |= (off & 0x3fff) << 1;
6896 newval |= ((off >> 14) & 0x3) << 16;
6897 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6898
6899 buf += s7_INSN_SIZE;
6900 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6901 off = fixp->fx_offset & 0xffff;
6902 newval |= ((off & 0x3fff) << 1);
6903 newval |= (((off >> 14) & 0x3) << 16);
6904 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6905
6906 retval[1] = XNEW (arelent);
6907 retval[2] = NULL;
6908 retval[1]->sym_ptr_ptr = XNEW (asymbol *);
6909 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6910 retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6911
6912 retval[1]->addend = 0;
6913 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6914 gas_assert (retval[1]->howto != NULL);
6915
6916 fixp->fx_r_type = BFD_RELOC_HI16_S;
6917 }
6918
6919 code = fixp->fx_r_type;
6920 switch (fixp->fx_r_type)
6921 {
6922 case BFD_RELOC_32:
6923 if (fixp->fx_pcrel)
6924 {
6925 code = BFD_RELOC_32_PCREL;
6926 break;
6927 }
6928 /* Fall through. */
6929 case BFD_RELOC_HI16_S:
6930 case BFD_RELOC_LO16:
6931 case BFD_RELOC_SCORE_JMP:
6932 case BFD_RELOC_SCORE_BRANCH:
6933 case BFD_RELOC_SCORE16_JMP:
6934 case BFD_RELOC_SCORE16_BRANCH:
6935 case BFD_RELOC_VTABLE_ENTRY:
6936 case BFD_RELOC_VTABLE_INHERIT:
6937 case BFD_RELOC_SCORE_GPREL15:
6938 case BFD_RELOC_SCORE_GOT15:
6939 case BFD_RELOC_SCORE_DUMMY_HI16:
6940 case BFD_RELOC_SCORE_GOT_LO16:
6941 case BFD_RELOC_SCORE_CALL15:
6942 case BFD_RELOC_GPREL32:
6943 case BFD_RELOC_NONE:
6944 code = fixp->fx_r_type;
6945 break;
6946 default:
6947 type = _("<unknown>");
6948 as_bad_where (fixp->fx_file, fixp->fx_line,
6949 _("cannot represent %s relocation in this object file format"), type);
6950 return NULL;
6951 }
6952
6953 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6954 if (reloc->howto == NULL)
6955 {
6956 as_bad_where (fixp->fx_file, fixp->fx_line,
6957 _("cannot represent %s relocation in this object file format1"),
6958 bfd_get_reloc_code_name (code));
6959 return NULL;
6960 }
6961 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6962 vtable entry to be used in the relocation's section offset. */
6963 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6964 reloc->address = fixp->fx_offset;
6965
6966 return retval;
6967 }