[PATCH 5/57][Arm][GAS] Add support for MVE instructions: vmull{b,t}
[binutils-gdb.git] / gas / config / tc-score7.c
blob90cd5e3962d8f27ed2b5b81d55017d6cb7191459
1 /* tc-score7.c -- Assembler for Score7
2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
3 Contributed by:
4 Brain.lin (brain.lin@sunplusct.com)
5 Mei Ligang (ligang@sunnorth.com.cn)
6 Pei-Lin Tsai (pltsai@sunplus.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
25 #include "as.h"
26 #include "config.h"
27 #include "subsegs.h"
28 #include "safe-ctype.h"
29 #include "opcode/score-inst.h"
30 #include "libiberty.h"
32 #ifdef OBJ_ELF
33 #include "elf/score.h"
34 #include "dwarf2dbg.h"
35 #endif
37 static void s7_do_ldst_insn (char *);
38 static void s7_do_crdcrscrsimm5 (char *);
39 static void s7_do_ldst_unalign (char *);
40 static void s7_do_ldst_atomic (char *);
41 static void s7_do_ldst_cop (char *);
42 static void s7_do_macro_li_rdi32 (char *);
43 static void s7_do_macro_la_rdi32 (char *);
44 static void s7_do_macro_rdi32hi (char *);
45 static void s7_do_macro_rdi32lo (char *);
46 static void s7_do_macro_mul_rdrsrs (char *);
47 static void s7_do_macro_ldst_label (char *);
48 static void s7_do_branch (char *);
49 static void s7_do_jump (char *);
50 static void s7_do_empty (char *);
51 static void s7_do_rdrsrs (char *);
52 static void s7_do_rdsi16 (char *);
53 static void s7_do_rdrssi14 (char *);
54 static void s7_do_sub_rdsi16 (char *);
55 static void s7_do_sub_rdrssi14 (char *);
56 static void s7_do_rdrsi5 (char *);
57 static void s7_do_rdrsi14 (char *);
58 static void s7_do_rdi16 (char *);
59 static void s7_do_xrsi5 (char *);
60 static void s7_do_rdrs (char *);
61 static void s7_do_rdxrs (char *);
62 static void s7_do_rsrs (char *);
63 static void s7_do_rdcrs (char *);
64 static void s7_do_rdsrs (char *);
65 static void s7_do_rd (char *);
66 static void s7_do_rs (char *);
67 static void s7_do_i15 (char *);
68 static void s7_do_xi5x (char *);
69 static void s7_do_ceinst (char *);
70 static void s7_do_cache (char *);
71 static void s7_do16_rdrs (char *);
72 static void s7_do16_rs (char *);
73 static void s7_do16_xrs (char *);
74 static void s7_do16_mv_rdrs (char *);
75 static void s7_do16_hrdrs (char *);
76 static void s7_do16_rdhrs (char *);
77 static void s7_do16_rdi4 (char *);
78 static void s7_do16_rdi5 (char *);
79 static void s7_do16_xi5 (char *);
80 static void s7_do16_ldst_insn (char *);
81 static void s7_do16_ldst_imm_insn (char *);
82 static void s7_do16_push_pop (char *);
83 static void s7_do16_branch (char *);
84 static void s7_do16_jump (char *);
85 static void s7_do_rdi16_pic (char *);
86 static void s7_do_addi_s_pic (char *);
87 static void s7_do_addi_u_pic (char *);
88 static void s7_do_lw_pic (char *);
90 #define s7_GP 28
91 #define s7_PIC_CALL_REG 29
92 #define s7_MAX_LITERAL_POOL_SIZE 1024
93 #define s7_FAIL 0x80000000
94 #define s7_SUCCESS 0
95 #define s7_INSN_SIZE 4
96 #define s7_INSN16_SIZE 2
97 #define s7_RELAX_INST_NUM 3
99 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
100 #define s7_BAD_ARGS _("bad arguments to instruction")
101 #define s7_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
102 #define s7_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
103 #define s7_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
104 #define s7_BAD_SKIP_COMMA s7_BAD_ARGS
105 #define s7_BAD_GARBAGE _("garbage following instruction");
107 #define s7_skip_whitespace(str) while (*(str) == ' ') ++(str)
109 /* The name of the readonly data section. */
110 #define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
111 ? ".data" \
112 : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
113 ? ".rdata" \
114 : OUTPUT_FLAVOR == bfd_target_coff_flavour \
115 ? ".rdata" \
116 : OUTPUT_FLAVOR == bfd_target_elf_flavour \
117 ? ".rodata" \
118 : (abort (), ""))
120 #define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
121 ((relax_substateT) \
122 (((old) << 23) \
123 | ((new) << 16) \
124 | ((type) << 9) \
125 | ((reloc1) << 5) \
126 | ((reloc2) << 1) \
127 | ((opt) ? 1 : 0)))
129 #define s7_RELAX_OLD(i) (((i) >> 23) & 0x7f)
130 #define s7_RELAX_NEW(i) (((i) >> 16) & 0x7f)
131 #define s7_RELAX_TYPE(i) (((i) >> 9) & 0x7f)
132 #define s7_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
133 #define s7_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
134 #define s7_RELAX_OPT(i) ((i) & 1)
135 #define s7_RELAX_OPT_CLEAR(i) ((i) & ~1)
137 #define s7_SET_INSN_ERROR(s) (s7_inst.error = (s))
138 #define s7_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
140 #define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type))
142 #define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \
143 ? s7_INSN16_SIZE : s7_INSN_SIZE)
145 #define s7_INSN_NAME_LEN 16
147 /* Relax will need some padding for alignment. */
148 #define s7_RELAX_PAD_BYTE 3
150 #define s7_USE_GLOBAL_POINTER_OPT 1
154 /* Enumeration matching entries in table above. */
155 enum s7_score_reg_type
157 s7_REG_TYPE_SCORE = 0,
158 #define REG_TYPE_FIRST s7_REG_TYPE_SCORE
159 s7_REG_TYPE_SCORE_SR = 1,
160 s7_REG_TYPE_SCORE_CR = 2,
161 s7_REG_TYPE_MAX = 3
164 enum s7_score_pic_level
166 s7_NO_PIC,
167 s7_PIC
169 static enum s7_score_pic_level s7_score_pic = s7_NO_PIC;
171 enum s7_insn_type_for_dependency
173 s7_D_pce,
174 s7_D_cond_br,
175 s7_D_cond_mv,
176 s7_D_cached,
177 s7_D_cachei,
178 s7_D_ldst,
179 s7_D_ldcombine,
180 s7_D_mtcr,
181 s7_D_mfcr,
182 s7_D_mfsr,
183 s7_D_mftlb,
184 s7_D_mtptlb,
185 s7_D_mtrtlb,
186 s7_D_stlb,
187 s7_D_all_insn
190 struct s7_insn_to_dependency
192 const char *insn_name;
193 enum s7_insn_type_for_dependency type;
196 struct s7_data_dependency
198 enum s7_insn_type_for_dependency pre_insn_type;
199 char pre_reg[6];
200 enum s7_insn_type_for_dependency cur_insn_type;
201 char cur_reg[6];
202 int bubblenum_7;
203 int bubblenum_5;
204 int warn_or_error; /* warning - 0; error - 1 */
207 static const struct s7_insn_to_dependency s7_insn_to_dependency_table[] =
209 /* pce instruction. */
210 {"pce", s7_D_pce},
211 /* conditional branch instruction. */
212 {"bcs", s7_D_cond_br},
213 {"bcc", s7_D_cond_br},
214 {"bgtu", s7_D_cond_br},
215 {"bleu", s7_D_cond_br},
216 {"beq", s7_D_cond_br},
217 {"bne", s7_D_cond_br},
218 {"bgt", s7_D_cond_br},
219 {"ble", s7_D_cond_br},
220 {"bge", s7_D_cond_br},
221 {"blt", s7_D_cond_br},
222 {"bmi", s7_D_cond_br},
223 {"bpl", s7_D_cond_br},
224 {"bvs", s7_D_cond_br},
225 {"bvc", s7_D_cond_br},
226 {"bcsl", s7_D_cond_br},
227 {"bccl", s7_D_cond_br},
228 {"bgtul", s7_D_cond_br},
229 {"bleul", s7_D_cond_br},
230 {"beql", s7_D_cond_br},
231 {"bnel", s7_D_cond_br},
232 {"bgtl", s7_D_cond_br},
233 {"blel", s7_D_cond_br},
234 {"bgel", s7_D_cond_br},
235 {"bltl", s7_D_cond_br},
236 {"bmil", s7_D_cond_br},
237 {"bpll", s7_D_cond_br},
238 {"bvsl", s7_D_cond_br},
239 {"bvcl", s7_D_cond_br},
240 {"bcs!", s7_D_cond_br},
241 {"bcc!", s7_D_cond_br},
242 {"bgtu!", s7_D_cond_br},
243 {"bleu!", s7_D_cond_br},
244 {"beq!", s7_D_cond_br},
245 {"bne!", s7_D_cond_br},
246 {"bgt!", s7_D_cond_br},
247 {"ble!", s7_D_cond_br},
248 {"bge!", s7_D_cond_br},
249 {"blt!", s7_D_cond_br},
250 {"bmi!", s7_D_cond_br},
251 {"bpl!", s7_D_cond_br},
252 {"bvs!", s7_D_cond_br},
253 {"bvc!", s7_D_cond_br},
254 {"brcs", s7_D_cond_br},
255 {"brcc", s7_D_cond_br},
256 {"brgtu", s7_D_cond_br},
257 {"brleu", s7_D_cond_br},
258 {"breq", s7_D_cond_br},
259 {"brne", s7_D_cond_br},
260 {"brgt", s7_D_cond_br},
261 {"brle", s7_D_cond_br},
262 {"brge", s7_D_cond_br},
263 {"brlt", s7_D_cond_br},
264 {"brmi", s7_D_cond_br},
265 {"brpl", s7_D_cond_br},
266 {"brvs", s7_D_cond_br},
267 {"brvc", s7_D_cond_br},
268 {"brcsl", s7_D_cond_br},
269 {"brccl", s7_D_cond_br},
270 {"brgtul", s7_D_cond_br},
271 {"brleul", s7_D_cond_br},
272 {"breql", s7_D_cond_br},
273 {"brnel", s7_D_cond_br},
274 {"brgtl", s7_D_cond_br},
275 {"brlel", s7_D_cond_br},
276 {"brgel", s7_D_cond_br},
277 {"brltl", s7_D_cond_br},
278 {"brmil", s7_D_cond_br},
279 {"brpll", s7_D_cond_br},
280 {"brvsl", s7_D_cond_br},
281 {"brvcl", s7_D_cond_br},
282 {"brcs!", s7_D_cond_br},
283 {"brcc!", s7_D_cond_br},
284 {"brgtu!", s7_D_cond_br},
285 {"brleu!", s7_D_cond_br},
286 {"breq!", s7_D_cond_br},
287 {"brne!", s7_D_cond_br},
288 {"brgt!", s7_D_cond_br},
289 {"brle!", s7_D_cond_br},
290 {"brge!", s7_D_cond_br},
291 {"brlt!", s7_D_cond_br},
292 {"brmi!", s7_D_cond_br},
293 {"brpl!", s7_D_cond_br},
294 {"brvs!", s7_D_cond_br},
295 {"brvc!", s7_D_cond_br},
296 {"brcsl!", s7_D_cond_br},
297 {"brccl!", s7_D_cond_br},
298 {"brgtul!", s7_D_cond_br},
299 {"brleul!", s7_D_cond_br},
300 {"breql!", s7_D_cond_br},
301 {"brnel!", s7_D_cond_br},
302 {"brgtl!", s7_D_cond_br},
303 {"brlel!", s7_D_cond_br},
304 {"brgel!", s7_D_cond_br},
305 {"brltl!", s7_D_cond_br},
306 {"brmil!", s7_D_cond_br},
307 {"brpll!", s7_D_cond_br},
308 {"brvsl!", s7_D_cond_br},
309 {"brvcl!", s7_D_cond_br},
310 /* conditional move instruction. */
311 {"mvcs", s7_D_cond_mv},
312 {"mvcc", s7_D_cond_mv},
313 {"mvgtu", s7_D_cond_mv},
314 {"mvleu", s7_D_cond_mv},
315 {"mveq", s7_D_cond_mv},
316 {"mvne", s7_D_cond_mv},
317 {"mvgt", s7_D_cond_mv},
318 {"mvle", s7_D_cond_mv},
319 {"mvge", s7_D_cond_mv},
320 {"mvlt", s7_D_cond_mv},
321 {"mvmi", s7_D_cond_mv},
322 {"mvpl", s7_D_cond_mv},
323 {"mvvs", s7_D_cond_mv},
324 {"mvvc", s7_D_cond_mv},
325 /* move special instruction. */
326 {"mtcr", s7_D_mtcr},
327 {"mftlb", s7_D_mftlb},
328 {"mtptlb", s7_D_mtptlb},
329 {"mtrtlb", s7_D_mtrtlb},
330 {"stlb", s7_D_stlb},
331 {"mfcr", s7_D_mfcr},
332 {"mfsr", s7_D_mfsr},
333 /* cache instruction. */
334 {"cache 8", s7_D_cached},
335 {"cache 9", s7_D_cached},
336 {"cache 10", s7_D_cached},
337 {"cache 11", s7_D_cached},
338 {"cache 12", s7_D_cached},
339 {"cache 13", s7_D_cached},
340 {"cache 14", s7_D_cached},
341 {"cache 24", s7_D_cached},
342 {"cache 26", s7_D_cached},
343 {"cache 27", s7_D_cached},
344 {"cache 29", s7_D_cached},
345 {"cache 30", s7_D_cached},
346 {"cache 31", s7_D_cached},
347 {"cache 0", s7_D_cachei},
348 {"cache 1", s7_D_cachei},
349 {"cache 2", s7_D_cachei},
350 {"cache 3", s7_D_cachei},
351 {"cache 4", s7_D_cachei},
352 {"cache 16", s7_D_cachei},
353 {"cache 17", s7_D_cachei},
354 /* load/store instruction. */
355 {"lb", s7_D_ldst},
356 {"lbu", s7_D_ldst},
357 {"lbu!", s7_D_ldst},
358 {"lbup!", s7_D_ldst},
359 {"lh", s7_D_ldst},
360 {"lhu", s7_D_ldst},
361 {"lh!", s7_D_ldst},
362 {"lhp!", s7_D_ldst},
363 {"lw", s7_D_ldst},
364 {"lw!", s7_D_ldst},
365 {"lwp!", s7_D_ldst},
366 {"sb", s7_D_ldst},
367 {"sb!", s7_D_ldst},
368 {"sbp!", s7_D_ldst},
369 {"sh", s7_D_ldst},
370 {"sh!", s7_D_ldst},
371 {"shp!", s7_D_ldst},
372 {"sw", s7_D_ldst},
373 {"sw!", s7_D_ldst},
374 {"swp!", s7_D_ldst},
375 {"alw", s7_D_ldst},
376 {"asw", s7_D_ldst},
377 {"push!", s7_D_ldst},
378 {"pushhi!", s7_D_ldst},
379 {"pop!", s7_D_ldst},
380 {"pophi!", s7_D_ldst},
381 {"ldc1", s7_D_ldst},
382 {"ldc2", s7_D_ldst},
383 {"ldc3", s7_D_ldst},
384 {"stc1", s7_D_ldst},
385 {"stc2", s7_D_ldst},
386 {"stc3", s7_D_ldst},
387 {"scb", s7_D_ldst},
388 {"scw", s7_D_ldst},
389 {"sce", s7_D_ldst},
390 /* load combine instruction. */
391 {"lcb", s7_D_ldcombine},
392 {"lcw", s7_D_ldcombine},
393 {"lce", s7_D_ldcombine},
396 static const struct s7_data_dependency s7_data_dependency_table[] =
398 /* Condition register. */
399 {s7_D_mtcr, "cr1", s7_D_pce, "", 2, 1, 0},
400 {s7_D_mtcr, "cr1", s7_D_cond_br, "", 1, 0, 1},
401 {s7_D_mtcr, "cr1", s7_D_cond_mv, "", 1, 0, 1},
402 /* Status register. */
403 {s7_D_mtcr, "cr0", s7_D_all_insn, "", 5, 4, 0},
404 /* CCR register. */
405 {s7_D_mtcr, "cr4", s7_D_all_insn, "", 6, 5, 0},
406 /* EntryHi/EntryLo register. */
407 {s7_D_mftlb, "", s7_D_mtptlb, "", 1, 1, 1},
408 {s7_D_mftlb, "", s7_D_mtrtlb, "", 1, 1, 1},
409 {s7_D_mftlb, "", s7_D_stlb, "", 1, 1,1},
410 {s7_D_mftlb, "", s7_D_mfcr, "cr11", 1, 1, 1},
411 {s7_D_mftlb, "", s7_D_mfcr, "cr12", 1, 1, 1},
412 /* Index register. */
413 {s7_D_stlb, "", s7_D_mtptlb, "", 1, 1, 1},
414 {s7_D_stlb, "", s7_D_mftlb, "", 1, 1, 1},
415 {s7_D_stlb, "", s7_D_mfcr, "cr8", 2, 2, 1},
416 /* Cache. */
417 {s7_D_cached, "", s7_D_ldst, "", 1, 1, 0},
418 {s7_D_cached, "", s7_D_ldcombine, "", 1, 1, 0},
419 {s7_D_cachei, "", s7_D_all_insn, "", 5, 4, 0},
420 /* Load combine. */
421 {s7_D_ldcombine, "", s7_D_mfsr, "sr1", 3, 3, 1},
426 /* Used to contain constructed error messages. */
427 static char s7_err_msg[255];
428 static int s7_fix_data_dependency = 0;
429 static int s7_warn_fix_data_dependency = 1;
431 static int s7_in_my_get_expression = 0;
433 /* Default, pop warning message when using r1. */
434 static int s7_nor1 = 1;
436 /* Default will do instruction relax, -O0 will set s7_g_opt = 0. */
437 static unsigned int s7_g_opt = 1;
439 /* The size of the small data section. */
440 static unsigned int s7_g_switch_value = 8;
442 static segT s7_pdr_seg;
444 struct s7_score_it
446 char name[s7_INSN_NAME_LEN];
447 unsigned long instruction;
448 unsigned long relax_inst;
449 int size;
450 int relax_size;
451 enum score_insn_type type;
452 char str[s7_MAX_LITERAL_POOL_SIZE];
453 const char *error;
454 int bwarn;
455 char reg[s7_INSN_NAME_LEN];
456 struct
458 bfd_reloc_code_real_type type;
459 expressionS exp;
460 int pc_rel;
461 }reloc;
463 static struct s7_score_it s7_inst;
465 typedef struct proc
467 symbolS *isym;
468 unsigned long reg_mask;
469 unsigned long reg_offset;
470 unsigned long fpreg_mask;
471 unsigned long leaf;
472 unsigned long frame_offset;
473 unsigned long frame_reg;
474 unsigned long pc_reg;
475 } s7_procS;
476 static s7_procS s7_cur_proc;
477 static s7_procS *s7_cur_proc_ptr;
478 static int s7_numprocs;
480 /* Structure for a hash table entry for a register. */
481 struct s7_reg_entry
483 const char *name;
484 int number;
487 static const struct s7_reg_entry s7_score_rn_table[] =
489 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
490 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
491 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
492 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
493 {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
494 {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
495 {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
496 {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
497 {NULL, 0}
500 static const struct s7_reg_entry s7_score_srn_table[] =
502 {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
503 {NULL, 0}
506 static const struct s7_reg_entry s7_score_crn_table[] =
508 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
509 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
510 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
511 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
512 {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
513 {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
514 {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
515 {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
516 {NULL, 0}
519 struct s7_reg_map
521 const struct s7_reg_entry *names;
522 int max_regno;
523 struct hash_control *htab;
524 const char *expected;
527 static struct s7_reg_map s7_all_reg_maps[] =
529 {s7_score_rn_table, 31, NULL, N_("S+core register expected")},
530 {s7_score_srn_table, 2, NULL, N_("S+core special-register expected")},
531 {s7_score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
534 static struct hash_control *s7_score_ops_hsh = NULL;
535 static struct hash_control *s7_dependency_insn_hsh = NULL;
538 struct s7_datafield_range
540 int data_type;
541 int bits;
542 int range[2];
545 static struct s7_datafield_range s7_score_df_range[] =
547 {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */
548 {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */
549 {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */
550 {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */
551 {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
552 {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
553 {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */
554 {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */
555 {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */
556 {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */
557 {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
558 {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */
559 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */
560 {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
561 {_IMM20, 20, {0, (1 << 20) - 1}},
562 {_IMM25, 25, {0, (1 << 25) - 1}},
563 {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */
564 {_DISP11div2, 11, {0, 0}},
565 {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */
566 {_DISP24div2, 24, {0, 0}},
567 {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}},
568 {_VALUE_HI16, 16, {0, (1 << 16) - 1}},
569 {_VALUE_LO16, 16, {0, (1 << 16) - 1}},
570 {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}},
571 {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
572 {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */
573 {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */
574 {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
575 {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */
576 {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */
577 {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */
578 {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */
579 {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */
580 {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */
581 {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */
582 {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */
583 {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
584 {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
585 {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */
586 {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */
587 {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */
588 {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */
589 {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
590 {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
591 {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
595 struct s7_asm_opcode
597 /* Instruction name. */
598 const char *template_name;
600 /* Instruction Opcode. */
601 bfd_vma value;
603 /* Instruction bit mask. */
604 bfd_vma bitmask;
606 /* Relax instruction opcode. 0x8000 imply no relaxation. */
607 bfd_vma relax_value;
609 /* Instruction type. */
610 enum score_insn_type type;
612 /* Function to call to parse args. */
613 void (*parms) (char *);
616 static const struct s7_asm_opcode s7_score_ldst_insns[] =
618 {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, s7_do_ldst_insn},
619 {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
620 {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
621 {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, s7_do_ldst_insn},
622 {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
623 {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
624 {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn},
625 {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
626 {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
627 {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn},
628 {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
629 {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
630 {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, s7_do_ldst_insn},
631 {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
632 {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
633 {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, s7_do_ldst_insn},
634 {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
635 {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
636 {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, s7_do_ldst_insn},
637 {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn},
638 {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn},
639 {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, s7_do_ldst_insn},
640 {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn},
641 {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn},
644 static const struct s7_asm_opcode s7_score_insns[] =
646 {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
647 {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
648 {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
649 {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, s7_do_rdrsrs},
650 {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
651 {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
652 {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, s7_do_rdrsrs},
653 {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
654 {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
655 {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16},
656 {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16},
657 {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14},
658 {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14},
659 {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, s7_do16_rdrs},
660 {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, s7_do16_rdrs},
661 {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4},
662 {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16},
663 {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16},
664 {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14},
665 {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14},
666 {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
667 {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, s7_do_rdrsrs},
668 {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
669 {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
670 {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
671 {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
672 {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
673 {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
674 {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, s7_do16_rdrs},
675 {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
676 {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
677 {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
678 {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
679 {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
680 {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
681 {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, s7_do16_branch},
682 {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, s7_do16_branch},
683 {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, s7_do16_branch},
684 {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
685 {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
686 {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, s7_do16_branch},
687 {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
688 {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
689 {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
690 {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
691 {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
692 {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
693 {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, s7_do16_branch},
694 {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, s7_do16_branch},
695 {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, s7_do16_branch},
696 {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, s7_do_rdrsi5},
697 {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
698 {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, s7_do_rdrsi5},
699 {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, s7_do_xrsi5},
700 {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, s7_do_rdrsi5},
701 {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, s7_do16_rdi5},
702 {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, s7_do16_rdi5},
703 {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, s7_do16_rdi5},
704 {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, s7_do16_rdi5},
705 {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
706 {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
707 {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
708 {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
709 {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
710 {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
711 {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
712 {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, s7_do16_branch},
713 {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, s7_do16_branch},
714 {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, s7_do16_branch},
715 {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
716 {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
717 {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, s7_do16_branch},
718 {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
719 {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
720 {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, s7_do16_branch},
721 {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
722 {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
723 {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, s7_do16_branch},
724 {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, s7_do_rs},
725 {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, s7_do_rs},
726 {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, s7_do_rs},
727 {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, s7_do_rs},
728 {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, s7_do_rs},
729 {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, s7_do_rs},
730 {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, s7_do_rs},
731 {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, s7_do_rs},
732 {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, s7_do_rs},
733 {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, s7_do_rs},
734 {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, s7_do_rs},
735 {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, s7_do_rs},
736 {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, s7_do_rs},
737 {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, s7_do_rs},
738 {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, s7_do_rs},
739 {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, s7_do_rs},
740 {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, s7_do_rs},
741 {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, s7_do_rs},
742 {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, s7_do_rs},
743 {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, s7_do_rs},
744 {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, s7_do_rs},
745 {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, s7_do_rs},
746 {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, s7_do_rs},
747 {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, s7_do_rs},
748 {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, s7_do_rs},
749 {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, s7_do_rs},
750 {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, s7_do_rs},
751 {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, s7_do_rs},
752 {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, s7_do_rs},
753 {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, s7_do_rs},
754 {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, s7_do_rs},
755 {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, s7_do_rs},
756 {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, s7_do16_xrs},
757 {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, s7_do16_xrs},
758 {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, s7_do16_xrs},
759 {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, s7_do16_xrs},
760 {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, s7_do16_xrs},
761 {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, s7_do16_xrs},
762 {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, s7_do16_xrs},
763 {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, s7_do16_xrs},
764 {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, s7_do16_xrs},
765 {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, s7_do16_xrs},
766 {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, s7_do16_xrs},
767 {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, s7_do16_xrs},
768 {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, s7_do16_xrs},
769 {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, s7_do16_xrs},
770 {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, s7_do16_xrs},
771 {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, s7_do16_xrs},
772 {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, s7_do16_xrs},
773 {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, s7_do16_xrs},
774 {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, s7_do16_xrs},
775 {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, s7_do16_xrs},
776 {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, s7_do16_xrs},
777 {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, s7_do16_xrs},
778 {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, s7_do16_xrs},
779 {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, s7_do16_xrs},
780 {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, s7_do16_xrs},
781 {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, s7_do16_xrs},
782 {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, s7_do16_xrs},
783 {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, s7_do16_xrs},
784 {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, s7_do16_xrs},
785 {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, s7_do16_xrs},
786 {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, s7_do16_xrs},
787 {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, s7_do16_xrs},
788 {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
789 {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
790 {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
791 {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch},
792 {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, s7_do16_branch},
793 {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, s7_do16_branch},
794 {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, s7_do16_branch},
795 {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch},
796 {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s7_do_cache},
797 {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s7_do_ceinst},
798 {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
799 {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
800 {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
801 {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, s7_do_rsrs},
802 {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
803 {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
804 {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs},
805 {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16},
806 {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, s7_do16_rdrs},
807 {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
808 {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
809 {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5},
810 {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
811 {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
812 {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
813 {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
814 {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
815 {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
816 {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
817 {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
818 {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
819 {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump},
820 {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, s7_do16_jump},
821 {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, s7_do16_jump},
822 {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump},
823 {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, s7_do16_ldst_insn},
824 {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
825 {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s7_do_ldst_atomic},
826 {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s7_do_ldst_unalign},
827 {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign},
828 {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign},
829 {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
830 {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
831 {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop},
832 {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, s7_do16_ldst_insn},
833 {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
834 {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, s7_do_rdsi16},
835 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s7_do_rdi16},
836 {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, s7_do16_ldst_imm_insn},
837 {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, s7_do16_ldst_insn},
838 {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn},
839 {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
840 {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, s7_do16_rs},
841 {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
842 {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, s7_do16_rdrs},
843 {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
844 {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
845 {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, s7_do16_rdrs},
846 {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
847 {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
848 {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, s7_do16_rdrs},
849 {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
850 {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, s7_do16_rdrs},
851 {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
852 {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
853 {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
854 {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
855 {"mazh.f!", 0x1009, 0x700f, 0x38000383, Rd_Rs, s7_do16_rdrs},
856 {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
857 {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
858 {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, s7_do16_rdrs},
859 {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
860 {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, s7_do16_rs},
861 {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
862 {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s7_do_rdsrs},
863 {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
864 {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
865 {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
866 {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
867 {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
868 {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
869 {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
870 {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, s7_do16_hrdrs},
871 {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
872 {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, s7_do16_rdhrs},
873 {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
874 {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, s7_do16_rdrs},
875 {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
876 {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
877 {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, s7_do16_rdrs},
878 {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
879 {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
880 {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, s7_do16_rdrs},
881 {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
882 {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, s7_do16_rdrs},
883 {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
884 {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
885 {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
886 {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, s7_do16_rdrs},
887 {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
888 {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs},
889 {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, s7_do16_rdrs},
890 {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, s7_do16_rs},
891 {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
892 {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd},
893 {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, s7_do16_rs},
894 {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
895 {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s7_do_rdsrs},
896 {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
897 {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
898 {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
899 {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
900 {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
901 {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
902 {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs},
903 {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, s7_do16_rdrs},
904 {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, s7_do16_rdrs},
905 {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
906 {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
907 {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
908 {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
909 {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
910 {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
911 {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
912 {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
913 {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
914 {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
915 {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
916 {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
917 {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
918 {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs},
919 {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, s7_do_rdrs},
920 {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, s7_do16_mv_rdrs},
921 {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s7_do_rdxrs},
922 {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, s7_do_rdxrs},
923 {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, s7_do16_rdrs},
924 {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s7_do_empty},
925 {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs},
926 {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, s7_do_rdrs},
927 {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, s7_do_empty},
928 {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, s7_do16_rdrs},
929 {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
930 {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, s7_do_rdrsrs},
931 {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
932 {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
933 {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
934 {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16},
935 {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
936 {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14},
937 {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, s7_do16_rdrs},
938 {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
939 {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, s7_do16_push_pop},
940 {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, s7_do16_push_pop},
941 {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
942 {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
943 {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
944 {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
945 {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
946 {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
947 {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
948 {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
949 {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
950 {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
951 {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
952 {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
953 {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
954 {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, s7_do16_ldst_insn},
955 {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
956 {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s7_do_ldst_atomic},
957 {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign},
958 {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign},
959 {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s7_do_ldst_unalign},
960 {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, s7_do_xi5x},
961 {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, s7_do16_xi5},
962 {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, s7_do16_ldst_insn},
963 {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
964 {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
965 {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
966 {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, s7_do_rdrsrs},
967 {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
968 {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
969 {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, s7_do_rdrsi5},
970 {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, s7_do16_rdrs},
971 {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, s7_do16_rdi5},
972 {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
973 {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, s7_do_rdrsrs},
974 {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
975 {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, s7_do_rdrsrs},
976 {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
977 {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, s7_do_rdrsi5},
978 {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
979 {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5},
980 {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, s7_do16_rdrs},
981 {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, s7_do16_rdrs},
982 {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, s7_do16_rdi5},
983 {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
984 {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
985 {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop},
986 {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
987 {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, s7_do_rdrsrs},
988 {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
989 {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
990 {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
991 {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, s7_do16_rdrs},
992 {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4},
993 {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, s7_do16_ldst_insn},
994 {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn},
995 {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s7_do_i15},
996 {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, s7_do_empty},
997 {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, s7_do_empty},
998 {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, s7_do_empty},
999 {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, s7_do_empty},
1000 {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, s7_do_empty},
1001 {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, s7_do_empty},
1002 {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, s7_do_empty},
1003 {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, s7_do_empty},
1004 {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, s7_do_empty},
1005 {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, s7_do_empty},
1006 {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, s7_do_empty},
1007 {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, s7_do_empty},
1008 {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, s7_do_empty},
1009 {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, s7_do_empty},
1010 {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, s7_do_empty},
1011 {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, s7_do_empty},
1012 {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, s7_do_empty},
1013 {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1014 {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1015 {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1016 {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty},
1017 {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, s7_do_empty},
1018 {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, s7_do_empty},
1019 {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, s7_do_empty},
1020 {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, s7_do_empty},
1021 {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, s7_do_empty},
1022 {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, s7_do_empty},
1023 {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, s7_do_empty},
1024 {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, s7_do_empty},
1025 {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, s7_do_empty},
1026 {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1027 {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1028 {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1029 {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1030 {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1031 {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1032 {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1033 {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1034 {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1035 {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1036 {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1037 {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1038 {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1039 {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1040 {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x},
1041 {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, s7_do_empty},
1042 {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, s7_do_empty},
1043 {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, s7_do_empty},
1044 {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, s7_do_empty},
1045 {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, s7_do_empty},
1046 {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, s7_do_empty},
1047 {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs},
1048 {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, s7_do_rdrsrs},
1049 {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, s7_do16_rdrs},
1050 /* Macro instruction. */
1051 {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_li_rdi32},
1052 /* la reg, imm32 -->(1) ldi reg, simm16
1053 (2) ldis reg, %HI(imm32)
1054 ori reg, %LO(imm32)
1056 la reg, symbol -->(1) lis reg, %HI(imm32)
1057 ori reg, %LO(imm32) */
1058 {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_la_rdi32},
1059 {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1060 {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1061 {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1062 {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1063 {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1064 {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1065 {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1066 {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1067 {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1068 {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs},
1069 {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label},
1070 {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, s7_do_macro_ldst_label},
1071 {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, s7_do_macro_ldst_label},
1072 {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label},
1073 {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, s7_do_macro_ldst_label},
1074 {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, s7_do_macro_ldst_label},
1075 {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, s7_do_macro_ldst_label},
1076 {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, s7_do_macro_ldst_label},
1077 /* Assembler use internal. */
1078 {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s7_do_macro_rdi32hi},
1079 {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_macro_rdi32lo},
1080 {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, s7_do_rdi16_pic},
1081 {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_s_pic},
1082 {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_u_pic},
1083 {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s7_do_lw_pic},
1086 #define s7_SCORE5_PIPELINE 5
1087 #define s7_SCORE7_PIPELINE 7
1089 static int s7_university_version = 0;
1090 static int s7_vector_size = s7_SCORE7_PIPELINE;
1091 static struct s7_score_it s7_dependency_vector[s7_SCORE7_PIPELINE];
1093 static int s7_score7d = 1;
1097 static int
1098 s7_end_of_line (char *str)
1100 int retval = s7_SUCCESS;
1102 s7_skip_whitespace (str);
1103 if (*str != '\0')
1105 retval = (int) s7_FAIL;
1107 if (!s7_inst.error)
1108 s7_inst.error = s7_BAD_GARBAGE;
1111 return retval;
1114 static int
1115 s7_score_reg_parse (char **ccp, struct hash_control *htab)
1117 char *start = *ccp;
1118 char c;
1119 char *p;
1120 struct s7_reg_entry *reg;
1122 p = start;
1123 if (!ISALPHA (*p) || !is_name_beginner (*p))
1124 return (int) s7_FAIL;
1126 c = *p++;
1128 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1129 c = *p++;
1131 *--p = 0;
1132 reg = (struct s7_reg_entry *) hash_find (htab, start);
1133 *p = c;
1135 if (reg)
1137 *ccp = p;
1138 return reg->number;
1140 return (int) s7_FAIL;
1143 /* If shift <= 0, only return reg. */
1144 static int
1145 s7_reg_required_here (char **str, int shift, enum s7_score_reg_type reg_type)
1147 static char buff[s7_MAX_LITERAL_POOL_SIZE];
1148 int reg = (int) s7_FAIL;
1149 char *start = *str;
1151 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[reg_type].htab)) != (int) s7_FAIL)
1153 if (reg_type == s7_REG_TYPE_SCORE)
1155 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
1157 as_warn (_("Using temp register(r1)"));
1158 s7_inst.bwarn = 1;
1161 if (shift >= 0)
1163 if (reg_type == s7_REG_TYPE_SCORE_CR)
1164 strcpy (s7_inst.reg, s7_score_crn_table[reg].name);
1165 else if (reg_type == s7_REG_TYPE_SCORE_SR)
1166 strcpy (s7_inst.reg, s7_score_srn_table[reg].name);
1167 else
1168 strcpy (s7_inst.reg, "");
1170 s7_inst.instruction |= reg << shift;
1173 else
1175 *str = start;
1176 sprintf (buff, _("register expected, not '%.100s'"), start);
1177 s7_inst.error = buff;
1180 return reg;
1183 static int
1184 s7_skip_past_comma (char **str)
1186 char *p = *str;
1187 char c;
1188 int comma = 0;
1190 while ((c = *p) == ' ' || c == ',')
1192 p++;
1193 if (c == ',' && comma++)
1195 s7_inst.error = s7_BAD_SKIP_COMMA;
1196 return (int) s7_FAIL;
1200 if ((c == '\0') || (comma == 0))
1202 s7_inst.error = s7_BAD_SKIP_COMMA;
1203 return (int) s7_FAIL;
1206 *str = p;
1207 return comma ? s7_SUCCESS : (int) s7_FAIL;
1210 static void
1211 s7_do_rdrsrs (char *str)
1213 s7_skip_whitespace (str);
1215 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1216 || s7_skip_past_comma (&str) == (int) s7_FAIL
1217 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1218 || s7_skip_past_comma (&str) == (int) s7_FAIL
1219 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1220 || s7_end_of_line (str) == (int) s7_FAIL)
1222 return;
1224 else
1226 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
1227 && (((s7_inst.instruction >> 10) & 0x10) == 0)
1228 && (((s7_inst.instruction >> 20) & 0x10) == 0)
1229 && (s7_inst.relax_inst != 0x8000)
1230 && (((s7_inst.instruction >> 20) & 0xf) == ((s7_inst.instruction >> 15) & 0xf)))
1232 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4)
1233 | (((s7_inst.instruction >> 15) & 0xf) << 8);
1234 s7_inst.relax_size = 2;
1236 else
1238 s7_inst.relax_inst = 0x8000;
1243 static int
1244 s7_walk_no_bignums (symbolS * sp)
1246 if (symbol_get_value_expression (sp)->X_op == O_big)
1247 return 1;
1249 if (symbol_get_value_expression (sp)->X_add_symbol)
1250 return (s7_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1251 || (symbol_get_value_expression (sp)->X_op_symbol
1252 && s7_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1254 return 0;
1257 static int
1258 s7_my_get_expression (expressionS * ep, char **str)
1260 char *save_in;
1262 save_in = input_line_pointer;
1263 input_line_pointer = *str;
1264 s7_in_my_get_expression = 1;
1266 (void) expression (ep);
1267 s7_in_my_get_expression = 0;
1269 if (ep->X_op == O_illegal)
1271 *str = input_line_pointer;
1272 input_line_pointer = save_in;
1273 s7_inst.error = _("illegal expression");
1274 return (int) s7_FAIL;
1276 /* Get rid of any bignums now, so that we don't generate an error for which
1277 we can't establish a line number later on. Big numbers are never valid
1278 in instructions, which is where this routine is always called. */
1279 if (ep->X_op == O_big
1280 || (ep->X_add_symbol
1281 && (s7_walk_no_bignums (ep->X_add_symbol)
1282 || (ep->X_op_symbol && s7_walk_no_bignums (ep->X_op_symbol)))))
1284 s7_inst.error = _("invalid constant");
1285 *str = input_line_pointer;
1286 input_line_pointer = save_in;
1287 return (int) s7_FAIL;
1290 if ((ep->X_add_symbol != NULL)
1291 && (s7_inst.type != PC_DISP19div2)
1292 && (s7_inst.type != PC_DISP8div2)
1293 && (s7_inst.type != PC_DISP24div2)
1294 && (s7_inst.type != PC_DISP11div2)
1295 && (s7_inst.type != Insn_Type_SYN)
1296 && (s7_inst.type != Rd_rvalueRs_SI15)
1297 && (s7_inst.type != Rd_lvalueRs_SI15)
1298 && (s7_inst.type != Insn_internal))
1300 s7_inst.error = s7_BAD_ARGS;
1301 *str = input_line_pointer;
1302 input_line_pointer = save_in;
1303 return (int) s7_FAIL;
1306 *str = input_line_pointer;
1307 input_line_pointer = save_in;
1308 return s7_SUCCESS;
1311 /* Check if an immediate is valid. If so, convert it to the right format. */
1313 static bfd_signed_vma
1314 s7_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
1316 switch (data_type)
1318 case _VALUE_HI16:
1320 int val_hi = ((val & 0xffff0000) >> 16);
1322 if (s7_score_df_range[data_type].range[0] <= val_hi
1323 && val_hi <= s7_score_df_range[data_type].range[1])
1324 return val_hi;
1326 break;
1328 case _VALUE_LO16:
1330 int val_lo = (val & 0xffff);
1332 if (s7_score_df_range[data_type].range[0] <= val_lo
1333 && val_lo <= s7_score_df_range[data_type].range[1])
1334 return val_lo;
1336 break;
1338 case _SIMM12:
1339 if (hex_p == 1)
1341 if (!(val >= -0x800 && val <= 0xfff))
1343 return (int) s7_FAIL;
1346 else
1348 if (!(val >= -2048 && val <= 2047))
1350 return (int) s7_FAIL;
1354 return val;
1355 break;
1357 case _SIMM14:
1358 if (hex_p == 1)
1360 if (!(val >= -0x2000 && val <= 0x3fff))
1362 return (int) s7_FAIL;
1365 else
1367 if (!(val >= -8192 && val <= 8191))
1369 return (int) s7_FAIL;
1373 return val;
1374 break;
1376 case _SIMM15:
1377 if (hex_p == 1)
1379 if (!(val >= -0x4000 && val <= 0x7fff))
1381 return (int) s7_FAIL;
1384 else
1386 if (!(val >= -16384 && val <= 16383))
1388 return (int) s7_FAIL;
1392 return val;
1393 break;
1395 case _SIMM16:
1396 if (hex_p == 1)
1398 if (!(val >= -0x8000 && val <= 0xffff))
1400 return (int) s7_FAIL;
1403 else
1405 if (!(val >= -32768 && val <= 32767))
1407 return (int) s7_FAIL;
1411 return val;
1412 break;
1414 case _SIMM16_NEG:
1415 if (hex_p == 1)
1417 if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1419 return (int) s7_FAIL;
1422 else
1424 if (!(val >= -32767 && val <= 32768))
1426 return (int) s7_FAIL;
1430 val = -val;
1431 return val;
1432 break;
1434 case _IMM32:
1435 if (val >= 0 && val <= 0xffffffff)
1437 return val;
1439 else
1441 return (int) s7_FAIL;
1444 default:
1445 if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1446 val = -val;
1448 if (s7_score_df_range[data_type].range[0] <= val
1449 && val <= s7_score_df_range[data_type].range[1])
1450 return val;
1452 break;
1455 return (int) s7_FAIL;
1458 static int
1459 s7_data_op2 (char **str, int shift, enum score_data_type data_type)
1461 int value;
1462 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
1463 char *dataptr;
1464 int cnt = 0;
1465 char *pp = NULL;
1467 s7_skip_whitespace (*str);
1468 s7_inst.error = NULL;
1469 dataptr = * str;
1471 /* Set hex_p to zero. */
1472 int hex_p = 0;
1474 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
1476 data_exp[cnt] = *dataptr;
1477 dataptr++;
1478 cnt++;
1481 data_exp[cnt] = '\0';
1482 pp = (char *)&data_exp;
1484 if (*dataptr == '|') /* process PCE */
1486 if (s7_my_get_expression (&s7_inst.reloc.exp, &pp) == (int) s7_FAIL)
1487 return (int) s7_FAIL;
1488 s7_end_of_line (pp);
1489 if (s7_inst.error != 0)
1490 return (int) s7_FAIL; /* to ouptut_inst to printf out the error */
1491 *str = dataptr;
1493 else /* process 16 bit */
1495 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
1497 return (int) s7_FAIL;
1500 dataptr = (char *) data_exp;
1501 for (; *dataptr != '\0'; dataptr++)
1503 *dataptr = TOLOWER (*dataptr);
1504 if (*dataptr == '!' || *dataptr == ' ')
1505 break;
1507 dataptr = (char *) data_exp;
1509 if ((dataptr != NULL)
1510 && (((strstr (dataptr, "0x")) != NULL)
1511 || ((strstr (dataptr, "0X")) != NULL)))
1513 hex_p = 1;
1514 if ((data_type != _SIMM16_LA)
1515 && (data_type != _VALUE_HI16)
1516 && (data_type != _VALUE_LO16)
1517 && (data_type != _IMM16)
1518 && (data_type != _IMM15)
1519 && (data_type != _IMM14)
1520 && (data_type != _IMM4)
1521 && (data_type != _IMM5)
1522 && (data_type != _IMM8)
1523 && (data_type != _IMM5_RSHIFT_1)
1524 && (data_type != _IMM5_RSHIFT_2)
1525 && (data_type != _SIMM14)
1526 && (data_type != _SIMM16)
1527 && (data_type != _SIMM14_NEG)
1528 && (data_type != _SIMM16_NEG)
1529 && (data_type != _IMM10_RSHIFT_2)
1530 && (data_type != _GP_IMM15))
1532 data_type += 24;
1536 if ((s7_inst.reloc.exp.X_add_number == 0)
1537 /* for "addi r0,-((((((32*4)+4)+4)+4)+4)&0xf)". */
1538 && (s7_inst.type != Rd_SI16)
1539 && (s7_inst.type != Insn_Type_SYN)
1540 && (s7_inst.type != Rd_rvalueRs_SI15)
1541 && (s7_inst.type != Rd_lvalueRs_SI15)
1542 && (s7_inst.type != Insn_internal)
1543 && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1544 || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1545 || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1546 || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1548 s7_inst.error = s7_BAD_ARGS;
1549 return (int) s7_FAIL;
1553 if ((s7_inst.reloc.exp.X_add_symbol)
1554 && ((data_type == _SIMM16)
1555 || (data_type == _SIMM16_NEG)
1556 || (data_type == _IMM16_NEG)
1557 || (data_type == _SIMM14)
1558 || (data_type == _SIMM14_NEG)
1559 || (data_type == _IMM5)
1560 || (data_type == _IMM14)
1561 || (data_type == _IMM20)
1562 || (data_type == _IMM16)
1563 || (data_type == _IMM15)
1564 || (data_type == _IMM4)))
1566 s7_inst.error = s7_BAD_ARGS;
1567 return (int) s7_FAIL;
1570 if (s7_inst.reloc.exp.X_add_symbol)
1572 switch (data_type)
1574 case _SIMM16_LA:
1575 return (int) s7_FAIL;
1576 case _VALUE_HI16:
1577 s7_inst.reloc.type = BFD_RELOC_HI16_S;
1578 s7_inst.reloc.pc_rel = 0;
1579 break;
1580 case _VALUE_LO16:
1581 s7_inst.reloc.type = BFD_RELOC_LO16;
1582 s7_inst.reloc.pc_rel = 0;
1583 break;
1584 case _GP_IMM15:
1585 s7_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1586 s7_inst.reloc.pc_rel = 0;
1587 break;
1588 case _SIMM16_pic:
1589 case _IMM16_LO16_pic:
1590 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1591 s7_inst.reloc.pc_rel = 0;
1592 break;
1593 default:
1594 s7_inst.reloc.type = BFD_RELOC_32;
1595 s7_inst.reloc.pc_rel = 0;
1596 break;
1599 else
1601 if (data_type == _IMM16_pic)
1603 s7_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1604 s7_inst.reloc.pc_rel = 0;
1607 if (data_type == _SIMM16_LA && s7_inst.reloc.exp.X_unsigned == 1)
1609 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
1610 if (value == (int) s7_FAIL) /* for advance to check if this is ldis */
1611 if ((s7_inst.reloc.exp.X_add_number & 0xffff) == 0)
1613 s7_inst.instruction |= 0x8000000;
1614 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1615 return s7_SUCCESS;
1618 else
1620 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
1623 if (value == (int) s7_FAIL)
1625 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1627 sprintf (s7_err_msg,
1628 _("invalid constant: %d bit expression not in range %d..%d"),
1629 s7_score_df_range[data_type].bits,
1630 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
1632 else
1634 sprintf (s7_err_msg,
1635 _("invalid constant: %d bit expression not in range %d..%d"),
1636 s7_score_df_range[data_type].bits,
1637 -s7_score_df_range[data_type].range[1], -s7_score_df_range[data_type].range[0]);
1640 s7_inst.error = s7_err_msg;
1641 return (int) s7_FAIL;
1644 if ((s7_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1646 value &= (1 << s7_score_df_range[data_type].bits) - 1;
1649 s7_inst.instruction |= value << shift;
1652 if ((s7_inst.instruction & 0x3e000000) == 0x30000000)
1654 if ((((s7_inst.instruction >> 20) & 0x1F) != 0)
1655 && (((s7_inst.instruction >> 20) & 0x1F) != 1)
1656 && (((s7_inst.instruction >> 20) & 0x1F) != 2)
1657 && (((s7_inst.instruction >> 20) & 0x1F) != 3)
1658 && (((s7_inst.instruction >> 20) & 0x1F) != 4)
1659 && (((s7_inst.instruction >> 20) & 0x1F) != 8)
1660 && (((s7_inst.instruction >> 20) & 0x1F) != 9)
1661 && (((s7_inst.instruction >> 20) & 0x1F) != 0xa)
1662 && (((s7_inst.instruction >> 20) & 0x1F) != 0xb)
1663 && (((s7_inst.instruction >> 20) & 0x1F) != 0xc)
1664 && (((s7_inst.instruction >> 20) & 0x1F) != 0xd)
1665 && (((s7_inst.instruction >> 20) & 0x1F) != 0xe)
1666 && (((s7_inst.instruction >> 20) & 0x1F) != 0x10)
1667 && (((s7_inst.instruction >> 20) & 0x1F) != 0x11)
1668 && (((s7_inst.instruction >> 20) & 0x1F) != 0x18)
1669 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1A)
1670 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1B)
1671 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1d)
1672 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1e)
1673 && (((s7_inst.instruction >> 20) & 0x1F) != 0x1f))
1675 s7_inst.error = _("invalid constant: bit expression not defined");
1676 return (int) s7_FAIL;
1680 return s7_SUCCESS;
1683 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
1685 static void
1686 s7_do_rdsi16 (char *str)
1688 s7_skip_whitespace (str);
1690 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1691 || s7_skip_past_comma (&str) == (int) s7_FAIL
1692 || s7_data_op2 (&str, 1, _SIMM16) == (int) s7_FAIL
1693 || s7_end_of_line (str) == (int) s7_FAIL)
1694 return;
1696 /* ldi. */
1697 if ((s7_inst.instruction & 0x20c0000) == 0x20c0000)
1699 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10) || ((s7_inst.instruction & 0x1fe00) != 0))
1701 s7_inst.relax_inst = 0x8000;
1703 else
1705 s7_inst.relax_inst |= (s7_inst.instruction >> 1) & 0xff;
1706 s7_inst.relax_inst |= (((s7_inst.instruction >> 20) & 0xf) << 8);
1707 s7_inst.relax_size = 2;
1710 else if (((s7_inst.instruction >> 20) & 0x10) == 0x10)
1712 s7_inst.relax_inst = 0x8000;
1716 /* Handle subi/subi.c. */
1718 static void
1719 s7_do_sub_rdsi16 (char *str)
1721 s7_skip_whitespace (str);
1723 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1724 && s7_skip_past_comma (&str) != (int) s7_FAIL
1725 && s7_data_op2 (&str, 1, _SIMM16_NEG) != (int) s7_FAIL)
1726 s7_end_of_line (str);
1730 /* Handle addri/addri.c. */
1732 static void
1733 s7_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1735 s7_skip_whitespace (str);
1737 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1738 && s7_skip_past_comma (&str) != (int) s7_FAIL
1739 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1740 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1741 s7_data_op2 (&str, 1, _SIMM14);
1744 /* Handle subri.c/subri. */
1746 static void
1747 s7_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
1749 s7_skip_whitespace (str);
1751 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1752 && s7_skip_past_comma (&str) != (int) s7_FAIL
1753 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1754 && s7_skip_past_comma (&str) != (int) s7_FAIL
1755 && s7_data_op2 (&str, 1, _SIMM14_NEG) != (int) s7_FAIL)
1756 s7_end_of_line (str);
1759 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */
1761 static void
1762 s7_do_rdrsi5 (char *str) /* 0~((2^14)-1) */
1764 s7_skip_whitespace (str);
1766 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1767 || s7_skip_past_comma (&str) == (int) s7_FAIL
1768 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1769 || s7_skip_past_comma (&str) == (int) s7_FAIL
1770 || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
1771 || s7_end_of_line (str) == (int) s7_FAIL)
1772 return;
1774 if ((((s7_inst.instruction >> 20) & 0x1f) == ((s7_inst.instruction >> 15) & 0x1f))
1775 && (s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1777 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1778 s7_inst.relax_size = 2;
1780 else
1781 s7_inst.relax_inst = 0x8000;
1784 /* Handle andri/orri/andri.c/orri.c. */
1786 static void
1787 s7_do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */
1789 s7_skip_whitespace (str);
1791 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1792 && s7_skip_past_comma (&str) != (int) s7_FAIL
1793 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1794 && s7_skip_past_comma (&str) != (int) s7_FAIL
1795 && s7_data_op2 (&str, 1, _IMM14) != (int) s7_FAIL)
1796 s7_end_of_line (str);
1799 /* Handle bittst.c. */
1801 static void
1802 s7_do_xrsi5 (char *str)
1804 s7_skip_whitespace (str);
1806 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1807 || s7_skip_past_comma (&str) == (int) s7_FAIL
1808 || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
1809 || s7_end_of_line (str) == (int) s7_FAIL)
1810 return;
1812 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1814 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
1815 s7_inst.relax_size = 2;
1817 else
1818 s7_inst.relax_inst = 0x8000;
1821 /* Handle addis/andi/ori/andis/oris/ldis. */
1823 static void
1824 s7_do_rdi16 (char *str)
1826 s7_skip_whitespace (str);
1828 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1829 || s7_skip_past_comma (&str) == (int) s7_FAIL
1830 || s7_data_op2 (&str, 1, _IMM16) == (int) s7_FAIL
1831 || s7_end_of_line (str) == (int) s7_FAIL)
1832 return;
1835 static void
1836 s7_do_macro_rdi32hi (char *str)
1838 s7_skip_whitespace (str);
1840 /* Do not handle s7_end_of_line(). */
1841 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1842 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1843 s7_data_op2 (&str, 1, _VALUE_HI16);
1846 static void
1847 s7_do_macro_rdi32lo (char *str)
1849 s7_skip_whitespace (str);
1851 /* Do not handle s7_end_of_line(). */
1852 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1853 && s7_skip_past_comma (&str) != (int) s7_FAIL)
1854 s7_data_op2 (&str, 1, _VALUE_LO16);
1857 /* Handle ldis_pic. */
1859 static void
1860 s7_do_rdi16_pic (char *str)
1862 s7_skip_whitespace (str);
1864 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1865 && s7_skip_past_comma (&str) != (int) s7_FAIL
1866 && s7_data_op2 (&str, 1, _IMM16_pic) != (int) s7_FAIL)
1867 s7_end_of_line (str);
1870 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1872 static void
1873 s7_do_addi_s_pic (char *str)
1875 s7_skip_whitespace (str);
1877 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1878 && s7_skip_past_comma (&str) != (int) s7_FAIL
1879 && s7_data_op2 (&str, 1, _SIMM16_pic) != (int) s7_FAIL)
1880 s7_end_of_line (str);
1883 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1885 static void
1886 s7_do_addi_u_pic (char *str)
1888 s7_skip_whitespace (str);
1890 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
1891 && s7_skip_past_comma (&str) != (int) s7_FAIL
1892 && s7_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s7_FAIL)
1893 s7_end_of_line (str);
1896 /* Handle mfceh/mfcel/mtceh/mtchl. */
1898 static void
1899 s7_do_rd (char *str)
1901 s7_skip_whitespace (str);
1903 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL)
1904 s7_end_of_line (str);
1907 static void
1908 s7_do_rs (char *str)
1910 s7_skip_whitespace (str);
1912 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1913 || s7_end_of_line (str) == (int) s7_FAIL)
1914 return;
1916 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
1918 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8) | (((s7_inst.instruction >> 15) & 0xf) << 4);
1919 s7_inst.relax_size = 2;
1921 else
1922 s7_inst.relax_inst = 0x8000;
1925 static void
1926 s7_do_i15 (char *str)
1928 s7_skip_whitespace (str);
1930 if (s7_data_op2 (&str, 10, _IMM15) != (int) s7_FAIL)
1931 s7_end_of_line (str);
1934 static void
1935 s7_do_xi5x (char *str)
1937 s7_skip_whitespace (str);
1939 if (s7_data_op2 (&str, 15, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
1940 return;
1942 if (s7_inst.relax_inst != 0x8000)
1944 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0x1f) << 3);
1945 s7_inst.relax_size = 2;
1949 static void
1950 s7_do_rdrs (char *str)
1952 s7_skip_whitespace (str);
1954 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1955 || s7_skip_past_comma (&str) == (int) s7_FAIL
1956 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
1957 || s7_end_of_line (str) == (int) s7_FAIL)
1958 return;
1960 if (s7_inst.relax_inst != 0x8000)
1962 if (((s7_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1964 /* mlfh */
1965 if ((((s7_inst.instruction >> 15) & 0x10) != 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1967 s7_inst.relax_inst = 0x00000001 | (((s7_inst.instruction >> 15) & 0xf) << 4)
1968 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1969 s7_inst.relax_size = 2;
1971 /* mhfl */
1972 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && ((s7_inst.instruction >> 20) & 0x10) != 0)
1974 s7_inst.relax_inst = 0x00000002 | (((s7_inst.instruction >> 15) & 0xf) << 4)
1975 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1976 s7_inst.relax_size = 2;
1978 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1980 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1981 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1982 s7_inst.relax_size = 2;
1984 else
1986 s7_inst.relax_inst = 0x8000;
1989 else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
1991 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
1992 | (((s7_inst.instruction >> 20) & 0xf) << 8);
1993 s7_inst.relax_size = 2;
1995 else
1997 s7_inst.relax_inst = 0x8000;
2002 /* Handle mfcr/mtcr. */
2003 static void
2004 s7_do_rdcrs (char *str)
2006 s7_skip_whitespace (str);
2008 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2009 && s7_skip_past_comma (&str) != (int) s7_FAIL
2010 && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) != (int) s7_FAIL)
2011 s7_end_of_line (str);
2014 /* Handle mfsr/mtsr. */
2016 static void
2017 s7_do_rdsrs (char *str)
2019 s7_skip_whitespace (str);
2021 /* mfsr */
2022 if ((s7_inst.instruction & 0xff) == 0x50)
2024 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2025 && s7_skip_past_comma (&str) != (int) s7_FAIL
2026 && s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR) != (int) s7_FAIL)
2027 s7_end_of_line (str);
2029 else
2031 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
2032 && s7_skip_past_comma (&str) != (int) s7_FAIL)
2033 s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR);
2037 /* Handle neg. */
2039 static void
2040 s7_do_rdxrs (char *str)
2042 s7_skip_whitespace (str);
2044 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2045 || s7_skip_past_comma (&str) == (int) s7_FAIL
2046 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2047 || s7_end_of_line (str) == (int) s7_FAIL)
2048 return;
2050 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 10) & 0x10) == 0)
2051 && (((s7_inst.instruction >> 20) & 0x10) == 0))
2053 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 20) & 0xf) << 8);
2054 s7_inst.relax_size = 2;
2056 else
2057 s7_inst.relax_inst = 0x8000;
2060 /* Handle cmp.c/cmp<cond>. */
2061 static void
2062 s7_do_rsrs (char *str)
2064 s7_skip_whitespace (str);
2066 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2067 || s7_skip_past_comma (&str) == (int) s7_FAIL
2068 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2069 || s7_end_of_line (str) == (int) s7_FAIL)
2070 return;
2072 if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 20) & 0x1f) == 3)
2073 && (((s7_inst.instruction >> 10) & 0x10) == 0) && (((s7_inst.instruction >> 15) & 0x10) == 0))
2075 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 15) & 0xf) << 8);
2076 s7_inst.relax_size = 2;
2078 else
2079 s7_inst.relax_inst = 0x8000;
2082 static void
2083 s7_do_ceinst (char *str)
2085 char *strbak;
2087 strbak = str;
2088 s7_skip_whitespace (str);
2090 if (s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL
2091 || s7_skip_past_comma (&str) == (int) s7_FAIL
2092 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2093 || s7_skip_past_comma (&str) == (int) s7_FAIL
2094 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
2095 || s7_skip_past_comma (&str) == (int) s7_FAIL
2096 || s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL
2097 || s7_skip_past_comma (&str) == (int) s7_FAIL
2098 || s7_data_op2 (&str, 0, _IMM5) == (int) s7_FAIL
2099 || s7_end_of_line (str) == (int) s7_FAIL)
2101 return;
2103 else
2105 str = strbak;
2106 if (s7_data_op2 (&str, 0, _IMM25) == (int) s7_FAIL)
2107 return;
2111 static int
2112 s7_reglow_required_here (char **str, int shift)
2114 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2115 int reg;
2116 char *start = *str;
2118 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2120 if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
2122 as_warn (_("Using temp register(r1)"));
2123 s7_inst.bwarn = 1;
2125 if (reg < 16)
2127 if (shift >= 0)
2128 s7_inst.instruction |= reg << shift;
2130 return reg;
2134 /* Restore the start point, we may have got a reg of the wrong class. */
2135 *str = start;
2136 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
2137 s7_inst.error = buff;
2138 return (int) s7_FAIL;
2141 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
2143 static void
2144 s7_do16_rdrs (char *str)
2146 s7_skip_whitespace (str);
2148 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2149 || s7_skip_past_comma (&str) == (int) s7_FAIL
2150 || s7_reglow_required_here (&str, 4) == (int) s7_FAIL
2151 || s7_end_of_line (str) == (int) s7_FAIL)
2153 return;
2155 else
2157 if ((s7_inst.instruction & 0x700f) == 0x2003) /* cmp! */
2159 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2160 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2162 else if ((s7_inst.instruction & 0x700f) == 0x2006) /* not! */
2164 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2165 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2167 else if ((s7_inst.instruction & 0x700f) == 0x1009) /* mazh.f! */
2169 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
2170 | (((s7_inst.instruction >> 4) & 0xf) << 10);
2172 else
2174 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2175 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 4) & 0xf) << 10);
2177 s7_inst.relax_size = 4;
2181 static void
2182 s7_do16_rs (char *str)
2184 int rd = 0;
2186 s7_skip_whitespace (str);
2188 if ((rd = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL
2189 || s7_end_of_line (str) == (int) s7_FAIL)
2191 return;
2193 else
2195 s7_inst.relax_inst |= rd << 20;
2196 s7_inst.relax_size = 4;
2200 /* Handle br!/brl!. */
2202 static void
2203 s7_do16_xrs (char *str)
2205 s7_skip_whitespace (str);
2207 if (s7_reglow_required_here (&str, 4) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2209 return;
2211 else
2213 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 10)
2214 | (((s7_inst.instruction >> 4) & 0xf) << 15);
2215 s7_inst.relax_size = 4;
2219 static int
2220 s7_reghigh_required_here (char **str, int shift)
2222 static char buff[s7_MAX_LITERAL_POOL_SIZE];
2223 int reg;
2224 char *start = *str;
2226 if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
2228 if (15 < reg && reg < 32)
2230 if (shift >= 0)
2231 s7_inst.instruction |= (reg & 0xf) << shift;
2233 return reg;
2237 *str = start;
2238 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
2239 s7_inst.error = buff;
2240 return (int) s7_FAIL;
2243 /* Handle mhfl!. */
2245 static void
2246 s7_do16_hrdrs (char *str)
2248 s7_skip_whitespace (str);
2250 if (s7_reghigh_required_here (&str, 8) != (int) s7_FAIL
2251 && s7_skip_past_comma (&str) != (int) s7_FAIL
2252 && s7_reglow_required_here (&str, 4) != (int) s7_FAIL
2253 && s7_end_of_line (str) != (int) s7_FAIL)
2255 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
2256 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2257 s7_inst.relax_size = 4;
2261 /* Handle mlfh!. */
2263 static void
2264 s7_do16_rdhrs (char *str)
2266 s7_skip_whitespace (str);
2268 if (s7_reglow_required_here (&str, 8) != (int) s7_FAIL
2269 && s7_skip_past_comma (&str) != (int) s7_FAIL
2270 && s7_reghigh_required_here (&str, 4) != (int) s7_FAIL
2271 && s7_end_of_line (str) != (int) s7_FAIL)
2273 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2274 | ((((s7_inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
2275 s7_inst.relax_size = 4;
2279 /* We need to be able to fix up arbitrary expressions in some statements.
2280 This is so that we can handle symbols that are an arbitrary distance from
2281 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
2282 which returns part of an address in a form which will be valid for
2283 a data instruction. We do this by pushing the expression into a symbol
2284 in the expr_section, and creating a fix for that. */
2286 static fixS *
2287 s7_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
2289 fixS *new_fix;
2291 switch (exp->X_op)
2293 case O_constant:
2294 case O_symbol:
2295 case O_add:
2296 case O_subtract:
2297 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
2298 break;
2299 default:
2300 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
2301 break;
2303 return new_fix;
2306 static void
2307 s7_init_dependency_vector (void)
2309 int i;
2311 for (i = 0; i < s7_vector_size; i++)
2312 memset (&s7_dependency_vector[i], '\0', sizeof (s7_dependency_vector[i]));
2314 return;
2317 static enum s7_insn_type_for_dependency
2318 s7_dependency_type_from_insn (char *insn_name)
2320 char name[s7_INSN_NAME_LEN];
2321 const struct s7_insn_to_dependency *tmp;
2323 strcpy (name, insn_name);
2324 tmp = (const struct s7_insn_to_dependency *) hash_find (s7_dependency_insn_hsh, name);
2326 if (tmp)
2327 return tmp->type;
2329 return s7_D_all_insn;
2332 static int
2333 s7_check_dependency (char *pre_insn, char *pre_reg,
2334 char *cur_insn, char *cur_reg, int *warn_or_error)
2336 int bubbles = 0;
2337 unsigned int i;
2338 enum s7_insn_type_for_dependency pre_insn_type;
2339 enum s7_insn_type_for_dependency cur_insn_type;
2341 pre_insn_type = s7_dependency_type_from_insn (pre_insn);
2342 cur_insn_type = s7_dependency_type_from_insn (cur_insn);
2344 for (i = 0; i < sizeof (s7_data_dependency_table) / sizeof (s7_data_dependency_table[0]); i++)
2346 if ((pre_insn_type == s7_data_dependency_table[i].pre_insn_type)
2347 && (s7_D_all_insn == s7_data_dependency_table[i].cur_insn_type
2348 || cur_insn_type == s7_data_dependency_table[i].cur_insn_type)
2349 && (strcmp (s7_data_dependency_table[i].pre_reg, "") == 0
2350 || strcmp (s7_data_dependency_table[i].pre_reg, pre_reg) == 0)
2351 && (strcmp (s7_data_dependency_table[i].cur_reg, "") == 0
2352 || strcmp (s7_data_dependency_table[i].cur_reg, cur_reg) == 0))
2354 if (s7_vector_size == s7_SCORE5_PIPELINE)
2355 bubbles = s7_data_dependency_table[i].bubblenum_5;
2356 else
2357 bubbles = s7_data_dependency_table[i].bubblenum_7;
2358 *warn_or_error = s7_data_dependency_table[i].warn_or_error;
2359 break;
2363 return bubbles;
2366 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
2367 for use in the a.out file, and stores them in the array pointed to by buf.
2368 This knows about the endian-ness of the target machine and does
2369 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
2370 2 (short) and 4 (long) Floating numbers are put out as a series of
2371 LITTLENUMS (shorts, here at least). */
2373 static void
2374 s7_number_to_chars (char *buf, valueT val, int n)
2376 if (target_big_endian)
2377 number_to_chars_bigendian (buf, val, n);
2378 else
2379 number_to_chars_littleendian (buf, val, n);
2382 static void
2383 s7_build_one_frag (struct s7_score_it one_inst)
2385 char *p;
2386 int relaxable_p = s7_g_opt;
2387 int relax_size = 0;
2389 /* Start a new frag if frag_now is not empty. */
2390 if (frag_now_fix () != 0)
2392 if (!frag_now->tc_frag_data.is_insn)
2393 frag_wane (frag_now);
2395 frag_new (0);
2397 frag_grow (20);
2399 p = frag_more (one_inst.size);
2400 s7_number_to_chars (p, one_inst.instruction, one_inst.size);
2402 #ifdef OBJ_ELF
2403 dwarf2_emit_insn (one_inst.size);
2404 #endif
2406 relaxable_p &= (one_inst.relax_size != 0);
2407 relax_size = relaxable_p ? one_inst.relax_size : 0;
2409 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2410 s7_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2411 one_inst.type, 0, 0, relaxable_p),
2412 NULL, 0, NULL);
2414 if (relaxable_p)
2415 s7_number_to_chars (p, one_inst.relax_inst, relax_size);
2418 static void
2419 s7_handle_dependency (struct s7_score_it *theinst)
2421 int i;
2422 int warn_or_error = 0; /* warn - 0; error - 1 */
2423 int bubbles = 0;
2424 int remainder_bubbles = 0;
2425 char cur_insn[s7_INSN_NAME_LEN];
2426 char pre_insn[s7_INSN_NAME_LEN];
2427 struct s7_score_it nop_inst;
2428 struct s7_score_it pflush_inst;
2430 nop_inst.instruction = 0x0000;
2431 nop_inst.size = 2;
2432 nop_inst.relax_inst = 0x80008000;
2433 nop_inst.relax_size = 4;
2434 nop_inst.type = NO16_OPD;
2436 pflush_inst.instruction = 0x8000800a;
2437 pflush_inst.size = 4;
2438 pflush_inst.relax_inst = 0x8000;
2439 pflush_inst.relax_size = 0;
2440 pflush_inst.type = NO_OPD;
2442 /* pflush will clear all data dependency. */
2443 if (strcmp (theinst->name, "pflush") == 0)
2445 s7_init_dependency_vector ();
2446 return;
2449 /* Push current instruction to s7_dependency_vector[0]. */
2450 for (i = s7_vector_size - 1; i > 0; i--)
2451 memcpy (&s7_dependency_vector[i], &s7_dependency_vector[i - 1], sizeof (s7_dependency_vector[i]));
2453 memcpy (&s7_dependency_vector[0], theinst, sizeof (s7_dependency_vector[i]));
2455 /* There is no dependency between nop and any instruction. */
2456 if (strcmp (s7_dependency_vector[0].name, "nop") == 0
2457 || strcmp (s7_dependency_vector[0].name, "nop!") == 0)
2458 return;
2460 /* "pce" is defined in s7_insn_to_dependency_table. */
2461 #define PCE_NAME "pce"
2463 if (s7_dependency_vector[0].type == Insn_Type_PCE)
2464 strcpy (cur_insn, PCE_NAME);
2465 else
2466 strcpy (cur_insn, s7_dependency_vector[0].name);
2468 for (i = 1; i < s7_vector_size; i++)
2470 /* The element of s7_dependency_vector is NULL. */
2471 if (s7_dependency_vector[i].name[0] == '\0')
2472 continue;
2474 if (s7_dependency_vector[i].type == Insn_Type_PCE)
2475 strcpy (pre_insn, PCE_NAME);
2476 else
2477 strcpy (pre_insn, s7_dependency_vector[i].name);
2479 bubbles = s7_check_dependency (pre_insn, s7_dependency_vector[i].reg,
2480 cur_insn, s7_dependency_vector[0].reg, &warn_or_error);
2481 remainder_bubbles = bubbles - i + 1;
2483 if (remainder_bubbles > 0)
2485 int j;
2487 if (s7_fix_data_dependency == 1)
2489 if (remainder_bubbles <= 2)
2491 if (s7_warn_fix_data_dependency)
2492 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
2493 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2494 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2495 remainder_bubbles, bubbles);
2497 for (j = (s7_vector_size - 1); (j - remainder_bubbles) > 0; j--)
2498 memcpy (&s7_dependency_vector[j], &s7_dependency_vector[j - remainder_bubbles],
2499 sizeof (s7_dependency_vector[j]));
2501 for (j = 1; j <= remainder_bubbles; j++)
2503 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2504 /* Insert nop!. */
2505 s7_build_one_frag (nop_inst);
2508 else
2510 if (s7_warn_fix_data_dependency)
2511 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
2512 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2513 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2514 bubbles);
2516 for (j = 1; j < s7_vector_size; j++)
2517 memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
2519 /* Insert pflush. */
2520 s7_build_one_frag (pflush_inst);
2523 else
2525 if (warn_or_error)
2527 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2528 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2529 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2530 remainder_bubbles, bubbles);
2532 else
2534 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
2535 s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
2536 s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
2537 remainder_bubbles, bubbles);
2544 static enum insn_class
2545 s7_get_insn_class_from_type (enum score_insn_type type)
2547 enum insn_class retval = (int) s7_FAIL;
2549 switch (type)
2551 case Rd_I4:
2552 case Rd_I5:
2553 case Rd_rvalueBP_I5:
2554 case Rd_lvalueBP_I5:
2555 case Rd_I8:
2556 case PC_DISP8div2:
2557 case PC_DISP11div2:
2558 case Rd_Rs:
2559 case Rd_HighRs:
2560 case Rd_lvalueRs:
2561 case Rd_rvalueRs:
2562 case x_Rs:
2563 case Rd_LowRs:
2564 case NO16_OPD:
2565 retval = INSN_CLASS_16;
2566 break;
2567 case Rd_Rs_I5:
2568 case x_Rs_I5:
2569 case x_I5_x:
2570 case Rd_Rs_I14:
2571 case I15:
2572 case Rd_I16:
2573 case Rd_SI16:
2574 case Rd_rvalueRs_SI10:
2575 case Rd_lvalueRs_SI10:
2576 case Rd_rvalueRs_preSI12:
2577 case Rd_rvalueRs_postSI12:
2578 case Rd_lvalueRs_preSI12:
2579 case Rd_lvalueRs_postSI12:
2580 case Rd_Rs_SI14:
2581 case Rd_rvalueRs_SI15:
2582 case Rd_lvalueRs_SI15:
2583 case PC_DISP19div2:
2584 case PC_DISP24div2:
2585 case Rd_Rs_Rs:
2586 case x_Rs_x:
2587 case x_Rs_Rs:
2588 case Rd_Rs_x:
2589 case Rd_x_Rs:
2590 case Rd_x_x:
2591 case OP5_rvalueRs_SI15:
2592 case I5_Rs_Rs_I5_OP5:
2593 case x_rvalueRs_post4:
2594 case Rd_rvalueRs_post4:
2595 case Rd_x_I5:
2596 case Rd_lvalueRs_post4:
2597 case x_lvalueRs_post4:
2598 case Rd_Rs_Rs_imm:
2599 case NO_OPD:
2600 case Rd_lvalue32Rs:
2601 case Rd_rvalue32Rs:
2602 case Insn_GP:
2603 case Insn_PIC:
2604 case Insn_internal:
2605 retval = INSN_CLASS_32;
2606 break;
2607 case Insn_Type_PCE:
2608 retval = INSN_CLASS_PCE;
2609 break;
2610 case Insn_Type_SYN:
2611 retval = INSN_CLASS_SYN;
2612 break;
2613 default:
2614 abort ();
2615 break;
2617 return retval;
2620 static unsigned long
2621 s7_adjust_paritybit (unsigned long m_code, enum insn_class i_class)
2623 unsigned long result = 0;
2624 unsigned long m_code_high = 0;
2625 unsigned long m_code_low = 0;
2626 unsigned long pb_high = 0;
2627 unsigned long pb_low = 0;
2629 if (i_class == INSN_CLASS_32)
2631 pb_high = 0x80000000;
2632 pb_low = 0x00008000;
2634 else if (i_class == INSN_CLASS_16)
2636 pb_high = 0;
2637 pb_low = 0;
2639 else if (i_class == INSN_CLASS_PCE)
2641 pb_high = 0;
2642 pb_low = 0x00008000;
2644 else if (i_class == INSN_CLASS_SYN)
2646 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2647 be changed if macro instruction has been expanded. */
2648 pb_high = 0x80000000;
2649 pb_low = 0x00008000;
2651 else
2653 abort ();
2656 m_code_high = m_code & 0x3fff8000;
2657 m_code_low = m_code & 0x00007fff;
2658 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2659 return result;
2663 static void
2664 s7_gen_insn_frag (struct s7_score_it *part_1, struct s7_score_it *part_2)
2666 char *p;
2667 bfd_boolean pce_p = FALSE;
2668 int relaxable_p = s7_g_opt;
2669 int relax_size = 0;
2670 struct s7_score_it *inst1 = part_1;
2671 struct s7_score_it *inst2 = part_2;
2672 struct s7_score_it backup_inst1;
2674 pce_p = (inst2) ? TRUE : FALSE;
2675 memcpy (&backup_inst1, inst1, sizeof (struct s7_score_it));
2677 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2678 if (pce_p)
2680 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2681 | (inst2->instruction & 0x7FFF);
2682 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2683 if (!target_big_endian)
2685 unsigned long tmp = backup_inst1.instruction;
2686 backup_inst1.instruction = ((tmp & 0xffff) << 16)
2687 | (tmp >> 16);
2689 backup_inst1.relax_inst = 0x8000;
2690 backup_inst1.size = s7_INSN_SIZE;
2691 backup_inst1.relax_size = 0;
2692 backup_inst1.type = Insn_Type_PCE;
2694 else
2696 backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction,
2697 s7_GET_INSN_CLASS (backup_inst1.type));
2700 if (backup_inst1.relax_size != 0)
2702 enum insn_class tmp;
2704 tmp = (backup_inst1.size == s7_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2705 backup_inst1.relax_inst = s7_adjust_paritybit (backup_inst1.relax_inst, tmp);
2708 /* Check data dependency. */
2709 s7_handle_dependency (&backup_inst1);
2711 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2712 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2713 if (frag_now_fix () != 0)
2715 if (!frag_now->tc_frag_data.is_insn)
2716 frag_wane (frag_now);
2718 frag_new (0);
2721 /* Here, we must call frag_grow in order to keep the instruction frag type is
2722 rs_machine_dependent.
2723 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2724 actually will call frag_wane.
2725 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2726 for frag_var. */
2727 frag_grow (20);
2729 p = frag_more (backup_inst1.size);
2730 s7_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2732 #ifdef OBJ_ELF
2733 dwarf2_emit_insn (backup_inst1.size);
2734 #endif
2736 /* Generate fixup structure. */
2737 if (pce_p)
2739 if (inst1->reloc.type != BFD_RELOC_NONE)
2740 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2741 inst1->size, &inst1->reloc.exp,
2742 inst1->reloc.pc_rel, inst1->reloc.type);
2744 if (inst2->reloc.type != BFD_RELOC_NONE)
2745 s7_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2746 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2748 else
2750 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2751 s7_fix_new_score (frag_now, p - frag_now->fr_literal,
2752 backup_inst1.size, &backup_inst1.reloc.exp,
2753 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2756 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2757 relaxable_p &= (backup_inst1.relax_size != 0);
2758 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2760 p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
2761 s7_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2762 backup_inst1.type, 0, 0, relaxable_p),
2763 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2765 if (relaxable_p)
2766 s7_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2768 memcpy (inst1, &backup_inst1, sizeof (struct s7_score_it));
2771 static void
2772 s7_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2774 char c;
2775 char *p;
2776 char *operator = insnstr;
2777 const struct s7_asm_opcode *opcode;
2779 /* Parse operator and operands. */
2780 s7_skip_whitespace (operator);
2782 for (p = operator; *p != '\0'; p++)
2783 if ((*p == ' ') || (*p == '!'))
2784 break;
2786 if (*p == '!')
2787 p++;
2789 c = *p;
2790 *p = '\0';
2792 opcode = (const struct s7_asm_opcode *) hash_find (s7_score_ops_hsh, operator);
2793 *p = c;
2795 memset (&s7_inst, '\0', sizeof (s7_inst));
2796 strcpy (s7_inst.str, insnstr);
2797 if (opcode)
2799 s7_inst.instruction = opcode->value;
2800 s7_inst.relax_inst = opcode->relax_value;
2801 s7_inst.type = opcode->type;
2802 s7_inst.size = s7_GET_INSN_SIZE (s7_inst.type);
2803 s7_inst.relax_size = 0;
2804 s7_inst.bwarn = 0;
2805 strcpy (s7_inst.name, opcode->template_name);
2806 strcpy (s7_inst.reg, "");
2807 s7_inst.error = NULL;
2808 s7_inst.reloc.type = BFD_RELOC_NONE;
2810 (*opcode->parms) (p);
2812 /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1. */
2813 if ((s7_inst.bwarn != -1) && (!s7_inst.error) && (gen_frag_p))
2814 s7_gen_insn_frag (&s7_inst, NULL);
2816 else
2817 s7_inst.error = _("unrecognized opcode");
2820 static int
2821 s7_append_insn (char *str, bfd_boolean gen_frag_p)
2823 int retval = s7_SUCCESS;
2825 s7_parse_16_32_inst (str, gen_frag_p);
2827 if (s7_inst.error)
2829 retval = (int) s7_FAIL;
2830 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
2831 s7_inst.error = NULL;
2834 return retval;
2837 /* Handle mv! reg_high, reg_low;
2838 mv! reg_low, reg_high;
2839 mv! reg_low, reg_low; */
2840 static void
2841 s7_do16_mv_rdrs (char *str)
2843 int reg_rd;
2844 int reg_rs;
2845 char *backupstr = NULL;
2847 backupstr = str;
2848 s7_skip_whitespace (str);
2850 if ((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2851 || s7_skip_past_comma (&str) == (int) s7_FAIL
2852 || (reg_rs = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
2853 || s7_end_of_line (str) == (int) s7_FAIL)
2855 return;
2857 else
2859 /* Case 1 : mv! or mlfh!. */
2860 if (reg_rd < 16)
2862 if (reg_rs < 16)
2864 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2865 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2866 s7_inst.relax_size = 4;
2868 else
2870 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2872 sprintf (append_str, "mlfh! %s", backupstr);
2873 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2874 return;
2875 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2876 s7_inst.bwarn = -1;
2879 /* Case 2 : mhfl!. */
2880 else
2882 if (reg_rs > 16)
2884 s7_SET_INSN_ERROR (s7_BAD_ARGS);
2885 return;
2887 else
2889 char append_str[s7_MAX_LITERAL_POOL_SIZE];
2891 sprintf (append_str, "mhfl! %s", backupstr);
2892 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
2893 return;
2895 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2896 s7_inst.bwarn = -1;
2902 static void
2903 s7_do16_rdi4 (char *str)
2905 s7_skip_whitespace (str);
2907 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2908 || s7_skip_past_comma (&str) == (int) s7_FAIL
2909 || s7_data_op2 (&str, 3, _IMM4) == (int) s7_FAIL
2910 || s7_end_of_line (str) == (int) s7_FAIL)
2912 return;
2914 else
2916 if (((s7_inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2918 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2920 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2921 | ((1 << ((s7_inst.instruction >> 3) & 0xf)) << 1);
2922 s7_inst.relax_size = 4;
2924 else
2926 s7_inst.relax_inst = 0x8000;
2929 else
2931 if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
2933 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2934 | (((-(1 << ((s7_inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2935 s7_inst.relax_size = 4;
2937 else
2939 s7_inst.relax_inst = 0x8000;
2945 static void
2946 s7_do16_rdi5 (char *str)
2948 s7_skip_whitespace (str);
2950 if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
2951 || s7_skip_past_comma (&str) == (int) s7_FAIL
2952 || s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL
2953 || s7_end_of_line (str) == (int) s7_FAIL)
2954 return;
2955 else
2957 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
2958 | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 3) & 0x1f) << 10);
2959 s7_inst.relax_size = 4;
2963 /* Handle sdbbp. */
2965 static void
2966 s7_do16_xi5 (char *str)
2968 s7_skip_whitespace (str);
2970 if (s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
2971 return;
2972 else
2974 s7_inst.relax_inst |= (((s7_inst.instruction >> 3) & 0x1f) << 15);
2975 s7_inst.relax_size = 4;
2979 /* Check that an immediate is word alignment or half word alignment.
2980 If so, convert it to the right format. */
2982 static int
2983 s7_validate_immediate_align (int val, unsigned int data_type)
2985 if (data_type == _IMM5_RSHIFT_1)
2987 if (val % 2)
2989 s7_inst.error = _("address offset must be half word alignment");
2990 return (int) s7_FAIL;
2993 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2995 if (val % 4)
2997 s7_inst.error = _("address offset must be word alignment");
2998 return (int) s7_FAIL;
3002 return s7_SUCCESS;
3005 static int
3006 s7_exp_ldst_offset (char **str, int shift, unsigned int data_type)
3008 char *dataptr;
3009 int hex_p = 0;
3011 dataptr = * str;
3013 if ((dataptr != NULL)
3014 && (((strstr (dataptr, "0x")) != NULL)
3015 || ((strstr (dataptr, "0X")) != NULL)))
3017 hex_p = 1;
3018 if ((data_type != _SIMM16_LA)
3019 && (data_type != _VALUE_HI16)
3020 && (data_type != _VALUE_LO16)
3021 && (data_type != _IMM16)
3022 && (data_type != _IMM15)
3023 && (data_type != _IMM14)
3024 && (data_type != _IMM4)
3025 && (data_type != _IMM5)
3026 && (data_type != _IMM8)
3027 && (data_type != _IMM5_RSHIFT_1)
3028 && (data_type != _IMM5_RSHIFT_2)
3029 && (data_type != _SIMM12)
3030 && (data_type != _SIMM15)
3031 && (data_type != _SIMM14_NEG)
3032 && (data_type != _IMM10_RSHIFT_2))
3034 data_type += 24;
3038 if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
3039 return (int) s7_FAIL;
3041 if (s7_inst.reloc.exp.X_op == O_constant)
3043 /* Need to check the immediate align. */
3044 int value = s7_validate_immediate_align (s7_inst.reloc.exp.X_add_number, data_type);
3046 if (value == (int) s7_FAIL)
3047 return (int) s7_FAIL;
3049 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3050 if (value == (int) s7_FAIL)
3052 if (data_type < 30)
3053 sprintf (s7_err_msg,
3054 _("invalid constant: %d bit expression not in range %d..%d"),
3055 s7_score_df_range[data_type].bits,
3056 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3057 else
3058 sprintf (s7_err_msg,
3059 _("invalid constant: %d bit expression not in range %d..%d"),
3060 s7_score_df_range[data_type - 24].bits,
3061 s7_score_df_range[data_type - 24].range[0], s7_score_df_range[data_type - 24].range[1]);
3062 s7_inst.error = s7_err_msg;
3063 return (int) s7_FAIL;
3066 if (data_type == _IMM5_RSHIFT_1)
3068 value >>= 1;
3070 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
3072 value >>= 2;
3075 if (s7_score_df_range[data_type].range[0] != 0)
3077 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3080 s7_inst.instruction |= value << shift;
3082 else
3084 s7_inst.reloc.pc_rel = 0;
3087 return s7_SUCCESS;
3090 static void
3091 s7_do_ldst_insn (char *str)
3093 int pre_inc = 0;
3094 int conflict_reg;
3095 int value;
3096 char * temp;
3097 char *dataptr;
3098 int reg;
3099 int ldst_idx = 0;
3101 int hex_p = 0;
3103 s7_skip_whitespace (str);
3105 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3106 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3107 return;
3109 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
3110 if (*str == '[')
3112 str++;
3113 s7_skip_whitespace (str);
3115 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3116 return;
3118 /* Conflicts can occur on stores as well as loads. */
3119 conflict_reg = (conflict_reg == reg);
3120 s7_skip_whitespace (str);
3121 temp = str + 1; /* The latter will process decimal/hex expression. */
3123 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
3124 if (*str == ']')
3126 str++;
3127 if (*str == '+')
3129 str++;
3130 /* ld/sw rD, [rA]+, simm12. */
3131 if (s7_skip_past_comma (&str) == s7_SUCCESS)
3133 if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
3134 || (s7_end_of_line (str) == (int) s7_FAIL))
3135 return;
3137 if (conflict_reg)
3139 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3141 if ((ldst_func == INSN_LH)
3142 || (ldst_func == INSN_LHU)
3143 || (ldst_func == INSN_LW)
3144 || (ldst_func == INSN_LB)
3145 || (ldst_func == INSN_LBU))
3147 s7_inst.error = _("register same as write-back base");
3148 return;
3152 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3153 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3154 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
3156 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
3157 if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
3159 /* rs = r0-r7, offset = 4 */
3160 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3161 && (((s7_inst.instruction >> 3) & 0xfff) == 4))
3163 /* Relax to pophi. */
3164 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3166 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3167 << 8) | 1 << 7 |
3168 (((s7_inst.instruction >> 15) & 0x7) << 4);
3170 /* Relax to pop. */
3171 else
3173 s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3174 << 8) | 0 << 7 |
3175 (((s7_inst.instruction >> 15) & 0x7) << 4);
3177 s7_inst.relax_size = 2;
3180 return;
3182 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
3183 else
3185 s7_SET_INSN_ERROR (NULL);
3186 if (s7_end_of_line (str) == (int) s7_FAIL)
3188 return;
3191 pre_inc = 1;
3192 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
3193 value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
3194 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3195 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3196 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3197 s7_inst.instruction |= value << 3;
3198 s7_inst.relax_inst = 0x8000;
3199 return;
3202 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
3203 else
3205 if (s7_end_of_line (str) == (int) s7_FAIL)
3206 return;
3208 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3209 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3210 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3212 /* lbu rd, [rs] -> lbu! rd, [rs] */
3213 if (ldst_idx == INSN_LBU)
3215 s7_inst.relax_inst = INSN16_LBU;
3217 else if (ldst_idx == INSN_LH)
3219 s7_inst.relax_inst = INSN16_LH;
3221 else if (ldst_idx == INSN_LW)
3223 s7_inst.relax_inst = INSN16_LW;
3225 else if (ldst_idx == INSN_SB)
3227 s7_inst.relax_inst = INSN16_SB;
3229 else if (ldst_idx == INSN_SH)
3231 s7_inst.relax_inst = INSN16_SH;
3233 else if (ldst_idx == INSN_SW)
3235 s7_inst.relax_inst = INSN16_SW;
3237 else
3239 s7_inst.relax_inst = 0x8000;
3242 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
3243 if ((ldst_idx == INSN_LBU)
3244 || (ldst_idx == INSN_LH)
3245 || (ldst_idx == INSN_LW)
3246 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
3248 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3250 s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
3251 (((s7_inst.instruction >> 15) & 0xf) << 4);
3252 s7_inst.relax_size = 2;
3256 return;
3259 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
3260 else
3262 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3264 s7_inst.error = _("pre-indexed expression expected");
3265 return;
3268 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
3269 return;
3271 s7_skip_whitespace (str);
3272 if (*str++ != ']')
3274 s7_inst.error = _("missing ]");
3275 return;
3278 s7_skip_whitespace (str);
3279 /* ld/sw rD, [rA, simm12]+. */
3280 if (*str == '+')
3282 str++;
3283 pre_inc = 1;
3284 if (conflict_reg)
3286 unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3288 if ((ldst_func == INSN_LH)
3289 || (ldst_func == INSN_LHU)
3290 || (ldst_func == INSN_LW)
3291 || (ldst_func == INSN_LB)
3292 || (ldst_func == INSN_LBU))
3294 s7_inst.error = _("register same as write-back base");
3295 return;
3300 if (s7_end_of_line (str) == (int) s7_FAIL)
3301 return;
3303 if (s7_inst.reloc.exp.X_op == O_constant)
3305 unsigned int data_type;
3307 if (pre_inc == 1)
3308 data_type = _SIMM12;
3309 else
3310 data_type = _SIMM15;
3311 dataptr = temp;
3313 if ((dataptr != NULL)
3314 && (((strstr (dataptr, "0x")) != NULL)
3315 || ((strstr (dataptr, "0X")) != NULL)))
3317 hex_p = 1;
3318 if ((data_type != _SIMM16_LA)
3319 && (data_type != _VALUE_HI16)
3320 && (data_type != _VALUE_LO16)
3321 && (data_type != _IMM16)
3322 && (data_type != _IMM15)
3323 && (data_type != _IMM14)
3324 && (data_type != _IMM4)
3325 && (data_type != _IMM5)
3326 && (data_type != _IMM8)
3327 && (data_type != _SIMM12)
3328 && (data_type != _SIMM15)
3329 && (data_type != _IMM5_RSHIFT_1)
3330 && (data_type != _IMM5_RSHIFT_2)
3331 && (data_type != _SIMM14_NEG)
3332 && (data_type != _IMM10_RSHIFT_2))
3334 data_type += 24;
3338 value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3339 if (value == (int) s7_FAIL)
3341 if (data_type < 30)
3342 sprintf (s7_err_msg,
3343 _("invalid constant: %d bit expression not in range %d..%d"),
3344 s7_score_df_range[data_type].bits,
3345 s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3346 else
3347 sprintf (s7_err_msg,
3348 _("invalid constant: %d bit expression not in range %d..%d"),
3349 s7_score_df_range[data_type - 24].bits,
3350 s7_score_df_range[data_type - 24].range[0],
3351 s7_score_df_range[data_type - 24].range[1]);
3352 s7_inst.error = s7_err_msg;
3353 return;
3356 value &= (1 << s7_score_df_range[data_type].bits) - 1;
3357 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3358 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3359 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3360 if (pre_inc == 1)
3361 s7_inst.instruction |= value << 3;
3362 else
3363 s7_inst.instruction |= value;
3365 /* lw rD, [rA, simm15] */
3366 if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3368 /* Both rD and rA are in [r0 - r15]. */
3369 if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3370 && (((s7_inst.instruction >> 20) & 0x10) == 0))
3372 /* simm15 = 0, lw -> lw!. */
3373 if ((s7_inst.instruction & 0x7fff) == 0)
3375 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3376 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3377 s7_inst.relax_size = 2;
3379 /* rA = r2, lw -> lwp!. */
3380 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3381 && ((s7_inst.instruction & 0x3) == 0)
3382 && ((s7_inst.instruction & 0x7fff) < 128))
3384 s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3385 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3386 s7_inst.relax_size = 2;
3388 else
3390 s7_inst.relax_inst = 0x8000;
3393 else
3395 s7_inst.relax_inst = 0x8000;
3398 /* sw rD, [rA, simm15] */
3399 else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3401 /* Both rD and rA are in [r0 - r15]. */
3402 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3404 /* simm15 = 0, sw -> sw!. */
3405 if ((s7_inst.instruction & 0x7fff) == 0)
3407 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3408 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3409 s7_inst.relax_size = 2;
3411 /* rA = r2, sw -> swp!. */
3412 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3413 && ((s7_inst.instruction & 0x3) == 0)
3414 && ((s7_inst.instruction & 0x7fff) < 128))
3416 s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3417 | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3418 s7_inst.relax_size = 2;
3420 else
3422 s7_inst.relax_inst = 0x8000;
3425 else
3427 s7_inst.relax_inst = 0x8000;
3430 /* sw rD, [rA, simm15]+ sw pre. */
3431 else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3433 /* rA is in [r0 - r7], and simm15 = -4. */
3434 if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3435 && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3437 /* sw -> pushhi!. */
3438 if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3440 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3441 | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3442 s7_inst.relax_size = 2;
3444 /* sw -> push!. */
3445 else
3447 s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3448 | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3449 s7_inst.relax_size = 2;
3452 else
3454 s7_inst.relax_inst = 0x8000;
3457 /* lh rD, [rA, simm15] */
3458 else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3460 /* Both rD and rA are in [r0 - r15]. */
3461 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3463 /* simm15 = 0, lh -> lh!. */
3464 if ((s7_inst.instruction & 0x7fff) == 0)
3466 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3467 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3468 s7_inst.relax_size = 2;
3470 /* rA = r2, lh -> lhp!. */
3471 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3472 && ((s7_inst.instruction & 0x1) == 0)
3473 && ((s7_inst.instruction & 0x7fff) < 64))
3475 s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3476 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3477 s7_inst.relax_size = 2;
3479 else
3481 s7_inst.relax_inst = 0x8000;
3484 else
3486 s7_inst.relax_inst = 0x8000;
3489 /* sh rD, [rA, simm15] */
3490 else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3492 /* Both rD and rA are in [r0 - r15]. */
3493 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3495 /* simm15 = 0, sh -> sh!. */
3496 if ((s7_inst.instruction & 0x7fff) == 0)
3498 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3499 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3500 s7_inst.relax_size = 2;
3502 /* rA = r2, sh -> shp!. */
3503 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3504 && ((s7_inst.instruction & 0x1) == 0)
3505 && ((s7_inst.instruction & 0x7fff) < 64))
3507 s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3508 | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3509 s7_inst.relax_size = 2;
3511 else
3513 s7_inst.relax_inst = 0x8000;
3516 else
3518 s7_inst.relax_inst = 0x8000;
3521 /* lbu rD, [rA, simm15] */
3522 else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3524 /* Both rD and rA are in [r0 - r15]. */
3525 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3527 /* simm15 = 0, lbu -> lbu!. */
3528 if ((s7_inst.instruction & 0x7fff) == 0)
3530 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3531 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3532 s7_inst.relax_size = 2;
3534 /* rA = r2, lbu -> lbup!. */
3535 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3536 && ((s7_inst.instruction & 0x7fff) < 32))
3538 s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3539 | ((s7_inst.instruction & 0x7fff) << 3);
3540 s7_inst.relax_size = 2;
3542 else
3544 s7_inst.relax_inst = 0x8000;
3547 else
3549 s7_inst.relax_inst = 0x8000;
3552 /* sb rD, [rA, simm15] */
3553 else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3555 /* Both rD and rA are in [r0 - r15]. */
3556 if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3558 /* simm15 = 0, sb -> sb!. */
3559 if ((s7_inst.instruction & 0x7fff) == 0)
3561 s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3562 | (((s7_inst.instruction >> 20) & 0xf) << 8);
3563 s7_inst.relax_size = 2;
3565 /* rA = r2, sb -> sb!. */
3566 else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3567 && ((s7_inst.instruction & 0x7fff) < 32))
3569 s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3570 | ((s7_inst.instruction & 0x7fff) << 3);
3571 s7_inst.relax_size = 2;
3573 else
3575 s7_inst.relax_inst = 0x8000;
3578 else
3580 s7_inst.relax_inst = 0x8000;
3583 else
3585 s7_inst.relax_inst = 0x8000;
3588 return;
3590 else
3592 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3593 s7_inst.reloc.pc_rel = 0;
3597 else
3599 s7_inst.error = s7_BAD_ARGS;
3603 /* Handle cache. */
3604 static void
3605 s7_do_cache (char *str)
3607 s7_skip_whitespace (str);
3609 if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3611 return;
3613 else
3615 int cache_op;
3617 cache_op = (s7_inst.instruction >> 20) & 0x1F;
3618 sprintf (s7_inst.name, "cache %d", cache_op);
3621 if (*str == '[')
3623 str++;
3624 s7_skip_whitespace (str);
3626 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3627 return;
3629 s7_skip_whitespace (str);
3631 /* cache op, [rA] */
3632 if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3634 s7_SET_INSN_ERROR (NULL);
3635 if (*str != ']')
3637 s7_inst.error = _("missing ]");
3638 return;
3640 str++;
3642 /* cache op, [rA, simm15] */
3643 else
3645 if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3647 return;
3650 s7_skip_whitespace (str);
3651 if (*str++ != ']')
3653 s7_inst.error = _("missing ]");
3654 return;
3658 if (s7_end_of_line (str) == (int) s7_FAIL)
3659 return;
3661 else
3663 s7_inst.error = s7_BAD_ARGS;
3667 static void
3668 s7_do_crdcrscrsimm5 (char *str)
3670 char *strbak;
3672 strbak = str;
3673 s7_skip_whitespace (str);
3675 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3676 || s7_skip_past_comma (&str) == (int) s7_FAIL
3677 || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3678 || s7_skip_past_comma (&str) == (int) s7_FAIL
3679 || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3680 || s7_skip_past_comma (&str) == (int) s7_FAIL)
3682 str = strbak;
3683 /* cop1 cop_code20. */
3684 if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3685 return;
3687 else
3689 if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3690 return;
3693 s7_end_of_line (str);
3696 /* Handle ldc/stc. */
3697 static void
3698 s7_do_ldst_cop (char *str)
3700 s7_skip_whitespace (str);
3702 if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3703 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3704 return;
3706 if (*str == '[')
3708 str++;
3709 s7_skip_whitespace (str);
3711 if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3712 return;
3714 s7_skip_whitespace (str);
3716 if (*str++ != ']')
3718 if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3719 return;
3721 s7_skip_whitespace (str);
3722 if (*str++ != ']')
3724 s7_inst.error = _("missing ]");
3725 return;
3729 s7_end_of_line (str);
3731 else
3732 s7_inst.error = s7_BAD_ARGS;
3735 static void
3736 s7_do16_ldst_insn (char *str)
3738 s7_skip_whitespace (str);
3740 if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3741 return;
3743 if (*str == '[')
3745 int reg;
3747 str++;
3748 s7_skip_whitespace (str);
3750 if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3751 return;
3753 s7_skip_whitespace (str);
3754 if (*str++ == ']')
3756 if (s7_end_of_line (str) == (int) s7_FAIL)
3757 return;
3758 else
3760 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3761 | (((s7_inst.instruction >> 4) & 0xf) << 15);
3762 s7_inst.relax_size = 4;
3765 else
3767 s7_inst.error = _("missing ]");
3770 else
3772 s7_inst.error = s7_BAD_ARGS;
3776 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3778 static void
3779 s7_do16_ldst_imm_insn (char *str)
3781 char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3782 int reg_rd;
3783 char *dataptr = NULL, *pp = NULL;
3784 int cnt = 0;
3785 int assign_data = (int) s7_FAIL;
3786 unsigned int ldst_func;
3788 s7_skip_whitespace (str);
3790 if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3791 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3792 return;
3794 s7_skip_whitespace (str);
3795 dataptr = str;
3797 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3799 data_exp[cnt] = *dataptr;
3800 dataptr++;
3801 cnt++;
3804 data_exp[cnt] = '\0';
3805 pp = &data_exp[0];
3807 str = dataptr;
3809 ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3810 if (ldst_func == N16_LIU)
3811 assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3812 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3813 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3814 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3815 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3816 else
3817 assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3819 if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3820 return;
3821 else
3823 if ((s7_inst.instruction & 0x7000) == N16_LIU)
3825 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3826 | ((s7_inst.instruction & 0xff) << 1);
3828 else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3829 || ((s7_inst.instruction & 0x7007) == N16_SHP))
3831 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3832 | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3834 else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3835 || ((s7_inst.instruction & 0x7007) == N16_SWP))
3837 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3838 | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3840 else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3841 || ((s7_inst.instruction & 0x7007) == N16_SBP))
3843 s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3844 | (((s7_inst.instruction >> 3) & 0x1f));
3847 s7_inst.relax_size = 4;
3851 static void
3852 s7_do16_push_pop (char *str)
3854 int reg_rd;
3855 int H_bit_mask = 0;
3857 s7_skip_whitespace (str);
3858 if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3859 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3860 return;
3862 if (reg_rd >= 16)
3863 H_bit_mask = 1;
3865 /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3866 s7_inst.instruction &= ~(1 << 12);
3868 s7_inst.instruction |= H_bit_mask << 7;
3870 if (*str == '[')
3872 int reg;
3874 str++;
3875 s7_skip_whitespace (str);
3876 if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3877 return;
3878 else if (reg > 7)
3880 if (!s7_inst.error)
3881 s7_inst.error = _("base register nums are over 3 bit");
3883 return;
3886 s7_skip_whitespace (str);
3887 if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3889 if (!s7_inst.error)
3890 s7_inst.error = _("missing ]");
3892 return;
3895 /* pop! */
3896 if ((s7_inst.instruction & 0xf) == 0xa)
3898 if (H_bit_mask)
3900 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3901 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3903 else
3905 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3906 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3909 /* push! */
3910 else
3912 if (H_bit_mask)
3914 s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3915 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3917 else
3919 s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3920 | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3923 s7_inst.relax_size = 4;
3925 else
3927 s7_inst.error = s7_BAD_ARGS;
3931 /* Handle lcb/lcw/lce/scb/scw/sce. */
3932 static void
3933 s7_do_ldst_unalign (char *str)
3935 int conflict_reg;
3937 if (s7_university_version == 1)
3939 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3940 return;
3943 s7_skip_whitespace (str);
3945 /* lcb/scb [rA]+. */
3946 if (*str == '[')
3948 str++;
3949 s7_skip_whitespace (str);
3951 if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3952 return;
3954 if (*str++ == ']')
3956 if (*str++ != '+')
3958 s7_inst.error = _("missing +");
3959 return;
3962 else
3964 s7_inst.error = _("missing ]");
3965 return;
3968 if (s7_end_of_line (str) == (int) s7_FAIL)
3969 return;
3971 /* lcw/lce/scb/sce rD, [rA]+. */
3972 else
3974 if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3975 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3977 return;
3980 s7_skip_whitespace (str);
3981 if (*str++ == '[')
3983 int reg;
3985 s7_skip_whitespace (str);
3986 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3988 return;
3991 /* Conflicts can occur on stores as well as loads. */
3992 conflict_reg = (conflict_reg == reg);
3993 s7_skip_whitespace (str);
3994 if (*str++ == ']')
3996 unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
3998 if (*str++ == '+')
4000 if (conflict_reg)
4002 as_warn (_("%s register same as write-back base"),
4003 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4004 ? _("destination") : _("source")));
4007 else
4009 s7_inst.error = _("missing +");
4010 return;
4013 if (s7_end_of_line (str) == (int) s7_FAIL)
4014 return;
4016 else
4018 s7_inst.error = _("missing ]");
4019 return;
4022 else
4024 s7_inst.error = s7_BAD_ARGS;
4025 return;
4030 /* Handle alw/asw. */
4032 static void
4033 s7_do_ldst_atomic (char *str)
4035 if (s7_university_version == 1)
4037 s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4038 return;
4041 s7_skip_whitespace (str);
4043 if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4044 || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4046 return;
4048 else
4051 s7_skip_whitespace (str);
4052 if (*str++ == '[')
4054 int reg;
4056 s7_skip_whitespace (str);
4057 if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4059 return;
4062 s7_skip_whitespace (str);
4063 if (*str++ != ']')
4065 s7_inst.error = _("missing ]");
4066 return;
4069 s7_end_of_line (str);
4071 else
4072 s7_inst.error = s7_BAD_ARGS;
4076 static void
4077 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4078 int fix_num ATTRIBUTE_UNUSED,
4079 struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4080 symbolS *add_symbol)
4082 int i;
4083 char *p;
4084 fixS *fixp = NULL;
4085 fixS *cur_fixp = NULL;
4086 long where;
4087 struct s7_score_it inst_main;
4089 memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4091 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4092 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4093 inst_main.type = Insn_PIC;
4095 for (i = 0; i < var_num; i++)
4097 inst_main.relax_size += var_insts[i].size;
4098 var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4099 s7_GET_INSN_CLASS (var_insts[i].type));
4102 /* Check data dependency. */
4103 s7_handle_dependency (&inst_main);
4105 /* Start a new frag if frag_now is not empty. */
4106 if (frag_now_fix () != 0)
4108 if (!frag_now->tc_frag_data.is_insn)
4110 frag_wane (frag_now);
4112 frag_new (0);
4114 frag_grow (20);
4116 /* Write fr_fix part. */
4117 p = frag_more (inst_main.size);
4118 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4120 if (inst_main.reloc.type != BFD_RELOC_NONE)
4121 fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4122 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4124 frag_now->tc_frag_data.fixp = fixp;
4125 cur_fixp = frag_now->tc_frag_data.fixp;
4127 #ifdef OBJ_ELF
4128 dwarf2_emit_insn (inst_main.size);
4129 #endif
4131 where = p - frag_now->fr_literal + inst_main.size;
4132 for (i = 0; i < var_num; i++)
4134 if (i > 0)
4135 where += var_insts[i - 1].size;
4137 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4139 fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4140 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4141 var_insts[i].reloc.type);
4142 if (fixp)
4144 if (cur_fixp)
4146 cur_fixp->fx_next = fixp;
4147 cur_fixp = cur_fixp->fx_next;
4149 else
4151 frag_now->tc_frag_data.fixp = fixp;
4152 cur_fixp = frag_now->tc_frag_data.fixp;
4158 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4159 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4160 0, inst_main.size, 0), add_symbol, 0, NULL);
4162 /* Write fr_var part.
4163 no calling s7_gen_insn_frag, no fixS will be generated. */
4164 for (i = 0; i < var_num; i++)
4166 s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4167 p += var_insts[i].size;
4169 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4170 s7_inst.bwarn = -1;
4173 /* Build a relax frag for la instruction when generating s7_PIC,
4174 external symbol first and local symbol second. */
4176 static void
4177 s7_build_la_pic (int reg_rd, expressionS exp)
4179 symbolS *add_symbol = exp.X_add_symbol;
4180 offsetT add_number = exp.X_add_number;
4181 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4182 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4183 int fix_num = 0;
4184 int var_num = 0;
4185 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4186 int r1_bak;
4188 r1_bak = s7_nor1;
4189 s7_nor1 = 0;
4191 if (add_number == 0)
4193 fix_num = 1;
4194 var_num = 2;
4196 /* For an external symbol, only one insn is generated;
4197 For a local symbol, two insns are generated. */
4198 /* Fix part
4199 For an external symbol: lw rD, <sym>($gp)
4200 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
4201 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4202 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4203 return;
4205 if (reg_rd == s7_PIC_CALL_REG)
4206 s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4207 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4209 /* Var part
4210 For a local symbol :
4211 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4212 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4213 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4214 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4215 sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4216 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4217 return;
4219 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4220 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4222 else if (add_number >= -0x8000 && add_number <= 0x7fff)
4224 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4225 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4226 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4227 return;
4229 /* Insn 2 */
4230 fix_num = 1;
4231 var_num = 1;
4232 /* Fix part
4233 For an external symbol: addi rD, <constant> */
4234 sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4235 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4236 return;
4238 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4240 /* Var part
4241 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
4242 sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd,
4243 S_GET_NAME (add_symbol), (int) add_number);
4244 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4245 return;
4247 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4248 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4250 else
4252 int hi = (add_number >> 16) & 0x0000FFFF;
4253 int lo = add_number & 0x0000FFFF;
4255 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
4256 sprintf (tmp, "lw_pic r%d, %s", reg_rd, S_GET_NAME (add_symbol));
4257 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4258 return;
4260 /* Insn 2 */
4261 fix_num = 1;
4262 var_num = 1;
4263 /* Fix part
4264 For an external symbol: ldis r1, HI%<constant> */
4265 sprintf (tmp, "ldis r1, %d", hi);
4266 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4267 return;
4269 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4271 /* Var part
4272 For a local symbol: ldis r1, HI%<constant>
4273 but, if lo is out of 16 bit, make hi plus 1 */
4274 if ((lo < -0x8000) || (lo > 0x7fff))
4276 hi += 1;
4278 sprintf (tmp, "ldis_pic r1, %d", hi);
4279 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4280 return;
4282 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4283 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4285 /* Insn 3 */
4286 fix_num = 1;
4287 var_num = 1;
4288 /* Fix part
4289 For an external symbol: ori r1, LO%<constant> */
4290 sprintf (tmp, "ori r1, %d", lo);
4291 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4292 return;
4294 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4296 /* Var part
4297 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
4298 sprintf (tmp, "addi_u_pic r1, %s + %d", S_GET_NAME (add_symbol), lo);
4299 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4300 return;
4302 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4303 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4305 /* Insn 4: add rD, rD, r1 */
4306 sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4307 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4308 return;
4310 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4311 s7_inst.bwarn = -1;
4314 s7_nor1 = r1_bak;
4317 /* Handle la. */
4319 static void
4320 s7_do_macro_la_rdi32 (char *str)
4322 int reg_rd;
4324 s7_skip_whitespace (str);
4325 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4326 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4328 return;
4330 else
4332 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4333 char *keep_data = str;
4335 /* Check immediate value. */
4336 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4338 s7_inst.error = _("expression error");
4339 return;
4341 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4342 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4344 s7_inst.error = _("value not in range [0, 0xffffffff]");
4345 return;
4348 /* Reset str. */
4349 str = keep_data;
4351 /* la rd, simm16. */
4352 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4354 s7_end_of_line (str);
4355 return;
4357 /* la rd, imm32 or la rd, label. */
4358 else
4360 s7_SET_INSN_ERROR (NULL);
4361 str = keep_data;
4362 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4363 || (s7_end_of_line (str) == (int) s7_FAIL))
4365 return;
4367 else
4369 if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4371 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4372 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4373 return;
4375 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4376 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4377 return;
4379 else
4381 gas_assert (s7_inst.reloc.exp.X_add_symbol);
4382 s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4385 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4386 s7_inst.bwarn = -1;
4392 /* Handle li. */
4394 static void
4395 s7_do_macro_li_rdi32 (char *str)
4397 int reg_rd;
4399 s7_skip_whitespace (str);
4400 if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4401 || s7_skip_past_comma (&str) == (int) s7_FAIL)
4403 return;
4405 else
4407 char *keep_data = str;
4409 /* Check immediate value. */
4410 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4412 s7_inst.error = _("expression error");
4413 return;
4415 else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4416 && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4418 s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4419 return;
4422 /* Reset str. */
4423 str = keep_data;
4425 /* li rd, simm16. */
4426 if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4428 s7_end_of_line (str);
4429 return;
4431 /* li rd, imm32. */
4432 else
4434 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4436 str = keep_data;
4438 if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4439 || (s7_end_of_line (str) == (int) s7_FAIL))
4441 return;
4443 else if (s7_inst.reloc.exp.X_add_symbol)
4445 s7_inst.error = _("li rd label isn't correct instruction form");
4446 return;
4448 else
4450 sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4452 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4453 return;
4454 else
4456 sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4457 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4458 return;
4460 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4461 s7_inst.bwarn = -1;
4468 /* Handle mul/mulu/div/divu/rem/remu. */
4470 static void
4471 s7_do_macro_mul_rdrsrs (char *str)
4473 int reg_rd;
4474 int reg_rs1;
4475 int reg_rs2;
4476 char *backupstr;
4477 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4479 if (s7_university_version == 1)
4480 as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4482 strcpy (append_str, str);
4483 backupstr = append_str;
4484 s7_skip_whitespace (backupstr);
4485 if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4486 || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4487 || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4489 s7_inst.error = s7_BAD_ARGS;
4490 return;
4493 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4495 /* rem/remu rA, rB is error format. */
4496 if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4498 s7_SET_INSN_ERROR (s7_BAD_ARGS);
4500 else
4502 s7_SET_INSN_ERROR (NULL);
4503 s7_do_rsrs (str);
4505 return;
4507 else
4509 s7_SET_INSN_ERROR (NULL);
4510 if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4511 || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4513 return;
4515 else
4517 char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4519 if (strcmp (s7_inst.name, "rem") == 0)
4521 sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4522 sprintf (append_str1, "mfceh r%d", reg_rd);
4524 else if (strcmp (s7_inst.name, "remu") == 0)
4526 sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4527 sprintf (append_str1, "mfceh r%d", reg_rd);
4529 else
4531 sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4532 sprintf (append_str1, "mfcel r%d", reg_rd);
4535 /* Output mul/mulu or div/divu or rem/remu. */
4536 if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4537 return;
4539 /* Output mfcel or mfceh. */
4540 if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4541 return;
4543 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4544 s7_inst.bwarn = -1;
4549 static void
4550 s7_exp_macro_ldst_abs (char *str)
4552 int reg_rd;
4553 char *backupstr, *tmp;
4554 char append_str[s7_MAX_LITERAL_POOL_SIZE];
4555 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4556 struct s7_score_it inst_backup;
4557 int r1_bak = 0;
4559 r1_bak = s7_nor1;
4560 s7_nor1 = 0;
4561 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4563 strcpy (verifystr, str);
4564 backupstr = verifystr;
4565 s7_skip_whitespace (backupstr);
4566 if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4567 return;
4569 tmp = backupstr;
4570 if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4571 return;
4573 backupstr = tmp;
4574 sprintf (append_str, "li r1 %s", backupstr);
4575 s7_append_insn (append_str, TRUE);
4577 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4578 sprintf (append_str, " r%d, [r1,0]", reg_rd);
4579 s7_do_ldst_insn (append_str);
4581 s7_nor1 = r1_bak;
4584 static int
4585 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4587 if (sym == NULL)
4588 return 0;
4589 else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4591 const char *symname;
4592 const char *segname;
4594 /* Find out whether this symbol can be referenced off the $gp
4595 register. It can be if it is smaller than the -G size or if
4596 it is in the .sdata or .sbss section. Certain symbols can
4597 not be referenced off the $gp, although it appears as though
4598 they can. */
4599 symname = S_GET_NAME (sym);
4600 if (symname != NULL
4601 && (strcmp (symname, "eprol") == 0
4602 || strcmp (symname, "etext") == 0
4603 || strcmp (symname, "_gp") == 0
4604 || strcmp (symname, "edata") == 0
4605 || strcmp (symname, "_fbss") == 0
4606 || strcmp (symname, "_fdata") == 0
4607 || strcmp (symname, "_ftext") == 0
4608 || strcmp (symname, "end") == 0
4609 || strcmp (symname, GP_DISP_LABEL) == 0))
4611 return 1;
4613 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4614 /* We must defer this decision until after the whole file has been read,
4615 since there might be a .extern after the first use of this symbol. */
4616 || (before_relaxing
4617 && S_GET_VALUE (sym) == 0)
4618 || (S_GET_VALUE (sym) != 0
4619 && S_GET_VALUE (sym) <= s7_g_switch_value)))
4621 return 0;
4624 segname = segment_name (S_GET_SEGMENT (sym));
4625 return (strcmp (segname, ".sdata") != 0
4626 && strcmp (segname, ".sbss") != 0
4627 && strncmp (segname, ".sdata.", 7) != 0
4628 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4630 /* We are not optimizing for the $gp register. */
4631 else
4632 return 1;
4635 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4636 external symbol first and local symbol second. */
4638 static void
4639 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4641 symbolS *add_symbol = exp.X_add_symbol;
4642 int add_number = exp.X_add_number;
4643 struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4644 struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4645 int fix_num = 0;
4646 int var_num = 0;
4647 char tmp[s7_MAX_LITERAL_POOL_SIZE];
4648 int r1_bak;
4650 r1_bak = s7_nor1;
4651 s7_nor1 = 0;
4653 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4655 fix_num = 1;
4656 var_num = 2;
4658 /* For an external symbol, two insns are generated;
4659 For a local symbol, three insns are generated. */
4660 /* Fix part
4661 For an external symbol: lw rD, <sym>($gp)
4662 (BFD_RELOC_SCORE_GOT15) */
4663 sprintf (tmp, "lw_pic r1, %s", S_GET_NAME (add_symbol));
4664 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4665 return;
4667 memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4669 /* Var part
4670 For a local symbol :
4671 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4672 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4673 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4674 memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4675 sprintf (tmp, "addi_s_pic r1, %s", S_GET_NAME (add_symbol));
4676 if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4677 return;
4679 memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4680 s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4682 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
4683 sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4684 if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4685 return;
4687 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4688 s7_inst.bwarn = -1;
4690 else
4692 s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4693 return;
4696 s7_nor1 = r1_bak;
4699 static void
4700 s7_do_macro_ldst_label (char *str)
4702 int i;
4703 int ldst_gp_p = 0;
4704 int reg_rd;
4705 int r1_bak;
4706 char *backup_str;
4707 char *label_str;
4708 char *absolute_value;
4709 char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4710 char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4711 struct s7_score_it inst_backup;
4712 struct s7_score_it inst_expand[3];
4713 struct s7_score_it inst_main;
4715 memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4716 strcpy (verifystr, str);
4717 backup_str = verifystr;
4719 s7_skip_whitespace (backup_str);
4720 if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4721 return;
4723 if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4724 return;
4726 label_str = backup_str;
4728 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4729 if (*backup_str == '[')
4731 s7_inst.type = Rd_rvalueRs_preSI12;
4732 s7_do_ldst_insn (str);
4733 return;
4736 /* Ld/st rD, imm. */
4737 absolute_value = backup_str;
4738 s7_inst.type = Rd_rvalueRs_SI15;
4740 if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4742 s7_inst.error = _("expression error");
4743 return;
4745 else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4746 && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4748 s7_inst.error = _("value not in range [0, 0x7fffffff]");
4749 return;
4751 else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4753 s7_inst.error = _("end on line error");
4754 return;
4756 else
4758 if (s7_inst.reloc.exp.X_add_symbol == 0)
4760 memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4761 s7_exp_macro_ldst_abs (str);
4762 return;
4766 /* Ld/st rD, label. */
4767 s7_inst.type = Rd_rvalueRs_SI15;
4768 backup_str = absolute_value;
4769 if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4770 || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4772 return;
4774 else
4776 if (s7_inst.reloc.exp.X_add_symbol == 0)
4778 if (!s7_inst.error)
4779 s7_inst.error = s7_BAD_ARGS;
4781 return;
4784 if (s7_score_pic == s7_PIC)
4786 int ldst_idx = 0;
4787 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4788 s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4789 s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4790 return;
4792 else
4794 if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4795 && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4796 && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4798 int ldst_idx = 0;
4800 /* Assign the real opcode. */
4801 ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4802 s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4803 s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4804 s7_inst.instruction |= reg_rd << 20;
4805 s7_inst.instruction |= s7_GP << 15;
4806 s7_inst.relax_inst = 0x8000;
4807 s7_inst.relax_size = 0;
4808 ldst_gp_p = 1;
4813 /* Backup s7_inst. */
4814 memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4815 r1_bak = s7_nor1;
4816 s7_nor1 = 0;
4818 /* Determine which instructions should be output. */
4819 sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4820 sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4821 sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4823 /* Generate three instructions.
4824 la r1, label
4825 ld/st rd, [r1, 0] */
4826 for (i = 0; i < 3; i++)
4828 if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4829 return;
4831 memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4834 if (ldst_gp_p)
4836 char *p;
4838 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4839 inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4840 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4841 inst_main.type = Insn_GP;
4843 for (i = 0; i < 3; i++)
4844 inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4845 , s7_GET_INSN_CLASS (inst_expand[i].type));
4847 /* Check data dependency. */
4848 s7_handle_dependency (&inst_main);
4850 /* Start a new frag if frag_now is not empty. */
4851 if (frag_now_fix () != 0)
4853 if (!frag_now->tc_frag_data.is_insn)
4854 frag_wane (frag_now);
4856 frag_new (0);
4858 frag_grow (20);
4860 /* Write fr_fix part. */
4861 p = frag_more (inst_main.size);
4862 s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4864 if (inst_main.reloc.type != BFD_RELOC_NONE)
4866 s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4867 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4870 #ifdef OBJ_ELF
4871 dwarf2_emit_insn (inst_main.size);
4872 #endif
4874 /* s7_GP instruction can not do optimization, only can do relax between
4875 1 instruction and 3 instructions. */
4876 p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4877 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4878 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4880 /* Write fr_var part.
4881 no calling s7_gen_insn_frag, no fixS will be generated. */
4882 s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4883 p += inst_expand[0].size;
4884 s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4885 p += inst_expand[1].size;
4886 s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4888 else
4890 s7_gen_insn_frag (&inst_expand[0], NULL);
4891 s7_gen_insn_frag (&inst_expand[1], NULL);
4892 s7_gen_insn_frag (&inst_expand[2], NULL);
4894 s7_nor1 = r1_bak;
4896 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4897 s7_inst.bwarn = -1;
4900 static void
4901 s7_do_lw_pic (char *str)
4903 int reg_rd;
4905 s7_skip_whitespace (str);
4906 if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4907 || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4908 || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4909 || (s7_end_of_line (str) == (int) s7_FAIL))
4911 return;
4913 else
4915 if (s7_inst.reloc.exp.X_add_symbol == 0)
4917 if (!s7_inst.error)
4918 s7_inst.error = s7_BAD_ARGS;
4920 return;
4923 s7_inst.instruction |= s7_GP << 15;
4924 s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4928 static void
4929 s7_do_empty (char *str)
4931 str = str;
4932 if (s7_university_version == 1)
4934 if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4935 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4936 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4937 || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4939 s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4940 return;
4943 if (s7_end_of_line (str) == (int) s7_FAIL)
4944 return;
4946 if (s7_inst.relax_inst != 0x8000)
4948 if (s7_inst.type == NO_OPD)
4950 s7_inst.relax_size = 2;
4952 else
4954 s7_inst.relax_size = 4;
4959 static void
4960 s7_do_jump (char *str)
4962 char *save_in;
4964 s7_skip_whitespace (str);
4965 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4966 || s7_end_of_line (str) == (int) s7_FAIL)
4967 return;
4969 if (s7_inst.reloc.exp.X_add_symbol == 0)
4971 s7_inst.error = _("lacking label ");
4972 return;
4975 if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4976 && s7_inst.reloc.exp.X_add_number <= 16777215))
4978 s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4979 return;
4982 save_in = input_line_pointer;
4983 input_line_pointer = str;
4984 s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4985 s7_inst.reloc.pc_rel = 1;
4986 input_line_pointer = save_in;
4989 static void
4990 s7_do16_jump (char *str)
4992 s7_skip_whitespace (str);
4993 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4994 || s7_end_of_line (str) == (int) s7_FAIL)
4996 return;
4998 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5000 s7_inst.error = _("lacking label ");
5001 return;
5003 else if (!(s7_inst.reloc.exp.X_add_number >= 0
5004 && s7_inst.reloc.exp.X_add_number <= 4095))
5006 s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5007 return;
5010 s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5011 s7_inst.reloc.pc_rel = 1;
5014 static void
5015 s7_do_branch (char *str)
5017 unsigned long abs_value = 0;
5019 if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5020 || s7_end_of_line (str) == (int) s7_FAIL)
5022 return;
5024 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5026 s7_inst.error = _("lacking label ");
5027 return;
5029 else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5030 && s7_inst.reloc.exp.X_add_number <= 524287))
5032 s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5033 return;
5036 s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5037 s7_inst.reloc.pc_rel = 1;
5039 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
5040 s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5042 /* Compute 16 bit branch instruction. */
5043 if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5045 s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5046 s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5047 s7_inst.relax_size = 2;
5049 else
5051 s7_inst.relax_inst = 0x8000;
5055 static void
5056 s7_do16_branch (char *str)
5058 if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5059 || s7_end_of_line (str) == (int) s7_FAIL))
5063 else if (s7_inst.reloc.exp.X_add_symbol == 0)
5065 s7_inst.error = _("lacking label");
5067 else if (!(s7_inst.reloc.exp.X_add_number >= -512
5068 && s7_inst.reloc.exp.X_add_number <= 511))
5070 s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5072 else
5074 s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5075 s7_inst.reloc.pc_rel = 1;
5076 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5080 /* Iterate over the base tables to create the instruction patterns. */
5082 static void
5083 s7_build_score_ops_hsh (void)
5085 unsigned int i;
5086 static struct obstack insn_obstack;
5088 obstack_begin (&insn_obstack, 4000);
5089 for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5091 const struct s7_asm_opcode *insn = s7_score_insns + i;
5092 size_t len = strlen (insn->template_name);
5093 struct s7_asm_opcode *new_opcode;
5094 char *template_name;
5095 new_opcode = (struct s7_asm_opcode *)
5096 obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5097 template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5099 strcpy (template_name, insn->template_name);
5100 new_opcode->template_name = template_name;
5101 new_opcode->parms = insn->parms;
5102 new_opcode->value = insn->value;
5103 new_opcode->relax_value = insn->relax_value;
5104 new_opcode->type = insn->type;
5105 new_opcode->bitmask = insn->bitmask;
5106 hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5107 (void *) new_opcode);
5111 static void
5112 s7_build_dependency_insn_hsh (void)
5114 unsigned int i;
5115 static struct obstack dependency_obstack;
5117 obstack_begin (&dependency_obstack, 4000);
5118 for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5120 const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5121 size_t len = strlen (tmp->insn_name);
5122 struct s7_insn_to_dependency *new_i2d;
5123 char *insn_name;
5125 new_i2d = (struct s7_insn_to_dependency *)
5126 obstack_alloc (&dependency_obstack,
5127 sizeof (struct s7_insn_to_dependency));
5128 insn_name = (char *) obstack_alloc (&dependency_obstack, len + 1);
5130 strcpy (insn_name, tmp->insn_name);
5131 new_i2d->insn_name = insn_name;
5132 new_i2d->type = tmp->type;
5133 hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5134 (void *) new_i2d);
5138 static valueT
5139 s7_md_chars_to_number (char *buf, int n)
5141 valueT result = 0;
5142 unsigned char *where = (unsigned char *) buf;
5144 if (target_big_endian)
5146 while (n--)
5148 result <<= 8;
5149 result |= (*where++ & 255);
5152 else
5154 while (n--)
5156 result <<= 8;
5157 result |= (where[n] & 255);
5161 return result;
5164 /* Return true if the given symbol should be considered local for s7_PIC. */
5166 static bfd_boolean
5167 s7_pic_need_relax (symbolS *sym, asection *segtype)
5169 asection *symsec;
5170 bfd_boolean linkonce;
5172 /* Handle the case of a symbol equated to another symbol. */
5173 while (symbol_equated_reloc_p (sym))
5175 symbolS *n;
5177 /* It's possible to get a loop here in a badly written
5178 program. */
5179 n = symbol_get_value_expression (sym)->X_add_symbol;
5180 if (n == sym)
5181 break;
5182 sym = n;
5185 symsec = S_GET_SEGMENT (sym);
5187 /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5188 linkonce = FALSE;
5189 if (symsec != segtype && ! S_IS_LOCAL (sym))
5191 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5192 linkonce = TRUE;
5194 /* The GNU toolchain uses an extension for ELF: a section
5195 beginning with the magic string .gnu.linkonce is a linkonce
5196 section. */
5197 if (strncmp (segment_name (symsec), ".gnu.linkonce",
5198 sizeof ".gnu.linkonce" - 1) == 0)
5199 linkonce = TRUE;
5202 /* This must duplicate the test in adjust_reloc_syms. */
5203 return (!bfd_is_und_section (symsec)
5204 && !bfd_is_abs_section (symsec)
5205 && !bfd_is_com_section (symsec)
5206 && !linkonce
5207 #ifdef OBJ_ELF
5208 /* A global or weak symbol is treated as external. */
5209 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5210 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5211 #endif
5215 static int
5216 s7_judge_size_before_relax (fragS * fragp, asection *sec)
5218 int change = 0;
5220 if (s7_score_pic == s7_NO_PIC)
5221 change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5222 else
5223 change = s7_pic_need_relax (fragp->fr_symbol, sec);
5225 if (change == 1)
5227 /* Only at the first time determining whether s7_GP instruction relax should be done,
5228 return the difference between instruction size and instruction relax size. */
5229 if (fragp->fr_opcode == NULL)
5231 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
5232 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
5233 return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
5237 return 0;
5240 static int
5241 s7_b32_relax_to_b16 (fragS * fragp)
5243 int grows = 0;
5244 int relaxable_p = 0;
5245 int frag_addr = fragp->fr_address + fragp->insn_addr;
5247 addressT symbol_address = 0;
5248 symbolS *s;
5249 offsetT offset;
5250 unsigned long value;
5251 unsigned long abs_value;
5253 /* FIXME : here may be able to modify better .
5254 I don't know how to get the fragp's section ,
5255 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5256 is different from the symbol's. */
5258 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5260 s = fragp->fr_symbol;
5261 /* b/bl immediate */
5262 if (s == NULL)
5263 frag_addr = 0;
5264 else
5265 symbol_address = (addressT) symbol_get_frag (s)->fr_address;
5267 value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5269 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
5270 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
5271 if ((offset & 0x80000) == 0x80000)
5272 offset |= 0xfff00000;
5274 abs_value = offset + symbol_address - frag_addr;
5275 if ((abs_value & 0x80000000) == 0x80000000)
5276 abs_value = 0xffffffff - abs_value + 1;
5278 /* Relax branch 32 to branch 16. */
5279 if (relaxable_p && ((abs_value & 0xffffff00) == 0)
5280 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
5282 /* do nothing. */
5284 else
5286 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
5287 fragp->fr_opcode = NULL;
5288 fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
5291 return grows;
5294 static void
5295 s7_parse_pce_inst (char *insnstr)
5297 char c;
5298 char *p;
5299 char *q;
5300 char first[s7_MAX_LITERAL_POOL_SIZE];
5301 char second[s7_MAX_LITERAL_POOL_SIZE];
5302 struct s7_score_it pec_part_1;
5304 /* Get first part string of PCE. */
5305 p = strstr (insnstr, "||");
5306 c = *p;
5307 *p = '\0';
5308 strcpy (first, insnstr);
5310 /* Get second part string of PCE. */
5311 *p = c;
5312 p += 2;
5313 strcpy (second, p);
5315 s7_parse_16_32_inst (first, FALSE);
5316 if (s7_inst.error)
5317 return;
5319 memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5321 q = second;
5322 while (q && *q)
5324 *q = TOLOWER (*q);
5325 q++;
5328 s7_parse_16_32_inst (second, FALSE);
5329 if (s7_inst.error)
5330 return;
5332 if ( ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
5333 || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
5334 || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
5336 s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5337 strcpy (s7_inst.str, insnstr);
5338 return;
5341 if (!s7_inst.error)
5342 s7_gen_insn_frag (&pec_part_1, &s7_inst);
5347 static void
5348 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5350 int i = 0;
5351 int len = strlen (r->name) + 2;
5352 char *buf = XNEWVEC (char, len);
5353 char *buf2 = XNEWVEC (char, len);
5355 strcpy (buf + i, r->name);
5356 for (i = 0; buf[i]; i++)
5358 buf2[i] = TOUPPER (buf[i]);
5360 buf2[i] = '\0';
5362 hash_insert (htab, buf, (void *) r);
5363 hash_insert (htab, buf2, (void *) r);
5366 static void
5367 s7_build_reg_hsh (struct s7_reg_map *map)
5369 const struct s7_reg_entry *r;
5371 if ((map->htab = hash_new ()) == NULL)
5373 as_fatal (_("virtual memory exhausted"));
5375 for (r = map->names; r->name != NULL; r++)
5377 s7_insert_reg (r, map->htab);
5383 /* If we change section we must dump the literal pool first. */
5384 static void
5385 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5387 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5388 demand_empty_rest_of_line ();
5391 static void
5392 s7_s_score_text (int ignore)
5394 obj_elf_text (ignore);
5395 record_alignment (now_seg, 2);
5398 static void
5399 s7_s_section (int ignore)
5401 obj_elf_section (ignore);
5402 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5403 record_alignment (now_seg, 2);
5407 static void
5408 s7_s_change_sec (int sec)
5410 segT seg;
5412 #ifdef OBJ_ELF
5413 /* The ELF backend needs to know that we are changing sections, so
5414 that .previous works correctly. We could do something like check
5415 for an obj_section_change_hook macro, but that might be confusing
5416 as it would not be appropriate to use it in the section changing
5417 functions in read.c, since obj-elf.c intercepts those. FIXME:
5418 This should be cleaner, somehow. */
5419 obj_elf_section_change_hook ();
5420 #endif
5421 switch (sec)
5423 case 'r':
5424 seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5425 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5426 if (strcmp (TARGET_OS, "elf") != 0)
5427 record_alignment (seg, 4);
5428 demand_empty_rest_of_line ();
5429 break;
5430 case 's':
5431 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5432 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5433 if (strcmp (TARGET_OS, "elf") != 0)
5434 record_alignment (seg, 4);
5435 demand_empty_rest_of_line ();
5436 break;
5440 static void
5441 s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5443 long mask, off;
5445 if (s7_cur_proc_ptr == NULL)
5447 as_warn (_(".mask outside of .ent"));
5448 demand_empty_rest_of_line ();
5449 return;
5451 if (get_absolute_expression_and_terminator (&mask) != ',')
5453 as_warn (_("Bad .mask directive"));
5454 --input_line_pointer;
5455 demand_empty_rest_of_line ();
5456 return;
5458 off = get_absolute_expression ();
5459 s7_cur_proc_ptr->reg_mask = mask;
5460 s7_cur_proc_ptr->reg_offset = off;
5461 demand_empty_rest_of_line ();
5464 static symbolS *
5465 s7_get_symbol (void)
5467 int c;
5468 char *name;
5469 symbolS *p;
5471 c = get_symbol_name (&name);
5472 p = (symbolS *) symbol_find_or_make (name);
5473 (void) restore_line_pointer (c);
5474 return p;
5477 static long
5478 s7_get_number (void)
5480 int negative = 0;
5481 long val = 0;
5483 if (*input_line_pointer == '-')
5485 ++input_line_pointer;
5486 negative = 1;
5488 if (!ISDIGIT (*input_line_pointer))
5489 as_bad (_("expected simple number"));
5490 if (input_line_pointer[0] == '0')
5492 if (input_line_pointer[1] == 'x')
5494 input_line_pointer += 2;
5495 while (ISXDIGIT (*input_line_pointer))
5497 val <<= 4;
5498 val |= hex_value (*input_line_pointer++);
5500 return negative ? -val : val;
5502 else
5504 ++input_line_pointer;
5505 while (ISDIGIT (*input_line_pointer))
5507 val <<= 3;
5508 val |= *input_line_pointer++ - '0';
5510 return negative ? -val : val;
5513 if (!ISDIGIT (*input_line_pointer))
5515 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5516 as_warn (_("invalid number"));
5517 return -1;
5519 while (ISDIGIT (*input_line_pointer))
5521 val *= 10;
5522 val += *input_line_pointer++ - '0';
5524 return negative ? -val : val;
5527 /* The .aent and .ent directives. */
5529 static void
5530 s7_s_score_ent (int aent)
5532 symbolS *symbolP;
5533 int maybe_text;
5535 symbolP = s7_get_symbol ();
5536 if (*input_line_pointer == ',')
5537 ++input_line_pointer;
5538 SKIP_WHITESPACE ();
5539 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5540 s7_get_number ();
5542 #ifdef BFD_ASSEMBLER
5543 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5544 maybe_text = 1;
5545 else
5546 maybe_text = 0;
5547 #else
5548 if (now_seg != data_section && now_seg != bss_section)
5549 maybe_text = 1;
5550 else
5551 maybe_text = 0;
5552 #endif
5553 if (!maybe_text)
5554 as_warn (_(".ent or .aent not in text section."));
5555 if (!aent && s7_cur_proc_ptr)
5556 as_warn (_("missing .end"));
5557 if (!aent)
5559 s7_cur_proc_ptr = &s7_cur_proc;
5560 s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5561 s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5562 s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5563 s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5564 s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5565 s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5566 s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5567 s7_cur_proc_ptr->isym = symbolP;
5568 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5569 ++s7_numprocs;
5570 if (debug_type == DEBUG_STABS)
5571 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5573 demand_empty_rest_of_line ();
5576 static void
5577 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5579 char *backupstr;
5580 char str[30];
5581 long val;
5582 int i = 0;
5584 backupstr = input_line_pointer;
5586 #ifdef OBJ_ELF
5587 if (s7_cur_proc_ptr == NULL)
5589 as_warn (_(".frame outside of .ent"));
5590 demand_empty_rest_of_line ();
5591 return;
5593 s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5594 SKIP_WHITESPACE ();
5595 s7_skip_past_comma (&backupstr);
5596 while (*backupstr != ',')
5598 str[i] = *backupstr;
5599 i++;
5600 backupstr++;
5602 str[i] = '\0';
5603 val = atoi (str);
5605 SKIP_WHITESPACE ();
5606 s7_skip_past_comma (&backupstr);
5607 s7_cur_proc_ptr->frame_offset = val;
5608 s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5610 SKIP_WHITESPACE ();
5611 s7_skip_past_comma (&backupstr);
5612 i = 0;
5613 while (*backupstr != '\n')
5615 str[i] = *backupstr;
5616 i++;
5617 backupstr++;
5619 str[i] = '\0';
5620 val = atoi (str);
5621 s7_cur_proc_ptr->leaf = val;
5622 SKIP_WHITESPACE ();
5623 s7_skip_past_comma (&backupstr);
5625 #endif /* OBJ_ELF */
5626 while (input_line_pointer != backupstr)
5627 input_line_pointer++;
5630 /* The .end directive. */
5632 static void
5633 s7_s_score_end (int x ATTRIBUTE_UNUSED)
5635 symbolS *p;
5636 int maybe_text;
5638 /* Generate a .pdr section. */
5639 segT saved_seg = now_seg;
5640 subsegT saved_subseg = now_subseg;
5641 expressionS exp;
5642 char *fragp;
5644 if (!is_end_of_line[(unsigned char)*input_line_pointer])
5646 p = s7_get_symbol ();
5647 demand_empty_rest_of_line ();
5649 else
5650 p = NULL;
5652 #ifdef BFD_ASSEMBLER
5653 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5654 maybe_text = 1;
5655 else
5656 maybe_text = 0;
5657 #else
5658 if (now_seg != data_section && now_seg != bss_section)
5659 maybe_text = 1;
5660 else
5661 maybe_text = 0;
5662 #endif
5664 if (!maybe_text)
5665 as_warn (_(".end not in text section"));
5666 if (!s7_cur_proc_ptr)
5668 as_warn (_(".end directive without a preceding .ent directive."));
5669 demand_empty_rest_of_line ();
5670 return;
5672 if (p != NULL)
5674 gas_assert (S_GET_NAME (p));
5675 if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5676 as_warn (_(".end symbol does not match .ent symbol."));
5677 if (debug_type == DEBUG_STABS)
5678 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5680 else
5681 as_warn (_(".end directive missing or unknown symbol"));
5683 if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5684 (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5685 (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5686 (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5687 (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5689 else
5691 (void) frag_now_fix ();
5692 gas_assert (s7_pdr_seg);
5693 subseg_set (s7_pdr_seg, 0);
5694 /* Write the symbol. */
5695 exp.X_op = O_symbol;
5696 exp.X_add_symbol = p;
5697 exp.X_add_number = 0;
5698 emit_expr (&exp, 4);
5699 fragp = frag_more (7 * 4);
5700 s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5701 s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5702 s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5703 s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5704 s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5705 s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5706 s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5707 subseg_set (saved_seg, saved_subseg);
5710 s7_cur_proc_ptr = NULL;
5713 /* Handle the .set pseudo-op. */
5715 static void
5716 s7_s_score_set (int x ATTRIBUTE_UNUSED)
5718 int i = 0;
5719 char name[s7_MAX_LITERAL_POOL_SIZE];
5720 char * orig_ilp = input_line_pointer;
5722 while (!is_end_of_line[(unsigned char)*input_line_pointer])
5724 name[i] = (char) * input_line_pointer;
5725 i++;
5726 ++input_line_pointer;
5729 name[i] = '\0';
5731 if (strcmp (name, "nwarn") == 0)
5733 s7_warn_fix_data_dependency = 0;
5735 else if (strcmp (name, "fixdd") == 0)
5737 s7_fix_data_dependency = 1;
5739 else if (strcmp (name, "nofixdd") == 0)
5741 s7_fix_data_dependency = 0;
5743 else if (strcmp (name, "r1") == 0)
5745 s7_nor1 = 0;
5747 else if (strcmp (name, "nor1") == 0)
5749 s7_nor1 = 1;
5751 else if (strcmp (name, "optimize") == 0)
5753 s7_g_opt = 1;
5755 else if (strcmp (name, "volatile") == 0)
5757 s7_g_opt = 0;
5759 else if (strcmp (name, "pic") == 0)
5761 s7_score_pic = s7_PIC;
5763 else
5765 input_line_pointer = orig_ilp;
5766 s_set (0);
5770 /* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the
5771 $gp register for the function based on the function address, which is in the register
5772 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5773 specially by the linker. The result is:
5774 ldis gp, %hi(GP_DISP_LABEL)
5775 ori gp, %low(GP_DISP_LABEL)
5776 add gp, gp, .cpload argument
5777 The .cpload argument is normally r29. */
5779 static void
5780 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5782 int reg;
5783 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5785 /* If we are not generating s7_PIC code, .cpload is ignored. */
5786 if (s7_score_pic == s7_NO_PIC)
5788 s_ignore (0);
5789 return;
5792 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5793 return;
5795 demand_empty_rest_of_line ();
5797 sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5798 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5799 return;
5801 sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5802 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5803 return;
5805 sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5806 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5807 return;
5810 /* Handle the .cprestore pseudo-op. This stores $gp into a given
5811 offset from $sp. The offset is remembered, and after making a s7_PIC
5812 call $gp is restored from that location. */
5814 static void
5815 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5817 int reg;
5818 int cprestore_offset;
5819 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5821 /* If we are not generating s7_PIC code, .cprestore is ignored. */
5822 if (s7_score_pic == s7_NO_PIC)
5824 s_ignore (0);
5825 return;
5828 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5829 || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5831 return;
5834 cprestore_offset = get_absolute_expression ();
5836 if (cprestore_offset <= 0x3fff)
5838 sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5839 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5840 return;
5842 else
5844 int r1_bak;
5846 r1_bak = s7_nor1;
5847 s7_nor1 = 0;
5849 sprintf (insn_str, "li r1, %d", cprestore_offset);
5850 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5851 return;
5853 sprintf (insn_str, "add r1, r1, r%d", reg);
5854 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5855 return;
5857 sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5858 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5859 return;
5861 s7_nor1 = r1_bak;
5864 demand_empty_rest_of_line ();
5867 /* Handle the .gpword pseudo-op. This is used when generating s7_PIC
5868 code. It generates a 32 bit s7_GP relative reloc. */
5870 static void
5871 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5873 expressionS ex;
5874 char *p;
5876 /* When not generating s7_PIC code, this is treated as .word. */
5877 if (s7_score_pic == s7_NO_PIC)
5879 cons (4);
5880 return;
5882 expression (&ex);
5883 if (ex.X_op != O_symbol || ex.X_add_number != 0)
5885 as_bad (_("Unsupported use of .gpword"));
5886 ignore_rest_of_line ();
5888 p = frag_more (4);
5889 s7_number_to_chars (p, (valueT) 0, 4);
5890 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5891 demand_empty_rest_of_line ();
5894 /* Handle the .cpadd pseudo-op. This is used when dealing with switch
5895 tables in s7_PIC code. */
5897 static void
5898 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5900 int reg;
5901 char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5903 /* If we are not generating s7_PIC code, .cpload is ignored. */
5904 if (s7_score_pic == s7_NO_PIC)
5906 s_ignore (0);
5907 return;
5910 if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5912 return;
5914 demand_empty_rest_of_line ();
5916 /* Add $gp to the register named as an argument. */
5917 sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5918 if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5919 return;
5922 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5923 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
5924 do \
5926 if ((SIZE) >= 8) \
5927 (P2VAR) = 3; \
5928 else if ((SIZE) >= 4) \
5929 (P2VAR) = 2; \
5930 else if ((SIZE) >= 2) \
5931 (P2VAR) = 1; \
5932 else \
5933 (P2VAR) = 0; \
5935 while (0)
5936 #endif
5938 static void
5939 s7_s_score_lcomm (int bytes_p)
5941 char *name;
5942 char c;
5943 char *p;
5944 int temp;
5945 symbolS *symbolP;
5946 segT current_seg = now_seg;
5947 subsegT current_subseg = now_subseg;
5948 const int max_alignment = 15;
5949 int align = 0;
5950 segT bss_seg = bss_section;
5951 int needs_align = 0;
5953 c = get_symbol_name (&name);
5954 p = input_line_pointer;
5955 *p = c;
5957 if (name == p)
5959 as_bad (_("expected symbol name"));
5960 discard_rest_of_line ();
5961 return;
5964 SKIP_WHITESPACE_AFTER_NAME ();
5966 /* Accept an optional comma after the name. The comma used to be
5967 required, but Irix 5 cc does not generate it. */
5968 if (*input_line_pointer == ',')
5970 ++input_line_pointer;
5971 SKIP_WHITESPACE ();
5974 if (is_end_of_line[(unsigned char)*input_line_pointer])
5976 as_bad (_("missing size expression"));
5977 return;
5980 if ((temp = get_absolute_expression ()) < 0)
5982 as_warn (_("BSS length (%d) < 0 ignored"), temp);
5983 ignore_rest_of_line ();
5984 return;
5987 #if defined (TC_SCORE)
5988 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
5990 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
5991 if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
5993 bss_seg = subseg_new (".sbss", 1);
5994 seg_info (bss_seg)->bss = 1;
5995 #ifdef BFD_ASSEMBLER
5996 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
5997 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
5998 #endif
6001 #endif
6003 SKIP_WHITESPACE ();
6004 if (*input_line_pointer == ',')
6006 ++input_line_pointer;
6007 SKIP_WHITESPACE ();
6009 if (is_end_of_line[(unsigned char)*input_line_pointer])
6011 as_bad (_("missing alignment"));
6012 return;
6014 else
6016 align = get_absolute_expression ();
6017 needs_align = 1;
6021 if (!needs_align)
6023 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6025 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6026 if (align)
6027 record_alignment (bss_seg, align);
6030 if (needs_align)
6032 if (bytes_p)
6034 /* Convert to a power of 2. */
6035 if (align != 0)
6037 unsigned int i;
6039 for (i = 0; align != 0; align >>= 1, ++i)
6041 align = i - 1;
6045 if (align > max_alignment)
6047 align = max_alignment;
6048 as_warn (_("alignment too large; %d assumed"), align);
6050 else if (align < 0)
6052 align = 0;
6053 as_warn (_("alignment negative; 0 assumed"));
6056 record_alignment (bss_seg, align);
6058 else
6060 /* Assume some objects may require alignment on some systems. */
6061 #if defined (TC_ALPHA) && ! defined (VMS)
6062 if (temp > 1)
6064 align = ffs (temp) - 1;
6065 if (temp % (1 << align))
6066 abort ();
6068 #endif
6071 *p = 0;
6072 symbolP = symbol_find_or_make (name);
6073 *p = c;
6075 if (
6076 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
6077 #ifdef BFD_ASSEMBLER
6078 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6079 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6080 #else
6081 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6082 #endif
6083 #endif
6084 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6086 char *pfrag;
6088 subseg_set (bss_seg, 1);
6090 if (align)
6091 frag_align (align, 0, 0);
6093 /* Detach from old frag. */
6094 if (S_GET_SEGMENT (symbolP) == bss_seg)
6095 symbol_get_frag (symbolP)->fr_symbol = NULL;
6097 symbol_set_frag (symbolP, frag_now);
6098 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6099 *pfrag = 0;
6102 S_SET_SEGMENT (symbolP, bss_seg);
6104 #ifdef OBJ_COFF
6105 /* The symbol may already have been created with a preceding
6106 ".globl" directive -- be careful not to step on storage class
6107 in that case. Otherwise, set it to static. */
6108 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6110 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6112 #endif /* OBJ_COFF */
6114 #ifdef S_SET_SIZE
6115 S_SET_SIZE (symbolP, temp);
6116 #endif
6118 else
6119 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6121 subseg_set (current_seg, current_subseg);
6123 demand_empty_rest_of_line ();
6128 static void
6129 s7_begin (void)
6131 unsigned int i;
6132 segT seg;
6133 subsegT subseg;
6135 if ((s7_score_ops_hsh = hash_new ()) == NULL)
6136 as_fatal (_("virtual memory exhausted"));
6138 s7_build_score_ops_hsh ();
6140 if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6141 as_fatal (_("virtual memory exhausted"));
6143 s7_build_dependency_insn_hsh ();
6145 for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6146 s7_build_reg_hsh (s7_all_reg_maps + i);
6148 /* Initialize dependency vector. */
6149 s7_init_dependency_vector ();
6151 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6152 seg = now_seg;
6153 subseg = now_subseg;
6154 s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6155 (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6156 (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
6157 subseg_set (seg, subseg);
6159 if (s7_USE_GLOBAL_POINTER_OPT)
6160 bfd_set_gp_size (stdoutput, s7_g_switch_value);
6163 static void
6164 s7_assemble (char *str)
6166 know (str);
6167 know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6169 memset (&s7_inst, '\0', sizeof (s7_inst));
6170 if (s7_INSN_IS_PCE_P (str))
6171 s7_parse_pce_inst (str);
6172 else
6173 s7_parse_16_32_inst (str, TRUE);
6175 if (s7_inst.error)
6176 as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6179 /* We handle all bad expressions here, so that we can report the faulty
6180 instruction in the error message. */
6182 static void
6183 s7_operand (expressionS * exp)
6185 if (s7_in_my_get_expression)
6187 exp->X_op = O_illegal;
6188 if (s7_inst.error == NULL)
6190 s7_inst.error = _("bad expression");
6195 /* Turn a string in input_line_pointer into a floating point constant
6196 of type TYPE, and store the appropriate bytes in *LITP. The number
6197 of LITTLENUMS emitted is stored in *SIZEP. An error message is
6198 returned, or NULL on OK.
6200 Note that fp constants aren't represent in the normal way on the ARM.
6201 In big endian mode, things are as expected. However, in little endian
6202 mode fp constants are big-endian word-wise, and little-endian byte-wise
6203 within the words. For example, (double) 1.1 in big endian mode is
6204 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6205 the byte sequence 99 99 f1 3f 9a 99 99 99. */
6207 static const char *
6208 s7_atof (int type, char *litP, int *sizeP)
6210 int prec;
6211 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6212 char *t;
6213 int i;
6215 switch (type)
6217 case 'f':
6218 case 'F':
6219 case 's':
6220 case 'S':
6221 prec = 2;
6222 break;
6223 case 'd':
6224 case 'D':
6225 case 'r':
6226 case 'R':
6227 prec = 4;
6228 break;
6229 case 'x':
6230 case 'X':
6231 case 'p':
6232 case 'P':
6233 prec = 6;
6234 break;
6235 default:
6236 *sizeP = 0;
6237 return _("bad call to MD_ATOF()");
6240 t = atof_ieee (input_line_pointer, type, words);
6241 if (t)
6242 input_line_pointer = t;
6243 *sizeP = prec * 2;
6245 if (target_big_endian)
6247 for (i = 0; i < prec; i++)
6249 s7_number_to_chars (litP, (valueT) words[i], 2);
6250 litP += 2;
6253 else
6255 for (i = 0; i < prec; i += 2)
6257 s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6258 s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6259 litP += 4;
6263 return 0;
6266 /* Implementation of md_frag_check.
6267 Called after md_convert_frag(). */
6269 static void
6270 s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6272 know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6275 /* Implementation of TC_VALIDATE_FIX.
6276 Called before md_apply_fix() and after md_convert_frag(). */
6278 static void
6279 s7_validate_fix (fixS *fixP)
6281 fixP->fx_where += fixP->fx_frag->insn_addr;
6284 static int
6285 s7_force_relocation (struct fix *fixp)
6287 int retval = 0;
6289 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6290 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6291 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6292 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6293 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6294 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6296 retval = 1;
6299 return retval;
6302 static bfd_boolean
6303 s7_fix_adjustable (fixS * fixP)
6305 if (fixP->fx_addsy == NULL)
6307 return 1;
6309 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6310 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6312 return 0;
6314 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6315 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6316 || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6317 || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6319 return 0;
6322 return 1;
6325 static void
6326 s7_elf_final_processing (void)
6328 unsigned long val = E_SCORE_MACH_SCORE7;
6330 elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6331 elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6332 elf_elfheader (stdoutput)->e_flags |= val;
6334 if (s7_fix_data_dependency == 1)
6336 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6338 if (s7_score_pic == s7_PIC)
6340 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6344 /* In this function, we determine whether s7_GP instruction should do relaxation,
6345 for the label being against was known now.
6346 Doing this here but not in md_relax_frag() can induce iteration times
6347 in stage of doing relax. */
6349 static int
6350 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6352 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6353 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6354 return s7_judge_size_before_relax (fragp, sec);
6356 return 0;
6359 static int
6360 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6361 fragS * fragp,
6362 long stretch ATTRIBUTE_UNUSED)
6364 int grows = 0;
6365 int insn_size;
6366 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
6367 int relaxable_p = 0;
6368 bfd_boolean word_align_p = FALSE;
6369 fragS *next_fragp;
6371 /* If the instruction address is odd, make it half word align first. */
6372 if ((fragp->fr_address) % 2 != 0)
6374 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6376 fragp->insn_addr = 1;
6377 grows += 1;
6381 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6383 /* Get instruction size and relax size after the last relaxation. */
6384 if (fragp->fr_opcode)
6385 insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6386 else
6387 insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6389 /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine
6390 whether the s7_GP instruction should do relax. */
6391 if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6392 || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6394 if (!word_align_p)
6396 if (fragp->insn_addr < 2)
6398 fragp->insn_addr += 2;
6399 grows += 2;
6401 else
6403 fragp->insn_addr -= 2;
6404 grows -= 2;
6408 if (fragp->fr_opcode)
6409 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6410 else
6411 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6413 else
6415 if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6416 s7_b32_relax_to_b16 (fragp);
6418 relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6419 next_fragp = fragp->fr_next;
6420 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6422 next_fragp = next_fragp->fr_next;
6425 if (next_fragp)
6427 int n_insn_size;
6428 int n_relaxable_p = 0;
6430 if (next_fragp->fr_opcode)
6432 n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6434 else
6436 n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6439 if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6440 s7_b32_relax_to_b16 (next_fragp);
6441 n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6443 if (word_align_p)
6445 if (insn_size == 4)
6447 /* 32 -> 16. */
6448 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6450 grows -= 2;
6451 do_relax_p = 1;
6454 else if (insn_size == 2)
6456 /* 16 -> 32. */
6457 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6459 grows += 2;
6460 do_relax_p = 1;
6463 else
6465 abort ();
6468 else
6470 if (insn_size == 4)
6472 /* 32 -> 16. */
6473 if (relaxable_p)
6475 grows -= 2;
6476 do_relax_p = 1;
6478 /* Make the 32 bit instruction word align. */
6479 else
6481 fragp->insn_addr += 2;
6482 grows += 2;
6485 else if (insn_size == 2)
6487 /* Do nothing. */
6489 else
6491 abort ();
6495 else
6497 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
6498 if (!word_align_p)
6500 if (insn_size % 4 == 0)
6502 /* 32 -> 16. */
6503 if (relaxable_p)
6505 grows -= 2;
6506 do_relax_p = 1;
6508 else
6510 fragp->insn_addr += 2;
6511 grows += 2;
6515 else
6517 /* Do nothing. */
6521 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6522 if (do_relax_p)
6524 if (fragp->fr_opcode)
6526 fragp->fr_opcode = NULL;
6527 /* Guarantee estimate stage is correct. */
6528 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6529 fragp->fr_fix += fragp->insn_addr;
6531 else
6533 fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6534 /* Guarantee estimate stage is correct. */
6535 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6536 fragp->fr_fix += fragp->insn_addr;
6539 else
6541 if (fragp->fr_opcode)
6543 /* Guarantee estimate stage is correct. */
6544 fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6545 fragp->fr_fix += fragp->insn_addr;
6547 else
6549 /* Guarantee estimate stage is correct. */
6550 fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6551 fragp->fr_fix += fragp->insn_addr;
6556 return grows;
6559 static void
6560 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6561 segT sec ATTRIBUTE_UNUSED,
6562 fragS * fragp)
6564 unsigned int r_old;
6565 unsigned int r_new;
6566 char backup[20];
6567 fixS *fixp;
6569 r_old = s7_RELAX_OLD (fragp->fr_subtype);
6570 r_new = s7_RELAX_NEW (fragp->fr_subtype);
6572 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
6573 if (fragp->fr_opcode == NULL)
6575 memcpy (backup, fragp->fr_literal, r_old);
6576 fragp->fr_fix = r_old;
6578 else
6580 memcpy (backup, fragp->fr_literal + r_old, r_new);
6581 fragp->fr_fix = r_new;
6584 fixp = fragp->tc_frag_data.fixp;
6585 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6587 if (fragp->fr_opcode)
6588 fixp->fx_done = 1;
6589 fixp = fixp->fx_next;
6591 while (fixp && fixp->fx_frag == fragp)
6593 if (fragp->fr_opcode)
6594 fixp->fx_where -= r_old + fragp->insn_addr;
6595 else
6596 fixp->fx_done = 1;
6597 fixp = fixp->fx_next;
6600 if (fragp->insn_addr)
6602 s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6604 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6605 fragp->fr_fix += fragp->insn_addr;
6608 static long
6609 s7_pcrel_from (fixS * fixP)
6611 long retval = 0;
6613 if (fixP->fx_addsy
6614 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6615 && (fixP->fx_subsy == NULL))
6617 retval = 0;
6619 else
6621 retval = fixP->fx_where + fixP->fx_frag->fr_address;
6624 return retval;
6627 /* Round up a section size to the appropriate boundary. */
6628 static valueT
6629 s7_section_align (segT segment, valueT size)
6631 int align = bfd_get_section_alignment (stdoutput, segment);
6633 return ((size + (1 << align) - 1) & -(1 << align));
6636 static void
6637 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6639 offsetT value = *valP;
6640 offsetT abs_value = 0;
6641 offsetT newval;
6642 offsetT content;
6643 unsigned short HI, LO;
6645 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6647 gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6648 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6650 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6651 fixP->fx_done = 1;
6654 /* If this symbol is in a different section then we need to leave it for
6655 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
6656 so we have to undo it's effects here. */
6657 if (fixP->fx_pcrel)
6659 if (fixP->fx_addsy != NULL
6660 && S_IS_DEFINED (fixP->fx_addsy)
6661 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6662 value += md_pcrel_from (fixP);
6665 /* Remember value for emit_reloc. */
6666 fixP->fx_addnumber = value;
6668 switch (fixP->fx_r_type)
6670 case BFD_RELOC_HI16_S:
6671 if (fixP->fx_done)
6672 { /* For la rd, imm32. */
6673 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6674 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
6675 newval |= (HI & 0x3fff) << 1;
6676 newval |= ((HI >> 14) & 0x3) << 16;
6677 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6679 break;
6680 case BFD_RELOC_LO16:
6681 if (fixP->fx_done) /* For la rd, imm32. */
6683 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6684 LO = (value) & 0xffff;
6685 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
6686 newval |= ((LO >> 14) & 0x3) << 16;
6687 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6689 break;
6690 case BFD_RELOC_SCORE_JMP:
6692 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6693 value = fixP->fx_offset;
6694 if (!(value >= 0 && value <= 0x1ffffff))
6696 as_bad_where (fixP->fx_file, fixP->fx_line,
6697 _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value);
6698 return;
6700 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6701 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6703 break;
6704 case BFD_RELOC_SCORE_BRANCH:
6705 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6706 value = fixP->fx_offset;
6707 else
6708 fixP->fx_done = 1;
6710 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6711 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6713 if ((value & 0x80000000) == 0x80000000)
6714 abs_value = 0xffffffff - value + 1;
6715 if ((abs_value & 0xffffff00) != 0)
6717 as_bad_where (fixP->fx_file, fixP->fx_line,
6718 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6719 return;
6721 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6722 content &= 0xff00;
6723 content = (content & 0xff00) | ((value >> 1) & 0xff);
6724 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6725 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6726 fixP->fx_size = 2;
6728 else
6730 if ((value & 0x80000000) == 0x80000000)
6731 abs_value = 0xffffffff - value + 1;
6732 if ((abs_value & 0xfff80000) != 0)
6734 as_bad_where (fixP->fx_file, fixP->fx_line,
6735 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6736 (unsigned int) value);
6737 return;
6739 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6740 content &= 0xfc00fc01;
6741 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6742 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6744 break;
6745 case BFD_RELOC_SCORE16_JMP:
6746 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6747 content &= 0xf001;
6748 value = fixP->fx_offset;
6749 if (!(value >= 0 && value <= 0xfff))
6751 as_bad_where (fixP->fx_file, fixP->fx_line,
6752 _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value);
6753 return;
6755 value = fixP->fx_offset & 0xfff;
6756 content = (content & 0xfc01) | (value & 0xffe);
6757 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6758 break;
6759 case BFD_RELOC_SCORE16_BRANCH:
6760 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6761 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6763 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6764 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6765 value = fixP->fx_offset;
6766 else
6767 fixP->fx_done = 1;
6769 if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6771 as_bad_where (fixP->fx_file, fixP->fx_line,
6772 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6773 (unsigned int) value);
6774 return;
6776 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6777 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6778 s7_number_to_chars (buf, content, s7_INSN_SIZE);
6779 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6780 fixP->fx_size = 4;
6781 break;
6783 else
6785 /* In different section. */
6786 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6787 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6788 value = fixP->fx_offset;
6789 else
6790 fixP->fx_done = 1;
6792 if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6794 as_bad_where (fixP->fx_file, fixP->fx_line,
6795 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"),
6796 (unsigned int) value);
6797 return;
6799 content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6800 content = (content & 0xff00) | ((value >> 1) & 0xff);
6801 s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6802 break;
6804 case BFD_RELOC_8:
6805 if (fixP->fx_done || fixP->fx_pcrel)
6806 s7_number_to_chars (buf, value, 1);
6807 #ifdef OBJ_ELF
6808 else
6810 value = fixP->fx_offset;
6811 s7_number_to_chars (buf, value, 1);
6813 #endif
6814 break;
6816 case BFD_RELOC_16:
6817 if (fixP->fx_done || fixP->fx_pcrel)
6818 s7_number_to_chars (buf, value, 2);
6819 #ifdef OBJ_ELF
6820 else
6822 value = fixP->fx_offset;
6823 s7_number_to_chars (buf, value, 2);
6825 #endif
6826 break;
6827 case BFD_RELOC_RVA:
6828 case BFD_RELOC_32:
6829 if (fixP->fx_done || fixP->fx_pcrel)
6830 s7_number_to_chars (buf, value, 4);
6831 #ifdef OBJ_ELF
6832 else
6834 value = fixP->fx_offset;
6835 s7_number_to_chars (buf, value, 4);
6837 #endif
6838 break;
6839 case BFD_RELOC_VTABLE_INHERIT:
6840 fixP->fx_done = 0;
6841 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6842 S_SET_WEAK (fixP->fx_addsy);
6843 break;
6844 case BFD_RELOC_VTABLE_ENTRY:
6845 fixP->fx_done = 0;
6846 break;
6847 case BFD_RELOC_SCORE_GPREL15:
6848 content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6849 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6850 fixP->fx_r_type = BFD_RELOC_NONE;
6851 fixP->fx_done = 0;
6852 break;
6853 case BFD_RELOC_SCORE_GOT15:
6854 case BFD_RELOC_SCORE_DUMMY_HI16:
6855 case BFD_RELOC_SCORE_GOT_LO16:
6856 case BFD_RELOC_SCORE_CALL15:
6857 case BFD_RELOC_GPREL32:
6858 break;
6859 case BFD_RELOC_NONE:
6860 default:
6861 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6865 /* Translate internal representation of relocation info to BFD target format. */
6867 static arelent **
6868 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6870 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
6871 arelent *reloc;
6872 bfd_reloc_code_real_type code;
6873 const char *type;
6875 reloc = retval[0] = XNEW (arelent);
6876 retval[1] = NULL;
6878 reloc->sym_ptr_ptr = XNEW (asymbol *);
6879 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6880 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6881 reloc->addend = fixp->fx_offset;
6883 /* If this is a variant frag, we may need to adjust the existing
6884 reloc and generate a new one. */
6885 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6887 /* Update instruction imm bit. */
6888 offsetT newval;
6889 unsigned short off;
6890 char *buf;
6892 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6893 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6894 off = fixp->fx_offset >> 16;
6895 newval |= (off & 0x3fff) << 1;
6896 newval |= ((off >> 14) & 0x3) << 16;
6897 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6899 buf += s7_INSN_SIZE;
6900 newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6901 off = fixp->fx_offset & 0xffff;
6902 newval |= ((off & 0x3fff) << 1);
6903 newval |= (((off >> 14) & 0x3) << 16);
6904 s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6906 retval[1] = XNEW (arelent);
6907 retval[2] = NULL;
6908 retval[1]->sym_ptr_ptr = XNEW (asymbol *);
6909 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6910 retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6912 retval[1]->addend = 0;
6913 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6914 gas_assert (retval[1]->howto != NULL);
6916 fixp->fx_r_type = BFD_RELOC_HI16_S;
6919 code = fixp->fx_r_type;
6920 switch (fixp->fx_r_type)
6922 case BFD_RELOC_32:
6923 if (fixp->fx_pcrel)
6925 code = BFD_RELOC_32_PCREL;
6926 break;
6928 /* Fall through. */
6929 case BFD_RELOC_HI16_S:
6930 case BFD_RELOC_LO16:
6931 case BFD_RELOC_SCORE_JMP:
6932 case BFD_RELOC_SCORE_BRANCH:
6933 case BFD_RELOC_SCORE16_JMP:
6934 case BFD_RELOC_SCORE16_BRANCH:
6935 case BFD_RELOC_VTABLE_ENTRY:
6936 case BFD_RELOC_VTABLE_INHERIT:
6937 case BFD_RELOC_SCORE_GPREL15:
6938 case BFD_RELOC_SCORE_GOT15:
6939 case BFD_RELOC_SCORE_DUMMY_HI16:
6940 case BFD_RELOC_SCORE_GOT_LO16:
6941 case BFD_RELOC_SCORE_CALL15:
6942 case BFD_RELOC_GPREL32:
6943 case BFD_RELOC_NONE:
6944 code = fixp->fx_r_type;
6945 break;
6946 default:
6947 type = _("<unknown>");
6948 as_bad_where (fixp->fx_file, fixp->fx_line,
6949 _("cannot represent %s relocation in this object file format"), type);
6950 return NULL;
6953 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6954 if (reloc->howto == NULL)
6956 as_bad_where (fixp->fx_file, fixp->fx_line,
6957 _("cannot represent %s relocation in this object file format1"),
6958 bfd_get_reloc_code_name (code));
6959 return NULL;
6961 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6962 vtable entry to be used in the relocation's section offset. */
6963 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6964 reloc->address = fixp->fx_offset;
6966 return retval;