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