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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-score.c] - Blame information for rev 81

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

Line No. Rev Author Line
1 16 khays
/* 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 *);
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
              unsigned int data_type;
3142
 
3143
              if (pre_inc == 1)
3144
                data_type = _SIMM12;
3145
              else
3146
                data_type = _SIMM15;
3147
              dataptr = temp;
3148
 
3149
              if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
3150
                  && (data_type != _SIMM16_LA)
3151
                  && (data_type != _VALUE_HI16)
3152
                  && (data_type != _VALUE_LO16)
3153
                  && (data_type != _IMM16)
3154
                  && (data_type != _IMM15)
3155
                  && (data_type != _IMM14)
3156
                  && (data_type != _IMM4)
3157
                  && (data_type != _IMM5)
3158
                  && (data_type != _IMM8)
3159
                  && (data_type != _IMM5_RSHIFT_1)
3160
                  && (data_type != _IMM5_RSHIFT_2)
3161
                  && (data_type != _SIMM14_NEG)
3162
                  && (data_type != _IMM10_RSHIFT_2))
3163
                {
3164
                  data_type += 24;
3165
                }
3166
 
3167
              value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3168
              if (value == (int) s3_FAIL)
3169
                {
3170
                  if (data_type < 30)
3171
                    sprintf (s3_err_msg,
3172
                             _("invalid constant: %d bit expression not in range %d..%d"),
3173
                             s3_score_df_range[data_type].bits,
3174
                             s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3175
                  else
3176
                    sprintf (s3_err_msg,
3177
                             _("invalid constant: %d bit expression not in range %d..%d"),
3178
                             s3_score_df_range[data_type - 24].bits,
3179
                             s3_score_df_range[data_type - 24].range[0],
3180
                             s3_score_df_range[data_type - 24].range[1]);
3181
                  s3_inst.error = s3_err_msg;
3182
                  return;
3183
                }
3184
 
3185
              value &= (1 << s3_score_df_range[data_type].bits) - 1;
3186
              ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
3187
              s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3188
              s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3189
              if (pre_inc == 1)
3190
                s3_inst.instruction |= value << 3;
3191
              else
3192
                s3_inst.instruction |= value;
3193
 
3194
              /* lw rD, [rA, simm15]  */
3195
              if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
3196
                {
3197
                  /*  rD  in [r0 - r15]. , ra in [r0-r7] */
3198
                  if ((((s3_inst.instruction >> 15) & 0x18) == 0)
3199
                      && (((s3_inst.instruction >> 20) & 0x10) == 0))
3200
                    {
3201
                      /* simm = [bit 7], lw -> lw!.  */
3202
                      if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3203
                        {
3204
                          s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5)
3205
                            | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3206
                          s3_inst.relax_size = 2;
3207
                        }
3208
                      else
3209
                        {
3210
                          s3_inst.relax_inst = 0x8000;
3211
                        }
3212
                    }
3213
                  else
3214
                    {
3215
                      s3_inst.relax_inst = 0x8000;
3216
                    }
3217
                }
3218
              /* sw rD, [rA, simm15]  */
3219
              else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
3220
                {
3221
                  /* rD is  in [r0 - r15] and ra in [r0-r7] */
3222
                  if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
3223
                    {
3224
                      /* simm15 =7 bit  , sw -> sw!.  */
3225
                      if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
3226
                        {
3227
                          s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5)
3228
                            | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
3229
                          s3_inst.relax_size = 2;
3230
                        }
3231
                      /* rA = r2, sw -> swp!.  */
3232
                      else
3233
                        {
3234
                          s3_inst.relax_inst = 0x8000;
3235
                        }
3236
                    }
3237
                  else
3238
                    {
3239
                      s3_inst.relax_inst = 0x8000;
3240
                    }
3241
                }
3242
              /* sw rD, [rA, simm15]+    sw pre.  */
3243
              else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
3244
                {
3245
                  /* simm15 = -4. and ra==r0 */
3246
                  if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
3247
                      && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
3248
                    {
3249
                      /* sw -> push!.  */
3250
                      s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
3251
                      s3_inst.relax_size = 2;
3252
                    }
3253
                  else
3254
                    {
3255
                      s3_inst.relax_inst = 0x8000;
3256
                    }
3257
                }
3258
              else
3259
                {
3260
                  s3_inst.relax_inst = 0x8000;
3261
                }
3262
 
3263
              return;
3264
            }
3265
          else
3266
            {
3267
              /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3268
              s3_inst.reloc.pc_rel = 0;
3269
            }
3270
        }
3271
    }
3272
  else
3273
    {
3274
      s3_inst.error = s3_BAD_ARGS;
3275
    }
3276
}
3277
 
3278
/* Handle cache.  */
3279
static void
3280
s3_do_cache (char *str)
3281
{
3282
  s3_skip_whitespace (str);
3283
 
3284
  if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3285
    {
3286
      return;
3287
    }
3288
  else
3289
    {
3290
      int cache_op;
3291
 
3292
      cache_op = (s3_inst.instruction >> 20) & 0x1F;
3293
      sprintf (s3_inst.name, "cache %d", cache_op);
3294
    }
3295
 
3296
  if (*str == '[')
3297
    {
3298
      str++;
3299
      s3_skip_whitespace (str);
3300
 
3301
      if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3302
        return;
3303
 
3304
      s3_skip_whitespace (str);
3305
 
3306
      /* cache op, [rA]  */
3307
      if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3308
        {
3309
          s3_SET_INSN_ERROR (NULL);
3310
          if (*str != ']')
3311
            {
3312
              s3_inst.error = _("missing ]");
3313
              return;
3314
            }
3315
          str++;
3316
        }
3317
      /* cache op, [rA, simm15]  */
3318
      else
3319
        {
3320
          if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
3321
            {
3322
              return;
3323
            }
3324
 
3325
          s3_skip_whitespace (str);
3326
          if (*str++ != ']')
3327
            {
3328
              s3_inst.error = _("missing ]");
3329
              return;
3330
            }
3331
        }
3332
 
3333
      if (s3_end_of_line (str) == (int) s3_FAIL)
3334
        return;
3335
    }
3336
  else
3337
    {
3338
      s3_inst.error = s3_BAD_ARGS;
3339
    }
3340
}
3341
 
3342
static void
3343
s3_do_crdcrscrsimm5 (char *str)
3344
{
3345
  char *strbak;
3346
 
3347
  strbak = str;
3348
  s3_skip_whitespace (str);
3349
 
3350
  if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3351
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3352
      || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3353
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3354
      || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
3355
      || s3_skip_past_comma (&str) == (int) s3_FAIL)
3356
    {
3357
      str = strbak;
3358
      /* cop1 cop_code20.  */
3359
      if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
3360
        return;
3361
    }
3362
  else
3363
    {
3364
      if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
3365
        return;
3366
    }
3367
 
3368
  s3_end_of_line (str);
3369
}
3370
 
3371
/* Handle ldc/stc.  */
3372
static void
3373
s3_do_ldst_cop (char *str)
3374
{
3375
  s3_skip_whitespace (str);
3376
 
3377
  if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL)
3378
      || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3379
    return;
3380
 
3381
  if (*str == '[')
3382
    {
3383
      str++;
3384
      s3_skip_whitespace (str);
3385
 
3386
      if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3387
        return;
3388
 
3389
      s3_skip_whitespace (str);
3390
 
3391
      if (*str++ != ']')
3392
        {
3393
          if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
3394
            return;
3395
 
3396
          s3_skip_whitespace (str);
3397
          if (*str++ != ']')
3398
            {
3399
              s3_inst.error = _("missing ]");
3400
              return;
3401
            }
3402
        }
3403
 
3404
      s3_end_of_line (str);
3405
    }
3406
  else
3407
    s3_inst.error = s3_BAD_ARGS;
3408
}
3409
 
3410
static void
3411
s3_do16_ldst_insn (char *str)
3412
{
3413
  int conflict_reg=0;
3414
  char * temp;
3415
  s3_skip_whitespace (str);
3416
 
3417
  if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3418
    return;
3419
 
3420
  if (*str == '[')
3421
    {
3422
 
3423
      str++;
3424
      s3_skip_whitespace (str);
3425
 
3426
      if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
3427
        return;
3428
      if (conflict_reg&0x8)
3429
        {
3430
          sprintf (s3_err_msg,  _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
3431
          s3_inst.error=s3_err_msg;
3432
          return ;
3433
        }
3434
 
3435
      s3_skip_whitespace (str);
3436
      temp = str + 1;    /* The latter will process decimal/hex expression.  */
3437
      if (*str == ']')
3438
        {
3439
          str++;
3440
          if (s3_end_of_line (str) == (int) s3_FAIL)
3441
            return;
3442
        }
3443
      else
3444
        {
3445
          if (s3_skip_past_comma (&str) == (int) s3_FAIL)
3446
            {
3447
              s3_inst.error = _("comma is  expected");
3448
              return;
3449
            }
3450
          if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
3451
            return;
3452
          s3_skip_whitespace (str);
3453
          if (*str++ != ']')
3454
            {
3455
              s3_inst.error = _("missing ]");
3456
              return;
3457
            }
3458
          if (s3_end_of_line (str) == (int) s3_FAIL)
3459
            return;
3460
          if (s3_inst.reloc.exp.X_op == O_constant)
3461
            {
3462
              int value;
3463
              unsigned int data_type;
3464
              data_type = _IMM5_RSHIFT_2;
3465
              value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
3466
              if (value == (int) s3_FAIL)
3467
               {
3468
                if (data_type < 30)
3469
                  sprintf (s3_err_msg,
3470
                    _("invalid constant: %d bit expression not in range %d..%d"),
3471
                    s3_score_df_range[data_type].bits,
3472
                    s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
3473
                  s3_inst.error = s3_err_msg;
3474
                  return;
3475
                }
3476
              if (value &0x3)
3477
                {
3478
                  sprintf (s3_err_msg,  _("invalid constant: %d is not word align integer"),value);
3479
                  s3_inst.error=s3_err_msg;
3480
                  return ;
3481
                }
3482
 
3483
              value >>=2;
3484
              s3_inst.instruction |= value;
3485
            }
3486
        }
3487
 
3488
    }
3489
  else
3490
    {
3491
      sprintf (s3_err_msg,  _("missing ["));
3492
      s3_inst.error=s3_err_msg;
3493
      return ;
3494
    }
3495
}
3496
 
3497
static void
3498
s3_do_lw48 (char *str)
3499
{
3500
  bfd_signed_vma val = 0;
3501
 
3502
  s3_skip_whitespace (str);
3503
 
3504
  if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3505
      || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3506
    return;
3507
 
3508
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3509
      || s3_end_of_line (str) == (int) s3_FAIL)
3510
    {
3511
      return;
3512
    }
3513
 
3514
  /* Check word align for lw48 rd, value.  */
3515
  if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3516
      && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3517
    {
3518
      s3_inst.error = _("invalid constant: 32 bit expression not word align");
3519
      return;
3520
    }
3521
 
3522
  /* Check and set offset.  */
3523
  val = s3_inst.reloc.exp.X_add_number;
3524
  if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3525
      && (!(val >= 0 && val <= 0xffffffffLL)))
3526
    {
3527
      s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3528
      return;
3529
    }
3530
 
3531
  val &= 0xffffffff;
3532
  val >>= 2;
3533
  s3_inst.instruction |= (val << 7);
3534
 
3535
  /* Set reloc type.  */
3536
  s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3537
 
3538
}
3539
 
3540
static void
3541
s3_do_sw48 (char *str)
3542
{
3543
  bfd_signed_vma val = 0;
3544
 
3545
  s3_skip_whitespace (str);
3546
 
3547
  if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3548
      || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3549
    return;
3550
 
3551
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3552
      || s3_end_of_line (str) == (int) s3_FAIL)
3553
    {
3554
      return;
3555
    }
3556
 
3557
  /* Check word align for lw48 rd, value.  */
3558
  if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3559
      && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
3560
    {
3561
      s3_inst.error = _("invalid constant: 32 bit expression not word align");
3562
      return;
3563
    }
3564
 
3565
  /* Check and set offset.  */
3566
  val = s3_inst.reloc.exp.X_add_number;
3567
  if ((s3_inst.reloc.exp.X_add_symbol == NULL)
3568
      && (!(val >= 0 && val <= 0xffffffffLL)))
3569
    {
3570
      s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
3571
      return;
3572
    }
3573
 
3574
  val &= 0xffffffff;
3575
  val >>= 2;
3576
  s3_inst.instruction |= (val << 7);
3577
 
3578
  /* Set reloc type.  */
3579
  s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
3580
}
3581
 
3582
static void
3583
s3_do_ldi48 (char *str)
3584
{
3585
  bfd_signed_vma val;
3586
 
3587
  s3_skip_whitespace (str);
3588
 
3589
  if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL
3590
      || s3_skip_past_comma (&str) == (int) s3_FAIL)
3591
    return;
3592
 
3593
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
3594
      || s3_end_of_line (str) == (int) s3_FAIL)
3595
    {
3596
      return;
3597
    }
3598
 
3599
  /* Check and set offset.  */
3600
  val = s3_inst.reloc.exp.X_add_number;
3601
  if (!(val >= -0xffffffffLL && val <= 0xffffffffLL))
3602
    {
3603
      s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]");
3604
      return;
3605
    }
3606
 
3607
  val &= 0xffffffff;
3608
  s3_inst.instruction |= (val << 5);
3609
 
3610
  /* Set reloc type.  */
3611
  s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32;
3612
}
3613
 
3614
static void
3615
s3_do_sdbbp48 (char *str)
3616
{
3617
  s3_skip_whitespace (str);
3618
 
3619
  if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
3620
    return;
3621
}
3622
 
3623
static void
3624
s3_do_and48 (char *str)
3625
{
3626
  s3_skip_whitespace (str);
3627
 
3628
  if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3629
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3630
      || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3631
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3632
      || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3633
      || s3_end_of_line (str) == (int) s3_FAIL)
3634
    return;
3635
}
3636
 
3637
static void
3638
s3_do_or48 (char *str)
3639
{
3640
  s3_skip_whitespace (str);
3641
 
3642
  if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
3643
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3644
      || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
3645
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3646
      || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
3647
      || s3_end_of_line (str) == (int) s3_FAIL)
3648
    return;
3649
}
3650
 
3651
static void
3652
s3_do_mbitclr (char *str)
3653
{
3654
  int val;
3655
  s3_skip_whitespace (str);
3656
 
3657
  if (*str != '[')
3658
    {
3659
      sprintf (s3_err_msg,  _("missing ["));
3660
      s3_inst.error=s3_err_msg;
3661
      return;
3662
    }
3663
  str++;
3664
 
3665
  s3_inst.instruction &= 0x0;
3666
 
3667
  if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3668
      || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3669
      || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3670
    return;
3671
 
3672
  /* Get imm11 and refill opcode.  */
3673
  val = s3_inst.instruction & 0x7ff;
3674
  val >>= 2;
3675
  s3_inst.instruction &= 0x000f8000;
3676
  s3_inst.instruction |= 0x00000064;
3677
 
3678
  if (*str != ']')
3679
    {
3680
      sprintf (s3_err_msg,  _("missing ]"));
3681
      s3_inst.error=s3_err_msg;
3682
      return;
3683
    }
3684
  str++;
3685
 
3686
  if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3687
      || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3688
    return;
3689
 
3690
  /* Set imm11 to opcode.  */
3691
  s3_inst.instruction |= (val & 0x1)
3692
                      | (((val >> 1 ) & 0x7) << 7)
3693
                      | (((val >> 4 ) & 0x1f) << 20);
3694
}
3695
 
3696
static void
3697
s3_do_mbitset (char *str)
3698
{
3699
  int val;
3700
  s3_skip_whitespace (str);
3701
 
3702
  if (*str != '[')
3703
    {
3704
      sprintf (s3_err_msg,  _("missing ["));
3705
      s3_inst.error=s3_err_msg;
3706
      return;
3707
    }
3708
  str++;
3709
 
3710
  s3_inst.instruction &= 0x0;
3711
 
3712
  if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3713
      || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3714
      || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
3715
    return;
3716
 
3717
  /* Get imm11 and refill opcode.  */
3718
  val = s3_inst.instruction & 0x7ff;
3719
  val >>= 2;
3720
  s3_inst.instruction &= 0x000f8000;
3721
  s3_inst.instruction |= 0x0000006c;
3722
 
3723
  if (*str != ']')
3724
    {
3725
      sprintf (s3_err_msg,  _("missing ]"));
3726
      s3_inst.error=s3_err_msg;
3727
      return;
3728
    }
3729
  str++;
3730
 
3731
  if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
3732
      || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
3733
    return;
3734
 
3735
  /* Set imm11 to opcode.  */
3736
  s3_inst.instruction |= (val & 0x1)
3737
                      | (((val >> 1 ) & 0x7) << 7)
3738
                      | (((val >> 4 ) & 0x1f) << 20);
3739
}
3740
 
3741
static void
3742
s3_do16_slli_srli (char *str)
3743
{
3744
  s3_skip_whitespace (str);
3745
 
3746
  if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL)
3747
      || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3748
      || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3749
      || s3_end_of_line (str) == (int) s3_FAIL)
3750
    return;
3751
}
3752
 
3753
static void
3754
s3_do16_ldiu (char *str)
3755
{
3756
  s3_skip_whitespace (str);
3757
 
3758
  if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3759
      || (s3_skip_past_comma (&str) == (int) s3_FAIL)
3760
      || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
3761
      || s3_end_of_line (str) == (int) s3_FAIL)
3762
    return;
3763
}
3764
 
3765
static void
3766
s3_do16_push_pop (char *str)
3767
{
3768
  s3_skip_whitespace (str);
3769
  if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
3770
      || s3_end_of_line (str) == (int) s3_FAIL)
3771
    return;
3772
}
3773
 
3774
static void
3775
s3_do16_rpush (char *str)
3776
{
3777
  int reg;
3778
  int val;
3779
  s3_skip_whitespace (str);
3780
  if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3781
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3782
      || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3783
      || s3_end_of_line (str) == (int) s3_FAIL)
3784
    return;
3785
 
3786
  /* 0: indicate 32.
3787
     1: invalide value.
3788
     2: to 31: normal value.  */
3789
  val = s3_inst.instruction & 0x1f;
3790
  if (val == 1)
3791
    {
3792
      s3_inst.error = _("imm5 should >= 2");
3793
      return;
3794
    }
3795
  if (reg >= 32)
3796
    {
3797
      s3_inst.error = _("reg should <= 31");
3798
      return;
3799
    }
3800
}
3801
 
3802
static void
3803
s3_do16_rpop (char *str)
3804
{
3805
  int reg;
3806
  int val;
3807
  s3_skip_whitespace (str);
3808
  if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
3809
      || s3_skip_past_comma (&str) == (int) s3_FAIL
3810
      || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
3811
      || s3_end_of_line (str) == (int) s3_FAIL)
3812
    return;
3813
 
3814
  /* 0: indicate 32.
3815
     1: invalide value.
3816
     2: to 31: normal value.  */
3817
  val = s3_inst.instruction & 0x1f;
3818
  if (val == 1)
3819
    {
3820
      s3_inst.error = _("imm5 should >= 2");
3821
      return;
3822
    }
3823
 
3824
  if (reg >= 32)
3825
    {
3826
      s3_inst.error = _("reg should <= 31");
3827
      return;
3828
    }
3829
  else
3830
    {
3831
      if ((reg + val) <= 32)
3832
        reg = reg + val - 1;
3833
      else
3834
        reg = reg + val - 33;
3835
      s3_inst.instruction &= 0x7c1f;
3836
      s3_inst.instruction |= (reg << 5);
3837
      return;
3838
    }
3839
}
3840
 
3841
/* Handle lcb/lcw/lce/scb/scw/sce.  */
3842
static void
3843
s3_do_ldst_unalign (char *str)
3844
{
3845
  int conflict_reg;
3846
 
3847
  if (s3_university_version == 1)
3848
    {
3849
      s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3850
      return;
3851
    }
3852
 
3853
  s3_skip_whitespace (str);
3854
 
3855
  /* lcb/scb [rA]+.  */
3856
  if (*str == '[')
3857
    {
3858
      str++;
3859
      s3_skip_whitespace (str);
3860
 
3861
      if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3862
        return;
3863
 
3864
      if (*str++ == ']')
3865
        {
3866
          if (*str++ != '+')
3867
            {
3868
              s3_inst.error = _("missing +");
3869
              return;
3870
            }
3871
        }
3872
      else
3873
        {
3874
          s3_inst.error = _("missing ]");
3875
          return;
3876
        }
3877
 
3878
      if (s3_end_of_line (str) == (int) s3_FAIL)
3879
        return;
3880
    }
3881
  /* lcw/lce/scb/sce rD, [rA]+.  */
3882
  else
3883
    {
3884
      if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3885
          || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3886
        {
3887
          return;
3888
        }
3889
 
3890
      s3_skip_whitespace (str);
3891
      if (*str++ == '[')
3892
        {
3893
          int reg;
3894
 
3895
          s3_skip_whitespace (str);
3896
          if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3897
            {
3898
              return;
3899
            }
3900
 
3901
          /* Conflicts can occur on stores as well as loads.  */
3902
          conflict_reg = (conflict_reg == reg);
3903
          s3_skip_whitespace (str);
3904
          if (*str++ == ']')
3905
            {
3906
              unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
3907
 
3908
              if (*str++ == '+')
3909
                {
3910
                  if (conflict_reg)
3911
                    {
3912
                      as_warn (_("%s register same as write-back base"),
3913
                               ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3914
                                ? _("destination") : _("source")));
3915
                    }
3916
                }
3917
              else
3918
                {
3919
                  s3_inst.error = _("missing +");
3920
                  return;
3921
                }
3922
 
3923
              if (s3_end_of_line (str) == (int) s3_FAIL)
3924
                return;
3925
            }
3926
          else
3927
            {
3928
              s3_inst.error = _("missing ]");
3929
              return;
3930
            }
3931
        }
3932
      else
3933
        {
3934
          s3_inst.error = s3_BAD_ARGS;
3935
          return;
3936
        }
3937
    }
3938
}
3939
 
3940
/* Handle alw/asw.  */
3941
static void
3942
s3_do_ldst_atomic (char *str)
3943
{
3944
  if (s3_university_version == 1)
3945
    {
3946
      s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
3947
      return;
3948
    }
3949
 
3950
  s3_skip_whitespace (str);
3951
 
3952
  if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
3953
      || (s3_skip_past_comma (&str) == (int) s3_FAIL))
3954
    {
3955
      return;
3956
    }
3957
  else
3958
    {
3959
 
3960
      s3_skip_whitespace (str);
3961
      if (*str++ == '[')
3962
        {
3963
          int reg;
3964
 
3965
          s3_skip_whitespace (str);
3966
          if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
3967
            {
3968
              return;
3969
            }
3970
 
3971
          s3_skip_whitespace (str);
3972
          if (*str++ != ']')
3973
            {
3974
              s3_inst.error = _("missing ]");
3975
              return;
3976
            }
3977
 
3978
          s3_end_of_line (str);
3979
        }
3980
      else
3981
        s3_inst.error = s3_BAD_ARGS;
3982
    }
3983
}
3984
 
3985
static void
3986
s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3987
                  struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
3988
                  symbolS *add_symbol)
3989
{
3990
  int i;
3991
  char *p;
3992
  fixS *fixp = NULL;
3993
  fixS *cur_fixp = NULL;
3994
  long where;
3995
  struct s3_score_it inst_main;
3996
 
3997
  memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
3998
 
3999
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4000
  inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4001
  inst_main.type = Insn_PIC;
4002
 
4003
  for (i = 0; i < var_num; i++)
4004
    {
4005
      inst_main.relax_size += var_insts[i].size;
4006
      var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
4007
                                                   s3_GET_INSN_CLASS (var_insts[i].type));
4008
    }
4009
 
4010
  /* Check data dependency.  */
4011
  s3_handle_dependency (&inst_main);
4012
 
4013
  /* Start a new frag if frag_now is not empty.  */
4014
  if (frag_now_fix () != 0)
4015
    {
4016
      if (!frag_now->tc_frag_data.is_insn)
4017
        {
4018
          frag_wane (frag_now);
4019
        }
4020
      frag_new (0);
4021
    }
4022
  frag_grow (20);
4023
 
4024
  /* Write fr_fix part.  */
4025
  p = frag_more (inst_main.size);
4026
  s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4027
 
4028
  if (inst_main.reloc.type != BFD_RELOC_NONE)
4029
    fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4030
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4031
 
4032
  frag_now->tc_frag_data.fixp = fixp;
4033
  cur_fixp = frag_now->tc_frag_data.fixp;
4034
 
4035
#ifdef OBJ_ELF
4036
  dwarf2_emit_insn (inst_main.size);
4037
#endif
4038
 
4039
  where = p - frag_now->fr_literal + inst_main.size;
4040
  for (i = 0; i < var_num; i++)
4041
    {
4042
      if (i > 0)
4043
        where += var_insts[i - 1].size;
4044
 
4045
      if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4046
        {
4047
          fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
4048
                                &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4049
                                var_insts[i].reloc.type);
4050
          if (fixp)
4051
            {
4052
              if (cur_fixp)
4053
                {
4054
                  cur_fixp->fx_next = fixp;
4055
                  cur_fixp = cur_fixp->fx_next;
4056
                }
4057
              else
4058
                {
4059
                  frag_now->tc_frag_data.fixp = fixp;
4060
                  cur_fixp = frag_now->tc_frag_data.fixp;
4061
                }
4062
            }
4063
        }
4064
    }
4065
 
4066
  p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4067
                s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4068
                0, inst_main.size, 0), add_symbol, 0, NULL);
4069
 
4070
  /* Write fr_var part.
4071
     no calling s3_gen_insn_frag, no fixS will be generated.  */
4072
  for (i = 0; i < var_num; i++)
4073
    {
4074
      s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4075
      p += var_insts[i].size;
4076
    }
4077
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4078
  s3_inst.bwarn = -1;
4079
}
4080
 
4081
/* Build a relax frag for la instruction when generating s3_PIC,
4082
   external symbol first and local symbol second.  */
4083
static void
4084
s3_build_la_pic (int reg_rd, expressionS exp)
4085
{
4086
  symbolS *add_symbol = exp.X_add_symbol;
4087
  offsetT add_number = exp.X_add_number;
4088
  struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4089
  struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4090
  int fix_num = 0;
4091
  int var_num = 0;
4092
  char tmp[s3_MAX_LITERAL_POOL_SIZE];
4093
  int r1_bak;
4094
 
4095
  r1_bak = s3_nor1;
4096
  s3_nor1 = 0;
4097
 
4098
  if (add_number == 0)
4099
    {
4100
      fix_num = 1;
4101
      var_num = 2;
4102
 
4103
      /* For an external symbol, only one insn is generated;
4104
         For a local symbol, two insns are generated.  */
4105
      /* Fix part
4106
         For an external symbol: lw rD, <sym>($gp)
4107
                                 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
4108
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4109
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4110
        return;
4111
 
4112
      if (reg_rd == s3_PIC_CALL_REG)
4113
        s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4114
      memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4115
 
4116
      /* Var part
4117
         For a local symbol :
4118
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4119
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4120
      s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4121
      memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4122
      sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4123
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4124
        return;
4125
 
4126
      memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4127
      s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4128
    }
4129
  else if (add_number >= -0x8000 && add_number <= 0x7fff)
4130
    {
4131
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4132
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4133
      if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4134
        return;
4135
 
4136
      /* Insn 2  */
4137
      fix_num = 1;
4138
      var_num = 1;
4139
      /* Fix part
4140
         For an external symbol: addi rD, <constant> */
4141
      sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
4142
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4143
        return;
4144
 
4145
      memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4146
 
4147
      /* Var part
4148
         For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
4149
      sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
4150
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4151
        return;
4152
 
4153
      memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4154
      s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4155
    }
4156
  else
4157
    {
4158
      int hi = (add_number >> 16) & 0x0000FFFF;
4159
      int lo = add_number & 0x0000FFFF;
4160
 
4161
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4162
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4163
      if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4164
        return;
4165
 
4166
      /* Insn 2  */
4167
      fix_num = 1;
4168
      var_num = 1;
4169
      /* Fix part
4170
         For an external symbol: ldis r1, HI%<constant>  */
4171
      sprintf (tmp, "ldis r1, %d", hi);
4172
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4173
        return;
4174
 
4175
      memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4176
 
4177
      /* Var part
4178
         For a local symbol: ldis r1, HI%<constant>
4179
         but, if lo is outof 16 bit, make hi plus 1  */
4180
      if ((lo < -0x8000) || (lo > 0x7fff))
4181
        {
4182
          hi += 1;
4183
        }
4184
      sprintf (tmp, "ldis_pic r1, %d", hi);
4185
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4186
        return;
4187
 
4188
      memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4189
      s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4190
 
4191
      /* Insn 3  */
4192
      fix_num = 1;
4193
      var_num = 1;
4194
      /* Fix part
4195
         For an external symbol: ori r1, LO%<constant>  */
4196
      sprintf (tmp, "ori r1, %d", lo);
4197
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4198
        return;
4199
 
4200
      memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4201
 
4202
      /* Var part
4203
         For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
4204
      sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
4205
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4206
        return;
4207
 
4208
      memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4209
      s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4210
 
4211
      /* Insn 4: add rD, rD, r1  */
4212
      sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4213
      if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4214
        return;
4215
 
4216
     /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4217
     s3_inst.bwarn = -1;
4218
    }
4219
 
4220
  s3_nor1 = r1_bak;
4221
}
4222
 
4223
/* Handle la.  */
4224
static void
4225
s3_do_macro_la_rdi32 (char *str)
4226
{
4227
  int reg_rd;
4228
 
4229
  s3_skip_whitespace (str);
4230
  if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4231
      || s3_skip_past_comma (&str) == (int) s3_FAIL)
4232
    {
4233
      return;
4234
    }
4235
  else
4236
    {
4237
      /* Save str.  */
4238
      char *keep_data = str;
4239
      char append_str[s3_MAX_LITERAL_POOL_SIZE];
4240
 
4241
      /* Check immediate value.  */
4242
      if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4243
        {
4244
          s3_inst.error = _("expression error");
4245
          return;
4246
        }
4247
      else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4248
               && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL))
4249
        {
4250
          s3_inst.error = _("value not in range [0, 0xffffffff]");
4251
          return;
4252
        }
4253
 
4254
      /* Reset str.  */
4255
      str = keep_data;
4256
 
4257
      /* la rd, simm16.  */
4258
      if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
4259
        {
4260
          s3_end_of_line (str);
4261
          return;
4262
        }
4263
      /* la rd, imm32 or la rd, label.  */
4264
      else
4265
        {
4266
          s3_SET_INSN_ERROR (NULL);
4267
          /* Reset str.  */
4268
          str = keep_data;
4269
          if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4270
              || (s3_end_of_line (str) == (int) s3_FAIL))
4271
            {
4272
              return;
4273
            }
4274
          else
4275
            {
4276
              if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol))
4277
                {
4278
                  sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4279
                  if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4280
                    return;
4281
 
4282
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4283
                  if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4284
                    return;
4285
                }
4286
              else
4287
                {
4288
                  gas_assert (s3_inst.reloc.exp.X_add_symbol);
4289
                  s3_build_la_pic (reg_rd, s3_inst.reloc.exp);
4290
                }
4291
 
4292
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4293
              s3_inst.bwarn = -1;
4294
            }
4295
        }
4296
    }
4297
}
4298
 
4299
/* Handle li.  */
4300
static void
4301
s3_do_macro_li_rdi32 (char *str)
4302
{
4303
 
4304
  int reg_rd;
4305
 
4306
  s3_skip_whitespace (str);
4307
  if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4308
      || s3_skip_past_comma (&str) == (int) s3_FAIL)
4309
    {
4310
      return;
4311
    }
4312
  else
4313
    {
4314
      /* Save str.  */
4315
      char *keep_data = str;
4316
 
4317
      /* Check immediate value.  */
4318
      if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
4319
        {
4320
          s3_inst.error = _("expression error");
4321
          return;
4322
        }
4323
      else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL
4324
                 && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4325
        {
4326
          s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4327
          return;
4328
        }
4329
 
4330
      /* Reset str.  */
4331
      str = keep_data;
4332
 
4333
      /* li rd, simm16.  */
4334
      if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
4335
        {
4336
          s3_end_of_line (str);
4337
          return;
4338
        }
4339
      /* li rd, imm32.  */
4340
      else
4341
        {
4342
          char append_str[s3_MAX_LITERAL_POOL_SIZE];
4343
 
4344
          /* Reset str.  */
4345
          str = keep_data;
4346
 
4347
          if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
4348
              || (s3_end_of_line (str) == (int) s3_FAIL))
4349
            {
4350
              return;
4351
            }
4352
          else if (s3_inst.reloc.exp.X_add_symbol)
4353
            {
4354
              s3_inst.error = _("li rd label isn't correct instruction form");
4355
              return;
4356
            }
4357
          else
4358
            {
4359
              sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4360
 
4361
              if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4362
                return;
4363
              else
4364
                {
4365
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4366
                  if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4367
                    return;
4368
 
4369
                  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4370
                  s3_inst.bwarn = -1;
4371
                }
4372
            }
4373
        }
4374
    }
4375
}
4376
 
4377
/* Handle mul/mulu/div/divu/rem/remu.  */
4378
static void
4379
s3_do_macro_mul_rdrsrs (char *str)
4380
{
4381
  int reg_rd;
4382
  int reg_rs1;
4383
  int reg_rs2;
4384
  char *backupstr;
4385
  char append_str[s3_MAX_LITERAL_POOL_SIZE];
4386
 
4387
  if (s3_university_version == 1)
4388
    as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV);
4389
 
4390
  strcpy (append_str, str);
4391
  backupstr = append_str;
4392
  s3_skip_whitespace (backupstr);
4393
  if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4394
      || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4395
      || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL))
4396
    {
4397
      s3_inst.error = s3_BAD_ARGS;
4398
      return;
4399
    }
4400
 
4401
  if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4402
    {
4403
      /* rem/remu rA, rB is error format.  */
4404
      if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0)
4405
        {
4406
          s3_SET_INSN_ERROR (s3_BAD_ARGS);
4407
        }
4408
      else
4409
        {
4410
          s3_SET_INSN_ERROR (NULL);
4411
          s3_do_rsrs (str);
4412
        }
4413
      return;
4414
    }
4415
  else
4416
    {
4417
      s3_SET_INSN_ERROR (NULL);
4418
      if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4419
          || (s3_end_of_line (backupstr) == (int) s3_FAIL))
4420
        {
4421
          return;
4422
        }
4423
      else
4424
        {
4425
          char append_str1[s3_MAX_LITERAL_POOL_SIZE];
4426
 
4427
          if (strcmp (s3_inst.name, "rem") == 0)
4428
            {
4429
              sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4430
              sprintf (append_str1, "mfceh  r%d", reg_rd);
4431
            }
4432
          else if (strcmp (s3_inst.name, "remu") == 0)
4433
            {
4434
              sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4435
              sprintf (append_str1, "mfceh  r%d", reg_rd);
4436
            }
4437
          else
4438
            {
4439
              sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2);
4440
              sprintf (append_str1, "mfcel  r%d", reg_rd);
4441
            }
4442
 
4443
          /* Output mul/mulu or div/divu or rem/remu.  */
4444
          if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
4445
            return;
4446
 
4447
          /* Output mfcel or mfceh.  */
4448
          if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL)
4449
            return;
4450
 
4451
          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4452
          s3_inst.bwarn = -1;
4453
        }
4454
    }
4455
}
4456
 
4457
static void
4458
s3_exp_macro_ldst_abs (char *str)
4459
{
4460
  int reg_rd;
4461
  char *backupstr, *tmp;
4462
  char append_str[s3_MAX_LITERAL_POOL_SIZE];
4463
  char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4464
  struct s3_score_it inst_backup;
4465
  int r1_bak = 0;
4466
 
4467
  r1_bak = s3_nor1;
4468
  s3_nor1 = 0;
4469
  memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
4470
 
4471
  strcpy (verifystr, str);
4472
  backupstr = verifystr;
4473
  s3_skip_whitespace (backupstr);
4474
  if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4475
    return;
4476
 
4477
  tmp = backupstr;
4478
  if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
4479
    return;
4480
 
4481
  backupstr = tmp;
4482
  sprintf (append_str, "li r1  %s", backupstr);
4483
  s3_append_insn (append_str, TRUE);
4484
 
4485
  memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4486
  sprintf (append_str, " r%d, [r1,0]", reg_rd);
4487
  s3_do_ldst_insn (append_str);
4488
 
4489
  s3_nor1 = r1_bak;
4490
}
4491
/* Handle bcmpeq / bcmpne  */
4492
static void
4493
s3_do_macro_bcmp (char *str)
4494
{
4495
  int reg_a , reg_b;
4496
  char keep_data[s3_MAX_LITERAL_POOL_SIZE];
4497
  char* ptemp;
4498
  int i=0;
4499
  struct s3_score_it inst_expand[2];
4500
  struct s3_score_it inst_main;
4501
 
4502
 
4503
  s3_skip_whitespace (str);
4504
  if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4505
      || s3_skip_past_comma (&str) == (int) s3_FAIL
4506
      ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4507
      || s3_skip_past_comma (&str) == (int) s3_FAIL)
4508
      return;
4509
  ptemp =str;
4510
  while(*ptemp!=0)
4511
  {
4512
        keep_data[i]=*ptemp;
4513
        i++;
4514
        ptemp++;
4515
  }
4516
  keep_data[i]=0;
4517
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4518
      ||reg_b ==0
4519
      || s3_end_of_line (str) == (int) s3_FAIL)
4520
    return ;
4521
  else if (s3_inst.reloc.exp.X_add_symbol == 0)
4522
    {
4523
      s3_inst.error = _("lacking label  ");
4524
      return;
4525
    }
4526
  else
4527
    {
4528
      char append_str[s3_MAX_LITERAL_POOL_SIZE];
4529
      s3_SET_INSN_ERROR (NULL);
4530
 
4531
      s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
4532
      s3_inst.reloc.pc_rel = 1;
4533
      bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
4534
 
4535
      /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
4536
      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;
4537
 
4538
      /* Check and set offset.  */
4539
      if (((val & 0xfffffe00) != 0)
4540
           && ((val & 0xfffffe00) != 0xfffffe00))
4541
        {
4542
          /* support bcmp --> cmp!+beq (bne) */
4543
          if (s3_score_pic == s3_NO_PIC)
4544
            {
4545
              sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b);
4546
              if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL)
4547
                return;
4548
              if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4549
                sprintf (&append_str[1], "beq %s", keep_data);
4550
              else
4551
                sprintf (&append_str[1], "bne %s", keep_data);
4552
              if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL)
4553
                return;
4554
              }
4555
            else
4556
              {
4557
                gas_assert (s3_inst.reloc.exp.X_add_symbol);
4558
              }
4559
            /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4560
            s3_inst.bwarn = -1;
4561
            return;
4562
        }
4563
      else
4564
        {
4565
          val >>= 1;
4566
          s3_inst.instruction |= (val & 0x1)
4567
                              | (((val >> 1) & 0x7) << 7)
4568
                              | (((val >> 4) & 0x1f) << 20);
4569
        }
4570
 
4571
      /* Backup s3_inst.  */
4572
      memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
4573
 
4574
      if (s3_score_pic == s3_NO_PIC)
4575
        {
4576
          sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b);
4577
          if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL)
4578
            return;
4579
          memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4580
 
4581
          if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4582
            sprintf (&append_str[1], "beq %s", keep_data);
4583
          else
4584
            sprintf (&append_str[1], "bne %s", keep_data);
4585
          if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL)
4586
            return;
4587
          memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
4588
        }
4589
      else
4590
        {
4591
          gas_assert (s3_inst.reloc.exp.X_add_symbol);
4592
        }
4593
      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4594
      inst_main.type = Insn_BCMP;
4595
 
4596
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4597
      inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4598
 
4599
      for (i = 0; i < 2; i++)
4600
        inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
4601
                                                          s3_GET_INSN_CLASS (inst_expand[i].type));
4602
      /* Check data dependency.  */
4603
      s3_handle_dependency (&inst_main);
4604
      /* Start a new frag if frag_now is not empty.  */
4605
      if (frag_now_fix () != 0)
4606
      {
4607
        if (!frag_now->tc_frag_data.is_insn)
4608
          frag_wane (frag_now);
4609
        frag_new (0);
4610
      }
4611
      frag_grow (20);
4612
 
4613
      /* Write fr_fix part.  */
4614
      char *p;
4615
      p = frag_more (inst_main.size);
4616
      s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4617
 
4618
      if (inst_main.reloc.type != BFD_RELOC_NONE)
4619
      {
4620
        s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4621
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4622
      }
4623
#ifdef OBJ_ELF
4624
      dwarf2_emit_insn (inst_main.size);
4625
#endif
4626
 
4627
      /* s3_GP instruction can not do optimization, only can do relax between
4628
         1 instruction and 3 instructions.  */
4629
      p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4630
                    s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4631
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
4632
 
4633
      /* Write fr_var part.
4634
         no calling s3_gen_insn_frag, no fixS will be generated.  */
4635
      s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4636
      p += inst_expand[0].size;
4637
      s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4638
      p += inst_expand[1].size;
4639
 
4640
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4641
      s3_inst.bwarn = -1;
4642
     }
4643
}
4644
 
4645
/* Handle bcmpeqz / bcmpnez  */
4646
static void
4647
s3_do_macro_bcmpz (char *str)
4648
{
4649
  int reg_a ;
4650
  char keep_data[s3_MAX_LITERAL_POOL_SIZE];
4651
  char* ptemp;
4652
  int i=0;
4653
  struct s3_score_it inst_expand[2];
4654
  struct s3_score_it inst_main;
4655
 
4656
  s3_skip_whitespace (str);
4657
  if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
4658
      || s3_skip_past_comma (&str) == (int) s3_FAIL   )
4659
    return;
4660
  ptemp =str;
4661
  while(*ptemp!=0)
4662
  {
4663
        keep_data[i]=*ptemp;
4664
        i++;
4665
        ptemp++;
4666
  }
4667
  keep_data[i]=0;
4668
  if ( s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
4669
      || s3_end_of_line (str) == (int) s3_FAIL)
4670
    return ;
4671
 
4672
  else if (s3_inst.reloc.exp.X_add_symbol == 0)
4673
    {
4674
      s3_inst.error = _("lacking label  ");
4675
      return;
4676
    }
4677
  else
4678
    {
4679
      char append_str[s3_MAX_LITERAL_POOL_SIZE];
4680
      s3_SET_INSN_ERROR (NULL);
4681
      s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
4682
      s3_inst.reloc.pc_rel = 1;
4683
      bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
4684
 
4685
      /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
4686
      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;
4687
 
4688
      /* Check and set offset.  */
4689
      if (((val & 0xfffffe00) != 0)
4690
           && ((val & 0xfffffe00) != 0xfffffe00))
4691
        {
4692
          if (s3_score_pic == s3_NO_PIC)
4693
            {
4694
              sprintf (&append_str[0], "cmpi! r%d,0", reg_a);
4695
              if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL)
4696
                return;
4697
              if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4698
                sprintf (&append_str[1], "beq %s", keep_data);
4699
              else
4700
                sprintf (&append_str[1], "bne %s", keep_data);
4701
              if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL)
4702
                return;
4703
            }
4704
          else
4705
            {
4706
              gas_assert (s3_inst.reloc.exp.X_add_symbol);
4707
            }
4708
          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4709
          s3_inst.bwarn = -1;
4710
          return;
4711
        }
4712
      else
4713
        {
4714
          val >>= 1;
4715
          s3_inst.instruction |= (val & 0x1)
4716
                              | (((val >> 1) & 0x7) << 7)
4717
                              | (((val >> 4) & 0x1f) << 20);
4718
        }
4719
 
4720
      /* Backup s3_inst.  */
4721
      memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
4722
 
4723
      if (s3_score_pic == s3_NO_PIC)
4724
        {
4725
          sprintf (&append_str[0], "cmpi! r%d, 0", reg_a);
4726
          if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL)
4727
            return;
4728
          memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
4729
          if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
4730
            sprintf (&append_str[1], "beq %s", keep_data);
4731
          else
4732
            sprintf (&append_str[1], "bne %s", keep_data);
4733
          if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL)
4734
            return;
4735
          memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
4736
        }
4737
      else
4738
        {
4739
          gas_assert (s3_inst.reloc.exp.X_add_symbol);
4740
        }
4741
      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
4742
      inst_main.type = Insn_BCMP;
4743
 
4744
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4745
      inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
4746
 
4747
      for (i = 0; i < 2; i++)
4748
        inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction , s3_GET_INSN_CLASS (inst_expand[i].type));
4749
      /* Check data dependency.  */
4750
      s3_handle_dependency (&inst_main);
4751
      /* Start a new frag if frag_now is not empty.  */
4752
      if (frag_now_fix () != 0)
4753
      {
4754
        if (!frag_now->tc_frag_data.is_insn)
4755
          frag_wane (frag_now);
4756
        frag_new (0);
4757
      }
4758
      frag_grow (20);
4759
 
4760
      /* Write fr_fix part.  */
4761
      char *p;
4762
      p = frag_more (inst_main.size);
4763
      s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
4764
 
4765
      if (inst_main.reloc.type != BFD_RELOC_NONE)
4766
      {
4767
        s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4768
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4769
      }
4770
#ifdef OBJ_ELF
4771
      dwarf2_emit_insn (inst_main.size);
4772
#endif
4773
 
4774
      /* s3_GP instruction can not do optimization, only can do relax between
4775
         1 instruction and 3 instructions.  */
4776
      p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
4777
                    s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
4778
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
4779
 
4780
      /* Write fr_var part.
4781
         no calling s3_gen_insn_frag, no fixS will be generated.  */
4782
      s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4783
      p += inst_expand[0].size;
4784
      s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4785
      p += inst_expand[1].size;
4786
 
4787
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4788
      s3_inst.bwarn = -1;
4789
     }
4790
}
4791
 
4792
static int
4793
s3_nopic_need_relax (symbolS * sym, int before_relaxing)
4794
{
4795
  if (sym == NULL)
4796
    return 0;
4797
  else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0)
4798
    {
4799
      const char *symname;
4800
      const char *segname;
4801
 
4802
      /* Find out whether this symbol can be referenced off the $gp
4803
         register.  It can be if it is smaller than the -G size or if
4804
         it is in the .sdata or .sbss section.  Certain symbols can
4805
         not be referenced off the $gp, although it appears as though
4806
         they can.  */
4807
      symname = S_GET_NAME (sym);
4808
      if (symname != (const char *)NULL
4809
          && (strcmp (symname, "eprol") == 0
4810
              || strcmp (symname, "etext") == 0
4811
              || strcmp (symname, "_gp") == 0
4812
              || strcmp (symname, "edata") == 0
4813
              || strcmp (symname, "_fbss") == 0
4814
              || strcmp (symname, "_fdata") == 0
4815
              || strcmp (symname, "_ftext") == 0
4816
              || strcmp (symname, "end") == 0
4817
              || strcmp (symname, GP_DISP_LABEL) == 0))
4818
        {
4819
          return 1;
4820
        }
4821
      else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4822
      /* We must defer this decision until after the whole file has been read,
4823
         since there might be a .extern after the first use of this symbol.  */
4824
               || (before_relaxing
4825
                   && S_GET_VALUE (sym) == 0)
4826
               || (S_GET_VALUE (sym) != 0
4827
                   && S_GET_VALUE (sym) <= s3_g_switch_value)))
4828
        {
4829
          return 0;
4830
        }
4831
 
4832
      segname = segment_name (S_GET_SEGMENT (sym));
4833
      return (strcmp (segname, ".sdata") != 0
4834
              && strcmp (segname, ".sbss") != 0
4835
              && strncmp (segname, ".sdata.", 7) != 0
4836
              && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4837
    }
4838
  /* We are not optimizing for the $gp register.  */
4839
  else
4840
    return 1;
4841
}
4842
 
4843
/* Build a relax frag for lw/st instruction when generating s3_PIC,
4844
   external symbol first and local symbol second.  */
4845
static void
4846
s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4847
{
4848
  symbolS *add_symbol = exp.X_add_symbol;
4849
  int add_number = exp.X_add_number;
4850
  struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
4851
  struct s3_score_it var_insts[s3_RELAX_INST_NUM];
4852
  int fix_num = 0;
4853
  int var_num = 0;
4854
  char tmp[s3_MAX_LITERAL_POOL_SIZE];
4855
  int r1_bak;
4856
 
4857
  r1_bak = s3_nor1;
4858
  s3_nor1 = 0;
4859
 
4860
  if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4861
    {
4862
      fix_num = 1;
4863
      var_num = 2;
4864
 
4865
      /* For an external symbol, two insns are generated;
4866
         For a local symbol, three insns are generated.  */
4867
      /* Fix part
4868
         For an external symbol: lw rD, <sym>($gp)
4869
                                 (BFD_RELOC_SCORE_GOT15)  */
4870
      sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4871
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4872
        return;
4873
 
4874
      memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
4875
 
4876
      /* Var part
4877
         For a local symbol :
4878
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4879
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4880
      s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4881
      memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
4882
      sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4883
      if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
4884
        return;
4885
 
4886
      memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
4887
      s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4888
 
4889
      /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
4890
      sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4891
      if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
4892
        return;
4893
 
4894
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4895
      s3_inst.bwarn = -1;
4896
    }
4897
  else
4898
    {
4899
      s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)");
4900
      return;
4901
    }
4902
 
4903
  s3_nor1 = r1_bak;
4904
}
4905
 
4906
static void
4907
s3_do_macro_ldst_label (char *str)
4908
{
4909
  int i;
4910
  int ldst_gp_p = 0;
4911
  int reg_rd;
4912
  int r1_bak;
4913
  char *backup_str;
4914
  char *label_str;
4915
  char *absolute_value;
4916
  char append_str[3][s3_MAX_LITERAL_POOL_SIZE];
4917
  char verifystr[s3_MAX_LITERAL_POOL_SIZE];
4918
  struct s3_score_it inst_backup;
4919
  struct s3_score_it inst_expand[3];
4920
  struct s3_score_it inst_main;
4921
 
4922
  memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
4923
  strcpy (verifystr, str);
4924
  backup_str = verifystr;
4925
 
4926
  s3_skip_whitespace (backup_str);
4927
  if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
4928
    return;
4929
 
4930
  if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL)
4931
    return;
4932
 
4933
  label_str = backup_str;
4934
 
4935
  /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
4936
  if (*backup_str == '[')
4937
    {
4938
      s3_inst.type = Rd_rvalueRs_preSI12;
4939
      s3_do_ldst_insn (str);
4940
      return;
4941
    }
4942
 
4943
  /* Ld/st rD, imm.  */
4944
  absolute_value = backup_str;
4945
  s3_inst.type = Rd_rvalueRs_SI15;
4946
 
4947
  if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL)
4948
    {
4949
      s3_inst.error = _("expression error");
4950
      return;
4951
    }
4952
  else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
4953
           && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL))
4954
    {
4955
      s3_inst.error = _("value not in range [0, 0x7fffffff]");
4956
      return;
4957
    }
4958
  else if (s3_end_of_line (backup_str) == (int) s3_FAIL)
4959
    {
4960
      s3_inst.error = _("end on line error");
4961
      return;
4962
    }
4963
  else
4964
    {
4965
      if (s3_inst.reloc.exp.X_add_symbol == 0)
4966
        {
4967
          memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
4968
          s3_exp_macro_ldst_abs (str);
4969
          return;
4970
        }
4971
    }
4972
 
4973
  /* Ld/st rD, label.  */
4974
  s3_inst.type = Rd_rvalueRs_SI15;
4975
  backup_str = absolute_value;
4976
  if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL)
4977
      || (s3_end_of_line (backup_str) == (int) s3_FAIL))
4978
    {
4979
      return;
4980
    }
4981
  else
4982
    {
4983
      if (s3_inst.reloc.exp.X_add_symbol == 0)
4984
        {
4985
          if (!s3_inst.error)
4986
            s3_inst.error = s3_BAD_ARGS;
4987
 
4988
          return;
4989
        }
4990
 
4991
      if (s3_score_pic == s3_PIC)
4992
        {
4993
          int ldst_idx = 0;
4994
          ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
4995
          s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp,
4996
                             s3_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4997
          return;
4998
        }
4999
      else
5000
        {
5001
          if ((s3_inst.reloc.exp.X_add_number <= 0x3fff)
5002
               && (s3_inst.reloc.exp.X_add_number >= -0x4000)
5003
               && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1)))
5004
            {
5005
              int ldst_idx = 0;
5006
 
5007
              /* Assign the real opcode.  */
5008
              ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
5009
              s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
5010
              s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value;
5011
              s3_inst.instruction |= reg_rd << 20;
5012
              s3_inst.instruction |= s3_GP << 15;
5013
              s3_inst.relax_inst = 0x8000;
5014
              s3_inst.relax_size = 0;
5015
              ldst_gp_p = 1;
5016
            }
5017
        }
5018
    }
5019
 
5020
  /* Backup s3_inst.  */
5021
  memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
5022
  r1_bak = s3_nor1;
5023
  s3_nor1 = 0;
5024
 
5025
  /* Determine which instructions should be output.  */
5026
  sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
5027
  sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
5028
  sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
5029
 
5030
  /* Generate three instructions.
5031
     la r1, label
5032
     ld/st rd, [r1, 0]  */
5033
  for (i = 0; i < 3; i++)
5034
    {
5035
      if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL)
5036
        return;
5037
 
5038
      memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it));
5039
    }
5040
 
5041
  if (ldst_gp_p)
5042
    {
5043
      char *p;
5044
 
5045
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
5046
      inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
5047
 
5048
      /* relax lw rd, label -> ldis rs, imm16
5049
                               ori  rd, imm16
5050
                               lw rd, [rs, imm15] or lw! rd, [rs, imm5].  */
5051
      if (inst_expand[2].relax_size == 0)
5052
        inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
5053
      else
5054
        inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size;
5055
 
5056
      inst_main.type = Insn_GP;
5057
 
5058
      for (i = 0; i < 3; i++)
5059
        inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
5060
                                                          s3_GET_INSN_CLASS (inst_expand[i].type));
5061
 
5062
      /* Check data dependency.  */
5063
      s3_handle_dependency (&inst_main);
5064
 
5065
      /* Start a new frag if frag_now is not empty.  */
5066
      if (frag_now_fix () != 0)
5067
        {
5068
          if (!frag_now->tc_frag_data.is_insn)
5069
            frag_wane (frag_now);
5070
 
5071
          frag_new (0);
5072
        }
5073
      frag_grow (20);
5074
 
5075
      /* Write fr_fix part.  */
5076
      p = frag_more (inst_main.size);
5077
      s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
5078
 
5079
      if (inst_main.reloc.type != BFD_RELOC_NONE)
5080
        {
5081
          s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
5082
                         &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
5083
        }
5084
 
5085
#ifdef OBJ_ELF
5086
      dwarf2_emit_insn (inst_main.size);
5087
#endif
5088
 
5089
      /* s3_GP instruction can not do optimization, only can do relax between
5090
         1 instruction and 3 instructions.  */
5091
      p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
5092
                    s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
5093
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
5094
 
5095
      /* Write fr_var part.
5096
         no calling s3_gen_insn_frag, no fixS will be generated.  */
5097
      s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
5098
      p += inst_expand[0].size;
5099
      s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
5100
      p += inst_expand[1].size;
5101
 
5102
      /* relax lw rd, label -> ldis rs, imm16
5103
                               ori  rd, imm16
5104
                               lw rd, [rs, imm15] or lw! rd, [rs, imm5].  */
5105
      if (inst_expand[2].relax_size == 0)
5106
        s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
5107
      else
5108
        s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size);
5109
    }
5110
  else
5111
    {
5112
      s3_gen_insn_frag (&inst_expand[0], NULL);
5113
      s3_gen_insn_frag (&inst_expand[1], NULL);
5114
      s3_gen_insn_frag (&inst_expand[2], NULL);
5115
    }
5116
  s3_nor1 = r1_bak;
5117
 
5118
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
5119
  s3_inst.bwarn = -1;
5120
}
5121
 
5122
static void
5123
s3_do_lw_pic (char *str)
5124
{
5125
  int reg_rd;
5126
 
5127
  s3_skip_whitespace (str);
5128
  if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5129
      || (s3_skip_past_comma (&str) == (int) s3_FAIL)
5130
      || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
5131
      || (s3_end_of_line (str) == (int) s3_FAIL))
5132
    {
5133
      return;
5134
    }
5135
  else
5136
    {
5137
      if (s3_inst.reloc.exp.X_add_symbol == 0)
5138
        {
5139
          if (!s3_inst.error)
5140
            s3_inst.error = s3_BAD_ARGS;
5141
 
5142
          return;
5143
        }
5144
 
5145
      s3_inst.instruction |= s3_GP << 15;
5146
      s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
5147
    }
5148
}
5149
 
5150
static void
5151
s3_do_empty (char *str)
5152
{
5153
  str = str;
5154
  if (s3_university_version == 1)
5155
    {
5156
      if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004)
5157
          || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024)
5158
          || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044)
5159
          || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064))
5160
        {
5161
          s3_inst.error = s3_ERR_FOR_SCORE5U_MMU;
5162
          return;
5163
        }
5164
    }
5165
  if (s3_end_of_line (str) == (int) s3_FAIL)
5166
    return;
5167
 
5168
  if (s3_inst.relax_inst != 0x8000)
5169
    {
5170
      if (s3_inst.type == NO_OPD)
5171
        {
5172
          s3_inst.relax_size = 2;
5173
        }
5174
      else
5175
        {
5176
          s3_inst.relax_size = 4;
5177
        }
5178
    }
5179
}
5180
 
5181
static void
5182
s3_do16_int (char *str)
5183
{
5184
  s3_skip_whitespace (str);
5185
  return;
5186
}
5187
 
5188
static void
5189
s3_do_jump (char *str)
5190
{
5191
  char *save_in;
5192
 
5193
  s3_skip_whitespace (str);
5194
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5195
      || s3_end_of_line (str) == (int) s3_FAIL)
5196
    return;
5197
 
5198
  if (s3_inst.reloc.exp.X_add_symbol == 0)
5199
    {
5200
      s3_inst.error = _("lacking label  ");
5201
      return;
5202
    }
5203
 
5204
  if (!(s3_inst.reloc.exp.X_add_number >= -16777216
5205
      && s3_inst.reloc.exp.X_add_number <= 16777215))
5206
    {
5207
      s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
5208
      return;
5209
    }
5210
 
5211
  save_in = input_line_pointer;
5212
  input_line_pointer = str;
5213
  s3_inst.reloc.type = BFD_RELOC_SCORE_JMP;
5214
  s3_inst.reloc.pc_rel = 1;
5215
  input_line_pointer = save_in;
5216
}
5217
 
5218
static void
5219
s3_do_branch (char *str)
5220
{
5221
  if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5222
      || s3_end_of_line (str) == (int) s3_FAIL)
5223
    {
5224
      return;
5225
    }
5226
  else if (s3_inst.reloc.exp.X_add_symbol == 0)
5227
    {
5228
      s3_inst.error = _("lacking label  ");
5229
      return;
5230
    }
5231
  else if (!(s3_inst.reloc.exp.X_add_number >= -524288
5232
           && s3_inst.reloc.exp.X_add_number <= 524287))
5233
    {
5234
      s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5235
      return;
5236
    }
5237
 
5238
  s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5239
  s3_inst.reloc.pc_rel = 1;
5240
 
5241
  /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
5242
  s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5243
 
5244
  /* Compute 16 bit branch instruction.  */
5245
  if ((s3_inst.relax_inst != 0x8000)
5246
      && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511))
5247
    {
5248
      s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */
5249
      s3_inst.relax_size = 2;
5250
    }
5251
  else
5252
    {
5253
      s3_inst.relax_inst = 0x8000;
5254
    }
5255
}
5256
 
5257
static void
5258
s3_do16_branch (char *str)
5259
{
5260
  if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
5261
      || s3_end_of_line (str) == (int) s3_FAIL))
5262
    {
5263
      ;
5264
    }
5265
  else if (s3_inst.reloc.exp.X_add_symbol == 0)
5266
    {
5267
      s3_inst.error = _("lacking label");
5268
    }
5269
  else if (!(s3_inst.reloc.exp.X_add_number >= -512
5270
           && s3_inst.reloc.exp.X_add_number <= 511))
5271
    {
5272
      s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5273
    }
5274
  else
5275
    {
5276
      s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5277
      s3_inst.reloc.pc_rel = 1;
5278
      s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);
5279
      s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff);
5280
      s3_inst.relax_size = 4;
5281
    }
5282
}
5283
 
5284
/* Return true if the given symbol should be considered local for s3_PIC.  */
5285
static bfd_boolean
5286
s3_pic_need_relax (symbolS *sym, asection *segtype)
5287
{
5288
  asection *symsec;
5289
  bfd_boolean linkonce;
5290
 
5291
  /* Handle the case of a symbol equated to another symbol.  */
5292
  while (symbol_equated_reloc_p (sym))
5293
    {
5294
      symbolS *n;
5295
 
5296
      /* It's possible to get a loop here in a badly written
5297
         program.  */
5298
      n = symbol_get_value_expression (sym)->X_add_symbol;
5299
      if (n == sym)
5300
        break;
5301
      sym = n;
5302
    }
5303
 
5304
  symsec = S_GET_SEGMENT (sym);
5305
 
5306
  /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5307
  linkonce = FALSE;
5308
  if (symsec != segtype && ! S_IS_LOCAL (sym))
5309
    {
5310
      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5311
        linkonce = TRUE;
5312
 
5313
      /* The GNU toolchain uses an extension for ELF: a section
5314
          beginning with the magic string .gnu.linkonce is a linkonce
5315
          section.  */
5316
      if (strncmp (segment_name (symsec), ".gnu.linkonce",
5317
                   sizeof ".gnu.linkonce" - 1) == 0)
5318
        linkonce = TRUE;
5319
    }
5320
 
5321
  /* This must duplicate the test in adjust_reloc_syms.  */
5322
  return (symsec != &bfd_und_section
5323
            && symsec != &bfd_abs_section
5324
          && ! bfd_is_com_section (symsec)
5325
            && !linkonce
5326
#ifdef OBJ_ELF
5327
          /* A global or weak symbol is treated as external.  */
5328
          && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5329
              || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5330
#endif
5331
          );
5332
}
5333
 
5334
static void
5335
s3_parse_pce_inst (char *insnstr)
5336
{
5337
  char c;
5338
  char *p;
5339
  char first[s3_MAX_LITERAL_POOL_SIZE];
5340
  char second[s3_MAX_LITERAL_POOL_SIZE];
5341
  struct s3_score_it pec_part_1;
5342
 
5343
  /* Get first part string of PCE.  */
5344
  p = strstr (insnstr, "||");
5345
  c = *p;
5346
  *p = '\0';
5347
  sprintf (first, "%s", insnstr);
5348
 
5349
  /* Get second part string of PCE.  */
5350
  *p = c;
5351
  p += 2;
5352
  sprintf (second, "%s", p);
5353
 
5354
  s3_parse_16_32_inst (first, FALSE);
5355
  if (s3_inst.error)
5356
    return;
5357
 
5358
  memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst));
5359
 
5360
  s3_parse_16_32_inst (second, FALSE);
5361
  if (s3_inst.error)
5362
    return;
5363
 
5364
  if (   ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE))
5365
      || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE))
5366
      || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE)))
5367
    {
5368
      s3_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5369
      sprintf (s3_inst.str, insnstr);
5370
      return;
5371
    }
5372
 
5373
  if (!s3_inst.error)
5374
    s3_gen_insn_frag (&pec_part_1, &s3_inst);
5375
}
5376
 
5377
/* s3: dsp.  */
5378
static void
5379
s3_do16_dsp (char *str)
5380
{
5381
  int rd = 0;
5382
 
5383
  /* Check 3d.  */
5384
  if (s3_score3d == 0)
5385
    {
5386
      s3_inst.error = _("score3d instruction.");
5387
      return;
5388
    }
5389
 
5390
  s3_skip_whitespace (str);
5391
 
5392
  if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL
5393
      || s3_end_of_line (str) == (int) s3_FAIL)
5394
    {
5395
      return;
5396
    }
5397
  else
5398
    {
5399
      s3_inst.relax_inst |= rd << 20;
5400
      s3_inst.relax_size = 4;
5401
    }
5402
}
5403
 
5404
static void
5405
s3_do16_dsp2 (char *str)
5406
{
5407
  /* Check 3d.  */
5408
  if (s3_score3d == 0)
5409
    {
5410
      s3_inst.error = _("score3d instruction.");
5411
      return;
5412
    }
5413
 
5414
  s3_skip_whitespace (str);
5415
 
5416
  if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
5417
      || s3_skip_past_comma (&str) == (int) s3_FAIL
5418
      || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
5419
      || s3_end_of_line (str) == (int) s3_FAIL)
5420
    {
5421
      return;
5422
    }
5423
  else
5424
    {
5425
      s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20)
5426
        | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10);
5427
      s3_inst.relax_size = 4;
5428
    }
5429
}
5430
 
5431
static void
5432
s3_do_dsp (char *str)
5433
{
5434
  /* Check 3d.  */
5435
  if (s3_score3d == 0)
5436
    {
5437
      s3_inst.error = _("score3d instruction.");
5438
      return;
5439
    }
5440
 
5441
  s3_skip_whitespace (str);
5442
 
5443
  if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5444
      || s3_skip_past_comma (&str) == (int) s3_FAIL
5445
      || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5446
      || s3_end_of_line (str) == (int) s3_FAIL)
5447
    return;
5448
 
5449
  if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
5450
    {
5451
      s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5452
      s3_inst.relax_size = 2;
5453
    }
5454
  else
5455
    s3_inst.relax_inst = 0x8000;
5456
}
5457
 
5458
static void
5459
s3_do_dsp2 (char *str)
5460
{
5461
  int reg;
5462
 
5463
  /* Check 3d.  */
5464
  if (s3_score3d == 0)
5465
    {
5466
      s3_inst.error = _("score3d instruction.");
5467
      return;
5468
    }
5469
 
5470
  s3_skip_whitespace (str);
5471
 
5472
  if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5473
      || s3_skip_past_comma (&str) == (int) s3_FAIL
5474
      || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5475
      || s3_skip_past_comma (&str) == (int) s3_FAIL
5476
      || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5477
      || s3_end_of_line (str) == (int) s3_FAIL)
5478
    {
5479
      return;
5480
    }
5481
  else
5482
    {
5483
      /* Check mulr, mulur rd is even number.  */
5484
      if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
5485
            || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
5486
          && (reg % 2))
5487
        {
5488
          s3_inst.error = _("rd must be even number.");
5489
          return;
5490
        }
5491
 
5492
      if ((((s3_inst.instruction >> 15) & 0x10) == 0)
5493
          && (((s3_inst.instruction >> 10) & 0x10) == 0)
5494
          && (((s3_inst.instruction >> 20) & 0x10) == 0)
5495
          && (s3_inst.relax_inst != 0x8000)
5496
          && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
5497
        {
5498
          s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
5499
            | (((s3_inst.instruction >> 15) & 0xf) << 4);
5500
          s3_inst.relax_size = 2;
5501
        }
5502
      else
5503
        {
5504
          s3_inst.relax_inst = 0x8000;
5505
        }
5506
    }
5507
}
5508
 
5509
static void
5510
s3_do_dsp3 (char *str)
5511
{
5512
  /* Check 3d.  */
5513
  if (s3_score3d == 0)
5514
    {
5515
      s3_inst.error = _("score3d instruction.");
5516
      return;
5517
    }
5518
 
5519
  s3_skip_whitespace (str);
5520
 
5521
  if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5522
      || s3_skip_past_comma (&str) == (int) s3_FAIL
5523
      || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
5524
      || s3_end_of_line (str) == (int) s3_FAIL)
5525
    return;
5526
 
5527
  if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
5528
    {
5529
      s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
5530
      s3_inst.relax_size = 2;
5531
    }
5532
  else
5533
    s3_inst.relax_inst = 0x8000;
5534
}
5535
 
5536
 
5537
/* If we change section we must dump the literal pool first.  */
5538
static void
5539
s3_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5540
{
5541
  subseg_set (bss_section, (subsegT) get_absolute_expression ());
5542
  demand_empty_rest_of_line ();
5543
}
5544
 
5545
static void
5546
s3_s_score_text (int ignore)
5547
{
5548
  obj_elf_text (ignore);
5549
  record_alignment (now_seg, 2);
5550
}
5551
 
5552
static void
5553
s3_score_s_section (int ignore)
5554
{
5555
  obj_elf_section (ignore);
5556
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5557
    record_alignment (now_seg, 2);
5558
 
5559
}
5560
 
5561
static void
5562
s3_s_change_sec (int sec)
5563
{
5564
  segT seg;
5565
 
5566
#ifdef OBJ_ELF
5567
  /* The ELF backend needs to know that we are changing sections, so
5568
     that .previous works correctly.  We could do something like check
5569
     for an obj_section_change_hook macro, but that might be confusing
5570
     as it would not be appropriate to use it in the section changing
5571
     functions in read.c, since obj-elf.c intercepts those.  FIXME:
5572
     This should be cleaner, somehow.  */
5573
  obj_elf_section_change_hook ();
5574
#endif
5575
  switch (sec)
5576
    {
5577
    case 'r':
5578
      seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5579
      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5580
      if (strcmp (TARGET_OS, "elf") != 0)
5581
        record_alignment (seg, 4);
5582
      demand_empty_rest_of_line ();
5583
      break;
5584
    case 's':
5585
      seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5586
      bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5587
      if (strcmp (TARGET_OS, "elf") != 0)
5588
        record_alignment (seg, 4);
5589
      demand_empty_rest_of_line ();
5590
      break;
5591
    }
5592
}
5593
 
5594
static void
5595
s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5596
{
5597
  long mask, off;
5598
 
5599
  if (s3_cur_proc_ptr == (s3_procS *) NULL)
5600
    {
5601
      as_warn (_(".mask outside of .ent"));
5602
      demand_empty_rest_of_line ();
5603
      return;
5604
    }
5605
  if (get_absolute_expression_and_terminator (&mask) != ',')
5606
    {
5607
      as_warn (_("Bad .mask directive"));
5608
      --input_line_pointer;
5609
      demand_empty_rest_of_line ();
5610
      return;
5611
    }
5612
  off = get_absolute_expression ();
5613
  s3_cur_proc_ptr->reg_mask = mask;
5614
  s3_cur_proc_ptr->reg_offset = off;
5615
  demand_empty_rest_of_line ();
5616
}
5617
 
5618
static symbolS *
5619
s3_get_symbol (void)
5620
{
5621
  int c;
5622
  char *name;
5623
  symbolS *p;
5624
 
5625
  name = input_line_pointer;
5626
  c = get_symbol_end ();
5627
  p = (symbolS *) symbol_find_or_make (name);
5628
  *input_line_pointer = c;
5629
  return p;
5630
}
5631
 
5632
static long
5633
s3_get_number (void)
5634
{
5635
  int negative = 0;
5636
  long val = 0;
5637
 
5638
  if (*input_line_pointer == '-')
5639
    {
5640
      ++input_line_pointer;
5641
      negative = 1;
5642
    }
5643
  if (!ISDIGIT (*input_line_pointer))
5644
    as_bad (_("expected simple number"));
5645
  if (input_line_pointer[0] == '0')
5646
    {
5647
      if (input_line_pointer[1] == 'x')
5648
        {
5649
          input_line_pointer += 2;
5650
          while (ISXDIGIT (*input_line_pointer))
5651
            {
5652
              val <<= 4;
5653
              val |= hex_value (*input_line_pointer++);
5654
            }
5655
          return negative ? -val : val;
5656
        }
5657
      else
5658
        {
5659
          ++input_line_pointer;
5660
          while (ISDIGIT (*input_line_pointer))
5661
            {
5662
              val <<= 3;
5663
              val |= *input_line_pointer++ - '0';
5664
            }
5665
          return negative ? -val : val;
5666
        }
5667
    }
5668
  if (!ISDIGIT (*input_line_pointer))
5669
    {
5670
      printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5671
      as_warn (_("invalid number"));
5672
      return -1;
5673
    }
5674
  while (ISDIGIT (*input_line_pointer))
5675
    {
5676
      val *= 10;
5677
      val += *input_line_pointer++ - '0';
5678
    }
5679
  return negative ? -val : val;
5680
}
5681
 
5682
/* The .aent and .ent directives.  */
5683
static void
5684
s3_s_score_ent (int aent)
5685
{
5686
  symbolS *symbolP;
5687
  int maybe_text;
5688
 
5689
  symbolP = s3_get_symbol ();
5690
  if (*input_line_pointer == ',')
5691
    ++input_line_pointer;
5692
  SKIP_WHITESPACE ();
5693
  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5694
    s3_get_number ();
5695
 
5696
#ifdef BFD_ASSEMBLER
5697
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5698
    maybe_text = 1;
5699
  else
5700
    maybe_text = 0;
5701
#else
5702
  if (now_seg != data_section && now_seg != bss_section)
5703
    maybe_text = 1;
5704
  else
5705
    maybe_text = 0;
5706
#endif
5707
  if (!maybe_text)
5708
    as_warn (_(".ent or .aent not in text section."));
5709
  if (!aent && s3_cur_proc_ptr)
5710
    as_warn (_("missing .end"));
5711
  if (!aent)
5712
    {
5713
      s3_cur_proc_ptr = &s3_cur_proc;
5714
      s3_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5715
      s3_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5716
      s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5717
      s3_cur_proc_ptr->leaf = 0xdeafbeaf;
5718
      s3_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5719
      s3_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5720
      s3_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5721
      s3_cur_proc_ptr->isym = symbolP;
5722
      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5723
      ++s3_numprocs;
5724
      if (debug_type == DEBUG_STABS)
5725
        stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5726
    }
5727
  demand_empty_rest_of_line ();
5728
}
5729
 
5730
static void
5731
s3_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5732
{
5733
  char *backupstr;
5734
  char str[30];
5735
  long val;
5736
  int i = 0;
5737
 
5738
  backupstr = input_line_pointer;
5739
 
5740
#ifdef OBJ_ELF
5741
  if (s3_cur_proc_ptr == (s3_procS *) NULL)
5742
    {
5743
      as_warn (_(".frame outside of .ent"));
5744
      demand_empty_rest_of_line ();
5745
      return;
5746
    }
5747
  s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5748
  SKIP_WHITESPACE ();
5749
  s3_skip_past_comma (&backupstr);
5750
  while (*backupstr != ',')
5751
    {
5752
      str[i] = *backupstr;
5753
      i++;
5754
      backupstr++;
5755
    }
5756
  str[i] = '\0';
5757
  val = atoi (str);
5758
 
5759
  SKIP_WHITESPACE ();
5760
  s3_skip_past_comma (&backupstr);
5761
  s3_cur_proc_ptr->frame_offset = val;
5762
  s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
5763
 
5764
  SKIP_WHITESPACE ();
5765
  s3_skip_past_comma (&backupstr);
5766
  i = 0;
5767
  while (*backupstr != '\n')
5768
    {
5769
      str[i] = *backupstr;
5770
      i++;
5771
      backupstr++;
5772
    }
5773
  str[i] = '\0';
5774
  val = atoi (str);
5775
  s3_cur_proc_ptr->leaf = val;
5776
  SKIP_WHITESPACE ();
5777
  s3_skip_past_comma (&backupstr);
5778
 
5779
#endif /* OBJ_ELF */
5780
  while (input_line_pointer != backupstr)
5781
    input_line_pointer++;
5782
}
5783
 
5784
/* The .end directive.  */
5785
static void
5786
s3_s_score_end (int x ATTRIBUTE_UNUSED)
5787
{
5788
  symbolS *p;
5789
  int maybe_text;
5790
 
5791
  /* Generate a .pdr section.  */
5792
  segT saved_seg = now_seg;
5793
  subsegT saved_subseg = now_subseg;
5794
  valueT dot;
5795
  expressionS exp;
5796
  char *fragp;
5797
 
5798
  if (!is_end_of_line[(unsigned char)*input_line_pointer])
5799
    {
5800
      p = s3_get_symbol ();
5801
      demand_empty_rest_of_line ();
5802
    }
5803
  else
5804
    p = NULL;
5805
 
5806
#ifdef BFD_ASSEMBLER
5807
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5808
    maybe_text = 1;
5809
  else
5810
    maybe_text = 0;
5811
#else
5812
  if (now_seg != data_section && now_seg != bss_section)
5813
    maybe_text = 1;
5814
  else
5815
    maybe_text = 0;
5816
#endif
5817
 
5818
  if (!maybe_text)
5819
    as_warn (_(".end not in text section"));
5820
  if (!s3_cur_proc_ptr)
5821
    {
5822
      as_warn (_(".end directive without a preceding .ent directive."));
5823
      demand_empty_rest_of_line ();
5824
      return;
5825
    }
5826
  if (p != NULL)
5827
    {
5828
      gas_assert (S_GET_NAME (p));
5829
      if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym)))
5830
        as_warn (_(".end symbol does not match .ent symbol."));
5831
      if (debug_type == DEBUG_STABS)
5832
        stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5833
    }
5834
  else
5835
    as_warn (_(".end directive missing or unknown symbol"));
5836
 
5837
  if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5838
      (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5839
      (s3_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5840
      (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5841
      (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5842
 
5843
  else
5844
    {
5845
      dot = frag_now_fix ();
5846
      gas_assert (s3_pdr_seg);
5847
      subseg_set (s3_pdr_seg, 0);
5848
      /* Write the symbol.  */
5849
      exp.X_op = O_symbol;
5850
      exp.X_add_symbol = p;
5851
      exp.X_add_number = 0;
5852
      emit_expr (&exp, 4);
5853
      fragp = frag_more (7 * 4);
5854
      md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4);
5855
      md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4);
5856
      md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4);
5857
      md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4);
5858
      md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4);
5859
      md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4);
5860
      md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4);
5861
      subseg_set (saved_seg, saved_subseg);
5862
 
5863
    }
5864
  s3_cur_proc_ptr = NULL;
5865
}
5866
 
5867
/* Handle the .set pseudo-op.  */
5868
static void
5869
s3_s_score_set (int x ATTRIBUTE_UNUSED)
5870
{
5871
  int i = 0;
5872
  char name[s3_MAX_LITERAL_POOL_SIZE];
5873
  char * orig_ilp = input_line_pointer;
5874
 
5875
  while (!is_end_of_line[(unsigned char)*input_line_pointer])
5876
    {
5877
      name[i] = (char) * input_line_pointer;
5878
      i++;
5879
      ++input_line_pointer;
5880
    }
5881
 
5882
  name[i] = '\0';
5883
 
5884
  if (strcmp (name, "nwarn") == 0)
5885
    {
5886
      s3_warn_fix_data_dependency = 0;
5887
    }
5888
  else if (strcmp (name, "fixdd") == 0)
5889
    {
5890
      s3_fix_data_dependency = 1;
5891
    }
5892
  else if (strcmp (name, "nofixdd") == 0)
5893
    {
5894
      s3_fix_data_dependency = 0;
5895
    }
5896
  else if (strcmp (name, "r1") == 0)
5897
    {
5898
      s3_nor1 = 0;
5899
    }
5900
  else if (strcmp (name, "nor1") == 0)
5901
    {
5902
      s3_nor1 = 1;
5903
    }
5904
  else if (strcmp (name, "optimize") == 0)
5905
    {
5906
      s3_g_opt = 1;
5907
    }
5908
  else if (strcmp (name, "volatile") == 0)
5909
    {
5910
      s3_g_opt = 0;
5911
    }
5912
  else if (strcmp (name, "pic") == 0)
5913
    {
5914
      s3_score_pic = s3_PIC;
5915
    }
5916
  else
5917
    {
5918
      input_line_pointer = orig_ilp;
5919
      s_set (0);
5920
    }
5921
}
5922
 
5923
/* Handle the .cpload pseudo-op.  This is used when generating s3_PIC code.  It sets the
5924
   $gp register for the function based on the function address, which is in the register
5925
   named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5926
   specially by the linker.  The result is:
5927
   ldis gp, %hi(GP_DISP_LABEL)
5928
   ori  gp, %low(GP_DISP_LABEL)
5929
   add  gp, gp, .cpload argument
5930
   The .cpload argument is normally r29.  */
5931
static void
5932
s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5933
{
5934
  int reg;
5935
  char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5936
 
5937
  /* If we are not generating s3_PIC code, .cpload is ignored.  */
5938
  if (s3_score_pic == s3_NO_PIC)
5939
    {
5940
      s_ignore (0);
5941
      return;
5942
    }
5943
 
5944
  if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
5945
    return;
5946
 
5947
  demand_empty_rest_of_line ();
5948
 
5949
  sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL);
5950
  if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5951
    return;
5952
 
5953
  sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL);
5954
  if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5955
    return;
5956
 
5957
  sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg);
5958
  if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5959
    return;
5960
}
5961
 
5962
/* Handle the .cprestore pseudo-op.  This stores $gp into a given
5963
   offset from $sp.  The offset is remembered, and after making a s3_PIC
5964
   call $gp is restored from that location.  */
5965
static void
5966
s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5967
{
5968
  int reg;
5969
  int cprestore_offset;
5970
  char insn_str[s3_MAX_LITERAL_POOL_SIZE];
5971
 
5972
  /* If we are not generating s3_PIC code, .cprestore is ignored.  */
5973
  if (s3_score_pic == s3_NO_PIC)
5974
    {
5975
      s_ignore (0);
5976
      return;
5977
    }
5978
 
5979
  if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
5980
      || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL)
5981
    {
5982
      return;
5983
    }
5984
 
5985
  cprestore_offset = get_absolute_expression ();
5986
 
5987
  if (cprestore_offset <= 0x3fff)
5988
    {
5989
      sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset);
5990
      if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
5991
        return;
5992
    }
5993
  else
5994
    {
5995
      int r1_bak;
5996
 
5997
      r1_bak = s3_nor1;
5998
      s3_nor1 = 0;
5999
 
6000
      sprintf (insn_str, "li r1, %d", cprestore_offset);
6001
      if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6002
        return;
6003
 
6004
      sprintf (insn_str, "add r1, r1, r%d", reg);
6005
      if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6006
        return;
6007
 
6008
      sprintf (insn_str, "sw r%d, [r1]", s3_GP);
6009
      if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6010
        return;
6011
 
6012
      s3_nor1 = r1_bak;
6013
    }
6014
 
6015
  demand_empty_rest_of_line ();
6016
}
6017
 
6018
/* Handle the .gpword pseudo-op.  This is used when generating s3_PIC
6019
   code.  It generates a 32 bit s3_GP relative reloc.  */
6020
static void
6021
s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6022
{
6023
  expressionS ex;
6024
  char *p;
6025
 
6026
  /* When not generating s3_PIC code, this is treated as .word.  */
6027
  if (s3_score_pic == s3_NO_PIC)
6028
    {
6029
      cons (4);
6030
      return;
6031
    }
6032
  expression (&ex);
6033
  if (ex.X_op != O_symbol || ex.X_add_number != 0)
6034
    {
6035
      as_bad (_("Unsupported use of .gpword"));
6036
      ignore_rest_of_line ();
6037
    }
6038
  p = frag_more (4);
6039
  s3_md_number_to_chars (p, (valueT) 0, 4);
6040
  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6041
  demand_empty_rest_of_line ();
6042
}
6043
 
6044
/* Handle the .cpadd pseudo-op.  This is used when dealing with switch
6045
   tables in s3_PIC code.  */
6046
static void
6047
s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6048
{
6049
  int reg;
6050
  char insn_str[s3_MAX_LITERAL_POOL_SIZE];
6051
 
6052
  /* If we are not generating s3_PIC code, .cpload is ignored.  */
6053
  if (s3_score_pic == s3_NO_PIC)
6054
    {
6055
      s_ignore (0);
6056
      return;
6057
    }
6058
 
6059
  if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
6060
    {
6061
      return;
6062
    }
6063
  demand_empty_rest_of_line ();
6064
 
6065
  /* Add $gp to the register named as an argument.  */
6066
  sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP);
6067
  if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
6068
    return;
6069
}
6070
 
6071
#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6072
#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)                \
6073
    do                                                          \
6074
    {                                                           \
6075
    if ((SIZE) >= 8)                                            \
6076
    (P2VAR) = 3;                                                \
6077
    else if ((SIZE) >= 4)                                       \
6078
    (P2VAR) = 2;                                                \
6079
    else if ((SIZE) >= 2)                                       \
6080
    (P2VAR) = 1;                                                \
6081
    else                                                        \
6082
    (P2VAR) = 0;                                         \
6083
    }                                                           \
6084
  while (0)
6085
#endif
6086
 
6087
static void
6088
s3_s_score_lcomm (int bytes_p)
6089
{
6090
  char *name;
6091
  char c;
6092
  char *p;
6093
  int temp;
6094
  symbolS *symbolP;
6095
  segT current_seg = now_seg;
6096
  subsegT current_subseg = now_subseg;
6097
  const int max_alignment = 15;
6098
  int align = 0;
6099
  segT bss_seg = bss_section;
6100
  int needs_align = 0;
6101
 
6102
  name = input_line_pointer;
6103
  c = get_symbol_end ();
6104
  p = input_line_pointer;
6105
  *p = c;
6106
 
6107
  if (name == p)
6108
    {
6109
      as_bad (_("expected symbol name"));
6110
      discard_rest_of_line ();
6111
      return;
6112
    }
6113
 
6114
  SKIP_WHITESPACE ();
6115
 
6116
  /* Accept an optional comma after the name.  The comma used to be
6117
     required, but Irix 5 cc does not generate it.  */
6118
  if (*input_line_pointer == ',')
6119
    {
6120
      ++input_line_pointer;
6121
      SKIP_WHITESPACE ();
6122
    }
6123
 
6124
  if (is_end_of_line[(unsigned char)*input_line_pointer])
6125
    {
6126
      as_bad (_("missing size expression"));
6127
      return;
6128
    }
6129
 
6130
  if ((temp = get_absolute_expression ()) < 0)
6131
    {
6132
      as_warn (_("BSS length (%d) < 0 ignored"), temp);
6133
      ignore_rest_of_line ();
6134
      return;
6135
    }
6136
 
6137
#if defined (TC_SCORE)
6138
  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6139
    {
6140
      /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
6141
      if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6142
        {
6143
          bss_seg = subseg_new (".sbss", 1);
6144
          seg_info (bss_seg)->bss = 1;
6145
#ifdef BFD_ASSEMBLER
6146
          if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6147
            as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6148
#endif
6149
        }
6150
    }
6151
#endif
6152
 
6153
  SKIP_WHITESPACE ();
6154
  if (*input_line_pointer == ',')
6155
    {
6156
      ++input_line_pointer;
6157
      SKIP_WHITESPACE ();
6158
 
6159
      if (is_end_of_line[(unsigned char)*input_line_pointer])
6160
        {
6161
          as_bad (_("missing alignment"));
6162
          return;
6163
        }
6164
      else
6165
        {
6166
          align = get_absolute_expression ();
6167
          needs_align = 1;
6168
        }
6169
    }
6170
 
6171
  if (!needs_align)
6172
    {
6173
      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6174
 
6175
      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6176
      if (align)
6177
        record_alignment (bss_seg, align);
6178
    }
6179
 
6180
  if (needs_align)
6181
    {
6182
      if (bytes_p)
6183
        {
6184
          /* Convert to a power of 2.  */
6185
          if (align != 0)
6186
            {
6187
              unsigned int i;
6188
 
6189
              for (i = 0; align != 0; align >>= 1, ++i)
6190
                ;
6191
              align = i - 1;
6192
            }
6193
        }
6194
 
6195
      if (align > max_alignment)
6196
        {
6197
          align = max_alignment;
6198
          as_warn (_("alignment too large; %d assumed"), align);
6199
        }
6200
      else if (align < 0)
6201
        {
6202
          align = 0;
6203
          as_warn (_("alignment negative; 0 assumed"));
6204
        }
6205
 
6206
      record_alignment (bss_seg, align);
6207
    }
6208
  else
6209
    {
6210
      /* Assume some objects may require alignment on some systems.  */
6211
#if defined (TC_ALPHA) && ! defined (VMS)
6212
      if (temp > 1)
6213
        {
6214
          align = ffs (temp) - 1;
6215
          if (temp % (1 << align))
6216
            abort ();
6217
        }
6218
#endif
6219
    }
6220
 
6221
  *p = 0;
6222
  symbolP = symbol_find_or_make (name);
6223
  *p = c;
6224
 
6225
  if (
6226
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6227
     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6228
#ifdef BFD_ASSEMBLER
6229
       (OUTPUT_FLAVOR != bfd_target_aout_flavour
6230
        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6231
#else
6232
       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6233
#endif
6234
#endif
6235
       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6236
    {
6237
      char *pfrag;
6238
 
6239
      subseg_set (bss_seg, 1);
6240
 
6241
      if (align)
6242
        frag_align (align, 0, 0);
6243
 
6244
      /* Detach from old frag.  */
6245
      if (S_GET_SEGMENT (symbolP) == bss_seg)
6246
        symbol_get_frag (symbolP)->fr_symbol = NULL;
6247
 
6248
      symbol_set_frag (symbolP, frag_now);
6249
      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6250
      *pfrag = 0;
6251
 
6252
 
6253
      S_SET_SEGMENT (symbolP, bss_seg);
6254
 
6255
#ifdef OBJ_COFF
6256
      /* The symbol may already have been created with a preceding
6257
         ".globl" directive -- be careful not to step on storage class
6258
         in that case.  Otherwise, set it to static.  */
6259
      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6260
        {
6261
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
6262
        }
6263
#endif /* OBJ_COFF */
6264
 
6265
#ifdef S_SET_SIZE
6266
      S_SET_SIZE (symbolP, temp);
6267
#endif
6268
    }
6269
  else
6270
    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6271
 
6272
  subseg_set (current_seg, current_subseg);
6273
 
6274
  demand_empty_rest_of_line ();
6275
}
6276
 
6277
static void
6278
s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab)
6279
{
6280
  int i = 0;
6281
  int len = strlen (r->name) + 2;
6282
  char *buf = xmalloc (len);
6283
  char *buf2 = xmalloc (len);
6284
 
6285
  strcpy (buf + i, r->name);
6286
  for (i = 0; buf[i]; i++)
6287
    {
6288
      buf2[i] = TOUPPER (buf[i]);
6289
    }
6290
  buf2[i] = '\0';
6291
 
6292
  hash_insert (htab, buf, (void *) r);
6293
  hash_insert (htab, buf2, (void *) r);
6294
}
6295
 
6296
static void
6297
s3_build_reg_hsh (struct s3_reg_map *map)
6298
{
6299
  const struct s3_reg_entry *r;
6300
 
6301
  if ((map->htab = hash_new ()) == NULL)
6302
    {
6303
      as_fatal (_("virtual memory exhausted"));
6304
    }
6305
  for (r = map->names; r->name != NULL; r++)
6306
    {
6307
      s3_insert_reg (r, map->htab);
6308
    }
6309
}
6310
 
6311
/* Iterate over the base tables to create the instruction patterns.  */
6312
static void
6313
s3_build_score_ops_hsh (void)
6314
{
6315
  unsigned int i;
6316
  static struct obstack insn_obstack;
6317
 
6318
  obstack_begin (&insn_obstack, 4000);
6319
  for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
6320
    {
6321
      const struct s3_asm_opcode *insn = s3_score_insns + i;
6322
      unsigned len = strlen (insn->template_name);
6323
      struct s3_asm_opcode *new_opcode;
6324
      char *template_name;
6325
      new_opcode = (struct s3_asm_opcode *)
6326
          obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
6327
      template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
6328
 
6329
      strcpy (template_name, insn->template_name);
6330
      new_opcode->template_name = template_name;
6331
      new_opcode->parms = insn->parms;
6332
      new_opcode->value = insn->value;
6333
      new_opcode->relax_value = insn->relax_value;
6334
      new_opcode->type = insn->type;
6335
      new_opcode->bitmask = insn->bitmask;
6336
      hash_insert (s3_score_ops_hsh, new_opcode->template_name,
6337
                   (void *) new_opcode);
6338
    }
6339
}
6340
 
6341
static void
6342
s3_build_dependency_insn_hsh (void)
6343
{
6344
  unsigned int i;
6345
  static struct obstack dependency_obstack;
6346
 
6347
  obstack_begin (&dependency_obstack, 4000);
6348
  for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
6349
    {
6350
      const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
6351
      unsigned len = strlen (tmp->insn_name);
6352
      struct s3_insn_to_dependency *new_i2n;
6353
 
6354
      new_i2n = (struct s3_insn_to_dependency *)
6355
          obstack_alloc (&dependency_obstack,
6356
                         sizeof (struct s3_insn_to_dependency));
6357
      new_i2n->insn_name = (char *) obstack_alloc (&dependency_obstack,
6358
                                                   len + 1);
6359
 
6360
      strcpy (new_i2n->insn_name, tmp->insn_name);
6361
      new_i2n->type = tmp->type;
6362
      hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name,
6363
                   (void *) new_i2n);
6364
    }
6365
}
6366
 
6367
static void
6368
s_score_bss (int ignore ATTRIBUTE_UNUSED)
6369
{
6370
  if (score3)
6371
    return s3_s_score_bss (ignore);
6372
  else
6373
    return s7_s_score_bss (ignore);
6374
}
6375
 
6376
static void
6377
s_score_text (int ignore)
6378
{
6379
  if (score3)
6380
    return s3_s_score_text (ignore);
6381
  else
6382
    return s7_s_score_text (ignore);
6383
}
6384
 
6385
static void
6386
s_section (int ignore)
6387
{
6388
  if (score3)
6389
    return s3_score_s_section (ignore);
6390
  else
6391
    return s7_s_section (ignore);
6392
}
6393
 
6394
static void
6395
s_change_sec (int sec)
6396
{
6397
  if (score3)
6398
    return s3_s_change_sec (sec);
6399
  else
6400
    return s7_s_change_sec (sec);
6401
}
6402
 
6403
static void
6404
s_score_mask (int reg_type ATTRIBUTE_UNUSED)
6405
{
6406
  if (score3)
6407
    return s3_s_score_mask (reg_type);
6408
  else
6409
    return s7_s_score_mask (reg_type);
6410
}
6411
 
6412
static void
6413
s_score_ent (int aent)
6414
{
6415
  if (score3)
6416
    return s3_s_score_ent (aent);
6417
  else
6418
    return s7_s_score_ent (aent);
6419
}
6420
 
6421
static void
6422
s_score_frame (int ignore ATTRIBUTE_UNUSED)
6423
{
6424
  if (score3)
6425
    return s3_s_score_frame (ignore);
6426
  else
6427
    return s7_s_score_frame (ignore);
6428
}
6429
 
6430
static void
6431
s_score_end (int x ATTRIBUTE_UNUSED)
6432
{
6433
  if (score3)
6434
    return s3_s_score_end (x);
6435
  else
6436
    return s7_s_score_end (x);
6437
}
6438
 
6439
static void
6440
s_score_set (int x ATTRIBUTE_UNUSED)
6441
{
6442
  if (score3)
6443
    return s3_s_score_set (x);
6444
  else
6445
    return s7_s_score_set (x);
6446
}
6447
 
6448
static void
6449
s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6450
{
6451
  if (score3)
6452
    return s3_s_score_cpload (ignore);
6453
  else
6454
    return s7_s_score_cpload (ignore);
6455
}
6456
 
6457
static void
6458
s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6459
{
6460
  if (score3)
6461
    return s3_s_score_cprestore (ignore);
6462
  else
6463
    return s7_s_score_cprestore (ignore);
6464
}
6465
 
6466
static void
6467
s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6468
{
6469
  if (score3)
6470
    return s3_s_score_gpword (ignore);
6471
  else
6472
    return s7_s_score_gpword (ignore);
6473
}
6474
 
6475
static void
6476
s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6477
{
6478
  if (score3)
6479
    return s3_s_score_cpadd (ignore);
6480
  else
6481
    return s7_s_score_cpadd (ignore);
6482
}
6483
 
6484
static void
6485
s_score_lcomm (int bytes_p)
6486
{
6487
  if (score3)
6488
    return s3_s_score_lcomm (bytes_p);
6489
  else
6490
    return s7_s_score_lcomm (bytes_p);
6491
}
6492
 
6493
static void
6494
s3_assemble (char *str)
6495
{
6496
  know (str);
6497
  know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
6498
 
6499
  memset (&s3_inst, '\0', sizeof (s3_inst));
6500
  if (s3_INSN_IS_PCE_P (str))
6501
    s3_parse_pce_inst (str);
6502
  else if (s3_INSN_IS_48_P (str))
6503
    s3_parse_48_inst (str, TRUE);
6504
  else
6505
    s3_parse_16_32_inst (str, TRUE);
6506
 
6507
  if (s3_inst.error)
6508
    as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
6509
}
6510
 
6511
static void
6512
s3_operand (expressionS * exp)
6513
{
6514
  if (s3_in_my_get_expression)
6515
    {
6516
      exp->X_op = O_illegal;
6517
      if (s3_inst.error == NULL)
6518
        {
6519
          s3_inst.error = _("bad expression");
6520
        }
6521
    }
6522
}
6523
 
6524
static void
6525
s3_begin (void)
6526
{
6527
  unsigned int i;
6528
  segT seg;
6529
  subsegT subseg;
6530
 
6531
  if ((s3_score_ops_hsh = hash_new ()) == NULL)
6532
    as_fatal (_("virtual memory exhausted"));
6533
 
6534
  s3_build_score_ops_hsh ();
6535
 
6536
  if ((s3_dependency_insn_hsh = hash_new ()) == NULL)
6537
    as_fatal (_("virtual memory exhausted"));
6538
 
6539
  s3_build_dependency_insn_hsh ();
6540
 
6541
  for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
6542
    s3_build_reg_hsh (s3_all_reg_maps + i);
6543
 
6544
  /* Initialize dependency vector.  */
6545
  s3_init_dependency_vector ();
6546
 
6547
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6548
  seg = now_seg;
6549
  subseg = now_subseg;
6550
  s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6551
  (void)bfd_set_section_flags (stdoutput, s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6552
  (void)bfd_set_section_alignment (stdoutput, s3_pdr_seg, 2);
6553
  subseg_set (seg, subseg);
6554
 
6555
  if (s3_USE_GLOBAL_POINTER_OPT)
6556
    bfd_set_gp_size (stdoutput, s3_g_switch_value);
6557
}
6558
 
6559
static void
6560
s3_number_to_chars (char *buf, valueT val, int n)
6561
{
6562
  if (target_big_endian)
6563
    number_to_chars_bigendian (buf, val, n);
6564
  else
6565
    number_to_chars_littleendian (buf, val, n);
6566
}
6567
 
6568
static valueT
6569
s3_normal_chars_to_number (char *buf, int n)
6570
{
6571
  valueT result = 0;
6572
  unsigned char *where = (unsigned char *)buf;
6573
 
6574
  if (target_big_endian)
6575
    {
6576
      while (n--)
6577
        {
6578
          result <<= 8;
6579
          result |= (*where++ & 255);
6580
        }
6581
    }
6582
  else
6583
    {
6584
      while (n--)
6585
        {
6586
          result <<= 8;
6587
          result |= (where[n] & 255);
6588
        }
6589
    }
6590
 
6591
  return result;
6592
}
6593
 
6594
static void
6595
s3_number_to_chars_littleendian (void *p, valueT data, int n)
6596
{
6597
  char *buf = (char *) p;
6598
 
6599
  switch (n)
6600
    {
6601
    case 4:
6602
      md_number_to_chars (buf, data >> 16, 2);
6603
      md_number_to_chars (buf + 2, data, 2);
6604
      break;
6605
    case 6:
6606
      md_number_to_chars (buf, data >> 32, 2);
6607
      md_number_to_chars (buf + 2, data >> 16, 2);
6608
      md_number_to_chars (buf + 4, data, 2);
6609
      break;
6610
    default:
6611
      /* Error routine.  */
6612
      as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6613
      break;
6614
    }
6615
}
6616
 
6617
static valueT
6618
s3_chars_to_number_littleendian (const void *p, int n)
6619
{
6620
  char *buf = (char *) p;
6621
  valueT result = 0;
6622
 
6623
  switch (n)
6624
    {
6625
    case 4:
6626
      result =  s3_normal_chars_to_number (buf, 2) << 16;
6627
      result |= s3_normal_chars_to_number (buf + 2, 2);
6628
      break;
6629
    case 6:
6630
      result =  s3_normal_chars_to_number (buf, 2) << 32;
6631
      result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
6632
      result |= s3_normal_chars_to_number (buf + 4, 2);
6633
      break;
6634
    default:
6635
      /* Error routine.  */
6636
      as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
6637
      break;
6638
    }
6639
 
6640
  return result;
6641
}
6642
 
6643
static void
6644
s3_md_number_to_chars (char *buf, valueT val, int n)
6645
{
6646
  if (!target_big_endian && n >= 4)
6647
    s3_number_to_chars_littleendian (buf, val, n);
6648
  else
6649
    md_number_to_chars (buf, val, n);
6650
}
6651
 
6652
static valueT
6653
s3_md_chars_to_number (char *buf, int n)
6654
{
6655
  valueT result = 0;
6656
 
6657
  if (!target_big_endian && n >= 4)
6658
    result = s3_chars_to_number_littleendian (buf, n);
6659
  else
6660
    result = s3_normal_chars_to_number (buf, n);
6661
 
6662
  return result;
6663
}
6664
 
6665
static char *
6666
s3_atof (int type, char *litP, int *sizeP)
6667
{
6668
  int prec;
6669
  LITTLENUM_TYPE words[s3_MAX_LITTLENUMS];
6670
  char *t;
6671
  int i;
6672
 
6673
  switch (type)
6674
    {
6675
    case 'f':
6676
    case 'F':
6677
    case 's':
6678
    case 'S':
6679
      prec = 2;
6680
      break;
6681
    case 'd':
6682
    case 'D':
6683
    case 'r':
6684
    case 'R':
6685
      prec = 4;
6686
      break;
6687
    case 'x':
6688
    case 'X':
6689
    case 'p':
6690
    case 'P':
6691
      prec = 6;
6692
      break;
6693
    default:
6694
      *sizeP = 0;
6695
      return _("bad call to MD_ATOF()");
6696
    }
6697
 
6698
  t = atof_ieee (input_line_pointer, type, words);
6699
  if (t)
6700
    input_line_pointer = t;
6701
  *sizeP = prec * 2;
6702
 
6703
  if (target_big_endian)
6704
    {
6705
      for (i = 0; i < prec; i++)
6706
        {
6707
          s3_md_number_to_chars (litP, (valueT) words[i], 2);
6708
          litP += 2;
6709
        }
6710
    }
6711
  else
6712
    {
6713
      for (i = 0; i < prec; i += 2)
6714
        {
6715
          s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
6716
          s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
6717
          litP += 4;
6718
        }
6719
    }
6720
 
6721
  return 0;
6722
}
6723
 
6724
static void
6725
s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6726
{
6727
  know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
6728
}
6729
 
6730
static void
6731
s3_validate_fix (fixS *fixP)
6732
{
6733
  fixP->fx_where += fixP->fx_frag->insn_addr;
6734
}
6735
 
6736
static int
6737
s3_force_relocation (struct fix *fixp)
6738
{
6739
  int retval = 0;
6740
 
6741
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6742
      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6743
      || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6744
      || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6745
      || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6746
      || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
6747
      || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
6748
    {
6749
      retval = 1;
6750
    }
6751
  return retval;
6752
}
6753
 
6754
static bfd_boolean
6755
s3_fix_adjustable (fixS * fixP)
6756
{
6757
  if (fixP->fx_addsy == NULL)
6758
    {
6759
      return 1;
6760
    }
6761
  else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6762
      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6763
    {
6764
      return 0;
6765
    }
6766
  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6767
           || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6768
           || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6769
           || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6770
    {
6771
      return 0;
6772
    }
6773
 
6774
  return 1;
6775
}
6776
 
6777
static void
6778
s3_elf_final_processing (void)
6779
{
6780
  unsigned long val = 0;
6781
 
6782
  if (score3)
6783
    val = E_SCORE_MACH_SCORE3;
6784
  else if (score7)
6785
    val = E_SCORE_MACH_SCORE7;
6786
 
6787
  elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6788
  elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6789
  elf_elfheader (stdoutput)->e_flags |= val;
6790
 
6791
  if (s3_fix_data_dependency == 1)
6792
    {
6793
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6794
    }
6795
  if (s3_score_pic == s3_PIC)
6796
    {
6797
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6798
    }
6799
}
6800
 
6801
static int
6802
s3_judge_size_before_relax (fragS * fragp, asection *sec)
6803
{
6804
  int change = 0;
6805
 
6806
  if (s3_score_pic == s3_NO_PIC)
6807
    change = s3_nopic_need_relax (fragp->fr_symbol, 0);
6808
  else
6809
    change = s3_pic_need_relax (fragp->fr_symbol, sec);
6810
 
6811
  if (change == 1)
6812
    {
6813
      /* Only at the first time determining whether s3_GP instruction relax should be done,
6814
         return the difference between insntruction size and instruction relax size.  */
6815
      if (fragp->fr_opcode == NULL)
6816
        {
6817
          fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
6818
          fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6819
          return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
6820
        }
6821
    }
6822
 
6823
  return 0;
6824
}
6825
 
6826
static int
6827
s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
6828
{
6829
  if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6830
      || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6831
    return s3_judge_size_before_relax (fragp, sec);
6832
 
6833
  return 0;
6834
}
6835
 
6836
static int
6837
s3_relax_branch_inst32 (fragS * fragp)
6838
{
6839
  fragp->fr_opcode = NULL;
6840
  return 0;
6841
}
6842
 
6843
static int
6844
s3_relax_branch_inst16 (fragS * fragp)
6845
{
6846
  int relaxable_p = 0;
6847
  int frag_addr = fragp->fr_address + fragp->insn_addr;
6848
  addressT symbol_address = 0;
6849
  symbolS *s;
6850
  offsetT offset;
6851
  long value;
6852
  unsigned long inst_value;
6853
 
6854
  relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6855
 
6856
  s = fragp->fr_symbol;
6857
  if (s == NULL)
6858
    frag_addr = 0;
6859
  else
6860
    {
6861
      if (s->bsym != 0)
6862
        symbol_address = (addressT) s->sy_frag->fr_address;
6863
    }
6864
 
6865
  inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
6866
  offset = (inst_value & 0x1ff) << 1;
6867
  if ((offset & 0x200) == 0x200)
6868
    offset |= 0xfffffc00;
6869
 
6870
  value = offset + symbol_address - frag_addr;
6871
 
6872
  if (relaxable_p
6873
      && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6874
      && fragp->fr_fix == 2
6875
      && (s->bsym != NULL)
6876
      && (S_IS_DEFINED (s)
6877
          && !S_IS_COMMON (s)
6878
          && !S_IS_EXTERNAL (s)))
6879
    {
6880
      /* Relax branch 32 to branch 16.  */
6881
      fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6882
      fragp->fr_fix = 4;
6883
      return 2;
6884
    }
6885
  else
6886
    return 0;
6887
}
6888
 
6889
static int
6890
s3_relax_cmpbranch_inst32 (fragS * fragp)
6891
{
6892
  int relaxable_p = 0;
6893
  symbolS *s;
6894
  /* For sign bit.  */
6895
  long offset;
6896
  long frag_addr = fragp->fr_address + fragp->insn_addr;
6897
  long symbol_address = 0;
6898
  long value;
6899
  unsigned long inst_value;
6900
 
6901
  relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6902
 
6903
  s = fragp->fr_symbol;
6904
  if (s == NULL)
6905
    frag_addr = 0;
6906
  else
6907
    {
6908
      if (s->bsym != 0)
6909
        symbol_address = (addressT) s->sy_frag->fr_address;
6910
    }
6911
 
6912
  inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
6913
  offset = (inst_value & 0x1)
6914
           | (((inst_value >> 7) & 0x7) << 1)
6915
           | (((inst_value >> 21) & 0x1f) << 4);
6916
  offset <<= 1;
6917
  if ((offset & 0x200) == 0x200)
6918
    offset |= 0xfffffe00;
6919
 
6920
  value = offset + symbol_address - frag_addr;
6921
  /* change the order of judging rule is because
6922
     1.not defined symbol or common sysbol or external symbol will change
6923
       bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
6924
     2.if the flow is as before : it will results to recursive loop
6925
  */
6926
  if (fragp->fr_fix == 6)
6927
    {
6928
      /* Have already relaxed!  Just return 0 to terminate the loop.  */
6929
      return 0;
6930
    }
6931
  /* need to translate when extern or not defind or common sysbol */
6932
  else if ((relaxable_p
6933
      && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
6934
      && fragp->fr_fix == 4
6935
      && (s->bsym != NULL))
6936
      || !S_IS_DEFINED (s)
6937
       ||S_IS_COMMON (s)
6938
        ||S_IS_EXTERNAL (s))
6939
    {
6940
      fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6941
      fragp->fr_fix = 6;
6942
      return 2;
6943
    }
6944
 
6945
  else
6946
    {
6947
      /* Never relax.  Modify fr_opcode to NULL to verify it's value in
6948
         md_apply_fix.  */
6949
      fragp->fr_opcode = NULL;
6950
      return 0;
6951
    }
6952
}
6953
 
6954
 
6955
static int
6956
s3_relax_other_inst32 (fragS * fragp)
6957
{
6958
  int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
6959
 
6960
  if (relaxable_p
6961
      && fragp->fr_fix == 4)
6962
    {
6963
      fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
6964
      fragp->fr_fix = 2;
6965
      return -2;
6966
    }
6967
  else
6968
    return 0;
6969
}
6970
 
6971
static int
6972
s3_relax_gp_and_pic_inst32 (void)
6973
{
6974
  /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
6975
     instructions.  We don't change relax size here.  */
6976
  return 0;
6977
}
6978
 
6979
static int
6980
s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
6981
{
6982
  int grows = 0;
6983
  int adjust_align_p = 0;
6984
 
6985
  /* If the instruction address is odd, make it half word align first.  */
6986
  if ((fragp->fr_address) % 2 != 0)
6987
    {
6988
      if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6989
      {
6990
          fragp->insn_addr = 1;
6991
          grows += 1;
6992
          adjust_align_p = 1;
6993
      }
6994
    }
6995
 
6996
  switch (s3_RELAX_TYPE (fragp->fr_subtype))
6997
    {
6998
    case PC_DISP19div2:
6999
      grows += s3_relax_branch_inst32 (fragp);
7000
      break;
7001
 
7002
    case PC_DISP8div2:
7003
      grows += s3_relax_branch_inst16 (fragp);
7004
      break;
7005
 
7006
    case Insn_BCMP :
7007
      grows += s3_relax_cmpbranch_inst32 (fragp);
7008
      break;
7009
 
7010
    case Insn_GP:
7011
    case Insn_PIC:
7012
      grows += s3_relax_gp_and_pic_inst32 ();
7013
      break;
7014
 
7015
    default:
7016
      grows += s3_relax_other_inst32 (fragp);
7017
      break;
7018
    }
7019
 
7020
  /* newly added */
7021
  if (adjust_align_p && fragp->insn_addr)
7022
    {
7023
      fragp->fr_fix += fragp->insn_addr;
7024
    }
7025
 
7026
  return grows;
7027
}
7028
 
7029
static void
7030
s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7031
{
7032
  int r_old;
7033
  int r_new;
7034
  char backup[20];
7035
  fixS *fixp;
7036
 
7037
  r_old = s3_RELAX_OLD (fragp->fr_subtype);
7038
  r_new = s3_RELAX_NEW (fragp->fr_subtype);
7039
 
7040
  /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
7041
  if (fragp->fr_opcode == NULL)
7042
    {
7043
      memcpy (backup, fragp->fr_literal, r_old);
7044
      fragp->fr_fix = r_old;
7045
    }
7046
  else
7047
    {
7048
      memcpy (backup, fragp->fr_literal + r_old, r_new);
7049
      fragp->fr_fix = r_new;
7050
    }
7051
 
7052
  fixp = fragp->tc_frag_data.fixp;
7053
  while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
7054
    {
7055
      if (fragp->fr_opcode)
7056
        fixp->fx_done = 1;
7057
      fixp = fixp->fx_next;
7058
    }
7059
  while (fixp && fixp->fx_frag == fragp)
7060
    {
7061
      if (fragp->fr_opcode)
7062
        fixp->fx_where -= r_old + fragp->insn_addr;
7063
      else
7064
        fixp->fx_done = 1;
7065
      fixp = fixp->fx_next;
7066
    }
7067
 
7068
  if (fragp->insn_addr)
7069
    {
7070
      s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
7071
    }
7072
  memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
7073
  fragp->fr_fix += fragp->insn_addr;
7074
}
7075
 
7076
static long
7077
s3_pcrel_from (fixS * fixP)
7078
{
7079
  long retval = 0;
7080
 
7081
  if (fixP->fx_addsy
7082
      && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
7083
      && (fixP->fx_subsy == NULL))
7084
    {
7085
      retval = 0;
7086
    }
7087
  else
7088
    {
7089
      retval = fixP->fx_where + fixP->fx_frag->fr_address;
7090
    }
7091
 
7092
  return retval;
7093
}
7094
 
7095
static valueT
7096
s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7097
{
7098
  int align = bfd_get_section_alignment (stdoutput, segment);
7099
  return ((size + (1 << align) - 1) & (-1 << align));
7100
}
7101
 
7102
static void
7103
s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
7104
{
7105
  offsetT value = *valP;
7106
  offsetT newval;
7107
  offsetT content;
7108
  unsigned short HI, LO;
7109
 
7110
  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
7111
 
7112
  gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
7113
  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
7114
    {
7115
      if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
7116
        fixP->fx_done = 1;
7117
    }
7118
 
7119
  /* If this symbol is in a different section then we need to leave it for
7120
     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
7121
     so we have to undo it's effects here.  */
7122
  if (fixP->fx_pcrel)
7123
    {
7124
      if (fixP->fx_addsy != NULL
7125
          && S_IS_DEFINED (fixP->fx_addsy)
7126
          && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7127
        value += md_pcrel_from (fixP);
7128
    }
7129
 
7130
  /* Remember value for emit_reloc.  */
7131
  fixP->fx_addnumber = value;
7132
 
7133
  switch (fixP->fx_r_type)
7134
    {
7135
    case BFD_RELOC_HI16_S:
7136
      if (fixP->fx_done)        /* For la rd, imm32.  */
7137
        {
7138
          newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7139
          HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
7140
          newval |= (HI & 0x3fff) << 1;
7141
          newval |= ((HI >> 14) & 0x3) << 16;
7142
          s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7143
        }
7144
      break;
7145
    case BFD_RELOC_LO16:
7146
      if (fixP->fx_done)        /* For la rd, imm32.  */
7147
        {
7148
          newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7149
          LO = (value) & 0xffff;
7150
          newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
7151
          newval |= ((LO >> 14) & 0x3) << 16;
7152
          s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7153
        }
7154
      break;
7155
    case BFD_RELOC_SCORE_JMP:
7156
      {
7157
        content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7158
        value = fixP->fx_offset;
7159
        content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
7160
        s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7161
      }
7162
      break;
7163
 
7164
    case BFD_RELOC_SCORE_IMM30:
7165
      {
7166
        content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7167
        value = fixP->fx_offset;
7168
        value >>= 2;
7169
        content = (content & ~0x7f7fff7f80LL)
7170
                  | (((value & 0xff) >> 0) << 7)
7171
                  | (((value & 0x7fff00) >> 8) << 16)
7172
                  | (((value & 0x3f800000) >> 23) << 32);
7173
        s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7174
        break;
7175
      }
7176
 
7177
    case BFD_RELOC_SCORE_IMM32:
7178
      {
7179
        content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
7180
        value = fixP->fx_offset;
7181
        content = (content & ~0x7f7fff7fe0LL)
7182
                 | ((value & 0x3ff) << 5)
7183
                 | (((value >> 10) & 0x7fff) << 16)
7184
                 | (((value >> 25) & 0x7f) << 32);
7185
        s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
7186
        break;
7187
      }
7188
 
7189
    case BFD_RELOC_SCORE_BRANCH:
7190
      if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7191
        value = fixP->fx_offset;
7192
      else
7193
        fixP->fx_done = 1;
7194
 
7195
      content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7196
 
7197
      /* Don't check c-bit.  */
7198
      if (fixP->fx_frag->fr_opcode != 0)
7199
        {
7200
          if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7201
            {
7202
              as_bad_where (fixP->fx_file, fixP->fx_line,
7203
                            _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value);
7204
              return;
7205
            }
7206
          content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7207
          content &= 0xfe00;
7208
          content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7209
          s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7210
          fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
7211
          fixP->fx_size = 2;
7212
        }
7213
      else
7214
        {
7215
          if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7216
            {
7217
              as_bad_where (fixP->fx_file, fixP->fx_line,
7218
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
7219
              return;
7220
            }
7221
          content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7222
          content &= 0xfc00fc01;
7223
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7224
          s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7225
        }
7226
      break;
7227
    case BFD_RELOC_SCORE16_JMP:
7228
      content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7229
      content &= 0xf001;
7230
      value = fixP->fx_offset & 0xfff;
7231
      content = (content & 0xfc01) | (value & 0xffe);
7232
      s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7233
      break;
7234
   case BFD_RELOC_SCORE16_BRANCH:
7235
      content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7236
      /* Don't check c-bit.  */
7237
      if (fixP->fx_frag->fr_opcode != 0)
7238
        {
7239
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7240
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7241
            value = fixP->fx_offset;
7242
          else
7243
            fixP->fx_done = 1;
7244
          if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7245
            {
7246
              as_bad_where (fixP->fx_file, fixP->fx_line,
7247
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
7248
              return;
7249
            }
7250
          content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7251
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7252
          s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7253
          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7254
          fixP->fx_size = 4;
7255
          break;
7256
        }
7257
      else
7258
        {
7259
          /* In differnt section.  */
7260
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
7261
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7262
            value = fixP->fx_offset;
7263
          else
7264
            fixP->fx_done = 1;
7265
 
7266
          if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7267
            {
7268
              as_bad_where (fixP->fx_file, fixP->fx_line,
7269
                            _(" branch relocation truncate (0x%x)  [-2^9 ~ 2^9]"), (unsigned int)value);
7270
              return;
7271
            }
7272
 
7273
          content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
7274
          content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
7275
          s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
7276
          break;
7277
        }
7278
 
7279
    break;
7280
 
7281
    case BFD_RELOC_SCORE_BCMP:
7282
      if (fixP->fx_frag->fr_opcode != 0)
7283
        {
7284
          char *buf_ptr = buf;
7285
          buf_ptr += 2;
7286
 
7287
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7288
            value = fixP->fx_offset;
7289
          else
7290
            fixP->fx_done = 1;
7291
 
7292
          /* NOTE!!!
7293
             bcmp -> cmp! and branch, so value -= 2.  */
7294
          value -= 2;
7295
 
7296
          if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
7297
            {
7298
              as_bad_where (fixP->fx_file, fixP->fx_line,
7299
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
7300
              return;
7301
            }
7302
 
7303
          content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
7304
          content &= 0xfc00fc01;
7305
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
7306
          s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
7307
          /* change relocation type to BFD_RELOC_SCORE_BRANCH */
7308
          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
7309
          fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
7310
          break;
7311
        }
7312
      else
7313
        {
7314
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
7315
            value = fixP->fx_offset;
7316
          else
7317
            fixP->fx_done = 1;
7318
 
7319
          content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7320
 
7321
          if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
7322
            {
7323
              as_bad_where (fixP->fx_file, fixP->fx_line,
7324
                _(" branch relocation truncate (0x%x)  [-2^9 ~ 2^9]"), (unsigned int)value);
7325
              return;
7326
            }
7327
 
7328
          value >>= 1;
7329
          content &= ~0x03e00381;
7330
          content = content
7331
                    | (value & 0x1)
7332
                    | (((value & 0xe) >> 1) << 7)
7333
                    | (((value & 0x1f0) >> 4) << 21);
7334
 
7335
          s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
7336
          break;
7337
        }
7338
 
7339
    case BFD_RELOC_8:
7340
      if (fixP->fx_done || fixP->fx_pcrel)
7341
        s3_md_number_to_chars (buf, value, 1);
7342
#ifdef OBJ_ELF
7343
      else
7344
        {
7345
          value = fixP->fx_offset;
7346
          s3_md_number_to_chars (buf, value, 1);
7347
        }
7348
#endif
7349
      break;
7350
 
7351
    case BFD_RELOC_16:
7352
      if (fixP->fx_done || fixP->fx_pcrel)
7353
        s3_md_number_to_chars (buf, value, 2);
7354
#ifdef OBJ_ELF
7355
      else
7356
        {
7357
          value = fixP->fx_offset;
7358
          s3_md_number_to_chars (buf, value, 2);
7359
        }
7360
#endif
7361
      break;
7362
    case BFD_RELOC_RVA:
7363
    case BFD_RELOC_32:
7364
      if (fixP->fx_done || fixP->fx_pcrel)
7365
        md_number_to_chars (buf, value, 4);
7366
#ifdef OBJ_ELF
7367
      else
7368
        {
7369
          value = fixP->fx_offset;
7370
          md_number_to_chars (buf, value, 4);
7371
        }
7372
#endif
7373
      break;
7374
    case BFD_RELOC_VTABLE_INHERIT:
7375
      fixP->fx_done = 0;
7376
      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
7377
        S_SET_WEAK (fixP->fx_addsy);
7378
      break;
7379
    case BFD_RELOC_VTABLE_ENTRY:
7380
      fixP->fx_done = 0;
7381
      break;
7382
    case BFD_RELOC_SCORE_GPREL15:
7383
      content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7384
      /* c-bit.  */
7385
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
7386
        fixP->fx_r_type = BFD_RELOC_NONE;
7387
      fixP->fx_done = 0;
7388
      break;
7389
    case BFD_RELOC_SCORE_GOT15:
7390
    case BFD_RELOC_SCORE_DUMMY_HI16:
7391
    case BFD_RELOC_SCORE_GOT_LO16:
7392
    case BFD_RELOC_SCORE_CALL15:
7393
    case BFD_RELOC_GPREL32:
7394
      break;
7395
    case BFD_RELOC_NONE:
7396
    default:
7397
      as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
7398
    }
7399
}
7400
 
7401
static arelent **
7402
s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7403
{
7404
  static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
7405
  arelent *reloc;
7406
  bfd_reloc_code_real_type code;
7407
  char *type;
7408
  fragS *f;
7409
  symbolS *s;
7410
  expressionS e;
7411
 
7412
  reloc = retval[0] = xmalloc (sizeof (arelent));
7413
  retval[1] = NULL;
7414
 
7415
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
7416
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7417
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7418
  reloc->addend = fixp->fx_offset;
7419
 
7420
  /* If this is a variant frag, we may need to adjust the existing
7421
     reloc and generate a new one.  */
7422
  if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
7423
    {
7424
      /* Update instruction imm bit.  */
7425
      offsetT newval;
7426
      unsigned short off;
7427
      char *buf;
7428
 
7429
      buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
7430
      newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7431
      off = fixp->fx_offset >> 16;
7432
      newval |= (off & 0x3fff) << 1;
7433
      newval |= ((off >> 14) & 0x3) << 16;
7434
      s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7435
 
7436
      buf += s3_INSN_SIZE;
7437
      newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
7438
      off = fixp->fx_offset & 0xffff;
7439
      newval |= ((off & 0x3fff) << 1);
7440
      newval |= (((off >> 14) & 0x3) << 16);
7441
      s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
7442
 
7443
      retval[1] = xmalloc (sizeof (arelent));
7444
      retval[2] = NULL;
7445
      retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
7446
      *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7447
      retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
7448
 
7449
      f = fixp->fx_frag;
7450
      s = f->fr_symbol;
7451
      e = s->sy_value;
7452
 
7453
      retval[1]->addend = 0;
7454
      retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
7455
      gas_assert (retval[1]->howto != NULL);
7456
 
7457
      fixp->fx_r_type = BFD_RELOC_HI16_S;
7458
    }
7459
 
7460
  code = fixp->fx_r_type;
7461
  switch (fixp->fx_r_type)
7462
    {
7463
    case BFD_RELOC_32:
7464
      if (fixp->fx_pcrel)
7465
        {
7466
          code = BFD_RELOC_32_PCREL;
7467
          break;
7468
        }
7469
    case BFD_RELOC_HI16_S:
7470
    case BFD_RELOC_LO16:
7471
    case BFD_RELOC_SCORE_JMP:
7472
    case BFD_RELOC_SCORE_BRANCH:
7473
    case BFD_RELOC_SCORE16_JMP:
7474
    case BFD_RELOC_SCORE16_BRANCH:
7475
    case BFD_RELOC_SCORE_BCMP:
7476
    case BFD_RELOC_VTABLE_ENTRY:
7477
    case BFD_RELOC_VTABLE_INHERIT:
7478
    case BFD_RELOC_SCORE_GPREL15:
7479
    case BFD_RELOC_SCORE_GOT15:
7480
    case BFD_RELOC_SCORE_DUMMY_HI16:
7481
    case BFD_RELOC_SCORE_GOT_LO16:
7482
    case BFD_RELOC_SCORE_CALL15:
7483
    case BFD_RELOC_GPREL32:
7484
    case BFD_RELOC_NONE:
7485
    case BFD_RELOC_SCORE_IMM30:
7486
    case BFD_RELOC_SCORE_IMM32:
7487
      code = fixp->fx_r_type;
7488
      break;
7489
    default:
7490
      type = _("<unknown>");
7491
      as_bad_where (fixp->fx_file, fixp->fx_line,
7492
                    _("cannot represent %s relocation in this object file format"), type);
7493
      return NULL;
7494
    }
7495
 
7496
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7497
  if (reloc->howto == NULL)
7498
    {
7499
      as_bad_where (fixp->fx_file, fixp->fx_line,
7500
                    _("cannot represent %s relocation in this object file format1"),
7501
                    bfd_get_reloc_code_name (code));
7502
      return NULL;
7503
    }
7504
  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
7505
     vtable entry to be used in the relocation's section offset.  */
7506
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
7507
    reloc->address = fixp->fx_offset;
7508
 
7509
  return retval;
7510
}
7511
 
7512
void
7513
md_assemble (char *str)
7514
{
7515
  if (score3)
7516
    s3_assemble (str);
7517
  else
7518
    s7_assemble (str);
7519
}
7520
 
7521
/* We handle all bad expressions here, so that we can report the faulty
7522
   instruction in the error message.  */
7523
void
7524
md_operand (expressionS * exp)
7525
{
7526
  if (score3)
7527
    s3_operand (exp);
7528
  else
7529
    s7_operand (exp);
7530
}
7531
 
7532
/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
7533
   for use in the a.out file, and stores them in the array pointed to by buf.
7534
   This knows about the endian-ness of the target machine and does
7535
   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
7536
   2 (short) and 4 (long)  Floating numbers are put out as a series of
7537
   LITTLENUMS (shorts, here at least).  */
7538
void
7539
md_number_to_chars (char *buf, valueT val, int n)
7540
{
7541
  if (score3)
7542
    s3_number_to_chars (buf, val, n);
7543
  else
7544
    s7_number_to_chars (buf, val, n);
7545
}
7546
 
7547
/* Turn a string in input_line_pointer into a floating point constant
7548
   of type TYPE, and store the appropriate bytes in *LITP.  The number
7549
   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
7550
   returned, or NULL on OK.
7551
 
7552
   Note that fp constants aren't represent in the normal way on the ARM.
7553
   In big endian mode, things are as expected.  However, in little endian
7554
   mode fp constants are big-endian word-wise, and little-endian byte-wise
7555
   within the words.  For example, (double) 1.1 in big endian mode is
7556
   the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
7557
   the byte sequence 99 99 f1 3f 9a 99 99 99.  */
7558
char *
7559
md_atof (int type, char *litP, int *sizeP)
7560
{
7561
  if (score3)
7562
    return s3_atof (type, litP, sizeP);
7563
  else
7564
    return s7_atof (type, litP, sizeP);
7565
}
7566
 
7567
void
7568
score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
7569
{
7570
  if (score3)
7571
    s3_frag_check (fragp);
7572
  else
7573
    s7_frag_check (fragp);
7574
}
7575
 
7576
/* Implementation of TC_VALIDATE_FIX.
7577
   Called before md_apply_fix() and after md_convert_frag().  */
7578
void
7579
score_validate_fix (fixS *fixP)
7580
{
7581
  if (score3)
7582
    s3_validate_fix (fixP);
7583
  else
7584
    s7_validate_fix (fixP);
7585
}
7586
 
7587
int
7588
score_force_relocation (struct fix *fixp)
7589
{
7590
  if (score3)
7591
    return s3_force_relocation (fixp);
7592
  else
7593
    return s7_force_relocation (fixp);
7594
}
7595
 
7596
/* Implementation of md_frag_check.
7597
   Called after md_convert_frag().  */
7598
bfd_boolean
7599
score_fix_adjustable (fixS * fixP)
7600
{
7601
  if (score3)
7602
    return s3_fix_adjustable (fixP);
7603
  else
7604
    return s7_fix_adjustable (fixP);
7605
}
7606
 
7607
void
7608
score_elf_final_processing (void)
7609
{
7610
  if (score3)
7611
    s3_elf_final_processing ();
7612
  else
7613
    s7_elf_final_processing ();
7614
}
7615
 
7616
/* In this function, we determine whether s3_GP instruction should do relaxation,
7617
   for the label being against was known now.
7618
   Doing this here but not in md_relax_frag() can induce iteration times
7619
   in stage of doing relax.  */
7620
int
7621
md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
7622
{
7623
  if (score3)
7624
    return s3_estimate_size_before_relax (fragp, sec);
7625
  else
7626
    return s7_estimate_size_before_relax (fragp, sec);
7627
}
7628
 
7629
int
7630
score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
7631
{
7632
  if (score3)
7633
    return s3_relax_frag (sec, fragp, stretch);
7634
  else
7635
    return s7_relax_frag (sec, fragp, stretch);
7636
}
7637
 
7638
void
7639
md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
7640
{
7641
  if (score3)
7642
    return s3_convert_frag (abfd, sec, fragp);
7643
  else
7644
    return s7_convert_frag (abfd, sec, fragp);
7645
}
7646
 
7647
long
7648
md_pcrel_from (fixS * fixP)
7649
{
7650
  if (score3)
7651
    return s3_pcrel_from (fixP);
7652
  else
7653
    return s7_pcrel_from (fixP);
7654
}
7655
 
7656
/* Round up a section size to the appropriate boundary.  */
7657
valueT
7658
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
7659
{
7660
  if (score3)
7661
    return s3_section_align (segment, size);
7662
  else
7663
    return s7_section_align (segment, size);
7664
}
7665
 
7666
void
7667
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
7668
{
7669
  if (score3)
7670
    return s3_apply_fix (fixP, valP, seg);
7671
  else
7672
    return s7_apply_fix (fixP, valP, seg);
7673
}
7674
 
7675
/* Translate internal representation of relocation info to BFD target format.  */
7676
arelent **
7677
tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
7678
{
7679
  if (score3)
7680
    return s3_gen_reloc (section, fixp);
7681
  else
7682
    return s7_gen_reloc (section, fixp);
7683
}
7684
 
7685
void
7686
md_begin (void)
7687
{
7688
  s3_begin ();
7689
  s7_begin ();
7690
}
7691
 
7692
static void
7693
score_set_mach (const char *arg)
7694
{
7695
  if (strcmp (arg, MARCH_SCORE3) == 0)
7696
    {
7697
      score3 = 1;
7698
      score7 = 0;
7699
      s3_score3d = 1;
7700
    }
7701
  else if (strcmp (arg, MARCH_SCORE7) == 0)
7702
    {
7703
      score3 = 0;
7704
      score7 = 1;
7705
      s7_score7d = 1;
7706
      s7_university_version = 0;
7707
      s7_vector_size = s7_SCORE7_PIPELINE;
7708
    }
7709
  else if (strcmp (arg, MARCH_SCORE5) == 0)
7710
    {
7711
      score3 = 0;
7712
      score7 = 1;
7713
      s7_score7d = 1;
7714
      s7_university_version = 0;
7715
      s7_vector_size = s7_SCORE5_PIPELINE;
7716
    }
7717
  else if (strcmp (arg, MARCH_SCORE5U) == 0)
7718
    {
7719
      score3 = 0;
7720
      score7 = 1;
7721
      s7_score7d = 1;
7722
      s7_university_version = 1;
7723
      s7_vector_size = s7_SCORE5_PIPELINE;
7724
    }
7725
  else
7726
    {
7727
      as_bad (_("unknown architecture `%s'\n"), arg);
7728
    }
7729
}
7730
 
7731
int
7732
md_parse_option (int c, char *arg)
7733
{
7734
  switch (c)
7735
    {
7736
#ifdef OPTION_EB
7737
    case OPTION_EB:
7738
      target_big_endian = 1;
7739
      break;
7740
#endif
7741
#ifdef OPTION_EL
7742
    case OPTION_EL:
7743
      target_big_endian = 0;
7744
      break;
7745
#endif
7746
    case OPTION_FIXDD:
7747
      s3_fix_data_dependency = 1;
7748
      s7_fix_data_dependency = 1;
7749
      break;
7750
    case OPTION_NWARN:
7751
      s3_warn_fix_data_dependency = 0;
7752
      s7_warn_fix_data_dependency = 0;
7753
      break;
7754
    case OPTION_SCORE5:
7755
      score3 = 0;
7756
      score7 = 1;
7757
      s7_university_version = 0;
7758
      s7_vector_size = s7_SCORE5_PIPELINE;
7759
      break;
7760
    case OPTION_SCORE5U:
7761
      score3 = 0;
7762
      score7 = 1;
7763
      s7_university_version = 1;
7764
      s7_vector_size = s7_SCORE5_PIPELINE;
7765
      break;
7766
    case OPTION_SCORE7:
7767
      score3 = 0;
7768
      score7 = 1;
7769
      s7_score7d = 1;
7770
      s7_university_version = 0;
7771
      s7_vector_size = s7_SCORE7_PIPELINE;
7772
      break;
7773
    case OPTION_SCORE3:
7774
      score3 = 1;
7775
      score7 = 0;
7776
      s3_score3d = 1;
7777
      break;
7778
    case OPTION_R1:
7779
      s3_nor1 = 0;
7780
      s7_nor1 = 0;
7781
      break;
7782
    case 'G':
7783
      s3_g_switch_value = atoi (arg);
7784
      s7_g_switch_value = atoi (arg);
7785
      break;
7786
    case OPTION_O0:
7787
      s3_g_opt = 0;
7788
      s7_g_opt = 0;
7789
      break;
7790
    case OPTION_SCORE_VERSION:
7791
      printf (_("Sunplus-v2-0-0-20060510\n"));
7792
      break;
7793
    case OPTION_PIC:
7794
      s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now.  */
7795
      s7_score_pic = s7_PIC;
7796
      s3_g_switch_value = 0;    /* Must set -G num as 0 to generate s3_PIC code.  */
7797
      s7_g_switch_value = 0;    /* Must set -G num as 0 to generate s7_PIC code.  */
7798
      break;
7799
    case OPTION_MARCH:
7800
      score_set_mach (arg);
7801
      break;
7802
    default:
7803
      return 0;
7804
    }
7805
  return 1;
7806
}
7807
 
7808
void
7809
md_show_usage (FILE * fp)
7810
{
7811
  fprintf (fp, _(" Score-specific assembler options:\n"));
7812
#ifdef OPTION_EB
7813
  fprintf (fp, _("\
7814
        -EB\t\tassemble code for a big-endian cpu\n"));
7815
#endif
7816
 
7817
#ifdef OPTION_EL
7818
  fprintf (fp, _("\
7819
        -EL\t\tassemble code for a little-endian cpu\n"));
7820
#endif
7821
 
7822
  fprintf (fp, _("\
7823
        -FIXDD\t\tassemble code for fix data dependency\n"));
7824
  fprintf (fp, _("\
7825
        -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
7826
  fprintf (fp, _("\
7827
        -SCORE5\t\tassemble code for target is SCORE5\n"));
7828
  fprintf (fp, _("\
7829
        -SCORE5U\tassemble code for target is SCORE5U\n"));
7830
  fprintf (fp, _("\
7831
        -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
7832
  fprintf (fp, _("\
7833
        -SCORE3\t\tassemble code for target is SCORE3\n"));
7834
  fprintf (fp, _("\
7835
        -march=score7\tassemble code for target is SCORE7, this is default setting\n"));
7836
  fprintf (fp, _("\
7837
        -march=score3\tassemble code for target is SCORE3\n"));
7838
  fprintf (fp, _("\
7839
        -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
7840
  fprintf (fp, _("\
7841
        -KPIC\t\tassemble code for PIC\n"));
7842
  fprintf (fp, _("\
7843
        -O0\t\tassembler will not perform any optimizations\n"));
7844
  fprintf (fp, _("\
7845
        -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
7846
  fprintf (fp, _("\
7847
        -V \t\tSunplus release version \n"));
7848
}

powered by: WebSVN 2.1.0

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