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