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