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