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

Subversion Repositories open8_urisc

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

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

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

powered by: WebSVN 2.1.0

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