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 158

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

powered by: WebSVN 2.1.0

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