1214571Sdim/* tc-score.c -- Assembler for Score
2214571Sdim   Copyright 2006 Free Software Foundation, Inc.
3214571Sdim   Contributed by:
4214571Sdim   Mei Ligang (ligang@sunnorth.com.cn)
5214571Sdim   Pei-Lin Tsai (pltsai@sunplus.com)
6214571Sdim
7214571Sdim   This file is part of GAS, the GNU Assembler.
8214571Sdim
9214571Sdim   GAS is free software; you can redistribute it and/or modify
10214571Sdim   it under the terms of the GNU General Public License as published by
11214571Sdim   the Free Software Foundation; either version 2, or (at your option)
12214571Sdim   any later version.
13214571Sdim
14214571Sdim   GAS is distributed in the hope that it will be useful,
15214571Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
16214571Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17214571Sdim   GNU General Public License for more details.
18214571Sdim
19214571Sdim   You should have received a copy of the GNU General Public License
20214571Sdim   along with GAS; see the file COPYING.  If not, write to the Free
21214571Sdim   Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22214571Sdim   02110-1301, USA.  */
23214571Sdim
24214571Sdim#include "as.h"
25214571Sdim#include "config.h"
26214571Sdim#include "subsegs.h"
27214571Sdim#include "safe-ctype.h"
28214571Sdim#include "opcode/score-inst.h"
29214571Sdim#include "opcode/score-datadep.h"
30214571Sdim#include "struc-symbol.h"
31214571Sdim
32214571Sdim#ifdef OBJ_ELF
33214571Sdim#include "elf/score.h"
34214571Sdim#include "dwarf2dbg.h"
35214571Sdim#endif
36214571Sdim
37214571Sdim#define GP                     28
38214571Sdim#define PIC_CALL_REG           29
39214571Sdim#define MAX_LITERAL_POOL_SIZE  1024
40214571Sdim#define FAIL	               0x80000000
41214571Sdim#define SUCCESS         0
42214571Sdim#define INSN_SIZE       4
43214571Sdim#define INSN16_SIZE     2
44214571Sdim#define RELAX_INST_NUM  3
45214571Sdim
46214571Sdim/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message.  */
47214571Sdim#define BAD_ARGS 	          _("bad arguments to instruction")
48214571Sdim#define BAD_PC 		          _("r15 not allowed here")
49214571Sdim#define BAD_COND 	          _("instruction is not conditional")
50214571Sdim#define ERR_NO_ACCUM	          _("acc0 expected")
51214571Sdim#define ERR_FOR_SCORE5U_MUL_DIV   _("div / mul are reserved instructions")
52214571Sdim#define ERR_FOR_SCORE5U_MMU       _("This architecture doesn't support mmu")
53214571Sdim#define ERR_FOR_SCORE5U_ATOMIC    _("This architecture doesn't support atomic instruction")
54214571Sdim#define LONG_LABEL_LEN            _("the label length is longer than 1024");
55214571Sdim#define BAD_SKIP_COMMA            BAD_ARGS
56214571Sdim#define BAD_GARBAGE               _("garbage following instruction");
57214571Sdim
58214571Sdim#define skip_whitespace(str)  while (*(str) == ' ') ++(str)
59214571Sdim
60214571Sdim/* The name of the readonly data section.  */
61214571Sdim#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
62214571Sdim			    ? ".data" \
63214571Sdim			    : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
64214571Sdim			    ? ".rdata" \
65214571Sdim			    : OUTPUT_FLAVOR == bfd_target_coff_flavour \
66214571Sdim			    ? ".rdata" \
67214571Sdim			    : OUTPUT_FLAVOR == bfd_target_elf_flavour \
68214571Sdim			    ? ".rodata" \
69214571Sdim			    : (abort (), ""))
70214571Sdim
71214571Sdim#define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
72214571Sdim  ((relax_substateT) \
73214571Sdim   (((old) << 23) \
74214571Sdim    | ((new) << 16) \
75214571Sdim    | ((type) << 9) \
76214571Sdim    | ((reloc1) << 5) \
77214571Sdim    | ((reloc2) << 1) \
78214571Sdim    | ((opt) ? 1 : 0)))
79214571Sdim
80214571Sdim#define RELAX_OLD(i)       (((i) >> 23) & 0x7f)
81214571Sdim#define RELAX_NEW(i)       (((i) >> 16) & 0x7f)
82214571Sdim#define RELAX_TYPE(i)      (((i) >> 9) & 0x7f)
83214571Sdim#define RELAX_RELOC1(i)    ((valueT) ((i) >> 5) & 0xf)
84214571Sdim#define RELAX_RELOC2(i)    ((valueT) ((i) >> 1) & 0xf)
85214571Sdim#define RELAX_OPT(i)       ((i) & 1)
86214571Sdim#define RELAX_OPT_CLEAR(i) ((i) & ~1)
87214571Sdim
88214571Sdim#define SET_INSN_ERROR(s) (inst.error = (s))
89214571Sdim#define INSN_IS_PCE_P(s)  (strstr (str, "||") != NULL)
90214571Sdim
91214571Sdim#define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
92214571Sdim
93214571Sdim#define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
94214571Sdim                             ? INSN16_SIZE : INSN_SIZE)
95214571Sdim
96214571Sdim/* This array holds the chars that always start a comment.  If the
97214571Sdim   pre-processor is disabled, these aren't very useful.  */
98214571Sdimconst char comment_chars[] = "#";
99214571Sdimconst char line_comment_chars[] = "#";
100214571Sdimconst char line_separator_chars[] = ";";
101214571Sdim
102214571Sdim/* Chars that can be used to separate mant from exp in floating point numbers.  */
103214571Sdimconst char EXP_CHARS[] = "eE";
104214571Sdimconst char FLT_CHARS[] = "rRsSfFdDxXeEpP";
105214571Sdim
106214571Sdim/* Used to contain constructed error messages.  */
107214571Sdimstatic char err_msg[255];
108214571Sdim
109214571SdimfragS *score_fragp = 0;
110214571Sdimstatic int fix_data_dependency = 0;
111214571Sdimstatic int warn_fix_data_dependency = 1;
112214571Sdimstatic int score7 = 1;
113214571Sdimstatic int university_version = 0;
114214571Sdim
115214571Sdimstatic int in_my_get_expression = 0;
116214571Sdim
117214571Sdim#define USE_GLOBAL_POINTER_OPT 1
118214571Sdim#define SCORE_BI_ENDIAN
119214571Sdim
120214571Sdim/* Default, pop warning message when using r1.  */
121214571Sdimstatic int nor1 = 1;
122214571Sdim
123214571Sdim/* Default will do instruction relax, -O0 will set g_opt = 0.  */
124214571Sdimstatic unsigned int g_opt = 1;
125214571Sdim
126214571Sdim/* The size of the small data section.  */
127214571Sdimstatic unsigned int g_switch_value = 8;
128214571Sdim
129214571Sdim#ifdef OBJ_ELF
130214571Sdim/* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
131214571SdimsymbolS *GOT_symbol;
132214571Sdim#endif
133214571Sdimstatic segT pdr_seg;
134214571Sdim
135214571Sdimenum score_pic_level score_pic = NO_PIC;
136214571Sdim
137214571Sdim#define INSN_NAME_LEN 16
138214571Sdimstruct score_it
139214571Sdim{
140214571Sdim  char name[INSN_NAME_LEN];
141214571Sdim  unsigned long instruction;
142214571Sdim  unsigned long relax_inst;
143214571Sdim  int size;
144214571Sdim  int relax_size;
145214571Sdim  enum score_insn_type type;
146214571Sdim  char str[MAX_LITERAL_POOL_SIZE];
147214571Sdim  const char *error;
148214571Sdim  int bwarn;
149214571Sdim  char reg[INSN_NAME_LEN];
150214571Sdim  struct
151214571Sdim  {
152214571Sdim    bfd_reloc_code_real_type type;
153214571Sdim    expressionS exp;
154214571Sdim    int pc_rel;
155214571Sdim  }reloc;
156214571Sdim};
157214571Sdimstruct score_it inst;
158214571Sdim
159214571Sdimtypedef struct proc
160214571Sdim{
161214571Sdim  symbolS *isym;
162214571Sdim  unsigned long reg_mask;
163214571Sdim  unsigned long reg_offset;
164214571Sdim  unsigned long fpreg_mask;
165214571Sdim  unsigned long leaf;
166214571Sdim  unsigned long frame_offset;
167214571Sdim  unsigned long frame_reg;
168214571Sdim  unsigned long pc_reg;
169214571Sdim}
170214571SdimprocS;
171214571Sdim
172214571Sdimstatic procS cur_proc;
173214571Sdimstatic procS *cur_proc_ptr;
174214571Sdimstatic int numprocs;
175214571Sdim
176214571Sdim#define SCORE7_PIPELINE 7
177214571Sdim#define SCORE5_PIPELINE 5
178214571Sdimstatic int vector_size = SCORE7_PIPELINE;
179214571Sdimstruct score_it dependency_vector[SCORE7_PIPELINE];
180214571Sdim
181214571Sdim/* Relax will need some padding for alignment.  */
182214571Sdim#define RELAX_PAD_BYTE 3
183214571Sdim
184214571Sdim/* Number of littlenums required to hold an extended precision number.  For md_atof.  */
185214571Sdim#define NUM_FLOAT_VALS 8
186214571Sdim#define MAX_LITTLENUMS 6
187214571SdimLITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
188214571Sdim
189214571Sdim/* Structure for a hash table entry for a register.  */
190214571Sdimstruct reg_entry
191214571Sdim{
192214571Sdim  const char *name;
193214571Sdim  int number;
194214571Sdim};
195214571Sdim
196214571Sdimstatic const struct reg_entry score_rn_table[] =
197214571Sdim{
198214571Sdim  {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
199214571Sdim  {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
200214571Sdim  {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
201214571Sdim  {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
202214571Sdim  {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
203214571Sdim  {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
204214571Sdim  {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
205214571Sdim  {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
206214571Sdim  {NULL, 0}
207214571Sdim};
208214571Sdim
209214571Sdimstatic const struct reg_entry score_srn_table[] =
210214571Sdim{
211214571Sdim  {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
212214571Sdim  {NULL, 0}
213214571Sdim};
214214571Sdim
215214571Sdimstatic const struct reg_entry score_crn_table[] =
216214571Sdim{
217214571Sdim  {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
218214571Sdim  {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
219214571Sdim  {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
220214571Sdim  {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
221214571Sdim  {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
222214571Sdim  {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
223214571Sdim  {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
224214571Sdim  {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
225214571Sdim  {NULL, 0}
226214571Sdim};
227214571Sdim
228214571Sdimstruct reg_map
229214571Sdim{
230214571Sdim  const struct reg_entry *names;
231214571Sdim  int max_regno;
232214571Sdim  struct hash_control *htab;
233214571Sdim  const char *expected;
234214571Sdim};
235214571Sdim
236214571Sdimstruct reg_map all_reg_maps[] =
237214571Sdim{
238214571Sdim  {score_rn_table, 31, NULL, N_("S+core register expected")},
239214571Sdim  {score_srn_table, 2, NULL, N_("S+core special-register expected")},
240214571Sdim  {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
241214571Sdim};
242214571Sdim
243214571Sdimstatic struct hash_control *score_ops_hsh = NULL;
244214571Sdim
245214571Sdimstatic struct hash_control *dependency_insn_hsh = NULL;
246214571Sdim
247214571Sdim/* Enumeration matching entries in table above.  */
248214571Sdimenum score_reg_type
249214571Sdim{
250214571Sdim  REG_TYPE_SCORE = 0,
251214571Sdim#define REG_TYPE_FIRST REG_TYPE_SCORE
252214571Sdim  REG_TYPE_SCORE_SR = 1,
253214571Sdim  REG_TYPE_SCORE_CR = 2,
254214571Sdim  REG_TYPE_MAX = 3
255214571Sdim};
256214571Sdim
257214571Sdimtypedef struct literalS
258214571Sdim{
259214571Sdim  struct expressionS exp;
260214571Sdim  struct score_it *inst;
261214571Sdim}
262214571SdimliteralT;
263214571Sdim
264214571SdimliteralT literals[MAX_LITERAL_POOL_SIZE];
265214571Sdim
266214571Sdimstatic void do_ldst_insn (char *);
267214571Sdimstatic void do_crdcrscrsimm5 (char *);
268214571Sdimstatic void do_ldst_unalign (char *);
269214571Sdimstatic void do_ldst_atomic (char *);
270214571Sdimstatic void do_ldst_cop (char *);
271214571Sdimstatic void do_macro_li_rdi32 (char *);
272214571Sdimstatic void do_macro_la_rdi32 (char *);
273214571Sdimstatic void do_macro_rdi32hi (char *);
274214571Sdimstatic void do_macro_rdi32lo (char *);
275214571Sdimstatic void do_macro_mul_rdrsrs (char *);
276214571Sdimstatic void do_macro_ldst_label (char *);
277214571Sdimstatic void do_branch (char *);
278214571Sdimstatic void do_jump (char *);
279214571Sdimstatic void do_empty (char *);
280214571Sdimstatic void do_rdrsrs (char *);
281214571Sdimstatic void do_rdsi16 (char *);
282214571Sdimstatic void do_rdrssi14 (char *);
283214571Sdimstatic void do_sub_rdsi16 (char *);
284214571Sdimstatic void do_sub_rdrssi14 (char *);
285214571Sdimstatic void do_rdrsi5 (char *);
286214571Sdimstatic void do_rdrsi14 (char *);
287214571Sdimstatic void do_rdi16 (char *);
288214571Sdimstatic void do_xrsi5 (char *);
289214571Sdimstatic void do_rdrs (char *);
290214571Sdimstatic void do_rdxrs (char *);
291214571Sdimstatic void do_rsrs (char *);
292214571Sdimstatic void do_rdcrs (char *);
293214571Sdimstatic void do_rdsrs (char *);
294214571Sdimstatic void do_rd (char *);
295214571Sdimstatic void do_rs (char *);
296214571Sdimstatic void do_i15 (char *);
297214571Sdimstatic void do_xi5x (char *);
298214571Sdimstatic void do_ceinst (char *);
299214571Sdimstatic void do_cache (char *);
300214571Sdimstatic void do16_rdrs (char *);
301214571Sdimstatic void do16_rs (char *);
302214571Sdimstatic void do16_xrs (char *);
303214571Sdimstatic void do16_mv_rdrs (char *);
304214571Sdimstatic void do16_hrdrs (char *);
305214571Sdimstatic void do16_rdhrs (char *);
306214571Sdimstatic void do16_rdi4 (char *);
307214571Sdimstatic void do16_rdi5 (char *);
308214571Sdimstatic void do16_xi5 (char *);
309214571Sdimstatic void do16_ldst_insn (char *);
310214571Sdimstatic void do16_ldst_imm_insn (char *);
311214571Sdimstatic void do16_push_pop (char *);
312214571Sdimstatic void do16_branch (char *);
313214571Sdimstatic void do16_jump (char *);
314214571Sdimstatic void do_rdi16_pic (char *);
315214571Sdimstatic void do_addi_s_pic (char *);
316214571Sdimstatic void do_addi_u_pic (char *);
317214571Sdimstatic void do_lw_pic (char *);
318214571Sdim
319214571Sdimstatic const struct asm_opcode score_ldst_insns[] =
320214571Sdim{
321214571Sdim  {"lw",        0x20000000, 0x3e000000, 0x2008,     Rd_rvalueRs_SI15,     do_ldst_insn},
322214571Sdim  {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
323214571Sdim  {"lw",        0x0e000000, 0x3e000007, 0x200a,     Rd_rvalueRs_postSI12, do_ldst_insn},
324214571Sdim  {"lh",        0x22000000, 0x3e000000, 0x2009,     Rd_rvalueRs_SI15,     do_ldst_insn},
325214571Sdim  {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
326214571Sdim  {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
327214571Sdim  {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
328214571Sdim  {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
329214571Sdim  {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
330214571Sdim  {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
331214571Sdim  {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
332214571Sdim  {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
333214571Sdim  {"sw",        0x28000000, 0x3e000000, 0x200c,     Rd_lvalueRs_SI15,     do_ldst_insn},
334214571Sdim  {"sw",        0x06000004, 0x3e000007, 0x200e,     Rd_lvalueRs_preSI12,  do_ldst_insn},
335214571Sdim  {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
336214571Sdim  {"sh",        0x2a000000, 0x3e000000, 0x200d,     Rd_lvalueRs_SI15,     do_ldst_insn},
337214571Sdim  {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
338214571Sdim  {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
339214571Sdim  {"lbu",       0x2c000000, 0x3e000000, 0x200b,     Rd_rvalueRs_SI15,     do_ldst_insn},
340214571Sdim  {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
341214571Sdim  {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
342214571Sdim  {"sb",        0x2e000000, 0x3e000000, 0x200f,     Rd_lvalueRs_SI15,     do_ldst_insn},
343214571Sdim  {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
344214571Sdim  {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
345214571Sdim};
346214571Sdim
347214571Sdimstatic const struct asm_opcode score_insns[] =
348214571Sdim{
349214571Sdim  {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
350214571Sdim  {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
351214571Sdim  {"add",       0x00000010, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
352214571Sdim  {"add.c",     0x00000011, 0x3e0003ff, 0x2000,     Rd_Rs_Rs,             do_rdrsrs},
353214571Sdim  {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
354214571Sdim  {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
355214571Sdim  {"addc.c",    0x00000013, 0x3e0003ff, 0x0009,     Rd_Rs_Rs,             do_rdrsrs},
356214571Sdim  {"addi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
357214571Sdim  {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
358214571Sdim  {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
359214571Sdim  {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
360214571Sdim  {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
361214571Sdim  {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
362214571Sdim  {"addc!",     0x0009,     0x700f,     0x00000013, Rd_Rs,                do16_rdrs},
363214571Sdim  {"add!",      0x2000,     0x700f,     0x00000011, Rd_Rs,                do16_rdrs},
364214571Sdim  {"addei!",    0x6000    , 0x7087,     0x02000001, Rd_I4,                do16_rdi4},
365214571Sdim  {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
366214571Sdim  {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
367214571Sdim  {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
368214571Sdim  {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
369214571Sdim  {"and",       0x00000020, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
370214571Sdim  {"and.c",     0x00000021, 0x3e0003ff, 0x2004,     Rd_Rs_Rs,             do_rdrsrs},
371214571Sdim  {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
372214571Sdim  {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
373214571Sdim  {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
374214571Sdim  {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
375214571Sdim  {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
376214571Sdim  {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
377214571Sdim  {"and!",      0x2004,     0x700f,     0x00000021, Rd_Rs,                do16_rdrs},
378214571Sdim  {"bcs",       0x08000000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
379214571Sdim  {"bcc",       0x08000400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
380214571Sdim  {"bcnz",      0x08003800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
381214571Sdim  {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
382214571Sdim  {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
383214571Sdim  {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
384214571Sdim  {"bcs!",      0x4000,     0x7f00,     0x08000000, PC_DISP8div2,         do16_branch},
385214571Sdim  {"bcc!",      0x4100,     0x7f00,     0x08000400, PC_DISP8div2,         do16_branch},
386214571Sdim  {"bcnz!",     0x4e00,     0x7f00,     0x08003800, PC_DISP8div2,         do16_branch},
387214571Sdim  {"beq",       0x08001000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
388214571Sdim  {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
389214571Sdim  {"beq!",      0x4400,     0x7f00,     0x08001000, PC_DISP8div2,         do16_branch},
390214571Sdim  {"bgtu",      0x08000800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
391214571Sdim  {"bgt",       0x08001800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
392214571Sdim  {"bge",       0x08002000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
393214571Sdim  {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
394214571Sdim  {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
395214571Sdim  {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
396214571Sdim  {"bgtu!",     0x4200,     0x7f00,     0x08000800, PC_DISP8div2,         do16_branch},
397214571Sdim  {"bgt!",      0x4600,     0x7f00,     0x08001800, PC_DISP8div2,         do16_branch},
398214571Sdim  {"bge!",      0x4800,     0x7f00,     0x08002000, PC_DISP8div2,         do16_branch},
399214571Sdim  {"bitclr.c",  0x00000029, 0x3e0003ff, 0x6004,     Rd_Rs_I5,             do_rdrsi5},
400214571Sdim  {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
401214571Sdim  {"bitset.c",  0x0000002b, 0x3e0003ff, 0x6005,     Rd_Rs_I5,             do_rdrsi5},
402214571Sdim  {"bittst.c",  0x0000002d, 0x3e0003ff, 0x6006,     x_Rs_I5,              do_xrsi5},
403214571Sdim  {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x6007,     Rd_Rs_I5,             do_rdrsi5},
404214571Sdim  {"bitclr!",   0x6004,     0x7007,     0x00000029, Rd_I5,                do16_rdi5},
405214571Sdim  {"bitset!",   0x6005,     0x7007,     0x0000002b, Rd_I5,                do16_rdi5},
406214571Sdim  {"bittst!",   0x6006,     0x7007,     0x0000002d, Rd_I5,                do16_rdi5},
407214571Sdim  {"bittgl!",   0x6007,     0x7007,     0x0000002f, Rd_I5,                do16_rdi5},
408214571Sdim  {"bleu",      0x08000c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
409214571Sdim  {"ble",       0x08001c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
410214571Sdim  {"blt",       0x08002400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
411214571Sdim  {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
412214571Sdim  {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
413214571Sdim  {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
414214571Sdim  {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
415214571Sdim  {"bleu!",     0x4300,     0x7f00,     0x08000c00, PC_DISP8div2,         do16_branch},
416214571Sdim  {"ble!",      0x4700,     0x7f00,     0x08001c00, PC_DISP8div2,         do16_branch},
417214571Sdim  {"blt!",      0x4900,     0x7f00,     0x08002400, PC_DISP8div2,         do16_branch},
418214571Sdim  {"bmi",       0x08002800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
419214571Sdim  {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
420214571Sdim  {"bmi!",      0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2,         do16_branch},
421214571Sdim  {"bne",       0x08001400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
422214571Sdim  {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
423214571Sdim  {"bne!",      0x4500,     0x7f00,     0x08001400, PC_DISP8div2,         do16_branch},
424214571Sdim  {"bpl",       0x08002c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
425214571Sdim  {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
426214571Sdim  {"bpl!",      0x4b00,     0x7f00,     0x08002c00, PC_DISP8div2,         do16_branch},
427214571Sdim  {"brcs",      0x00000008, 0x3e007fff, 0x0004,     x_Rs_x,               do_rs},
428214571Sdim  {"brcc",      0x00000408, 0x3e007fff, 0x0104,     x_Rs_x,               do_rs},
429214571Sdim  {"brgtu",     0x00000808, 0x3e007fff, 0x0204,     x_Rs_x,               do_rs},
430214571Sdim  {"brleu",     0x00000c08, 0x3e007fff, 0x0304,     x_Rs_x,               do_rs},
431214571Sdim  {"breq",      0x00001008, 0x3e007fff, 0x0404,     x_Rs_x,               do_rs},
432214571Sdim  {"brne",      0x00001408, 0x3e007fff, 0x0504,     x_Rs_x,               do_rs},
433214571Sdim  {"brgt",      0x00001808, 0x3e007fff, 0x0604,     x_Rs_x,               do_rs},
434214571Sdim  {"brle",      0x00001c08, 0x3e007fff, 0x0704,     x_Rs_x,               do_rs},
435214571Sdim  {"brge",      0x00002008, 0x3e007fff, 0x0804,     x_Rs_x,               do_rs},
436214571Sdim  {"brlt",      0x00002408, 0x3e007fff, 0x0904,     x_Rs_x,               do_rs},
437214571Sdim  {"brmi",      0x00002808, 0x3e007fff, 0x0a04,     x_Rs_x,               do_rs},
438214571Sdim  {"brpl",      0x00002c08, 0x3e007fff, 0x0b04,     x_Rs_x,               do_rs},
439214571Sdim  {"brvs",      0x00003008, 0x3e007fff, 0x0c04,     x_Rs_x,               do_rs},
440214571Sdim  {"brvc",      0x00003408, 0x3e007fff, 0x0d04,     x_Rs_x,               do_rs},
441214571Sdim  {"brcnz",     0x00003808, 0x3e007fff, 0x0e04,     x_Rs_x,               do_rs},
442214571Sdim  {"br",        0x00003c08, 0x3e007fff, 0x0f04,     x_Rs_x,               do_rs},
443214571Sdim  {"brcsl",     0x00000009, 0x3e007fff, 0x000c,     x_Rs_x,               do_rs},
444214571Sdim  {"brccl",     0x00000409, 0x3e007fff, 0x010c,     x_Rs_x,               do_rs},
445214571Sdim  {"brgtul",    0x00000809, 0x3e007fff, 0x020c,     x_Rs_x,               do_rs},
446214571Sdim  {"brleul",    0x00000c09, 0x3e007fff, 0x030c,     x_Rs_x,               do_rs},
447214571Sdim  {"breql",     0x00001009, 0x3e007fff, 0x040c,     x_Rs_x,               do_rs},
448214571Sdim  {"brnel",     0x00001409, 0x3e007fff, 0x050c,     x_Rs_x,               do_rs},
449214571Sdim  {"brgtl",     0x00001809, 0x3e007fff, 0x060c,     x_Rs_x,               do_rs},
450214571Sdim  {"brlel",     0x00001c09, 0x3e007fff, 0x070c,     x_Rs_x,               do_rs},
451214571Sdim  {"brgel",     0x00002009, 0x3e007fff, 0x080c,     x_Rs_x,               do_rs},
452214571Sdim  {"brltl",     0x00002409, 0x3e007fff, 0x090c,     x_Rs_x,               do_rs},
453214571Sdim  {"brmil",     0x00002809, 0x3e007fff, 0x0a0c,     x_Rs_x,               do_rs},
454214571Sdim  {"brpll",     0x00002c09, 0x3e007fff, 0x0b0c,     x_Rs_x,               do_rs},
455214571Sdim  {"brvsl",     0x00003009, 0x3e007fff, 0x0c0c,     x_Rs_x,               do_rs},
456214571Sdim  {"brvcl",     0x00003409, 0x3e007fff, 0x0d0c,     x_Rs_x,               do_rs},
457214571Sdim  {"brcnzl",    0x00003809, 0x3e007fff, 0x0e0c,     x_Rs_x,               do_rs},
458214571Sdim  {"brl",       0x00003c09, 0x3e007fff, 0x0f0c,     x_Rs_x,               do_rs},
459214571Sdim  {"brcs!",     0x0004,     0x7f0f,     0x00000008, x_Rs,                 do16_xrs},
460214571Sdim  {"brcc!",     0x0104,     0x7f0f,     0x00000408, x_Rs,                 do16_xrs},
461214571Sdim  {"brgtu!",    0x0204,     0x7f0f,     0x00000808, x_Rs,                 do16_xrs},
462214571Sdim  {"brleu!",    0x0304,     0x7f0f,     0x00000c08, x_Rs,                 do16_xrs},
463214571Sdim  {"breq!",     0x0404,     0x7f0f,     0x00001008, x_Rs,                 do16_xrs},
464214571Sdim  {"brne!",     0x0504,     0x7f0f,     0x00001408, x_Rs,                 do16_xrs},
465214571Sdim  {"brgt!",     0x0604,     0x7f0f,     0x00001808, x_Rs,                 do16_xrs},
466214571Sdim  {"brle!",     0x0704,     0x7f0f,     0x00001c08, x_Rs,                 do16_xrs},
467214571Sdim  {"brge!",     0x0804,     0x7f0f,     0x00002008, x_Rs,                 do16_xrs},
468214571Sdim  {"brlt!",     0x0904,     0x7f0f,     0x00002408, x_Rs,                 do16_xrs},
469214571Sdim  {"brmi!",     0x0a04,     0x7f0f,     0x00002808, x_Rs,                 do16_xrs},
470214571Sdim  {"brpl!",     0x0b04,     0x7f0f,     0x00002c08, x_Rs,                 do16_xrs},
471214571Sdim  {"brvs!",     0x0c04,     0x7f0f,     0x00003008, x_Rs,                 do16_xrs},
472214571Sdim  {"brvc!",     0x0d04,     0x7f0f,     0x00003408, x_Rs,                 do16_xrs},
473214571Sdim  {"brcnz!",    0x0e04,     0x7f0f,     0x00003808, x_Rs,                 do16_xrs},
474214571Sdim  {"br!",       0x0f04,     0x7f0f,     0x00003c08, x_Rs,                 do16_xrs},
475214571Sdim  {"brcsl!",    0x000c,     0x7f0f,     0x00000009, x_Rs,                 do16_xrs},
476214571Sdim  {"brccl!",    0x010c,     0x7f0f,     0x00000409, x_Rs,                 do16_xrs},
477214571Sdim  {"brgtul!",   0x020c,     0x7f0f,     0x00000809, x_Rs,                 do16_xrs},
478214571Sdim  {"brleul!",   0x030c,     0x7f0f,     0x00000c09, x_Rs,                 do16_xrs},
479214571Sdim  {"breql!",    0x040c,     0x7f0f,     0x00001009, x_Rs,                 do16_xrs},
480214571Sdim  {"brnel!",    0x050c,     0x7f0f,     0x00001409, x_Rs,                 do16_xrs},
481214571Sdim  {"brgtl!",    0x060c,     0x7f0f,     0x00001809, x_Rs,                 do16_xrs},
482214571Sdim  {"brlel!",    0x070c,     0x7f0f,     0x00001c09, x_Rs,                 do16_xrs},
483214571Sdim  {"brgel!",    0x080c,     0x7f0f,     0x00002009, x_Rs,                 do16_xrs},
484214571Sdim  {"brltl!",    0x090c,     0x7f0f,     0x00002409, x_Rs,                 do16_xrs},
485214571Sdim  {"brmil!",    0x0a0c,     0x7f0f,     0x00002809, x_Rs,                 do16_xrs},
486214571Sdim  {"brpll!",    0x0b0c,     0x7f0f,     0x00002c09, x_Rs,                 do16_xrs},
487214571Sdim  {"brvsl!",    0x0c0c,     0x7f0f,     0x00003009, x_Rs,                 do16_xrs},
488214571Sdim  {"brvcl!",    0x0d0c,     0x7f0f,     0x00003409, x_Rs,                 do16_xrs},
489214571Sdim  {"brcnzl!",   0x0e0c,     0x7f0f,     0x00003809, x_Rs,                 do16_xrs},
490214571Sdim  {"brl!",      0x0f0c,     0x7f0f,     0x00003c09, x_Rs,                 do16_xrs},
491214571Sdim  {"bvs",       0x08003000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
492214571Sdim  {"bvc",       0x08003400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
493214571Sdim  {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
494214571Sdim  {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
495214571Sdim  {"bvs!",      0x4c00,     0x7f00,     0x08003000, PC_DISP8div2,         do16_branch},
496214571Sdim  {"bvc!",      0x4d00,     0x7f00,     0x08003400, PC_DISP8div2,         do16_branch},
497214571Sdim  {"b!",        0x4f00,     0x7f00,     0x08003c00, PC_DISP8div2,         do16_branch},
498214571Sdim  {"b",         0x08003c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
499214571Sdim  {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    do_cache},
500214571Sdim  {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      do_ceinst},
501214571Sdim  {"clz",       0x3800000d, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
502214571Sdim  {"cmpteq.c",  0x00000019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
503214571Sdim  {"cmptmi.c",  0x00100019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
504214571Sdim  {"cmp.c",     0x00300019, 0x3ff003ff, 0x2003,     x_Rs_Rs,              do_rsrs},
505214571Sdim  {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
506214571Sdim  {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
507214571Sdim  {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
508214571Sdim  {"cmpi.c",    0x02040001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
509214571Sdim  {"cmp!",      0x2003,     0x700f,     0x00300019, Rd_Rs,                do16_rdrs},
510214571Sdim  {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
511214571Sdim  {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
512214571Sdim  {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
513214571Sdim  {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
514214571Sdim  {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
515214571Sdim  {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
516214571Sdim  {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
517214571Sdim  {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
518214571Sdim  {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
519214571Sdim  {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
520214571Sdim  {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
521214571Sdim  {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
522214571Sdim  {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
523214571Sdim  {"jl!",       0x3001,     0x7001,     0x04000001, PC_DISP11div2,        do16_jump},
524214571Sdim  {"j!",        0x3000,     0x7001,     0x04000000, PC_DISP11div2,        do16_jump},
525214571Sdim  {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
526214571Sdim  {"lbu!",      0x200b,     0x0000700f, 0x2c000000, Rd_rvalueRs,          do16_ldst_insn},
527214571Sdim  {"lbup!",     0x7003,     0x7007,     0x2c000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
528214571Sdim  {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        do_ldst_atomic},
529214571Sdim  {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     do_ldst_unalign},
530214571Sdim  {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
531214571Sdim  {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
532214571Sdim  {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
533214571Sdim  {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
534214571Sdim  {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
535214571Sdim  {"lh!",       0x2009,     0x700f,     0x22000000, Rd_rvalueRs,          do16_ldst_insn},
536214571Sdim  {"lhp!",      0x7001,     0x7007,     0x22000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
537214571Sdim  {"ldi",       0x020c0000, 0x3e0e0000, 0x5000,     Rd_SI16,              do_rdsi16},
538214571Sdim  {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               do_rdi16},
539214571Sdim  {"ldiu!",     0x5000,     0x7000,     0x020c0000, Rd_I8,                do16_ldst_imm_insn},
540214571Sdim  {"lw!",       0x2008,     0x700f,     0x20000000, Rd_rvalueRs,          do16_ldst_insn},
541214571Sdim  {"lwp!",      0x7000,     0x7007,     0x20000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
542214571Sdim  {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
543214571Sdim  {"mfcel!",    0x1001,     0x7f0f,     0x00000448, x_Rs,                 do16_rs},
544214571Sdim  {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
545214571Sdim  {"mad.f!",    0x1004,     0x700f,     0x38000080, Rd_Rs,                do16_rdrs},
546214571Sdim  {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
547214571Sdim  {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
548214571Sdim  {"madh.fs!",  0x100b,     0x700f,     0x380002c3, Rd_Rs,                do16_rdrs},
549214571Sdim  {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
550214571Sdim  {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
551214571Sdim  {"madl.fs!",  0x100a,     0x700f,     0x380000c2, Rd_Rs,                do16_rdrs},
552214571Sdim  {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
553214571Sdim  {"madu!",     0x1005,     0x700f,     0x38000020, Rd_Rs,                do16_rdrs},
554214571Sdim  {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
555214571Sdim  {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
556214571Sdim  {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
557214571Sdim  {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
558214571Sdim  {"mazh.f!",   0x1009,     0x700f,     0x3800038c, Rd_Rs,                do16_rdrs},
559214571Sdim  {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
560214571Sdim  {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
561214571Sdim  {"mazl.f!",   0x1008,     0x700f,     0x38000182, Rd_Rs,                do16_rdrs},
562214571Sdim  {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
563214571Sdim  {"mfceh!",    0x1101,     0x7f0f,     0x00000848, x_Rs,                 do16_rs},
564214571Sdim  {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
565214571Sdim  {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              do_rdsrs},
566214571Sdim  {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
567214571Sdim  {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
568214571Sdim  {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
569214571Sdim  {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
570214571Sdim  {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
571214571Sdim  {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
572214571Sdim  {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
573214571Sdim  {"mhfl!",     0x0002,     0x700f,     0x00003c56, Rd_LowRs,             do16_hrdrs},
574214571Sdim  {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
575214571Sdim  {"mlfh!",     0x0001,     0x700f,     0x00003c56, Rd_HighRs,            do16_rdhrs},
576214571Sdim  {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
577214571Sdim  {"msb.f!",    0x1006,     0x700f,     0x38000081, Rd_Rs,                do16_rdrs},
578214571Sdim  {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
579214571Sdim  {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
580214571Sdim  {"msbh.fs!",  0x100f,     0x700f,     0x380002c5, Rd_Rs,                do16_rdrs},
581214571Sdim  {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
582214571Sdim  {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
583214571Sdim  {"msbl.fs!",  0x100e,     0x700f,     0x380000c4, Rd_Rs,                do16_rdrs},
584214571Sdim  {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
585214571Sdim  {"msbu!",     0x1007,     0x700f,     0x38000021, Rd_Rs,                do16_rdrs},
586214571Sdim  {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
587214571Sdim  {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
588214571Sdim  {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
589214571Sdim  {"mszh.f!",   0x100d,     0x700f,     0x38000385, Rd_Rs,                do16_rdrs},
590214571Sdim  {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
591214571Sdim  {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
592214571Sdim  {"mszl.f!",   0x100c,     0x700f,     0x38000184, Rd_Rs,                do16_rdrs},
593214571Sdim  {"mtcel!",    0x1000,     0x7f0f,     0x0000044a, x_Rs,                 do16_rs},
594214571Sdim  {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
595214571Sdim  {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
596214571Sdim  {"mtceh!",    0x1100,     0x7f0f,     0x0000084a, x_Rs,                 do16_rs},
597214571Sdim  {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
598214571Sdim  {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              do_rdsrs},
599214571Sdim  {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
600214571Sdim  {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
601214571Sdim  {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
602214571Sdim  {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
603214571Sdim  {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
604214571Sdim  {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
605214571Sdim  {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
606214571Sdim  {"mul.f!",    0x1002,     0x700f,     0x00000041, Rd_Rs,                do16_rdrs},
607214571Sdim  {"mulu!",     0x1003,     0x700f,     0x00000042, Rd_Rs,                do16_rdrs},
608214571Sdim  {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
609214571Sdim  {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
610214571Sdim  {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
611214571Sdim  {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
612214571Sdim  {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
613214571Sdim  {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
614214571Sdim  {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
615214571Sdim  {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
616214571Sdim  {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
617214571Sdim  {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
618214571Sdim  {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
619214571Sdim  {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
620214571Sdim  {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
621214571Sdim  {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
622214571Sdim  {"mv",        0x00003c56, 0x3e007fff, 0x0003,     Rd_Rs_x,              do_rdrs},
623214571Sdim  {"mv!",       0x0003,     0x700f,     0x00003c56, Rd_Rs,                do16_mv_rdrs},
624214571Sdim  {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              do_rdxrs},
625214571Sdim  {"neg.c",     0x0000001f, 0x3e0003ff, 0x2002,     Rd_x_Rs,              do_rdxrs},
626214571Sdim  {"neg!",      0x2002,     0x700f,     0x0000001f, Rd_Rs,                do16_rdrs},
627214571Sdim  {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               do_empty},
628214571Sdim  {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
629214571Sdim  {"not.c",     0x00000025, 0x3e0003ff, 0x2006,     Rd_Rs_x,              do_rdrs},
630214571Sdim  {"nop!",      0x0000,     0x700f,     0x00000000, NO16_OPD,               do_empty},
631214571Sdim  {"not!",      0x2006,     0x700f,     0x00000025, Rd_Rs,                do16_rdrs},
632214571Sdim  {"or",        0x00000022, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
633214571Sdim  {"or.c",      0x00000023, 0x3e0003ff, 0x2005,     Rd_Rs_Rs,             do_rdrsrs},
634214571Sdim  {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
635214571Sdim  {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
636214571Sdim  {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
637214571Sdim  {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
638214571Sdim  {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
639214571Sdim  {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
640214571Sdim  {"or!",       0x2005,     0x700f,     0x00000023, Rd_Rs,                do16_rdrs},
641214571Sdim  {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
642214571Sdim  {"pop!",      0x200a,     0x700f,     0x0e000000, Rd_rvalueRs,          do16_push_pop},
643214571Sdim  {"push!",     0x200e,     0x700f,     0x06000004, Rd_lvalueRs,          do16_push_pop},
644214571Sdim  {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
645214571Sdim  {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
646214571Sdim  {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
647214571Sdim  {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
648214571Sdim  {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
649214571Sdim  {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
650214571Sdim  {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
651214571Sdim  {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
652214571Sdim  {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
653214571Sdim  {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
654214571Sdim  {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
655214571Sdim  {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
656214571Sdim  {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
657214571Sdim  {"sb!",       0x200f,     0x700f,     0x2e000000, Rd_lvalueRs,          do16_ldst_insn},
658214571Sdim  {"sbp!",      0x7007,     0x7007,     0x2e000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
659214571Sdim  {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        do_ldst_atomic},
660214571Sdim  {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
661214571Sdim  {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
662214571Sdim  {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     do_ldst_unalign},
663214571Sdim  {"sdbbp",     0x00000006, 0x3e0003ff, 0x6002,     x_I5_x,               do_xi5x},
664214571Sdim  {"sdbbp!",    0x6002,     0x7007,     0x00000006, Rd_I5,                do16_xi5},
665214571Sdim  {"sh!",       0x200d,     0x700f,     0x2a000000, Rd_lvalueRs,          do16_ldst_insn},
666214571Sdim  {"shp!",      0x7005,     0x7007,     0x2a000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
667214571Sdim  {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
668214571Sdim  {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
669214571Sdim  {"sll.c",     0x00000031, 0x3e0003ff, 0x0008,     Rd_Rs_Rs,             do_rdrsrs},
670214571Sdim  {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
671214571Sdim  {"slli",      0x00000070, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
672214571Sdim  {"slli.c",    0x00000071, 0x3e0003ff, 0x6001,     Rd_Rs_I5,             do_rdrsi5},
673214571Sdim  {"sll!",      0x0008,     0x700f,     0x00000031, Rd_Rs,                do16_rdrs},
674214571Sdim  {"slli!",     0x6001,     0x7007,     0x00000071, Rd_I5,                do16_rdi5},
675214571Sdim  {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
676214571Sdim  {"srl.c",     0x00000035, 0x3e0003ff, 0x000a,     Rd_Rs_Rs,             do_rdrsrs},
677214571Sdim  {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
678214571Sdim  {"sra.c",     0x00000037, 0x3e0003ff, 0x000b,     Rd_Rs_Rs,             do_rdrsrs},
679214571Sdim  {"srli",      0x00000074, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
680214571Sdim  {"srli.c",    0x00000075, 0x3e0003ff, 0x6003,     Rd_Rs_I5,             do_rdrsi5},
681214571Sdim  {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
682214571Sdim  {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
683214571Sdim  {"srl!",      0x000a,     0x700f,     0x00000035, Rd_Rs,                do16_rdrs},
684214571Sdim  {"sra!",      0x000b,     0x700f,     0x00000037, Rd_Rs,                do16_rdrs},
685214571Sdim  {"srli!",     0x6003,     0x7007,     0x00000075, Rd_Rs,                do16_rdi5},
686214571Sdim  {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
687214571Sdim  {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
688214571Sdim  {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
689214571Sdim  {"sub",       0x00000014, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
690214571Sdim  {"sub.c",     0x00000015, 0x3e0003ff, 0x2001,     Rd_Rs_Rs,             do_rdrsrs},
691214571Sdim  {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
692214571Sdim  {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
693214571Sdim  {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
694214571Sdim  {"sub!",      0x2001,     0x700f,     0x00000015, Rd_Rs,                do16_rdrs},
695214571Sdim  {"subei!",    0x6080,     0x7087,     0x02000001, Rd_I4,                do16_rdi4},
696214571Sdim  {"sw!",       0x200c,     0x700f,     0x28000000, Rd_lvalueRs,          do16_ldst_insn},
697214571Sdim  {"swp!",      0x7004,     0x7007,     0x28000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
698214571Sdim  {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  do_i15},
699214571Sdim  {"tcs",       0x00000054, 0x3e007fff, 0x0005,     NO_OPD,               do_empty},
700214571Sdim  {"tcc",       0x00000454, 0x3e007fff, 0x0105,     NO_OPD,               do_empty},
701214571Sdim  {"tcnz",      0x00003854, 0x3e007fff, 0x0e05,     NO_OPD,               do_empty},
702214571Sdim  {"tcs!",      0x0005,     0x7f0f,     0x00000054, NO16_OPD,             do_empty},
703214571Sdim  {"tcc!",      0x0105,     0x7f0f,     0x00000454, NO16_OPD,             do_empty},
704214571Sdim  {"tcnz!",     0x0e05,     0x7f0f,     0x00003854, NO16_OPD,             do_empty},
705214571Sdim  {"teq",       0x00001054, 0x3e007fff, 0x0405,     NO_OPD,               do_empty},
706214571Sdim  {"teq!",      0x0405,     0x7f0f,     0x00001054, NO16_OPD,             do_empty},
707214571Sdim  {"tgtu",      0x00000854, 0x3e007fff, 0x0205,     NO_OPD,               do_empty},
708214571Sdim  {"tgt",       0x00001854, 0x3e007fff, 0x0605,     NO_OPD,               do_empty},
709214571Sdim  {"tge",       0x00002054, 0x3e007fff, 0x0805,     NO_OPD,               do_empty},
710214571Sdim  {"tgtu!",     0x0205,     0x7f0f,     0x00000854, NO16_OPD,             do_empty},
711214571Sdim  {"tgt!",      0x0605,     0x7f0f,     0x00001854, NO16_OPD,             do_empty},
712214571Sdim  {"tge!",      0x0805,     0x7f0f,     0x00002054, NO16_OPD,             do_empty},
713214571Sdim  {"tleu",      0x00000c54, 0x3e007fff, 0x0305,     NO_OPD,               do_empty},
714214571Sdim  {"tle",       0x00001c54, 0x3e007fff, 0x0705,     NO_OPD,               do_empty},
715214571Sdim  {"tlt",       0x00002454, 0x3e007fff, 0x0905,     NO_OPD,               do_empty},
716214571Sdim  {"stlb",      0x0c000004, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
717214571Sdim  {"mftlb",     0x0c000024, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
718214571Sdim  {"mtptlb",    0x0c000044, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
719214571Sdim  {"mtrtlb",    0x0c000064, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
720214571Sdim  {"tleu!",     0x0305,     0x7f0f,     0x00000c54, NO16_OPD,             do_empty},
721214571Sdim  {"tle!",      0x0705,     0x7f0f,     0x00001c54, NO16_OPD,             do_empty},
722214571Sdim  {"tlt!",      0x0905,     0x7f0f,     0x00002454, NO16_OPD,             do_empty},
723214571Sdim  {"tmi",       0x00002854, 0x3e007fff, 0x0a05,     NO_OPD,               do_empty},
724214571Sdim  {"tmi!",      0x0a05,     0x7f0f,     0x00002854, NO16_OPD,             do_empty},
725214571Sdim  {"tne",       0x00001454, 0x3e007fff, 0x0505,     NO_OPD,               do_empty},
726214571Sdim  {"tne!",      0x0505,     0x7f0f,     0x00001454, NO16_OPD,             do_empty},
727214571Sdim  {"tpl",       0x00002c54, 0x3e007fff, 0x0b05,     NO_OPD,               do_empty},
728214571Sdim  {"tpl!",      0x0b05,     0x7f0f,     0x00002c54, NO16_OPD,             do_empty},
729214571Sdim  {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
730214571Sdim  {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
731214571Sdim  {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
732214571Sdim  {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
733214571Sdim  {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
734214571Sdim  {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
735214571Sdim  {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
736214571Sdim  {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
737214571Sdim  {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
738214571Sdim  {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
739214571Sdim  {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
740214571Sdim  {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
741214571Sdim  {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
742214571Sdim  {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
743214571Sdim  {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
744214571Sdim  {"tset",      0x00003c54, 0x3e007fff, 0x0f05,     NO_OPD,               do_empty},
745214571Sdim  {"tset!",     0x0f05,     0x00007f0f, 0x00003c54, NO16_OPD,             do_empty},
746214571Sdim  {"tvs",       0x00003054, 0x3e007fff, 0x0c05,     NO_OPD,               do_empty},
747214571Sdim  {"tvc",       0x00003454, 0x3e007fff, 0x0d05,     NO_OPD,               do_empty},
748214571Sdim  {"tvs!",      0x0c05,     0x7f0f,     0x00003054, NO16_OPD,             do_empty},
749214571Sdim  {"tvc!",      0x0d05,     0x7f0f,     0x00003454, NO16_OPD,             do_empty},
750214571Sdim  {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
751214571Sdim  {"xor.c",     0x00000027, 0x3e0003ff, 0x2007,     Rd_Rs_Rs,             do_rdrsrs},
752214571Sdim  {"xor!",      0x2007,     0x700f,     0x00000027, Rd_Rs,                do16_rdrs},
753214571Sdim  /* Macro instruction.  */
754214571Sdim  {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_li_rdi32},
755214571Sdim  /* la reg, imm32        -->(1)  ldi  reg, simm16
756214571Sdim                             (2)  ldis reg, %HI(imm32)
757214571Sdim                                  ori  reg, %LO(imm32)
758214571Sdim
759214571Sdim     la reg, symbol       -->(1)  lis  reg, %HI(imm32)
760214571Sdim                                  ori  reg, %LO(imm32)  */
761214571Sdim  {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_la_rdi32},
762214571Sdim  {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
763214571Sdim  {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
764214571Sdim  {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
765214571Sdim  {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
766214571Sdim  {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
767214571Sdim  {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
768214571Sdim  {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
769214571Sdim  {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
770214571Sdim  {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
771214571Sdim  {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
772214571Sdim  {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
773214571Sdim  {"lbu",       INSN_LBU,   0x00000000, 0x200b,     Insn_Type_SYN,        do_macro_ldst_label},
774214571Sdim  {"lh",        INSN_LH,    0x00000000, 0x2009,     Insn_Type_SYN,        do_macro_ldst_label},
775214571Sdim  {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
776214571Sdim  {"lw",        INSN_LW,    0x00000000, 0x2008,     Insn_Type_SYN,        do_macro_ldst_label},
777214571Sdim  {"sb",        INSN_SB,    0x00000000, 0x200f,     Insn_Type_SYN,        do_macro_ldst_label},
778214571Sdim  {"sh",        INSN_SH,    0x00000000, 0x200d,     Insn_Type_SYN,        do_macro_ldst_label},
779214571Sdim  {"sw",        INSN_SW,    0x00000000, 0x200c,     Insn_Type_SYN,        do_macro_ldst_label},
780214571Sdim  /* Assembler use internal.  */
781214571Sdim  {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, do_macro_rdi32hi},
782214571Sdim  {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, do_macro_rdi32lo},
783214571Sdim  {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x5000,     Insn_internal, do_rdi16_pic},
784214571Sdim  {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_s_pic},
785214571Sdim  {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_u_pic},
786214571Sdim  {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, do_lw_pic},
787214571Sdim};
788214571Sdim
789214571Sdim/* Next free entry in the pool.  */
790214571Sdimint next_literal_pool_place = 0;
791214571Sdim
792214571Sdim/* Next literal pool number.  */
793214571Sdimint lit_pool_num = 1;
794214571SdimsymbolS *current_poolP = NULL;
795214571Sdim
796214571Sdim
797214571Sdimstatic int
798214571Sdimend_of_line (char *str)
799214571Sdim{
800214571Sdim  int retval = SUCCESS;
801214571Sdim
802214571Sdim  skip_whitespace (str);
803214571Sdim  if (*str != '\0')
804214571Sdim    {
805214571Sdim      retval = (int) FAIL;
806214571Sdim
807214571Sdim      if (!inst.error)
808214571Sdim        inst.error = BAD_GARBAGE;
809214571Sdim    }
810214571Sdim
811214571Sdim  return retval;
812214571Sdim}
813214571Sdim
814214571Sdimstatic int
815214571Sdimscore_reg_parse (char **ccp, struct hash_control *htab)
816214571Sdim{
817214571Sdim  char *start = *ccp;
818214571Sdim  char c;
819214571Sdim  char *p;
820214571Sdim  struct reg_entry *reg;
821214571Sdim
822214571Sdim  p = start;
823214571Sdim  if (!ISALPHA (*p) || !is_name_beginner (*p))
824214571Sdim    return (int) FAIL;
825214571Sdim
826214571Sdim  c = *p++;
827214571Sdim
828214571Sdim  while (ISALPHA (c) || ISDIGIT (c) || c == '_')
829214571Sdim    c = *p++;
830214571Sdim
831214571Sdim  *--p = 0;
832214571Sdim  reg = (struct reg_entry *) hash_find (htab, start);
833214571Sdim  *p = c;
834214571Sdim
835214571Sdim  if (reg)
836214571Sdim    {
837214571Sdim      *ccp = p;
838214571Sdim      return reg->number;
839214571Sdim    }
840214571Sdim  return (int) FAIL;
841214571Sdim}
842214571Sdim
843214571Sdim/* If shift <= 0, only return reg.  */
844214571Sdim
845214571Sdimstatic int
846214571Sdimreg_required_here (char **str, int shift, enum score_reg_type reg_type)
847214571Sdim{
848214571Sdim  static char buff[MAX_LITERAL_POOL_SIZE];
849214571Sdim  int reg = (int) FAIL;
850214571Sdim  char *start = *str;
851214571Sdim
852214571Sdim  if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
853214571Sdim    {
854214571Sdim      if (reg_type == REG_TYPE_SCORE)
855214571Sdim        {
856214571Sdim          if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
857214571Sdim            {
858214571Sdim              as_warn (_("Using temp register(r1)"));
859214571Sdim              inst.bwarn = 1;
860214571Sdim            }
861214571Sdim        }
862214571Sdim      if (shift >= 0)
863214571Sdim	{
864214571Sdim          if (reg_type == REG_TYPE_SCORE_CR)
865214571Sdim	    strcpy (inst.reg, score_crn_table[reg].name);
866214571Sdim          else if (reg_type == REG_TYPE_SCORE_SR)
867214571Sdim	    strcpy (inst.reg, score_srn_table[reg].name);
868214571Sdim          else
869214571Sdim	    strcpy (inst.reg, "");
870214571Sdim
871214571Sdim          inst.instruction |= reg << shift;
872214571Sdim	}
873214571Sdim    }
874214571Sdim  else
875214571Sdim    {
876214571Sdim      *str = start;
877214571Sdim      sprintf (buff, _("register expected, not '%.100s'"), start);
878214571Sdim      inst.error = buff;
879214571Sdim    }
880214571Sdim
881214571Sdim  return reg;
882214571Sdim}
883214571Sdim
884214571Sdimstatic int
885214571Sdimskip_past_comma (char **str)
886214571Sdim{
887214571Sdim  char *p = *str;
888214571Sdim  char c;
889214571Sdim  int comma = 0;
890214571Sdim
891214571Sdim  while ((c = *p) == ' ' || c == ',')
892214571Sdim    {
893214571Sdim      p++;
894214571Sdim      if (c == ',' && comma++)
895214571Sdim        {
896214571Sdim          inst.error = BAD_SKIP_COMMA;
897214571Sdim          return (int) FAIL;
898214571Sdim        }
899214571Sdim    }
900214571Sdim
901214571Sdim  if ((c == '\0') || (comma == 0))
902214571Sdim    {
903214571Sdim      inst.error = BAD_SKIP_COMMA;
904214571Sdim      return (int) FAIL;
905214571Sdim    }
906214571Sdim
907214571Sdim  *str = p;
908214571Sdim  return comma ? SUCCESS : (int) FAIL;
909214571Sdim}
910214571Sdim
911214571Sdimstatic void
912214571Sdimdo_rdrsrs (char *str)
913214571Sdim{
914214571Sdim  skip_whitespace (str);
915214571Sdim
916214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
917214571Sdim      || skip_past_comma (&str) == (int) FAIL
918214571Sdim      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
919214571Sdim      || skip_past_comma (&str) == (int) FAIL
920214571Sdim      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
921214571Sdim      || end_of_line (str) == (int) FAIL)
922214571Sdim    {
923214571Sdim      return;
924214571Sdim    }
925214571Sdim  else
926214571Sdim    {
927214571Sdim      if ((((inst.instruction >> 15) & 0x10) == 0)
928214571Sdim          && (((inst.instruction >> 10) & 0x10) == 0)
929214571Sdim          && (((inst.instruction >> 20) & 0x10) == 0)
930214571Sdim          && (inst.relax_inst != 0x8000)
931214571Sdim          && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
932214571Sdim        {
933214571Sdim          inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
934214571Sdim            | (((inst.instruction >> 15) & 0xf) << 8);
935214571Sdim          inst.relax_size = 2;
936214571Sdim        }
937214571Sdim      else
938214571Sdim        {
939214571Sdim          inst.relax_inst = 0x8000;
940214571Sdim        }
941214571Sdim    }
942214571Sdim}
943214571Sdim
944214571Sdimstatic int
945214571Sdimwalk_no_bignums (symbolS * sp)
946214571Sdim{
947214571Sdim  if (symbol_get_value_expression (sp)->X_op == O_big)
948214571Sdim    return 1;
949214571Sdim
950214571Sdim  if (symbol_get_value_expression (sp)->X_add_symbol)
951214571Sdim    return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
952214571Sdim	    || (symbol_get_value_expression (sp)->X_op_symbol
953214571Sdim		&& walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
954214571Sdim
955214571Sdim  return 0;
956214571Sdim}
957214571Sdim
958214571Sdimstatic int
959214571Sdimmy_get_expression (expressionS * ep, char **str)
960214571Sdim{
961214571Sdim  char *save_in;
962214571Sdim  segT seg;
963214571Sdim
964214571Sdim  save_in = input_line_pointer;
965214571Sdim  input_line_pointer = *str;
966214571Sdim  in_my_get_expression = 1;
967214571Sdim  seg = expression (ep);
968214571Sdim  in_my_get_expression = 0;
969214571Sdim
970214571Sdim  if (ep->X_op == O_illegal)
971214571Sdim    {
972214571Sdim      *str = input_line_pointer;
973214571Sdim      input_line_pointer = save_in;
974214571Sdim      inst.error = _("illegal expression");
975214571Sdim      return (int) FAIL;
976214571Sdim    }
977214571Sdim  /* Get rid of any bignums now, so that we don't generate an error for which
978214571Sdim     we can't establish a line number later on.  Big numbers are never valid
979214571Sdim     in instructions, which is where this routine is always called.  */
980214571Sdim  if (ep->X_op == O_big
981214571Sdim      || (ep->X_add_symbol
982214571Sdim          && (walk_no_bignums (ep->X_add_symbol)
983214571Sdim              || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
984214571Sdim    {
985214571Sdim      inst.error = _("invalid constant");
986214571Sdim      *str = input_line_pointer;
987214571Sdim      input_line_pointer = save_in;
988214571Sdim      return (int) FAIL;
989214571Sdim    }
990214571Sdim
991214571Sdim  if ((ep->X_add_symbol != NULL)
992214571Sdim      && (inst.type != PC_DISP19div2)
993214571Sdim      && (inst.type != PC_DISP8div2)
994214571Sdim      && (inst.type != PC_DISP24div2)
995214571Sdim      && (inst.type != PC_DISP11div2)
996214571Sdim      && (inst.type != Insn_Type_SYN)
997214571Sdim      && (inst.type != Rd_rvalueRs_SI15)
998214571Sdim      && (inst.type != Rd_lvalueRs_SI15)
999214571Sdim      && (inst.type != Insn_internal))
1000214571Sdim    {
1001214571Sdim      inst.error = BAD_ARGS;
1002214571Sdim      *str = input_line_pointer;
1003214571Sdim      input_line_pointer = save_in;
1004214571Sdim      return (int) FAIL;
1005214571Sdim    }
1006214571Sdim
1007214571Sdim  *str = input_line_pointer;
1008214571Sdim  input_line_pointer = save_in;
1009214571Sdim  return SUCCESS;
1010214571Sdim}
1011214571Sdim
1012214571Sdim/* Check if an immediate is valid.  If so, convert it to the right format.  */
1013214571Sdim
1014214571Sdimstatic int
1015214571Sdimvalidate_immediate (int val, unsigned int data_type, int hex_p)
1016214571Sdim{
1017214571Sdim  switch (data_type)
1018214571Sdim    {
1019214571Sdim    case _VALUE_HI16:
1020214571Sdim      {
1021214571Sdim        int val_hi = ((val & 0xffff0000) >> 16);
1022214571Sdim
1023214571Sdim        if (score_df_range[data_type].range[0] <= val_hi
1024214571Sdim            && val_hi <= score_df_range[data_type].range[1])
1025214571Sdim	  return val_hi;
1026214571Sdim      }
1027214571Sdim      break;
1028214571Sdim
1029214571Sdim    case _VALUE_LO16:
1030214571Sdim      {
1031214571Sdim        int val_lo = (val & 0xffff);
1032214571Sdim
1033214571Sdim        if (score_df_range[data_type].range[0] <= val_lo
1034214571Sdim            && val_lo <= score_df_range[data_type].range[1])
1035214571Sdim	  return val_lo;
1036214571Sdim      }
1037214571Sdim      break;
1038214571Sdim
1039214571Sdim    case _VALUE:
1040214571Sdim      return val;
1041214571Sdim      break;
1042214571Sdim
1043214571Sdim    case _SIMM14:
1044214571Sdim      if (hex_p == 1)
1045214571Sdim        {
1046214571Sdim          if (!(val >= -0x2000 && val <= 0x3fff))
1047214571Sdim            {
1048214571Sdim              return (int) FAIL;
1049214571Sdim            }
1050214571Sdim        }
1051214571Sdim      else
1052214571Sdim        {
1053214571Sdim          if (!(val >= -8192 && val <= 8191))
1054214571Sdim            {
1055214571Sdim              return (int) FAIL;
1056214571Sdim            }
1057214571Sdim        }
1058214571Sdim
1059214571Sdim      return val;
1060214571Sdim      break;
1061214571Sdim
1062214571Sdim    case _SIMM16_NEG:
1063214571Sdim      if (hex_p == 1)
1064214571Sdim        {
1065214571Sdim          if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
1066214571Sdim            {
1067214571Sdim              return (int) FAIL;
1068214571Sdim            }
1069214571Sdim        }
1070214571Sdim      else
1071214571Sdim        {
1072214571Sdim          if (!(val >= -32767 && val <= 32768))
1073214571Sdim            {
1074214571Sdim              return (int) FAIL;
1075214571Sdim            }
1076214571Sdim        }
1077214571Sdim
1078214571Sdim      val = -val;
1079214571Sdim      return val;
1080214571Sdim      break;
1081214571Sdim
1082214571Sdim    default:
1083214571Sdim      if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
1084214571Sdim	val = -val;
1085214571Sdim
1086214571Sdim      if (score_df_range[data_type].range[0] <= val
1087214571Sdim          && val <= score_df_range[data_type].range[1])
1088214571Sdim	return val;
1089214571Sdim
1090214571Sdim      break;
1091214571Sdim    }
1092214571Sdim
1093214571Sdim  return (int) FAIL;
1094214571Sdim}
1095214571Sdim
1096214571Sdimstatic int
1097214571Sdimdata_op2 (char **str, int shift, enum score_data_type data_type)
1098214571Sdim{
1099214571Sdim  int value;
1100214571Sdim  char data_exp[MAX_LITERAL_POOL_SIZE];
1101214571Sdim  char *dataptr;
1102214571Sdim  int cnt = 0;
1103214571Sdim  char *pp = NULL;
1104214571Sdim
1105214571Sdim  skip_whitespace (*str);
1106214571Sdim  inst.error = NULL;
1107214571Sdim  dataptr = * str;
1108214571Sdim
1109214571Sdim  /* Set hex_p to zero.  */
1110214571Sdim  int hex_p = 0;
1111214571Sdim
1112214571Sdim  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
1113214571Sdim    {
1114214571Sdim      data_exp[cnt] = *dataptr;
1115214571Sdim      dataptr++;
1116214571Sdim      cnt++;
1117214571Sdim    }
1118214571Sdim
1119214571Sdim  data_exp[cnt] = '\0';
1120214571Sdim  pp = (char *)&data_exp;
1121214571Sdim
1122214571Sdim  if (*dataptr == '|')          /* process PCE */
1123214571Sdim    {
1124214571Sdim      if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
1125214571Sdim        return (int) FAIL;
1126214571Sdim      end_of_line (pp);
1127214571Sdim      if (inst.error != 0)
1128214571Sdim        return (int) FAIL;       /* to ouptut_inst to printf out the error */
1129214571Sdim      *str = dataptr;
1130214571Sdim    }
1131214571Sdim  else                          /* process  16 bit */
1132214571Sdim    {
1133214571Sdim      if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
1134214571Sdim        {
1135214571Sdim          return (int) FAIL;
1136214571Sdim        }
1137214571Sdim
1138214571Sdim      dataptr = (char *)data_exp;
1139214571Sdim      for (; *dataptr != '\0'; dataptr++)
1140214571Sdim        {
1141214571Sdim          *dataptr = TOLOWER (*dataptr);
1142214571Sdim          if (*dataptr == '!' || *dataptr == ' ')
1143214571Sdim            break;
1144214571Sdim        }
1145214571Sdim      dataptr = (char *)data_exp;
1146214571Sdim
1147214571Sdim      if ((dataptr != NULL)
1148214571Sdim          && (((strstr (dataptr, "0x")) != NULL)
1149214571Sdim              || ((strstr (dataptr, "0X")) != NULL)))
1150214571Sdim        {
1151214571Sdim          hex_p = 1;
1152214571Sdim          if ((data_type != _SIMM16_LA)
1153214571Sdim              && (data_type != _VALUE_HI16)
1154214571Sdim              && (data_type != _VALUE_LO16)
1155214571Sdim              && (data_type != _IMM16)
1156214571Sdim              && (data_type != _IMM15)
1157214571Sdim              && (data_type != _IMM14)
1158214571Sdim              && (data_type != _IMM4)
1159214571Sdim              && (data_type != _IMM5)
1160214571Sdim              && (data_type != _IMM8)
1161214571Sdim              && (data_type != _IMM5_RSHIFT_1)
1162214571Sdim              && (data_type != _IMM5_RSHIFT_2)
1163214571Sdim              && (data_type != _SIMM14)
1164214571Sdim              && (data_type != _SIMM14_NEG)
1165214571Sdim              && (data_type != _SIMM16_NEG)
1166214571Sdim              && (data_type != _IMM10_RSHIFT_2)
1167214571Sdim              && (data_type != _GP_IMM15))
1168214571Sdim            {
1169214571Sdim              data_type += 24;
1170214571Sdim            }
1171214571Sdim        }
1172214571Sdim
1173214571Sdim      if ((inst.reloc.exp.X_add_number == 0)
1174214571Sdim          && (inst.type != Insn_Type_SYN)
1175214571Sdim          && (inst.type != Rd_rvalueRs_SI15)
1176214571Sdim          && (inst.type != Rd_lvalueRs_SI15)
1177214571Sdim          && (inst.type != Insn_internal)
1178214571Sdim          && (((*dataptr >= 'a') && (*dataptr <= 'z'))
1179214571Sdim             || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
1180214571Sdim             || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
1181214571Sdim             || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
1182214571Sdim        {
1183214571Sdim          inst.error = BAD_ARGS;
1184214571Sdim          return (int) FAIL;
1185214571Sdim        }
1186214571Sdim    }
1187214571Sdim
1188214571Sdim  if ((inst.reloc.exp.X_add_symbol)
1189214571Sdim      && ((data_type == _SIMM16)
1190214571Sdim          || (data_type == _SIMM16_NEG)
1191214571Sdim          || (data_type == _IMM16_NEG)
1192214571Sdim          || (data_type == _SIMM14)
1193214571Sdim          || (data_type == _SIMM14_NEG)
1194214571Sdim          || (data_type == _IMM5)
1195214571Sdim          || (data_type == _IMM14)
1196214571Sdim          || (data_type == _IMM20)
1197214571Sdim          || (data_type == _IMM16)
1198214571Sdim          || (data_type == _IMM15)
1199214571Sdim          || (data_type == _IMM4)))
1200214571Sdim    {
1201214571Sdim      inst.error = BAD_ARGS;
1202214571Sdim      return (int) FAIL;
1203214571Sdim    }
1204214571Sdim
1205214571Sdim  if (inst.reloc.exp.X_add_symbol)
1206214571Sdim    {
1207214571Sdim      switch (data_type)
1208214571Sdim        {
1209214571Sdim        case _SIMM16_LA:
1210214571Sdim          return (int) FAIL;
1211214571Sdim        case _VALUE_HI16:
1212214571Sdim          inst.reloc.type = BFD_RELOC_HI16_S;
1213214571Sdim          inst.reloc.pc_rel = 0;
1214214571Sdim          break;
1215214571Sdim        case _VALUE_LO16:
1216214571Sdim          inst.reloc.type = BFD_RELOC_LO16;
1217214571Sdim          inst.reloc.pc_rel = 0;
1218214571Sdim          break;
1219214571Sdim        case _GP_IMM15:
1220214571Sdim          inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
1221214571Sdim          inst.reloc.pc_rel = 0;
1222214571Sdim          break;
1223214571Sdim        case _SIMM16_pic:
1224214571Sdim        case _IMM16_LO16_pic:
1225214571Sdim          inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
1226214571Sdim          inst.reloc.pc_rel = 0;
1227214571Sdim          break;
1228214571Sdim        default:
1229214571Sdim          inst.reloc.type = BFD_RELOC_32;
1230214571Sdim          inst.reloc.pc_rel = 0;
1231214571Sdim          break;
1232214571Sdim        }
1233214571Sdim    }
1234214571Sdim  else
1235214571Sdim    {
1236214571Sdim      if (data_type == _IMM16_pic)
1237214571Sdim	{
1238214571Sdim          inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
1239214571Sdim          inst.reloc.pc_rel = 0;
1240214571Sdim	}
1241214571Sdim
1242214571Sdim      if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
1243214571Sdim        {
1244214571Sdim          value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
1245214571Sdim          if (value == (int) FAIL)       /* for advance to check if this is ldis */
1246214571Sdim            if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
1247214571Sdim              {
1248214571Sdim                inst.instruction |= 0x8000000;
1249214571Sdim                inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
1250214571Sdim                return SUCCESS;
1251214571Sdim              }
1252214571Sdim        }
1253214571Sdim      else
1254214571Sdim        {
1255214571Sdim          value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p);
1256214571Sdim        }
1257214571Sdim
1258214571Sdim      if (value == (int) FAIL)
1259214571Sdim        {
1260214571Sdim          if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1261214571Sdim            {
1262214571Sdim              sprintf (err_msg,
1263214571Sdim                       _("invalid constant: %d bit expression not in range %d..%d"),
1264214571Sdim                       score_df_range[data_type].bits,
1265214571Sdim                       score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
1266214571Sdim            }
1267214571Sdim          else
1268214571Sdim            {
1269214571Sdim              sprintf (err_msg,
1270214571Sdim                       _("invalid constant: %d bit expression not in range %d..%d"),
1271214571Sdim                       score_df_range[data_type].bits,
1272214571Sdim                       -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
1273214571Sdim            }
1274214571Sdim
1275214571Sdim          inst.error = err_msg;
1276214571Sdim          return (int) FAIL;
1277214571Sdim        }
1278214571Sdim
1279214571Sdim      if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
1280214571Sdim        {
1281214571Sdim          value &= (1 << score_df_range[data_type].bits) - 1;
1282214571Sdim        }
1283214571Sdim
1284214571Sdim      inst.instruction |= value << shift;
1285214571Sdim    }
1286214571Sdim
1287214571Sdim  if ((inst.instruction & 0xf0000000) == 0x30000000)
1288214571Sdim    {
1289214571Sdim      if ((((inst.instruction >> 20) & 0x1F) != 0)
1290214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 1)
1291214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 2)
1292214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 3)
1293214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 4)
1294214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 8)
1295214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 9)
1296214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0xa)
1297214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0xb)
1298214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0xc)
1299214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0xd)
1300214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0xe)
1301214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x10)
1302214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x11)
1303214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x18)
1304214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x1A)
1305214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x1B)
1306214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x1d)
1307214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x1e)
1308214571Sdim          && (((inst.instruction >> 20) & 0x1F) != 0x1f))
1309214571Sdim        {
1310214571Sdim          inst.error = _("invalid constant: bit expression not defined");
1311214571Sdim          return (int) FAIL;
1312214571Sdim        }
1313214571Sdim    }
1314214571Sdim
1315214571Sdim  return SUCCESS;
1316214571Sdim}
1317214571Sdim
1318214571Sdim/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
1319214571Sdim
1320214571Sdimstatic void
1321214571Sdimdo_rdsi16 (char *str)
1322214571Sdim{
1323214571Sdim  skip_whitespace (str);
1324214571Sdim
1325214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1326214571Sdim      || skip_past_comma (&str) == (int) FAIL
1327214571Sdim      || data_op2 (&str, 1, _SIMM16) == (int) FAIL
1328214571Sdim      || end_of_line (str) == (int) FAIL)
1329214571Sdim    return;
1330214571Sdim
1331214571Sdim  /* ldi.  */
1332214571Sdim  if ((inst.instruction & 0x20c0000) == 0x20c0000)
1333214571Sdim    {
1334214571Sdim      if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
1335214571Sdim        {
1336214571Sdim          inst.relax_inst = 0x8000;
1337214571Sdim        }
1338214571Sdim      else
1339214571Sdim        {
1340214571Sdim          inst.relax_inst |= (inst.instruction >> 1) & 0xff;
1341214571Sdim          inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
1342214571Sdim          inst.relax_size = 2;
1343214571Sdim        }
1344214571Sdim    }
1345214571Sdim  else if (((inst.instruction >> 20) & 0x10) == 0x10)
1346214571Sdim    {
1347214571Sdim      inst.relax_inst = 0x8000;
1348214571Sdim    }
1349214571Sdim}
1350214571Sdim
1351214571Sdim/* Handle subi/subi.c.  */
1352214571Sdim
1353214571Sdimstatic void
1354214571Sdimdo_sub_rdsi16 (char *str)
1355214571Sdim{
1356214571Sdim  skip_whitespace (str);
1357214571Sdim
1358214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1359214571Sdim      && skip_past_comma (&str) != (int) FAIL
1360214571Sdim      && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
1361214571Sdim    end_of_line (str);
1362214571Sdim}
1363214571Sdim
1364214571Sdim/* Handle addri/addri.c.  */
1365214571Sdim
1366214571Sdimstatic void
1367214571Sdimdo_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
1368214571Sdim{
1369214571Sdim  skip_whitespace (str);
1370214571Sdim
1371214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1372214571Sdim      && skip_past_comma (&str) != (int) FAIL
1373214571Sdim      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1374214571Sdim      && skip_past_comma (&str) != (int) FAIL)
1375214571Sdim    data_op2 (&str, 1, _SIMM14);
1376214571Sdim}
1377214571Sdim
1378214571Sdim/* Handle subri.c/subri.  */
1379214571Sdimstatic void
1380214571Sdimdo_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
1381214571Sdim{
1382214571Sdim  skip_whitespace (str);
1383214571Sdim
1384214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1385214571Sdim      && skip_past_comma (&str) != (int) FAIL
1386214571Sdim      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1387214571Sdim      && skip_past_comma (&str) != (int) FAIL
1388214571Sdim      && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
1389214571Sdim    end_of_line (str);
1390214571Sdim}
1391214571Sdim
1392214571Sdim/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.  */
1393214571Sdimstatic void
1394214571Sdimdo_rdrsi5 (char *str)           /* 0~((2^14)-1) */
1395214571Sdim{
1396214571Sdim  skip_whitespace (str);
1397214571Sdim
1398214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1399214571Sdim      || skip_past_comma (&str) == (int) FAIL
1400214571Sdim      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1401214571Sdim      || skip_past_comma (&str) == (int) FAIL
1402214571Sdim      || data_op2 (&str, 10, _IMM5) == (int) FAIL
1403214571Sdim      || end_of_line (str) == (int) FAIL)
1404214571Sdim    return;
1405214571Sdim
1406214571Sdim  if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
1407214571Sdim      && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1408214571Sdim    {
1409214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1410214571Sdim      inst.relax_size = 2;
1411214571Sdim    }
1412214571Sdim  else
1413214571Sdim    inst.relax_inst = 0x8000;
1414214571Sdim}
1415214571Sdim
1416214571Sdim/* Handle andri/orri/andri.c/orri.c.  */
1417214571Sdim
1418214571Sdimstatic void
1419214571Sdimdo_rdrsi14 (char *str)          /* 0 ~ ((2^14)-1)  */
1420214571Sdim{
1421214571Sdim  skip_whitespace (str);
1422214571Sdim
1423214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1424214571Sdim      && skip_past_comma (&str) != (int) FAIL
1425214571Sdim      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1426214571Sdim      && skip_past_comma (&str) != (int) FAIL
1427214571Sdim      && data_op2 (&str, 1, _IMM14) != (int) FAIL)
1428214571Sdim    end_of_line (str);
1429214571Sdim}
1430214571Sdim
1431214571Sdim/* Handle bittst.c.  */
1432214571Sdimstatic void
1433214571Sdimdo_xrsi5 (char *str)
1434214571Sdim{
1435214571Sdim  skip_whitespace (str);
1436214571Sdim
1437214571Sdim  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1438214571Sdim      || skip_past_comma (&str) == (int) FAIL
1439214571Sdim      || data_op2 (&str, 10, _IMM5) == (int) FAIL
1440214571Sdim      || end_of_line (str) == (int) FAIL)
1441214571Sdim    return;
1442214571Sdim
1443214571Sdim  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1444214571Sdim    {
1445214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
1446214571Sdim      inst.relax_size = 2;
1447214571Sdim    }
1448214571Sdim  else
1449214571Sdim    inst.relax_inst = 0x8000;
1450214571Sdim}
1451214571Sdim
1452214571Sdim/* Handle addis/andi/ori/andis/oris/ldis.  */
1453214571Sdimstatic void
1454214571Sdimdo_rdi16 (char *str)
1455214571Sdim{
1456214571Sdim  skip_whitespace (str);
1457214571Sdim
1458214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1459214571Sdim      || skip_past_comma (&str) == (int) FAIL
1460214571Sdim      || data_op2 (&str, 1, _IMM16) == (int) FAIL
1461214571Sdim      || end_of_line (str) == (int) FAIL)
1462214571Sdim    return;
1463214571Sdim  /*
1464214571Sdim  if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
1465214571Sdim    inst.relax_inst = 0x8000;
1466214571Sdim  else
1467214571Sdim    inst.relax_size = 2;
1468214571Sdim  */
1469214571Sdim}
1470214571Sdim
1471214571Sdimstatic void
1472214571Sdimdo_macro_rdi32hi (char *str)
1473214571Sdim{
1474214571Sdim  skip_whitespace (str);
1475214571Sdim
1476214571Sdim  /* Do not handle end_of_line().  */
1477214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1478214571Sdim      && skip_past_comma (&str) != (int) FAIL)
1479214571Sdim    data_op2 (&str, 1, _VALUE_HI16);
1480214571Sdim}
1481214571Sdim
1482214571Sdimstatic void
1483214571Sdimdo_macro_rdi32lo (char *str)
1484214571Sdim{
1485214571Sdim  skip_whitespace (str);
1486214571Sdim
1487214571Sdim  /* Do not handle end_of_line().  */
1488214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1489214571Sdim      && skip_past_comma (&str) != (int) FAIL)
1490214571Sdim    data_op2 (&str, 1, _VALUE_LO16);
1491214571Sdim}
1492214571Sdim
1493214571Sdim/* Handle ldis_pic.  */
1494214571Sdim
1495214571Sdimstatic void
1496214571Sdimdo_rdi16_pic (char *str)
1497214571Sdim{
1498214571Sdim  skip_whitespace (str);
1499214571Sdim
1500214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1501214571Sdim      && skip_past_comma (&str) != (int) FAIL
1502214571Sdim      && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
1503214571Sdim    end_of_line (str);
1504214571Sdim}
1505214571Sdim
1506214571Sdim/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
1507214571Sdim
1508214571Sdimstatic void
1509214571Sdimdo_addi_s_pic (char *str)
1510214571Sdim{
1511214571Sdim  skip_whitespace (str);
1512214571Sdim
1513214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1514214571Sdim      && skip_past_comma (&str) != (int) FAIL
1515214571Sdim      && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
1516214571Sdim    end_of_line (str);
1517214571Sdim}
1518214571Sdim
1519214571Sdim/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
1520214571Sdim
1521214571Sdimstatic void
1522214571Sdimdo_addi_u_pic (char *str)
1523214571Sdim{
1524214571Sdim  skip_whitespace (str);
1525214571Sdim
1526214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1527214571Sdim      && skip_past_comma (&str) != (int) FAIL
1528214571Sdim      && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
1529214571Sdim    end_of_line (str);
1530214571Sdim}
1531214571Sdim
1532214571Sdim/* Handle mfceh/mfcel/mtceh/mtchl.  */
1533214571Sdim
1534214571Sdimstatic void
1535214571Sdimdo_rd (char *str)
1536214571Sdim{
1537214571Sdim  skip_whitespace (str);
1538214571Sdim
1539214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
1540214571Sdim    end_of_line (str);
1541214571Sdim}
1542214571Sdim
1543214571Sdimstatic void
1544214571Sdimdo_rs (char *str)
1545214571Sdim{
1546214571Sdim  skip_whitespace (str);
1547214571Sdim
1548214571Sdim  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1549214571Sdim      || end_of_line (str) == (int) FAIL)
1550214571Sdim    return;
1551214571Sdim
1552214571Sdim  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1553214571Sdim    {
1554214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
1555214571Sdim      inst.relax_size = 2;
1556214571Sdim    }
1557214571Sdim  else
1558214571Sdim    inst.relax_inst = 0x8000;
1559214571Sdim}
1560214571Sdim
1561214571Sdimstatic void
1562214571Sdimdo_i15 (char *str)
1563214571Sdim{
1564214571Sdim  skip_whitespace (str);
1565214571Sdim
1566214571Sdim  if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
1567214571Sdim    end_of_line (str);
1568214571Sdim}
1569214571Sdim
1570214571Sdimstatic void
1571214571Sdimdo_xi5x (char *str)
1572214571Sdim{
1573214571Sdim  skip_whitespace (str);
1574214571Sdim
1575214571Sdim  if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
1576214571Sdim    return;
1577214571Sdim
1578214571Sdim  if (inst.relax_inst != 0x8000)
1579214571Sdim    {
1580214571Sdim      inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
1581214571Sdim      inst.relax_size = 2;
1582214571Sdim    }
1583214571Sdim}
1584214571Sdim
1585214571Sdimstatic void
1586214571Sdimdo_rdrs (char *str)
1587214571Sdim{
1588214571Sdim  skip_whitespace (str);
1589214571Sdim
1590214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1591214571Sdim      || skip_past_comma (&str) == (int) FAIL
1592214571Sdim      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1593214571Sdim      || end_of_line (str) == (int) FAIL)
1594214571Sdim    return;
1595214571Sdim
1596214571Sdim  if (inst.relax_inst != 0x8000)
1597214571Sdim    {
1598214571Sdim      if (((inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv! / mlfh! / mhfl! */
1599214571Sdim        {
1600214571Sdim          /* mlfh */
1601214571Sdim          if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1602214571Sdim            {
1603214571Sdim              inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
1604214571Sdim                | (((inst.instruction >> 20) & 0xf) << 8);
1605214571Sdim              inst.relax_size = 2;
1606214571Sdim            }
1607214571Sdim          /* mhfl */
1608214571Sdim          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
1609214571Sdim            {
1610214571Sdim              inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
1611214571Sdim                | (((inst.instruction >> 20) & 0xf) << 8);
1612214571Sdim              inst.relax_size = 2;
1613214571Sdim            }
1614214571Sdim          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1615214571Sdim            {
1616214571Sdim              inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1617214571Sdim                | (((inst.instruction >> 20) & 0xf) << 8);
1618214571Sdim              inst.relax_size = 2;
1619214571Sdim            }
1620214571Sdim          else
1621214571Sdim            {
1622214571Sdim              inst.relax_inst = 0x8000;
1623214571Sdim            }
1624214571Sdim        }
1625214571Sdim      else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1626214571Sdim        {
1627214571Sdim          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1628214571Sdim            | (((inst.instruction >> 20) & 0xf) << 8);
1629214571Sdim          inst.relax_size = 2;
1630214571Sdim        }
1631214571Sdim      else
1632214571Sdim        {
1633214571Sdim          inst.relax_inst = 0x8000;
1634214571Sdim        }
1635214571Sdim    }
1636214571Sdim}
1637214571Sdim
1638214571Sdim/* Handle mfcr/mtcr.  */
1639214571Sdimstatic void
1640214571Sdimdo_rdcrs (char *str)
1641214571Sdim{
1642214571Sdim  skip_whitespace (str);
1643214571Sdim
1644214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1645214571Sdim      && skip_past_comma (&str) != (int) FAIL
1646214571Sdim      && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
1647214571Sdim    end_of_line (str);
1648214571Sdim}
1649214571Sdim
1650214571Sdim/* Handle mfsr/mtsr.  */
1651214571Sdim
1652214571Sdimstatic void
1653214571Sdimdo_rdsrs (char *str)
1654214571Sdim{
1655214571Sdim  skip_whitespace (str);
1656214571Sdim
1657214571Sdim  /* mfsr */
1658214571Sdim  if ((inst.instruction & 0xff) == 0x50)
1659214571Sdim    {
1660214571Sdim      if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1661214571Sdim          && skip_past_comma (&str) != (int) FAIL
1662214571Sdim          && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
1663214571Sdim	end_of_line (str);
1664214571Sdim    }
1665214571Sdim  else
1666214571Sdim    {
1667214571Sdim      if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1668214571Sdim          && skip_past_comma (&str) != (int) FAIL)
1669214571Sdim	reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
1670214571Sdim    }
1671214571Sdim}
1672214571Sdim
1673214571Sdim/* Handle neg.  */
1674214571Sdim
1675214571Sdimstatic void
1676214571Sdimdo_rdxrs (char *str)
1677214571Sdim{
1678214571Sdim  skip_whitespace (str);
1679214571Sdim
1680214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1681214571Sdim      || skip_past_comma (&str) == (int) FAIL
1682214571Sdim      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1683214571Sdim      || end_of_line (str) == (int) FAIL)
1684214571Sdim    return;
1685214571Sdim
1686214571Sdim  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
1687214571Sdim      && (((inst.instruction >> 20) & 0x10) == 0))
1688214571Sdim    {
1689214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
1690214571Sdim      inst.relax_size = 2;
1691214571Sdim    }
1692214571Sdim  else
1693214571Sdim    inst.relax_inst = 0x8000;
1694214571Sdim}
1695214571Sdim
1696214571Sdim/* Handle cmp.c/cmp<cond>.  */
1697214571Sdimstatic void
1698214571Sdimdo_rsrs (char *str)
1699214571Sdim{
1700214571Sdim  skip_whitespace (str);
1701214571Sdim
1702214571Sdim  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1703214571Sdim      || skip_past_comma (&str) == (int) FAIL
1704214571Sdim      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1705214571Sdim      || end_of_line (str) == (int) FAIL)
1706214571Sdim    return;
1707214571Sdim
1708214571Sdim  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
1709214571Sdim      && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
1710214571Sdim    {
1711214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
1712214571Sdim      inst.relax_size = 2;
1713214571Sdim    }
1714214571Sdim  else
1715214571Sdim    inst.relax_inst = 0x8000;
1716214571Sdim}
1717214571Sdim
1718214571Sdimstatic void
1719214571Sdimdo_ceinst (char *str)
1720214571Sdim{
1721214571Sdim  char *strbak;
1722214571Sdim
1723214571Sdim  strbak = str;
1724214571Sdim  skip_whitespace (str);
1725214571Sdim
1726214571Sdim  if (data_op2 (&str, 20, _IMM5) == (int) FAIL
1727214571Sdim      || skip_past_comma (&str) == (int) FAIL
1728214571Sdim      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1729214571Sdim      || skip_past_comma (&str) == (int) FAIL
1730214571Sdim      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1731214571Sdim      || skip_past_comma (&str) == (int) FAIL
1732214571Sdim      || data_op2 (&str, 5, _IMM5) == (int) FAIL
1733214571Sdim      || skip_past_comma (&str) == (int) FAIL
1734214571Sdim      || data_op2 (&str, 0, _IMM5) == (int) FAIL
1735214571Sdim      || end_of_line (str) == (int) FAIL)
1736214571Sdim    {
1737214571Sdim      return;
1738214571Sdim    }
1739214571Sdim  else
1740214571Sdim    {
1741214571Sdim      str = strbak;
1742214571Sdim      if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
1743214571Sdim	return;
1744214571Sdim    }
1745214571Sdim}
1746214571Sdim
1747214571Sdimstatic int
1748214571Sdimreglow_required_here (char **str, int shift)
1749214571Sdim{
1750214571Sdim  static char buff[MAX_LITERAL_POOL_SIZE];
1751214571Sdim  int reg;
1752214571Sdim  char *start = *str;
1753214571Sdim
1754214571Sdim  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1755214571Sdim    {
1756214571Sdim      if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
1757214571Sdim        {
1758214571Sdim          as_warn (_("Using temp register(r1)"));
1759214571Sdim          inst.bwarn = 1;
1760214571Sdim        }
1761214571Sdim      if (reg < 16)
1762214571Sdim        {
1763214571Sdim          if (shift >= 0)
1764214571Sdim            inst.instruction |= reg << shift;
1765214571Sdim
1766214571Sdim          return reg;
1767214571Sdim        }
1768214571Sdim    }
1769214571Sdim
1770214571Sdim  /* Restore the start point, we may have got a reg of the wrong class.  */
1771214571Sdim  *str = start;
1772214571Sdim  sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
1773214571Sdim  inst.error = buff;
1774214571Sdim  return (int) FAIL;
1775214571Sdim}
1776214571Sdim
1777214571Sdim/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!.  */
1778214571Sdimstatic void
1779214571Sdimdo16_rdrs (char *str)
1780214571Sdim{
1781214571Sdim  skip_whitespace (str);
1782214571Sdim
1783214571Sdim  if (reglow_required_here (&str, 8) == (int) FAIL
1784214571Sdim      || skip_past_comma (&str) == (int) FAIL
1785214571Sdim      || reglow_required_here (&str, 4) == (int) FAIL
1786214571Sdim      || end_of_line (str) == (int) FAIL)
1787214571Sdim    {
1788214571Sdim      return;
1789214571Sdim    }
1790214571Sdim  else
1791214571Sdim    {
1792214571Sdim      if ((inst.instruction & 0x700f) == 0x2003)        /* cmp!  */
1793214571Sdim        {
1794214571Sdim          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
1795214571Sdim            | (((inst.instruction >> 4) & 0xf) << 10);
1796214571Sdim        }
1797214571Sdim      else if ((inst.instruction & 0x700f) == 0x2006)   /* not!  */
1798214571Sdim	{
1799214571Sdim	  inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1800214571Sdim	    | (((inst.instruction >> 4) & 0xf) << 15);
1801214571Sdim	}
1802214571Sdim      else
1803214571Sdim        {
1804214571Sdim          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1805214571Sdim            | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
1806214571Sdim        }
1807214571Sdim      inst.relax_size = 4;
1808214571Sdim    }
1809214571Sdim}
1810214571Sdim
1811214571Sdimstatic void
1812214571Sdimdo16_rs (char *str)
1813214571Sdim{
1814214571Sdim  int rd = 0;
1815214571Sdim
1816214571Sdim  skip_whitespace (str);
1817214571Sdim
1818214571Sdim  if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
1819214571Sdim      || end_of_line (str) == (int) FAIL)
1820214571Sdim    {
1821214571Sdim      return;
1822214571Sdim    }
1823214571Sdim  else
1824214571Sdim    {
1825214571Sdim      inst.relax_inst |= rd << 20;
1826214571Sdim      inst.relax_size = 4;
1827214571Sdim    }
1828214571Sdim}
1829214571Sdim
1830214571Sdim/* Handle br!/brl!.  */
1831214571Sdimstatic void
1832214571Sdimdo16_xrs (char *str)
1833214571Sdim{
1834214571Sdim  skip_whitespace (str);
1835214571Sdim
1836214571Sdim  if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
1837214571Sdim    {
1838214571Sdim      return;
1839214571Sdim    }
1840214571Sdim  else
1841214571Sdim    {
1842214571Sdim      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
1843214571Sdim                      | (((inst.instruction >> 4) & 0xf) << 15);
1844214571Sdim      inst.relax_size = 4;
1845214571Sdim    }
1846214571Sdim}
1847214571Sdim
1848214571Sdimstatic int
1849214571Sdimreghigh_required_here (char **str, int shift)
1850214571Sdim{
1851214571Sdim  static char buff[MAX_LITERAL_POOL_SIZE];
1852214571Sdim  int reg;
1853214571Sdim  char *start = *str;
1854214571Sdim
1855214571Sdim  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1856214571Sdim    {
1857214571Sdim      if (15 < reg && reg < 32)
1858214571Sdim        {
1859214571Sdim          if (shift >= 0)
1860214571Sdim            inst.instruction |= (reg & 0xf) << shift;
1861214571Sdim
1862214571Sdim          return reg;
1863214571Sdim        }
1864214571Sdim    }
1865214571Sdim
1866214571Sdim  *str = start;
1867214571Sdim  sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
1868214571Sdim  inst.error = buff;
1869214571Sdim  return (int) FAIL;
1870214571Sdim}
1871214571Sdim
1872214571Sdim/* Handle mhfl!.  */
1873214571Sdimstatic void
1874214571Sdimdo16_hrdrs (char *str)
1875214571Sdim{
1876214571Sdim  skip_whitespace (str);
1877214571Sdim
1878214571Sdim  if (reghigh_required_here (&str, 8) != (int) FAIL
1879214571Sdim      && skip_past_comma (&str) != (int) FAIL
1880214571Sdim      && reglow_required_here (&str, 4) != (int) FAIL
1881214571Sdim      && end_of_line (str) != (int) FAIL)
1882214571Sdim    {
1883214571Sdim      inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
1884214571Sdim        | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
1885214571Sdim      inst.relax_size = 4;
1886214571Sdim    }
1887214571Sdim}
1888214571Sdim
1889214571Sdim/* Handle mlfh!.  */
1890214571Sdimstatic void
1891214571Sdimdo16_rdhrs (char *str)
1892214571Sdim{
1893214571Sdim  skip_whitespace (str);
1894214571Sdim
1895214571Sdim  if (reglow_required_here (&str, 8) != (int) FAIL
1896214571Sdim      && skip_past_comma (&str) != (int) FAIL
1897214571Sdim      && reghigh_required_here (&str, 4) != (int) FAIL
1898214571Sdim      && end_of_line (str) != (int) FAIL)
1899214571Sdim    {
1900214571Sdim      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1901214571Sdim        | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
1902214571Sdim      inst.relax_size = 4;
1903214571Sdim    }
1904214571Sdim}
1905214571Sdim
1906214571Sdim/* We need to be able to fix up arbitrary expressions in some statements.
1907214571Sdim   This is so that we can handle symbols that are an arbitrary distance from
1908214571Sdim   the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
1909214571Sdim   which returns part of an address in a form which will be valid for
1910214571Sdim   a data instruction.  We do this by pushing the expression into a symbol
1911214571Sdim   in the expr_section, and creating a fix for that.  */
1912214571Sdimstatic fixS *
1913214571Sdimfix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1914214571Sdim{
1915214571Sdim  fixS *new_fix;
1916214571Sdim
1917214571Sdim  switch (exp->X_op)
1918214571Sdim    {
1919214571Sdim    case O_constant:
1920214571Sdim    case O_symbol:
1921214571Sdim    case O_add:
1922214571Sdim    case O_subtract:
1923214571Sdim      new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
1924214571Sdim      break;
1925214571Sdim    default:
1926214571Sdim      new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
1927214571Sdim      break;
1928214571Sdim    }
1929214571Sdim  return new_fix;
1930214571Sdim}
1931214571Sdim
1932214571Sdimstatic void
1933214571Sdiminit_dependency_vector (void)
1934214571Sdim{
1935214571Sdim  int i;
1936214571Sdim
1937214571Sdim  for (i = 0; i < vector_size; i++)
1938214571Sdim    memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
1939214571Sdim
1940214571Sdim  return;
1941214571Sdim}
1942214571Sdim
1943214571Sdimstatic enum insn_type_for_dependency
1944214571Sdimdependency_type_from_insn (char *insn_name)
1945214571Sdim{
1946214571Sdim  char name[INSN_NAME_LEN];
1947214571Sdim  const struct insn_to_dependency *tmp;
1948214571Sdim
1949214571Sdim  strcpy (name, insn_name);
1950214571Sdim  tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
1951214571Sdim
1952214571Sdim  if (tmp)
1953214571Sdim    return tmp->type;
1954214571Sdim
1955214571Sdim  return D_all_insn;
1956214571Sdim}
1957214571Sdim
1958214571Sdimstatic int
1959214571Sdimcheck_dependency (char *pre_insn, char *pre_reg,
1960214571Sdim                  char *cur_insn, char *cur_reg, int *warn_or_error)
1961214571Sdim{
1962214571Sdim  int bubbles = 0;
1963214571Sdim  unsigned int i;
1964214571Sdim  enum insn_type_for_dependency pre_insn_type;
1965214571Sdim  enum insn_type_for_dependency cur_insn_type;
1966214571Sdim
1967214571Sdim  pre_insn_type = dependency_type_from_insn (pre_insn);
1968214571Sdim  cur_insn_type = dependency_type_from_insn (cur_insn);
1969214571Sdim
1970214571Sdim  for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
1971214571Sdim    {
1972214571Sdim      if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
1973214571Sdim          && (D_all_insn == data_dependency_table[i].cur_insn_type
1974214571Sdim              || cur_insn_type == data_dependency_table[i].cur_insn_type)
1975214571Sdim          && (strcmp (data_dependency_table[i].pre_reg, "") == 0
1976214571Sdim              || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
1977214571Sdim          && (strcmp (data_dependency_table[i].cur_reg, "") == 0
1978214571Sdim              || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
1979214571Sdim        {
1980214571Sdim          bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
1981214571Sdim          *warn_or_error = data_dependency_table[i].warn_or_error;
1982214571Sdim          break;
1983214571Sdim        }
1984214571Sdim    }
1985214571Sdim
1986214571Sdim  return bubbles;
1987214571Sdim}
1988214571Sdim
1989214571Sdimstatic void
1990214571Sdimbuild_one_frag (struct score_it one_inst)
1991214571Sdim{
1992214571Sdim  char *p;
1993214571Sdim  int relaxable_p = g_opt;
1994214571Sdim  int relax_size = 0;
1995214571Sdim
1996214571Sdim  /* Start a new frag if frag_now is not empty.  */
1997214571Sdim  if (frag_now_fix () != 0)
1998214571Sdim    {
1999214571Sdim      if (!frag_now->tc_frag_data.is_insn)
2000214571Sdim	frag_wane (frag_now);
2001214571Sdim
2002214571Sdim      frag_new (0);
2003214571Sdim    }
2004214571Sdim  frag_grow (20);
2005214571Sdim
2006214571Sdim  p = frag_more (one_inst.size);
2007214571Sdim  md_number_to_chars (p, one_inst.instruction, one_inst.size);
2008214571Sdim
2009214571Sdim#ifdef OBJ_ELF
2010214571Sdim  dwarf2_emit_insn (one_inst.size);
2011214571Sdim#endif
2012214571Sdim
2013214571Sdim  relaxable_p &= (one_inst.relax_size != 0);
2014214571Sdim  relax_size = relaxable_p ? one_inst.relax_size : 0;
2015214571Sdim
2016214571Sdim  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2017214571Sdim                RELAX_ENCODE (one_inst.size, one_inst.relax_size,
2018214571Sdim                              one_inst.type, 0, 0, relaxable_p),
2019214571Sdim                NULL, 0, NULL);
2020214571Sdim
2021214571Sdim  if (relaxable_p)
2022214571Sdim    md_number_to_chars (p, one_inst.relax_inst, relax_size);
2023214571Sdim}
2024214571Sdim
2025214571Sdimstatic void
2026214571Sdimhandle_dependency (struct score_it *theinst)
2027214571Sdim{
2028214571Sdim  int i;
2029214571Sdim  int warn_or_error = 0;   /* warn - 0; error - 1  */
2030214571Sdim  int bubbles = 0;
2031214571Sdim  int remainder_bubbles = 0;
2032214571Sdim  char cur_insn[INSN_NAME_LEN];
2033214571Sdim  char pre_insn[INSN_NAME_LEN];
2034214571Sdim  struct score_it nop_inst;
2035214571Sdim  struct score_it pflush_inst;
2036214571Sdim
2037214571Sdim  nop_inst.instruction = 0x0000;
2038214571Sdim  nop_inst.size = 2;
2039214571Sdim  nop_inst.relax_inst = 0x80008000;
2040214571Sdim  nop_inst.relax_size = 4;
2041214571Sdim  nop_inst.type = NO16_OPD;
2042214571Sdim
2043214571Sdim  pflush_inst.instruction = 0x8000800a;
2044214571Sdim  pflush_inst.size = 4;
2045214571Sdim  pflush_inst.relax_inst = 0x8000;
2046214571Sdim  pflush_inst.relax_size = 0;
2047214571Sdim  pflush_inst.type = NO_OPD;
2048214571Sdim
2049214571Sdim  /* pflush will clear all data dependency.  */
2050214571Sdim  if (strcmp (theinst->name, "pflush") == 0)
2051214571Sdim    {
2052214571Sdim      init_dependency_vector ();
2053214571Sdim      return;
2054214571Sdim    }
2055214571Sdim
2056214571Sdim  /* Push current instruction to dependency_vector[0].  */
2057214571Sdim  for (i = vector_size - 1; i > 0; i--)
2058214571Sdim    memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
2059214571Sdim
2060214571Sdim  memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
2061214571Sdim
2062214571Sdim  /* There is no dependency between nop and any instruction.  */
2063214571Sdim  if (strcmp (dependency_vector[0].name, "nop") == 0
2064214571Sdim      || strcmp (dependency_vector[0].name, "nop!") == 0)
2065214571Sdim    return;
2066214571Sdim
2067214571Sdim  /* "pce" is defined in insn_to_dependency_table.  */
2068214571Sdim#define PCE_NAME "pce"
2069214571Sdim
2070214571Sdim  if (dependency_vector[0].type == Insn_Type_PCE)
2071214571Sdim    strcpy (cur_insn, PCE_NAME);
2072214571Sdim  else
2073214571Sdim    strcpy (cur_insn, dependency_vector[0].name);
2074214571Sdim
2075214571Sdim  for (i = 1; i < vector_size; i++)
2076214571Sdim    {
2077214571Sdim      /* The element of dependency_vector is NULL.  */
2078214571Sdim      if (dependency_vector[i].name[0] == '\0')
2079214571Sdim	continue;
2080214571Sdim
2081214571Sdim      if (dependency_vector[i].type == Insn_Type_PCE)
2082214571Sdim	strcpy (pre_insn, PCE_NAME);
2083214571Sdim      else
2084214571Sdim	strcpy (pre_insn, dependency_vector[i].name);
2085214571Sdim
2086214571Sdim      bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
2087214571Sdim                                  cur_insn, dependency_vector[0].reg, &warn_or_error);
2088214571Sdim      remainder_bubbles = bubbles - i + 1;
2089214571Sdim
2090214571Sdim      if (remainder_bubbles > 0)
2091214571Sdim        {
2092214571Sdim          int j;
2093214571Sdim
2094214571Sdim          if (fix_data_dependency == 1)
2095214571Sdim            {
2096214571Sdim	      if (remainder_bubbles <= 2)
2097214571Sdim		{
2098214571Sdim		  if (warn_fix_data_dependency)
2099214571Sdim		    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert %d nop!/%d)"),
2100214571Sdim			     dependency_vector[i].name, dependency_vector[i].reg,
2101214571Sdim			     dependency_vector[0].name, dependency_vector[0].reg,
2102214571Sdim			     remainder_bubbles, bubbles);
2103214571Sdim
2104214571Sdim                  for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
2105214571Sdim		    memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
2106214571Sdim			    sizeof (dependency_vector[j]));
2107214571Sdim
2108214571Sdim                  for (j = 1; j <= remainder_bubbles; j++)
2109214571Sdim                    {
2110214571Sdim                      memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2111214571Sdim		      /* Insert nop!.  */
2112214571Sdim    		      build_one_frag (nop_inst);
2113214571Sdim                    }
2114214571Sdim		}
2115214571Sdim	      else
2116214571Sdim		{
2117214571Sdim		  if (warn_fix_data_dependency)
2118214571Sdim		    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert 1 pflush/%d)"),
2119214571Sdim			     dependency_vector[i].name, dependency_vector[i].reg,
2120214571Sdim			     dependency_vector[0].name, dependency_vector[0].reg,
2121214571Sdim			     bubbles);
2122214571Sdim
2123214571Sdim                  for (j = 1; j < vector_size; j++)
2124214571Sdim		    memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2125214571Sdim
2126214571Sdim                  /* Insert pflush.  */
2127214571Sdim                  build_one_frag (pflush_inst);
2128214571Sdim		}
2129214571Sdim            }
2130214571Sdim          else
2131214571Sdim            {
2132214571Sdim	      if (warn_or_error)
2133214571Sdim		{
2134214571Sdim                  as_bad (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
2135214571Sdim                           dependency_vector[i].name, dependency_vector[i].reg,
2136214571Sdim                           dependency_vector[0].name, dependency_vector[0].reg,
2137214571Sdim                           remainder_bubbles, bubbles);
2138214571Sdim		}
2139214571Sdim	      else
2140214571Sdim		{
2141214571Sdim                  as_warn (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
2142214571Sdim                           dependency_vector[i].name, dependency_vector[i].reg,
2143214571Sdim                           dependency_vector[0].name, dependency_vector[0].reg,
2144214571Sdim                           remainder_bubbles, bubbles);
2145214571Sdim		}
2146214571Sdim            }
2147214571Sdim        }
2148214571Sdim    }
2149214571Sdim}
2150214571Sdim
2151214571Sdimstatic enum insn_class
2152214571Sdimget_insn_class_from_type (enum score_insn_type type)
2153214571Sdim{
2154214571Sdim  enum insn_class retval = (int) FAIL;
2155214571Sdim
2156214571Sdim  switch (type)
2157214571Sdim    {
2158214571Sdim    case Rd_I4:
2159214571Sdim    case Rd_I5:
2160214571Sdim    case Rd_rvalueBP_I5:
2161214571Sdim    case Rd_lvalueBP_I5:
2162214571Sdim    case Rd_I8:
2163214571Sdim    case PC_DISP8div2:
2164214571Sdim    case PC_DISP11div2:
2165214571Sdim    case Rd_Rs:
2166214571Sdim    case Rd_HighRs:
2167214571Sdim    case Rd_lvalueRs:
2168214571Sdim    case Rd_rvalueRs:
2169214571Sdim    case x_Rs:
2170214571Sdim    case Rd_LowRs:
2171214571Sdim    case NO16_OPD:
2172214571Sdim      retval = INSN_CLASS_16;
2173214571Sdim      break;
2174214571Sdim    case Rd_Rs_I5:
2175214571Sdim    case x_Rs_I5:
2176214571Sdim    case x_I5_x:
2177214571Sdim    case Rd_Rs_I14:
2178214571Sdim    case I15:
2179214571Sdim    case Rd_I16:
2180214571Sdim    case Rd_SI16:
2181214571Sdim    case Rd_rvalueRs_SI10:
2182214571Sdim    case Rd_lvalueRs_SI10:
2183214571Sdim    case Rd_rvalueRs_preSI12:
2184214571Sdim    case Rd_rvalueRs_postSI12:
2185214571Sdim    case Rd_lvalueRs_preSI12:
2186214571Sdim    case Rd_lvalueRs_postSI12:
2187214571Sdim    case Rd_Rs_SI14:
2188214571Sdim    case Rd_rvalueRs_SI15:
2189214571Sdim    case Rd_lvalueRs_SI15:
2190214571Sdim    case PC_DISP19div2:
2191214571Sdim    case PC_DISP24div2:
2192214571Sdim    case Rd_Rs_Rs:
2193214571Sdim    case x_Rs_x:
2194214571Sdim    case x_Rs_Rs:
2195214571Sdim    case Rd_Rs_x:
2196214571Sdim    case Rd_x_Rs:
2197214571Sdim    case Rd_x_x:
2198214571Sdim    case OP5_rvalueRs_SI15:
2199214571Sdim    case I5_Rs_Rs_I5_OP5:
2200214571Sdim    case x_rvalueRs_post4:
2201214571Sdim    case Rd_rvalueRs_post4:
2202214571Sdim    case Rd_x_I5:
2203214571Sdim    case Rd_lvalueRs_post4:
2204214571Sdim    case x_lvalueRs_post4:
2205214571Sdim    case Rd_Rs_Rs_imm:
2206214571Sdim    case NO_OPD:
2207214571Sdim    case Rd_lvalue32Rs:
2208214571Sdim    case Rd_rvalue32Rs:
2209214571Sdim    case Insn_GP:
2210214571Sdim    case Insn_PIC:
2211214571Sdim    case Insn_internal:
2212214571Sdim      retval = INSN_CLASS_32;
2213214571Sdim      break;
2214214571Sdim    case Insn_Type_PCE:
2215214571Sdim      retval = INSN_CLASS_PCE;
2216214571Sdim      break;
2217214571Sdim    case Insn_Type_SYN:
2218214571Sdim      retval = INSN_CLASS_SYN;
2219214571Sdim      break;
2220214571Sdim    default:
2221214571Sdim      abort ();
2222214571Sdim      break;
2223214571Sdim    }
2224214571Sdim  return retval;
2225214571Sdim}
2226214571Sdim
2227214571Sdimstatic unsigned long
2228214571Sdimadjust_paritybit (unsigned long m_code, enum insn_class class)
2229214571Sdim{
2230214571Sdim  unsigned long result = 0;
2231214571Sdim  unsigned long m_code_high = 0;
2232214571Sdim  unsigned long m_code_low = 0;
2233214571Sdim  unsigned long pb_high = 0;
2234214571Sdim  unsigned long pb_low = 0;
2235214571Sdim
2236214571Sdim  if (class == INSN_CLASS_32)
2237214571Sdim    {
2238214571Sdim      pb_high = 0x80000000;
2239214571Sdim      pb_low = 0x00008000;
2240214571Sdim    }
2241214571Sdim  else if (class == INSN_CLASS_16)
2242214571Sdim    {
2243214571Sdim      pb_high = 0;
2244214571Sdim      pb_low = 0;
2245214571Sdim    }
2246214571Sdim  else if (class == INSN_CLASS_PCE)
2247214571Sdim    {
2248214571Sdim      pb_high = 0;
2249214571Sdim      pb_low = 0x00008000;
2250214571Sdim    }
2251214571Sdim  else if (class == INSN_CLASS_SYN)
2252214571Sdim    {
2253214571Sdim      /* FIXME.  at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2254214571Sdim         be changed if macro instruction has been expanded.  */
2255214571Sdim      pb_high = 0x80000000;
2256214571Sdim      pb_low = 0x00008000;
2257214571Sdim    }
2258214571Sdim  else
2259214571Sdim    {
2260214571Sdim      abort ();
2261214571Sdim    }
2262214571Sdim
2263214571Sdim  m_code_high = m_code & 0x3fff8000;
2264214571Sdim  m_code_low = m_code & 0x00007fff;
2265214571Sdim  result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2266214571Sdim  return result;
2267214571Sdim
2268214571Sdim}
2269214571Sdim
2270214571Sdimstatic void
2271214571Sdimgen_insn_frag (struct score_it *part_1, struct score_it *part_2)
2272214571Sdim{
2273214571Sdim  char *p;
2274214571Sdim  bfd_boolean pce_p = FALSE;
2275214571Sdim  int relaxable_p = g_opt;
2276214571Sdim  int relax_size = 0;
2277214571Sdim  struct score_it *inst1 = part_1;
2278214571Sdim  struct score_it *inst2 = part_2;
2279214571Sdim  struct score_it backup_inst1;
2280214571Sdim
2281214571Sdim  pce_p = (inst2) ? TRUE : FALSE;
2282214571Sdim  memcpy (&backup_inst1, inst1, sizeof (struct score_it));
2283214571Sdim
2284214571Sdim  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
2285214571Sdim  if (pce_p)
2286214571Sdim    {
2287214571Sdim      backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2288214571Sdim                                  | (inst2->instruction & 0x7FFF);
2289214571Sdim      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2290214571Sdim      backup_inst1.relax_inst = 0x8000;
2291214571Sdim      backup_inst1.size = INSN_SIZE;
2292214571Sdim      backup_inst1.relax_size = 0;
2293214571Sdim      backup_inst1.type = Insn_Type_PCE;
2294214571Sdim    }
2295214571Sdim  else
2296214571Sdim    {
2297214571Sdim      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
2298214571Sdim						   GET_INSN_CLASS (backup_inst1.type));
2299214571Sdim    }
2300214571Sdim
2301214571Sdim  if (backup_inst1.relax_size != 0)
2302214571Sdim    {
2303214571Sdim      enum insn_class tmp;
2304214571Sdim
2305214571Sdim      tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2306214571Sdim      backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
2307214571Sdim    }
2308214571Sdim
2309214571Sdim  /* Check data dependency.  */
2310214571Sdim  handle_dependency (&backup_inst1);
2311214571Sdim
2312214571Sdim  /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2313214571Sdim     data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
2314214571Sdim  if (frag_now_fix () != 0)
2315214571Sdim    {
2316214571Sdim      if (!frag_now->tc_frag_data.is_insn)
2317214571Sdim	frag_wane (frag_now);
2318214571Sdim
2319214571Sdim      frag_new (0);
2320214571Sdim    }
2321214571Sdim
2322214571Sdim  /* Here, we must call frag_grow in order to keep the instruction frag type is
2323214571Sdim     rs_machine_dependent.
2324214571Sdim     For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2325214571Sdim     acturally will call frag_wane.
2326214571Sdim     Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2327214571Sdim     for frag_var.  */
2328214571Sdim  frag_grow (20);
2329214571Sdim
2330214571Sdim  p = frag_more (backup_inst1.size);
2331214571Sdim  md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2332214571Sdim
2333214571Sdim#ifdef OBJ_ELF
2334214571Sdim  dwarf2_emit_insn (backup_inst1.size);
2335214571Sdim#endif
2336214571Sdim
2337214571Sdim  /* Generate fixup structure.  */
2338214571Sdim  if (pce_p)
2339214571Sdim    {
2340214571Sdim      if (inst1->reloc.type != BFD_RELOC_NONE)
2341214571Sdim	fix_new_score (frag_now, p - frag_now->fr_literal,
2342214571Sdim		       inst1->size, &inst1->reloc.exp,
2343214571Sdim		       inst1->reloc.pc_rel, inst1->reloc.type);
2344214571Sdim
2345214571Sdim      if (inst2->reloc.type != BFD_RELOC_NONE)
2346214571Sdim	fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2347214571Sdim		       inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2348214571Sdim    }
2349214571Sdim  else
2350214571Sdim    {
2351214571Sdim      if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2352214571Sdim	fix_new_score (frag_now, p - frag_now->fr_literal,
2353214571Sdim		       backup_inst1.size, &backup_inst1.reloc.exp,
2354214571Sdim		       backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2355214571Sdim    }
2356214571Sdim
2357214571Sdim  /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
2358214571Sdim  relaxable_p &= (backup_inst1.relax_size != 0);
2359214571Sdim  relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2360214571Sdim
2361214571Sdim  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2362214571Sdim                RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2363214571Sdim                              backup_inst1.type, 0, 0, relaxable_p),
2364214571Sdim                backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2365214571Sdim
2366214571Sdim  if (relaxable_p)
2367214571Sdim    md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2368214571Sdim
2369214571Sdim  memcpy (inst1, &backup_inst1, sizeof (struct score_it));
2370214571Sdim}
2371214571Sdim
2372214571Sdimstatic void
2373214571Sdimparse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2374214571Sdim{
2375214571Sdim  char c;
2376214571Sdim  char *p;
2377214571Sdim  char *operator = insnstr;
2378214571Sdim  const struct asm_opcode *opcode;
2379214571Sdim
2380214571Sdim  /* Parse operator and operands.  */
2381214571Sdim  skip_whitespace (operator);
2382214571Sdim
2383214571Sdim  for (p = operator; *p != '\0'; p++)
2384214571Sdim    if ((*p == ' ') || (*p == '!'))
2385214571Sdim      break;
2386214571Sdim
2387214571Sdim  if (*p == '!')
2388214571Sdim    p++;
2389214571Sdim
2390214571Sdim  c = *p;
2391214571Sdim  *p = '\0';
2392214571Sdim
2393214571Sdim  opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
2394214571Sdim  *p = c;
2395214571Sdim
2396214571Sdim  memset (&inst, '\0', sizeof (inst));
2397214571Sdim  sprintf (inst.str, "%s", insnstr);
2398214571Sdim  if (opcode)
2399214571Sdim    {
2400214571Sdim      inst.instruction = opcode->value;
2401214571Sdim      inst.relax_inst = opcode->relax_value;
2402214571Sdim      inst.type = opcode->type;
2403214571Sdim      inst.size = GET_INSN_SIZE (inst.type);
2404214571Sdim      inst.relax_size = 0;
2405214571Sdim      inst.bwarn = 0;
2406214571Sdim      sprintf (inst.name, "%s", opcode->template);
2407214571Sdim      strcpy (inst.reg, "");
2408214571Sdim      inst.error = NULL;
2409214571Sdim      inst.reloc.type = BFD_RELOC_NONE;
2410214571Sdim
2411214571Sdim      (*opcode->parms) (p);
2412214571Sdim
2413214571Sdim      /* It indicates current instruction is a macro instruction if inst.bwarn equals -1.  */
2414214571Sdim      if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
2415214571Sdim	gen_insn_frag (&inst, NULL);
2416214571Sdim    }
2417214571Sdim  else
2418214571Sdim    inst.error = _("unrecognized opcode");
2419214571Sdim}
2420214571Sdim
2421214571Sdimstatic int
2422214571Sdimappend_insn (char *str, bfd_boolean gen_frag_p)
2423214571Sdim{
2424214571Sdim  int retval = SUCCESS;
2425214571Sdim
2426214571Sdim  parse_16_32_inst (str, gen_frag_p);
2427214571Sdim
2428214571Sdim  if (inst.error)
2429214571Sdim    {
2430214571Sdim      retval = (int) FAIL;
2431214571Sdim      as_bad (_("%s -- `%s'"), inst.error, inst.str);
2432214571Sdim      inst.error = NULL;
2433214571Sdim    }
2434214571Sdim
2435214571Sdim  return retval;
2436214571Sdim}
2437214571Sdim
2438214571Sdim/* Handle mv! reg_high, reg_low;
2439214571Sdim          mv! reg_low, reg_high;
2440214571Sdim          mv! reg_low, reg_low;  */
2441214571Sdimstatic void
2442214571Sdimdo16_mv_rdrs (char *str)
2443214571Sdim{
2444214571Sdim  int reg_rd;
2445214571Sdim  int reg_rs;
2446214571Sdim  char *backupstr = NULL;
2447214571Sdim
2448214571Sdim  backupstr = str;
2449214571Sdim  skip_whitespace (str);
2450214571Sdim
2451214571Sdim  if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
2452214571Sdim      || skip_past_comma (&str) == (int) FAIL
2453214571Sdim      || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
2454214571Sdim      || end_of_line (str) == (int) FAIL)
2455214571Sdim    {
2456214571Sdim      return;
2457214571Sdim    }
2458214571Sdim  else
2459214571Sdim    {
2460214571Sdim      /* Case 1 : mv! or mlfh!.  */
2461214571Sdim      if (reg_rd < 16)
2462214571Sdim        {
2463214571Sdim          if (reg_rs < 16)
2464214571Sdim            {
2465214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2466214571Sdim                | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2467214571Sdim              inst.relax_size = 4;
2468214571Sdim            }
2469214571Sdim          else
2470214571Sdim            {
2471214571Sdim              char append_str[MAX_LITERAL_POOL_SIZE];
2472214571Sdim
2473214571Sdim              sprintf (append_str, "mlfh! %s", backupstr);
2474214571Sdim              if (append_insn (append_str, TRUE) == (int) FAIL)
2475214571Sdim		return;
2476214571Sdim              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
2477214571Sdim              inst.bwarn = -1;
2478214571Sdim            }
2479214571Sdim        }
2480214571Sdim      /* Case 2 : mhfl!.  */
2481214571Sdim      else
2482214571Sdim        {
2483214571Sdim          if (reg_rs > 16)
2484214571Sdim            {
2485214571Sdim              SET_INSN_ERROR (BAD_ARGS);
2486214571Sdim              return;
2487214571Sdim            }
2488214571Sdim          else
2489214571Sdim            {
2490214571Sdim              char append_str[MAX_LITERAL_POOL_SIZE];
2491214571Sdim
2492214571Sdim              sprintf (append_str, "mhfl! %s", backupstr);
2493214571Sdim              if (append_insn (append_str, TRUE) == (int) FAIL)
2494214571Sdim		return;
2495214571Sdim
2496214571Sdim              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
2497214571Sdim              inst.bwarn = -1;
2498214571Sdim            }
2499214571Sdim        }
2500214571Sdim    }
2501214571Sdim}
2502214571Sdim
2503214571Sdimstatic void
2504214571Sdimdo16_rdi4 (char *str)
2505214571Sdim{
2506214571Sdim  skip_whitespace (str);
2507214571Sdim
2508214571Sdim  if (reglow_required_here (&str, 8) == (int) FAIL
2509214571Sdim      || skip_past_comma (&str) == (int) FAIL
2510214571Sdim      || data_op2 (&str, 3, _IMM4) == (int) FAIL
2511214571Sdim      || end_of_line (str) == (int) FAIL)
2512214571Sdim    {
2513214571Sdim      return;
2514214571Sdim    }
2515214571Sdim  else
2516214571Sdim    {
2517214571Sdim      if (((inst.instruction >> 3) & 0x10) == 0)        /* for judge is addei or subei : bit 5 =0 : addei */
2518214571Sdim        {
2519214571Sdim          if (((inst.instruction >> 3) & 0xf) != 0xf)
2520214571Sdim            {
2521214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2522214571Sdim                | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
2523214571Sdim              inst.relax_size = 4;
2524214571Sdim            }
2525214571Sdim          else
2526214571Sdim            {
2527214571Sdim              inst.relax_inst = 0x8000;
2528214571Sdim            }
2529214571Sdim        }
2530214571Sdim      else
2531214571Sdim        {
2532214571Sdim          if (((inst.instruction >> 3) & 0xf) != 0xf)
2533214571Sdim            {
2534214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2535214571Sdim                | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2536214571Sdim              inst.relax_size = 4;
2537214571Sdim            }
2538214571Sdim          else
2539214571Sdim            {
2540214571Sdim              inst.relax_inst = 0x8000;
2541214571Sdim            }
2542214571Sdim        }
2543214571Sdim    }
2544214571Sdim}
2545214571Sdim
2546214571Sdimstatic void
2547214571Sdimdo16_rdi5 (char *str)
2548214571Sdim{
2549214571Sdim  skip_whitespace (str);
2550214571Sdim
2551214571Sdim  if (reglow_required_here (&str, 8) == (int) FAIL
2552214571Sdim      || skip_past_comma (&str) == (int) FAIL
2553214571Sdim      || data_op2 (&str, 3, _IMM5) == (int) FAIL
2554214571Sdim      || end_of_line (str) == (int) FAIL)
2555214571Sdim    return;
2556214571Sdim  else
2557214571Sdim    {
2558214571Sdim      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2559214571Sdim        | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
2560214571Sdim      inst.relax_size = 4;
2561214571Sdim    }
2562214571Sdim}
2563214571Sdim
2564214571Sdim/* Handle sdbbp.  */
2565214571Sdimstatic void
2566214571Sdimdo16_xi5 (char *str)
2567214571Sdim{
2568214571Sdim  skip_whitespace (str);
2569214571Sdim
2570214571Sdim  if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
2571214571Sdim    return;
2572214571Sdim  else
2573214571Sdim    {
2574214571Sdim      inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
2575214571Sdim      inst.relax_size = 4;
2576214571Sdim    }
2577214571Sdim}
2578214571Sdim
2579214571Sdim/* Check that an immediate is word alignment or half word alignment.
2580214571Sdim   If so, convert it to the right format.  */
2581214571Sdimstatic int
2582214571Sdimvalidate_immediate_align (int val, unsigned int data_type)
2583214571Sdim{
2584214571Sdim  if (data_type == _IMM5_RSHIFT_1)
2585214571Sdim    {
2586214571Sdim      if (val % 2)
2587214571Sdim        {
2588214571Sdim          inst.error = _("address offset must be half word alignment");
2589214571Sdim          return (int) FAIL;
2590214571Sdim        }
2591214571Sdim    }
2592214571Sdim  else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2593214571Sdim    {
2594214571Sdim      if (val % 4)
2595214571Sdim        {
2596214571Sdim          inst.error = _("address offset must be word alignment");
2597214571Sdim          return (int) FAIL;
2598214571Sdim        }
2599214571Sdim    }
2600214571Sdim
2601214571Sdim  return SUCCESS;
2602214571Sdim}
2603214571Sdim
2604214571Sdimstatic int
2605214571Sdimexp_ldst_offset (char **str, int shift, unsigned int data_type)
2606214571Sdim{
2607214571Sdim  char *dataptr;
2608214571Sdim
2609214571Sdim  dataptr = * str;
2610214571Sdim
2611214571Sdim  if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2612214571Sdim      && (data_type != _SIMM16_LA)
2613214571Sdim      && (data_type != _VALUE_HI16)
2614214571Sdim      && (data_type != _VALUE_LO16)
2615214571Sdim      && (data_type != _IMM16)
2616214571Sdim      && (data_type != _IMM15)
2617214571Sdim      && (data_type != _IMM14)
2618214571Sdim      && (data_type != _IMM4)
2619214571Sdim      && (data_type != _IMM5)
2620214571Sdim      && (data_type != _IMM8)
2621214571Sdim      && (data_type != _IMM5_RSHIFT_1)
2622214571Sdim      && (data_type != _IMM5_RSHIFT_2)
2623214571Sdim      && (data_type != _SIMM14_NEG)
2624214571Sdim      && (data_type != _IMM10_RSHIFT_2))
2625214571Sdim    {
2626214571Sdim      data_type += 24;
2627214571Sdim    }
2628214571Sdim
2629214571Sdim  if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
2630214571Sdim    return (int) FAIL;
2631214571Sdim
2632214571Sdim  if (inst.reloc.exp.X_op == O_constant)
2633214571Sdim    {
2634214571Sdim      /* Need to check the immediate align.  */
2635214571Sdim      int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
2636214571Sdim
2637214571Sdim      if (value == (int) FAIL)
2638214571Sdim	return (int) FAIL;
2639214571Sdim
2640214571Sdim      value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
2641214571Sdim      if (value == (int) FAIL)
2642214571Sdim        {
2643214571Sdim          if (data_type < 30)
2644214571Sdim            sprintf (err_msg,
2645214571Sdim                     _("invalid constant: %d bit expression not in range %d..%d"),
2646214571Sdim                     score_df_range[data_type].bits,
2647214571Sdim                     score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2648214571Sdim          else
2649214571Sdim            sprintf (err_msg,
2650214571Sdim                     _("invalid constant: %d bit expression not in range %d..%d"),
2651214571Sdim                     score_df_range[data_type - 24].bits,
2652214571Sdim                     score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
2653214571Sdim          inst.error = err_msg;
2654214571Sdim          return (int) FAIL;
2655214571Sdim        }
2656214571Sdim
2657214571Sdim      if (data_type == _IMM5_RSHIFT_1)
2658214571Sdim        {
2659214571Sdim          value >>= 1;
2660214571Sdim        }
2661214571Sdim      else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2662214571Sdim        {
2663214571Sdim          value >>= 2;
2664214571Sdim        }
2665214571Sdim
2666214571Sdim      if (score_df_range[data_type].range[0] != 0)
2667214571Sdim        {
2668214571Sdim          value &= (1 << score_df_range[data_type].bits) - 1;
2669214571Sdim        }
2670214571Sdim
2671214571Sdim      inst.instruction |= value << shift;
2672214571Sdim    }
2673214571Sdim  else
2674214571Sdim    {
2675214571Sdim      inst.reloc.pc_rel = 0;
2676214571Sdim    }
2677214571Sdim
2678214571Sdim  return SUCCESS;
2679214571Sdim}
2680214571Sdim
2681214571Sdimstatic void
2682214571Sdimdo_ldst_insn (char *str)
2683214571Sdim{
2684214571Sdim  int pre_inc = 0;
2685214571Sdim  int conflict_reg;
2686214571Sdim  int value;
2687214571Sdim  char * temp;
2688214571Sdim  char *strbak;
2689214571Sdim  char *dataptr;
2690214571Sdim  int reg;
2691214571Sdim  int ldst_idx = 0;
2692214571Sdim
2693214571Sdim  strbak = str;
2694214571Sdim  skip_whitespace (str);
2695214571Sdim
2696214571Sdim  if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
2697214571Sdim      || (skip_past_comma (&str) == (int) FAIL))
2698214571Sdim    return;
2699214571Sdim
2700214571Sdim  /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
2701214571Sdim  if (*str == '[')
2702214571Sdim    {
2703214571Sdim      str++;
2704214571Sdim      skip_whitespace (str);
2705214571Sdim
2706214571Sdim      if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
2707214571Sdim	return;
2708214571Sdim
2709214571Sdim      /* Conflicts can occur on stores as well as loads.  */
2710214571Sdim      conflict_reg = (conflict_reg == reg);
2711214571Sdim      skip_whitespace (str);
2712214571Sdim      temp = str + 1;    /* The latter will process decimal/hex expression.  */
2713214571Sdim
2714214571Sdim      /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
2715214571Sdim      if (*str == ']')
2716214571Sdim        {
2717214571Sdim          str++;
2718214571Sdim          if (*str == '+')
2719214571Sdim            {
2720214571Sdim              str++;
2721214571Sdim              /* ld/sw rD, [rA]+, simm12.  */
2722214571Sdim              if (skip_past_comma (&str) == SUCCESS)
2723214571Sdim                {
2724214571Sdim                  if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
2725214571Sdim                      || (end_of_line (str) == (int) FAIL))
2726214571Sdim		    return;
2727214571Sdim
2728214571Sdim                  if (conflict_reg)
2729214571Sdim                    {
2730214571Sdim                      unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2731214571Sdim
2732214571Sdim                      if ((ldst_func == INSN_LH)
2733214571Sdim                          || (ldst_func == INSN_LHU)
2734214571Sdim                          || (ldst_func == INSN_LW)
2735214571Sdim                          || (ldst_func == INSN_LB)
2736214571Sdim                          || (ldst_func == INSN_LBU))
2737214571Sdim                        {
2738214571Sdim                          inst.error = _("register same as write-back base");
2739214571Sdim                          return;
2740214571Sdim                        }
2741214571Sdim                    }
2742214571Sdim
2743214571Sdim                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2744214571Sdim                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2745214571Sdim                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2746214571Sdim
2747214571Sdim                  /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
2748214571Sdim                  if ((inst.instruction & 0x3e000007) == 0x0e000000)
2749214571Sdim                    {
2750214571Sdim                      /* rs =  r0-r7, offset = 4 */
2751214571Sdim                      if ((((inst.instruction >> 15) & 0x18) == 0)
2752214571Sdim                          && (((inst.instruction >> 3) & 0xfff) == 4))
2753214571Sdim                        {
2754214571Sdim                          /* Relax to pophi.  */
2755214571Sdim                          if ((((inst.instruction >> 20) & 0x10) == 0x10))
2756214571Sdim                            {
2757214571Sdim                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2758214571Sdim                                                              << 8) | 1 << 7 |
2759214571Sdim                                (((inst.instruction >> 15) & 0x7) << 4);
2760214571Sdim                            }
2761214571Sdim                          /* Relax to pop.  */
2762214571Sdim                          else
2763214571Sdim                            {
2764214571Sdim                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2765214571Sdim                                                              << 8) | 0 << 7 |
2766214571Sdim                                (((inst.instruction >> 15) & 0x7) << 4);
2767214571Sdim                            }
2768214571Sdim                          inst.relax_size = 2;
2769214571Sdim                        }
2770214571Sdim                    }
2771214571Sdim                  return;
2772214571Sdim                }
2773214571Sdim              /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
2774214571Sdim              else
2775214571Sdim                {
2776214571Sdim                  SET_INSN_ERROR (NULL);
2777214571Sdim                  if (end_of_line (str) == (int) FAIL)
2778214571Sdim                    {
2779214571Sdim                      return;
2780214571Sdim                    }
2781214571Sdim
2782214571Sdim                  pre_inc = 1;
2783214571Sdim                  value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0);
2784214571Sdim                  value &= (1 << score_df_range[_SIMM12].bits) - 1;
2785214571Sdim                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2786214571Sdim                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2787214571Sdim                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2788214571Sdim                  inst.instruction |= value << 3;
2789214571Sdim                  inst.relax_inst = 0x8000;
2790214571Sdim                  return;
2791214571Sdim                }
2792214571Sdim            }
2793214571Sdim          /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
2794214571Sdim          else
2795214571Sdim            {
2796214571Sdim              if (end_of_line (str) == (int) FAIL)
2797214571Sdim		return;
2798214571Sdim
2799214571Sdim              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2800214571Sdim              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2801214571Sdim              inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
2802214571Sdim
2803214571Sdim              /* lbu rd, [rs] -> lbu! rd, [rs]  */
2804214571Sdim              if (ldst_idx == INSN_LBU)
2805214571Sdim                {
2806214571Sdim                  inst.relax_inst = INSN16_LBU;
2807214571Sdim                }
2808214571Sdim              else if (ldst_idx == INSN_LH)
2809214571Sdim                {
2810214571Sdim                  inst.relax_inst = INSN16_LH;
2811214571Sdim                }
2812214571Sdim              else if (ldst_idx == INSN_LW)
2813214571Sdim                {
2814214571Sdim                  inst.relax_inst = INSN16_LW;
2815214571Sdim                }
2816214571Sdim              else if (ldst_idx == INSN_SB)
2817214571Sdim                {
2818214571Sdim                  inst.relax_inst = INSN16_SB;
2819214571Sdim                }
2820214571Sdim              else if (ldst_idx == INSN_SH)
2821214571Sdim                {
2822214571Sdim                  inst.relax_inst = INSN16_SH;
2823214571Sdim                }
2824214571Sdim              else if (ldst_idx == INSN_SW)
2825214571Sdim                {
2826214571Sdim                  inst.relax_inst = INSN16_SW;
2827214571Sdim                }
2828214571Sdim              else
2829214571Sdim                {
2830214571Sdim                  inst.relax_inst = 0x8000;
2831214571Sdim                }
2832214571Sdim
2833214571Sdim              /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
2834214571Sdim              if ((ldst_idx == INSN_LBU)
2835214571Sdim                  || (ldst_idx == INSN_LH)
2836214571Sdim                  || (ldst_idx == INSN_LW)
2837214571Sdim                  || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
2838214571Sdim                {
2839214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2840214571Sdim                    {
2841214571Sdim                      inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
2842214571Sdim                        (((inst.instruction >> 15) & 0xf) << 4);
2843214571Sdim                      inst.relax_size = 2;
2844214571Sdim                    }
2845214571Sdim                }
2846214571Sdim
2847214571Sdim              return;
2848214571Sdim            }
2849214571Sdim        }
2850214571Sdim      /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
2851214571Sdim      else
2852214571Sdim        {
2853214571Sdim          if (skip_past_comma (&str) == (int) FAIL)
2854214571Sdim            {
2855214571Sdim              inst.error = _("pre-indexed expression expected");
2856214571Sdim              return;
2857214571Sdim            }
2858214571Sdim
2859214571Sdim          if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
2860214571Sdim	    return;
2861214571Sdim
2862214571Sdim          skip_whitespace (str);
2863214571Sdim          if (*str++ != ']')
2864214571Sdim            {
2865214571Sdim              inst.error = _("missing ]");
2866214571Sdim              return;
2867214571Sdim            }
2868214571Sdim
2869214571Sdim          skip_whitespace (str);
2870214571Sdim          /* ld/sw rD, [rA, simm12]+.  */
2871214571Sdim          if (*str == '+')
2872214571Sdim            {
2873214571Sdim              str++;
2874214571Sdim              pre_inc = 1;
2875214571Sdim              if (conflict_reg)
2876214571Sdim                {
2877214571Sdim                  unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2878214571Sdim
2879214571Sdim                  if ((ldst_func == INSN_LH)
2880214571Sdim                      || (ldst_func == INSN_LHU)
2881214571Sdim                      || (ldst_func == INSN_LW)
2882214571Sdim                      || (ldst_func == INSN_LB)
2883214571Sdim                      || (ldst_func == INSN_LBU))
2884214571Sdim                    {
2885214571Sdim                      inst.error = _("register same as write-back base");
2886214571Sdim                      return;
2887214571Sdim                    }
2888214571Sdim                }
2889214571Sdim            }
2890214571Sdim
2891214571Sdim          if (end_of_line (str) == (int) FAIL)
2892214571Sdim	    return;
2893214571Sdim
2894214571Sdim          if (inst.reloc.exp.X_op == O_constant)
2895214571Sdim            {
2896214571Sdim              int value;
2897214571Sdim              unsigned int data_type;
2898214571Sdim
2899214571Sdim              if (pre_inc == 1)
2900214571Sdim                data_type = _SIMM12;
2901214571Sdim              else
2902214571Sdim                data_type = _SIMM15;
2903214571Sdim              dataptr = temp;
2904214571Sdim
2905214571Sdim              if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2906214571Sdim                  && (data_type != _SIMM16_LA)
2907214571Sdim                  && (data_type != _VALUE_HI16)
2908214571Sdim                  && (data_type != _VALUE_LO16)
2909214571Sdim                  && (data_type != _IMM16)
2910214571Sdim                  && (data_type != _IMM15)
2911214571Sdim                  && (data_type != _IMM14)
2912214571Sdim                  && (data_type != _IMM4)
2913214571Sdim                  && (data_type != _IMM5)
2914214571Sdim                  && (data_type != _IMM8)
2915214571Sdim                  && (data_type != _IMM5_RSHIFT_1)
2916214571Sdim                  && (data_type != _IMM5_RSHIFT_2)
2917214571Sdim                  && (data_type != _SIMM14_NEG)
2918214571Sdim                  && (data_type != _IMM10_RSHIFT_2))
2919214571Sdim                {
2920214571Sdim                  data_type += 24;
2921214571Sdim                }
2922214571Sdim
2923214571Sdim              value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
2924214571Sdim              if (value == (int) FAIL)
2925214571Sdim                {
2926214571Sdim                  if (data_type < 30)
2927214571Sdim                    sprintf (err_msg,
2928214571Sdim                             _("invalid constant: %d bit expression not in range %d..%d"),
2929214571Sdim                             score_df_range[data_type].bits,
2930214571Sdim                             score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2931214571Sdim                  else
2932214571Sdim                    sprintf (err_msg,
2933214571Sdim                             _("invalid constant: %d bit expression not in range %d..%d"),
2934214571Sdim                             score_df_range[data_type - 24].bits,
2935214571Sdim                             score_df_range[data_type - 24].range[0],
2936214571Sdim                             score_df_range[data_type - 24].range[1]);
2937214571Sdim                  inst.error = err_msg;
2938214571Sdim                  return;
2939214571Sdim                }
2940214571Sdim
2941214571Sdim              value &= (1 << score_df_range[data_type].bits) - 1;
2942214571Sdim              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2943214571Sdim              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2944214571Sdim              inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2945214571Sdim              if (pre_inc == 1)
2946214571Sdim                inst.instruction |= value << 3;
2947214571Sdim              else
2948214571Sdim                inst.instruction |= value;
2949214571Sdim
2950214571Sdim              /* lw rD, [rA, simm15]  */
2951214571Sdim              if ((inst.instruction & 0x3e000000) == 0x20000000)
2952214571Sdim                {
2953214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
2954214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0)
2955214571Sdim                      && (((inst.instruction >> 20) & 0x10) == 0))
2956214571Sdim                    {
2957214571Sdim                      /* simm15 = 0, lw -> lw!.  */
2958214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
2959214571Sdim                        {
2960214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2961214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
2962214571Sdim                          inst.relax_size = 2;
2963214571Sdim                        }
2964214571Sdim                      /* rA = r2, lw -> lwp!.  */
2965214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
2966214571Sdim                               && ((inst.instruction & 0x3) == 0)
2967214571Sdim                               && ((inst.instruction & 0x7fff) < 128))
2968214571Sdim                        {
2969214571Sdim                          inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
2970214571Sdim                            | (((inst.instruction & 0x7fff) >> 2) << 3);
2971214571Sdim                          inst.relax_size = 2;
2972214571Sdim                        }
2973214571Sdim                      else
2974214571Sdim                        {
2975214571Sdim                          inst.relax_inst = 0x8000;
2976214571Sdim                        }
2977214571Sdim                    }
2978214571Sdim                  else
2979214571Sdim                    {
2980214571Sdim                      inst.relax_inst = 0x8000;
2981214571Sdim                    }
2982214571Sdim                }
2983214571Sdim              /* sw rD, [rA, simm15]  */
2984214571Sdim              else if ((inst.instruction & 0x3e000000) == 0x28000000)
2985214571Sdim                {
2986214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
2987214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2988214571Sdim                    {
2989214571Sdim                      /* simm15 = 0, sw -> sw!.  */
2990214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
2991214571Sdim                        {
2992214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2993214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
2994214571Sdim                          inst.relax_size = 2;
2995214571Sdim                        }
2996214571Sdim                      /* rA = r2, sw -> swp!.  */
2997214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
2998214571Sdim                               && ((inst.instruction & 0x3) == 0)
2999214571Sdim                               && ((inst.instruction & 0x7fff) < 128))
3000214571Sdim                        {
3001214571Sdim                          inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
3002214571Sdim                            | (((inst.instruction & 0x7fff) >> 2) << 3);
3003214571Sdim                          inst.relax_size = 2;
3004214571Sdim                        }
3005214571Sdim                      else
3006214571Sdim                        {
3007214571Sdim                          inst.relax_inst = 0x8000;
3008214571Sdim                        }
3009214571Sdim                    }
3010214571Sdim                  else
3011214571Sdim                    {
3012214571Sdim                      inst.relax_inst = 0x8000;
3013214571Sdim                    }
3014214571Sdim                }
3015214571Sdim              /* sw rD, [rA, simm15]+    sw pre.  */
3016214571Sdim              else if ((inst.instruction & 0x3e000007) == 0x06000004)
3017214571Sdim                {
3018214571Sdim                  /* rA is in [r0 - r7], and simm15 = -4.  */
3019214571Sdim                  if ((((inst.instruction >> 15) & 0x18) == 0)
3020214571Sdim                      && (((inst.instruction >> 3) & 0xfff) == 0xffc))
3021214571Sdim                    {
3022214571Sdim                      /* sw -> pushhi!.  */
3023214571Sdim                      if ((((inst.instruction >> 20) & 0x10) == 0x10))
3024214571Sdim                        {
3025214571Sdim                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3026214571Sdim                            | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3027214571Sdim                          inst.relax_size = 2;
3028214571Sdim                        }
3029214571Sdim                      /* sw -> push!.  */
3030214571Sdim                      else
3031214571Sdim                        {
3032214571Sdim                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3033214571Sdim                            | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3034214571Sdim                          inst.relax_size = 2;
3035214571Sdim                        }
3036214571Sdim                    }
3037214571Sdim                  else
3038214571Sdim                    {
3039214571Sdim                      inst.relax_inst = 0x8000;
3040214571Sdim                    }
3041214571Sdim                }
3042214571Sdim              /* lh rD, [rA, simm15]  */
3043214571Sdim              else if ((inst.instruction & 0x3e000000) == 0x22000000)
3044214571Sdim                {
3045214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
3046214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3047214571Sdim                    {
3048214571Sdim                      /* simm15 = 0, lh -> lh!.  */
3049214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
3050214571Sdim                        {
3051214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3052214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
3053214571Sdim                          inst.relax_size = 2;
3054214571Sdim                        }
3055214571Sdim                      /* rA = r2, lh -> lhp!.  */
3056214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
3057214571Sdim                               && ((inst.instruction & 0x1) == 0)
3058214571Sdim                               && ((inst.instruction & 0x7fff) < 64))
3059214571Sdim                        {
3060214571Sdim                          inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
3061214571Sdim                            | (((inst.instruction & 0x7fff) >> 1) << 3);
3062214571Sdim                          inst.relax_size = 2;
3063214571Sdim                        }
3064214571Sdim                      else
3065214571Sdim                        {
3066214571Sdim                          inst.relax_inst = 0x8000;
3067214571Sdim                        }
3068214571Sdim                    }
3069214571Sdim                  else
3070214571Sdim                    {
3071214571Sdim                      inst.relax_inst = 0x8000;
3072214571Sdim                    }
3073214571Sdim                }
3074214571Sdim              /* sh rD, [rA, simm15]  */
3075214571Sdim              else if ((inst.instruction & 0x3e000000) == 0x2a000000)
3076214571Sdim                {
3077214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
3078214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3079214571Sdim                    {
3080214571Sdim                      /* simm15 = 0, sh -> sh!.  */
3081214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
3082214571Sdim                        {
3083214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3084214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
3085214571Sdim                          inst.relax_size = 2;
3086214571Sdim                        }
3087214571Sdim                      /* rA = r2, sh -> shp!.  */
3088214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
3089214571Sdim                               && ((inst.instruction & 0x1) == 0)
3090214571Sdim                               && ((inst.instruction & 0x7fff) < 64))
3091214571Sdim                        {
3092214571Sdim                          inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
3093214571Sdim                            | (((inst.instruction & 0x7fff) >> 1) << 3);
3094214571Sdim                          inst.relax_size = 2;
3095214571Sdim                        }
3096214571Sdim                      else
3097214571Sdim                        {
3098214571Sdim                          inst.relax_inst = 0x8000;
3099214571Sdim                        }
3100214571Sdim                    }
3101214571Sdim                  else
3102214571Sdim                    {
3103214571Sdim                      inst.relax_inst = 0x8000;
3104214571Sdim                    }
3105214571Sdim                }
3106214571Sdim              /* lbu rD, [rA, simm15]  */
3107214571Sdim              else if ((inst.instruction & 0x3e000000) == 0x2c000000)
3108214571Sdim                {
3109214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
3110214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3111214571Sdim                    {
3112214571Sdim                      /* simm15 = 0, lbu -> lbu!.  */
3113214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
3114214571Sdim                        {
3115214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3116214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
3117214571Sdim                          inst.relax_size = 2;
3118214571Sdim                        }
3119214571Sdim                      /* rA = r2, lbu -> lbup!.  */
3120214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
3121214571Sdim                               && ((inst.instruction & 0x7fff) < 32))
3122214571Sdim                        {
3123214571Sdim                          inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
3124214571Sdim                            | ((inst.instruction & 0x7fff) << 3);
3125214571Sdim                          inst.relax_size = 2;
3126214571Sdim                        }
3127214571Sdim                      else
3128214571Sdim                        {
3129214571Sdim                          inst.relax_inst = 0x8000;
3130214571Sdim                        }
3131214571Sdim                    }
3132214571Sdim                  else
3133214571Sdim                    {
3134214571Sdim                      inst.relax_inst = 0x8000;
3135214571Sdim                    }
3136214571Sdim                }
3137214571Sdim              /* sb rD, [rA, simm15]  */
3138214571Sdim              else if ((inst.instruction & 0x3e000000) == 0x2e000000)
3139214571Sdim                {
3140214571Sdim                  /* Both rD and rA are in [r0 - r15].  */
3141214571Sdim                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3142214571Sdim                    {
3143214571Sdim                      /* simm15 = 0, sb -> sb!.  */
3144214571Sdim                      if ((inst.instruction & 0x7fff) == 0)
3145214571Sdim                        {
3146214571Sdim                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3147214571Sdim                            | (((inst.instruction >> 20) & 0xf) << 8);
3148214571Sdim                          inst.relax_size = 2;
3149214571Sdim                        }
3150214571Sdim                      /* rA = r2, sb -> sb!.  */
3151214571Sdim                      else if ((((inst.instruction >> 15) & 0xf) == 2)
3152214571Sdim                               && ((inst.instruction & 0x7fff) < 32))
3153214571Sdim                        {
3154214571Sdim                          inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
3155214571Sdim                            | ((inst.instruction & 0x7fff) << 3);
3156214571Sdim                          inst.relax_size = 2;
3157214571Sdim                        }
3158214571Sdim                      else
3159214571Sdim                        {
3160214571Sdim                          inst.relax_inst = 0x8000;
3161214571Sdim                        }
3162214571Sdim                    }
3163214571Sdim                  else
3164214571Sdim                    {
3165214571Sdim                      inst.relax_inst = 0x8000;
3166214571Sdim                    }
3167214571Sdim                }
3168214571Sdim              else
3169214571Sdim                {
3170214571Sdim                  inst.relax_inst = 0x8000;
3171214571Sdim                }
3172214571Sdim
3173214571Sdim              return;
3174214571Sdim            }
3175214571Sdim          else
3176214571Sdim            {
3177214571Sdim              /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3178214571Sdim              inst.reloc.pc_rel = 0;
3179214571Sdim            }
3180214571Sdim        }
3181214571Sdim    }
3182214571Sdim  else
3183214571Sdim    {
3184214571Sdim      inst.error = BAD_ARGS;
3185214571Sdim    }
3186214571Sdim}
3187214571Sdim
3188214571Sdim/* Handle cache.  */
3189214571Sdim
3190214571Sdimstatic void
3191214571Sdimdo_cache (char *str)
3192214571Sdim{
3193214571Sdim  skip_whitespace (str);
3194214571Sdim
3195214571Sdim  if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3196214571Sdim    {
3197214571Sdim      return;
3198214571Sdim    }
3199214571Sdim  else
3200214571Sdim    {
3201214571Sdim      int cache_op;
3202214571Sdim
3203214571Sdim      cache_op = (inst.instruction >> 20) & 0x1F;
3204214571Sdim      sprintf (inst.name, "cache %d", cache_op);
3205214571Sdim    }
3206214571Sdim
3207214571Sdim  if (*str == '[')
3208214571Sdim    {
3209214571Sdim      str++;
3210214571Sdim      skip_whitespace (str);
3211214571Sdim
3212214571Sdim      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3213214571Sdim	return;
3214214571Sdim
3215214571Sdim      skip_whitespace (str);
3216214571Sdim
3217214571Sdim      /* cache op, [rA]  */
3218214571Sdim      if (skip_past_comma (&str) == (int) FAIL)
3219214571Sdim        {
3220214571Sdim          SET_INSN_ERROR (NULL);
3221214571Sdim          if (*str != ']')
3222214571Sdim            {
3223214571Sdim              inst.error = _("missing ]");
3224214571Sdim              return;
3225214571Sdim            }
3226214571Sdim          str++;
3227214571Sdim        }
3228214571Sdim      /* cache op, [rA, simm15]  */
3229214571Sdim      else
3230214571Sdim        {
3231214571Sdim          if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
3232214571Sdim            {
3233214571Sdim              return;
3234214571Sdim            }
3235214571Sdim
3236214571Sdim          skip_whitespace (str);
3237214571Sdim          if (*str++ != ']')
3238214571Sdim            {
3239214571Sdim              inst.error = _("missing ]");
3240214571Sdim              return;
3241214571Sdim            }
3242214571Sdim        }
3243214571Sdim
3244214571Sdim      if (end_of_line (str) == (int) FAIL)
3245214571Sdim	return;
3246214571Sdim    }
3247214571Sdim  else
3248214571Sdim    {
3249214571Sdim      inst.error = BAD_ARGS;
3250214571Sdim    }
3251214571Sdim}
3252214571Sdim
3253214571Sdimstatic void
3254214571Sdimdo_crdcrscrsimm5 (char *str)
3255214571Sdim{
3256214571Sdim  char *strbak;
3257214571Sdim
3258214571Sdim  strbak = str;
3259214571Sdim  skip_whitespace (str);
3260214571Sdim
3261214571Sdim  if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
3262214571Sdim      || skip_past_comma (&str) == (int) FAIL
3263214571Sdim      || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
3264214571Sdim      || skip_past_comma (&str) == (int) FAIL
3265214571Sdim      || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
3266214571Sdim      || skip_past_comma (&str) == (int) FAIL)
3267214571Sdim    {
3268214571Sdim      str = strbak;
3269214571Sdim      /* cop1 cop_code20.  */
3270214571Sdim      if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
3271214571Sdim	return;
3272214571Sdim    }
3273214571Sdim  else
3274214571Sdim    {
3275214571Sdim      if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
3276214571Sdim	return;
3277214571Sdim    }
3278214571Sdim
3279214571Sdim  end_of_line (str);
3280214571Sdim}
3281214571Sdim
3282214571Sdim/* Handle ldc/stc.  */
3283214571Sdimstatic void
3284214571Sdimdo_ldst_cop (char *str)
3285214571Sdim{
3286214571Sdim  skip_whitespace (str);
3287214571Sdim
3288214571Sdim  if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
3289214571Sdim      || (skip_past_comma (&str) == (int) FAIL))
3290214571Sdim    return;
3291214571Sdim
3292214571Sdim  if (*str == '[')
3293214571Sdim    {
3294214571Sdim      str++;
3295214571Sdim      skip_whitespace (str);
3296214571Sdim
3297214571Sdim      if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3298214571Sdim	return;
3299214571Sdim
3300214571Sdim      skip_whitespace (str);
3301214571Sdim
3302214571Sdim      if (*str++ != ']')
3303214571Sdim        {
3304214571Sdim          if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
3305214571Sdim	    return;
3306214571Sdim
3307214571Sdim          skip_whitespace (str);
3308214571Sdim          if (*str++ != ']')
3309214571Sdim            {
3310214571Sdim              inst.error = _("missing ]");
3311214571Sdim              return;
3312214571Sdim            }
3313214571Sdim        }
3314214571Sdim
3315214571Sdim      end_of_line (str);
3316214571Sdim    }
3317214571Sdim  else
3318214571Sdim    inst.error = BAD_ARGS;
3319214571Sdim}
3320214571Sdim
3321214571Sdimstatic void
3322214571Sdimdo16_ldst_insn (char *str)
3323214571Sdim{
3324214571Sdim  skip_whitespace (str);
3325214571Sdim
3326214571Sdim  if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3327214571Sdim    return;
3328214571Sdim
3329214571Sdim  if (*str == '[')
3330214571Sdim    {
3331214571Sdim      int reg;
3332214571Sdim
3333214571Sdim      str++;
3334214571Sdim      skip_whitespace (str);
3335214571Sdim
3336214571Sdim      if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
3337214571Sdim	return;
3338214571Sdim
3339214571Sdim      skip_whitespace (str);
3340214571Sdim      if (*str++ == ']')
3341214571Sdim        {
3342214571Sdim          if (end_of_line (str) == (int) FAIL)
3343214571Sdim	    return;
3344214571Sdim          else
3345214571Sdim            {
3346214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3347214571Sdim                              | (((inst.instruction >> 4) & 0xf) << 15);
3348214571Sdim	      inst.relax_size = 4;
3349214571Sdim            }
3350214571Sdim        }
3351214571Sdim      else
3352214571Sdim        {
3353214571Sdim          inst.error = _("missing ]");
3354214571Sdim        }
3355214571Sdim    }
3356214571Sdim  else
3357214571Sdim    {
3358214571Sdim      inst.error = BAD_ARGS;
3359214571Sdim    }
3360214571Sdim}
3361214571Sdim
3362214571Sdim/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
3363214571Sdimstatic void
3364214571Sdimdo16_ldst_imm_insn (char *str)
3365214571Sdim{
3366214571Sdim  char data_exp[MAX_LITERAL_POOL_SIZE];
3367214571Sdim  int reg_rd;
3368214571Sdim  char *dataptr = NULL, *pp = NULL;
3369214571Sdim  int cnt = 0;
3370214571Sdim  int assign_data = (int) FAIL;
3371214571Sdim  unsigned int ldst_func;
3372214571Sdim
3373214571Sdim  skip_whitespace (str);
3374214571Sdim
3375214571Sdim  if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
3376214571Sdim      || (skip_past_comma (&str) == (int) FAIL))
3377214571Sdim    return;
3378214571Sdim
3379214571Sdim  skip_whitespace (str);
3380214571Sdim  dataptr = str;
3381214571Sdim
3382214571Sdim  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
3383214571Sdim    {
3384214571Sdim      data_exp[cnt] = *dataptr;
3385214571Sdim      dataptr++;
3386214571Sdim      cnt++;
3387214571Sdim    }
3388214571Sdim
3389214571Sdim  data_exp[cnt] = '\0';
3390214571Sdim  pp = &data_exp[0];
3391214571Sdim
3392214571Sdim  str = dataptr;
3393214571Sdim
3394214571Sdim  ldst_func = inst.instruction & LDST16_RI_MASK;
3395214571Sdim  if (ldst_func == N16_LIU)
3396214571Sdim    assign_data = exp_ldst_offset (&pp, 0, _IMM8);
3397214571Sdim  else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3398214571Sdim    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3399214571Sdim  else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3400214571Sdim    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3401214571Sdim  else
3402214571Sdim    assign_data = exp_ldst_offset (&pp, 3, _IMM5);
3403214571Sdim
3404214571Sdim  if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
3405214571Sdim    return;
3406214571Sdim  else
3407214571Sdim    {
3408214571Sdim      if ((inst.instruction & 0x7000) == N16_LIU)
3409214571Sdim        {
3410214571Sdim          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
3411214571Sdim                          | ((inst.instruction & 0xff) << 1);
3412214571Sdim        }
3413214571Sdim      else if (((inst.instruction & 0x7007) == N16_LHP)
3414214571Sdim               || ((inst.instruction & 0x7007) == N16_SHP))
3415214571Sdim        {
3416214571Sdim          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3417214571Sdim                          | (((inst.instruction >> 3) & 0x1f) << 1);
3418214571Sdim        }
3419214571Sdim      else if (((inst.instruction & 0x7007) == N16_LWP)
3420214571Sdim               || ((inst.instruction & 0x7007) == N16_SWP))
3421214571Sdim        {
3422214571Sdim          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3423214571Sdim                          | (((inst.instruction >> 3) & 0x1f) << 2);
3424214571Sdim        }
3425214571Sdim      else if (((inst.instruction & 0x7007) == N16_LBUP)
3426214571Sdim               || ((inst.instruction & 0x7007) == N16_SBP))
3427214571Sdim        {
3428214571Sdim          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3429214571Sdim                          | (((inst.instruction >> 3) & 0x1f));
3430214571Sdim        }
3431214571Sdim
3432214571Sdim      inst.relax_size = 4;
3433214571Sdim    }
3434214571Sdim}
3435214571Sdim
3436214571Sdimstatic void
3437214571Sdimdo16_push_pop (char *str)
3438214571Sdim{
3439214571Sdim  int reg_rd;
3440214571Sdim  int H_bit_mask = 0;
3441214571Sdim
3442214571Sdim  skip_whitespace (str);
3443214571Sdim  if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
3444214571Sdim      || (skip_past_comma (&str) == (int) FAIL))
3445214571Sdim    return;
3446214571Sdim
3447214571Sdim  if (reg_rd >= 16)
3448214571Sdim    H_bit_mask = 1;
3449214571Sdim
3450214571Sdim  /* reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
3451214571Sdim  inst.instruction &= ~(1 << 12);
3452214571Sdim
3453214571Sdim  inst.instruction |= H_bit_mask << 7;
3454214571Sdim
3455214571Sdim  if (*str == '[')
3456214571Sdim    {
3457214571Sdim      int reg;
3458214571Sdim
3459214571Sdim      str++;
3460214571Sdim      skip_whitespace (str);
3461214571Sdim      if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
3462214571Sdim	return;
3463214571Sdim      else if (reg > 7)
3464214571Sdim        {
3465214571Sdim          if (!inst.error)
3466214571Sdim	    inst.error = _("base register nums are over 3 bit");
3467214571Sdim
3468214571Sdim          return;
3469214571Sdim        }
3470214571Sdim
3471214571Sdim      skip_whitespace (str);
3472214571Sdim      if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
3473214571Sdim        {
3474214571Sdim          if (!inst.error)
3475214571Sdim	    inst.error = _("missing ]");
3476214571Sdim
3477214571Sdim          return;
3478214571Sdim        }
3479214571Sdim
3480214571Sdim      /* pop! */
3481214571Sdim      if ((inst.instruction & 0xf) == 0xa)
3482214571Sdim        {
3483214571Sdim          if (H_bit_mask)
3484214571Sdim            {
3485214571Sdim              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3486214571Sdim                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3487214571Sdim            }
3488214571Sdim          else
3489214571Sdim            {
3490214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3491214571Sdim                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3492214571Sdim            }
3493214571Sdim        }
3494214571Sdim      /* push! */
3495214571Sdim      else
3496214571Sdim        {
3497214571Sdim          if (H_bit_mask)
3498214571Sdim            {
3499214571Sdim              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3500214571Sdim                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3501214571Sdim            }
3502214571Sdim          else
3503214571Sdim            {
3504214571Sdim              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3505214571Sdim                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3506214571Sdim            }
3507214571Sdim        }
3508214571Sdim      inst.relax_size = 4;
3509214571Sdim    }
3510214571Sdim  else
3511214571Sdim    {
3512214571Sdim      inst.error = BAD_ARGS;
3513214571Sdim    }
3514214571Sdim}
3515214571Sdim
3516214571Sdim/* Handle lcb/lcw/lce/scb/scw/sce.  */
3517214571Sdimstatic void
3518214571Sdimdo_ldst_unalign (char *str)
3519214571Sdim{
3520214571Sdim  int conflict_reg;
3521214571Sdim
3522214571Sdim  if (university_version == 1)
3523214571Sdim    {
3524214571Sdim      inst.error = ERR_FOR_SCORE5U_ATOMIC;
3525214571Sdim      return;
3526214571Sdim    }
3527214571Sdim
3528214571Sdim  skip_whitespace (str);
3529214571Sdim
3530214571Sdim  /* lcb/scb [rA]+.  */
3531214571Sdim  if (*str == '[')
3532214571Sdim    {
3533214571Sdim      str++;
3534214571Sdim      skip_whitespace (str);
3535214571Sdim
3536214571Sdim      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3537214571Sdim	return;
3538214571Sdim
3539214571Sdim      if (*str++ == ']')
3540214571Sdim        {
3541214571Sdim          if (*str++ != '+')
3542214571Sdim            {
3543214571Sdim              inst.error = _("missing +");
3544214571Sdim              return;
3545214571Sdim            }
3546214571Sdim        }
3547214571Sdim      else
3548214571Sdim        {
3549214571Sdim          inst.error = _("missing ]");
3550214571Sdim          return;
3551214571Sdim        }
3552214571Sdim
3553214571Sdim      if (end_of_line (str) == (int) FAIL)
3554214571Sdim	return;
3555214571Sdim    }
3556214571Sdim  /* lcw/lce/scb/sce rD, [rA]+.  */
3557214571Sdim  else
3558214571Sdim    {
3559214571Sdim      if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
3560214571Sdim          || (skip_past_comma (&str) == (int) FAIL))
3561214571Sdim        {
3562214571Sdim          return;
3563214571Sdim        }
3564214571Sdim
3565214571Sdim      skip_whitespace (str);
3566214571Sdim      if (*str++ == '[')
3567214571Sdim        {
3568214571Sdim          int reg;
3569214571Sdim
3570214571Sdim          skip_whitespace (str);
3571214571Sdim          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3572214571Sdim            {
3573214571Sdim              return;
3574214571Sdim            }
3575214571Sdim
3576214571Sdim          /* Conflicts can occur on stores as well as loads.  */
3577214571Sdim          conflict_reg = (conflict_reg == reg);
3578214571Sdim          skip_whitespace (str);
3579214571Sdim          if (*str++ == ']')
3580214571Sdim            {
3581214571Sdim              unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
3582214571Sdim
3583214571Sdim              if (*str++ == '+')
3584214571Sdim                {
3585214571Sdim                  if (conflict_reg)
3586214571Sdim                    {
3587214571Sdim                      as_warn (_("%s register same as write-back base"),
3588214571Sdim                               ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3589214571Sdim                                ? _("destination") : _("source")));
3590214571Sdim                    }
3591214571Sdim                }
3592214571Sdim              else
3593214571Sdim                {
3594214571Sdim                  inst.error = _("missing +");
3595214571Sdim                  return;
3596214571Sdim                }
3597214571Sdim
3598214571Sdim              if (end_of_line (str) == (int) FAIL)
3599214571Sdim		return;
3600214571Sdim            }
3601214571Sdim          else
3602214571Sdim            {
3603214571Sdim              inst.error = _("missing ]");
3604214571Sdim              return;
3605214571Sdim            }
3606214571Sdim        }
3607214571Sdim      else
3608214571Sdim        {
3609214571Sdim          inst.error = BAD_ARGS;
3610214571Sdim          return;
3611214571Sdim        }
3612214571Sdim    }
3613214571Sdim}
3614214571Sdim
3615214571Sdim/* Handle alw/asw.  */
3616214571Sdimstatic void
3617214571Sdimdo_ldst_atomic (char *str)
3618214571Sdim{
3619214571Sdim  if (university_version == 1)
3620214571Sdim    {
3621214571Sdim      inst.error = ERR_FOR_SCORE5U_ATOMIC;
3622214571Sdim      return;
3623214571Sdim    }
3624214571Sdim
3625214571Sdim  skip_whitespace (str);
3626214571Sdim
3627214571Sdim  if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3628214571Sdim      || (skip_past_comma (&str) == (int) FAIL))
3629214571Sdim    {
3630214571Sdim      return;
3631214571Sdim    }
3632214571Sdim  else
3633214571Sdim    {
3634214571Sdim
3635214571Sdim      skip_whitespace (str);
3636214571Sdim      if (*str++ == '[')
3637214571Sdim        {
3638214571Sdim          int reg;
3639214571Sdim
3640214571Sdim          skip_whitespace (str);
3641214571Sdim          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3642214571Sdim            {
3643214571Sdim              return;
3644214571Sdim            }
3645214571Sdim
3646214571Sdim          skip_whitespace (str);
3647214571Sdim          if (*str++ != ']')
3648214571Sdim            {
3649214571Sdim              inst.error = _("missing ]");
3650214571Sdim              return;
3651214571Sdim            }
3652214571Sdim
3653214571Sdim          end_of_line (str);
3654214571Sdim        }
3655214571Sdim      else
3656214571Sdim	inst.error = BAD_ARGS;
3657214571Sdim    }
3658214571Sdim}
3659214571Sdim
3660214571Sdimstatic void
3661214571Sdimbuild_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3662214571Sdim                  struct score_it var_insts[RELAX_INST_NUM], int var_num,
3663214571Sdim                  symbolS *add_symbol)
3664214571Sdim{
3665214571Sdim  int i;
3666214571Sdim  char *p;
3667214571Sdim  fixS *fixp = NULL;
3668214571Sdim  fixS *cur_fixp = NULL;
3669214571Sdim  long where;
3670214571Sdim  struct score_it inst_main;
3671214571Sdim
3672214571Sdim  memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
3673214571Sdim
3674214571Sdim  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
3675214571Sdim  inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
3676214571Sdim  inst_main.type = Insn_PIC;
3677214571Sdim
3678214571Sdim  for (i = 0; i < var_num; i++)
3679214571Sdim    {
3680214571Sdim      inst_main.relax_size += var_insts[i].size;
3681214571Sdim      var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
3682214571Sdim                                                   GET_INSN_CLASS (var_insts[i].type));
3683214571Sdim    }
3684214571Sdim
3685214571Sdim  /* Check data dependency.  */
3686214571Sdim  handle_dependency (&inst_main);
3687214571Sdim
3688214571Sdim  /* Start a new frag if frag_now is not empty.  */
3689214571Sdim  if (frag_now_fix () != 0)
3690214571Sdim    {
3691214571Sdim      if (!frag_now->tc_frag_data.is_insn)
3692214571Sdim	{
3693214571Sdim          frag_wane (frag_now);
3694214571Sdim	}
3695214571Sdim      frag_new (0);
3696214571Sdim    }
3697214571Sdim  frag_grow (20);
3698214571Sdim
3699214571Sdim  /* Write fr_fix part.  */
3700214571Sdim  p = frag_more (inst_main.size);
3701214571Sdim  md_number_to_chars (p, inst_main.instruction, inst_main.size);
3702214571Sdim
3703214571Sdim  if (inst_main.reloc.type != BFD_RELOC_NONE)
3704214571Sdim    fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
3705214571Sdim			  &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
3706214571Sdim
3707214571Sdim  frag_now->tc_frag_data.fixp = fixp;
3708214571Sdim  cur_fixp = frag_now->tc_frag_data.fixp;
3709214571Sdim
3710214571Sdim#ifdef OBJ_ELF
3711214571Sdim  dwarf2_emit_insn (inst_main.size);
3712214571Sdim#endif
3713214571Sdim
3714214571Sdim  where = p - frag_now->fr_literal + inst_main.size;
3715214571Sdim  for (i = 0; i < var_num; i++)
3716214571Sdim    {
3717214571Sdim      if (i > 0)
3718214571Sdim        where += var_insts[i - 1].size;
3719214571Sdim
3720214571Sdim      if (var_insts[i].reloc.type != BFD_RELOC_NONE)
3721214571Sdim        {
3722214571Sdim          fixp = fix_new_score (frag_now, where, var_insts[i].size,
3723214571Sdim                                &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
3724214571Sdim                                var_insts[i].reloc.type);
3725214571Sdim          if (fixp)
3726214571Sdim            {
3727214571Sdim              if (cur_fixp)
3728214571Sdim                {
3729214571Sdim                  cur_fixp->fx_next = fixp;
3730214571Sdim                  cur_fixp = cur_fixp->fx_next;
3731214571Sdim                }
3732214571Sdim              else
3733214571Sdim                {
3734214571Sdim                  frag_now->tc_frag_data.fixp = fixp;
3735214571Sdim                  cur_fixp = frag_now->tc_frag_data.fixp;
3736214571Sdim                }
3737214571Sdim	    }
3738214571Sdim        }
3739214571Sdim    }
3740214571Sdim
3741214571Sdim  p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
3742214571Sdim                RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
3743214571Sdim                0, inst_main.size, 0), add_symbol, 0, NULL);
3744214571Sdim
3745214571Sdim  /* Write fr_var part.
3746214571Sdim     no calling gen_insn_frag, no fixS will be generated.  */
3747214571Sdim  for (i = 0; i < var_num; i++)
3748214571Sdim    {
3749214571Sdim      md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
3750214571Sdim      p += var_insts[i].size;
3751214571Sdim    }
3752214571Sdim  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
3753214571Sdim  inst.bwarn = -1;
3754214571Sdim}
3755214571Sdim
3756214571Sdim/* Build a relax frag for la instruction when generating PIC,
3757214571Sdim   external symbol first and local symbol second.  */
3758214571Sdim
3759214571Sdimstatic void
3760214571Sdimbuild_la_pic (int reg_rd, expressionS exp)
3761214571Sdim{
3762214571Sdim  symbolS *add_symbol = exp.X_add_symbol;
3763214571Sdim  offsetT add_number = exp.X_add_number;
3764214571Sdim  struct score_it fix_insts[RELAX_INST_NUM];
3765214571Sdim  struct score_it var_insts[RELAX_INST_NUM];
3766214571Sdim  int fix_num = 0;
3767214571Sdim  int var_num = 0;
3768214571Sdim  char tmp[MAX_LITERAL_POOL_SIZE];
3769214571Sdim  int r1_bak;
3770214571Sdim
3771214571Sdim  r1_bak = nor1;
3772214571Sdim  nor1 = 0;
3773214571Sdim
3774214571Sdim  if (add_number == 0)
3775214571Sdim    {
3776214571Sdim      fix_num = 1;
3777214571Sdim      var_num = 2;
3778214571Sdim
3779214571Sdim      /* For an external symbol, only one insn is generated;
3780214571Sdim         For a local symbol, two insns are generated.  */
3781214571Sdim      /* Fix part
3782214571Sdim         For an external symbol: lw rD, <sym>($gp)
3783214571Sdim                                 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
3784214571Sdim      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3785214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3786214571Sdim	return;
3787214571Sdim
3788214571Sdim      if (reg_rd == PIC_CALL_REG)
3789214571Sdim        inst.reloc.type = BFD_RELOC_SCORE_CALL15;
3790214571Sdim      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3791214571Sdim
3792214571Sdim      /* Var part
3793214571Sdim	 For a local symbol :
3794214571Sdim         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
3795214571Sdim	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
3796214571Sdim      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
3797214571Sdim      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3798214571Sdim      sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3799214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3800214571Sdim	return;
3801214571Sdim
3802214571Sdim      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
3803214571Sdim      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3804214571Sdim    }
3805214571Sdim  else if (add_number >= -0x8000 && add_number <= 0x7fff)
3806214571Sdim    {
3807214571Sdim      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
3808214571Sdim      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3809214571Sdim      if (append_insn (tmp, TRUE) == (int) FAIL)
3810214571Sdim	return;
3811214571Sdim
3812214571Sdim      /* Insn 2  */
3813214571Sdim      fix_num = 1;
3814214571Sdim      var_num = 1;
3815214571Sdim      /* Fix part
3816214571Sdim         For an external symbol: addi rD, <constant> */
3817214571Sdim      sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
3818214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3819214571Sdim	return;
3820214571Sdim
3821214571Sdim      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3822214571Sdim
3823214571Sdim      /* Var part
3824214571Sdim 	 For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
3825214571Sdim      sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
3826214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3827214571Sdim	return;
3828214571Sdim
3829214571Sdim      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3830214571Sdim      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3831214571Sdim    }
3832214571Sdim  else
3833214571Sdim    {
3834214571Sdim      int hi = (add_number >> 16) & 0x0000FFFF;
3835214571Sdim      int lo = add_number & 0x0000FFFF;
3836214571Sdim
3837214571Sdim      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
3838214571Sdim      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
3839214571Sdim      if (append_insn (tmp, TRUE) == (int) FAIL)
3840214571Sdim	return;
3841214571Sdim
3842214571Sdim      /* Insn 2  */
3843214571Sdim      fix_num = 1;
3844214571Sdim      var_num = 1;
3845214571Sdim      /* Fix part
3846214571Sdim	 For an external symbol: ldis r1, HI%<constant>  */
3847214571Sdim      sprintf (tmp, "ldis r1, %d", hi);
3848214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3849214571Sdim	return;
3850214571Sdim
3851214571Sdim      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3852214571Sdim
3853214571Sdim      /* Var part
3854214571Sdim	 For a local symbol: ldis r1, HI%<constant>
3855214571Sdim         but, if lo is outof 16 bit, make hi plus 1  */
3856214571Sdim      if ((lo < -0x8000) || (lo > 0x7fff))
3857214571Sdim	{
3858214571Sdim	  hi += 1;
3859214571Sdim	}
3860214571Sdim      sprintf (tmp, "ldis_pic r1, %d", hi);
3861214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3862214571Sdim	return;
3863214571Sdim
3864214571Sdim      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3865214571Sdim      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3866214571Sdim
3867214571Sdim      /* Insn 3  */
3868214571Sdim      fix_num = 1;
3869214571Sdim      var_num = 1;
3870214571Sdim      /* Fix part
3871214571Sdim	 For an external symbol: ori r1, LO%<constant>  */
3872214571Sdim      sprintf (tmp, "ori r1, %d", lo);
3873214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3874214571Sdim	return;
3875214571Sdim
3876214571Sdim      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3877214571Sdim
3878214571Sdim      /* Var part
3879214571Sdim  	 For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
3880214571Sdim      sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
3881214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
3882214571Sdim	return;
3883214571Sdim
3884214571Sdim      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3885214571Sdim      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3886214571Sdim
3887214571Sdim      /* Insn 4: add rD, rD, r1  */
3888214571Sdim      sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
3889214571Sdim      if (append_insn (tmp, TRUE) == (int) FAIL)
3890214571Sdim	return;
3891214571Sdim
3892214571Sdim     /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
3893214571Sdim     inst.bwarn = -1;
3894214571Sdim    }
3895214571Sdim
3896214571Sdim  nor1 = r1_bak;
3897214571Sdim}
3898214571Sdim
3899214571Sdim/* Handle la.  */
3900214571Sdimstatic void
3901214571Sdimdo_macro_la_rdi32 (char *str)
3902214571Sdim{
3903214571Sdim  int reg_rd;
3904214571Sdim
3905214571Sdim  skip_whitespace (str);
3906214571Sdim  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3907214571Sdim      || skip_past_comma (&str) == (int) FAIL)
3908214571Sdim    {
3909214571Sdim      return;
3910214571Sdim    }
3911214571Sdim  else
3912214571Sdim    {
3913214571Sdim      char append_str[MAX_LITERAL_POOL_SIZE];
3914214571Sdim      char *keep_data = str;
3915214571Sdim
3916214571Sdim      /* la rd, simm16.  */
3917214571Sdim      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3918214571Sdim        {
3919214571Sdim          end_of_line (str);
3920214571Sdim          return;
3921214571Sdim        }
3922214571Sdim      /* la rd, imm32 or la rd, label.  */
3923214571Sdim      else
3924214571Sdim        {
3925214571Sdim          SET_INSN_ERROR (NULL);
3926214571Sdim          str = keep_data;
3927214571Sdim          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3928214571Sdim              || (end_of_line (str) == (int) FAIL))
3929214571Sdim            {
3930214571Sdim              return;
3931214571Sdim            }
3932214571Sdim          else
3933214571Sdim            {
3934214571Sdim              if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
3935214571Sdim                {
3936214571Sdim                  sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3937214571Sdim                  if (append_insn (append_str, TRUE) == (int) FAIL)
3938214571Sdim		    return;
3939214571Sdim
3940214571Sdim                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
3941214571Sdim                  if (append_insn (append_str, TRUE) == (int) FAIL)
3942214571Sdim		    return;
3943214571Sdim		}
3944214571Sdim	      else
3945214571Sdim		{
3946214571Sdim		  assert (inst.reloc.exp.X_add_symbol);
3947214571Sdim		  build_la_pic (reg_rd, inst.reloc.exp);
3948214571Sdim		}
3949214571Sdim
3950214571Sdim              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
3951214571Sdim              inst.bwarn = -1;
3952214571Sdim            }
3953214571Sdim        }
3954214571Sdim    }
3955214571Sdim}
3956214571Sdim
3957214571Sdim/* Handle li.  */
3958214571Sdimstatic void
3959214571Sdimdo_macro_li_rdi32 (char *str){
3960214571Sdim
3961214571Sdim  int reg_rd;
3962214571Sdim
3963214571Sdim  skip_whitespace (str);
3964214571Sdim  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3965214571Sdim      || skip_past_comma (&str) == (int) FAIL)
3966214571Sdim    {
3967214571Sdim      return;
3968214571Sdim    }
3969214571Sdim  else
3970214571Sdim    {
3971214571Sdim      char *keep_data = str;
3972214571Sdim
3973214571Sdim      /* li rd, simm16.  */
3974214571Sdim      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3975214571Sdim        {
3976214571Sdim          end_of_line (str);
3977214571Sdim          return;
3978214571Sdim        }
3979214571Sdim      /* li rd, imm32.  */
3980214571Sdim      else
3981214571Sdim        {
3982214571Sdim          char append_str[MAX_LITERAL_POOL_SIZE];
3983214571Sdim
3984214571Sdim          str = keep_data;
3985214571Sdim
3986214571Sdim          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3987214571Sdim              || (end_of_line (str) == (int) FAIL))
3988214571Sdim            {
3989214571Sdim              return;
3990214571Sdim            }
3991214571Sdim          else if (inst.reloc.exp.X_add_symbol)
3992214571Sdim            {
3993214571Sdim              inst.error = _("li rd label isn't correct instruction form");
3994214571Sdim              return;
3995214571Sdim            }
3996214571Sdim          else
3997214571Sdim            {
3998214571Sdim              sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
3999214571Sdim
4000214571Sdim              if (append_insn (append_str, TRUE) == (int) FAIL)
4001214571Sdim		return;
4002214571Sdim              else
4003214571Sdim                {
4004214571Sdim                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4005214571Sdim                  if (append_insn (append_str, TRUE) == (int) FAIL)
4006214571Sdim		    return;
4007214571Sdim
4008214571Sdim                  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4009214571Sdim                  inst.bwarn = -1;
4010214571Sdim                }
4011214571Sdim            }
4012214571Sdim        }
4013214571Sdim    }
4014214571Sdim}
4015214571Sdim
4016214571Sdim/* Handle mul/mulu/div/divu/rem/remu.  */
4017214571Sdimstatic void
4018214571Sdimdo_macro_mul_rdrsrs (char *str)
4019214571Sdim{
4020214571Sdim  int reg_rd;
4021214571Sdim  int reg_rs1;
4022214571Sdim  int reg_rs2;
4023214571Sdim  char *backupstr;
4024214571Sdim  char append_str[MAX_LITERAL_POOL_SIZE];
4025214571Sdim
4026214571Sdim  if (university_version == 1)
4027214571Sdim    as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
4028214571Sdim
4029214571Sdim  strcpy (append_str, str);
4030214571Sdim  backupstr = append_str;
4031214571Sdim  skip_whitespace (backupstr);
4032214571Sdim  if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4033214571Sdim      || (skip_past_comma (&backupstr) == (int) FAIL)
4034214571Sdim      || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
4035214571Sdim    {
4036214571Sdim      inst.error = BAD_ARGS;
4037214571Sdim      return;
4038214571Sdim    }
4039214571Sdim
4040214571Sdim  if (skip_past_comma (&backupstr) == (int) FAIL)
4041214571Sdim    {
4042214571Sdim      /* rem/remu rA, rB is error format.  */
4043214571Sdim      if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
4044214571Sdim        {
4045214571Sdim          SET_INSN_ERROR (BAD_ARGS);
4046214571Sdim        }
4047214571Sdim      else
4048214571Sdim        {
4049214571Sdim          SET_INSN_ERROR (NULL);
4050214571Sdim          do_rsrs (str);
4051214571Sdim        }
4052214571Sdim      return;
4053214571Sdim    }
4054214571Sdim  else
4055214571Sdim    {
4056214571Sdim      SET_INSN_ERROR (NULL);
4057214571Sdim      if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4058214571Sdim          || (end_of_line (backupstr) == (int) FAIL))
4059214571Sdim        {
4060214571Sdim          return;
4061214571Sdim        }
4062214571Sdim      else
4063214571Sdim        {
4064214571Sdim          char append_str1[MAX_LITERAL_POOL_SIZE];
4065214571Sdim
4066214571Sdim          if (strcmp (inst.name, "rem") == 0)
4067214571Sdim            {
4068214571Sdim              sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4069214571Sdim              sprintf (append_str1, "mfceh  r%d", reg_rd);
4070214571Sdim            }
4071214571Sdim          else if (strcmp (inst.name, "remu") == 0)
4072214571Sdim            {
4073214571Sdim              sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4074214571Sdim              sprintf (append_str1, "mfceh  r%d", reg_rd);
4075214571Sdim            }
4076214571Sdim          else
4077214571Sdim            {
4078214571Sdim              sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
4079214571Sdim              sprintf (append_str1, "mfcel  r%d", reg_rd);
4080214571Sdim            }
4081214571Sdim
4082214571Sdim          /* Output mul/mulu or div/divu or rem/remu.  */
4083214571Sdim          if (append_insn (append_str, TRUE) == (int) FAIL)
4084214571Sdim	    return;
4085214571Sdim
4086214571Sdim          /* Output mfcel or mfceh.  */
4087214571Sdim          if (append_insn (append_str1, TRUE) == (int) FAIL)
4088214571Sdim	    return;
4089214571Sdim
4090214571Sdim          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4091214571Sdim          inst.bwarn = -1;
4092214571Sdim        }
4093214571Sdim    }
4094214571Sdim}
4095214571Sdim
4096214571Sdimstatic void
4097214571Sdimexp_macro_ldst_abs (char *str)
4098214571Sdim{
4099214571Sdim  int reg_rd;
4100214571Sdim  char *backupstr, *tmp;
4101214571Sdim  char append_str[MAX_LITERAL_POOL_SIZE];
4102214571Sdim  char verifystr[MAX_LITERAL_POOL_SIZE];
4103214571Sdim  struct score_it inst_backup;
4104214571Sdim  int r1_bak = 0;
4105214571Sdim
4106214571Sdim  r1_bak = nor1;
4107214571Sdim  nor1 = 0;
4108214571Sdim  memcpy (&inst_backup, &inst, sizeof (struct score_it));
4109214571Sdim
4110214571Sdim  strcpy (verifystr, str);
4111214571Sdim  backupstr = verifystr;
4112214571Sdim  skip_whitespace (backupstr);
4113214571Sdim  if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4114214571Sdim    return;
4115214571Sdim
4116214571Sdim  tmp = backupstr;
4117214571Sdim  if (skip_past_comma (&backupstr) == (int) FAIL)
4118214571Sdim    return;
4119214571Sdim
4120214571Sdim  backupstr = tmp;
4121214571Sdim  sprintf (append_str, "li r1  %s", backupstr);
4122214571Sdim  append_insn (append_str, TRUE);
4123214571Sdim
4124214571Sdim  memcpy (&inst, &inst_backup, sizeof (struct score_it));
4125214571Sdim  sprintf (append_str, " r%d, [r1,0]", reg_rd);
4126214571Sdim  do_ldst_insn (append_str);
4127214571Sdim
4128214571Sdim  nor1 = r1_bak;
4129214571Sdim}
4130214571Sdim
4131214571Sdimstatic int
4132214571Sdimnopic_need_relax (symbolS * sym, int before_relaxing)
4133214571Sdim{
4134214571Sdim  if (sym == NULL)
4135214571Sdim    return 0;
4136214571Sdim  else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
4137214571Sdim    {
4138214571Sdim      const char *symname;
4139214571Sdim      const char *segname;
4140214571Sdim
4141214571Sdim      /* Find out whether this symbol can be referenced off the $gp
4142214571Sdim         register.  It can be if it is smaller than the -G size or if
4143214571Sdim         it is in the .sdata or .sbss section.  Certain symbols can
4144214571Sdim         not be referenced off the $gp, although it appears as though
4145214571Sdim         they can.  */
4146214571Sdim      symname = S_GET_NAME (sym);
4147214571Sdim      if (symname != (const char *)NULL
4148214571Sdim          && (strcmp (symname, "eprol") == 0
4149214571Sdim              || strcmp (symname, "etext") == 0
4150214571Sdim              || strcmp (symname, "_gp") == 0
4151214571Sdim              || strcmp (symname, "edata") == 0
4152214571Sdim              || strcmp (symname, "_fbss") == 0
4153214571Sdim              || strcmp (symname, "_fdata") == 0
4154214571Sdim              || strcmp (symname, "_ftext") == 0
4155214571Sdim              || strcmp (symname, "end") == 0
4156214571Sdim              || strcmp (symname, GP_DISP_LABEL) == 0))
4157214571Sdim        {
4158214571Sdim          return 1;
4159214571Sdim        }
4160214571Sdim      else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4161214571Sdim      /* We must defer this decision until after the whole file has been read,
4162214571Sdim         since there might be a .extern after the first use of this symbol.  */
4163214571Sdim               || (before_relaxing
4164214571Sdim                   && S_GET_VALUE (sym) == 0)
4165214571Sdim               || (S_GET_VALUE (sym) != 0
4166214571Sdim                   && S_GET_VALUE (sym) <= g_switch_value)))
4167214571Sdim        {
4168214571Sdim          return 0;
4169214571Sdim        }
4170214571Sdim
4171214571Sdim      segname = segment_name (S_GET_SEGMENT (sym));
4172214571Sdim      return (strcmp (segname, ".sdata") != 0
4173214571Sdim	      && strcmp (segname, ".sbss") != 0
4174214571Sdim	      && strncmp (segname, ".sdata.", 7) != 0
4175214571Sdim	      && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4176214571Sdim    }
4177214571Sdim  /* We are not optimizing for the $gp register.  */
4178214571Sdim  else
4179214571Sdim    return 1;
4180214571Sdim}
4181214571Sdim
4182214571Sdim/* Build a relax frag for lw/st instruction when generating PIC,
4183214571Sdim   external symbol first and local symbol second.  */
4184214571Sdim
4185214571Sdimstatic void
4186214571Sdimbuild_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4187214571Sdim{
4188214571Sdim  symbolS *add_symbol = exp.X_add_symbol;
4189214571Sdim  int add_number = exp.X_add_number;
4190214571Sdim  struct score_it fix_insts[RELAX_INST_NUM];
4191214571Sdim  struct score_it var_insts[RELAX_INST_NUM];
4192214571Sdim  int fix_num = 0;
4193214571Sdim  int var_num = 0;
4194214571Sdim  char tmp[MAX_LITERAL_POOL_SIZE];
4195214571Sdim  int r1_bak;
4196214571Sdim
4197214571Sdim  r1_bak = nor1;
4198214571Sdim  nor1 = 0;
4199214571Sdim
4200214571Sdim  if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4201214571Sdim    {
4202214571Sdim      fix_num = 1;
4203214571Sdim      var_num = 2;
4204214571Sdim
4205214571Sdim      /* For an external symbol, two insns are generated;
4206214571Sdim         For a local symbol, three insns are generated.  */
4207214571Sdim      /* Fix part
4208214571Sdim         For an external symbol: lw rD, <sym>($gp)
4209214571Sdim                                 (BFD_RELOC_SCORE_GOT15)  */
4210214571Sdim      sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4211214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
4212214571Sdim        return;
4213214571Sdim
4214214571Sdim      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4215214571Sdim
4216214571Sdim      /* Var part
4217214571Sdim	 For a local symbol :
4218214571Sdim         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4219214571Sdim	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4220214571Sdim      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4221214571Sdim      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
4222214571Sdim      sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4223214571Sdim      if (append_insn (tmp, FALSE) == (int) FAIL)
4224214571Sdim        return;
4225214571Sdim
4226214571Sdim      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
4227214571Sdim      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4228214571Sdim
4229214571Sdim      /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
4230214571Sdim      sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4231214571Sdim      if (append_insn (tmp, TRUE) == (int) FAIL)
4232214571Sdim        return;
4233214571Sdim
4234214571Sdim      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4235214571Sdim      inst.bwarn = -1;
4236214571Sdim    }
4237214571Sdim  else
4238214571Sdim    {
4239214571Sdim      inst.error = _("PIC code offset overflow (max 16 signed bits)");
4240214571Sdim      return;
4241214571Sdim    }
4242214571Sdim
4243214571Sdim  nor1 = r1_bak;
4244214571Sdim}
4245214571Sdim
4246214571Sdimstatic void
4247214571Sdimdo_macro_ldst_label (char *str)
4248214571Sdim{
4249214571Sdim  int i;
4250214571Sdim  int ldst_gp_p = 0;
4251214571Sdim  int reg_rd;
4252214571Sdim  int r1_bak;
4253214571Sdim  char *backup_str;
4254214571Sdim  char *label_str;
4255214571Sdim  char *absolute_value;
4256214571Sdim  char append_str[3][MAX_LITERAL_POOL_SIZE];
4257214571Sdim  char verifystr[MAX_LITERAL_POOL_SIZE];
4258214571Sdim  struct score_it inst_backup;
4259214571Sdim  struct score_it inst_expand[3];
4260214571Sdim  struct score_it inst_main;
4261214571Sdim
4262214571Sdim  memcpy (&inst_backup, &inst, sizeof (struct score_it));
4263214571Sdim  strcpy (verifystr, str);
4264214571Sdim  backup_str = verifystr;
4265214571Sdim
4266214571Sdim  skip_whitespace (backup_str);
4267214571Sdim  if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
4268214571Sdim    return;
4269214571Sdim
4270214571Sdim  if (skip_past_comma (&backup_str) == (int) FAIL)
4271214571Sdim    return;
4272214571Sdim
4273214571Sdim  label_str = backup_str;
4274214571Sdim
4275214571Sdim  /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
4276214571Sdim  if (*backup_str == '[')
4277214571Sdim    {
4278214571Sdim      inst.type = Rd_rvalueRs_preSI12;
4279214571Sdim      do_ldst_insn (str);
4280214571Sdim      return;
4281214571Sdim    }
4282214571Sdim
4283214571Sdim  /* Ld/st rD, imm.  */
4284214571Sdim  absolute_value = backup_str;
4285214571Sdim  inst.type = Rd_rvalueRs_SI15;
4286214571Sdim  if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
4287214571Sdim      || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL)
4288214571Sdim      || (end_of_line (backup_str) == (int) FAIL))
4289214571Sdim    {
4290214571Sdim      return;
4291214571Sdim    }
4292214571Sdim  else
4293214571Sdim    {
4294214571Sdim      if (inst.reloc.exp.X_add_symbol == 0)
4295214571Sdim        {
4296214571Sdim          memcpy (&inst, &inst_backup, sizeof (struct score_it));
4297214571Sdim          exp_macro_ldst_abs (str);
4298214571Sdim          return;
4299214571Sdim        }
4300214571Sdim    }
4301214571Sdim
4302214571Sdim  /* Ld/st rD, label.  */
4303214571Sdim  inst.type = Rd_rvalueRs_SI15;
4304214571Sdim  backup_str = absolute_value;
4305214571Sdim  if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
4306214571Sdim      || (end_of_line (backup_str) == (int) FAIL))
4307214571Sdim    {
4308214571Sdim      return;
4309214571Sdim    }
4310214571Sdim  else
4311214571Sdim    {
4312214571Sdim      if (inst.reloc.exp.X_add_symbol == 0)
4313214571Sdim        {
4314214571Sdim          if (!inst.error)
4315214571Sdim	    inst.error = BAD_ARGS;
4316214571Sdim
4317214571Sdim          return;
4318214571Sdim        }
4319214571Sdim
4320214571Sdim      if (score_pic == PIC)
4321214571Sdim        {
4322214571Sdim          int ldst_idx = 0;
4323214571Sdim          ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4324214571Sdim          build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
4325214571Sdim          return;
4326214571Sdim        }
4327214571Sdim      else
4328214571Sdim	{
4329214571Sdim          if ((inst.reloc.exp.X_add_number <= 0x3fff)
4330214571Sdim               && (inst.reloc.exp.X_add_number >= -0x4000)
4331214571Sdim               && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
4332214571Sdim	    {
4333214571Sdim              int ldst_idx = 0;
4334214571Sdim
4335214571Sdim              /* Assign the real opcode.  */
4336214571Sdim              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4337214571Sdim              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4338214571Sdim              inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
4339214571Sdim              inst.instruction |= reg_rd << 20;
4340214571Sdim              inst.instruction |= GP << 15;
4341214571Sdim              inst.relax_inst = 0x8000;
4342214571Sdim              inst.relax_size = 0;
4343214571Sdim              ldst_gp_p = 1;
4344214571Sdim	    }
4345214571Sdim	}
4346214571Sdim    }
4347214571Sdim
4348214571Sdim  /* Backup inst.  */
4349214571Sdim  memcpy (&inst_main, &inst, sizeof (struct score_it));
4350214571Sdim  r1_bak = nor1;
4351214571Sdim  nor1 = 0;
4352214571Sdim
4353214571Sdim  /* Determine which instructions should be output.  */
4354214571Sdim  sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4355214571Sdim  sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4356214571Sdim  sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4357214571Sdim
4358214571Sdim  /* Generate three instructions.
4359214571Sdim     la r1, label
4360214571Sdim     ld/st rd, [r1, 0]  */
4361214571Sdim  for (i = 0; i < 3; i++)
4362214571Sdim    {
4363214571Sdim      if (append_insn (append_str[i], FALSE) == (int) FAIL)
4364214571Sdim	return;
4365214571Sdim
4366214571Sdim      memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
4367214571Sdim    }
4368214571Sdim
4369214571Sdim  if (ldst_gp_p)
4370214571Sdim    {
4371214571Sdim      char *p;
4372214571Sdim
4373214571Sdim      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4374214571Sdim      inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
4375214571Sdim      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4376214571Sdim      inst_main.type = Insn_GP;
4377214571Sdim
4378214571Sdim      for (i = 0; i < 3; i++)
4379214571Sdim	inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
4380214571Sdim						       , GET_INSN_CLASS (inst_expand[i].type));
4381214571Sdim
4382214571Sdim      /* Check data dependency.  */
4383214571Sdim      handle_dependency (&inst_main);
4384214571Sdim
4385214571Sdim      /* Start a new frag if frag_now is not empty.  */
4386214571Sdim      if (frag_now_fix () != 0)
4387214571Sdim        {
4388214571Sdim          if (!frag_now->tc_frag_data.is_insn)
4389214571Sdim	    frag_wane (frag_now);
4390214571Sdim
4391214571Sdim          frag_new (0);
4392214571Sdim        }
4393214571Sdim      frag_grow (20);
4394214571Sdim
4395214571Sdim      /* Write fr_fix part.  */
4396214571Sdim      p = frag_more (inst_main.size);
4397214571Sdim      md_number_to_chars (p, inst_main.instruction, inst_main.size);
4398214571Sdim
4399214571Sdim      if (inst_main.reloc.type != BFD_RELOC_NONE)
4400214571Sdim        {
4401214571Sdim          fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4402214571Sdim                         &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4403214571Sdim        }
4404214571Sdim
4405214571Sdim#ifdef OBJ_ELF
4406214571Sdim      dwarf2_emit_insn (inst_main.size);
4407214571Sdim#endif
4408214571Sdim
4409214571Sdim      /* GP instruction can not do optimization, only can do relax between
4410214571Sdim         1 instruction and 3 instructions.  */
4411214571Sdim      p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
4412214571Sdim                    RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4413214571Sdim                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
4414214571Sdim
4415214571Sdim      /* Write fr_var part.
4416214571Sdim         no calling gen_insn_frag, no fixS will be generated.  */
4417214571Sdim      md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4418214571Sdim      p += inst_expand[0].size;
4419214571Sdim      md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4420214571Sdim      p += inst_expand[1].size;
4421214571Sdim      md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4422214571Sdim    }
4423214571Sdim  else
4424214571Sdim    {
4425214571Sdim      gen_insn_frag (&inst_expand[0], NULL);
4426214571Sdim      gen_insn_frag (&inst_expand[1], NULL);
4427214571Sdim      gen_insn_frag (&inst_expand[2], NULL);
4428214571Sdim    }
4429214571Sdim  nor1 = r1_bak;
4430214571Sdim
4431214571Sdim  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4432214571Sdim  inst.bwarn = -1;
4433214571Sdim}
4434214571Sdim
4435214571Sdimstatic void
4436214571Sdimdo_lw_pic (char *str)
4437214571Sdim{
4438214571Sdim  int reg_rd;
4439214571Sdim
4440214571Sdim  skip_whitespace (str);
4441214571Sdim  if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
4442214571Sdim      || (skip_past_comma (&str) == (int) FAIL)
4443214571Sdim      || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
4444214571Sdim      || (end_of_line (str) == (int) FAIL))
4445214571Sdim    {
4446214571Sdim      return;
4447214571Sdim    }
4448214571Sdim  else
4449214571Sdim    {
4450214571Sdim      if (inst.reloc.exp.X_add_symbol == 0)
4451214571Sdim        {
4452214571Sdim          if (!inst.error)
4453214571Sdim	    inst.error = BAD_ARGS;
4454214571Sdim
4455214571Sdim          return;
4456214571Sdim        }
4457214571Sdim
4458214571Sdim      inst.instruction |= GP << 15;
4459214571Sdim      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4460214571Sdim    }
4461214571Sdim}
4462214571Sdim
4463214571Sdimstatic void
4464214571Sdimdo_empty (char *str)
4465214571Sdim{
4466214571Sdim  str = str;
4467214571Sdim  if (university_version == 1)
4468214571Sdim    {
4469214571Sdim      if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
4470214571Sdim          || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
4471214571Sdim          || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
4472214571Sdim          || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
4473214571Sdim        {
4474214571Sdim          inst.error = ERR_FOR_SCORE5U_MMU;
4475214571Sdim          return;
4476214571Sdim        }
4477214571Sdim    }
4478214571Sdim  if (end_of_line (str) == (int) FAIL)
4479214571Sdim    return;
4480214571Sdim
4481214571Sdim  if (inst.relax_inst != 0x8000)
4482214571Sdim    {
4483214571Sdim      if (inst.type == NO_OPD)
4484214571Sdim        {
4485214571Sdim          inst.relax_size = 2;
4486214571Sdim        }
4487214571Sdim      else
4488214571Sdim        {
4489214571Sdim          inst.relax_size = 4;
4490214571Sdim        }
4491214571Sdim    }
4492214571Sdim}
4493214571Sdim
4494214571Sdimstatic void
4495214571Sdimdo_jump (char *str)
4496214571Sdim{
4497214571Sdim  char *save_in;
4498214571Sdim
4499214571Sdim  skip_whitespace (str);
4500214571Sdim  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4501214571Sdim      || end_of_line (str) == (int) FAIL)
4502214571Sdim    return;
4503214571Sdim
4504214571Sdim  if (inst.reloc.exp.X_add_symbol == 0)
4505214571Sdim    {
4506214571Sdim      inst.error = _("lacking label  ");
4507214571Sdim      return;
4508214571Sdim    }
4509214571Sdim
4510214571Sdim  if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4511214571Sdim      && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4512214571Sdim    {
4513214571Sdim      inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24");
4514214571Sdim      return;
4515214571Sdim    }
4516214571Sdim
4517214571Sdim  save_in = input_line_pointer;
4518214571Sdim  input_line_pointer = str;
4519214571Sdim  inst.reloc.type = BFD_RELOC_SCORE_JMP;
4520214571Sdim  inst.reloc.pc_rel = 1;
4521214571Sdim  input_line_pointer = save_in;
4522214571Sdim}
4523214571Sdim
4524214571Sdimstatic void
4525214571Sdimdo16_jump (char *str)
4526214571Sdim{
4527214571Sdim  skip_whitespace (str);
4528214571Sdim  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4529214571Sdim      || end_of_line (str) == (int) FAIL)
4530214571Sdim    {
4531214571Sdim      return;
4532214571Sdim    }
4533214571Sdim  else if (inst.reloc.exp.X_add_symbol == 0)
4534214571Sdim    {
4535214571Sdim      inst.error = _("lacking label  ");
4536214571Sdim      return;
4537214571Sdim    }
4538214571Sdim  else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
4539214571Sdim           && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
4540214571Sdim    {
4541214571Sdim      inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
4542214571Sdim      return;
4543214571Sdim    }
4544214571Sdim
4545214571Sdim  inst.reloc.type = BFD_RELOC_SCORE16_JMP;
4546214571Sdim  inst.reloc.pc_rel = 1;
4547214571Sdim}
4548214571Sdim
4549214571Sdimstatic void
4550214571Sdimdo_branch (char *str)
4551214571Sdim{
4552214571Sdim  unsigned long abs_value = 0;
4553214571Sdim
4554214571Sdim  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4555214571Sdim      || end_of_line (str) == (int) FAIL)
4556214571Sdim    {
4557214571Sdim      return;
4558214571Sdim    }
4559214571Sdim  else if (inst.reloc.exp.X_add_symbol == 0)
4560214571Sdim    {
4561214571Sdim      inst.error = _("lacking label  ");
4562214571Sdim      return;
4563214571Sdim    }
4564214571Sdim  else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4565214571Sdim           && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4566214571Sdim    {
4567214571Sdim      inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
4568214571Sdim      return;
4569214571Sdim    }
4570214571Sdim
4571214571Sdim  inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
4572214571Sdim  inst.reloc.pc_rel = 1;
4573214571Sdim
4574214571Sdim  /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
4575214571Sdim  inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
4576214571Sdim
4577214571Sdim  /* Compute 16 bit branch instruction.  */
4578214571Sdim  if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
4579214571Sdim    {
4580214571Sdim      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
4581214571Sdim      inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4582214571Sdim      inst.relax_size = 2;
4583214571Sdim    }
4584214571Sdim  else
4585214571Sdim    {
4586214571Sdim      inst.relax_inst = 0x8000;
4587214571Sdim    }
4588214571Sdim}
4589214571Sdim
4590214571Sdimstatic void
4591214571Sdimdo16_branch (char *str)
4592214571Sdim{
4593214571Sdim  if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4594214571Sdim      || end_of_line (str) == (int) FAIL))
4595214571Sdim    {
4596214571Sdim      ;
4597214571Sdim    }
4598214571Sdim  else if (inst.reloc.exp.X_add_symbol == 0)
4599214571Sdim    {
4600214571Sdim      inst.error = _("lacking label");
4601214571Sdim    }
4602214571Sdim  else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
4603214571Sdim           && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
4604214571Sdim    {
4605214571Sdim      inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
4606214571Sdim    }
4607214571Sdim  else
4608214571Sdim    {
4609214571Sdim      inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
4610214571Sdim      inst.reloc.pc_rel = 1;
4611214571Sdim      inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4612214571Sdim    }
4613214571Sdim}
4614214571Sdim
4615214571Sdim/* Iterate over the base tables to create the instruction patterns.  */
4616214571Sdimstatic void
4617214571Sdimbuild_score_ops_hsh (void)
4618214571Sdim{
4619214571Sdim  unsigned int i;
4620214571Sdim  static struct obstack insn_obstack;
4621214571Sdim
4622214571Sdim  obstack_begin (&insn_obstack, 4000);
4623214571Sdim  for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
4624214571Sdim    {
4625214571Sdim      const struct asm_opcode *insn = score_insns + i;
4626214571Sdim      unsigned len = strlen (insn->template);
4627214571Sdim      struct asm_opcode *new;
4628214571Sdim      char *template;
4629214571Sdim      new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
4630214571Sdim      template = obstack_alloc (&insn_obstack, len + 1);
4631214571Sdim
4632214571Sdim      strcpy (template, insn->template);
4633214571Sdim      new->template = template;
4634214571Sdim      new->parms = insn->parms;
4635214571Sdim      new->value = insn->value;
4636214571Sdim      new->relax_value = insn->relax_value;
4637214571Sdim      new->type = insn->type;
4638214571Sdim      new->bitmask = insn->bitmask;
4639214571Sdim      hash_insert (score_ops_hsh, new->template, (void *) new);
4640214571Sdim    }
4641214571Sdim}
4642214571Sdim
4643214571Sdimstatic void
4644214571Sdimbuild_dependency_insn_hsh (void)
4645214571Sdim{
4646214571Sdim  unsigned int i;
4647214571Sdim  static struct obstack dependency_obstack;
4648214571Sdim
4649214571Sdim  obstack_begin (&dependency_obstack, 4000);
4650214571Sdim  for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
4651214571Sdim    {
4652214571Sdim      const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
4653214571Sdim      unsigned len = strlen (tmp->insn_name);
4654214571Sdim      struct insn_to_dependency *new;
4655214571Sdim
4656214571Sdim      new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
4657214571Sdim      new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
4658214571Sdim
4659214571Sdim      strcpy (new->insn_name, tmp->insn_name);
4660214571Sdim      new->type = tmp->type;
4661214571Sdim      hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
4662214571Sdim    }
4663214571Sdim}
4664214571Sdim
4665214571Sdim/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4666214571Sdim   for use in the a.out file, and stores them in the array pointed to by buf.
4667214571Sdim   This knows about the endian-ness of the target machine and does
4668214571Sdim   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
4669214571Sdim   2 (short) and 4 (long)  Floating numbers are put out as a series of
4670214571Sdim   LITTLENUMS (shorts, here at least).  */
4671214571Sdim
4672214571Sdimvoid
4673214571Sdimmd_number_to_chars (char *buf, valueT val, int n)
4674214571Sdim{
4675214571Sdim  if (target_big_endian)
4676214571Sdim    number_to_chars_bigendian (buf, val, n);
4677214571Sdim  else
4678214571Sdim    number_to_chars_littleendian (buf, val, n);
4679214571Sdim}
4680214571Sdim
4681214571Sdimstatic valueT
4682214571Sdimmd_chars_to_number (char *buf, int n)
4683214571Sdim{
4684214571Sdim  valueT result = 0;
4685214571Sdim  unsigned char *where = (unsigned char *)buf;
4686214571Sdim
4687214571Sdim  if (target_big_endian)
4688214571Sdim    {
4689214571Sdim      while (n--)
4690214571Sdim        {
4691214571Sdim          result <<= 8;
4692214571Sdim          result |= (*where++ & 255);
4693214571Sdim        }
4694214571Sdim    }
4695214571Sdim  else
4696214571Sdim    {
4697214571Sdim      while (n--)
4698214571Sdim        {
4699214571Sdim          result <<= 8;
4700214571Sdim          result |= (where[n] & 255);
4701214571Sdim        }
4702214571Sdim    }
4703214571Sdim
4704214571Sdim  return result;
4705214571Sdim}
4706214571Sdim
4707214571Sdim/* Turn a string in input_line_pointer into a floating point constant
4708214571Sdim   of type TYPE, and store the appropriate bytes in *LITP.  The number
4709214571Sdim   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
4710214571Sdim   returned, or NULL on OK.
4711214571Sdim
4712214571Sdim   Note that fp constants aren't represent in the normal way on the ARM.
4713214571Sdim   In big endian mode, things are as expected.  However, in little endian
4714214571Sdim   mode fp constants are big-endian word-wise, and little-endian byte-wise
4715214571Sdim   within the words.  For example, (double) 1.1 in big endian mode is
4716214571Sdim   the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4717214571Sdim   the byte sequence 99 99 f1 3f 9a 99 99 99.  */
4718214571Sdim
4719214571Sdimchar *
4720214571Sdimmd_atof (int type, char *litP, int *sizeP)
4721214571Sdim{
4722214571Sdim  int prec;
4723214571Sdim  LITTLENUM_TYPE words[MAX_LITTLENUMS];
4724214571Sdim  char *t;
4725214571Sdim  int i;
4726214571Sdim
4727214571Sdim  switch (type)
4728214571Sdim    {
4729214571Sdim    case 'f':
4730214571Sdim    case 'F':
4731214571Sdim    case 's':
4732214571Sdim    case 'S':
4733214571Sdim      prec = 2;
4734214571Sdim      break;
4735214571Sdim    case 'd':
4736214571Sdim    case 'D':
4737214571Sdim    case 'r':
4738214571Sdim    case 'R':
4739214571Sdim      prec = 4;
4740214571Sdim      break;
4741214571Sdim    case 'x':
4742214571Sdim    case 'X':
4743214571Sdim    case 'p':
4744214571Sdim    case 'P':
4745214571Sdim      prec = 6;
4746214571Sdim      break;
4747214571Sdim    default:
4748214571Sdim      *sizeP = 0;
4749214571Sdim      return _("bad call to MD_ATOF()");
4750214571Sdim    }
4751214571Sdim
4752214571Sdim  t = atof_ieee (input_line_pointer, type, words);
4753214571Sdim  if (t)
4754214571Sdim    input_line_pointer = t;
4755214571Sdim  *sizeP = prec * 2;
4756214571Sdim
4757214571Sdim  if (target_big_endian)
4758214571Sdim    {
4759214571Sdim      for (i = 0; i < prec; i++)
4760214571Sdim        {
4761214571Sdim          md_number_to_chars (litP, (valueT) words[i], 2);
4762214571Sdim          litP += 2;
4763214571Sdim        }
4764214571Sdim    }
4765214571Sdim  else
4766214571Sdim    {
4767214571Sdim      for (i = 0; i < prec; i += 2)
4768214571Sdim        {
4769214571Sdim          md_number_to_chars (litP, (valueT) words[i + 1], 2);
4770214571Sdim          md_number_to_chars (litP + 2, (valueT) words[i], 2);
4771214571Sdim          litP += 4;
4772214571Sdim        }
4773214571Sdim    }
4774214571Sdim
4775214571Sdim  return 0;
4776214571Sdim}
4777214571Sdim
4778214571Sdim/* Return true if the given symbol should be considered local for PIC.  */
4779214571Sdim
4780214571Sdimstatic bfd_boolean
4781214571Sdimpic_need_relax (symbolS *sym, asection *segtype)
4782214571Sdim{
4783214571Sdim  asection *symsec;
4784214571Sdim  bfd_boolean linkonce;
4785214571Sdim
4786214571Sdim  /* Handle the case of a symbol equated to another symbol.  */
4787214571Sdim  while (symbol_equated_reloc_p (sym))
4788214571Sdim    {
4789214571Sdim      symbolS *n;
4790214571Sdim
4791214571Sdim      /* It's possible to get a loop here in a badly written
4792214571Sdim	 program.  */
4793214571Sdim      n = symbol_get_value_expression (sym)->X_add_symbol;
4794214571Sdim      if (n == sym)
4795214571Sdim	break;
4796214571Sdim      sym = n;
4797214571Sdim    }
4798214571Sdim
4799214571Sdim  symsec = S_GET_SEGMENT (sym);
4800214571Sdim
4801214571Sdim  /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
4802214571Sdim  linkonce = FALSE;
4803214571Sdim  if (symsec != segtype && ! S_IS_LOCAL (sym))
4804214571Sdim    {
4805214571Sdim      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
4806214571Sdim	linkonce = TRUE;
4807214571Sdim
4808214571Sdim      /* The GNU toolchain uses an extension for ELF: a section
4809214571Sdim	  beginning with the magic string .gnu.linkonce is a linkonce
4810214571Sdim	  section.  */
4811214571Sdim      if (strncmp (segment_name (symsec), ".gnu.linkonce",
4812214571Sdim		   sizeof ".gnu.linkonce" - 1) == 0)
4813214571Sdim	linkonce = TRUE;
4814214571Sdim    }
4815214571Sdim
4816214571Sdim  /* This must duplicate the test in adjust_reloc_syms.  */
4817214571Sdim  return (symsec != &bfd_und_section
4818214571Sdim	    && symsec != &bfd_abs_section
4819214571Sdim	  && ! bfd_is_com_section (symsec)
4820214571Sdim	    && !linkonce
4821214571Sdim#ifdef OBJ_ELF
4822214571Sdim	  /* A global or weak symbol is treated as external.  */
4823214571Sdim	  && (OUTPUT_FLAVOR != bfd_target_elf_flavour
4824214571Sdim	      || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
4825214571Sdim#endif
4826214571Sdim	  );
4827214571Sdim}
4828214571Sdim
4829214571Sdimstatic int
4830214571Sdimjudge_size_before_relax (fragS * fragp, asection *sec)
4831214571Sdim{
4832214571Sdim  int change = 0;
4833214571Sdim
4834214571Sdim  if (score_pic == NO_PIC)
4835214571Sdim    change = nopic_need_relax (fragp->fr_symbol, 0);
4836214571Sdim  else
4837214571Sdim    change = pic_need_relax (fragp->fr_symbol, sec);
4838214571Sdim
4839214571Sdim  if (change == 1)
4840214571Sdim    {
4841214571Sdim      /* Only at the first time determining whether GP instruction relax should be done,
4842214571Sdim         return the difference between insntruction size and instruction relax size.  */
4843214571Sdim      if (fragp->fr_opcode == NULL)
4844214571Sdim	{
4845214571Sdim	  fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
4846214571Sdim	  fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
4847214571Sdim          return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
4848214571Sdim	}
4849214571Sdim    }
4850214571Sdim
4851214571Sdim  return 0;
4852214571Sdim}
4853214571Sdim
4854214571Sdim/* In this function, we determine whether GP instruction should do relaxation,
4855214571Sdim   for the label being against was known now.
4856214571Sdim   Doing this here but not in md_relax_frag() can induce iteration times
4857214571Sdim   in stage of doing relax.  */
4858214571Sdimint
4859214571Sdimmd_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
4860214571Sdim{
4861214571Sdim  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4862214571Sdim      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4863214571Sdim    return judge_size_before_relax (fragp, sec);
4864214571Sdim
4865214571Sdim  return 0;
4866214571Sdim}
4867214571Sdim
4868214571Sdimstatic int
4869214571Sdimb32_relax_to_b16 (fragS * fragp)
4870214571Sdim{
4871214571Sdim  int grows = 0;
4872214571Sdim  int relaxable_p = 0;
4873214571Sdim  int old;
4874214571Sdim  int new;
4875214571Sdim  int frag_addr = fragp->fr_address + fragp->insn_addr;
4876214571Sdim
4877214571Sdim  addressT symbol_address = 0;
4878214571Sdim  symbolS *s;
4879214571Sdim  offsetT offset;
4880214571Sdim  unsigned long value;
4881214571Sdim  unsigned long abs_value;
4882214571Sdim
4883214571Sdim  /* FIXME : here may be able to modify better .
4884214571Sdim     I don't know how to get the fragp's section ,
4885214571Sdim     so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
4886214571Sdim     is different from the symbol's.  */
4887214571Sdim
4888214571Sdim  old = RELAX_OLD (fragp->fr_subtype);
4889214571Sdim  new = RELAX_NEW (fragp->fr_subtype);
4890214571Sdim  relaxable_p = RELAX_OPT (fragp->fr_subtype);
4891214571Sdim
4892214571Sdim  s = fragp->fr_symbol;
4893214571Sdim  /* b/bl immediate  */
4894214571Sdim  if (s == NULL)
4895214571Sdim    frag_addr = 0;
4896214571Sdim  else
4897214571Sdim    {
4898214571Sdim      if (s->bsym != 0)
4899214571Sdim	symbol_address = (addressT) s->sy_frag->fr_address;
4900214571Sdim    }
4901214571Sdim
4902214571Sdim  value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
4903214571Sdim
4904214571Sdim  /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
4905214571Sdim  offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
4906214571Sdim  if ((offset & 0x80000) == 0x80000)
4907214571Sdim    offset |= 0xfff00000;
4908214571Sdim
4909214571Sdim  abs_value = offset + symbol_address - frag_addr;
4910214571Sdim  if ((abs_value & 0x80000000) == 0x80000000)
4911214571Sdim    abs_value = 0xffffffff - abs_value + 1;
4912214571Sdim
4913214571Sdim  /* Relax branch 32 to branch 16.  */
4914214571Sdim  if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
4915214571Sdim      && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
4916214571Sdim    {
4917214571Sdim      /* do nothing.  */
4918214571Sdim    }
4919214571Sdim  else
4920214571Sdim    {
4921214571Sdim      /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
4922214571Sdim      fragp->fr_opcode = NULL;
4923214571Sdim      fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
4924214571Sdim    }
4925214571Sdim
4926214571Sdim  return grows;
4927214571Sdim}
4928214571Sdim
4929214571Sdim/* Main purpose is to determine whether one frag should do relax.
4930214571Sdim   frag->fr_opcode indicates this point.  */
4931214571Sdim
4932214571Sdimint
4933214571Sdimscore_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
4934214571Sdim{
4935214571Sdim  int grows = 0;
4936214571Sdim  int insn_size;
4937214571Sdim  int insn_relax_size;
4938214571Sdim  int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
4939214571Sdim  int relaxable_p = 0;
4940214571Sdim  bfd_boolean word_align_p = FALSE;
4941214571Sdim  fragS *next_fragp;
4942214571Sdim
4943214571Sdim  /* If the instruction address is odd, make it half word align first.  */
4944214571Sdim  if ((fragp->fr_address) % 2 != 0)
4945214571Sdim    {
4946214571Sdim      if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
4947214571Sdim	{
4948214571Sdim          fragp->insn_addr = 1;
4949214571Sdim          grows += 1;
4950214571Sdim	}
4951214571Sdim    }
4952214571Sdim
4953214571Sdim  word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
4954214571Sdim
4955214571Sdim  /* Get instruction size and relax size after the last relaxation.  */
4956214571Sdim  if (fragp->fr_opcode)
4957214571Sdim    {
4958214571Sdim      insn_size = RELAX_NEW (fragp->fr_subtype);
4959214571Sdim      insn_relax_size = RELAX_OLD (fragp->fr_subtype);
4960214571Sdim    }
4961214571Sdim  else
4962214571Sdim    {
4963214571Sdim      insn_size = RELAX_OLD (fragp->fr_subtype);
4964214571Sdim      insn_relax_size = RELAX_NEW (fragp->fr_subtype);
4965214571Sdim    }
4966214571Sdim
4967214571Sdim  /* Handle specially for GP instruction.  for, judge_size_before_relax() has already determine
4968214571Sdim     whether the GP instruction should do relax.  */
4969214571Sdim  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4970214571Sdim      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4971214571Sdim    {
4972214571Sdim      if (!word_align_p)
4973214571Sdim        {
4974214571Sdim          if (fragp->insn_addr < 2)
4975214571Sdim            {
4976214571Sdim              fragp->insn_addr += 2;
4977214571Sdim              grows += 2;
4978214571Sdim            }
4979214571Sdim          else
4980214571Sdim            {
4981214571Sdim              fragp->insn_addr -= 2;
4982214571Sdim              grows -= 2;
4983214571Sdim            }
4984214571Sdim        }
4985214571Sdim
4986214571Sdim      if (fragp->fr_opcode)
4987214571Sdim	fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
4988214571Sdim      else
4989214571Sdim	fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
4990214571Sdim    }
4991214571Sdim  else
4992214571Sdim    {
4993214571Sdim      if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
4994214571Sdim	b32_relax_to_b16 (fragp);
4995214571Sdim
4996214571Sdim      relaxable_p = RELAX_OPT (fragp->fr_subtype);
4997214571Sdim      next_fragp = fragp->fr_next;
4998214571Sdim      while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
4999214571Sdim	{
5000214571Sdim          next_fragp = next_fragp->fr_next;
5001214571Sdim	}
5002214571Sdim
5003214571Sdim      if (next_fragp)
5004214571Sdim        {
5005214571Sdim          int n_insn_size;
5006214571Sdim          int n_relaxable_p = 0;
5007214571Sdim
5008214571Sdim          if (next_fragp->fr_opcode)
5009214571Sdim            {
5010214571Sdim              n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
5011214571Sdim            }
5012214571Sdim          else
5013214571Sdim            {
5014214571Sdim              n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
5015214571Sdim            }
5016214571Sdim
5017214571Sdim          if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
5018214571Sdim            b32_relax_to_b16 (next_fragp);
5019214571Sdim          n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
5020214571Sdim
5021214571Sdim          if (word_align_p)
5022214571Sdim            {
5023214571Sdim              if (insn_size == 4)
5024214571Sdim                {
5025214571Sdim                  /* 32 -> 16.  */
5026214571Sdim                  if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
5027214571Sdim                    {
5028214571Sdim                      grows -= 2;
5029214571Sdim                      do_relax_p = 1;
5030214571Sdim                    }
5031214571Sdim                }
5032214571Sdim              else if (insn_size == 2)
5033214571Sdim                {
5034214571Sdim                  /* 16 -> 32.  */
5035214571Sdim                  if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
5036214571Sdim                    {
5037214571Sdim                      grows += 2;
5038214571Sdim                      do_relax_p = 1;
5039214571Sdim                    }
5040214571Sdim                }
5041214571Sdim              else
5042214571Sdim                {
5043214571Sdim		  abort ();
5044214571Sdim                }
5045214571Sdim            }
5046214571Sdim          else
5047214571Sdim            {
5048214571Sdim              if (insn_size == 4)
5049214571Sdim                {
5050214571Sdim                  /* 32 -> 16.  */
5051214571Sdim                  if (relaxable_p)
5052214571Sdim                    {
5053214571Sdim                      grows -= 2;
5054214571Sdim                      do_relax_p = 1;
5055214571Sdim                    }
5056214571Sdim                  /* Make the 32 bit insturction word align.  */
5057214571Sdim                  else
5058214571Sdim                    {
5059214571Sdim                      fragp->insn_addr += 2;
5060214571Sdim                      grows += 2;
5061214571Sdim		    }
5062214571Sdim                }
5063214571Sdim              else if (insn_size == 2)
5064214571Sdim                {
5065214571Sdim                  /* Do nothing.  */
5066214571Sdim                }
5067214571Sdim              else
5068214571Sdim                {
5069214571Sdim		  abort ();
5070214571Sdim                }
5071214571Sdim            }
5072214571Sdim        }
5073214571Sdim      else
5074214571Sdim        {
5075214571Sdim	  /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
5076214571Sdim          if (word_align_p == FALSE)
5077214571Sdim            {
5078214571Sdim              if (insn_size % 4 == 0)
5079214571Sdim                {
5080214571Sdim                  /* 32 -> 16.  */
5081214571Sdim                  if (relaxable_p)
5082214571Sdim                    {
5083214571Sdim                      grows -= 2;
5084214571Sdim                      do_relax_p = 1;
5085214571Sdim                    }
5086214571Sdim                  else
5087214571Sdim                    {
5088214571Sdim                      fragp->insn_addr += 2;
5089214571Sdim                      grows += 2;
5090214571Sdim                    }
5091214571Sdim                }
5092214571Sdim            }
5093214571Sdim          else
5094214571Sdim            {
5095214571Sdim	      /* Do nothing.  */
5096214571Sdim            }
5097214571Sdim        }
5098214571Sdim
5099214571Sdim      /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
5100214571Sdim      if (do_relax_p)
5101214571Sdim        {
5102214571Sdim          if (fragp->fr_opcode)
5103214571Sdim            {
5104214571Sdim              fragp->fr_opcode = NULL;
5105214571Sdim	      /* Guarantee estimate stage is correct.  */
5106214571Sdim              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5107214571Sdim              fragp->fr_fix += fragp->insn_addr;
5108214571Sdim            }
5109214571Sdim          else
5110214571Sdim            {
5111214571Sdim              fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
5112214571Sdim	      /* Guarantee estimate stage is correct.  */
5113214571Sdim              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5114214571Sdim              fragp->fr_fix += fragp->insn_addr;
5115214571Sdim            }
5116214571Sdim        }
5117214571Sdim      else
5118214571Sdim	{
5119214571Sdim          if (fragp->fr_opcode)
5120214571Sdim            {
5121214571Sdim	      /* Guarantee estimate stage is correct.  */
5122214571Sdim              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5123214571Sdim              fragp->fr_fix += fragp->insn_addr;
5124214571Sdim            }
5125214571Sdim          else
5126214571Sdim            {
5127214571Sdim	      /* Guarantee estimate stage is correct.  */
5128214571Sdim              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5129214571Sdim              fragp->fr_fix += fragp->insn_addr;
5130214571Sdim            }
5131214571Sdim	}
5132214571Sdim    }
5133214571Sdim
5134214571Sdim  return grows;
5135214571Sdim}
5136214571Sdim
5137214571Sdimvoid
5138214571Sdimmd_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
5139214571Sdim{
5140214571Sdim  int old;
5141214571Sdim  int new;
5142214571Sdim  char backup[20];
5143214571Sdim  fixS *fixp;
5144214571Sdim
5145214571Sdim  old = RELAX_OLD (fragp->fr_subtype);
5146214571Sdim  new = RELAX_NEW (fragp->fr_subtype);
5147214571Sdim
5148214571Sdim  /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
5149214571Sdim  if (fragp->fr_opcode == NULL)
5150214571Sdim    {
5151214571Sdim      memcpy (backup, fragp->fr_literal, old);
5152214571Sdim      fragp->fr_fix = old;
5153214571Sdim    }
5154214571Sdim  else
5155214571Sdim    {
5156214571Sdim      memcpy (backup, fragp->fr_literal + old, new);
5157214571Sdim      fragp->fr_fix = new;
5158214571Sdim    }
5159214571Sdim
5160214571Sdim  fixp = fragp->tc_frag_data.fixp;
5161214571Sdim  while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
5162214571Sdim    {
5163214571Sdim      if (fragp->fr_opcode)
5164214571Sdim	fixp->fx_done = 1;
5165214571Sdim      fixp = fixp->fx_next;
5166214571Sdim    }
5167214571Sdim  while (fixp && fixp->fx_frag == fragp)
5168214571Sdim    {
5169214571Sdim      if (fragp->fr_opcode)
5170214571Sdim	fixp->fx_where -= old + fragp->insn_addr;
5171214571Sdim      else
5172214571Sdim	fixp->fx_done = 1;
5173214571Sdim      fixp = fixp->fx_next;
5174214571Sdim    }
5175214571Sdim
5176214571Sdim  if (fragp->insn_addr)
5177214571Sdim    {
5178214571Sdim      md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
5179214571Sdim    }
5180214571Sdim  memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
5181214571Sdim  fragp->fr_fix += fragp->insn_addr;
5182214571Sdim}
5183214571Sdim
5184214571Sdim/* Implementation of md_frag_check.
5185214571Sdim   Called after md_convert_frag().  */
5186214571Sdim
5187214571Sdimvoid
5188214571Sdimscore_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
5189214571Sdim{
5190214571Sdim  know (fragp->insn_addr <= RELAX_PAD_BYTE);
5191214571Sdim}
5192214571Sdim
5193214571Sdimbfd_boolean
5194214571Sdimscore_fix_adjustable (fixS * fixP)
5195214571Sdim{
5196214571Sdim  if (fixP->fx_addsy == NULL)
5197214571Sdim    {
5198214571Sdim      return 1;
5199214571Sdim    }
5200214571Sdim  else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
5201214571Sdim      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
5202214571Sdim    {
5203214571Sdim      return 0;
5204214571Sdim    }
5205214571Sdim  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5206214571Sdim      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5207214571Sdim    {
5208214571Sdim      return 0;
5209214571Sdim    }
5210214571Sdim
5211214571Sdim  return 1;
5212214571Sdim}
5213214571Sdim
5214214571Sdim/* Implementation of TC_VALIDATE_FIX.
5215214571Sdim   Called before md_apply_fix() and after md_convert_frag().  */
5216214571Sdimvoid
5217214571Sdimscore_validate_fix (fixS *fixP)
5218214571Sdim{
5219214571Sdim  fixP->fx_where += fixP->fx_frag->insn_addr;
5220214571Sdim}
5221214571Sdim
5222214571Sdimlong
5223214571Sdimmd_pcrel_from (fixS * fixP)
5224214571Sdim{
5225214571Sdim  long retval = 0;
5226214571Sdim
5227214571Sdim  if (fixP->fx_addsy
5228214571Sdim      && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
5229214571Sdim      && (fixP->fx_subsy == NULL))
5230214571Sdim    {
5231214571Sdim      retval = 0;
5232214571Sdim    }
5233214571Sdim  else
5234214571Sdim    {
5235214571Sdim      retval = fixP->fx_where + fixP->fx_frag->fr_address;
5236214571Sdim    }
5237214571Sdim
5238214571Sdim  return retval;
5239214571Sdim}
5240214571Sdim
5241214571Sdimint
5242214571Sdimscore_force_relocation (struct fix *fixp)
5243214571Sdim{
5244214571Sdim  int retval = 0;
5245214571Sdim
5246214571Sdim  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5247214571Sdim      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
5248214571Sdim      || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
5249214571Sdim      || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
5250214571Sdim      || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
5251214571Sdim      || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
5252214571Sdim    {
5253214571Sdim      retval = 1;
5254214571Sdim    }
5255214571Sdim
5256214571Sdim  return retval;
5257214571Sdim}
5258214571Sdim
5259214571Sdim/* Round up a section size to the appropriate boundary.  */
5260214571SdimvalueT
5261214571Sdimmd_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5262214571Sdim{
5263214571Sdim  int align = bfd_get_section_alignment (stdoutput, segment);
5264214571Sdim
5265214571Sdim  return ((size + (1 << align) - 1) & (-1 << align));
5266214571Sdim}
5267214571Sdim
5268214571Sdimvoid
5269214571Sdimmd_apply_fix (fixS *fixP, valueT *valP, segT seg)
5270214571Sdim{
5271214571Sdim  offsetT value = *valP;
5272214571Sdim  offsetT abs_value = 0;
5273214571Sdim  offsetT newval;
5274214571Sdim  offsetT content;
5275214571Sdim  unsigned short HI, LO;
5276214571Sdim
5277214571Sdim  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
5278214571Sdim
5279214571Sdim  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5280214571Sdim  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5281214571Sdim    {
5282214571Sdim      if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
5283214571Sdim        fixP->fx_done = 1;
5284214571Sdim    }
5285214571Sdim
5286214571Sdim  /* If this symbol is in a different section then we need to leave it for
5287214571Sdim     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
5288214571Sdim     so we have to undo it's effects here.  */
5289214571Sdim  if (fixP->fx_pcrel)
5290214571Sdim    {
5291214571Sdim      if (fixP->fx_addsy != NULL
5292214571Sdim	  && S_IS_DEFINED (fixP->fx_addsy)
5293214571Sdim	  && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5294214571Sdim	value += md_pcrel_from (fixP);
5295214571Sdim    }
5296214571Sdim
5297214571Sdim  /* Remember value for emit_reloc.  */
5298214571Sdim  fixP->fx_addnumber = value;
5299214571Sdim
5300214571Sdim  switch (fixP->fx_r_type)
5301214571Sdim    {
5302214571Sdim    case BFD_RELOC_HI16_S:
5303214571Sdim      if (fixP->fx_done)
5304214571Sdim        {                       /* For la rd, imm32.  */
5305214571Sdim          newval = md_chars_to_number (buf, INSN_SIZE);
5306214571Sdim          HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
5307214571Sdim          newval |= (HI & 0x3fff) << 1;
5308214571Sdim          newval |= ((HI >> 14) & 0x3) << 16;
5309214571Sdim          md_number_to_chars (buf, newval, INSN_SIZE);
5310214571Sdim        }
5311214571Sdim      break;
5312214571Sdim    case BFD_RELOC_LO16:
5313214571Sdim      if (fixP->fx_done)        /* For la rd, imm32.  */
5314214571Sdim        {
5315214571Sdim          newval = md_chars_to_number (buf, INSN_SIZE);
5316214571Sdim          LO = (value) & 0xffff;
5317214571Sdim          newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
5318214571Sdim          newval |= ((LO >> 14) & 0x3) << 16;
5319214571Sdim          md_number_to_chars (buf, newval, INSN_SIZE);
5320214571Sdim        }
5321214571Sdim      break;
5322214571Sdim    case BFD_RELOC_SCORE_JMP:
5323214571Sdim      {
5324214571Sdim        content = md_chars_to_number (buf, INSN_SIZE);
5325214571Sdim        value = fixP->fx_offset;
5326214571Sdim        content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
5327214571Sdim        md_number_to_chars (buf, content, INSN_SIZE);
5328214571Sdim      }
5329214571Sdim      break;
5330214571Sdim    case BFD_RELOC_SCORE_BRANCH:
5331214571Sdim      if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5332214571Sdim        value = fixP->fx_offset;
5333214571Sdim      else
5334214571Sdim        fixP->fx_done = 1;
5335214571Sdim
5336214571Sdim      content = md_chars_to_number (buf, INSN_SIZE);
5337214571Sdim      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
5338214571Sdim        {
5339214571Sdim          if ((value & 0x80000000) == 0x80000000)
5340214571Sdim            abs_value = 0xffffffff - value + 1;
5341214571Sdim          if ((abs_value & 0xffffff00) != 0)
5342214571Sdim            {
5343214571Sdim              as_bad_where (fixP->fx_file, fixP->fx_line,
5344214571Sdim                            _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5345214571Sdim              return;
5346214571Sdim            }
5347214571Sdim          content = md_chars_to_number (buf, INSN16_SIZE);
5348214571Sdim          content &= 0xff00;
5349214571Sdim          content = (content & 0xff00) | ((value >> 1) & 0xff);
5350214571Sdim          md_number_to_chars (buf, content, INSN16_SIZE);
5351214571Sdim          fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
5352214571Sdim          fixP->fx_size = 2;
5353214571Sdim        }
5354214571Sdim      else
5355214571Sdim        {
5356214571Sdim          if ((value & 0x80000000) == 0x80000000)
5357214571Sdim            abs_value = 0xffffffff - value + 1;
5358214571Sdim          if ((abs_value & 0xfff80000) != 0)
5359214571Sdim            {
5360214571Sdim              as_bad_where (fixP->fx_file, fixP->fx_line,
5361214571Sdim                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5362214571Sdim              return;
5363214571Sdim            }
5364214571Sdim          content = md_chars_to_number (buf, INSN_SIZE);
5365214571Sdim          content &= 0xfc00fc01;
5366214571Sdim          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5367214571Sdim          md_number_to_chars (buf, content, INSN_SIZE);
5368214571Sdim        }
5369214571Sdim      break;
5370214571Sdim    case BFD_RELOC_SCORE16_JMP:
5371214571Sdim      content = md_chars_to_number (buf, INSN16_SIZE);
5372214571Sdim      content &= 0xf001;
5373214571Sdim      value = fixP->fx_offset & 0xfff;
5374214571Sdim      content = (content & 0xfc01) | (value & 0xffe);
5375214571Sdim      md_number_to_chars (buf, content, INSN16_SIZE);
5376214571Sdim      break;
5377214571Sdim    case BFD_RELOC_SCORE16_BRANCH:
5378214571Sdim      content = md_chars_to_number (buf, INSN_SIZE);
5379214571Sdim      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
5380214571Sdim        {
5381214571Sdim          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5382214571Sdim              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5383214571Sdim            value = fixP->fx_offset;
5384214571Sdim          else
5385214571Sdim            fixP->fx_done = 1;
5386214571Sdim          if ((value & 0x80000000) == 0x80000000)
5387214571Sdim            abs_value = 0xffffffff - value + 1;
5388214571Sdim          if ((abs_value & 0xfff80000) != 0)
5389214571Sdim            {
5390214571Sdim              as_bad_where (fixP->fx_file, fixP->fx_line,
5391214571Sdim                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5392214571Sdim              return;
5393214571Sdim            }
5394214571Sdim          content = md_chars_to_number (buf, INSN_SIZE);
5395214571Sdim          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5396214571Sdim          md_number_to_chars (buf, content, INSN_SIZE);
5397214571Sdim          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
5398214571Sdim          fixP->fx_size = 4;
5399214571Sdim          break;
5400214571Sdim        }
5401214571Sdim      else
5402214571Sdim        {
5403214571Sdim          /* In differnt section.  */
5404214571Sdim          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5405214571Sdim              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5406214571Sdim            value = fixP->fx_offset;
5407214571Sdim          else
5408214571Sdim            fixP->fx_done = 1;
5409214571Sdim
5410214571Sdim          if ((value & 0x80000000) == 0x80000000)
5411214571Sdim            abs_value = 0xffffffff - value + 1;
5412214571Sdim          if ((abs_value & 0xffffff00) != 0)
5413214571Sdim            {
5414214571Sdim              as_bad_where (fixP->fx_file, fixP->fx_line,
5415214571Sdim                            _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"), (unsigned int)value);
5416214571Sdim              return;
5417214571Sdim            }
5418214571Sdim          content = md_chars_to_number (buf, INSN16_SIZE);
5419214571Sdim          content = (content & 0xff00) | ((value >> 1) & 0xff);
5420214571Sdim          md_number_to_chars (buf, content, INSN16_SIZE);
5421214571Sdim          break;
5422214571Sdim        }
5423214571Sdim    case BFD_RELOC_8:
5424214571Sdim      if (fixP->fx_done || fixP->fx_pcrel)
5425214571Sdim	md_number_to_chars (buf, value, 1);
5426214571Sdim#ifdef OBJ_ELF
5427214571Sdim      else
5428214571Sdim        {
5429214571Sdim          value = fixP->fx_offset;
5430214571Sdim          md_number_to_chars (buf, value, 1);
5431214571Sdim        }
5432214571Sdim#endif
5433214571Sdim      break;
5434214571Sdim
5435214571Sdim    case BFD_RELOC_16:
5436214571Sdim      if (fixP->fx_done || fixP->fx_pcrel)
5437214571Sdim        md_number_to_chars (buf, value, 2);
5438214571Sdim#ifdef OBJ_ELF
5439214571Sdim      else
5440214571Sdim        {
5441214571Sdim          value = fixP->fx_offset;
5442214571Sdim          md_number_to_chars (buf, value, 2);
5443214571Sdim        }
5444214571Sdim#endif
5445214571Sdim      break;
5446214571Sdim    case BFD_RELOC_RVA:
5447214571Sdim    case BFD_RELOC_32:
5448214571Sdim      if (fixP->fx_done || fixP->fx_pcrel)
5449214571Sdim        md_number_to_chars (buf, value, 4);
5450214571Sdim#ifdef OBJ_ELF
5451214571Sdim      else
5452214571Sdim        {
5453214571Sdim          value = fixP->fx_offset;
5454214571Sdim          md_number_to_chars (buf, value, 4);
5455214571Sdim        }
5456214571Sdim#endif
5457214571Sdim      break;
5458214571Sdim    case BFD_RELOC_VTABLE_INHERIT:
5459214571Sdim      fixP->fx_done = 0;
5460214571Sdim      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
5461214571Sdim        S_SET_WEAK (fixP->fx_addsy);
5462214571Sdim      break;
5463214571Sdim    case BFD_RELOC_VTABLE_ENTRY:
5464214571Sdim      fixP->fx_done = 0;
5465214571Sdim      break;
5466214571Sdim    case BFD_RELOC_SCORE_GPREL15:
5467214571Sdim      content = md_chars_to_number (buf, INSN_SIZE);
5468214571Sdim      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
5469214571Sdim        fixP->fx_r_type = BFD_RELOC_NONE;
5470214571Sdim      fixP->fx_done = 0;
5471214571Sdim      break;
5472214571Sdim    case BFD_RELOC_SCORE_GOT15:
5473214571Sdim    case BFD_RELOC_SCORE_DUMMY_HI16:
5474214571Sdim    case BFD_RELOC_SCORE_GOT_LO16:
5475214571Sdim    case BFD_RELOC_SCORE_CALL15:
5476214571Sdim    case BFD_RELOC_GPREL32:
5477214571Sdim      break;
5478214571Sdim    case BFD_RELOC_NONE:
5479214571Sdim    default:
5480214571Sdim      as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
5481214571Sdim    }
5482214571Sdim}
5483214571Sdim
5484214571Sdim/* Translate internal representation of relocation info to BFD target format.  */
5485214571Sdimarelent **
5486214571Sdimtc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
5487214571Sdim{
5488214571Sdim  static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
5489214571Sdim  arelent *reloc;
5490214571Sdim  bfd_reloc_code_real_type code;
5491214571Sdim  char *type;
5492214571Sdim  fragS *f;
5493214571Sdim  symbolS *s;
5494214571Sdim  expressionS e;
5495214571Sdim
5496214571Sdim  reloc = retval[0] = xmalloc (sizeof (arelent));
5497214571Sdim  retval[1] = NULL;
5498214571Sdim
5499214571Sdim  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5500214571Sdim  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5501214571Sdim  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5502214571Sdim  reloc->addend = fixp->fx_offset;
5503214571Sdim
5504214571Sdim  /* If this is a variant frag, we may need to adjust the existing
5505214571Sdim     reloc and generate a new one.  */
5506214571Sdim  if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
5507214571Sdim    {
5508214571Sdim      /* Update instruction imm bit.  */
5509214571Sdim      offsetT newval;
5510214571Sdim      unsigned short off;
5511214571Sdim      char *buf;
5512214571Sdim
5513214571Sdim      buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
5514214571Sdim      newval = md_chars_to_number (buf, INSN_SIZE);
5515214571Sdim      off = fixp->fx_offset >> 16;
5516214571Sdim      newval |= (off & 0x3fff) << 1;
5517214571Sdim      newval |= ((off >> 14) & 0x3) << 16;
5518214571Sdim      md_number_to_chars (buf, newval, INSN_SIZE);
5519214571Sdim
5520214571Sdim      buf += INSN_SIZE;
5521214571Sdim      newval = md_chars_to_number (buf, INSN_SIZE);
5522214571Sdim      off = fixp->fx_offset & 0xffff;
5523214571Sdim      newval |= ((off & 0x3fff) << 1);
5524214571Sdim      newval |= (((off >> 14) & 0x3) << 16);
5525214571Sdim      md_number_to_chars (buf, newval, INSN_SIZE);
5526214571Sdim
5527214571Sdim      retval[1] = xmalloc (sizeof (arelent));
5528214571Sdim      retval[2] = NULL;
5529214571Sdim      retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5530214571Sdim      *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5531214571Sdim      retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
5532214571Sdim
5533214571Sdim      f = fixp->fx_frag;
5534214571Sdim      s = f->fr_symbol;
5535214571Sdim      e = s->sy_value;
5536214571Sdim
5537214571Sdim      retval[1]->addend = 0;
5538214571Sdim      retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
5539214571Sdim      assert (retval[1]->howto != NULL);
5540214571Sdim
5541214571Sdim      fixp->fx_r_type = BFD_RELOC_HI16_S;
5542214571Sdim    }
5543214571Sdim
5544214571Sdim  code = fixp->fx_r_type;
5545214571Sdim  switch (fixp->fx_r_type)
5546214571Sdim    {
5547214571Sdim    case BFD_RELOC_32:
5548214571Sdim      if (fixp->fx_pcrel)
5549214571Sdim        {
5550214571Sdim          code = BFD_RELOC_32_PCREL;
5551214571Sdim          break;
5552214571Sdim        }
5553214571Sdim    case BFD_RELOC_HI16_S:
5554214571Sdim    case BFD_RELOC_LO16:
5555214571Sdim    case BFD_RELOC_SCORE_JMP:
5556214571Sdim    case BFD_RELOC_SCORE_BRANCH:
5557214571Sdim    case BFD_RELOC_SCORE16_JMP:
5558214571Sdim    case BFD_RELOC_SCORE16_BRANCH:
5559214571Sdim    case BFD_RELOC_VTABLE_ENTRY:
5560214571Sdim    case BFD_RELOC_VTABLE_INHERIT:
5561214571Sdim    case BFD_RELOC_SCORE_GPREL15:
5562214571Sdim    case BFD_RELOC_SCORE_GOT15:
5563214571Sdim    case BFD_RELOC_SCORE_DUMMY_HI16:
5564214571Sdim    case BFD_RELOC_SCORE_GOT_LO16:
5565214571Sdim    case BFD_RELOC_SCORE_CALL15:
5566214571Sdim    case BFD_RELOC_GPREL32:
5567214571Sdim    case BFD_RELOC_NONE:
5568214571Sdim      code = fixp->fx_r_type;
5569214571Sdim      break;
5570214571Sdim    default:
5571214571Sdim      type = _("<unknown>");
5572214571Sdim      as_bad_where (fixp->fx_file, fixp->fx_line,
5573214571Sdim                    _("cannot represent %s relocation in this object file format"), type);
5574214571Sdim      return NULL;
5575214571Sdim    }
5576214571Sdim
5577214571Sdim  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5578214571Sdim  if (reloc->howto == NULL)
5579214571Sdim    {
5580214571Sdim      as_bad_where (fixp->fx_file, fixp->fx_line,
5581214571Sdim                    _("cannot represent %s relocation in this object file format1"),
5582214571Sdim                    bfd_get_reloc_code_name (code));
5583214571Sdim      return NULL;
5584214571Sdim    }
5585214571Sdim  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5586214571Sdim     vtable entry to be used in the relocation's section offset.  */
5587214571Sdim  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5588214571Sdim    reloc->address = fixp->fx_offset;
5589214571Sdim
5590214571Sdim  return retval;
5591214571Sdim}
5592214571Sdim
5593214571Sdimvoid
5594214571Sdimscore_elf_final_processing (void)
5595214571Sdim{
5596214571Sdim  if (fix_data_dependency == 1)
5597214571Sdim    {
5598214571Sdim      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
5599214571Sdim    }
5600214571Sdim  if (score_pic == PIC)
5601214571Sdim    {
5602214571Sdim      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
5603214571Sdim    }
5604214571Sdim}
5605214571Sdim
5606214571Sdimstatic void
5607214571Sdimparse_pce_inst (char *insnstr)
5608214571Sdim{
5609214571Sdim  char c;
5610214571Sdim  char *p;
5611214571Sdim  char first[MAX_LITERAL_POOL_SIZE];
5612214571Sdim  char second[MAX_LITERAL_POOL_SIZE];
5613214571Sdim  struct score_it pec_part_1;
5614214571Sdim
5615214571Sdim  /* Get first part string of PCE.  */
5616214571Sdim  p = strstr (insnstr, "||");
5617214571Sdim  c = *p;
5618214571Sdim  *p = '\0';
5619214571Sdim  sprintf (first, "%s", insnstr);
5620214571Sdim
5621214571Sdim  /* Get second part string of PCE.  */
5622214571Sdim  *p = c;
5623214571Sdim  p += 2;
5624214571Sdim  sprintf (second, "%s", p);
5625214571Sdim
5626214571Sdim  parse_16_32_inst (first, FALSE);
5627214571Sdim  if (inst.error)
5628214571Sdim    return;
5629214571Sdim
5630214571Sdim  memcpy (&pec_part_1, &inst, sizeof (inst));
5631214571Sdim
5632214571Sdim  parse_16_32_inst (second, FALSE);
5633214571Sdim  if (inst.error)
5634214571Sdim    return;
5635214571Sdim
5636214571Sdim  if (   ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
5637214571Sdim      || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
5638214571Sdim      || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
5639214571Sdim    {
5640214571Sdim      inst.error = _("pce instruction error (16 bit || 16 bit)'");
5641214571Sdim      sprintf (inst.str, insnstr);
5642214571Sdim      return;
5643214571Sdim    }
5644214571Sdim
5645214571Sdim  if (!inst.error)
5646214571Sdim    gen_insn_frag (&pec_part_1, &inst);
5647214571Sdim}
5648214571Sdim
5649214571Sdimvoid
5650214571Sdimmd_assemble (char *str)
5651214571Sdim{
5652214571Sdim  know (str);
5653214571Sdim  know (strlen (str) < MAX_LITERAL_POOL_SIZE);
5654214571Sdim
5655214571Sdim  memset (&inst, '\0', sizeof (inst));
5656214571Sdim  if (INSN_IS_PCE_P (str))
5657214571Sdim    parse_pce_inst (str);
5658214571Sdim  else
5659214571Sdim    parse_16_32_inst (str, TRUE);
5660214571Sdim
5661214571Sdim  if (inst.error)
5662214571Sdim    as_bad (_("%s -- `%s'"), inst.error, inst.str);
5663214571Sdim}
5664214571Sdim
5665214571Sdim/* We handle all bad expressions here, so that we can report the faulty
5666214571Sdim   instruction in the error message.  */
5667214571Sdimvoid
5668214571Sdimmd_operand (expressionS * expr)
5669214571Sdim{
5670214571Sdim  if (in_my_get_expression)
5671214571Sdim    {
5672214571Sdim      expr->X_op = O_illegal;
5673214571Sdim      if (inst.error == NULL)
5674214571Sdim        {
5675214571Sdim          inst.error = _("bad expression");
5676214571Sdim        }
5677214571Sdim    }
5678214571Sdim}
5679214571Sdim
5680214571Sdimconst char *md_shortopts = "nO::g::G:";
5681214571Sdim
5682214571Sdim#ifdef SCORE_BI_ENDIAN
5683214571Sdim#define OPTION_EB             (OPTION_MD_BASE + 0)
5684214571Sdim#define OPTION_EL             (OPTION_MD_BASE + 1)
5685214571Sdim#else
5686214571Sdim#if TARGET_BYTES_BIG_ENDIAN
5687214571Sdim#define OPTION_EB             (OPTION_MD_BASE + 0)
5688214571Sdim#else
5689214571Sdim#define OPTION_EL             (OPTION_MD_BASE + 1)
5690214571Sdim#endif
5691214571Sdim#endif
5692214571Sdim#define OPTION_FIXDD          (OPTION_MD_BASE + 2)
5693214571Sdim#define OPTION_NWARN          (OPTION_MD_BASE + 3)
5694214571Sdim#define OPTION_SCORE5         (OPTION_MD_BASE + 4)
5695214571Sdim#define OPTION_SCORE5U        (OPTION_MD_BASE + 5)
5696214571Sdim#define OPTION_SCORE7         (OPTION_MD_BASE + 6)
5697214571Sdim#define OPTION_R1             (OPTION_MD_BASE + 7)
5698214571Sdim#define OPTION_O0             (OPTION_MD_BASE + 8)
5699214571Sdim#define OPTION_SCORE_VERSION  (OPTION_MD_BASE + 9)
5700214571Sdim#define OPTION_PIC            (OPTION_MD_BASE + 10)
5701214571Sdim
5702214571Sdimstruct option md_longopts[] =
5703214571Sdim{
5704214571Sdim#ifdef OPTION_EB
5705214571Sdim  {"EB"     , no_argument, NULL, OPTION_EB},
5706214571Sdim#endif
5707214571Sdim#ifdef OPTION_EL
5708214571Sdim  {"EL"     , no_argument, NULL, OPTION_EL},
5709214571Sdim#endif
5710214571Sdim  {"FIXDD"  , no_argument, NULL, OPTION_FIXDD},
5711214571Sdim  {"NWARN"  , no_argument, NULL, OPTION_NWARN},
5712214571Sdim  {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
5713214571Sdim  {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
5714214571Sdim  {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
5715214571Sdim  {"USE_R1" , no_argument, NULL, OPTION_R1},
5716214571Sdim  {"O0"     , no_argument, NULL, OPTION_O0},
5717214571Sdim  {"V"      , no_argument, NULL, OPTION_SCORE_VERSION},
5718214571Sdim  {"KPIC"   , no_argument, NULL, OPTION_PIC},
5719214571Sdim  {NULL     , no_argument, NULL, 0}
5720214571Sdim};
5721214571Sdim
5722214571Sdimsize_t md_longopts_size = sizeof (md_longopts);
5723214571Sdim
5724214571Sdimint
5725214571Sdimmd_parse_option (int c, char *arg)
5726214571Sdim{
5727214571Sdim  switch (c)
5728214571Sdim    {
5729214571Sdim#ifdef OPTION_EB
5730214571Sdim    case OPTION_EB:
5731214571Sdim      target_big_endian = 1;
5732214571Sdim      break;
5733214571Sdim#endif
5734214571Sdim#ifdef OPTION_EL
5735214571Sdim    case OPTION_EL:
5736214571Sdim      target_big_endian = 0;
5737214571Sdim      break;
5738214571Sdim#endif
5739214571Sdim    case OPTION_FIXDD:
5740214571Sdim      fix_data_dependency = 1;
5741214571Sdim      break;
5742214571Sdim    case OPTION_NWARN:
5743214571Sdim      warn_fix_data_dependency = 0;
5744214571Sdim      break;
5745214571Sdim    case OPTION_SCORE5:
5746214571Sdim      score7 = 0;
5747214571Sdim      university_version = 0;
5748214571Sdim      vector_size = SCORE5_PIPELINE;
5749214571Sdim      break;
5750214571Sdim    case OPTION_SCORE5U:
5751214571Sdim      score7 = 0;
5752214571Sdim      university_version = 1;
5753214571Sdim      vector_size = SCORE5_PIPELINE;
5754214571Sdim      break;
5755214571Sdim    case OPTION_SCORE7:
5756214571Sdim      score7 = 1;
5757214571Sdim      university_version = 0;
5758214571Sdim      vector_size = SCORE7_PIPELINE;
5759214571Sdim      break;
5760214571Sdim    case OPTION_R1:
5761214571Sdim      nor1 = 0;
5762214571Sdim      break;
5763214571Sdim    case 'G':
5764214571Sdim      g_switch_value = atoi (arg);
5765214571Sdim      break;
5766214571Sdim    case OPTION_O0:
5767214571Sdim      g_opt = 0;
5768214571Sdim      break;
5769214571Sdim    case OPTION_SCORE_VERSION:
5770214571Sdim      printf (_("Sunplus-v2-0-0-20060510\n"));
5771214571Sdim      break;
5772214571Sdim    case OPTION_PIC:
5773214571Sdim      score_pic = PIC;
5774214571Sdim      g_switch_value = 0;    /* Must set -G num as 0 to generate PIC code.  */
5775214571Sdim      break;
5776214571Sdim    default:
5777214571Sdim      /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");  */
5778214571Sdim      return 0;
5779214571Sdim    }
5780214571Sdim  return 1;
5781214571Sdim}
5782214571Sdim
5783214571Sdimvoid
5784214571Sdimmd_show_usage (FILE * fp)
5785214571Sdim{
5786214571Sdim  fprintf (fp, _(" Score-specific assembler options:\n"));
5787214571Sdim#ifdef OPTION_EB
5788214571Sdim  fprintf (fp, _("\
5789214571Sdim        -EB\t\tassemble code for a big-endian cpu\n"));
5790214571Sdim#endif
5791214571Sdim
5792214571Sdim#ifdef OPTION_EL
5793214571Sdim  fprintf (fp, _("\
5794214571Sdim        -EL\t\tassemble code for a little-endian cpu\n"));
5795214571Sdim#endif
5796214571Sdim
5797214571Sdim  fprintf (fp, _("\
5798214571Sdim        -FIXDD\t\tassemble code for fix data dependency\n"));
5799214571Sdim  fprintf (fp, _("\
5800214571Sdim        -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
5801214571Sdim  fprintf (fp, _("\
5802214571Sdim        -SCORE5\t\tassemble code for target is SCORE5\n"));
5803214571Sdim  fprintf (fp, _("\
5804214571Sdim        -SCORE5U\tassemble code for target is SCORE5U\n"));
5805214571Sdim  fprintf (fp, _("\
5806214571Sdim        -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
5807214571Sdim  fprintf (fp, _("\
5808214571Sdim        -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
5809214571Sdim  fprintf (fp, _("\
5810214571Sdim        -KPIC\t\tassemble code for PIC\n"));
5811214571Sdim  fprintf (fp, _("\
5812214571Sdim        -O0\t\tassembler will not perform any optimizations\n"));
5813214571Sdim  fprintf (fp, _("\
5814214571Sdim        -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
5815214571Sdim  fprintf (fp, _("\
5816214571Sdim        -V \t\tSunplus release version \n"));
5817214571Sdim}
5818214571Sdim
5819214571Sdim
5820214571Sdim/* Pesudo handling functions.  */
5821214571Sdim
5822214571Sdim/* If we change section we must dump the literal pool first.  */
5823214571Sdimstatic void
5824214571Sdims_score_bss (int ignore ATTRIBUTE_UNUSED)
5825214571Sdim{
5826214571Sdim  subseg_set (bss_section, (subsegT) get_absolute_expression ());
5827214571Sdim  demand_empty_rest_of_line ();
5828214571Sdim}
5829214571Sdim
5830214571Sdimstatic void
5831214571Sdims_score_text (int ignore)
5832214571Sdim{
5833214571Sdim  obj_elf_text (ignore);
5834214571Sdim  record_alignment (now_seg, 2);
5835214571Sdim}
5836214571Sdim
5837214571Sdimstatic void
5838214571Sdimscore_s_section (int ignore)
5839214571Sdim{
5840214571Sdim  obj_elf_section (ignore);
5841214571Sdim  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5842214571Sdim    record_alignment (now_seg, 2);
5843214571Sdim
5844214571Sdim}
5845214571Sdim
5846214571Sdimstatic void
5847214571Sdims_change_sec (int sec)
5848214571Sdim{
5849214571Sdim  segT seg;
5850214571Sdim
5851214571Sdim#ifdef OBJ_ELF
5852214571Sdim  /* The ELF backend needs to know that we are changing sections, so
5853214571Sdim     that .previous works correctly.  We could do something like check
5854214571Sdim     for an obj_section_change_hook macro, but that might be confusing
5855214571Sdim     as it would not be appropriate to use it in the section changing
5856214571Sdim     functions in read.c, since obj-elf.c intercepts those.  FIXME:
5857214571Sdim     This should be cleaner, somehow.  */
5858214571Sdim  obj_elf_section_change_hook ();
5859214571Sdim#endif
5860214571Sdim  switch (sec)
5861214571Sdim    {
5862214571Sdim    case 'r':
5863214571Sdim      seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5864214571Sdim      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5865214571Sdim      if (strcmp (TARGET_OS, "elf") != 0)
5866214571Sdim        record_alignment (seg, 4);
5867214571Sdim      demand_empty_rest_of_line ();
5868214571Sdim      break;
5869214571Sdim    case 's':
5870214571Sdim      seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5871214571Sdim      bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5872214571Sdim      if (strcmp (TARGET_OS, "elf") != 0)
5873214571Sdim        record_alignment (seg, 4);
5874214571Sdim      demand_empty_rest_of_line ();
5875214571Sdim      break;
5876214571Sdim    }
5877214571Sdim}
5878214571Sdim
5879214571Sdimstatic void
5880214571Sdims_score_mask (int reg_type ATTRIBUTE_UNUSED)
5881214571Sdim{
5882214571Sdim  long mask, off;
5883214571Sdim
5884214571Sdim  if (cur_proc_ptr == (procS *) NULL)
5885214571Sdim    {
5886214571Sdim      as_warn (_(".mask outside of .ent"));
5887214571Sdim      demand_empty_rest_of_line ();
5888214571Sdim      return;
5889214571Sdim    }
5890214571Sdim  if (get_absolute_expression_and_terminator (&mask) != ',')
5891214571Sdim    {
5892214571Sdim      as_warn (_("Bad .mask directive"));
5893214571Sdim      --input_line_pointer;
5894214571Sdim      demand_empty_rest_of_line ();
5895214571Sdim      return;
5896214571Sdim    }
5897214571Sdim  off = get_absolute_expression ();
5898214571Sdim  cur_proc_ptr->reg_mask = mask;
5899214571Sdim  cur_proc_ptr->reg_offset = off;
5900214571Sdim  demand_empty_rest_of_line ();
5901214571Sdim}
5902214571Sdim
5903214571Sdimstatic symbolS *
5904214571Sdimget_symbol (void)
5905214571Sdim{
5906214571Sdim  int c;
5907214571Sdim  char *name;
5908214571Sdim  symbolS *p;
5909214571Sdim
5910214571Sdim  name = input_line_pointer;
5911214571Sdim  c = get_symbol_end ();
5912214571Sdim  p = (symbolS *) symbol_find_or_make (name);
5913214571Sdim  *input_line_pointer = c;
5914214571Sdim  return p;
5915214571Sdim}
5916214571Sdim
5917214571Sdimstatic long
5918214571Sdimget_number (void)
5919214571Sdim{
5920214571Sdim  int negative = 0;
5921214571Sdim  long val = 0;
5922214571Sdim
5923214571Sdim  if (*input_line_pointer == '-')
5924214571Sdim    {
5925214571Sdim      ++input_line_pointer;
5926214571Sdim      negative = 1;
5927214571Sdim    }
5928214571Sdim  if (!ISDIGIT (*input_line_pointer))
5929214571Sdim    as_bad (_("expected simple number"));
5930214571Sdim  if (input_line_pointer[0] == '0')
5931214571Sdim    {
5932214571Sdim      if (input_line_pointer[1] == 'x')
5933214571Sdim        {
5934214571Sdim          input_line_pointer += 2;
5935214571Sdim          while (ISXDIGIT (*input_line_pointer))
5936214571Sdim            {
5937214571Sdim              val <<= 4;
5938214571Sdim              val |= hex_value (*input_line_pointer++);
5939214571Sdim            }
5940214571Sdim          return negative ? -val : val;
5941214571Sdim        }
5942214571Sdim      else
5943214571Sdim        {
5944214571Sdim          ++input_line_pointer;
5945214571Sdim          while (ISDIGIT (*input_line_pointer))
5946214571Sdim            {
5947214571Sdim              val <<= 3;
5948214571Sdim              val |= *input_line_pointer++ - '0';
5949214571Sdim            }
5950214571Sdim          return negative ? -val : val;
5951214571Sdim        }
5952214571Sdim    }
5953214571Sdim  if (!ISDIGIT (*input_line_pointer))
5954214571Sdim    {
5955214571Sdim      printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5956214571Sdim      as_warn (_("invalid number"));
5957214571Sdim      return -1;
5958214571Sdim    }
5959214571Sdim  while (ISDIGIT (*input_line_pointer))
5960214571Sdim    {
5961214571Sdim      val *= 10;
5962214571Sdim      val += *input_line_pointer++ - '0';
5963214571Sdim    }
5964214571Sdim  return negative ? -val : val;
5965214571Sdim}
5966214571Sdim
5967214571Sdim/* The .aent and .ent directives.  */
5968214571Sdim
5969214571Sdimstatic void
5970214571Sdims_score_ent (int aent)
5971214571Sdim{
5972214571Sdim  symbolS *symbolP;
5973214571Sdim  int maybe_text;
5974214571Sdim
5975214571Sdim  symbolP = get_symbol ();
5976214571Sdim  if (*input_line_pointer == ',')
5977214571Sdim    ++input_line_pointer;
5978214571Sdim  SKIP_WHITESPACE ();
5979214571Sdim  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5980214571Sdim    get_number ();
5981214571Sdim
5982214571Sdim#ifdef BFD_ASSEMBLER
5983214571Sdim  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5984214571Sdim    maybe_text = 1;
5985214571Sdim  else
5986214571Sdim    maybe_text = 0;
5987214571Sdim#else
5988214571Sdim  if (now_seg != data_section && now_seg != bss_section)
5989214571Sdim    maybe_text = 1;
5990214571Sdim  else
5991214571Sdim    maybe_text = 0;
5992214571Sdim#endif
5993214571Sdim  if (!maybe_text)
5994214571Sdim    as_warn (_(".ent or .aent not in text section."));
5995214571Sdim  if (!aent && cur_proc_ptr)
5996214571Sdim    as_warn (_("missing .end"));
5997214571Sdim  if (!aent)
5998214571Sdim    {
5999214571Sdim      cur_proc_ptr = &cur_proc;
6000214571Sdim      cur_proc_ptr->reg_mask = 0xdeadbeaf;
6001214571Sdim      cur_proc_ptr->reg_offset = 0xdeadbeaf;
6002214571Sdim      cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
6003214571Sdim      cur_proc_ptr->leaf = 0xdeafbeaf;
6004214571Sdim      cur_proc_ptr->frame_offset = 0xdeafbeaf;
6005214571Sdim      cur_proc_ptr->frame_reg = 0xdeafbeaf;
6006214571Sdim      cur_proc_ptr->pc_reg = 0xdeafbeaf;
6007214571Sdim      cur_proc_ptr->isym = symbolP;
6008214571Sdim      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
6009214571Sdim      ++numprocs;
6010214571Sdim      if (debug_type == DEBUG_STABS)
6011214571Sdim        stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
6012214571Sdim    }
6013214571Sdim  demand_empty_rest_of_line ();
6014214571Sdim}
6015214571Sdim
6016214571Sdimstatic void
6017214571Sdims_score_frame (int ignore ATTRIBUTE_UNUSED)
6018214571Sdim{
6019214571Sdim  char *backupstr;
6020214571Sdim  char str[30];
6021214571Sdim  long val;
6022214571Sdim  int i = 0;
6023214571Sdim
6024214571Sdim  backupstr = input_line_pointer;
6025214571Sdim
6026214571Sdim#ifdef OBJ_ELF
6027214571Sdim  if (cur_proc_ptr == (procS *) NULL)
6028214571Sdim    {
6029214571Sdim      as_warn (_(".frame outside of .ent"));
6030214571Sdim      demand_empty_rest_of_line ();
6031214571Sdim      return;
6032214571Sdim    }
6033214571Sdim  cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6034214571Sdim  SKIP_WHITESPACE ();
6035214571Sdim  skip_past_comma (&backupstr);
6036214571Sdim  while (*backupstr != ',')
6037214571Sdim    {
6038214571Sdim      str[i] = *backupstr;
6039214571Sdim      i++;
6040214571Sdim      backupstr++;
6041214571Sdim    }
6042214571Sdim  str[i] = '\0';
6043214571Sdim  val = atoi (str);
6044214571Sdim
6045214571Sdim  SKIP_WHITESPACE ();
6046214571Sdim  skip_past_comma (&backupstr);
6047214571Sdim  cur_proc_ptr->frame_offset = val;
6048214571Sdim  cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6049214571Sdim
6050214571Sdim  SKIP_WHITESPACE ();
6051214571Sdim  skip_past_comma (&backupstr);
6052214571Sdim  i = 0;
6053214571Sdim  while (*backupstr != '\n')
6054214571Sdim    {
6055214571Sdim      str[i] = *backupstr;
6056214571Sdim      i++;
6057214571Sdim      backupstr++;
6058214571Sdim    }
6059214571Sdim  str[i] = '\0';
6060214571Sdim  val = atoi (str);
6061214571Sdim  cur_proc_ptr->leaf = val;
6062214571Sdim  SKIP_WHITESPACE ();
6063214571Sdim  skip_past_comma (&backupstr);
6064214571Sdim
6065214571Sdim#endif /* OBJ_ELF */
6066214571Sdim  while (input_line_pointer != backupstr)
6067214571Sdim    input_line_pointer++;
6068214571Sdim}
6069214571Sdim
6070214571Sdim/* The .end directive.  */
6071214571Sdimstatic void
6072214571Sdims_score_end (int x ATTRIBUTE_UNUSED)
6073214571Sdim{
6074214571Sdim  symbolS *p;
6075214571Sdim  int maybe_text;
6076214571Sdim
6077214571Sdim  /* Generate a .pdr section.  */
6078214571Sdim  segT saved_seg = now_seg;
6079214571Sdim  subsegT saved_subseg = now_subseg;
6080214571Sdim  valueT dot;
6081214571Sdim  expressionS exp;
6082214571Sdim  char *fragp;
6083214571Sdim
6084214571Sdim  if (!is_end_of_line[(unsigned char)*input_line_pointer])
6085214571Sdim    {
6086214571Sdim      p = get_symbol ();
6087214571Sdim      demand_empty_rest_of_line ();
6088214571Sdim    }
6089214571Sdim  else
6090214571Sdim    p = NULL;
6091214571Sdim
6092214571Sdim#ifdef BFD_ASSEMBLER
6093214571Sdim  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
6094214571Sdim    maybe_text = 1;
6095214571Sdim  else
6096214571Sdim    maybe_text = 0;
6097214571Sdim#else
6098214571Sdim  if (now_seg != data_section && now_seg != bss_section)
6099214571Sdim    maybe_text = 1;
6100214571Sdim  else
6101214571Sdim    maybe_text = 0;
6102214571Sdim#endif
6103214571Sdim
6104214571Sdim  if (!maybe_text)
6105214571Sdim    as_warn (_(".end not in text section"));
6106214571Sdim  if (!cur_proc_ptr)
6107214571Sdim    {
6108214571Sdim      as_warn (_(".end directive without a preceding .ent directive."));
6109214571Sdim      demand_empty_rest_of_line ();
6110214571Sdim      return;
6111214571Sdim    }
6112214571Sdim  if (p != NULL)
6113214571Sdim    {
6114214571Sdim      assert (S_GET_NAME (p));
6115214571Sdim      if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
6116214571Sdim        as_warn (_(".end symbol does not match .ent symbol."));
6117214571Sdim      if (debug_type == DEBUG_STABS)
6118214571Sdim        stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
6119214571Sdim    }
6120214571Sdim  else
6121214571Sdim    as_warn (_(".end directive missing or unknown symbol"));
6122214571Sdim
6123214571Sdim  if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
6124214571Sdim      (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
6125214571Sdim      (cur_proc_ptr->leaf == 0xdeafbeaf) ||
6126214571Sdim      (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
6127214571Sdim      (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
6128214571Sdim
6129214571Sdim  else
6130214571Sdim    {
6131214571Sdim      dot = frag_now_fix ();
6132214571Sdim      assert (pdr_seg);
6133214571Sdim      subseg_set (pdr_seg, 0);
6134214571Sdim      /* Write the symbol.  */
6135214571Sdim      exp.X_op = O_symbol;
6136214571Sdim      exp.X_add_symbol = p;
6137214571Sdim      exp.X_add_number = 0;
6138214571Sdim      emit_expr (&exp, 4);
6139214571Sdim      fragp = frag_more (7 * 4);
6140214571Sdim      md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
6141214571Sdim      md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
6142214571Sdim      md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
6143214571Sdim      md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
6144214571Sdim      md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
6145214571Sdim      md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
6146214571Sdim      md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
6147214571Sdim      subseg_set (saved_seg, saved_subseg);
6148214571Sdim
6149214571Sdim    }
6150214571Sdim  cur_proc_ptr = NULL;
6151214571Sdim}
6152214571Sdim
6153214571Sdim/* Handle the .set pseudo-op.  */
6154214571Sdimstatic void
6155214571Sdims_score_set (int x ATTRIBUTE_UNUSED)
6156214571Sdim{
6157214571Sdim  int i = 0;
6158214571Sdim  char name[MAX_LITERAL_POOL_SIZE];
6159214571Sdim  char * orig_ilp = input_line_pointer;
6160214571Sdim
6161214571Sdim  while (!is_end_of_line[(unsigned char)*input_line_pointer])
6162214571Sdim    {
6163214571Sdim      name[i] = (char) * input_line_pointer;
6164214571Sdim      i++;
6165214571Sdim      ++input_line_pointer;
6166214571Sdim    }
6167214571Sdim
6168214571Sdim  name[i] = '\0';
6169214571Sdim
6170214571Sdim  if (strcmp (name, "nwarn") == 0)
6171214571Sdim    {
6172214571Sdim      warn_fix_data_dependency = 0;
6173214571Sdim    }
6174214571Sdim  else if (strcmp (name, "fixdd") == 0)
6175214571Sdim    {
6176214571Sdim      fix_data_dependency = 1;
6177214571Sdim    }
6178214571Sdim  else if (strcmp (name, "nofixdd") == 0)
6179214571Sdim    {
6180214571Sdim      fix_data_dependency = 0;
6181214571Sdim    }
6182214571Sdim  else if (strcmp (name, "r1") == 0)
6183214571Sdim    {
6184214571Sdim      nor1 = 0;
6185214571Sdim    }
6186214571Sdim  else if (strcmp (name, "nor1") == 0)
6187214571Sdim    {
6188214571Sdim      nor1 = 1;
6189214571Sdim    }
6190214571Sdim  else if (strcmp (name, "optimize") == 0)
6191214571Sdim    {
6192214571Sdim      g_opt = 1;
6193214571Sdim    }
6194214571Sdim  else if (strcmp (name, "volatile") == 0)
6195214571Sdim    {
6196214571Sdim      g_opt = 0;
6197214571Sdim    }
6198214571Sdim  else if (strcmp (name, "pic") == 0)
6199214571Sdim    {
6200214571Sdim      score_pic = PIC;
6201214571Sdim    }
6202214571Sdim  else
6203214571Sdim    {
6204214571Sdim      input_line_pointer = orig_ilp;
6205214571Sdim      s_set (0);
6206214571Sdim    }
6207214571Sdim}
6208214571Sdim
6209214571Sdim/* Handle the .cpload pseudo-op.  This is used when generating PIC code.  It sets the
6210214571Sdim   $gp register for the function based on the function address, which is in the register
6211214571Sdim   named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
6212214571Sdim   specially by the linker.  The result is:
6213214571Sdim   ldis gp, %hi(GP_DISP_LABEL)
6214214571Sdim   ori  gp, %low(GP_DISP_LABEL)
6215214571Sdim   add  gp, gp, .cpload argument
6216214571Sdim   The .cpload argument is normally r29.  */
6217214571Sdim
6218214571Sdimstatic void
6219214571Sdims_score_cpload (int ignore ATTRIBUTE_UNUSED)
6220214571Sdim{
6221214571Sdim  int reg;
6222214571Sdim  char insn_str[MAX_LITERAL_POOL_SIZE];
6223214571Sdim
6224214571Sdim  /* If we are not generating PIC code, .cpload is ignored.  */
6225214571Sdim  if (score_pic == NO_PIC)
6226214571Sdim    {
6227214571Sdim      s_ignore (0);
6228214571Sdim      return;
6229214571Sdim    }
6230214571Sdim
6231214571Sdim  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6232214571Sdim    return;
6233214571Sdim
6234214571Sdim  demand_empty_rest_of_line ();
6235214571Sdim
6236214571Sdim  sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
6237214571Sdim  if (append_insn (insn_str, TRUE) == (int) FAIL)
6238214571Sdim    return;
6239214571Sdim
6240214571Sdim  sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
6241214571Sdim  if (append_insn (insn_str, TRUE) == (int) FAIL)
6242214571Sdim    return;
6243214571Sdim
6244214571Sdim  sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
6245214571Sdim  if (append_insn (insn_str, TRUE) == (int) FAIL)
6246214571Sdim    return;
6247214571Sdim}
6248214571Sdim
6249214571Sdim/* Handle the .cprestore pseudo-op.  This stores $gp into a given
6250214571Sdim   offset from $sp.  The offset is remembered, and after making a PIC
6251214571Sdim   call $gp is restored from that location.  */
6252214571Sdim
6253214571Sdimstatic void
6254214571Sdims_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6255214571Sdim{
6256214571Sdim  int reg;
6257214571Sdim  int cprestore_offset;
6258214571Sdim  char insn_str[MAX_LITERAL_POOL_SIZE];
6259214571Sdim
6260214571Sdim  /* If we are not generating PIC code, .cprestore is ignored.  */
6261214571Sdim  if (score_pic == NO_PIC)
6262214571Sdim    {
6263214571Sdim      s_ignore (0);
6264214571Sdim      return;
6265214571Sdim    }
6266214571Sdim
6267214571Sdim  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
6268214571Sdim      || skip_past_comma (&input_line_pointer) == (int) FAIL)
6269214571Sdim    {
6270214571Sdim      return;
6271214571Sdim    }
6272214571Sdim
6273214571Sdim  cprestore_offset = get_absolute_expression ();
6274214571Sdim
6275214571Sdim  if (cprestore_offset <= 0x3fff)
6276214571Sdim    {
6277214571Sdim      sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
6278214571Sdim      if (append_insn (insn_str, TRUE) == (int) FAIL)
6279214571Sdim        return;
6280214571Sdim    }
6281214571Sdim  else
6282214571Sdim    {
6283214571Sdim      int r1_bak;
6284214571Sdim
6285214571Sdim      r1_bak = nor1;
6286214571Sdim      nor1 = 0;
6287214571Sdim
6288214571Sdim      sprintf (insn_str, "li r1, %d", cprestore_offset);
6289214571Sdim      if (append_insn (insn_str, TRUE) == (int) FAIL)
6290214571Sdim        return;
6291214571Sdim
6292214571Sdim      sprintf (insn_str, "add r1, r1, r%d", reg);
6293214571Sdim      if (append_insn (insn_str, TRUE) == (int) FAIL)
6294214571Sdim        return;
6295214571Sdim
6296214571Sdim      sprintf (insn_str, "sw r%d, [r1]", GP);
6297214571Sdim      if (append_insn (insn_str, TRUE) == (int) FAIL)
6298214571Sdim        return;
6299214571Sdim
6300214571Sdim      nor1 = r1_bak;
6301214571Sdim    }
6302214571Sdim
6303214571Sdim  demand_empty_rest_of_line ();
6304214571Sdim}
6305214571Sdim
6306214571Sdim/* Handle the .gpword pseudo-op.  This is used when generating PIC
6307214571Sdim   code.  It generates a 32 bit GP relative reloc.  */
6308214571Sdimstatic void
6309214571Sdims_score_gpword (int ignore ATTRIBUTE_UNUSED)
6310214571Sdim{
6311214571Sdim  expressionS ex;
6312214571Sdim  char *p;
6313214571Sdim
6314214571Sdim  /* When not generating PIC code, this is treated as .word.  */
6315214571Sdim  if (score_pic == NO_PIC)
6316214571Sdim    {
6317214571Sdim      cons (4);
6318214571Sdim      return;
6319214571Sdim    }
6320214571Sdim  expression (&ex);
6321214571Sdim  if (ex.X_op != O_symbol || ex.X_add_number != 0)
6322214571Sdim    {
6323214571Sdim      as_bad (_("Unsupported use of .gpword"));
6324214571Sdim      ignore_rest_of_line ();
6325214571Sdim    }
6326214571Sdim  p = frag_more (4);
6327214571Sdim  md_number_to_chars (p, (valueT) 0, 4);
6328214571Sdim  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6329214571Sdim  demand_empty_rest_of_line ();
6330214571Sdim}
6331214571Sdim
6332214571Sdim/* Handle the .cpadd pseudo-op.  This is used when dealing with switch
6333214571Sdim   tables in PIC code.  */
6334214571Sdim
6335214571Sdimstatic void
6336214571Sdims_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6337214571Sdim{
6338214571Sdim  int reg;
6339214571Sdim  char insn_str[MAX_LITERAL_POOL_SIZE];
6340214571Sdim
6341214571Sdim  /* If we are not generating PIC code, .cpload is ignored.  */
6342214571Sdim  if (score_pic == NO_PIC)
6343214571Sdim    {
6344214571Sdim      s_ignore (0);
6345214571Sdim      return;
6346214571Sdim    }
6347214571Sdim
6348214571Sdim  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6349214571Sdim    {
6350214571Sdim      return;
6351214571Sdim    }
6352214571Sdim  demand_empty_rest_of_line ();
6353214571Sdim
6354214571Sdim  /* Add $gp to the register named as an argument.  */
6355214571Sdim  sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
6356214571Sdim  if (append_insn (insn_str, TRUE) == (int) FAIL)
6357214571Sdim    return;
6358214571Sdim}
6359214571Sdim
6360214571Sdim#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6361214571Sdim#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)        	\
6362214571Sdim    do								\
6363214571Sdim    {                                                   	\
6364214571Sdim    if ((SIZE) >= 8)                                      	\
6365214571Sdim    (P2VAR) = 3;                                        	\
6366214571Sdim    else if ((SIZE) >= 4)                                 	\
6367214571Sdim    (P2VAR) = 2;                                        	\
6368214571Sdim    else if ((SIZE) >= 2)                                 	\
6369214571Sdim    (P2VAR) = 1;                                        	\
6370214571Sdim    else                                                  	\
6371214571Sdim    (P2VAR) = 0;                                        	\
6372214571Sdim    }								\
6373214571Sdim  while (0)
6374214571Sdim#endif
6375214571Sdim
6376214571Sdimstatic void
6377214571Sdims_score_lcomm (int bytes_p)
6378214571Sdim{
6379214571Sdim  char *name;
6380214571Sdim  char c;
6381214571Sdim  char *p;
6382214571Sdim  int temp;
6383214571Sdim  symbolS *symbolP;
6384214571Sdim  segT current_seg = now_seg;
6385214571Sdim  subsegT current_subseg = now_subseg;
6386214571Sdim  const int max_alignment = 15;
6387214571Sdim  int align = 0;
6388214571Sdim  segT bss_seg = bss_section;
6389214571Sdim  int needs_align = 0;
6390214571Sdim
6391214571Sdim  name = input_line_pointer;
6392214571Sdim  c = get_symbol_end ();
6393214571Sdim  p = input_line_pointer;
6394214571Sdim  *p = c;
6395214571Sdim
6396214571Sdim  if (name == p)
6397214571Sdim    {
6398214571Sdim      as_bad (_("expected symbol name"));
6399214571Sdim      discard_rest_of_line ();
6400214571Sdim      return;
6401214571Sdim    }
6402214571Sdim
6403214571Sdim  SKIP_WHITESPACE ();
6404214571Sdim
6405214571Sdim  /* Accept an optional comma after the name.  The comma used to be
6406214571Sdim     required, but Irix 5 cc does not generate it.  */
6407214571Sdim  if (*input_line_pointer == ',')
6408214571Sdim    {
6409214571Sdim      ++input_line_pointer;
6410214571Sdim      SKIP_WHITESPACE ();
6411214571Sdim    }
6412214571Sdim
6413214571Sdim  if (is_end_of_line[(unsigned char)*input_line_pointer])
6414214571Sdim    {
6415214571Sdim      as_bad (_("missing size expression"));
6416214571Sdim      return;
6417214571Sdim    }
6418214571Sdim
6419214571Sdim  if ((temp = get_absolute_expression ()) < 0)
6420214571Sdim    {
6421214571Sdim      as_warn (_("BSS length (%d) < 0 ignored"), temp);
6422214571Sdim      ignore_rest_of_line ();
6423214571Sdim      return;
6424214571Sdim    }
6425214571Sdim
6426214571Sdim#if defined (TC_SCORE)
6427214571Sdim  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6428214571Sdim    {
6429214571Sdim      /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
6430214571Sdim      if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6431214571Sdim        {
6432214571Sdim          bss_seg = subseg_new (".sbss", 1);
6433214571Sdim          seg_info (bss_seg)->bss = 1;
6434214571Sdim#ifdef BFD_ASSEMBLER
6435214571Sdim          if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6436214571Sdim            as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6437214571Sdim#endif
6438214571Sdim        }
6439214571Sdim    }
6440214571Sdim#endif
6441214571Sdim
6442214571Sdim  SKIP_WHITESPACE ();
6443214571Sdim  if (*input_line_pointer == ',')
6444214571Sdim    {
6445214571Sdim      ++input_line_pointer;
6446214571Sdim      SKIP_WHITESPACE ();
6447214571Sdim
6448214571Sdim      if (is_end_of_line[(unsigned char)*input_line_pointer])
6449214571Sdim        {
6450214571Sdim          as_bad (_("missing alignment"));
6451214571Sdim          return;
6452214571Sdim        }
6453214571Sdim      else
6454214571Sdim        {
6455214571Sdim          align = get_absolute_expression ();
6456214571Sdim          needs_align = 1;
6457214571Sdim        }
6458214571Sdim    }
6459214571Sdim
6460214571Sdim  if (!needs_align)
6461214571Sdim    {
6462214571Sdim      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6463214571Sdim
6464214571Sdim      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6465214571Sdim      if (align)
6466214571Sdim        record_alignment (bss_seg, align);
6467214571Sdim    }
6468214571Sdim
6469214571Sdim  if (needs_align)
6470214571Sdim    {
6471214571Sdim      if (bytes_p)
6472214571Sdim        {
6473214571Sdim          /* Convert to a power of 2.  */
6474214571Sdim          if (align != 0)
6475214571Sdim            {
6476214571Sdim              unsigned int i;
6477214571Sdim
6478214571Sdim              for (i = 0; align != 0; align >>= 1, ++i)
6479214571Sdim                ;
6480214571Sdim              align = i - 1;
6481214571Sdim            }
6482214571Sdim        }
6483214571Sdim
6484214571Sdim      if (align > max_alignment)
6485214571Sdim        {
6486214571Sdim          align = max_alignment;
6487214571Sdim          as_warn (_("alignment too large; %d assumed"), align);
6488214571Sdim        }
6489214571Sdim      else if (align < 0)
6490214571Sdim        {
6491214571Sdim          align = 0;
6492214571Sdim          as_warn (_("alignment negative; 0 assumed"));
6493214571Sdim        }
6494214571Sdim
6495214571Sdim      record_alignment (bss_seg, align);
6496214571Sdim    }
6497214571Sdim  else
6498214571Sdim    {
6499214571Sdim      /* Assume some objects may require alignment on some systems.  */
6500214571Sdim#if defined (TC_ALPHA) && ! defined (VMS)
6501214571Sdim      if (temp > 1)
6502214571Sdim        {
6503214571Sdim          align = ffs (temp) - 1;
6504214571Sdim          if (temp % (1 << align))
6505214571Sdim            abort ();
6506214571Sdim        }
6507214571Sdim#endif
6508214571Sdim    }
6509214571Sdim
6510214571Sdim  *p = 0;
6511214571Sdim  symbolP = symbol_find_or_make (name);
6512214571Sdim  *p = c;
6513214571Sdim
6514214571Sdim  if (
6515214571Sdim#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6516214571Sdim     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6517214571Sdim#ifdef BFD_ASSEMBLER
6518214571Sdim       (OUTPUT_FLAVOR != bfd_target_aout_flavour
6519214571Sdim        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6520214571Sdim#else
6521214571Sdim       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6522214571Sdim#endif
6523214571Sdim#endif
6524214571Sdim       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6525214571Sdim    {
6526214571Sdim      char *pfrag;
6527214571Sdim
6528214571Sdim      subseg_set (bss_seg, 1);
6529214571Sdim
6530214571Sdim      if (align)
6531214571Sdim        frag_align (align, 0, 0);
6532214571Sdim
6533214571Sdim      /* Detach from old frag.  */
6534214571Sdim      if (S_GET_SEGMENT (symbolP) == bss_seg)
6535214571Sdim        symbol_get_frag (symbolP)->fr_symbol = NULL;
6536214571Sdim
6537214571Sdim      symbol_set_frag (symbolP, frag_now);
6538214571Sdim      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6539214571Sdim      *pfrag = 0;
6540214571Sdim
6541214571Sdim
6542214571Sdim      S_SET_SEGMENT (symbolP, bss_seg);
6543214571Sdim
6544214571Sdim#ifdef OBJ_COFF
6545214571Sdim      /* The symbol may already have been created with a preceding
6546214571Sdim         ".globl" directive -- be careful not to step on storage class
6547214571Sdim         in that case.  Otherwise, set it to static.  */
6548214571Sdim      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6549214571Sdim        {
6550214571Sdim          S_SET_STORAGE_CLASS (symbolP, C_STAT);
6551214571Sdim        }
6552214571Sdim#endif /* OBJ_COFF */
6553214571Sdim
6554214571Sdim#ifdef S_SET_SIZE
6555214571Sdim      S_SET_SIZE (symbolP, temp);
6556214571Sdim#endif
6557214571Sdim    }
6558214571Sdim  else
6559214571Sdim    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6560214571Sdim
6561214571Sdim  subseg_set (current_seg, current_subseg);
6562214571Sdim
6563214571Sdim  demand_empty_rest_of_line ();
6564214571Sdim}
6565214571Sdim
6566214571Sdimstatic void
6567214571Sdiminsert_reg (const struct reg_entry *r, struct hash_control *htab)
6568214571Sdim{
6569214571Sdim  int i = 0;
6570214571Sdim  int len = strlen (r->name) + 2;
6571214571Sdim  char *buf = xmalloc (len);
6572214571Sdim  char *buf2 = xmalloc (len);
6573214571Sdim
6574214571Sdim  strcpy (buf + i, r->name);
6575214571Sdim  for (i = 0; buf[i]; i++)
6576214571Sdim    {
6577214571Sdim      buf2[i] = TOUPPER (buf[i]);
6578214571Sdim    }
6579214571Sdim  buf2[i] = '\0';
6580214571Sdim
6581214571Sdim  hash_insert (htab, buf, (void *) r);
6582214571Sdim  hash_insert (htab, buf2, (void *) r);
6583214571Sdim}
6584214571Sdim
6585214571Sdimstatic void
6586214571Sdimbuild_reg_hsh (struct reg_map *map)
6587214571Sdim{
6588214571Sdim  const struct reg_entry *r;
6589214571Sdim
6590214571Sdim  if ((map->htab = hash_new ()) == NULL)
6591214571Sdim    {
6592214571Sdim      as_fatal (_("virtual memory exhausted"));
6593214571Sdim    }
6594214571Sdim  for (r = map->names; r->name != NULL; r++)
6595214571Sdim    {
6596214571Sdim      insert_reg (r, map->htab);
6597214571Sdim    }
6598214571Sdim}
6599214571Sdim
6600214571Sdimvoid
6601214571Sdimmd_begin (void)
6602214571Sdim{
6603214571Sdim  unsigned int i;
6604214571Sdim  segT seg;
6605214571Sdim  subsegT subseg;
6606214571Sdim
6607214571Sdim  if ((score_ops_hsh = hash_new ()) == NULL)
6608214571Sdim    as_fatal (_("virtual memory exhausted"));
6609214571Sdim
6610214571Sdim  build_score_ops_hsh ();
6611214571Sdim
6612214571Sdim  if ((dependency_insn_hsh = hash_new ()) == NULL)
6613214571Sdim    as_fatal (_("virtual memory exhausted"));
6614214571Sdim
6615214571Sdim  build_dependency_insn_hsh ();
6616214571Sdim
6617214571Sdim  for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
6618214571Sdim    build_reg_hsh (all_reg_maps + i);
6619214571Sdim
6620214571Sdim  /* Initialize dependency vector.  */
6621214571Sdim  init_dependency_vector ();
6622214571Sdim
6623214571Sdim  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6624214571Sdim  seg = now_seg;
6625214571Sdim  subseg = now_subseg;
6626214571Sdim  pdr_seg = subseg_new (".pdr", (subsegT) 0);
6627214571Sdim  (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6628214571Sdim  (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
6629214571Sdim  subseg_set (seg, subseg);
6630214571Sdim
6631214571Sdim  if (USE_GLOBAL_POINTER_OPT)
6632214571Sdim    bfd_set_gp_size (stdoutput, g_switch_value);
6633214571Sdim}
6634214571Sdim
6635214571Sdim
6636214571Sdimconst pseudo_typeS md_pseudo_table[] =
6637214571Sdim{
6638214571Sdim  {"bss", s_score_bss, 0},
6639214571Sdim  {"text", s_score_text, 0},
6640214571Sdim  {"word", cons, 4},
6641214571Sdim  {"long", cons, 4},
6642214571Sdim  {"extend", float_cons, 'x'},
6643214571Sdim  {"ldouble", float_cons, 'x'},
6644214571Sdim  {"packed", float_cons, 'p'},
6645214571Sdim  {"end", s_score_end, 0},
6646214571Sdim  {"ent", s_score_ent, 0},
6647214571Sdim  {"frame", s_score_frame, 0},
6648214571Sdim  {"rdata", s_change_sec, 'r'},
6649214571Sdim  {"sdata", s_change_sec, 's'},
6650214571Sdim  {"set", s_score_set, 0},
6651214571Sdim  {"mask", s_score_mask, 'R'},
6652214571Sdim  {"dword", cons, 8},
6653214571Sdim  {"lcomm", s_score_lcomm, 1},
6654214571Sdim  {"section", score_s_section, 0},
6655214571Sdim  {"cpload", s_score_cpload, 0},
6656214571Sdim  {"cprestore", s_score_cprestore, 0},
6657214571Sdim  {"gpword", s_score_gpword, 0},
6658214571Sdim  {"cpadd", s_score_cpadd, 0},
6659214571Sdim  {0, 0, 0}
6660214571Sdim};
6661214571Sdim
6662