c931102ce31fc2807bf1bcad1baa15119fab31de
[deliverable/binutils-gdb.git] / gas / config / tc-score7.c
1 /* tc-score7.c -- Assembler for Score7
2 Copyright 2009 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 segT seg;
1264
1265 save_in = input_line_pointer;
1266 input_line_pointer = *str;
1267 s7_in_my_get_expression = 1;
1268 seg = 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 sprintf (s7_inst.str, "%s", 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 sprintf (s7_inst.name, "%s", 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 *strbak;
3100 char *dataptr;
3101 int reg;
3102 int ldst_idx = 0;
3103
3104 int hex_p = 0;
3105
3106 strbak = str;
3107 s7_skip_whitespace (str);
3108
3109 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3110 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3111 return;
3112
3113 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
3114 if (*str == '[')
3115 {
3116 str++;
3117 s7_skip_whitespace (str);
3118
3119 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3120 return;
3121
3122 /* Conflicts can occur on stores as well as loads. */
3123 conflict_reg = (conflict_reg == reg);
3124 s7_skip_whitespace (str);
3125 temp = str + 1; /* The latter will process decimal/hex expression. */
3126
3127 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
3128 if (*str == ']')
3129 {
3130 str++;
3131 if (*str == '+')
3132 {
3133 str++;
3134 /* ld/sw rD, [rA]+, simm12. */
3135 if (s7_skip_past_comma (&str) == s7_SUCCESS)
3136 {
3137 if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
3138 || (s7_end_of_line (str) == (int) s7_FAIL))
3139 return;
3140
3141 if (conflict_reg)
3142 {
3143 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3144
3145 if ((ldst_func == INSN_LH)
3146 || (ldst_func == INSN_LHU)
3147 || (ldst_func == INSN_LW)
3148 || (ldst_func == INSN_LB)
3149 || (ldst_func == INSN_LBU))
3150 {
3151 s7_inst.error = _("register same as write-back base");
3152 return;
3153 }
3154 }
3155
3156 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3157 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3158 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
3159
3160 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
3161 if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
3162 {
3163 /* rs = r0-r7, offset = 4 */
3164 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3165 && (((s7_inst.instruction >> 3) & 0xfff) == 4))
3166 {
3167 /* Relax to pophi. */
3168 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3169 {
3170 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3171 << 8) | 1 << 7 |
3172 (((s7_inst.instruction >> 15) & 0x7) << 4);
3173 }
3174 /* Relax to pop. */
3175 else
3176 {
3177 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3178 << 8) | 0 << 7 |
3179 (((s7_inst.instruction >> 15) & 0x7) << 4);
3180 }
3181 s7_inst.relax_size = 2;
3182 }
3183 }
3184 return;
3185 }
3186 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3187 else
3188 {
3189 s7_SET_INSN_ERROR (NULL);
3190 if (s7_end_of_line (str) == (int) s7_FAIL)
3191 {
3192 return;
3193 }
3194
3195 pre_inc = 1;
3196 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
3197 value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
3198 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3199 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3200 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3201 s7_inst.instruction |= value << 3;
3202 s7_inst.relax_inst = 0x8000;
3203 return;
3204 }
3205 }
3206 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3207 else
3208 {
3209 if (s7_end_of_line (str) == (int) s7_FAIL)
3210 return;
3211
3212 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3213 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3214 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3215
3216 /* lbu rd, [rs] -> lbu! rd, [rs] */
3217 if (ldst_idx == INSN_LBU)
3218 {
3219 s7_inst.relax_inst = INSN16_LBU;
3220 }
3221 else if (ldst_idx == INSN_LH)
3222 {
3223 s7_inst.relax_inst = INSN16_LH;
3224 }
3225 else if (ldst_idx == INSN_LW)
3226 {
3227 s7_inst.relax_inst = INSN16_LW;
3228 }
3229 else if (ldst_idx == INSN_SB)
3230 {
3231 s7_inst.relax_inst = INSN16_SB;
3232 }
3233 else if (ldst_idx == INSN_SH)
3234 {
3235 s7_inst.relax_inst = INSN16_SH;
3236 }
3237 else if (ldst_idx == INSN_SW)
3238 {
3239 s7_inst.relax_inst = INSN16_SW;
3240 }
3241 else
3242 {
3243 s7_inst.relax_inst = 0x8000;
3244 }
3245
3246 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
3247 if ((ldst_idx == INSN_LBU)
3248 || (ldst_idx == INSN_LH)
3249 || (ldst_idx == INSN_LW)
3250 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
3251 {
3252 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3253 {
3254 s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
3255 (((s7_inst.instruction >> 15) & 0xf) << 4);
3256 s7_inst.relax_size = 2;
3257 }
3258 }
3259
3260 return;
3261 }
3262 }
3263 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3264 else
3265 {
3266 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3267 {
3268 s7_inst.error = _("pre-indexed expression expected");
3269 return;
3270 }
3271
3272 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
3273 return;
3274
3275 s7_skip_whitespace (str);
3276 if (*str++ != ']')
3277 {
3278 s7_inst.error = _("missing ]");
3279 return;
3280 }
3281
3282 s7_skip_whitespace (str);
3283 /* ld/sw rD, [rA, simm12]+. */
3284 if (*str == '+')
3285 {
3286 str++;
3287 pre_inc = 1;
3288 if (conflict_reg)
3289 {
3290 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3291
3292 if ((ldst_func == INSN_LH)
3293 || (ldst_func == INSN_LHU)
3294 || (ldst_func == INSN_LW)
3295 || (ldst_func == INSN_LB)
3296 || (ldst_func == INSN_LBU))
3297 {
3298 s7_inst.error = _("register same as write-back base");
3299 return;
3300 }
3301 }
3302 }
3303
3304 if (s7_end_of_line (str) == (int) s7_FAIL)
3305 return;
3306
3307 if (s7_inst.reloc.exp.X_op == O_constant)
3308 {
3309 int value;
3310 unsigned int data_type;
3311
3312 if (pre_inc == 1)
3313 data_type = _SIMM12;
3314 else
3315 data_type = _SIMM15;
3316 dataptr = temp;
3317
3318 if ((dataptr != NULL)
3319 && (((strstr (dataptr, "0x")) != NULL)
3320 || ((strstr (dataptr, "0X")) != NULL)))
3321 {
3322 hex_p = 1;
3323 if ((data_type != _SIMM16_LA)
3324 && (data_type != _VALUE_HI16)
3325 && (data_type != _VALUE_LO16)
3326 && (data_type != _IMM16)
3327 && (data_type != _IMM15)
3328 && (data_type != _IMM14)
3329 && (data_type != _IMM4)
3330 && (data_type != _IMM5)
3331 && (data_type != _IMM8)
3332 && (data_type != _SIMM12)
3333 && (data_type != _SIMM15)
3334 && (data_type != _IMM5_RSHIFT_1)
3335 && (data_type != _IMM5_RSHIFT_2)
3336 && (data_type != _SIMM14_NEG)
3337 && (data_type != _IMM10_RSHIFT_2))
3338 {
3339 data_type += 24;
3340 }
3341 }
3342
3343 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3344 if (value == (int) s7_FAIL)
3345 {
3346 if (data_type < 30)
3347 sprintf (s7_err_msg,
3348 _("invalid constant: %d bit expression not in range %d..%d"),
3349 s7_score_df_range[data_type].bits,
3350 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3351 else
3352 sprintf (s7_err_msg,
3353 _("invalid constant: %d bit expression not in range %d..%d"),
3354 s7_score_df_range[data_type - 24].bits,
3355 s7_score_df_range[data_type - 24].range[0],
3356 s7_score_df_range[data_type - 24].range[1]);
3357 s7_inst.error = s7_err_msg;
3358 return;
3359 }
3360
3361 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3362 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3363 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3364 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3365 if (pre_inc == 1)
3366 s7_inst.instruction |= value << 3;
3367 else
3368 s7_inst.instruction |= value;
3369
3370 /* lw rD, [rA, simm15] */
3371 if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3372 {
3373 /* Both rD and rA are in [r0 - r15]. */
3374 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3375 && (((s7_inst.instruction >> 20) & 0x10) == 0))
3376 {
3377 /* simm15 = 0, lw -> lw!. */
3378 if ((s7_inst.instruction & 0x7fff) == 0)
3379 {
3380 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3381 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3382 s7_inst.relax_size = 2;
3383 }
3384 /* rA = r2, lw -> lwp!. */
3385 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3386 && ((s7_inst.instruction & 0x3) == 0)
3387 && ((s7_inst.instruction & 0x7fff) < 128))
3388 {
3389 s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3390 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3391 s7_inst.relax_size = 2;
3392 }
3393 else
3394 {
3395 s7_inst.relax_inst = 0x8000;
3396 }
3397 }
3398 else
3399 {
3400 s7_inst.relax_inst = 0x8000;
3401 }
3402 }
3403 /* sw rD, [rA, simm15] */
3404 else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3405 {
3406 /* Both rD and rA are in [r0 - r15]. */
3407 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3408 {
3409 /* simm15 = 0, sw -> sw!. */
3410 if ((s7_inst.instruction & 0x7fff) == 0)
3411 {
3412 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3413 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3414 s7_inst.relax_size = 2;
3415 }
3416 /* rA = r2, sw -> swp!. */
3417 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3418 && ((s7_inst.instruction & 0x3) == 0)
3419 && ((s7_inst.instruction & 0x7fff) < 128))
3420 {
3421 s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3422 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3423 s7_inst.relax_size = 2;
3424 }
3425 else
3426 {
3427 s7_inst.relax_inst = 0x8000;
3428 }
3429 }
3430 else
3431 {
3432 s7_inst.relax_inst = 0x8000;
3433 }
3434 }
3435 /* sw rD, [rA, simm15]+ sw pre. */
3436 else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3437 {
3438 /* rA is in [r0 - r7], and simm15 = -4. */
3439 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3440 && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3441 {
3442 /* sw -> pushhi!. */
3443 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3444 {
3445 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3446 | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3447 s7_inst.relax_size = 2;
3448 }
3449 /* sw -> push!. */
3450 else
3451 {
3452 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3453 | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3454 s7_inst.relax_size = 2;
3455 }
3456 }
3457 else
3458 {
3459 s7_inst.relax_inst = 0x8000;
3460 }
3461 }
3462 /* lh rD, [rA, simm15] */
3463 else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3464 {
3465 /* Both rD and rA are in [r0 - r15]. */
3466 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3467 {
3468 /* simm15 = 0, lh -> lh!. */
3469 if ((s7_inst.instruction & 0x7fff) == 0)
3470 {
3471 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3472 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3473 s7_inst.relax_size = 2;
3474 }
3475 /* rA = r2, lh -> lhp!. */
3476 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3477 && ((s7_inst.instruction & 0x1) == 0)
3478 && ((s7_inst.instruction & 0x7fff) < 64))
3479 {
3480 s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3481 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3482 s7_inst.relax_size = 2;
3483 }
3484 else
3485 {
3486 s7_inst.relax_inst = 0x8000;
3487 }
3488 }
3489 else
3490 {
3491 s7_inst.relax_inst = 0x8000;
3492 }
3493 }
3494 /* sh rD, [rA, simm15] */
3495 else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3496 {
3497 /* Both rD and rA are in [r0 - r15]. */
3498 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3499 {
3500 /* simm15 = 0, sh -> sh!. */
3501 if ((s7_inst.instruction & 0x7fff) == 0)
3502 {
3503 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3504 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3505 s7_inst.relax_size = 2;
3506 }
3507 /* rA = r2, sh -> shp!. */
3508 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3509 && ((s7_inst.instruction & 0x1) == 0)
3510 && ((s7_inst.instruction & 0x7fff) < 64))
3511 {
3512 s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3513 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3514 s7_inst.relax_size = 2;
3515 }
3516 else
3517 {
3518 s7_inst.relax_inst = 0x8000;
3519 }
3520 }
3521 else
3522 {
3523 s7_inst.relax_inst = 0x8000;
3524 }
3525 }
3526 /* lbu rD, [rA, simm15] */
3527 else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3528 {
3529 /* Both rD and rA are in [r0 - r15]. */
3530 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3531 {
3532 /* simm15 = 0, lbu -> lbu!. */
3533 if ((s7_inst.instruction & 0x7fff) == 0)
3534 {
3535 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3536 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3537 s7_inst.relax_size = 2;
3538 }
3539 /* rA = r2, lbu -> lbup!. */
3540 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3541 && ((s7_inst.instruction & 0x7fff) < 32))
3542 {
3543 s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3544 | ((s7_inst.instruction & 0x7fff) << 3);
3545 s7_inst.relax_size = 2;
3546 }
3547 else
3548 {
3549 s7_inst.relax_inst = 0x8000;
3550 }
3551 }
3552 else
3553 {
3554 s7_inst.relax_inst = 0x8000;
3555 }
3556 }
3557 /* sb rD, [rA, simm15] */
3558 else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3559 {
3560 /* Both rD and rA are in [r0 - r15]. */
3561 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3562 {
3563 /* simm15 = 0, sb -> sb!. */
3564 if ((s7_inst.instruction & 0x7fff) == 0)
3565 {
3566 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3567 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3568 s7_inst.relax_size = 2;
3569 }
3570 /* rA = r2, sb -> sb!. */
3571 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3572 && ((s7_inst.instruction & 0x7fff) < 32))
3573 {
3574 s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3575 | ((s7_inst.instruction & 0x7fff) << 3);
3576 s7_inst.relax_size = 2;
3577 }
3578 else
3579 {
3580 s7_inst.relax_inst = 0x8000;
3581 }
3582 }
3583 else
3584 {
3585 s7_inst.relax_inst = 0x8000;
3586 }
3587 }
3588 else
3589 {
3590 s7_inst.relax_inst = 0x8000;
3591 }
3592
3593 return;
3594 }
3595 else
3596 {
3597 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3598 s7_inst.reloc.pc_rel = 0;
3599 }
3600 }
3601 }
3602 else
3603 {
3604 s7_inst.error = s7_BAD_ARGS;
3605 }
3606 }
3607
3608 /* Handle cache. */
3609 static void
3610 s7_do_cache (char *str)
3611 {
3612 s7_skip_whitespace (str);
3613
3614 if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3615 {
3616 return;
3617 }
3618 else
3619 {
3620 int cache_op;
3621
3622 cache_op = (s7_inst.instruction >> 20) & 0x1F;
3623 sprintf (s7_inst.name, "cache %d", cache_op);
3624 }
3625
3626 if (*str == '[')
3627 {
3628 str++;
3629 s7_skip_whitespace (str);
3630
3631 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3632 return;
3633
3634 s7_skip_whitespace (str);
3635
3636 /* cache op, [rA] */
3637 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3638 {
3639 s7_SET_INSN_ERROR (NULL);
3640 if (*str != ']')
3641 {
3642 s7_inst.error = _("missing ]");
3643 return;
3644 }
3645 str++;
3646 }
3647 /* cache op, [rA, simm15] */
3648 else
3649 {
3650 if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3651 {
3652 return;
3653 }
3654
3655 s7_skip_whitespace (str);
3656 if (*str++ != ']')
3657 {
3658 s7_inst.error = _("missing ]");
3659 return;
3660 }
3661 }
3662
3663 if (s7_end_of_line (str) == (int) s7_FAIL)
3664 return;
3665 }
3666 else
3667 {
3668 s7_inst.error = s7_BAD_ARGS;
3669 }
3670 }
3671
3672 static void
3673 s7_do_crdcrscrsimm5 (char *str)
3674 {
3675 char *strbak;
3676
3677 strbak = str;
3678 s7_skip_whitespace (str);
3679
3680 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3681 || s7_skip_past_comma (&str) == (int) s7_FAIL
3682 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3683 || s7_skip_past_comma (&str) == (int) s7_FAIL
3684 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3685 || s7_skip_past_comma (&str) == (int) s7_FAIL)
3686 {
3687 str = strbak;
3688 /* cop1 cop_code20. */
3689 if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3690 return;
3691 }
3692 else
3693 {
3694 if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3695 return;
3696 }
3697
3698 s7_end_of_line (str);
3699 }
3700
3701 /* Handle ldc/stc. */
3702 static void
3703 s7_do_ldst_cop (char *str)
3704 {
3705 s7_skip_whitespace (str);
3706
3707 if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3708 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3709 return;
3710
3711 if (*str == '[')
3712 {
3713 str++;
3714 s7_skip_whitespace (str);
3715
3716 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3717 return;
3718
3719 s7_skip_whitespace (str);
3720
3721 if (*str++ != ']')
3722 {
3723 if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3724 return;
3725
3726 s7_skip_whitespace (str);
3727 if (*str++ != ']')
3728 {
3729 s7_inst.error = _("missing ]");
3730 return;
3731 }
3732 }
3733
3734 s7_end_of_line (str);
3735 }
3736 else
3737 s7_inst.error = s7_BAD_ARGS;
3738 }
3739
3740 static void
3741 s7_do16_ldst_insn (char *str)
3742 {
3743 s7_skip_whitespace (str);
3744
3745 if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3746 return;
3747
3748 if (*str == '[')
3749 {
3750 int reg;
3751
3752 str++;
3753 s7_skip_whitespace (str);
3754
3755 if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3756 return;
3757
3758 s7_skip_whitespace (str);
3759 if (*str++ == ']')
3760 {
3761 if (s7_end_of_line (str) == (int) s7_FAIL)
3762 return;
3763 else
3764 {
3765 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3766 | (((s7_inst.instruction >> 4) & 0xf) << 15);
3767 s7_inst.relax_size = 4;
3768 }
3769 }
3770 else
3771 {
3772 s7_inst.error = _("missing ]");
3773 }
3774 }
3775 else
3776 {
3777 s7_inst.error = s7_BAD_ARGS;
3778 }
3779 }
3780
3781 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3782
3783 static void
3784 s7_do16_ldst_imm_insn (char *str)
3785 {
3786 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3787 int reg_rd;
3788 char *dataptr = NULL, *pp = NULL;
3789 int cnt = 0;
3790 int assign_data = (int) s7_FAIL;
3791 unsigned int ldst_func;
3792
3793 s7_skip_whitespace (str);
3794
3795 if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3796 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3797 return;
3798
3799 s7_skip_whitespace (str);
3800 dataptr = str;
3801
3802 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3803 {
3804 data_exp[cnt] = *dataptr;
3805 dataptr++;
3806 cnt++;
3807 }
3808
3809 data_exp[cnt] = '\0';
3810 pp = &data_exp[0];
3811
3812 str = dataptr;
3813
3814 ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3815 if (ldst_func == N16_LIU)
3816 assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3817 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3818 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3819 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3820 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3821 else
3822 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3823
3824 if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3825 return;
3826 else
3827 {
3828 if ((s7_inst.instruction & 0x7000) == N16_LIU)
3829 {
3830 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3831 | ((s7_inst.instruction & 0xff) << 1);
3832 }
3833 else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3834 || ((s7_inst.instruction & 0x7007) == N16_SHP))
3835 {
3836 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3837 | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3838 }
3839 else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3840 || ((s7_inst.instruction & 0x7007) == N16_SWP))
3841 {
3842 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3843 | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3844 }
3845 else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3846 || ((s7_inst.instruction & 0x7007) == N16_SBP))
3847 {
3848 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3849 | (((s7_inst.instruction >> 3) & 0x1f));
3850 }
3851
3852 s7_inst.relax_size = 4;
3853 }
3854 }
3855
3856 static void
3857 s7_do16_push_pop (char *str)
3858 {
3859 int reg_rd;
3860 int H_bit_mask = 0;
3861
3862 s7_skip_whitespace (str);
3863 if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3864 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3865 return;
3866
3867 if (reg_rd >= 16)
3868 H_bit_mask = 1;
3869
3870 /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3871 s7_inst.instruction &= ~(1 << 12);
3872
3873 s7_inst.instruction |= H_bit_mask << 7;
3874
3875 if (*str == '[')
3876 {
3877 int reg;
3878
3879 str++;
3880 s7_skip_whitespace (str);
3881 if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3882 return;
3883 else if (reg > 7)
3884 {
3885 if (!s7_inst.error)
3886 s7_inst.error = _("base register nums are over 3 bit");
3887
3888 return;
3889 }
3890
3891 s7_skip_whitespace (str);
3892 if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3893 {
3894 if (!s7_inst.error)
3895 s7_inst.error = _("missing ]");
3896
3897 return;
3898 }
3899
3900 /* pop! */
3901 if ((s7_inst.instruction & 0xf) == 0xa)
3902 {
3903 if (H_bit_mask)
3904 {
3905 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3906 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3907 }
3908 else
3909 {
3910 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3911 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3912 }
3913 }
3914 /* push! */
3915 else
3916 {
3917 if (H_bit_mask)
3918 {
3919 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3920 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3921 }
3922 else
3923 {
3924 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3925 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3926 }
3927 }
3928 s7_inst.relax_size = 4;
3929 }
3930 else
3931 {
3932 s7_inst.error = s7_BAD_ARGS;
3933 }
3934 }
3935
3936 /* Handle lcb/lcw/lce/scb/scw/sce. */
3937 static void
3938 s7_do_ldst_unalign (char *str)
3939 {
3940 int conflict_reg;
3941
3942 if (s7_university_version == 1)
3943 {
3944 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3945 return;
3946 }
3947
3948 s7_skip_whitespace (str);
3949
3950 /* lcb/scb [rA]+. */
3951 if (*str == '[')
3952 {
3953 str++;
3954 s7_skip_whitespace (str);
3955
3956 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3957 return;
3958
3959 if (*str++ == ']')
3960 {
3961 if (*str++ != '+')
3962 {
3963 s7_inst.error = _("missing +");
3964 return;
3965 }
3966 }
3967 else
3968 {
3969 s7_inst.error = _("missing ]");
3970 return;
3971 }
3972
3973 if (s7_end_of_line (str) == (int) s7_FAIL)
3974 return;
3975 }
3976 /* lcw/lce/scb/sce rD, [rA]+. */
3977 else
3978 {
3979 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3980 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3981 {
3982 return;
3983 }
3984
3985 s7_skip_whitespace (str);
3986 if (*str++ == '[')
3987 {
3988 int reg;
3989
3990 s7_skip_whitespace (str);
3991 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3992 {
3993 return;
3994 }
3995
3996 /* Conflicts can occur on stores as well as loads. */
3997 conflict_reg = (conflict_reg == reg);
3998 s7_skip_whitespace (str);
3999 if (*str++ == ']')
4000 {
4001 unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
4002
4003 if (*str++ == '+')
4004 {
4005 if (conflict_reg)
4006 {
4007 as_warn (_("%s register same as write-back base"),
4008 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4009 ? _("destination") : _("source")));
4010 }
4011 }
4012 else
4013 {
4014 s7_inst.error = _("missing +");
4015 return;
4016 }
4017
4018 if (s7_end_of_line (str) == (int) s7_FAIL)
4019 return;
4020 }
4021 else
4022 {
4023 s7_inst.error = _("missing ]");
4024 return;
4025 }
4026 }
4027 else
4028 {
4029 s7_inst.error = s7_BAD_ARGS;
4030 return;
4031 }
4032 }
4033 }
4034
4035 /* Handle alw/asw. */
4036
4037 static void
4038 s7_do_ldst_atomic (char *str)
4039 {
4040 if (s7_university_version == 1)
4041 {
4042 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4043 return;
4044 }
4045
4046 s7_skip_whitespace (str);
4047
4048 if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4049 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4050 {
4051 return;
4052 }
4053 else
4054 {
4055
4056 s7_skip_whitespace (str);
4057 if (*str++ == '[')
4058 {
4059 int reg;
4060
4061 s7_skip_whitespace (str);
4062 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4063 {
4064 return;
4065 }
4066
4067 s7_skip_whitespace (str);
4068 if (*str++ != ']')
4069 {
4070 s7_inst.error = _("missing ]");
4071 return;
4072 }
4073
4074 s7_end_of_line (str);
4075 }
4076 else
4077 s7_inst.error = s7_BAD_ARGS;
4078 }
4079 }
4080
4081 static void
4082 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4083 int fix_num ATTRIBUTE_UNUSED,
4084 struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4085 symbolS *add_symbol)
4086 {
4087 int i;
4088 char *p;
4089 fixS *fixp = NULL;
4090 fixS *cur_fixp = NULL;
4091 long where;
4092 struct s7_score_it inst_main;
4093
4094 memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4095
4096 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4097 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4098 inst_main.type = Insn_PIC;
4099
4100 for (i = 0; i < var_num; i++)
4101 {
4102 inst_main.relax_size += var_insts[i].size;
4103 var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4104 s7_GET_INSN_CLASS (var_insts[i].type));
4105 }
4106
4107 /* Check data dependency. */
4108 s7_handle_dependency (&inst_main);
4109
4110 /* Start a new frag if frag_now is not empty. */
4111 if (frag_now_fix () != 0)
4112 {
4113 if (!frag_now->tc_frag_data.is_insn)
4114 {
4115 frag_wane (frag_now);
4116 }
4117 frag_new (0);
4118 }
4119 frag_grow (20);
4120
4121 /* Write fr_fix part. */
4122 p = frag_more (inst_main.size);
4123 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4124
4125 if (inst_main.reloc.type != BFD_RELOC_NONE)
4126 fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4127 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4128
4129 frag_now->tc_frag_data.fixp = fixp;
4130 cur_fixp = frag_now->tc_frag_data.fixp;
4131
4132 #ifdef OBJ_ELF
4133 dwarf2_emit_insn (inst_main.size);
4134 #endif
4135
4136 where = p - frag_now->fr_literal + inst_main.size;
4137 for (i = 0; i < var_num; i++)
4138 {
4139 if (i > 0)
4140 where += var_insts[i - 1].size;
4141
4142 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4143 {
4144 fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4145 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4146 var_insts[i].reloc.type);
4147 if (fixp)
4148 {
4149 if (cur_fixp)
4150 {
4151 cur_fixp->fx_next = fixp;
4152 cur_fixp = cur_fixp->fx_next;
4153 }
4154 else
4155 {
4156 frag_now->tc_frag_data.fixp = fixp;
4157 cur_fixp = frag_now->tc_frag_data.fixp;
4158 }
4159 }
4160 }
4161 }
4162
4163 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4164 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4165 0, inst_main.size, 0), add_symbol, 0, NULL);
4166
4167 /* Write fr_var part.
4168 no calling s7_gen_insn_frag, no fixS will be generated. */
4169 for (i = 0; i < var_num; i++)
4170 {
4171 s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4172 p += var_insts[i].size;
4173 }
4174 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4175 s7_inst.bwarn = -1;
4176 }
4177
4178 /* Build a relax frag for la instruction when generating s7_PIC,
4179 external symbol first and local symbol second. */
4180
4181 static void
4182 s7_build_la_pic (int reg_rd, expressionS exp)
4183 {
4184 symbolS *add_symbol = exp.X_add_symbol;
4185 offsetT add_number = exp.X_add_number;
4186 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4187 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4188 int fix_num = 0;
4189 int var_num = 0;
4190 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4191 int r1_bak;
4192
4193 r1_bak = s7_nor1;
4194 s7_nor1 = 0;
4195
4196 if (add_number == 0)
4197 {
4198 fix_num = 1;
4199 var_num = 2;
4200
4201 /* For an external symbol, only one insn is generated;
4202 For a local symbol, two insns are generated. */
4203 /* Fix part
4204 For an external symbol: lw rD, <sym>($gp)
4205 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
4206 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4207 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4208 return;
4209
4210 if (reg_rd == s7_PIC_CALL_REG)
4211 s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4212 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4213
4214 /* Var part
4215 For a local symbol :
4216 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4217 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4218 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4219 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4220 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4221 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4222 return;
4223
4224 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4225 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4226 }
4227 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4228 {
4229 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4230 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4231 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4232 return;
4233
4234 /* Insn 2 */
4235 fix_num = 1;
4236 var_num = 1;
4237 /* Fix part
4238 For an external symbol: addi rD, <constant> */
4239 sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4240 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4241 return;
4242
4243 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4244
4245 /* Var part
4246 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
4247 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number);
4248 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4249 return;
4250
4251 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4252 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4253 }
4254 else
4255 {
4256 int hi = (add_number >> 16) & 0x0000FFFF;
4257 int lo = add_number & 0x0000FFFF;
4258
4259 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4260 sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4261 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4262 return;
4263
4264 /* Insn 2 */
4265 fix_num = 1;
4266 var_num = 1;
4267 /* Fix part
4268 For an external symbol: ldis r1, HI%<constant> */
4269 sprintf (tmp, "ldis r1, %d", hi);
4270 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4271 return;
4272
4273 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4274
4275 /* Var part
4276 For a local symbol: ldis r1, HI%<constant>
4277 but, if lo is outof 16 bit, make hi plus 1 */
4278 if ((lo < -0x8000) || (lo > 0x7fff))
4279 {
4280 hi += 1;
4281 }
4282 sprintf (tmp, "ldis_pic r1, %d", hi);
4283 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4284 return;
4285
4286 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4287 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4288
4289 /* Insn 3 */
4290 fix_num = 1;
4291 var_num = 1;
4292 /* Fix part
4293 For an external symbol: ori r1, LO%<constant> */
4294 sprintf (tmp, "ori r1, %d", lo);
4295 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4296 return;
4297
4298 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4299
4300 /* Var part
4301 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4302 sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
4303 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4304 return;
4305
4306 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4307 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4308
4309 /* Insn 4: add rD, rD, r1 */
4310 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4311 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4312 return;
4313
4314 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4315 s7_inst.bwarn = -1;
4316 }
4317
4318 s7_nor1 = r1_bak;
4319 }
4320
4321 /* Handle la. */
4322
4323 static void
4324 s7_do_macro_la_rdi32 (char *str)
4325 {
4326 int reg_rd;
4327
4328 s7_skip_whitespace (str);
4329 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4330 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4331 {
4332 return;
4333 }
4334 else
4335 {
4336 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4337 char *keep_data = str;
4338
4339 /* Check immediate value. */
4340 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4341 {
4342 s7_inst.error = _("expression error");
4343 return;
4344 }
4345 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4346 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4347 {
4348 s7_inst.error = _("value not in range [0, 0xffffffff]");
4349 return;
4350 }
4351
4352 /* Reset str. */
4353 str = keep_data;
4354
4355 /* la rd, simm16. */
4356 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4357 {
4358 s7_end_of_line (str);
4359 return;
4360 }
4361 /* la rd, imm32 or la rd, label. */
4362 else
4363 {
4364 s7_SET_INSN_ERROR (NULL);
4365 str = keep_data;
4366 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4367 || (s7_end_of_line (str) == (int) s7_FAIL))
4368 {
4369 return;
4370 }
4371 else
4372 {
4373 if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4374 {
4375 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4376 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4377 return;
4378
4379 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4380 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4381 return;
4382 }
4383 else
4384 {
4385 gas_assert (s7_inst.reloc.exp.X_add_symbol);
4386 s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4387 }
4388
4389 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4390 s7_inst.bwarn = -1;
4391 }
4392 }
4393 }
4394 }
4395
4396 /* Handle li. */
4397
4398 static void
4399 s7_do_macro_li_rdi32 (char *str)
4400 {
4401 int reg_rd;
4402
4403 s7_skip_whitespace (str);
4404 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4405 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4406 {
4407 return;
4408 }
4409 else
4410 {
4411 char *keep_data = str;
4412
4413 /* Check immediate value. */
4414 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4415 {
4416 s7_inst.error = _("expression error");
4417 return;
4418 }
4419 else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4420 && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4421 {
4422 s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4423 return;
4424 }
4425
4426 /* Reset str. */
4427 str = keep_data;
4428
4429 /* li rd, simm16. */
4430 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4431 {
4432 s7_end_of_line (str);
4433 return;
4434 }
4435 /* li rd, imm32. */
4436 else
4437 {
4438 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4439
4440 str = keep_data;
4441
4442 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4443 || (s7_end_of_line (str) == (int) s7_FAIL))
4444 {
4445 return;
4446 }
4447 else if (s7_inst.reloc.exp.X_add_symbol)
4448 {
4449 s7_inst.error = _("li rd label isn't correct instruction form");
4450 return;
4451 }
4452 else
4453 {
4454 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4455
4456 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4457 return;
4458 else
4459 {
4460 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4461 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4462 return;
4463
4464 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4465 s7_inst.bwarn = -1;
4466 }
4467 }
4468 }
4469 }
4470 }
4471
4472 /* Handle mul/mulu/div/divu/rem/remu. */
4473
4474 static void
4475 s7_do_macro_mul_rdrsrs (char *str)
4476 {
4477 int reg_rd;
4478 int reg_rs1;
4479 int reg_rs2;
4480 char *backupstr;
4481 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4482
4483 if (s7_university_version == 1)
4484 as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4485
4486 strcpy (append_str, str);
4487 backupstr = append_str;
4488 s7_skip_whitespace (backupstr);
4489 if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4490 || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4491 || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4492 {
4493 s7_inst.error = s7_BAD_ARGS;
4494 return;
4495 }
4496
4497 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4498 {
4499 /* rem/remu rA, rB is error format. */
4500 if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4501 {
4502 s7_SET_INSN_ERROR (s7_BAD_ARGS);
4503 }
4504 else
4505 {
4506 s7_SET_INSN_ERROR (NULL);
4507 s7_do_rsrs (str);
4508 }
4509 return;
4510 }
4511 else
4512 {
4513 s7_SET_INSN_ERROR (NULL);
4514 if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4515 || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4516 {
4517 return;
4518 }
4519 else
4520 {
4521 char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4522
4523 if (strcmp (s7_inst.name, "rem") == 0)
4524 {
4525 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4526 sprintf (append_str1, "mfceh r%d", reg_rd);
4527 }
4528 else if (strcmp (s7_inst.name, "remu") == 0)
4529 {
4530 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4531 sprintf (append_str1, "mfceh r%d", reg_rd);
4532 }
4533 else
4534 {
4535 sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4536 sprintf (append_str1, "mfcel r%d", reg_rd);
4537 }
4538
4539 /* Output mul/mulu or div/divu or rem/remu. */
4540 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4541 return;
4542
4543 /* Output mfcel or mfceh. */
4544 if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4545 return;
4546
4547 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4548 s7_inst.bwarn = -1;
4549 }
4550 }
4551 }
4552
4553 static void
4554 s7_exp_macro_ldst_abs (char *str)
4555 {
4556 int reg_rd;
4557 char *backupstr, *tmp;
4558 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4559 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4560 struct s7_score_it inst_backup;
4561 int r1_bak = 0;
4562
4563 r1_bak = s7_nor1;
4564 s7_nor1 = 0;
4565 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4566
4567 strcpy (verifystr, str);
4568 backupstr = verifystr;
4569 s7_skip_whitespace (backupstr);
4570 if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4571 return;
4572
4573 tmp = backupstr;
4574 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4575 return;
4576
4577 backupstr = tmp;
4578 sprintf (append_str, "li r1 %s", backupstr);
4579 s7_append_insn (append_str, TRUE);
4580
4581 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4582 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4583 s7_do_ldst_insn (append_str);
4584
4585 s7_nor1 = r1_bak;
4586 }
4587
4588 static int
4589 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4590 {
4591 if (sym == NULL)
4592 return 0;
4593 else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4594 {
4595 const char *symname;
4596 const char *segname;
4597
4598 /* Find out whether this symbol can be referenced off the $gp
4599 register. It can be if it is smaller than the -G size or if
4600 it is in the .sdata or .sbss section. Certain symbols can
4601 not be referenced off the $gp, although it appears as though
4602 they can. */
4603 symname = S_GET_NAME (sym);
4604 if (symname != NULL
4605 && (strcmp (symname, "eprol") == 0
4606 || strcmp (symname, "etext") == 0
4607 || strcmp (symname, "_gp") == 0
4608 || strcmp (symname, "edata") == 0
4609 || strcmp (symname, "_fbss") == 0
4610 || strcmp (symname, "_fdata") == 0
4611 || strcmp (symname, "_ftext") == 0
4612 || strcmp (symname, "end") == 0
4613 || strcmp (symname, GP_DISP_LABEL) == 0))
4614 {
4615 return 1;
4616 }
4617 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4618 /* We must defer this decision until after the whole file has been read,
4619 since there might be a .extern after the first use of this symbol. */
4620 || (before_relaxing
4621 && S_GET_VALUE (sym) == 0)
4622 || (S_GET_VALUE (sym) != 0
4623 && S_GET_VALUE (sym) <= s7_g_switch_value)))
4624 {
4625 return 0;
4626 }
4627
4628 segname = segment_name (S_GET_SEGMENT (sym));
4629 return (strcmp (segname, ".sdata") != 0
4630 && strcmp (segname, ".sbss") != 0
4631 && strncmp (segname, ".sdata.", 7) != 0
4632 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4633 }
4634 /* We are not optimizing for the $gp register. */
4635 else
4636 return 1;
4637 }
4638
4639 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4640 external symbol first and local symbol second. */
4641
4642 static void
4643 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4644 {
4645 symbolS *add_symbol = exp.X_add_symbol;
4646 int add_number = exp.X_add_number;
4647 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4648 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4649 int fix_num = 0;
4650 int var_num = 0;
4651 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4652 int r1_bak;
4653
4654 r1_bak = s7_nor1;
4655 s7_nor1 = 0;
4656
4657 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4658 {
4659 fix_num = 1;
4660 var_num = 2;
4661
4662 /* For an external symbol, two insns are generated;
4663 For a local symbol, three insns are generated. */
4664 /* Fix part
4665 For an external symbol: lw rD, <sym>($gp)
4666 (BFD_RELOC_SCORE_GOT15) */
4667 sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4668 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4669 return;
4670
4671 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4672
4673 /* Var part
4674 For a local symbol :
4675 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4676 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4677 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4678 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4679 sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4680 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4681 return;
4682
4683 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4684 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4685
4686 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4687 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4688 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4689 return;
4690
4691 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4692 s7_inst.bwarn = -1;
4693 }
4694 else
4695 {
4696 s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4697 return;
4698 }
4699
4700 s7_nor1 = r1_bak;
4701 }
4702
4703 static void
4704 s7_do_macro_ldst_label (char *str)
4705 {
4706 int i;
4707 int ldst_gp_p = 0;
4708 int reg_rd;
4709 int r1_bak;
4710 char *backup_str;
4711 char *label_str;
4712 char *absolute_value;
4713 char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4714 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4715 struct s7_score_it inst_backup;
4716 struct s7_score_it inst_expand[3];
4717 struct s7_score_it inst_main;
4718
4719 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4720 strcpy (verifystr, str);
4721 backup_str = verifystr;
4722
4723 s7_skip_whitespace (backup_str);
4724 if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4725 return;
4726
4727 if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4728 return;
4729
4730 label_str = backup_str;
4731
4732 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4733 if (*backup_str == '[')
4734 {
4735 s7_inst.type = Rd_rvalueRs_preSI12;
4736 s7_do_ldst_insn (str);
4737 return;
4738 }
4739
4740 /* Ld/st rD, imm. */
4741 absolute_value = backup_str;
4742 s7_inst.type = Rd_rvalueRs_SI15;
4743
4744 if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4745 {
4746 s7_inst.error = _("expression error");
4747 return;
4748 }
4749 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4750 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4751 {
4752 s7_inst.error = _("value not in range [0, 0x7fffffff]");
4753 return;
4754 }
4755 else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4756 {
4757 s7_inst.error = _("end on line error");
4758 return;
4759 }
4760 else
4761 {
4762 if (s7_inst.reloc.exp.X_add_symbol == 0)
4763 {
4764 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4765 s7_exp_macro_ldst_abs (str);
4766 return;
4767 }
4768 }
4769
4770 /* Ld/st rD, label. */
4771 s7_inst.type = Rd_rvalueRs_SI15;
4772 backup_str = absolute_value;
4773 if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4774 || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4775 {
4776 return;
4777 }
4778 else
4779 {
4780 if (s7_inst.reloc.exp.X_add_symbol == 0)
4781 {
4782 if (!s7_inst.error)
4783 s7_inst.error = s7_BAD_ARGS;
4784
4785 return;
4786 }
4787
4788 if (s7_score_pic == s7_PIC)
4789 {
4790 int ldst_idx = 0;
4791 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4792 s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4793 s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4794 return;
4795 }
4796 else
4797 {
4798 if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4799 && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4800 && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4801 {
4802 int ldst_idx = 0;
4803
4804 /* Assign the real opcode. */
4805 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4806 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4807 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4808 s7_inst.instruction |= reg_rd << 20;
4809 s7_inst.instruction |= s7_GP << 15;
4810 s7_inst.relax_inst = 0x8000;
4811 s7_inst.relax_size = 0;
4812 ldst_gp_p = 1;
4813 }
4814 }
4815 }
4816
4817 /* Backup s7_inst. */
4818 memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4819 r1_bak = s7_nor1;
4820 s7_nor1 = 0;
4821
4822 /* Determine which instructions should be output. */
4823 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4824 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4825 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4826
4827 /* Generate three instructions.
4828 la r1, label
4829 ld/st rd, [r1, 0] */
4830 for (i = 0; i < 3; i++)
4831 {
4832 if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4833 return;
4834
4835 memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4836 }
4837
4838 if (ldst_gp_p)
4839 {
4840 char *p;
4841
4842 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4843 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4844 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4845 inst_main.type = Insn_GP;
4846
4847 for (i = 0; i < 3; i++)
4848 inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4849 , s7_GET_INSN_CLASS (inst_expand[i].type));
4850
4851 /* Check data dependency. */
4852 s7_handle_dependency (&inst_main);
4853
4854 /* Start a new frag if frag_now is not empty. */
4855 if (frag_now_fix () != 0)
4856 {
4857 if (!frag_now->tc_frag_data.is_insn)
4858 frag_wane (frag_now);
4859
4860 frag_new (0);
4861 }
4862 frag_grow (20);
4863
4864 /* Write fr_fix part. */
4865 p = frag_more (inst_main.size);
4866 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4867
4868 if (inst_main.reloc.type != BFD_RELOC_NONE)
4869 {
4870 s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4871 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4872 }
4873
4874 #ifdef OBJ_ELF
4875 dwarf2_emit_insn (inst_main.size);
4876 #endif
4877
4878 /* s7_GP instruction can not do optimization, only can do relax between
4879 1 instruction and 3 instructions. */
4880 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4881 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4882 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4883
4884 /* Write fr_var part.
4885 no calling s7_gen_insn_frag, no fixS will be generated. */
4886 s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4887 p += inst_expand[0].size;
4888 s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4889 p += inst_expand[1].size;
4890 s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4891 }
4892 else
4893 {
4894 s7_gen_insn_frag (&inst_expand[0], NULL);
4895 s7_gen_insn_frag (&inst_expand[1], NULL);
4896 s7_gen_insn_frag (&inst_expand[2], NULL);
4897 }
4898 s7_nor1 = r1_bak;
4899
4900 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4901 s7_inst.bwarn = -1;
4902 }
4903
4904 static void
4905 s7_do_lw_pic (char *str)
4906 {
4907 int reg_rd;
4908
4909 s7_skip_whitespace (str);
4910 if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4911 || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4912 || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4913 || (s7_end_of_line (str) == (int) s7_FAIL))
4914 {
4915 return;
4916 }
4917 else
4918 {
4919 if (s7_inst.reloc.exp.X_add_symbol == 0)
4920 {
4921 if (!s7_inst.error)
4922 s7_inst.error = s7_BAD_ARGS;
4923
4924 return;
4925 }
4926
4927 s7_inst.instruction |= s7_GP << 15;
4928 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4929 }
4930 }
4931
4932 static void
4933 s7_do_empty (char *str)
4934 {
4935 str = str;
4936 if (s7_university_version == 1)
4937 {
4938 if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4939 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4940 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4941 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4942 {
4943 s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4944 return;
4945 }
4946 }
4947 if (s7_end_of_line (str) == (int) s7_FAIL)
4948 return;
4949
4950 if (s7_inst.relax_inst != 0x8000)
4951 {
4952 if (s7_inst.type == NO_OPD)
4953 {
4954 s7_inst.relax_size = 2;
4955 }
4956 else
4957 {
4958 s7_inst.relax_size = 4;
4959 }
4960 }
4961 }
4962
4963 static void
4964 s7_do_jump (char *str)
4965 {
4966 char *save_in;
4967
4968 s7_skip_whitespace (str);
4969 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4970 || s7_end_of_line (str) == (int) s7_FAIL)
4971 return;
4972
4973 if (s7_inst.reloc.exp.X_add_symbol == 0)
4974 {
4975 s7_inst.error = _("lacking label ");
4976 return;
4977 }
4978
4979 if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4980 && s7_inst.reloc.exp.X_add_number <= 16777215))
4981 {
4982 s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4983 return;
4984 }
4985
4986 save_in = input_line_pointer;
4987 input_line_pointer = str;
4988 s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4989 s7_inst.reloc.pc_rel = 1;
4990 input_line_pointer = save_in;
4991 }
4992
4993 static void
4994 s7_do16_jump (char *str)
4995 {
4996 s7_skip_whitespace (str);
4997 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4998 || s7_end_of_line (str) == (int) s7_FAIL)
4999 {
5000 return;
5001 }
5002 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5003 {
5004 s7_inst.error = _("lacking label ");
5005 return;
5006 }
5007 else if (!(s7_inst.reloc.exp.X_add_number >= 0
5008 && s7_inst.reloc.exp.X_add_number <= 4095))
5009 {
5010 s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5011 return;
5012 }
5013
5014 s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5015 s7_inst.reloc.pc_rel = 1;
5016 }
5017
5018 static void
5019 s7_do_branch (char *str)
5020 {
5021 unsigned long abs_value = 0;
5022
5023 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5024 || s7_end_of_line (str) == (int) s7_FAIL)
5025 {
5026 return;
5027 }
5028 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5029 {
5030 s7_inst.error = _("lacking label ");
5031 return;
5032 }
5033 else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5034 && s7_inst.reloc.exp.X_add_number <= 524287))
5035 {
5036 s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5037 return;
5038 }
5039
5040 s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5041 s7_inst.reloc.pc_rel = 1;
5042
5043 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
5044 s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5045
5046 /* Compute 16 bit branch instruction. */
5047 if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5048 {
5049 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5050 s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5051 s7_inst.relax_size = 2;
5052 }
5053 else
5054 {
5055 s7_inst.relax_inst = 0x8000;
5056 }
5057 }
5058
5059 static void
5060 s7_do16_branch (char *str)
5061 {
5062 if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5063 || s7_end_of_line (str) == (int) s7_FAIL))
5064 {
5065 ;
5066 }
5067 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5068 {
5069 s7_inst.error = _("lacking label");
5070 }
5071 else if (!(s7_inst.reloc.exp.X_add_number >= -512
5072 && s7_inst.reloc.exp.X_add_number <= 511))
5073 {
5074 s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5075 }
5076 else
5077 {
5078 s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5079 s7_inst.reloc.pc_rel = 1;
5080 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5081 }
5082 }
5083
5084 /* Iterate over the base tables to create the instruction patterns. */
5085
5086 static void
5087 s7_build_score_ops_hsh (void)
5088 {
5089 unsigned int i;
5090 static struct obstack insn_obstack;
5091
5092 obstack_begin (&insn_obstack, 4000);
5093 for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5094 {
5095 const struct s7_asm_opcode *insn = s7_score_insns + i;
5096 unsigned len = strlen (insn->template_name);
5097 struct s7_asm_opcode *new_opcode;
5098 char *template_name;
5099 new_opcode = (struct s7_asm_opcode *)
5100 obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5101 template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5102
5103 strcpy (template_name, insn->template_name);
5104 new_opcode->template_name = template_name;
5105 new_opcode->parms = insn->parms;
5106 new_opcode->value = insn->value;
5107 new_opcode->relax_value = insn->relax_value;
5108 new_opcode->type = insn->type;
5109 new_opcode->bitmask = insn->bitmask;
5110 hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5111 (void *) new_opcode);
5112 }
5113 }
5114
5115 static void
5116 s7_build_dependency_insn_hsh (void)
5117 {
5118 unsigned int i;
5119 static struct obstack dependency_obstack;
5120
5121 obstack_begin (&dependency_obstack, 4000);
5122 for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5123 {
5124 const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5125 unsigned len = strlen (tmp->insn_name);
5126 struct s7_insn_to_dependency *new_i2d;
5127
5128 new_i2d = (struct s7_insn_to_dependency *)
5129 obstack_alloc (&dependency_obstack,
5130 sizeof (struct s7_insn_to_dependency));
5131 new_i2d->insn_name = (char *) obstack_alloc (&dependency_obstack,
5132 len + 1);
5133
5134 strcpy (new_i2d->insn_name, tmp->insn_name);
5135 new_i2d->type = tmp->type;
5136 hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5137 (void *) new_i2d);
5138 }
5139 }
5140
5141 static valueT
5142 s7_md_chars_to_number (char *buf, int n)
5143 {
5144 valueT result = 0;
5145 unsigned char *where = (unsigned char *) buf;
5146
5147 if (target_big_endian)
5148 {
5149 while (n--)
5150 {
5151 result <<= 8;
5152 result |= (*where++ & 255);
5153 }
5154 }
5155 else
5156 {
5157 while (n--)
5158 {
5159 result <<= 8;
5160 result |= (where[n] & 255);
5161 }
5162 }
5163
5164 return result;
5165 }
5166
5167 /* Return true if the given symbol should be considered local for s7_PIC. */
5168
5169 static bfd_boolean
5170 s7_pic_need_relax (symbolS *sym, asection *segtype)
5171 {
5172 asection *symsec;
5173 bfd_boolean linkonce;
5174
5175 /* Handle the case of a symbol equated to another symbol. */
5176 while (symbol_equated_reloc_p (sym))
5177 {
5178 symbolS *n;
5179
5180 /* It's possible to get a loop here in a badly written
5181 program. */
5182 n = symbol_get_value_expression (sym)->X_add_symbol;
5183 if (n == sym)
5184 break;
5185 sym = n;
5186 }
5187
5188 symsec = S_GET_SEGMENT (sym);
5189
5190 /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5191 linkonce = FALSE;
5192 if (symsec != segtype && ! S_IS_LOCAL (sym))
5193 {
5194 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5195 linkonce = TRUE;
5196
5197 /* The GNU toolchain uses an extension for ELF: a section
5198 beginning with the magic string .gnu.linkonce is a linkonce
5199 section. */
5200 if (strncmp (segment_name (symsec), ".gnu.linkonce",
5201 sizeof ".gnu.linkonce" - 1) == 0)
5202 linkonce = TRUE;
5203 }
5204
5205 /* This must duplicate the test in adjust_reloc_syms. */
5206 return (symsec != &bfd_und_section
5207 && symsec != &bfd_abs_section
5208 && ! bfd_is_com_section (symsec)
5209 && !linkonce
5210 #ifdef OBJ_ELF
5211 /* A global or weak symbol is treated as external. */
5212 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5213 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5214 #endif
5215 );
5216 }
5217
5218 static int
5219 s7_judge_size_before_relax (fragS * fragp, asection *sec)
5220 {
5221 int change = 0;
5222
5223 if (s7_score_pic == s7_NO_PIC)
5224 change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5225 else
5226 change = s7_pic_need_relax (fragp->fr_symbol, sec);
5227
5228 if (change == 1)
5229 {
5230 /* Only at the first time determining whether s7_GP instruction relax should be done,
5231 return the difference between insntruction size and instruction relax size. */
5232 if (fragp->fr_opcode == NULL)
5233 {
5234 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
5235 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
5236 return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
5237 }
5238 }
5239
5240 return 0;
5241 }
5242
5243 static int
5244 s7_b32_relax_to_b16 (fragS * fragp)
5245 {
5246 int grows = 0;
5247 int relaxable_p = 0;
5248 int r_old;
5249 int r_new;
5250 int frag_addr = fragp->fr_address + fragp->insn_addr;
5251
5252 addressT symbol_address = 0;
5253 symbolS *s;
5254 offsetT offset;
5255 unsigned long value;
5256 unsigned long abs_value;
5257
5258 /* FIXME : here may be able to modify better .
5259 I don't know how to get the fragp's section ,
5260 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5261 is different from the symbol's. */
5262
5263 r_old = s7_RELAX_OLD (fragp->fr_subtype);
5264 r_new = s7_RELAX_NEW (fragp->fr_subtype);
5265 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5266
5267 s = fragp->fr_symbol;
5268 /* b/bl immediate */
5269 if (s == NULL)
5270 frag_addr = 0;
5271 else
5272 {
5273 if (s->bsym != 0)
5274 symbol_address = (addressT) s->sy_frag->fr_address;
5275 }
5276
5277 value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5278
5279 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
5280 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
5281 if ((offset & 0x80000) == 0x80000)
5282 offset |= 0xfff00000;
5283
5284 abs_value = offset + symbol_address - frag_addr;
5285 if ((abs_value & 0x80000000) == 0x80000000)
5286 abs_value = 0xffffffff - abs_value + 1;
5287
5288 /* Relax branch 32 to branch 16. */
5289 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
5290 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
5291 {
5292 /* do nothing. */
5293 }
5294 else
5295 {
5296 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
5297 fragp->fr_opcode = NULL;
5298 fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
5299 }
5300
5301 return grows;
5302 }
5303
5304 static void
5305 s7_parse_pce_inst (char *insnstr)
5306 {
5307 char c;
5308 char *p;
5309 char *q;
5310 char first[s7_MAX_LITERAL_POOL_SIZE];
5311 char second[s7_MAX_LITERAL_POOL_SIZE];
5312 struct s7_score_it pec_part_1;
5313
5314 /* Get first part string of PCE. */
5315 p = strstr (insnstr, "||");
5316 c = *p;
5317 *p = '\0';
5318 sprintf (first, "%s", insnstr);
5319
5320 /* Get second part string of PCE. */
5321 *p = c;
5322 p += 2;
5323 sprintf (second, "%s", p);
5324
5325 s7_parse_16_32_inst (first, FALSE);
5326 if (s7_inst.error)
5327 return;
5328
5329 memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5330
5331 q = second;
5332 while (q && *q)
5333 {
5334 *q = TOLOWER (*q);
5335 q++;
5336 }
5337
5338 s7_parse_16_32_inst (second, FALSE);
5339 if (s7_inst.error)
5340 return;
5341
5342 if ( ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
5343 || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
5344 || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
5345 {
5346 s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5347 sprintf (s7_inst.str, insnstr);
5348 return;
5349 }
5350
5351 if (!s7_inst.error)
5352 s7_gen_insn_frag (&pec_part_1, &s7_inst);
5353 }
5354
5355 \f
5356
5357 static void
5358 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5359 {
5360 int i = 0;
5361 int len = strlen (r->name) + 2;
5362 char *buf = xmalloc (len);
5363 char *buf2 = xmalloc (len);
5364
5365 strcpy (buf + i, r->name);
5366 for (i = 0; buf[i]; i++)
5367 {
5368 buf2[i] = TOUPPER (buf[i]);
5369 }
5370 buf2[i] = '\0';
5371
5372 hash_insert (htab, buf, (void *) r);
5373 hash_insert (htab, buf2, (void *) r);
5374 }
5375
5376 static void
5377 s7_build_reg_hsh (struct s7_reg_map *map)
5378 {
5379 const struct s7_reg_entry *r;
5380
5381 if ((map->htab = hash_new ()) == NULL)
5382 {
5383 as_fatal (_("virtual memory exhausted"));
5384 }
5385 for (r = map->names; r->name != NULL; r++)
5386 {
5387 s7_insert_reg (r, map->htab);
5388 }
5389 }
5390
5391 \f
5392
5393 /* If we change section we must dump the literal pool first. */
5394 static void
5395 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5396 {
5397 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5398 demand_empty_rest_of_line ();
5399 }
5400
5401 static void
5402 s7_s_score_text (int ignore)
5403 {
5404 obj_elf_text (ignore);
5405 record_alignment (now_seg, 2);
5406 }
5407
5408 static void
5409 s7_s_section (int ignore)
5410 {
5411 obj_elf_section (ignore);
5412 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5413 record_alignment (now_seg, 2);
5414
5415 }
5416
5417 static void
5418 s7_s_change_sec (int sec)
5419 {
5420 segT seg;
5421
5422 #ifdef OBJ_ELF
5423 /* The ELF backend needs to know that we are changing sections, so
5424 that .previous works correctly. We could do something like check
5425 for an obj_section_change_hook macro, but that might be confusing
5426 as it would not be appropriate to use it in the section changing
5427 functions in read.c, since obj-elf.c intercepts those. FIXME:
5428 This should be cleaner, somehow. */
5429 obj_elf_section_change_hook ();
5430 #endif
5431 switch (sec)
5432 {
5433 case 'r':
5434 seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5435 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | 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 case 's':
5441 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5442 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5443 if (strcmp (TARGET_OS, "elf") != 0)
5444 record_alignment (seg, 4);
5445 demand_empty_rest_of_line ();
5446 break;
5447 }
5448 }
5449
5450 static void
5451 s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5452 {
5453 long mask, off;
5454
5455 if (s7_cur_proc_ptr == NULL)
5456 {
5457 as_warn (_(".mask outside of .ent"));
5458 demand_empty_rest_of_line ();
5459 return;
5460 }
5461 if (get_absolute_expression_and_terminator (&mask) != ',')
5462 {
5463 as_warn (_("Bad .mask directive"));
5464 --input_line_pointer;
5465 demand_empty_rest_of_line ();
5466 return;
5467 }
5468 off = get_absolute_expression ();
5469 s7_cur_proc_ptr->reg_mask = mask;
5470 s7_cur_proc_ptr->reg_offset = off;
5471 demand_empty_rest_of_line ();
5472 }
5473
5474 static symbolS *
5475 s7_get_symbol (void)
5476 {
5477 int c;
5478 char *name;
5479 symbolS *p;
5480
5481 name = input_line_pointer;
5482 c = get_symbol_end ();
5483 p = (symbolS *) symbol_find_or_make (name);
5484 *input_line_pointer = c;
5485 return p;
5486 }
5487
5488 static long
5489 s7_get_number (void)
5490 {
5491 int negative = 0;
5492 long val = 0;
5493
5494 if (*input_line_pointer == '-')
5495 {
5496 ++input_line_pointer;
5497 negative = 1;
5498 }
5499 if (!ISDIGIT (*input_line_pointer))
5500 as_bad (_("expected simple number"));
5501 if (input_line_pointer[0] == '0')
5502 {
5503 if (input_line_pointer[1] == 'x')
5504 {
5505 input_line_pointer += 2;
5506 while (ISXDIGIT (*input_line_pointer))
5507 {
5508 val <<= 4;
5509 val |= hex_value (*input_line_pointer++);
5510 }
5511 return negative ? -val : val;
5512 }
5513 else
5514 {
5515 ++input_line_pointer;
5516 while (ISDIGIT (*input_line_pointer))
5517 {
5518 val <<= 3;
5519 val |= *input_line_pointer++ - '0';
5520 }
5521 return negative ? -val : val;
5522 }
5523 }
5524 if (!ISDIGIT (*input_line_pointer))
5525 {
5526 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5527 as_warn (_("invalid number"));
5528 return -1;
5529 }
5530 while (ISDIGIT (*input_line_pointer))
5531 {
5532 val *= 10;
5533 val += *input_line_pointer++ - '0';
5534 }
5535 return negative ? -val : val;
5536 }
5537
5538 /* The .aent and .ent directives. */
5539
5540 static void
5541 s7_s_score_ent (int aent)
5542 {
5543 symbolS *symbolP;
5544 int maybe_text;
5545
5546 symbolP = s7_get_symbol ();
5547 if (*input_line_pointer == ',')
5548 ++input_line_pointer;
5549 SKIP_WHITESPACE ();
5550 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5551 s7_get_number ();
5552
5553 #ifdef BFD_ASSEMBLER
5554 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5555 maybe_text = 1;
5556 else
5557 maybe_text = 0;
5558 #else
5559 if (now_seg != data_section && now_seg != bss_section)
5560 maybe_text = 1;
5561 else
5562 maybe_text = 0;
5563 #endif
5564 if (!maybe_text)
5565 as_warn (_(".ent or .aent not in text section."));
5566 if (!aent && s7_cur_proc_ptr)
5567 as_warn (_("missing .end"));
5568 if (!aent)
5569 {
5570 s7_cur_proc_ptr = &s7_cur_proc;
5571 s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5572 s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5573 s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5574 s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5575 s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5576 s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5577 s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5578 s7_cur_proc_ptr->isym = symbolP;
5579 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5580 ++s7_numprocs;
5581 if (debug_type == DEBUG_STABS)
5582 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5583 }
5584 demand_empty_rest_of_line ();
5585 }
5586
5587 static void
5588 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5589 {
5590 char *backupstr;
5591 char str[30];
5592 long val;
5593 int i = 0;
5594
5595 backupstr = input_line_pointer;
5596
5597 #ifdef OBJ_ELF
5598 if (s7_cur_proc_ptr == NULL)
5599 {
5600 as_warn (_(".frame outside of .ent"));
5601 demand_empty_rest_of_line ();
5602 return;
5603 }
5604 s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5605 SKIP_WHITESPACE ();
5606 s7_skip_past_comma (&backupstr);
5607 while (*backupstr != ',')
5608 {
5609 str[i] = *backupstr;
5610 i++;
5611 backupstr++;
5612 }
5613 str[i] = '\0';
5614 val = atoi (str);
5615
5616 SKIP_WHITESPACE ();
5617 s7_skip_past_comma (&backupstr);
5618 s7_cur_proc_ptr->frame_offset = val;
5619 s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5620
5621 SKIP_WHITESPACE ();
5622 s7_skip_past_comma (&backupstr);
5623 i = 0;
5624 while (*backupstr != '\n')
5625 {
5626 str[i] = *backupstr;
5627 i++;
5628 backupstr++;
5629 }
5630 str[i] = '\0';
5631 val = atoi (str);
5632 s7_cur_proc_ptr->leaf = val;
5633 SKIP_WHITESPACE ();
5634 s7_skip_past_comma (&backupstr);
5635
5636 #endif /* OBJ_ELF */
5637 while (input_line_pointer != backupstr)
5638 input_line_pointer++;
5639 }
5640
5641 /* The .end directive. */
5642
5643 static void
5644 s7_s_score_end (int x ATTRIBUTE_UNUSED)
5645 {
5646 symbolS *p;
5647 int maybe_text;
5648
5649 /* Generate a .pdr section. */
5650 segT saved_seg = now_seg;
5651 subsegT saved_subseg = now_subseg;
5652 valueT dot;
5653 expressionS exp;
5654 char *fragp;
5655
5656 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5657 {
5658 p = s7_get_symbol ();
5659 demand_empty_rest_of_line ();
5660 }
5661 else
5662 p = NULL;
5663
5664 #ifdef BFD_ASSEMBLER
5665 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5666 maybe_text = 1;
5667 else
5668 maybe_text = 0;
5669 #else
5670 if (now_seg != data_section && now_seg != bss_section)
5671 maybe_text = 1;
5672 else
5673 maybe_text = 0;
5674 #endif
5675
5676 if (!maybe_text)
5677 as_warn (_(".end not in text section"));
5678 if (!s7_cur_proc_ptr)
5679 {
5680 as_warn (_(".end directive without a preceding .ent directive."));
5681 demand_empty_rest_of_line ();
5682 return;
5683 }
5684 if (p != NULL)
5685 {
5686 gas_assert (S_GET_NAME (p));
5687 if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5688 as_warn (_(".end symbol does not match .ent symbol."));
5689 if (debug_type == DEBUG_STABS)
5690 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5691 }
5692 else
5693 as_warn (_(".end directive missing or unknown symbol"));
5694
5695 if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5696 (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5697 (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5698 (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5699 (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5700
5701 else
5702 {
5703 dot = frag_now_fix ();
5704 gas_assert (s7_pdr_seg);
5705 subseg_set (s7_pdr_seg, 0);
5706 /* Write the symbol. */
5707 exp.X_op = O_symbol;
5708 exp.X_add_symbol = p;
5709 exp.X_add_number = 0;
5710 emit_expr (&exp, 4);
5711 fragp = frag_more (7 * 4);
5712 s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5713 s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5714 s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5715 s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5716 s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5717 s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5718 s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5719 subseg_set (saved_seg, saved_subseg);
5720
5721 }
5722 s7_cur_proc_ptr = NULL;
5723 }
5724
5725 /* Handle the .set pseudo-op. */
5726
5727 static void
5728 s7_s_score_set (int x ATTRIBUTE_UNUSED)
5729 {
5730 int i = 0;
5731 char name[s7_MAX_LITERAL_POOL_SIZE];
5732 char * orig_ilp = input_line_pointer;
5733
5734 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5735 {
5736 name[i] = (char) * input_line_pointer;
5737 i++;
5738 ++input_line_pointer;
5739 }
5740
5741 name[i] = '\0';
5742
5743 if (strcmp (name, "nwarn") == 0)
5744 {
5745 s7_warn_fix_data_dependency = 0;
5746 }
5747 else if (strcmp (name, "fixdd") == 0)
5748 {
5749 s7_fix_data_dependency = 1;
5750 }
5751 else if (strcmp (name, "nofixdd") == 0)
5752 {
5753 s7_fix_data_dependency = 0;
5754 }
5755 else if (strcmp (name, "r1") == 0)
5756 {
5757 s7_nor1 = 0;
5758 }
5759 else if (strcmp (name, "nor1") == 0)
5760 {
5761 s7_nor1 = 1;
5762 }
5763 else if (strcmp (name, "optimize") == 0)
5764 {
5765 s7_g_opt = 1;
5766 }
5767 else if (strcmp (name, "volatile") == 0)
5768 {
5769 s7_g_opt = 0;
5770 }
5771 else if (strcmp (name, "pic") == 0)
5772 {
5773 s7_score_pic = s7_PIC;
5774 }
5775 else
5776 {
5777 input_line_pointer = orig_ilp;
5778 s_set (0);
5779 }
5780 }
5781
5782 /* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the
5783 $gp register for the function based on the function address, which is in the register
5784 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5785 specially by the linker. The result is:
5786 ldis gp, %hi(GP_DISP_LABEL)
5787 ori gp, %low(GP_DISP_LABEL)
5788 add gp, gp, .cpload argument
5789 The .cpload argument is normally r29. */
5790
5791 static void
5792 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5793 {
5794 int reg;
5795 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5796
5797 /* If we are not generating s7_PIC code, .cpload is ignored. */
5798 if (s7_score_pic == s7_NO_PIC)
5799 {
5800 s_ignore (0);
5801 return;
5802 }
5803
5804 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5805 return;
5806
5807 demand_empty_rest_of_line ();
5808
5809 sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5810 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5811 return;
5812
5813 sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5814 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5815 return;
5816
5817 sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5818 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5819 return;
5820 }
5821
5822 /* Handle the .cprestore pseudo-op. This stores $gp into a given
5823 offset from $sp. The offset is remembered, and after making a s7_PIC
5824 call $gp is restored from that location. */
5825
5826 static void
5827 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5828 {
5829 int reg;
5830 int cprestore_offset;
5831 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5832
5833 /* If we are not generating s7_PIC code, .cprestore is ignored. */
5834 if (s7_score_pic == s7_NO_PIC)
5835 {
5836 s_ignore (0);
5837 return;
5838 }
5839
5840 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5841 || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5842 {
5843 return;
5844 }
5845
5846 cprestore_offset = get_absolute_expression ();
5847
5848 if (cprestore_offset <= 0x3fff)
5849 {
5850 sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5851 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5852 return;
5853 }
5854 else
5855 {
5856 int r1_bak;
5857
5858 r1_bak = s7_nor1;
5859 s7_nor1 = 0;
5860
5861 sprintf (insn_str, "li r1, %d", cprestore_offset);
5862 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5863 return;
5864
5865 sprintf (insn_str, "add r1, r1, r%d", reg);
5866 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5867 return;
5868
5869 sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5870 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5871 return;
5872
5873 s7_nor1 = r1_bak;
5874 }
5875
5876 demand_empty_rest_of_line ();
5877 }
5878
5879 /* Handle the .gpword pseudo-op. This is used when generating s7_PIC
5880 code. It generates a 32 bit s7_GP relative reloc. */
5881
5882 static void
5883 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5884 {
5885 expressionS ex;
5886 char *p;
5887
5888 /* When not generating s7_PIC code, this is treated as .word. */
5889 if (s7_score_pic == s7_NO_PIC)
5890 {
5891 cons (4);
5892 return;
5893 }
5894 expression (&ex);
5895 if (ex.X_op != O_symbol || ex.X_add_number != 0)
5896 {
5897 as_bad (_("Unsupported use of .gpword"));
5898 ignore_rest_of_line ();
5899 }
5900 p = frag_more (4);
5901 s7_number_to_chars (p, (valueT) 0, 4);
5902 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5903 demand_empty_rest_of_line ();
5904 }
5905
5906 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
5907 tables in s7_PIC code. */
5908
5909 static void
5910 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5911 {
5912 int reg;
5913 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5914
5915 /* If we are not generating s7_PIC code, .cpload is ignored. */
5916 if (s7_score_pic == s7_NO_PIC)
5917 {
5918 s_ignore (0);
5919 return;
5920 }
5921
5922 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5923 {
5924 return;
5925 }
5926 demand_empty_rest_of_line ();
5927
5928 /* Add $gp to the register named as an argument. */
5929 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5930 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5931 return;
5932 }
5933
5934 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5935 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
5936 do \
5937 { \
5938 if ((SIZE) >= 8) \
5939 (P2VAR) = 3; \
5940 else if ((SIZE) >= 4) \
5941 (P2VAR) = 2; \
5942 else if ((SIZE) >= 2) \
5943 (P2VAR) = 1; \
5944 else \
5945 (P2VAR) = 0; \
5946 } \
5947 while (0)
5948 #endif
5949
5950 static void
5951 s7_s_score_lcomm (int bytes_p)
5952 {
5953 char *name;
5954 char c;
5955 char *p;
5956 int temp;
5957 symbolS *symbolP;
5958 segT current_seg = now_seg;
5959 subsegT current_subseg = now_subseg;
5960 const int max_alignment = 15;
5961 int align = 0;
5962 segT bss_seg = bss_section;
5963 int needs_align = 0;
5964
5965 name = input_line_pointer;
5966 c = get_symbol_end ();
5967 p = input_line_pointer;
5968 *p = c;
5969
5970 if (name == p)
5971 {
5972 as_bad (_("expected symbol name"));
5973 discard_rest_of_line ();
5974 return;
5975 }
5976
5977 SKIP_WHITESPACE ();
5978
5979 /* Accept an optional comma after the name. The comma used to be
5980 required, but Irix 5 cc does not generate it. */
5981 if (*input_line_pointer == ',')
5982 {
5983 ++input_line_pointer;
5984 SKIP_WHITESPACE ();
5985 }
5986
5987 if (is_end_of_line[(unsigned char)*input_line_pointer])
5988 {
5989 as_bad (_("missing size expression"));
5990 return;
5991 }
5992
5993 if ((temp = get_absolute_expression ()) < 0)
5994 {
5995 as_warn (_("BSS length (%d) < 0 ignored"), temp);
5996 ignore_rest_of_line ();
5997 return;
5998 }
5999
6000 #if defined (TC_SCORE)
6001 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6002 {
6003 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
6004 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6005 {
6006 bss_seg = subseg_new (".sbss", 1);
6007 seg_info (bss_seg)->bss = 1;
6008 #ifdef BFD_ASSEMBLER
6009 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6010 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6011 #endif
6012 }
6013 }
6014 #endif
6015
6016 SKIP_WHITESPACE ();
6017 if (*input_line_pointer == ',')
6018 {
6019 ++input_line_pointer;
6020 SKIP_WHITESPACE ();
6021
6022 if (is_end_of_line[(unsigned char)*input_line_pointer])
6023 {
6024 as_bad (_("missing alignment"));
6025 return;
6026 }
6027 else
6028 {
6029 align = get_absolute_expression ();
6030 needs_align = 1;
6031 }
6032 }
6033
6034 if (!needs_align)
6035 {
6036 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6037
6038 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6039 if (align)
6040 record_alignment (bss_seg, align);
6041 }
6042
6043 if (needs_align)
6044 {
6045 if (bytes_p)
6046 {
6047 /* Convert to a power of 2. */
6048 if (align != 0)
6049 {
6050 unsigned int i;
6051
6052 for (i = 0; align != 0; align >>= 1, ++i)
6053 ;
6054 align = i - 1;
6055 }
6056 }
6057
6058 if (align > max_alignment)
6059 {
6060 align = max_alignment;
6061 as_warn (_("alignment too large; %d assumed"), align);
6062 }
6063 else if (align < 0)
6064 {
6065 align = 0;
6066 as_warn (_("alignment negative; 0 assumed"));
6067 }
6068
6069 record_alignment (bss_seg, align);
6070 }
6071 else
6072 {
6073 /* Assume some objects may require alignment on some systems. */
6074 #if defined (TC_ALPHA) && ! defined (VMS)
6075 if (temp > 1)
6076 {
6077 align = ffs (temp) - 1;
6078 if (temp % (1 << align))
6079 abort ();
6080 }
6081 #endif
6082 }
6083
6084 *p = 0;
6085 symbolP = symbol_find_or_make (name);
6086 *p = c;
6087
6088 if (
6089 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6090 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6091 #ifdef BFD_ASSEMBLER
6092 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6093 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6094 #else
6095 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6096 #endif
6097 #endif
6098 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6099 {
6100 char *pfrag;
6101
6102 subseg_set (bss_seg, 1);
6103
6104 if (align)
6105 frag_align (align, 0, 0);
6106
6107 /* Detach from old frag. */
6108 if (S_GET_SEGMENT (symbolP) == bss_seg)
6109 symbol_get_frag (symbolP)->fr_symbol = NULL;
6110
6111 symbol_set_frag (symbolP, frag_now);
6112 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6113 *pfrag = 0;
6114
6115
6116 S_SET_SEGMENT (symbolP, bss_seg);
6117
6118 #ifdef OBJ_COFF
6119 /* The symbol may already have been created with a preceding
6120 ".globl" directive -- be careful not to step on storage class
6121 in that case. Otherwise, set it to static. */
6122 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6123 {
6124 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6125 }
6126 #endif /* OBJ_COFF */
6127
6128 #ifdef S_SET_SIZE
6129 S_SET_SIZE (symbolP, temp);
6130 #endif
6131 }
6132 else
6133 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6134
6135 subseg_set (current_seg, current_subseg);
6136
6137 demand_empty_rest_of_line ();
6138 }
6139
6140 \f
6141
6142 static void
6143 s7_begin (void)
6144 {
6145 unsigned int i;
6146 segT seg;
6147 subsegT subseg;
6148
6149 if ((s7_score_ops_hsh = hash_new ()) == NULL)
6150 as_fatal (_("virtual memory exhausted"));
6151
6152 s7_build_score_ops_hsh ();
6153
6154 if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6155 as_fatal (_("virtual memory exhausted"));
6156
6157 s7_build_dependency_insn_hsh ();
6158
6159 for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6160 s7_build_reg_hsh (s7_all_reg_maps + i);
6161
6162 /* Initialize dependency vector. */
6163 s7_init_dependency_vector ();
6164
6165 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6166 seg = now_seg;
6167 subseg = now_subseg;
6168 s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6169 (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6170 (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
6171 subseg_set (seg, subseg);
6172
6173 if (s7_USE_GLOBAL_POINTER_OPT)
6174 bfd_set_gp_size (stdoutput, s7_g_switch_value);
6175 }
6176
6177 static void
6178 s7_assemble (char *str)
6179 {
6180 know (str);
6181 know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6182
6183 memset (&s7_inst, '\0', sizeof (s7_inst));
6184 if (s7_INSN_IS_PCE_P (str))
6185 s7_parse_pce_inst (str);
6186 else
6187 s7_parse_16_32_inst (str, TRUE);
6188
6189 if (s7_inst.error)
6190 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6191 }
6192
6193 /* We handle all bad expressions here, so that we can report the faulty
6194 instruction in the error message. */
6195
6196 static void
6197 s7_operand (expressionS * expr)
6198 {
6199 if (s7_in_my_get_expression)
6200 {
6201 expr->X_op = O_illegal;
6202 if (s7_inst.error == NULL)
6203 {
6204 s7_inst.error = _("bad expression");
6205 }
6206 }
6207 }
6208
6209 /* Turn a string in input_line_pointer into a floating point constant
6210 of type TYPE, and store the appropriate bytes in *LITP. The number
6211 of LITTLENUMS emitted is stored in *SIZEP. An error message is
6212 returned, or NULL on OK.
6213
6214 Note that fp constants aren't represent in the normal way on the ARM.
6215 In big endian mode, things are as expected. However, in little endian
6216 mode fp constants are big-endian word-wise, and little-endian byte-wise
6217 within the words. For example, (double) 1.1 in big endian mode is
6218 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6219 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6220
6221 static char *
6222 s7_atof (int type, char *litP, int *sizeP)
6223 {
6224 int prec;
6225 LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
6226 char *t;
6227 int i;
6228
6229 switch (type)
6230 {
6231 case 'f':
6232 case 'F':
6233 case 's':
6234 case 'S':
6235 prec = 2;
6236 break;
6237 case 'd':
6238 case 'D':
6239 case 'r':
6240 case 'R':
6241 prec = 4;
6242 break;
6243 case 'x':
6244 case 'X':
6245 case 'p':
6246 case 'P':
6247 prec = 6;
6248 break;
6249 default:
6250 *sizeP = 0;
6251 return _("bad call to MD_ATOF()");
6252 }
6253
6254 t = atof_ieee (input_line_pointer, type, words);
6255 if (t)
6256 input_line_pointer = t;
6257 *sizeP = prec * 2;
6258
6259 if (target_big_endian)
6260 {
6261 for (i = 0; i < prec; i++)
6262 {
6263 s7_number_to_chars (litP, (valueT) words[i], 2);
6264 litP += 2;
6265 }
6266 }
6267 else
6268 {
6269 for (i = 0; i < prec; i += 2)
6270 {
6271 s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6272 s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6273 litP += 4;
6274 }
6275 }
6276
6277 return 0;
6278 }
6279
6280 /* Implementation of md_frag_check.
6281 Called after md_convert_frag(). */
6282
6283 static void
6284 s7_frag_check (fragS * fragp)
6285 {
6286 know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6287 }
6288
6289 /* Implementation of TC_VALIDATE_FIX.
6290 Called before md_apply_fix() and after md_convert_frag(). */
6291
6292 static void
6293 s7_validate_fix (fixS *fixP)
6294 {
6295 fixP->fx_where += fixP->fx_frag->insn_addr;
6296 }
6297
6298 static int
6299 s7_force_relocation (struct fix *fixp)
6300 {
6301 int retval = 0;
6302
6303 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6304 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6305 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6306 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6307 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6308 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6309 {
6310 retval = 1;
6311 }
6312
6313 return retval;
6314 }
6315
6316 static bfd_boolean
6317 s7_fix_adjustable (fixS * fixP)
6318 {
6319 if (fixP->fx_addsy == NULL)
6320 {
6321 return 1;
6322 }
6323 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6324 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6325 {
6326 return 0;
6327 }
6328 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6329 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6330 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6331 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6332 {
6333 return 0;
6334 }
6335
6336 return 1;
6337 }
6338
6339 static void
6340 s7_elf_final_processing (void)
6341 {
6342 unsigned long val = E_SCORE_MACH_SCORE7;
6343
6344 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6345 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6346 elf_elfheader (stdoutput)->e_flags |= val;
6347
6348 if (s7_fix_data_dependency == 1)
6349 {
6350 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6351 }
6352 if (s7_score_pic == s7_PIC)
6353 {
6354 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6355 }
6356 }
6357
6358 /* In this function, we determine whether s7_GP instruction should do relaxation,
6359 for the label being against was known now.
6360 Doing this here but not in md_relax_frag() can induce iteration times
6361 in stage of doing relax. */
6362
6363 static int
6364 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6365 {
6366 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6367 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6368 return s7_judge_size_before_relax (fragp, sec);
6369
6370 return 0;
6371 }
6372
6373 static int
6374 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6375 fragS * fragp,
6376 long stretch ATTRIBUTE_UNUSED)
6377 {
6378 int grows = 0;
6379 int insn_size;
6380 int insn_relax_size;
6381 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
6382 int relaxable_p = 0;
6383 bfd_boolean word_align_p = FALSE;
6384 fragS *next_fragp;
6385
6386 /* If the instruction address is odd, make it half word align first. */
6387 if ((fragp->fr_address) % 2 != 0)
6388 {
6389 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6390 {
6391 fragp->insn_addr = 1;
6392 grows += 1;
6393 }
6394 }
6395
6396 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6397
6398 /* Get instruction size and relax size after the last relaxation. */
6399 if (fragp->fr_opcode)
6400 {
6401 insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6402 insn_relax_size = s7_RELAX_OLD (fragp->fr_subtype);
6403 }
6404 else
6405 {
6406 insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6407 insn_relax_size = s7_RELAX_NEW (fragp->fr_subtype);
6408 }
6409
6410 /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine
6411 whether the s7_GP instruction should do relax. */
6412 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6413 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6414 {
6415 if (!word_align_p)
6416 {
6417 if (fragp->insn_addr < 2)
6418 {
6419 fragp->insn_addr += 2;
6420 grows += 2;
6421 }
6422 else
6423 {
6424 fragp->insn_addr -= 2;
6425 grows -= 2;
6426 }
6427 }
6428
6429 if (fragp->fr_opcode)
6430 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6431 else
6432 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6433 }
6434 else
6435 {
6436 if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6437 s7_b32_relax_to_b16 (fragp);
6438
6439 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6440 next_fragp = fragp->fr_next;
6441 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6442 {
6443 next_fragp = next_fragp->fr_next;
6444 }
6445
6446 if (next_fragp)
6447 {
6448 int n_insn_size;
6449 int n_relaxable_p = 0;
6450
6451 if (next_fragp->fr_opcode)
6452 {
6453 n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6454 }
6455 else
6456 {
6457 n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6458 }
6459
6460 if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6461 s7_b32_relax_to_b16 (next_fragp);
6462 n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6463
6464 if (word_align_p)
6465 {
6466 if (insn_size == 4)
6467 {
6468 /* 32 -> 16. */
6469 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6470 {
6471 grows -= 2;
6472 do_relax_p = 1;
6473 }
6474 }
6475 else if (insn_size == 2)
6476 {
6477 /* 16 -> 32. */
6478 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6479 {
6480 grows += 2;
6481 do_relax_p = 1;
6482 }
6483 }
6484 else
6485 {
6486 abort ();
6487 }
6488 }
6489 else
6490 {
6491 if (insn_size == 4)
6492 {
6493 /* 32 -> 16. */
6494 if (relaxable_p)
6495 {
6496 grows -= 2;
6497 do_relax_p = 1;
6498 }
6499 /* Make the 32 bit insturction word align. */
6500 else
6501 {
6502 fragp->insn_addr += 2;
6503 grows += 2;
6504 }
6505 }
6506 else if (insn_size == 2)
6507 {
6508 /* Do nothing. */
6509 }
6510 else
6511 {
6512 abort ();
6513 }
6514 }
6515 }
6516 else
6517 {
6518 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
6519 if (word_align_p == FALSE)
6520 {
6521 if (insn_size % 4 == 0)
6522 {
6523 /* 32 -> 16. */
6524 if (relaxable_p)
6525 {
6526 grows -= 2;
6527 do_relax_p = 1;
6528 }
6529 else
6530 {
6531 fragp->insn_addr += 2;
6532 grows += 2;
6533 }
6534 }
6535 }
6536 else
6537 {
6538 /* Do nothing. */
6539 }
6540 }
6541
6542 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6543 if (do_relax_p)
6544 {
6545 if (fragp->fr_opcode)
6546 {
6547 fragp->fr_opcode = NULL;
6548 /* Guarantee estimate stage is correct. */
6549 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6550 fragp->fr_fix += fragp->insn_addr;
6551 }
6552 else
6553 {
6554 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6555 /* Guarantee estimate stage is correct. */
6556 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6557 fragp->fr_fix += fragp->insn_addr;
6558 }
6559 }
6560 else
6561 {
6562 if (fragp->fr_opcode)
6563 {
6564 /* Guarantee estimate stage is correct. */
6565 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6566 fragp->fr_fix += fragp->insn_addr;
6567 }
6568 else
6569 {
6570 /* Guarantee estimate stage is correct. */
6571 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6572 fragp->fr_fix += fragp->insn_addr;
6573 }
6574 }
6575 }
6576
6577 return grows;
6578 }
6579
6580 static void
6581 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6582 segT sec ATTRIBUTE_UNUSED,
6583 fragS * fragp)
6584 {
6585 int r_old;
6586 int r_new;
6587 char backup[20];
6588 fixS *fixp;
6589
6590 r_old = s7_RELAX_OLD (fragp->fr_subtype);
6591 r_new = s7_RELAX_NEW (fragp->fr_subtype);
6592
6593 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6594 if (fragp->fr_opcode == NULL)
6595 {
6596 memcpy (backup, fragp->fr_literal, r_old);
6597 fragp->fr_fix = r_old;
6598 }
6599 else
6600 {
6601 memcpy (backup, fragp->fr_literal + r_old, r_new);
6602 fragp->fr_fix = r_new;
6603 }
6604
6605 fixp = fragp->tc_frag_data.fixp;
6606 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6607 {
6608 if (fragp->fr_opcode)
6609 fixp->fx_done = 1;
6610 fixp = fixp->fx_next;
6611 }
6612 while (fixp && fixp->fx_frag == fragp)
6613 {
6614 if (fragp->fr_opcode)
6615 fixp->fx_where -= r_old + fragp->insn_addr;
6616 else
6617 fixp->fx_done = 1;
6618 fixp = fixp->fx_next;
6619 }
6620
6621 if (fragp->insn_addr)
6622 {
6623 s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6624 }
6625 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6626 fragp->fr_fix += fragp->insn_addr;
6627 }
6628
6629 static long
6630 s7_pcrel_from (fixS * fixP)
6631 {
6632 long retval = 0;
6633
6634 if (fixP->fx_addsy
6635 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6636 && (fixP->fx_subsy == NULL))
6637 {
6638 retval = 0;
6639 }
6640 else
6641 {
6642 retval = fixP->fx_where + fixP->fx_frag->fr_address;
6643 }
6644
6645 return retval;
6646 }
6647
6648 /* Round up a section size to the appropriate boundary. */
6649 static valueT
6650 s7_section_align (segT segment, valueT size)
6651 {
6652 int align = bfd_get_section_alignment (stdoutput, segment);
6653
6654 return ((size + (1 << align) - 1) & (-1 << align));
6655 }
6656
6657 static void
6658 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6659 {
6660 offsetT value = *valP;
6661 offsetT abs_value = 0;
6662 offsetT newval;
6663 offsetT content;
6664 unsigned short HI, LO;
6665
6666 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6667
6668 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6669 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6670 {
6671 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6672 fixP->fx_done = 1;
6673 }
6674
6675 /* If this symbol is in a different section then we need to leave it for
6676 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
6677 so we have to undo it's effects here. */
6678 if (fixP->fx_pcrel)
6679 {
6680 if (fixP->fx_addsy != NULL
6681 && S_IS_DEFINED (fixP->fx_addsy)
6682 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6683 value += md_pcrel_from (fixP);
6684 }
6685
6686 /* Remember value for emit_reloc. */
6687 fixP->fx_addnumber = value;
6688
6689 switch (fixP->fx_r_type)
6690 {
6691 case BFD_RELOC_HI16_S:
6692 if (fixP->fx_done)
6693 { /* For la rd, imm32. */
6694 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6695 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
6696 newval |= (HI & 0x3fff) << 1;
6697 newval |= ((HI >> 14) & 0x3) << 16;
6698 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6699 }
6700 break;
6701 case BFD_RELOC_LO16:
6702 if (fixP->fx_done) /* For la rd, imm32. */
6703 {
6704 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6705 LO = (value) & 0xffff;
6706 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
6707 newval |= ((LO >> 14) & 0x3) << 16;
6708 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6709 }
6710 break;
6711 case BFD_RELOC_SCORE_JMP:
6712 {
6713 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6714 value = fixP->fx_offset;
6715 if (!(value >= 0 && value <= 0x1ffffff))
6716 {
6717 as_bad_where (fixP->fx_file, fixP->fx_line,
6718 _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value);
6719 return;
6720 }
6721 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6722 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6723 }
6724 break;
6725 case BFD_RELOC_SCORE_BRANCH:
6726 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6727 value = fixP->fx_offset;
6728 else
6729 fixP->fx_done = 1;
6730
6731 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6732 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6733 {
6734 if ((value & 0x80000000) == 0x80000000)
6735 abs_value = 0xffffffff - value + 1;
6736 if ((abs_value & 0xffffff00) != 0)
6737 {
6738 as_bad_where (fixP->fx_file, fixP->fx_line,
6739 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6740 return;
6741 }
6742 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6743 content &= 0xff00;
6744 content = (content & 0xff00) | ((value >> 1) & 0xff);
6745 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6746 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6747 fixP->fx_size = 2;
6748 }
6749 else
6750 {
6751 if ((value & 0x80000000) == 0x80000000)
6752 abs_value = 0xffffffff - value + 1;
6753 if ((abs_value & 0xfff80000) != 0)
6754 {
6755 as_bad_where (fixP->fx_file, fixP->fx_line,
6756 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6757 (unsigned int) value);
6758 return;
6759 }
6760 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6761 content &= 0xfc00fc01;
6762 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6763 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6764 }
6765 break;
6766 case BFD_RELOC_SCORE16_JMP:
6767 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6768 content &= 0xf001;
6769 value = fixP->fx_offset;
6770 if (!(value >= 0 && value <= 0xfff))
6771 {
6772 as_bad_where (fixP->fx_file, fixP->fx_line,
6773 _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value);
6774 return;
6775 }
6776 value = fixP->fx_offset & 0xfff;
6777 content = (content & 0xfc01) | (value & 0xffe);
6778 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6779 break;
6780 case BFD_RELOC_SCORE16_BRANCH:
6781 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6782 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6783 {
6784 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6785 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6786 value = fixP->fx_offset;
6787 else
6788 fixP->fx_done = 1;
6789
6790 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6791 {
6792 as_bad_where (fixP->fx_file, fixP->fx_line,
6793 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6794 (unsigned int) value);
6795 return;
6796 }
6797 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6798 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6799 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6800 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6801 fixP->fx_size = 4;
6802 break;
6803 }
6804 else
6805 {
6806 /* In differnt section. */
6807 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6808 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6809 value = fixP->fx_offset;
6810 else
6811 fixP->fx_done = 1;
6812
6813 if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6814 {
6815 as_bad_where (fixP->fx_file, fixP->fx_line,
6816 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"),
6817 (unsigned int) value);
6818 return;
6819 }
6820 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6821 content = (content & 0xff00) | ((value >> 1) & 0xff);
6822 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6823 break;
6824 }
6825 case BFD_RELOC_8:
6826 if (fixP->fx_done || fixP->fx_pcrel)
6827 s7_number_to_chars (buf, value, 1);
6828 #ifdef OBJ_ELF
6829 else
6830 {
6831 value = fixP->fx_offset;
6832 s7_number_to_chars (buf, value, 1);
6833 }
6834 #endif
6835 break;
6836
6837 case BFD_RELOC_16:
6838 if (fixP->fx_done || fixP->fx_pcrel)
6839 s7_number_to_chars (buf, value, 2);
6840 #ifdef OBJ_ELF
6841 else
6842 {
6843 value = fixP->fx_offset;
6844 s7_number_to_chars (buf, value, 2);
6845 }
6846 #endif
6847 break;
6848 case BFD_RELOC_RVA:
6849 case BFD_RELOC_32:
6850 if (fixP->fx_done || fixP->fx_pcrel)
6851 s7_number_to_chars (buf, value, 4);
6852 #ifdef OBJ_ELF
6853 else
6854 {
6855 value = fixP->fx_offset;
6856 s7_number_to_chars (buf, value, 4);
6857 }
6858 #endif
6859 break;
6860 case BFD_RELOC_VTABLE_INHERIT:
6861 fixP->fx_done = 0;
6862 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6863 S_SET_WEAK (fixP->fx_addsy);
6864 break;
6865 case BFD_RELOC_VTABLE_ENTRY:
6866 fixP->fx_done = 0;
6867 break;
6868 case BFD_RELOC_SCORE_GPREL15:
6869 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6870 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6871 fixP->fx_r_type = BFD_RELOC_NONE;
6872 fixP->fx_done = 0;
6873 break;
6874 case BFD_RELOC_SCORE_GOT15:
6875 case BFD_RELOC_SCORE_DUMMY_HI16:
6876 case BFD_RELOC_SCORE_GOT_LO16:
6877 case BFD_RELOC_SCORE_CALL15:
6878 case BFD_RELOC_GPREL32:
6879 break;
6880 case BFD_RELOC_NONE:
6881 default:
6882 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6883 }
6884 }
6885
6886 /* Translate internal representation of relocation info to BFD target format. */
6887
6888 static arelent **
6889 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6890 {
6891 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
6892 arelent *reloc;
6893 bfd_reloc_code_real_type code;
6894 char *type;
6895 fragS *f;
6896 symbolS *s;
6897 expressionS e;
6898
6899 reloc = retval[0] = xmalloc (sizeof (arelent));
6900 retval[1] = NULL;
6901
6902 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6903 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6904 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6905 reloc->addend = fixp->fx_offset;
6906
6907 /* If this is a variant frag, we may need to adjust the existing
6908 reloc and generate a new one. */
6909 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6910 {
6911 /* Update instruction imm bit. */
6912 offsetT newval;
6913 unsigned short off;
6914 char *buf;
6915
6916 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6917 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6918 off = fixp->fx_offset >> 16;
6919 newval |= (off & 0x3fff) << 1;
6920 newval |= ((off >> 14) & 0x3) << 16;
6921 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6922
6923 buf += s7_INSN_SIZE;
6924 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6925 off = fixp->fx_offset & 0xffff;
6926 newval |= ((off & 0x3fff) << 1);
6927 newval |= (((off >> 14) & 0x3) << 16);
6928 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6929
6930 retval[1] = xmalloc (sizeof (arelent));
6931 retval[2] = NULL;
6932 retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6933 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6934 retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6935
6936 f = fixp->fx_frag;
6937 s = f->fr_symbol;
6938 e = s->sy_value;
6939
6940 retval[1]->addend = 0;
6941 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6942 gas_assert (retval[1]->howto != NULL);
6943
6944 fixp->fx_r_type = BFD_RELOC_HI16_S;
6945 }
6946
6947 code = fixp->fx_r_type;
6948 switch (fixp->fx_r_type)
6949 {
6950 case BFD_RELOC_32:
6951 if (fixp->fx_pcrel)
6952 {
6953 code = BFD_RELOC_32_PCREL;
6954 break;
6955 }
6956 case BFD_RELOC_HI16_S:
6957 case BFD_RELOC_LO16:
6958 case BFD_RELOC_SCORE_JMP:
6959 case BFD_RELOC_SCORE_BRANCH:
6960 case BFD_RELOC_SCORE16_JMP:
6961 case BFD_RELOC_SCORE16_BRANCH:
6962 case BFD_RELOC_VTABLE_ENTRY:
6963 case BFD_RELOC_VTABLE_INHERIT:
6964 case BFD_RELOC_SCORE_GPREL15:
6965 case BFD_RELOC_SCORE_GOT15:
6966 case BFD_RELOC_SCORE_DUMMY_HI16:
6967 case BFD_RELOC_SCORE_GOT_LO16:
6968 case BFD_RELOC_SCORE_CALL15:
6969 case BFD_RELOC_GPREL32:
6970 case BFD_RELOC_NONE:
6971 code = fixp->fx_r_type;
6972 break;
6973 default:
6974 type = _("<unknown>");
6975 as_bad_where (fixp->fx_file, fixp->fx_line,
6976 _("cannot represent %s relocation in this object file format"), type);
6977 return NULL;
6978 }
6979
6980 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6981 if (reloc->howto == NULL)
6982 {
6983 as_bad_where (fixp->fx_file, fixp->fx_line,
6984 _("cannot represent %s relocation in this object file format1"),
6985 bfd_get_reloc_code_name (code));
6986 return NULL;
6987 }
6988 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6989 vtable entry to be used in the relocation's section offset. */
6990 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6991 reloc->address = fixp->fx_offset;
6992
6993 return retval;
6994 }
This page took 0.235725 seconds and 3 git commands to generate.