OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-score.c] - Blame information for rev 394

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.