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