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 146

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
   Copyright 2009 Free Software Foundation, Inc.
3
   Contributed by:
4
   Brain.lin (brain.lin@sunplusct.com)
5
   Mei Ligang (ligang@sunnorth.com.cn)
6
   Pei-Lin Tsai (pltsai@sunplus.com)
7
 
8
   This file is part of GAS, the GNU Assembler.
9
 
10
   GAS is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3, or (at your option)
13
   any later version.
14
 
15
   GAS is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with GAS; see the file COPYING.  If not, write to the Free
22
   Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
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
  segT seg;
1264
 
1265
  save_in = input_line_pointer;
1266
  input_line_pointer = *str;
1267
  s7_in_my_get_expression = 1;
1268
  seg = expression (ep);
1269
  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 *strbak;
3100
  char *dataptr;
3101
  int reg;
3102
  int ldst_idx = 0;
3103
 
3104
  int hex_p = 0;
3105
 
3106
  strbak = str;
3107
  s7_skip_whitespace (str);
3108
 
3109
  if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3110
      || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3111
    return;
3112
 
3113
  /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
3114
  if (*str == '[')
3115
    {
3116
      str++;
3117
      s7_skip_whitespace (str);
3118
 
3119
      if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3120
        return;
3121
 
3122
      /* Conflicts can occur on stores as well as loads.  */
3123
      conflict_reg = (conflict_reg == reg);
3124
      s7_skip_whitespace (str);
3125
      temp = str + 1;    /* The latter will process decimal/hex expression.  */
3126
 
3127
      /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
3128
      if (*str == ']')
3129
        {
3130
          str++;
3131
          if (*str == '+')
3132
            {
3133
              str++;
3134
              /* ld/sw rD, [rA]+, simm12.  */
3135
              if (s7_skip_past_comma (&str) == s7_SUCCESS)
3136
                {
3137
                  if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
3138
                      || (s7_end_of_line (str) == (int) s7_FAIL))
3139
                    return;
3140
 
3141
                  if (conflict_reg)
3142
                    {
3143
                      unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3144
 
3145
                      if ((ldst_func == INSN_LH)
3146
                          || (ldst_func == INSN_LHU)
3147
                          || (ldst_func == INSN_LW)
3148
                          || (ldst_func == INSN_LB)
3149
                          || (ldst_func == INSN_LBU))
3150
                        {
3151
                          s7_inst.error = _("register same as write-back base");
3152
                          return;
3153
                        }
3154
                    }
3155
 
3156
                  ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3157
                  s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3158
                  s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
3159
 
3160
                  /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
3161
                  if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
3162
                    {
3163
                      /* rs =  r0-r7, offset = 4 */
3164
                      if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3165
                          && (((s7_inst.instruction >> 3) & 0xfff) == 4))
3166
                        {
3167
                          /* Relax to pophi.  */
3168
                          if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3169
                            {
3170
                              s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3171
                                                              << 8) | 1 << 7 |
3172
                                (((s7_inst.instruction >> 15) & 0x7) << 4);
3173
                            }
3174
                          /* Relax to pop.  */
3175
                          else
3176
                            {
3177
                              s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
3178
                                                              << 8) | 0 << 7 |
3179
                                (((s7_inst.instruction >> 15) & 0x7) << 4);
3180
                            }
3181
                          s7_inst.relax_size = 2;
3182
                        }
3183
                    }
3184
                  return;
3185
                }
3186
              /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
3187
              else
3188
                {
3189
                  s7_SET_INSN_ERROR (NULL);
3190
                  if (s7_end_of_line (str) == (int) s7_FAIL)
3191
                    {
3192
                      return;
3193
                    }
3194
 
3195
                  pre_inc = 1;
3196
                  value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
3197
                  value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
3198
                  ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3199
                  s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3200
                  s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3201
                  s7_inst.instruction |= value << 3;
3202
                  s7_inst.relax_inst = 0x8000;
3203
                  return;
3204
                }
3205
            }
3206
          /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
3207
          else
3208
            {
3209
              if (s7_end_of_line (str) == (int) s7_FAIL)
3210
                return;
3211
 
3212
              ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3213
              s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3214
              s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
3215
 
3216
              /* lbu rd, [rs] -> lbu! rd, [rs]  */
3217
              if (ldst_idx == INSN_LBU)
3218
                {
3219
                  s7_inst.relax_inst = INSN16_LBU;
3220
                }
3221
              else if (ldst_idx == INSN_LH)
3222
                {
3223
                  s7_inst.relax_inst = INSN16_LH;
3224
                }
3225
              else if (ldst_idx == INSN_LW)
3226
                {
3227
                  s7_inst.relax_inst = INSN16_LW;
3228
                }
3229
              else if (ldst_idx == INSN_SB)
3230
                {
3231
                  s7_inst.relax_inst = INSN16_SB;
3232
                }
3233
              else if (ldst_idx == INSN_SH)
3234
                {
3235
                  s7_inst.relax_inst = INSN16_SH;
3236
                }
3237
              else if (ldst_idx == INSN_SW)
3238
                {
3239
                  s7_inst.relax_inst = INSN16_SW;
3240
                }
3241
              else
3242
                {
3243
                  s7_inst.relax_inst = 0x8000;
3244
                }
3245
 
3246
              /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
3247
              if ((ldst_idx == INSN_LBU)
3248
                  || (ldst_idx == INSN_LH)
3249
                  || (ldst_idx == INSN_LW)
3250
                  || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
3251
                {
3252
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3253
                    {
3254
                      s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
3255
                        (((s7_inst.instruction >> 15) & 0xf) << 4);
3256
                      s7_inst.relax_size = 2;
3257
                    }
3258
                }
3259
 
3260
              return;
3261
            }
3262
        }
3263
      /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
3264
      else
3265
        {
3266
          if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3267
            {
3268
              s7_inst.error = _("pre-indexed expression expected");
3269
              return;
3270
            }
3271
 
3272
          if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
3273
            return;
3274
 
3275
          s7_skip_whitespace (str);
3276
          if (*str++ != ']')
3277
            {
3278
              s7_inst.error = _("missing ]");
3279
              return;
3280
            }
3281
 
3282
          s7_skip_whitespace (str);
3283
          /* ld/sw rD, [rA, simm12]+.  */
3284
          if (*str == '+')
3285
            {
3286
              str++;
3287
              pre_inc = 1;
3288
              if (conflict_reg)
3289
                {
3290
                  unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3291
 
3292
                  if ((ldst_func == INSN_LH)
3293
                      || (ldst_func == INSN_LHU)
3294
                      || (ldst_func == INSN_LW)
3295
                      || (ldst_func == INSN_LB)
3296
                      || (ldst_func == INSN_LBU))
3297
                    {
3298
                      s7_inst.error = _("register same as write-back base");
3299
                      return;
3300
                    }
3301
                }
3302
            }
3303
 
3304
          if (s7_end_of_line (str) == (int) s7_FAIL)
3305
            return;
3306
 
3307
          if (s7_inst.reloc.exp.X_op == O_constant)
3308
            {
3309
              unsigned int data_type;
3310
 
3311
              if (pre_inc == 1)
3312
                data_type = _SIMM12;
3313
              else
3314
                data_type = _SIMM15;
3315
              dataptr = temp;
3316
 
3317
            if ((dataptr != NULL)
3318
              && (((strstr (dataptr, "0x")) != NULL)
3319
                  || ((strstr (dataptr, "0X")) != NULL)))
3320
              {
3321
                hex_p = 1;
3322
                if ((data_type != _SIMM16_LA)
3323
                    && (data_type != _VALUE_HI16)
3324
                    && (data_type != _VALUE_LO16)
3325
                    && (data_type != _IMM16)
3326
                    && (data_type != _IMM15)
3327
                    && (data_type != _IMM14)
3328
                    && (data_type != _IMM4)
3329
                    && (data_type != _IMM5)
3330
                    && (data_type != _IMM8)
3331
                    && (data_type != _SIMM12)
3332
                    && (data_type != _SIMM15)
3333
                    && (data_type != _IMM5_RSHIFT_1)
3334
                    && (data_type != _IMM5_RSHIFT_2)
3335
                    && (data_type != _SIMM14_NEG)
3336
                    && (data_type != _IMM10_RSHIFT_2))
3337
                  {
3338
                    data_type += 24;
3339
                  }
3340
              }
3341
 
3342
              value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3343
              if (value == (int) s7_FAIL)
3344
                {
3345
                  if (data_type < 30)
3346
                    sprintf (s7_err_msg,
3347
                             _("invalid constant: %d bit expression not in range %d..%d"),
3348
                             s7_score_df_range[data_type].bits,
3349
                             s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3350
                  else
3351
                    sprintf (s7_err_msg,
3352
                             _("invalid constant: %d bit expression not in range %d..%d"),
3353
                             s7_score_df_range[data_type - 24].bits,
3354
                             s7_score_df_range[data_type - 24].range[0],
3355
                             s7_score_df_range[data_type - 24].range[1]);
3356
                  s7_inst.error = s7_err_msg;
3357
                  return;
3358
                }
3359
 
3360
              value &= (1 << s7_score_df_range[data_type].bits) - 1;
3361
              ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3362
              s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3363
              s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3364
              if (pre_inc == 1)
3365
                s7_inst.instruction |= value << 3;
3366
              else
3367
                s7_inst.instruction |= value;
3368
 
3369
              /* lw rD, [rA, simm15]  */
3370
              if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3371
                {
3372
                  /* Both rD and rA are in [r0 - r15].  */
3373
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3374
                      && (((s7_inst.instruction >> 20) & 0x10) == 0))
3375
                    {
3376
                      /* simm15 = 0, lw -> lw!.  */
3377
                      if ((s7_inst.instruction & 0x7fff) == 0)
3378
                        {
3379
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3380
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3381
                          s7_inst.relax_size = 2;
3382
                        }
3383
                      /* rA = r2, lw -> lwp!.  */
3384
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3385
                               && ((s7_inst.instruction & 0x3) == 0)
3386
                               && ((s7_inst.instruction & 0x7fff) < 128))
3387
                        {
3388
                          s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3389
                            | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3390
                          s7_inst.relax_size = 2;
3391
                        }
3392
                      else
3393
                        {
3394
                          s7_inst.relax_inst = 0x8000;
3395
                        }
3396
                    }
3397
                  else
3398
                    {
3399
                      s7_inst.relax_inst = 0x8000;
3400
                    }
3401
                }
3402
              /* sw rD, [rA, simm15]  */
3403
              else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3404
                {
3405
                  /* Both rD and rA are in [r0 - r15].  */
3406
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3407
                    {
3408
                      /* simm15 = 0, sw -> sw!.  */
3409
                      if ((s7_inst.instruction & 0x7fff) == 0)
3410
                        {
3411
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3412
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3413
                          s7_inst.relax_size = 2;
3414
                        }
3415
                      /* rA = r2, sw -> swp!.  */
3416
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3417
                               && ((s7_inst.instruction & 0x3) == 0)
3418
                               && ((s7_inst.instruction & 0x7fff) < 128))
3419
                        {
3420
                          s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3421
                            | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3422
                          s7_inst.relax_size = 2;
3423
                        }
3424
                      else
3425
                        {
3426
                          s7_inst.relax_inst = 0x8000;
3427
                        }
3428
                    }
3429
                  else
3430
                    {
3431
                      s7_inst.relax_inst = 0x8000;
3432
                    }
3433
                }
3434
              /* sw rD, [rA, simm15]+    sw pre.  */
3435
              else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3436
                {
3437
                  /* rA is in [r0 - r7], and simm15 = -4.  */
3438
                  if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3439
                      && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3440
                    {
3441
                      /* sw -> pushhi!.  */
3442
                      if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3443
                        {
3444
                          s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3445
                            | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3446
                          s7_inst.relax_size = 2;
3447
                        }
3448
                      /* sw -> push!.  */
3449
                      else
3450
                        {
3451
                          s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3452
                            | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3453
                          s7_inst.relax_size = 2;
3454
                        }
3455
                    }
3456
                  else
3457
                    {
3458
                      s7_inst.relax_inst = 0x8000;
3459
                    }
3460
                }
3461
              /* lh rD, [rA, simm15]  */
3462
              else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3463
                {
3464
                  /* Both rD and rA are in [r0 - r15].  */
3465
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3466
                    {
3467
                      /* simm15 = 0, lh -> lh!.  */
3468
                      if ((s7_inst.instruction & 0x7fff) == 0)
3469
                        {
3470
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3471
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3472
                          s7_inst.relax_size = 2;
3473
                        }
3474
                      /* rA = r2, lh -> lhp!.  */
3475
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3476
                               && ((s7_inst.instruction & 0x1) == 0)
3477
                               && ((s7_inst.instruction & 0x7fff) < 64))
3478
                        {
3479
                          s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3480
                            | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3481
                          s7_inst.relax_size = 2;
3482
                        }
3483
                      else
3484
                        {
3485
                          s7_inst.relax_inst = 0x8000;
3486
                        }
3487
                    }
3488
                  else
3489
                    {
3490
                      s7_inst.relax_inst = 0x8000;
3491
                    }
3492
                }
3493
              /* sh rD, [rA, simm15]  */
3494
              else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3495
                {
3496
                  /* Both rD and rA are in [r0 - r15].  */
3497
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3498
                    {
3499
                      /* simm15 = 0, sh -> sh!.  */
3500
                      if ((s7_inst.instruction & 0x7fff) == 0)
3501
                        {
3502
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3503
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3504
                          s7_inst.relax_size = 2;
3505
                        }
3506
                      /* rA = r2, sh -> shp!.  */
3507
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3508
                               && ((s7_inst.instruction & 0x1) == 0)
3509
                               && ((s7_inst.instruction & 0x7fff) < 64))
3510
                        {
3511
                          s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3512
                            | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3513
                          s7_inst.relax_size = 2;
3514
                        }
3515
                      else
3516
                        {
3517
                          s7_inst.relax_inst = 0x8000;
3518
                        }
3519
                    }
3520
                  else
3521
                    {
3522
                      s7_inst.relax_inst = 0x8000;
3523
                    }
3524
                }
3525
              /* lbu rD, [rA, simm15]  */
3526
              else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3527
                {
3528
                  /* Both rD and rA are in [r0 - r15].  */
3529
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3530
                    {
3531
                      /* simm15 = 0, lbu -> lbu!.  */
3532
                      if ((s7_inst.instruction & 0x7fff) == 0)
3533
                        {
3534
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3535
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3536
                          s7_inst.relax_size = 2;
3537
                        }
3538
                      /* rA = r2, lbu -> lbup!.  */
3539
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3540
                               && ((s7_inst.instruction & 0x7fff) < 32))
3541
                        {
3542
                          s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3543
                            | ((s7_inst.instruction & 0x7fff) << 3);
3544
                          s7_inst.relax_size = 2;
3545
                        }
3546
                      else
3547
                        {
3548
                          s7_inst.relax_inst = 0x8000;
3549
                        }
3550
                    }
3551
                  else
3552
                    {
3553
                      s7_inst.relax_inst = 0x8000;
3554
                    }
3555
                }
3556
              /* sb rD, [rA, simm15]  */
3557
              else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3558
                {
3559
                  /* Both rD and rA are in [r0 - r15].  */
3560
                  if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3561
                    {
3562
                      /* simm15 = 0, sb -> sb!.  */
3563
                      if ((s7_inst.instruction & 0x7fff) == 0)
3564
                        {
3565
                          s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3566
                            | (((s7_inst.instruction >> 20) & 0xf) << 8);
3567
                          s7_inst.relax_size = 2;
3568
                        }
3569
                      /* rA = r2, sb -> sb!.  */
3570
                      else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3571
                               && ((s7_inst.instruction & 0x7fff) < 32))
3572
                        {
3573
                          s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3574
                            | ((s7_inst.instruction & 0x7fff) << 3);
3575
                          s7_inst.relax_size = 2;
3576
                        }
3577
                      else
3578
                        {
3579
                          s7_inst.relax_inst = 0x8000;
3580
                        }
3581
                    }
3582
                  else
3583
                    {
3584
                      s7_inst.relax_inst = 0x8000;
3585
                    }
3586
                }
3587
              else
3588
                {
3589
                  s7_inst.relax_inst = 0x8000;
3590
                }
3591
 
3592
              return;
3593
            }
3594
          else
3595
            {
3596
              /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3597
              s7_inst.reloc.pc_rel = 0;
3598
            }
3599
        }
3600
    }
3601
  else
3602
    {
3603
      s7_inst.error = s7_BAD_ARGS;
3604
    }
3605
}
3606
 
3607
/* Handle cache.  */
3608
static void
3609
s7_do_cache (char *str)
3610
{
3611
  s7_skip_whitespace (str);
3612
 
3613
  if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3614
    {
3615
      return;
3616
    }
3617
  else
3618
    {
3619
      int cache_op;
3620
 
3621
      cache_op = (s7_inst.instruction >> 20) & 0x1F;
3622
      sprintf (s7_inst.name, "cache %d", cache_op);
3623
    }
3624
 
3625
  if (*str == '[')
3626
    {
3627
      str++;
3628
      s7_skip_whitespace (str);
3629
 
3630
      if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3631
        return;
3632
 
3633
      s7_skip_whitespace (str);
3634
 
3635
      /* cache op, [rA]  */
3636
      if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3637
        {
3638
          s7_SET_INSN_ERROR (NULL);
3639
          if (*str != ']')
3640
            {
3641
              s7_inst.error = _("missing ]");
3642
              return;
3643
            }
3644
          str++;
3645
        }
3646
      /* cache op, [rA, simm15]  */
3647
      else
3648
        {
3649
          if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3650
            {
3651
              return;
3652
            }
3653
 
3654
          s7_skip_whitespace (str);
3655
          if (*str++ != ']')
3656
            {
3657
              s7_inst.error = _("missing ]");
3658
              return;
3659
            }
3660
        }
3661
 
3662
      if (s7_end_of_line (str) == (int) s7_FAIL)
3663
        return;
3664
    }
3665
  else
3666
    {
3667
      s7_inst.error = s7_BAD_ARGS;
3668
    }
3669
}
3670
 
3671
static void
3672
s7_do_crdcrscrsimm5 (char *str)
3673
{
3674
  char *strbak;
3675
 
3676
  strbak = str;
3677
  s7_skip_whitespace (str);
3678
 
3679
  if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3680
      || s7_skip_past_comma (&str) == (int) s7_FAIL
3681
      || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3682
      || s7_skip_past_comma (&str) == (int) s7_FAIL
3683
      || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3684
      || s7_skip_past_comma (&str) == (int) s7_FAIL)
3685
    {
3686
      str = strbak;
3687
      /* cop1 cop_code20.  */
3688
      if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3689
        return;
3690
    }
3691
  else
3692
    {
3693
      if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3694
        return;
3695
    }
3696
 
3697
  s7_end_of_line (str);
3698
}
3699
 
3700
/* Handle ldc/stc.  */
3701
static void
3702
s7_do_ldst_cop (char *str)
3703
{
3704
  s7_skip_whitespace (str);
3705
 
3706
  if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3707
      || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3708
    return;
3709
 
3710
  if (*str == '[')
3711
    {
3712
      str++;
3713
      s7_skip_whitespace (str);
3714
 
3715
      if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3716
        return;
3717
 
3718
      s7_skip_whitespace (str);
3719
 
3720
      if (*str++ != ']')
3721
        {
3722
          if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3723
            return;
3724
 
3725
          s7_skip_whitespace (str);
3726
          if (*str++ != ']')
3727
            {
3728
              s7_inst.error = _("missing ]");
3729
              return;
3730
            }
3731
        }
3732
 
3733
      s7_end_of_line (str);
3734
    }
3735
  else
3736
    s7_inst.error = s7_BAD_ARGS;
3737
}
3738
 
3739
static void
3740
s7_do16_ldst_insn (char *str)
3741
{
3742
  s7_skip_whitespace (str);
3743
 
3744
  if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3745
    return;
3746
 
3747
  if (*str == '[')
3748
    {
3749
      int reg;
3750
 
3751
      str++;
3752
      s7_skip_whitespace (str);
3753
 
3754
      if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3755
        return;
3756
 
3757
      s7_skip_whitespace (str);
3758
      if (*str++ == ']')
3759
        {
3760
          if (s7_end_of_line (str) == (int) s7_FAIL)
3761
            return;
3762
          else
3763
            {
3764
              s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3765
                              | (((s7_inst.instruction >> 4) & 0xf) << 15);
3766
              s7_inst.relax_size = 4;
3767
            }
3768
        }
3769
      else
3770
        {
3771
          s7_inst.error = _("missing ]");
3772
        }
3773
    }
3774
  else
3775
    {
3776
      s7_inst.error = s7_BAD_ARGS;
3777
    }
3778
}
3779
 
3780
/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
3781
 
3782
static void
3783
s7_do16_ldst_imm_insn (char *str)
3784
{
3785
  char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3786
  int reg_rd;
3787
  char *dataptr = NULL, *pp = NULL;
3788
  int cnt = 0;
3789
  int assign_data = (int) s7_FAIL;
3790
  unsigned int ldst_func;
3791
 
3792
  s7_skip_whitespace (str);
3793
 
3794
  if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3795
      || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3796
    return;
3797
 
3798
  s7_skip_whitespace (str);
3799
  dataptr = str;
3800
 
3801
  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3802
    {
3803
      data_exp[cnt] = *dataptr;
3804
      dataptr++;
3805
      cnt++;
3806
    }
3807
 
3808
  data_exp[cnt] = '\0';
3809
  pp = &data_exp[0];
3810
 
3811
  str = dataptr;
3812
 
3813
  ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3814
  if (ldst_func == N16_LIU)
3815
    assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3816
  else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3817
    assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3818
  else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3819
    assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3820
  else
3821
    assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3822
 
3823
  if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3824
    return;
3825
  else
3826
    {
3827
      if ((s7_inst.instruction & 0x7000) == N16_LIU)
3828
        {
3829
          s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3830
                          | ((s7_inst.instruction & 0xff) << 1);
3831
        }
3832
      else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3833
               || ((s7_inst.instruction & 0x7007) == N16_SHP))
3834
        {
3835
          s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3836
                          | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3837
        }
3838
      else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3839
               || ((s7_inst.instruction & 0x7007) == N16_SWP))
3840
        {
3841
          s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3842
                          | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3843
        }
3844
      else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3845
               || ((s7_inst.instruction & 0x7007) == N16_SBP))
3846
        {
3847
          s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3848
                          | (((s7_inst.instruction >> 3) & 0x1f));
3849
        }
3850
 
3851
      s7_inst.relax_size = 4;
3852
    }
3853
}
3854
 
3855
static void
3856
s7_do16_push_pop (char *str)
3857
{
3858
  int reg_rd;
3859
  int H_bit_mask = 0;
3860
 
3861
  s7_skip_whitespace (str);
3862
  if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3863
      || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3864
    return;
3865
 
3866
  if (reg_rd >= 16)
3867
    H_bit_mask = 1;
3868
 
3869
  /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
3870
  s7_inst.instruction &= ~(1 << 12);
3871
 
3872
  s7_inst.instruction |= H_bit_mask << 7;
3873
 
3874
  if (*str == '[')
3875
    {
3876
      int reg;
3877
 
3878
      str++;
3879
      s7_skip_whitespace (str);
3880
      if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3881
        return;
3882
      else if (reg > 7)
3883
        {
3884
          if (!s7_inst.error)
3885
            s7_inst.error = _("base register nums are over 3 bit");
3886
 
3887
          return;
3888
        }
3889
 
3890
      s7_skip_whitespace (str);
3891
      if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3892
        {
3893
          if (!s7_inst.error)
3894
            s7_inst.error = _("missing ]");
3895
 
3896
          return;
3897
        }
3898
 
3899
      /* pop! */
3900
      if ((s7_inst.instruction & 0xf) == 0xa)
3901
        {
3902
          if (H_bit_mask)
3903
            {
3904
              s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3905
                                  | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3906
            }
3907
          else
3908
            {
3909
              s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3910
                                  | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3911
            }
3912
        }
3913
      /* push! */
3914
      else
3915
        {
3916
          if (H_bit_mask)
3917
            {
3918
              s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3919
                                  | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3920
            }
3921
          else
3922
            {
3923
              s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3924
                                  | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3925
            }
3926
        }
3927
      s7_inst.relax_size = 4;
3928
    }
3929
  else
3930
    {
3931
      s7_inst.error = s7_BAD_ARGS;
3932
    }
3933
}
3934
 
3935
/* Handle lcb/lcw/lce/scb/scw/sce.  */
3936
static void
3937
s7_do_ldst_unalign (char *str)
3938
{
3939
  int conflict_reg;
3940
 
3941
  if (s7_university_version == 1)
3942
    {
3943
      s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3944
      return;
3945
    }
3946
 
3947
  s7_skip_whitespace (str);
3948
 
3949
  /* lcb/scb [rA]+.  */
3950
  if (*str == '[')
3951
    {
3952
      str++;
3953
      s7_skip_whitespace (str);
3954
 
3955
      if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3956
        return;
3957
 
3958
      if (*str++ == ']')
3959
        {
3960
          if (*str++ != '+')
3961
            {
3962
              s7_inst.error = _("missing +");
3963
              return;
3964
            }
3965
        }
3966
      else
3967
        {
3968
          s7_inst.error = _("missing ]");
3969
          return;
3970
        }
3971
 
3972
      if (s7_end_of_line (str) == (int) s7_FAIL)
3973
        return;
3974
    }
3975
  /* lcw/lce/scb/sce rD, [rA]+.  */
3976
  else
3977
    {
3978
      if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3979
          || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3980
        {
3981
          return;
3982
        }
3983
 
3984
      s7_skip_whitespace (str);
3985
      if (*str++ == '[')
3986
        {
3987
          int reg;
3988
 
3989
          s7_skip_whitespace (str);
3990
          if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3991
            {
3992
              return;
3993
            }
3994
 
3995
          /* Conflicts can occur on stores as well as loads.  */
3996
          conflict_reg = (conflict_reg == reg);
3997
          s7_skip_whitespace (str);
3998
          if (*str++ == ']')
3999
            {
4000
              unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
4001
 
4002
              if (*str++ == '+')
4003
                {
4004
                  if (conflict_reg)
4005
                    {
4006
                      as_warn (_("%s register same as write-back base"),
4007
                               ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4008
                                ? _("destination") : _("source")));
4009
                    }
4010
                }
4011
              else
4012
                {
4013
                  s7_inst.error = _("missing +");
4014
                  return;
4015
                }
4016
 
4017
              if (s7_end_of_line (str) == (int) s7_FAIL)
4018
                return;
4019
            }
4020
          else
4021
            {
4022
              s7_inst.error = _("missing ]");
4023
              return;
4024
            }
4025
        }
4026
      else
4027
        {
4028
          s7_inst.error = s7_BAD_ARGS;
4029
          return;
4030
        }
4031
    }
4032
}
4033
 
4034
/* Handle alw/asw.  */
4035
 
4036
static void
4037
s7_do_ldst_atomic (char *str)
4038
{
4039
  if (s7_university_version == 1)
4040
    {
4041
      s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4042
      return;
4043
    }
4044
 
4045
  s7_skip_whitespace (str);
4046
 
4047
  if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4048
      || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4049
    {
4050
      return;
4051
    }
4052
  else
4053
    {
4054
 
4055
      s7_skip_whitespace (str);
4056
      if (*str++ == '[')
4057
        {
4058
          int reg;
4059
 
4060
          s7_skip_whitespace (str);
4061
          if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4062
            {
4063
              return;
4064
            }
4065
 
4066
          s7_skip_whitespace (str);
4067
          if (*str++ != ']')
4068
            {
4069
              s7_inst.error = _("missing ]");
4070
              return;
4071
            }
4072
 
4073
          s7_end_of_line (str);
4074
        }
4075
      else
4076
        s7_inst.error = s7_BAD_ARGS;
4077
    }
4078
}
4079
 
4080
static void
4081
s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4082
                     int fix_num ATTRIBUTE_UNUSED,
4083
                     struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4084
                     symbolS *add_symbol)
4085
{
4086
  int i;
4087
  char *p;
4088
  fixS *fixp = NULL;
4089
  fixS *cur_fixp = NULL;
4090
  long where;
4091
  struct s7_score_it inst_main;
4092
 
4093
  memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4094
 
4095
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4096
  inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4097
  inst_main.type = Insn_PIC;
4098
 
4099
  for (i = 0; i < var_num; i++)
4100
    {
4101
      inst_main.relax_size += var_insts[i].size;
4102
      var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4103
                                                   s7_GET_INSN_CLASS (var_insts[i].type));
4104
    }
4105
 
4106
  /* Check data dependency.  */
4107
  s7_handle_dependency (&inst_main);
4108
 
4109
  /* Start a new frag if frag_now is not empty.  */
4110
  if (frag_now_fix () != 0)
4111
    {
4112
      if (!frag_now->tc_frag_data.is_insn)
4113
        {
4114
          frag_wane (frag_now);
4115
        }
4116
      frag_new (0);
4117
    }
4118
  frag_grow (20);
4119
 
4120
  /* Write fr_fix part.  */
4121
  p = frag_more (inst_main.size);
4122
  s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4123
 
4124
  if (inst_main.reloc.type != BFD_RELOC_NONE)
4125
    fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4126
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4127
 
4128
  frag_now->tc_frag_data.fixp = fixp;
4129
  cur_fixp = frag_now->tc_frag_data.fixp;
4130
 
4131
#ifdef OBJ_ELF
4132
  dwarf2_emit_insn (inst_main.size);
4133
#endif
4134
 
4135
  where = p - frag_now->fr_literal + inst_main.size;
4136
  for (i = 0; i < var_num; i++)
4137
    {
4138
      if (i > 0)
4139
        where += var_insts[i - 1].size;
4140
 
4141
      if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4142
        {
4143
          fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4144
                                &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4145
                                var_insts[i].reloc.type);
4146
          if (fixp)
4147
            {
4148
              if (cur_fixp)
4149
                {
4150
                  cur_fixp->fx_next = fixp;
4151
                  cur_fixp = cur_fixp->fx_next;
4152
                }
4153
              else
4154
                {
4155
                  frag_now->tc_frag_data.fixp = fixp;
4156
                  cur_fixp = frag_now->tc_frag_data.fixp;
4157
                }
4158
            }
4159
        }
4160
    }
4161
 
4162
  p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4163
                s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4164
                0, inst_main.size, 0), add_symbol, 0, NULL);
4165
 
4166
  /* Write fr_var part.
4167
     no calling s7_gen_insn_frag, no fixS will be generated.  */
4168
  for (i = 0; i < var_num; i++)
4169
    {
4170
      s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4171
      p += var_insts[i].size;
4172
    }
4173
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4174
  s7_inst.bwarn = -1;
4175
}
4176
 
4177
/* Build a relax frag for la instruction when generating s7_PIC,
4178
   external symbol first and local symbol second.  */
4179
 
4180
static void
4181
s7_build_la_pic (int reg_rd, expressionS exp)
4182
{
4183
  symbolS *add_symbol = exp.X_add_symbol;
4184
  offsetT add_number = exp.X_add_number;
4185
  struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4186
  struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4187
  int fix_num = 0;
4188
  int var_num = 0;
4189
  char tmp[s7_MAX_LITERAL_POOL_SIZE];
4190
  int r1_bak;
4191
 
4192
  r1_bak = s7_nor1;
4193
  s7_nor1 = 0;
4194
 
4195
  if (add_number == 0)
4196
    {
4197
      fix_num = 1;
4198
      var_num = 2;
4199
 
4200
      /* For an external symbol, only one insn is generated;
4201
         For a local symbol, two insns are generated.  */
4202
      /* Fix part
4203
         For an external symbol: lw rD, <sym>($gp)
4204
                                 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
4205
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4206
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4207
        return;
4208
 
4209
      if (reg_rd == s7_PIC_CALL_REG)
4210
        s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4211
      memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4212
 
4213
      /* Var part
4214
         For a local symbol :
4215
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4216
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4217
      s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4218
      memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4219
      sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4220
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4221
        return;
4222
 
4223
      memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4224
      s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4225
    }
4226
  else if (add_number >= -0x8000 && add_number <= 0x7fff)
4227
    {
4228
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4229
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4230
      if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4231
        return;
4232
 
4233
      /* Insn 2  */
4234
      fix_num = 1;
4235
      var_num = 1;
4236
      /* Fix part
4237
         For an external symbol: addi rD, <constant> */
4238
      sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4239
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4240
        return;
4241
 
4242
      memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4243
 
4244
      /* Var part
4245
         For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
4246
      sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number);
4247
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4248
        return;
4249
 
4250
      memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4251
      s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4252
    }
4253
  else
4254
    {
4255
      int hi = (add_number >> 16) & 0x0000FFFF;
4256
      int lo = add_number & 0x0000FFFF;
4257
 
4258
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4259
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4260
      if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4261
        return;
4262
 
4263
      /* Insn 2  */
4264
      fix_num = 1;
4265
      var_num = 1;
4266
      /* Fix part
4267
         For an external symbol: ldis r1, HI%<constant>  */
4268
      sprintf (tmp, "ldis r1, %d", hi);
4269
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4270
        return;
4271
 
4272
      memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4273
 
4274
      /* Var part
4275
         For a local symbol: ldis r1, HI%<constant>
4276
         but, if lo is outof 16 bit, make hi plus 1  */
4277
      if ((lo < -0x8000) || (lo > 0x7fff))
4278
        {
4279
          hi += 1;
4280
        }
4281
      sprintf (tmp, "ldis_pic r1, %d", hi);
4282
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4283
        return;
4284
 
4285
      memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4286
      s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4287
 
4288
      /* Insn 3  */
4289
      fix_num = 1;
4290
      var_num = 1;
4291
      /* Fix part
4292
         For an external symbol: ori r1, LO%<constant>  */
4293
      sprintf (tmp, "ori r1, %d", lo);
4294
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4295
        return;
4296
 
4297
      memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4298
 
4299
      /* Var part
4300
         For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
4301
      sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
4302
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4303
        return;
4304
 
4305
      memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4306
      s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4307
 
4308
      /* Insn 4: add rD, rD, r1  */
4309
      sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4310
      if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4311
        return;
4312
 
4313
     /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4314
     s7_inst.bwarn = -1;
4315
    }
4316
 
4317
  s7_nor1 = r1_bak;
4318
}
4319
 
4320
/* Handle la.  */
4321
 
4322
static void
4323
s7_do_macro_la_rdi32 (char *str)
4324
{
4325
  int reg_rd;
4326
 
4327
  s7_skip_whitespace (str);
4328
  if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4329
      || s7_skip_past_comma (&str) == (int) s7_FAIL)
4330
    {
4331
      return;
4332
    }
4333
  else
4334
    {
4335
      char append_str[s7_MAX_LITERAL_POOL_SIZE];
4336
      char *keep_data = str;
4337
 
4338
      /* Check immediate value.  */
4339
      if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4340
        {
4341
          s7_inst.error = _("expression error");
4342
          return;
4343
        }
4344
      else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4345
               && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4346
        {
4347
          s7_inst.error = _("value not in range [0, 0xffffffff]");
4348
          return;
4349
        }
4350
 
4351
      /* Reset str.  */
4352
      str = keep_data;
4353
 
4354
      /* la rd, simm16.  */
4355
      if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4356
        {
4357
          s7_end_of_line (str);
4358
          return;
4359
        }
4360
      /* la rd, imm32 or la rd, label.  */
4361
      else
4362
        {
4363
          s7_SET_INSN_ERROR (NULL);
4364
          str = keep_data;
4365
          if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4366
              || (s7_end_of_line (str) == (int) s7_FAIL))
4367
            {
4368
              return;
4369
            }
4370
          else
4371
            {
4372
              if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4373
                {
4374
                  sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4375
                  if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4376
                    return;
4377
 
4378
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4379
                  if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4380
                    return;
4381
                }
4382
              else
4383
                {
4384
                  gas_assert (s7_inst.reloc.exp.X_add_symbol);
4385
                  s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4386
                }
4387
 
4388
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4389
              s7_inst.bwarn = -1;
4390
            }
4391
        }
4392
    }
4393
}
4394
 
4395
/* Handle li.  */
4396
 
4397
static void
4398
s7_do_macro_li_rdi32 (char *str)
4399
{
4400
  int reg_rd;
4401
 
4402
  s7_skip_whitespace (str);
4403
  if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4404
      || s7_skip_past_comma (&str) == (int) s7_FAIL)
4405
    {
4406
      return;
4407
    }
4408
  else
4409
    {
4410
      char *keep_data = str;
4411
 
4412
      /* Check immediate value.  */
4413
      if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4414
        {
4415
          s7_inst.error = _("expression error");
4416
          return;
4417
        }
4418
      else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4419
                 && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4420
        {
4421
          s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4422
          return;
4423
        }
4424
 
4425
      /* Reset str.  */
4426
      str = keep_data;
4427
 
4428
      /* li rd, simm16.  */
4429
      if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4430
        {
4431
          s7_end_of_line (str);
4432
          return;
4433
        }
4434
      /* li rd, imm32.  */
4435
      else
4436
        {
4437
          char append_str[s7_MAX_LITERAL_POOL_SIZE];
4438
 
4439
          str = keep_data;
4440
 
4441
          if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4442
              || (s7_end_of_line (str) == (int) s7_FAIL))
4443
            {
4444
              return;
4445
            }
4446
          else if (s7_inst.reloc.exp.X_add_symbol)
4447
            {
4448
              s7_inst.error = _("li rd label isn't correct instruction form");
4449
              return;
4450
            }
4451
          else
4452
            {
4453
              sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4454
 
4455
              if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4456
                return;
4457
              else
4458
                {
4459
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4460
                  if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4461
                    return;
4462
 
4463
                  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4464
                  s7_inst.bwarn = -1;
4465
                }
4466
            }
4467
        }
4468
    }
4469
}
4470
 
4471
/* Handle mul/mulu/div/divu/rem/remu.  */
4472
 
4473
static void
4474
s7_do_macro_mul_rdrsrs (char *str)
4475
{
4476
  int reg_rd;
4477
  int reg_rs1;
4478
  int reg_rs2;
4479
  char *backupstr;
4480
  char append_str[s7_MAX_LITERAL_POOL_SIZE];
4481
 
4482
  if (s7_university_version == 1)
4483
    as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4484
 
4485
  strcpy (append_str, str);
4486
  backupstr = append_str;
4487
  s7_skip_whitespace (backupstr);
4488
  if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4489
      || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4490
      || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4491
    {
4492
      s7_inst.error = s7_BAD_ARGS;
4493
      return;
4494
    }
4495
 
4496
  if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4497
    {
4498
      /* rem/remu rA, rB is error format.  */
4499
      if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4500
        {
4501
          s7_SET_INSN_ERROR (s7_BAD_ARGS);
4502
        }
4503
      else
4504
        {
4505
          s7_SET_INSN_ERROR (NULL);
4506
          s7_do_rsrs (str);
4507
        }
4508
      return;
4509
    }
4510
  else
4511
    {
4512
      s7_SET_INSN_ERROR (NULL);
4513
      if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4514
          || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4515
        {
4516
          return;
4517
        }
4518
      else
4519
        {
4520
          char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4521
 
4522
          if (strcmp (s7_inst.name, "rem") == 0)
4523
            {
4524
              sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4525
              sprintf (append_str1, "mfceh  r%d", reg_rd);
4526
            }
4527
          else if (strcmp (s7_inst.name, "remu") == 0)
4528
            {
4529
              sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4530
              sprintf (append_str1, "mfceh  r%d", reg_rd);
4531
            }
4532
          else
4533
            {
4534
              sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4535
              sprintf (append_str1, "mfcel  r%d", reg_rd);
4536
            }
4537
 
4538
          /* Output mul/mulu or div/divu or rem/remu.  */
4539
          if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4540
            return;
4541
 
4542
          /* Output mfcel or mfceh.  */
4543
          if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4544
            return;
4545
 
4546
          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4547
          s7_inst.bwarn = -1;
4548
        }
4549
    }
4550
}
4551
 
4552
static void
4553
s7_exp_macro_ldst_abs (char *str)
4554
{
4555
  int reg_rd;
4556
  char *backupstr, *tmp;
4557
  char append_str[s7_MAX_LITERAL_POOL_SIZE];
4558
  char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4559
  struct s7_score_it inst_backup;
4560
  int r1_bak = 0;
4561
 
4562
  r1_bak = s7_nor1;
4563
  s7_nor1 = 0;
4564
  memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4565
 
4566
  strcpy (verifystr, str);
4567
  backupstr = verifystr;
4568
  s7_skip_whitespace (backupstr);
4569
  if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4570
    return;
4571
 
4572
  tmp = backupstr;
4573
  if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4574
    return;
4575
 
4576
  backupstr = tmp;
4577
  sprintf (append_str, "li r1  %s", backupstr);
4578
  s7_append_insn (append_str, TRUE);
4579
 
4580
  memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4581
  sprintf (append_str, " r%d, [r1,0]", reg_rd);
4582
  s7_do_ldst_insn (append_str);
4583
 
4584
  s7_nor1 = r1_bak;
4585
}
4586
 
4587
static int
4588
s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4589
{
4590
  if (sym == NULL)
4591
    return 0;
4592
  else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4593
    {
4594
      const char *symname;
4595
      const char *segname;
4596
 
4597
      /* Find out whether this symbol can be referenced off the $gp
4598
         register.  It can be if it is smaller than the -G size or if
4599
         it is in the .sdata or .sbss section.  Certain symbols can
4600
         not be referenced off the $gp, although it appears as though
4601
         they can.  */
4602
      symname = S_GET_NAME (sym);
4603
      if (symname != NULL
4604
          && (strcmp (symname, "eprol") == 0
4605
              || strcmp (symname, "etext") == 0
4606
              || strcmp (symname, "_gp") == 0
4607
              || strcmp (symname, "edata") == 0
4608
              || strcmp (symname, "_fbss") == 0
4609
              || strcmp (symname, "_fdata") == 0
4610
              || strcmp (symname, "_ftext") == 0
4611
              || strcmp (symname, "end") == 0
4612
              || strcmp (symname, GP_DISP_LABEL) == 0))
4613
        {
4614
          return 1;
4615
        }
4616
      else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4617
      /* We must defer this decision until after the whole file has been read,
4618
         since there might be a .extern after the first use of this symbol.  */
4619
               || (before_relaxing
4620
                   && S_GET_VALUE (sym) == 0)
4621
               || (S_GET_VALUE (sym) != 0
4622
                   && S_GET_VALUE (sym) <= s7_g_switch_value)))
4623
        {
4624
          return 0;
4625
        }
4626
 
4627
      segname = segment_name (S_GET_SEGMENT (sym));
4628
      return (strcmp (segname, ".sdata") != 0
4629
              && strcmp (segname, ".sbss") != 0
4630
              && strncmp (segname, ".sdata.", 7) != 0
4631
              && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4632
    }
4633
  /* We are not optimizing for the $gp register.  */
4634
  else
4635
    return 1;
4636
}
4637
 
4638
/* Build a relax frag for lw/st instruction when generating s7_PIC,
4639
   external symbol first and local symbol second.  */
4640
 
4641
static void
4642
s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4643
{
4644
  symbolS *add_symbol = exp.X_add_symbol;
4645
  int add_number = exp.X_add_number;
4646
  struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4647
  struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4648
  int fix_num = 0;
4649
  int var_num = 0;
4650
  char tmp[s7_MAX_LITERAL_POOL_SIZE];
4651
  int r1_bak;
4652
 
4653
  r1_bak = s7_nor1;
4654
  s7_nor1 = 0;
4655
 
4656
  if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4657
    {
4658
      fix_num = 1;
4659
      var_num = 2;
4660
 
4661
      /* For an external symbol, two insns are generated;
4662
         For a local symbol, three insns are generated.  */
4663
      /* Fix part
4664
         For an external symbol: lw rD, <sym>($gp)
4665
                                 (BFD_RELOC_SCORE_GOT15)  */
4666
      sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4667
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4668
        return;
4669
 
4670
      memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4671
 
4672
      /* Var part
4673
         For a local symbol :
4674
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4675
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4676
      s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4677
      memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4678
      sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4679
      if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4680
        return;
4681
 
4682
      memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4683
      s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4684
 
4685
      /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
4686
      sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4687
      if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4688
        return;
4689
 
4690
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4691
      s7_inst.bwarn = -1;
4692
    }
4693
  else
4694
    {
4695
      s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4696
      return;
4697
    }
4698
 
4699
  s7_nor1 = r1_bak;
4700
}
4701
 
4702
static void
4703
s7_do_macro_ldst_label (char *str)
4704
{
4705
  int i;
4706
  int ldst_gp_p = 0;
4707
  int reg_rd;
4708
  int r1_bak;
4709
  char *backup_str;
4710
  char *label_str;
4711
  char *absolute_value;
4712
  char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4713
  char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4714
  struct s7_score_it inst_backup;
4715
  struct s7_score_it inst_expand[3];
4716
  struct s7_score_it inst_main;
4717
 
4718
  memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4719
  strcpy (verifystr, str);
4720
  backup_str = verifystr;
4721
 
4722
  s7_skip_whitespace (backup_str);
4723
  if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4724
    return;
4725
 
4726
  if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4727
    return;
4728
 
4729
  label_str = backup_str;
4730
 
4731
  /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
4732
  if (*backup_str == '[')
4733
    {
4734
      s7_inst.type = Rd_rvalueRs_preSI12;
4735
      s7_do_ldst_insn (str);
4736
      return;
4737
    }
4738
 
4739
  /* Ld/st rD, imm.  */
4740
  absolute_value = backup_str;
4741
  s7_inst.type = Rd_rvalueRs_SI15;
4742
 
4743
  if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4744
    {
4745
      s7_inst.error = _("expression error");
4746
      return;
4747
    }
4748
  else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4749
           && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4750
    {
4751
      s7_inst.error = _("value not in range [0, 0x7fffffff]");
4752
      return;
4753
    }
4754
  else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4755
    {
4756
      s7_inst.error = _("end on line error");
4757
      return;
4758
    }
4759
  else
4760
    {
4761
      if (s7_inst.reloc.exp.X_add_symbol == 0)
4762
        {
4763
          memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4764
          s7_exp_macro_ldst_abs (str);
4765
          return;
4766
        }
4767
    }
4768
 
4769
  /* Ld/st rD, label.  */
4770
  s7_inst.type = Rd_rvalueRs_SI15;
4771
  backup_str = absolute_value;
4772
  if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4773
      || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4774
    {
4775
      return;
4776
    }
4777
  else
4778
    {
4779
      if (s7_inst.reloc.exp.X_add_symbol == 0)
4780
        {
4781
          if (!s7_inst.error)
4782
            s7_inst.error = s7_BAD_ARGS;
4783
 
4784
          return;
4785
        }
4786
 
4787
      if (s7_score_pic == s7_PIC)
4788
        {
4789
          int ldst_idx = 0;
4790
          ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4791
          s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4792
                             s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4793
          return;
4794
        }
4795
      else
4796
        {
4797
          if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4798
               && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4799
               && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4800
            {
4801
              int ldst_idx = 0;
4802
 
4803
              /* Assign the real opcode.  */
4804
              ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4805
              s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4806
              s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4807
              s7_inst.instruction |= reg_rd << 20;
4808
              s7_inst.instruction |= s7_GP << 15;
4809
              s7_inst.relax_inst = 0x8000;
4810
              s7_inst.relax_size = 0;
4811
              ldst_gp_p = 1;
4812
            }
4813
        }
4814
    }
4815
 
4816
  /* Backup s7_inst.  */
4817
  memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4818
  r1_bak = s7_nor1;
4819
  s7_nor1 = 0;
4820
 
4821
  /* Determine which instructions should be output.  */
4822
  sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4823
  sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4824
  sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4825
 
4826
  /* Generate three instructions.
4827
     la r1, label
4828
     ld/st rd, [r1, 0]  */
4829
  for (i = 0; i < 3; i++)
4830
    {
4831
      if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4832
        return;
4833
 
4834
      memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4835
    }
4836
 
4837
  if (ldst_gp_p)
4838
    {
4839
      char *p;
4840
 
4841
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4842
      inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4843
      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4844
      inst_main.type = Insn_GP;
4845
 
4846
      for (i = 0; i < 3; i++)
4847
        inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4848
                                                       , s7_GET_INSN_CLASS (inst_expand[i].type));
4849
 
4850
      /* Check data dependency.  */
4851
      s7_handle_dependency (&inst_main);
4852
 
4853
      /* Start a new frag if frag_now is not empty.  */
4854
      if (frag_now_fix () != 0)
4855
        {
4856
          if (!frag_now->tc_frag_data.is_insn)
4857
            frag_wane (frag_now);
4858
 
4859
          frag_new (0);
4860
        }
4861
      frag_grow (20);
4862
 
4863
      /* Write fr_fix part.  */
4864
      p = frag_more (inst_main.size);
4865
      s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4866
 
4867
      if (inst_main.reloc.type != BFD_RELOC_NONE)
4868
        {
4869
          s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4870
                         &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4871
        }
4872
 
4873
#ifdef OBJ_ELF
4874
      dwarf2_emit_insn (inst_main.size);
4875
#endif
4876
 
4877
      /* s7_GP instruction can not do optimization, only can do relax between
4878
         1 instruction and 3 instructions.  */
4879
      p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4880
                    s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4881
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
4882
 
4883
      /* Write fr_var part.
4884
         no calling s7_gen_insn_frag, no fixS will be generated.  */
4885
      s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4886
      p += inst_expand[0].size;
4887
      s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4888
      p += inst_expand[1].size;
4889
      s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4890
    }
4891
  else
4892
    {
4893
      s7_gen_insn_frag (&inst_expand[0], NULL);
4894
      s7_gen_insn_frag (&inst_expand[1], NULL);
4895
      s7_gen_insn_frag (&inst_expand[2], NULL);
4896
    }
4897
  s7_nor1 = r1_bak;
4898
 
4899
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4900
  s7_inst.bwarn = -1;
4901
}
4902
 
4903
static void
4904
s7_do_lw_pic (char *str)
4905
{
4906
  int reg_rd;
4907
 
4908
  s7_skip_whitespace (str);
4909
  if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4910
      || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4911
      || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4912
      || (s7_end_of_line (str) == (int) s7_FAIL))
4913
    {
4914
      return;
4915
    }
4916
  else
4917
    {
4918
      if (s7_inst.reloc.exp.X_add_symbol == 0)
4919
        {
4920
          if (!s7_inst.error)
4921
            s7_inst.error = s7_BAD_ARGS;
4922
 
4923
          return;
4924
        }
4925
 
4926
      s7_inst.instruction |= s7_GP << 15;
4927
      s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4928
    }
4929
}
4930
 
4931
static void
4932
s7_do_empty (char *str)
4933
{
4934
  str = str;
4935
  if (s7_university_version == 1)
4936
    {
4937
      if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4938
          || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4939
          || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4940
          || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4941
        {
4942
          s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4943
          return;
4944
        }
4945
    }
4946
  if (s7_end_of_line (str) == (int) s7_FAIL)
4947
    return;
4948
 
4949
  if (s7_inst.relax_inst != 0x8000)
4950
    {
4951
      if (s7_inst.type == NO_OPD)
4952
        {
4953
          s7_inst.relax_size = 2;
4954
        }
4955
      else
4956
        {
4957
          s7_inst.relax_size = 4;
4958
        }
4959
    }
4960
}
4961
 
4962
static void
4963
s7_do_jump (char *str)
4964
{
4965
  char *save_in;
4966
 
4967
  s7_skip_whitespace (str);
4968
  if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4969
      || s7_end_of_line (str) == (int) s7_FAIL)
4970
    return;
4971
 
4972
  if (s7_inst.reloc.exp.X_add_symbol == 0)
4973
    {
4974
      s7_inst.error = _("lacking label  ");
4975
      return;
4976
    }
4977
 
4978
  if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4979
      && s7_inst.reloc.exp.X_add_number <= 16777215))
4980
    {
4981
      s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4982
      return;
4983
    }
4984
 
4985
  save_in = input_line_pointer;
4986
  input_line_pointer = str;
4987
  s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4988
  s7_inst.reloc.pc_rel = 1;
4989
  input_line_pointer = save_in;
4990
}
4991
 
4992
static void
4993
s7_do16_jump (char *str)
4994
{
4995
  s7_skip_whitespace (str);
4996
  if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4997
      || s7_end_of_line (str) == (int) s7_FAIL)
4998
    {
4999
      return;
5000
    }
5001
  else if (s7_inst.reloc.exp.X_add_symbol == 0)
5002
    {
5003
      s7_inst.error = _("lacking label  ");
5004
      return;
5005
    }
5006
  else if (!(s7_inst.reloc.exp.X_add_number >= 0
5007
           && s7_inst.reloc.exp.X_add_number <= 4095))
5008
    {
5009
      s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5010
      return;
5011
    }
5012
 
5013
  s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5014
  s7_inst.reloc.pc_rel = 1;
5015
}
5016
 
5017
static void
5018
s7_do_branch (char *str)
5019
{
5020
  unsigned long abs_value = 0;
5021
 
5022
  if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5023
      || s7_end_of_line (str) == (int) s7_FAIL)
5024
    {
5025
      return;
5026
    }
5027
  else if (s7_inst.reloc.exp.X_add_symbol == 0)
5028
    {
5029
      s7_inst.error = _("lacking label  ");
5030
      return;
5031
    }
5032
  else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5033
           && s7_inst.reloc.exp.X_add_number <= 524287))
5034
    {
5035
      s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5036
      return;
5037
    }
5038
 
5039
  s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5040
  s7_inst.reloc.pc_rel = 1;
5041
 
5042
  /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
5043
  s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5044
 
5045
  /* Compute 16 bit branch instruction.  */
5046
  if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5047
    {
5048
      s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5049
      s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5050
      s7_inst.relax_size = 2;
5051
    }
5052
  else
5053
    {
5054
      s7_inst.relax_inst = 0x8000;
5055
    }
5056
}
5057
 
5058
static void
5059
s7_do16_branch (char *str)
5060
{
5061
  if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5062
      || s7_end_of_line (str) == (int) s7_FAIL))
5063
    {
5064
      ;
5065
    }
5066
  else if (s7_inst.reloc.exp.X_add_symbol == 0)
5067
    {
5068
      s7_inst.error = _("lacking label");
5069
    }
5070
  else if (!(s7_inst.reloc.exp.X_add_number >= -512
5071
           && s7_inst.reloc.exp.X_add_number <= 511))
5072
    {
5073
      s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5074
    }
5075
  else
5076
    {
5077
      s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5078
      s7_inst.reloc.pc_rel = 1;
5079
      s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5080
    }
5081
}
5082
 
5083
/* Iterate over the base tables to create the instruction patterns.  */
5084
 
5085
static void
5086
s7_build_score_ops_hsh (void)
5087
{
5088
  unsigned int i;
5089
  static struct obstack insn_obstack;
5090
 
5091
  obstack_begin (&insn_obstack, 4000);
5092
  for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5093
    {
5094
      const struct s7_asm_opcode *insn = s7_score_insns + i;
5095
      unsigned len = strlen (insn->template_name);
5096
      struct s7_asm_opcode *new_opcode;
5097
      char *template_name;
5098
      new_opcode = (struct s7_asm_opcode *)
5099
          obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5100
      template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5101
 
5102
      strcpy (template_name, insn->template_name);
5103
      new_opcode->template_name = template_name;
5104
      new_opcode->parms = insn->parms;
5105
      new_opcode->value = insn->value;
5106
      new_opcode->relax_value = insn->relax_value;
5107
      new_opcode->type = insn->type;
5108
      new_opcode->bitmask = insn->bitmask;
5109
      hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5110
                   (void *) new_opcode);
5111
    }
5112
}
5113
 
5114
static void
5115
s7_build_dependency_insn_hsh (void)
5116
{
5117
  unsigned int i;
5118
  static struct obstack dependency_obstack;
5119
 
5120
  obstack_begin (&dependency_obstack, 4000);
5121
  for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5122
    {
5123
      const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5124
      unsigned len = strlen (tmp->insn_name);
5125
      struct s7_insn_to_dependency *new_i2d;
5126
 
5127
      new_i2d = (struct s7_insn_to_dependency *)
5128
          obstack_alloc (&dependency_obstack,
5129
                         sizeof (struct s7_insn_to_dependency));
5130
      new_i2d->insn_name = (char *) obstack_alloc (&dependency_obstack,
5131
                                                   len + 1);
5132
 
5133
      strcpy (new_i2d->insn_name, tmp->insn_name);
5134
      new_i2d->type = tmp->type;
5135
      hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5136
                   (void *) new_i2d);
5137
    }
5138
}
5139
 
5140
static valueT
5141
s7_md_chars_to_number (char *buf, int n)
5142
{
5143
  valueT result = 0;
5144
  unsigned char *where = (unsigned char *) buf;
5145
 
5146
  if (target_big_endian)
5147
    {
5148
      while (n--)
5149
        {
5150
          result <<= 8;
5151
          result |= (*where++ & 255);
5152
        }
5153
    }
5154
  else
5155
    {
5156
      while (n--)
5157
        {
5158
          result <<= 8;
5159
          result |= (where[n] & 255);
5160
        }
5161
    }
5162
 
5163
  return result;
5164
}
5165
 
5166
/* Return true if the given symbol should be considered local for s7_PIC.  */
5167
 
5168
static bfd_boolean
5169
s7_pic_need_relax (symbolS *sym, asection *segtype)
5170
{
5171
  asection *symsec;
5172
  bfd_boolean linkonce;
5173
 
5174
  /* Handle the case of a symbol equated to another symbol.  */
5175
  while (symbol_equated_reloc_p (sym))
5176
    {
5177
      symbolS *n;
5178
 
5179
      /* It's possible to get a loop here in a badly written
5180
         program.  */
5181
      n = symbol_get_value_expression (sym)->X_add_symbol;
5182
      if (n == sym)
5183
        break;
5184
      sym = n;
5185
    }
5186
 
5187
  symsec = S_GET_SEGMENT (sym);
5188
 
5189
  /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5190
  linkonce = FALSE;
5191
  if (symsec != segtype && ! S_IS_LOCAL (sym))
5192
    {
5193
      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5194
        linkonce = TRUE;
5195
 
5196
      /* The GNU toolchain uses an extension for ELF: a section
5197
          beginning with the magic string .gnu.linkonce is a linkonce
5198
          section.  */
5199
      if (strncmp (segment_name (symsec), ".gnu.linkonce",
5200
                   sizeof ".gnu.linkonce" - 1) == 0)
5201
        linkonce = TRUE;
5202
    }
5203
 
5204
  /* This must duplicate the test in adjust_reloc_syms.  */
5205
  return (symsec != &bfd_und_section
5206
            && symsec != &bfd_abs_section
5207
          && ! bfd_is_com_section (symsec)
5208
            && !linkonce
5209
#ifdef OBJ_ELF
5210
          /* A global or weak symbol is treated as external.  */
5211
          && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5212
              || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5213
#endif
5214
          );
5215
}
5216
 
5217
static int
5218
s7_judge_size_before_relax (fragS * fragp, asection *sec)
5219
{
5220
  int change = 0;
5221
 
5222
  if (s7_score_pic == s7_NO_PIC)
5223
    change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5224
  else
5225
    change = s7_pic_need_relax (fragp->fr_symbol, sec);
5226
 
5227
  if (change == 1)
5228
    {
5229
      /* Only at the first time determining whether s7_GP instruction relax should be done,
5230
         return the difference between insntruction size and instruction relax size.  */
5231
      if (fragp->fr_opcode == NULL)
5232
        {
5233
          fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
5234
          fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
5235
          return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
5236
        }
5237
    }
5238
 
5239
  return 0;
5240
}
5241
 
5242
static int
5243
s7_b32_relax_to_b16 (fragS * fragp)
5244
{
5245
  int grows = 0;
5246
  int relaxable_p = 0;
5247
  int r_old;
5248
  int r_new;
5249
  int frag_addr = fragp->fr_address + fragp->insn_addr;
5250
 
5251
  addressT symbol_address = 0;
5252
  symbolS *s;
5253
  offsetT offset;
5254
  unsigned long value;
5255
  unsigned long abs_value;
5256
 
5257
  /* FIXME : here may be able to modify better .
5258
     I don't know how to get the fragp's section ,
5259
     so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5260
     is different from the symbol's.  */
5261
 
5262
  r_old = s7_RELAX_OLD (fragp->fr_subtype);
5263
  r_new = s7_RELAX_NEW (fragp->fr_subtype);
5264
  relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5265
 
5266
  s = fragp->fr_symbol;
5267
  /* b/bl immediate  */
5268
  if (s == NULL)
5269
    frag_addr = 0;
5270
  else
5271
    {
5272
      if (s->bsym != 0)
5273
        symbol_address = (addressT) s->sy_frag->fr_address;
5274
    }
5275
 
5276
  value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5277
 
5278
  /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
5279
  offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
5280
  if ((offset & 0x80000) == 0x80000)
5281
    offset |= 0xfff00000;
5282
 
5283
  abs_value = offset + symbol_address - frag_addr;
5284
  if ((abs_value & 0x80000000) == 0x80000000)
5285
    abs_value = 0xffffffff - abs_value + 1;
5286
 
5287
  /* Relax branch 32 to branch 16.  */
5288
  if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
5289
      && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
5290
    {
5291
      /* do nothing.  */
5292
    }
5293
  else
5294
    {
5295
      /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
5296
      fragp->fr_opcode = NULL;
5297
      fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
5298
    }
5299
 
5300
  return grows;
5301
}
5302
 
5303
static void
5304
s7_parse_pce_inst (char *insnstr)
5305
{
5306
  char c;
5307
  char *p;
5308
  char *q;
5309
  char first[s7_MAX_LITERAL_POOL_SIZE];
5310
  char second[s7_MAX_LITERAL_POOL_SIZE];
5311
  struct s7_score_it pec_part_1;
5312
 
5313
  /* Get first part string of PCE.  */
5314
  p = strstr (insnstr, "||");
5315
  c = *p;
5316
  *p = '\0';
5317
  sprintf (first, "%s", insnstr);
5318
 
5319
  /* Get second part string of PCE.  */
5320
  *p = c;
5321
  p += 2;
5322
  sprintf (second, "%s", p);
5323
 
5324
  s7_parse_16_32_inst (first, FALSE);
5325
  if (s7_inst.error)
5326
    return;
5327
 
5328
  memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5329
 
5330
  q = second;
5331
  while (q && *q)
5332
    {
5333
      *q = TOLOWER (*q);
5334
      q++;
5335
    }
5336
 
5337
  s7_parse_16_32_inst (second, FALSE);
5338
  if (s7_inst.error)
5339
    return;
5340
 
5341
  if (   ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
5342
      || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
5343
      || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
5344
    {
5345
      s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5346
      sprintf (s7_inst.str, insnstr);
5347
      return;
5348
    }
5349
 
5350
  if (!s7_inst.error)
5351
    s7_gen_insn_frag (&pec_part_1, &s7_inst);
5352
}
5353
 
5354
 
5355
 
5356
static void
5357
s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5358
{
5359
  int i = 0;
5360
  int len = strlen (r->name) + 2;
5361
  char *buf = xmalloc (len);
5362
  char *buf2 = xmalloc (len);
5363
 
5364
  strcpy (buf + i, r->name);
5365
  for (i = 0; buf[i]; i++)
5366
    {
5367
      buf2[i] = TOUPPER (buf[i]);
5368
    }
5369
  buf2[i] = '\0';
5370
 
5371
  hash_insert (htab, buf, (void *) r);
5372
  hash_insert (htab, buf2, (void *) r);
5373
}
5374
 
5375
static void
5376
s7_build_reg_hsh (struct s7_reg_map *map)
5377
{
5378
  const struct s7_reg_entry *r;
5379
 
5380
  if ((map->htab = hash_new ()) == NULL)
5381
    {
5382
      as_fatal (_("virtual memory exhausted"));
5383
    }
5384
  for (r = map->names; r->name != NULL; r++)
5385
    {
5386
      s7_insert_reg (r, map->htab);
5387
    }
5388
}
5389
 
5390
 
5391
 
5392
/* If we change section we must dump the literal pool first.  */
5393
static void
5394
s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5395
{
5396
  subseg_set (bss_section, (subsegT) get_absolute_expression ());
5397
  demand_empty_rest_of_line ();
5398
}
5399
 
5400
static void
5401
s7_s_score_text (int ignore)
5402
{
5403
  obj_elf_text (ignore);
5404
  record_alignment (now_seg, 2);
5405
}
5406
 
5407
static void
5408
s7_s_section (int ignore)
5409
{
5410
  obj_elf_section (ignore);
5411
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5412
    record_alignment (now_seg, 2);
5413
 
5414
}
5415
 
5416
static void
5417
s7_s_change_sec (int sec)
5418
{
5419
  segT seg;
5420
 
5421
#ifdef OBJ_ELF
5422
  /* The ELF backend needs to know that we are changing sections, so
5423
     that .previous works correctly.  We could do something like check
5424
     for an obj_section_change_hook macro, but that might be confusing
5425
     as it would not be appropriate to use it in the section changing
5426
     functions in read.c, since obj-elf.c intercepts those.  FIXME:
5427
     This should be cleaner, somehow.  */
5428
  obj_elf_section_change_hook ();
5429
#endif
5430
  switch (sec)
5431
    {
5432
    case 'r':
5433
      seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5434
      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5435
      if (strcmp (TARGET_OS, "elf") != 0)
5436
        record_alignment (seg, 4);
5437
      demand_empty_rest_of_line ();
5438
      break;
5439
    case 's':
5440
      seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5441
      bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5442
      if (strcmp (TARGET_OS, "elf") != 0)
5443
        record_alignment (seg, 4);
5444
      demand_empty_rest_of_line ();
5445
      break;
5446
    }
5447
}
5448
 
5449
static void
5450
s7_s_score_mask (int reg_type  ATTRIBUTE_UNUSED)
5451
{
5452
  long mask, off;
5453
 
5454
  if (s7_cur_proc_ptr == NULL)
5455
    {
5456
      as_warn (_(".mask outside of .ent"));
5457
      demand_empty_rest_of_line ();
5458
      return;
5459
    }
5460
  if (get_absolute_expression_and_terminator (&mask) != ',')
5461
    {
5462
      as_warn (_("Bad .mask directive"));
5463
      --input_line_pointer;
5464
      demand_empty_rest_of_line ();
5465
      return;
5466
    }
5467
  off = get_absolute_expression ();
5468
  s7_cur_proc_ptr->reg_mask = mask;
5469
  s7_cur_proc_ptr->reg_offset = off;
5470
  demand_empty_rest_of_line ();
5471
}
5472
 
5473
static symbolS *
5474
s7_get_symbol (void)
5475
{
5476
  int c;
5477
  char *name;
5478
  symbolS *p;
5479
 
5480
  name = input_line_pointer;
5481
  c = get_symbol_end ();
5482
  p = (symbolS *) symbol_find_or_make (name);
5483
  *input_line_pointer = c;
5484
  return p;
5485
}
5486
 
5487
static long
5488
s7_get_number (void)
5489
{
5490
  int negative = 0;
5491
  long val = 0;
5492
 
5493
  if (*input_line_pointer == '-')
5494
    {
5495
      ++input_line_pointer;
5496
      negative = 1;
5497
    }
5498
  if (!ISDIGIT (*input_line_pointer))
5499
    as_bad (_("expected simple number"));
5500
  if (input_line_pointer[0] == '0')
5501
    {
5502
      if (input_line_pointer[1] == 'x')
5503
        {
5504
          input_line_pointer += 2;
5505
          while (ISXDIGIT (*input_line_pointer))
5506
            {
5507
              val <<= 4;
5508
              val |= hex_value (*input_line_pointer++);
5509
            }
5510
          return negative ? -val : val;
5511
        }
5512
      else
5513
        {
5514
          ++input_line_pointer;
5515
          while (ISDIGIT (*input_line_pointer))
5516
            {
5517
              val <<= 3;
5518
              val |= *input_line_pointer++ - '0';
5519
            }
5520
          return negative ? -val : val;
5521
        }
5522
    }
5523
  if (!ISDIGIT (*input_line_pointer))
5524
    {
5525
      printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5526
      as_warn (_("invalid number"));
5527
      return -1;
5528
    }
5529
  while (ISDIGIT (*input_line_pointer))
5530
    {
5531
      val *= 10;
5532
      val += *input_line_pointer++ - '0';
5533
    }
5534
  return negative ? -val : val;
5535
}
5536
 
5537
/* The .aent and .ent directives.  */
5538
 
5539
static void
5540
s7_s_score_ent (int aent)
5541
{
5542
  symbolS *symbolP;
5543
  int maybe_text;
5544
 
5545
  symbolP = s7_get_symbol ();
5546
  if (*input_line_pointer == ',')
5547
    ++input_line_pointer;
5548
  SKIP_WHITESPACE ();
5549
  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5550
    s7_get_number ();
5551
 
5552
#ifdef BFD_ASSEMBLER
5553
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5554
    maybe_text = 1;
5555
  else
5556
    maybe_text = 0;
5557
#else
5558
  if (now_seg != data_section && now_seg != bss_section)
5559
    maybe_text = 1;
5560
  else
5561
    maybe_text = 0;
5562
#endif
5563
  if (!maybe_text)
5564
    as_warn (_(".ent or .aent not in text section."));
5565
  if (!aent && s7_cur_proc_ptr)
5566
    as_warn (_("missing .end"));
5567
  if (!aent)
5568
    {
5569
      s7_cur_proc_ptr = &s7_cur_proc;
5570
      s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5571
      s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5572
      s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5573
      s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5574
      s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5575
      s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5576
      s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5577
      s7_cur_proc_ptr->isym = symbolP;
5578
      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5579
      ++s7_numprocs;
5580
      if (debug_type == DEBUG_STABS)
5581
        stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5582
    }
5583
  demand_empty_rest_of_line ();
5584
}
5585
 
5586
static void
5587
s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5588
{
5589
  char *backupstr;
5590
  char str[30];
5591
  long val;
5592
  int i = 0;
5593
 
5594
  backupstr = input_line_pointer;
5595
 
5596
#ifdef OBJ_ELF
5597
  if (s7_cur_proc_ptr == NULL)
5598
    {
5599
      as_warn (_(".frame outside of .ent"));
5600
      demand_empty_rest_of_line ();
5601
      return;
5602
    }
5603
  s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5604
  SKIP_WHITESPACE ();
5605
  s7_skip_past_comma (&backupstr);
5606
  while (*backupstr != ',')
5607
    {
5608
      str[i] = *backupstr;
5609
      i++;
5610
      backupstr++;
5611
    }
5612
  str[i] = '\0';
5613
  val = atoi (str);
5614
 
5615
  SKIP_WHITESPACE ();
5616
  s7_skip_past_comma (&backupstr);
5617
  s7_cur_proc_ptr->frame_offset = val;
5618
  s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5619
 
5620
  SKIP_WHITESPACE ();
5621
  s7_skip_past_comma (&backupstr);
5622
  i = 0;
5623
  while (*backupstr != '\n')
5624
    {
5625
      str[i] = *backupstr;
5626
      i++;
5627
      backupstr++;
5628
    }
5629
  str[i] = '\0';
5630
  val = atoi (str);
5631
  s7_cur_proc_ptr->leaf = val;
5632
  SKIP_WHITESPACE ();
5633
  s7_skip_past_comma (&backupstr);
5634
 
5635
#endif /* OBJ_ELF */
5636
  while (input_line_pointer != backupstr)
5637
    input_line_pointer++;
5638
}
5639
 
5640
/* The .end directive.  */
5641
 
5642
static void
5643
s7_s_score_end (int x ATTRIBUTE_UNUSED)
5644
{
5645
  symbolS *p;
5646
  int maybe_text;
5647
 
5648
  /* Generate a .pdr section.  */
5649
  segT saved_seg = now_seg;
5650
  subsegT saved_subseg = now_subseg;
5651
  valueT dot;
5652
  expressionS exp;
5653
  char *fragp;
5654
 
5655
  if (!is_end_of_line[(unsigned char)*input_line_pointer])
5656
    {
5657
      p = s7_get_symbol ();
5658
      demand_empty_rest_of_line ();
5659
    }
5660
  else
5661
    p = NULL;
5662
 
5663
#ifdef BFD_ASSEMBLER
5664
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5665
    maybe_text = 1;
5666
  else
5667
    maybe_text = 0;
5668
#else
5669
  if (now_seg != data_section && now_seg != bss_section)
5670
    maybe_text = 1;
5671
  else
5672
    maybe_text = 0;
5673
#endif
5674
 
5675
  if (!maybe_text)
5676
    as_warn (_(".end not in text section"));
5677
  if (!s7_cur_proc_ptr)
5678
    {
5679
      as_warn (_(".end directive without a preceding .ent directive."));
5680
      demand_empty_rest_of_line ();
5681
      return;
5682
    }
5683
  if (p != NULL)
5684
    {
5685
      gas_assert (S_GET_NAME (p));
5686
      if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5687
        as_warn (_(".end symbol does not match .ent symbol."));
5688
      if (debug_type == DEBUG_STABS)
5689
        stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5690
    }
5691
  else
5692
    as_warn (_(".end directive missing or unknown symbol"));
5693
 
5694
  if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5695
      (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5696
      (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5697
      (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5698
      (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5699
 
5700
  else
5701
    {
5702
      dot = frag_now_fix ();
5703
      gas_assert (s7_pdr_seg);
5704
      subseg_set (s7_pdr_seg, 0);
5705
      /* Write the symbol.  */
5706
      exp.X_op = O_symbol;
5707
      exp.X_add_symbol = p;
5708
      exp.X_add_number = 0;
5709
      emit_expr (&exp, 4);
5710
      fragp = frag_more (7 * 4);
5711
      s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5712
      s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5713
      s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5714
      s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5715
      s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5716
      s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5717
      s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5718
      subseg_set (saved_seg, saved_subseg);
5719
 
5720
    }
5721
  s7_cur_proc_ptr = NULL;
5722
}
5723
 
5724
/* Handle the .set pseudo-op.  */
5725
 
5726
static void
5727
s7_s_score_set (int x ATTRIBUTE_UNUSED)
5728
{
5729
  int i = 0;
5730
  char name[s7_MAX_LITERAL_POOL_SIZE];
5731
  char * orig_ilp = input_line_pointer;
5732
 
5733
  while (!is_end_of_line[(unsigned char)*input_line_pointer])
5734
    {
5735
      name[i] = (char) * input_line_pointer;
5736
      i++;
5737
      ++input_line_pointer;
5738
    }
5739
 
5740
  name[i] = '\0';
5741
 
5742
  if (strcmp (name, "nwarn") == 0)
5743
    {
5744
      s7_warn_fix_data_dependency = 0;
5745
    }
5746
  else if (strcmp (name, "fixdd") == 0)
5747
    {
5748
      s7_fix_data_dependency = 1;
5749
    }
5750
  else if (strcmp (name, "nofixdd") == 0)
5751
    {
5752
      s7_fix_data_dependency = 0;
5753
    }
5754
  else if (strcmp (name, "r1") == 0)
5755
    {
5756
      s7_nor1 = 0;
5757
    }
5758
  else if (strcmp (name, "nor1") == 0)
5759
    {
5760
      s7_nor1 = 1;
5761
    }
5762
  else if (strcmp (name, "optimize") == 0)
5763
    {
5764
      s7_g_opt = 1;
5765
    }
5766
  else if (strcmp (name, "volatile") == 0)
5767
    {
5768
      s7_g_opt = 0;
5769
    }
5770
  else if (strcmp (name, "pic") == 0)
5771
    {
5772
      s7_score_pic = s7_PIC;
5773
    }
5774
  else
5775
    {
5776
      input_line_pointer = orig_ilp;
5777
      s_set (0);
5778
    }
5779
}
5780
 
5781
/* Handle the .cpload pseudo-op.  This is used when generating s7_PIC code.  It sets the
5782
   $gp register for the function based on the function address, which is in the register
5783
   named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5784
   specially by the linker.  The result is:
5785
   ldis gp, %hi(GP_DISP_LABEL)
5786
   ori  gp, %low(GP_DISP_LABEL)
5787
   add  gp, gp, .cpload argument
5788
   The .cpload argument is normally r29.  */
5789
 
5790
static void
5791
s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5792
{
5793
  int reg;
5794
  char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5795
 
5796
  /* If we are not generating s7_PIC code, .cpload is ignored.  */
5797
  if (s7_score_pic == s7_NO_PIC)
5798
    {
5799
      s_ignore (0);
5800
      return;
5801
    }
5802
 
5803
  if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5804
    return;
5805
 
5806
  demand_empty_rest_of_line ();
5807
 
5808
  sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5809
  if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5810
    return;
5811
 
5812
  sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5813
  if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5814
    return;
5815
 
5816
  sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5817
  if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5818
    return;
5819
}
5820
 
5821
/* Handle the .cprestore pseudo-op.  This stores $gp into a given
5822
   offset from $sp.  The offset is remembered, and after making a s7_PIC
5823
   call $gp is restored from that location.  */
5824
 
5825
static void
5826
s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5827
{
5828
  int reg;
5829
  int cprestore_offset;
5830
  char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5831
 
5832
  /* If we are not generating s7_PIC code, .cprestore is ignored.  */
5833
  if (s7_score_pic == s7_NO_PIC)
5834
    {
5835
      s_ignore (0);
5836
      return;
5837
    }
5838
 
5839
  if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5840
      || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5841
    {
5842
      return;
5843
    }
5844
 
5845
  cprestore_offset = get_absolute_expression ();
5846
 
5847
  if (cprestore_offset <= 0x3fff)
5848
    {
5849
      sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5850
      if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5851
        return;
5852
    }
5853
  else
5854
    {
5855
      int r1_bak;
5856
 
5857
      r1_bak = s7_nor1;
5858
      s7_nor1 = 0;
5859
 
5860
      sprintf (insn_str, "li r1, %d", cprestore_offset);
5861
      if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5862
        return;
5863
 
5864
      sprintf (insn_str, "add r1, r1, r%d", reg);
5865
      if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5866
        return;
5867
 
5868
      sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5869
      if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5870
        return;
5871
 
5872
      s7_nor1 = r1_bak;
5873
    }
5874
 
5875
  demand_empty_rest_of_line ();
5876
}
5877
 
5878
/* Handle the .gpword pseudo-op.  This is used when generating s7_PIC
5879
   code.  It generates a 32 bit s7_GP relative reloc.  */
5880
 
5881
static void
5882
s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5883
{
5884
  expressionS ex;
5885
  char *p;
5886
 
5887
  /* When not generating s7_PIC code, this is treated as .word.  */
5888
  if (s7_score_pic == s7_NO_PIC)
5889
    {
5890
      cons (4);
5891
      return;
5892
    }
5893
  expression (&ex);
5894
  if (ex.X_op != O_symbol || ex.X_add_number != 0)
5895
    {
5896
      as_bad (_("Unsupported use of .gpword"));
5897
      ignore_rest_of_line ();
5898
    }
5899
  p = frag_more (4);
5900
  s7_number_to_chars (p, (valueT) 0, 4);
5901
  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5902
  demand_empty_rest_of_line ();
5903
}
5904
 
5905
/* Handle the .cpadd pseudo-op.  This is used when dealing with switch
5906
   tables in s7_PIC code.  */
5907
 
5908
static void
5909
s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5910
{
5911
  int reg;
5912
  char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5913
 
5914
  /* If we are not generating s7_PIC code, .cpload is ignored.  */
5915
  if (s7_score_pic == s7_NO_PIC)
5916
    {
5917
      s_ignore (0);
5918
      return;
5919
    }
5920
 
5921
  if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5922
    {
5923
      return;
5924
    }
5925
  demand_empty_rest_of_line ();
5926
 
5927
  /* Add $gp to the register named as an argument.  */
5928
  sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5929
  if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5930
    return;
5931
}
5932
 
5933
#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5934
#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)                \
5935
    do                                                          \
5936
    {                                                           \
5937
    if ((SIZE) >= 8)                                            \
5938
    (P2VAR) = 3;                                                \
5939
    else if ((SIZE) >= 4)                                       \
5940
    (P2VAR) = 2;                                                \
5941
    else if ((SIZE) >= 2)                                       \
5942
    (P2VAR) = 1;                                                \
5943
    else                                                        \
5944
    (P2VAR) = 0;                                         \
5945
    }                                                           \
5946
  while (0)
5947
#endif
5948
 
5949
static void
5950
s7_s_score_lcomm (int bytes_p)
5951
{
5952
  char *name;
5953
  char c;
5954
  char *p;
5955
  int temp;
5956
  symbolS *symbolP;
5957
  segT current_seg = now_seg;
5958
  subsegT current_subseg = now_subseg;
5959
  const int max_alignment = 15;
5960
  int align = 0;
5961
  segT bss_seg = bss_section;
5962
  int needs_align = 0;
5963
 
5964
  name = input_line_pointer;
5965
  c = get_symbol_end ();
5966
  p = input_line_pointer;
5967
  *p = c;
5968
 
5969
  if (name == p)
5970
    {
5971
      as_bad (_("expected symbol name"));
5972
      discard_rest_of_line ();
5973
      return;
5974
    }
5975
 
5976
  SKIP_WHITESPACE ();
5977
 
5978
  /* Accept an optional comma after the name.  The comma used to be
5979
     required, but Irix 5 cc does not generate it.  */
5980
  if (*input_line_pointer == ',')
5981
    {
5982
      ++input_line_pointer;
5983
      SKIP_WHITESPACE ();
5984
    }
5985
 
5986
  if (is_end_of_line[(unsigned char)*input_line_pointer])
5987
    {
5988
      as_bad (_("missing size expression"));
5989
      return;
5990
    }
5991
 
5992
  if ((temp = get_absolute_expression ()) < 0)
5993
    {
5994
      as_warn (_("BSS length (%d) < 0 ignored"), temp);
5995
      ignore_rest_of_line ();
5996
      return;
5997
    }
5998
 
5999
#if defined (TC_SCORE)
6000
  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6001
    {
6002
      /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
6003
      if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6004
        {
6005
          bss_seg = subseg_new (".sbss", 1);
6006
          seg_info (bss_seg)->bss = 1;
6007
#ifdef BFD_ASSEMBLER
6008
          if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6009
            as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6010
#endif
6011
        }
6012
    }
6013
#endif
6014
 
6015
  SKIP_WHITESPACE ();
6016
  if (*input_line_pointer == ',')
6017
    {
6018
      ++input_line_pointer;
6019
      SKIP_WHITESPACE ();
6020
 
6021
      if (is_end_of_line[(unsigned char)*input_line_pointer])
6022
        {
6023
          as_bad (_("missing alignment"));
6024
          return;
6025
        }
6026
      else
6027
        {
6028
          align = get_absolute_expression ();
6029
          needs_align = 1;
6030
        }
6031
    }
6032
 
6033
  if (!needs_align)
6034
    {
6035
      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6036
 
6037
      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6038
      if (align)
6039
        record_alignment (bss_seg, align);
6040
    }
6041
 
6042
  if (needs_align)
6043
    {
6044
      if (bytes_p)
6045
        {
6046
          /* Convert to a power of 2.  */
6047
          if (align != 0)
6048
            {
6049
              unsigned int i;
6050
 
6051
              for (i = 0; align != 0; align >>= 1, ++i)
6052
                ;
6053
              align = i - 1;
6054
            }
6055
        }
6056
 
6057
      if (align > max_alignment)
6058
        {
6059
          align = max_alignment;
6060
          as_warn (_("alignment too large; %d assumed"), align);
6061
        }
6062
      else if (align < 0)
6063
        {
6064
          align = 0;
6065
          as_warn (_("alignment negative; 0 assumed"));
6066
        }
6067
 
6068
      record_alignment (bss_seg, align);
6069
    }
6070
  else
6071
    {
6072
      /* Assume some objects may require alignment on some systems.  */
6073
#if defined (TC_ALPHA) && ! defined (VMS)
6074
      if (temp > 1)
6075
        {
6076
          align = ffs (temp) - 1;
6077
          if (temp % (1 << align))
6078
            abort ();
6079
        }
6080
#endif
6081
    }
6082
 
6083
  *p = 0;
6084
  symbolP = symbol_find_or_make (name);
6085
  *p = c;
6086
 
6087
  if (
6088
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6089
     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6090
#ifdef BFD_ASSEMBLER
6091
       (OUTPUT_FLAVOR != bfd_target_aout_flavour
6092
        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6093
#else
6094
       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6095
#endif
6096
#endif
6097
       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6098
    {
6099
      char *pfrag;
6100
 
6101
      subseg_set (bss_seg, 1);
6102
 
6103
      if (align)
6104
        frag_align (align, 0, 0);
6105
 
6106
      /* Detach from old frag.  */
6107
      if (S_GET_SEGMENT (symbolP) == bss_seg)
6108
        symbol_get_frag (symbolP)->fr_symbol = NULL;
6109
 
6110
      symbol_set_frag (symbolP, frag_now);
6111
      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6112
      *pfrag = 0;
6113
 
6114
 
6115
      S_SET_SEGMENT (symbolP, bss_seg);
6116
 
6117
#ifdef OBJ_COFF
6118
      /* The symbol may already have been created with a preceding
6119
         ".globl" directive -- be careful not to step on storage class
6120
         in that case.  Otherwise, set it to static.  */
6121
      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6122
        {
6123
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
6124
        }
6125
#endif /* OBJ_COFF */
6126
 
6127
#ifdef S_SET_SIZE
6128
      S_SET_SIZE (symbolP, temp);
6129
#endif
6130
    }
6131
  else
6132
    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6133
 
6134
  subseg_set (current_seg, current_subseg);
6135
 
6136
  demand_empty_rest_of_line ();
6137
}
6138
 
6139
 
6140
 
6141
static void
6142
s7_begin (void)
6143
{
6144
  unsigned int i;
6145
  segT seg;
6146
  subsegT subseg;
6147
 
6148
  if ((s7_score_ops_hsh = hash_new ()) == NULL)
6149
    as_fatal (_("virtual memory exhausted"));
6150
 
6151
  s7_build_score_ops_hsh ();
6152
 
6153
  if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6154
    as_fatal (_("virtual memory exhausted"));
6155
 
6156
  s7_build_dependency_insn_hsh ();
6157
 
6158
  for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6159
    s7_build_reg_hsh (s7_all_reg_maps + i);
6160
 
6161
  /* Initialize dependency vector.  */
6162
  s7_init_dependency_vector ();
6163
 
6164
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6165
  seg = now_seg;
6166
  subseg = now_subseg;
6167
  s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6168
  (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6169
  (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
6170
  subseg_set (seg, subseg);
6171
 
6172
  if (s7_USE_GLOBAL_POINTER_OPT)
6173
    bfd_set_gp_size (stdoutput, s7_g_switch_value);
6174
}
6175
 
6176
static void
6177
s7_assemble (char *str)
6178
{
6179
  know (str);
6180
  know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6181
 
6182
  memset (&s7_inst, '\0', sizeof (s7_inst));
6183
  if (s7_INSN_IS_PCE_P (str))
6184
    s7_parse_pce_inst (str);
6185
  else
6186
    s7_parse_16_32_inst (str, TRUE);
6187
 
6188
  if (s7_inst.error)
6189
    as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6190
}
6191
 
6192
/* We handle all bad expressions here, so that we can report the faulty
6193
   instruction in the error message.  */
6194
 
6195
static void
6196
s7_operand (expressionS * exp)
6197
{
6198
  if (s7_in_my_get_expression)
6199
    {
6200
      exp->X_op = O_illegal;
6201
      if (s7_inst.error == NULL)
6202
        {
6203
          s7_inst.error = _("bad expression");
6204
        }
6205
    }
6206
}
6207
 
6208
/* Turn a string in input_line_pointer into a floating point constant
6209
   of type TYPE, and store the appropriate bytes in *LITP.  The number
6210
   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
6211
   returned, or NULL on OK.
6212
 
6213
   Note that fp constants aren't represent in the normal way on the ARM.
6214
   In big endian mode, things are as expected.  However, in little endian
6215
   mode fp constants are big-endian word-wise, and little-endian byte-wise
6216
   within the words.  For example, (double) 1.1 in big endian mode is
6217
   the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6218
   the byte sequence 99 99 f1 3f 9a 99 99 99.  */
6219
 
6220
static char *
6221
s7_atof (int type, char *litP, int *sizeP)
6222
{
6223
  int prec;
6224
  LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
6225
  char *t;
6226
  int i;
6227
 
6228
  switch (type)
6229
    {
6230
    case 'f':
6231
    case 'F':
6232
    case 's':
6233
    case 'S':
6234
      prec = 2;
6235
      break;
6236
    case 'd':
6237
    case 'D':
6238
    case 'r':
6239
    case 'R':
6240
      prec = 4;
6241
      break;
6242
    case 'x':
6243
    case 'X':
6244
    case 'p':
6245
    case 'P':
6246
      prec = 6;
6247
      break;
6248
    default:
6249
      *sizeP = 0;
6250
      return _("bad call to MD_ATOF()");
6251
    }
6252
 
6253
  t = atof_ieee (input_line_pointer, type, words);
6254
  if (t)
6255
    input_line_pointer = t;
6256
  *sizeP = prec * 2;
6257
 
6258
  if (target_big_endian)
6259
    {
6260
      for (i = 0; i < prec; i++)
6261
        {
6262
          s7_number_to_chars (litP, (valueT) words[i], 2);
6263
          litP += 2;
6264
        }
6265
    }
6266
  else
6267
    {
6268
      for (i = 0; i < prec; i += 2)
6269
        {
6270
          s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6271
          s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6272
          litP += 4;
6273
        }
6274
    }
6275
 
6276
  return 0;
6277
}
6278
 
6279
/* Implementation of md_frag_check.
6280
   Called after md_convert_frag().  */
6281
 
6282
static void
6283
s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
6284
{
6285
  know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6286
}
6287
 
6288
/* Implementation of TC_VALIDATE_FIX.
6289
   Called before md_apply_fix() and after md_convert_frag().  */
6290
 
6291
static void
6292
s7_validate_fix (fixS *fixP)
6293
{
6294
  fixP->fx_where += fixP->fx_frag->insn_addr;
6295
}
6296
 
6297
static int
6298
s7_force_relocation (struct fix *fixp)
6299
{
6300
  int retval = 0;
6301
 
6302
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6303
      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6304
      || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6305
      || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6306
      || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6307
      || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6308
    {
6309
      retval = 1;
6310
    }
6311
 
6312
  return retval;
6313
}
6314
 
6315
static bfd_boolean
6316
s7_fix_adjustable (fixS * fixP)
6317
{
6318
  if (fixP->fx_addsy == NULL)
6319
    {
6320
      return 1;
6321
    }
6322
  else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6323
      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6324
    {
6325
      return 0;
6326
    }
6327
  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6328
           || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6329
           || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6330
           || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6331
    {
6332
      return 0;
6333
    }
6334
 
6335
  return 1;
6336
}
6337
 
6338
static void
6339
s7_elf_final_processing (void)
6340
{
6341
  unsigned long val = E_SCORE_MACH_SCORE7;
6342
 
6343
  elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6344
  elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6345
  elf_elfheader (stdoutput)->e_flags |= val;
6346
 
6347
  if (s7_fix_data_dependency == 1)
6348
    {
6349
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6350
    }
6351
  if (s7_score_pic == s7_PIC)
6352
    {
6353
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6354
    }
6355
}
6356
 
6357
/* In this function, we determine whether s7_GP instruction should do relaxation,
6358
   for the label being against was known now.
6359
   Doing this here but not in md_relax_frag() can induce iteration times
6360
   in stage of doing relax.  */
6361
 
6362
static int
6363
s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6364
{
6365
  if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6366
      || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6367
    return s7_judge_size_before_relax (fragp, sec);
6368
 
6369
  return 0;
6370
}
6371
 
6372
static int
6373
s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6374
               fragS * fragp,
6375
               long stretch ATTRIBUTE_UNUSED)
6376
{
6377
  int grows = 0;
6378
  int insn_size;
6379
  int insn_relax_size;
6380
  int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
6381
  int relaxable_p = 0;
6382
  bfd_boolean word_align_p = FALSE;
6383
  fragS *next_fragp;
6384
 
6385
  /* If the instruction address is odd, make it half word align first.  */
6386
  if ((fragp->fr_address) % 2 != 0)
6387
    {
6388
      if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6389
        {
6390
          fragp->insn_addr = 1;
6391
          grows += 1;
6392
        }
6393
    }
6394
 
6395
  word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6396
 
6397
  /* Get instruction size and relax size after the last relaxation.  */
6398
  if (fragp->fr_opcode)
6399
    {
6400
      insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6401
      insn_relax_size = s7_RELAX_OLD (fragp->fr_subtype);
6402
    }
6403
  else
6404
    {
6405
      insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6406
      insn_relax_size = s7_RELAX_NEW (fragp->fr_subtype);
6407
    }
6408
 
6409
  /* Handle specially for s7_GP instruction.  for, s7_judge_size_before_relax() has already determine
6410
     whether the s7_GP instruction should do relax.  */
6411
  if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6412
      || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6413
    {
6414
      if (!word_align_p)
6415
        {
6416
          if (fragp->insn_addr < 2)
6417
            {
6418
              fragp->insn_addr += 2;
6419
              grows += 2;
6420
            }
6421
          else
6422
            {
6423
              fragp->insn_addr -= 2;
6424
              grows -= 2;
6425
            }
6426
        }
6427
 
6428
      if (fragp->fr_opcode)
6429
        fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6430
      else
6431
        fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6432
    }
6433
  else
6434
    {
6435
      if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6436
        s7_b32_relax_to_b16 (fragp);
6437
 
6438
      relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6439
      next_fragp = fragp->fr_next;
6440
      while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6441
        {
6442
          next_fragp = next_fragp->fr_next;
6443
        }
6444
 
6445
      if (next_fragp)
6446
        {
6447
          int n_insn_size;
6448
          int n_relaxable_p = 0;
6449
 
6450
          if (next_fragp->fr_opcode)
6451
            {
6452
              n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6453
            }
6454
          else
6455
            {
6456
              n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6457
            }
6458
 
6459
          if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6460
            s7_b32_relax_to_b16 (next_fragp);
6461
          n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6462
 
6463
          if (word_align_p)
6464
            {
6465
              if (insn_size == 4)
6466
                {
6467
                  /* 32 -> 16.  */
6468
                  if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6469
                    {
6470
                      grows -= 2;
6471
                      do_relax_p = 1;
6472
                    }
6473
                }
6474
              else if (insn_size == 2)
6475
                {
6476
                  /* 16 -> 32.  */
6477
                  if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6478
                    {
6479
                      grows += 2;
6480
                      do_relax_p = 1;
6481
                    }
6482
                }
6483
              else
6484
                {
6485
                  abort ();
6486
                }
6487
            }
6488
          else
6489
            {
6490
              if (insn_size == 4)
6491
                {
6492
                  /* 32 -> 16.  */
6493
                  if (relaxable_p)
6494
                    {
6495
                      grows -= 2;
6496
                      do_relax_p = 1;
6497
                    }
6498
                  /* Make the 32 bit insturction word align.  */
6499
                  else
6500
                    {
6501
                      fragp->insn_addr += 2;
6502
                      grows += 2;
6503
                    }
6504
                }
6505
              else if (insn_size == 2)
6506
                {
6507
                  /* Do nothing.  */
6508
                }
6509
              else
6510
                {
6511
                  abort ();
6512
                }
6513
            }
6514
        }
6515
      else
6516
        {
6517
          /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
6518
          if (word_align_p == FALSE)
6519
            {
6520
              if (insn_size % 4 == 0)
6521
                {
6522
                  /* 32 -> 16.  */
6523
                  if (relaxable_p)
6524
                    {
6525
                      grows -= 2;
6526
                      do_relax_p = 1;
6527
                    }
6528
                  else
6529
                    {
6530
                      fragp->insn_addr += 2;
6531
                      grows += 2;
6532
                    }
6533
                }
6534
            }
6535
          else
6536
            {
6537
              /* Do nothing.  */
6538
            }
6539
        }
6540
 
6541
      /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
6542
      if (do_relax_p)
6543
        {
6544
          if (fragp->fr_opcode)
6545
            {
6546
              fragp->fr_opcode = NULL;
6547
              /* Guarantee estimate stage is correct.  */
6548
              fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6549
              fragp->fr_fix += fragp->insn_addr;
6550
            }
6551
          else
6552
            {
6553
              fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6554
              /* Guarantee estimate stage is correct.  */
6555
              fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6556
              fragp->fr_fix += fragp->insn_addr;
6557
            }
6558
        }
6559
      else
6560
        {
6561
          if (fragp->fr_opcode)
6562
            {
6563
              /* Guarantee estimate stage is correct.  */
6564
              fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6565
              fragp->fr_fix += fragp->insn_addr;
6566
            }
6567
          else
6568
            {
6569
              /* Guarantee estimate stage is correct.  */
6570
              fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6571
              fragp->fr_fix += fragp->insn_addr;
6572
            }
6573
        }
6574
    }
6575
 
6576
  return grows;
6577
}
6578
 
6579
static void
6580
s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6581
                 segT sec ATTRIBUTE_UNUSED,
6582
                 fragS * fragp)
6583
{
6584
  int r_old;
6585
  int r_new;
6586
  char backup[20];
6587
  fixS *fixp;
6588
 
6589
  r_old = s7_RELAX_OLD (fragp->fr_subtype);
6590
  r_new = s7_RELAX_NEW (fragp->fr_subtype);
6591
 
6592
  /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
6593
  if (fragp->fr_opcode == NULL)
6594
    {
6595
      memcpy (backup, fragp->fr_literal, r_old);
6596
      fragp->fr_fix = r_old;
6597
    }
6598
  else
6599
    {
6600
      memcpy (backup, fragp->fr_literal + r_old, r_new);
6601
      fragp->fr_fix = r_new;
6602
    }
6603
 
6604
  fixp = fragp->tc_frag_data.fixp;
6605
  while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6606
    {
6607
      if (fragp->fr_opcode)
6608
        fixp->fx_done = 1;
6609
      fixp = fixp->fx_next;
6610
    }
6611
  while (fixp && fixp->fx_frag == fragp)
6612
    {
6613
      if (fragp->fr_opcode)
6614
        fixp->fx_where -= r_old + fragp->insn_addr;
6615
      else
6616
        fixp->fx_done = 1;
6617
      fixp = fixp->fx_next;
6618
    }
6619
 
6620
  if (fragp->insn_addr)
6621
    {
6622
      s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6623
    }
6624
  memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6625
  fragp->fr_fix += fragp->insn_addr;
6626
}
6627
 
6628
static long
6629
s7_pcrel_from (fixS * fixP)
6630
{
6631
  long retval = 0;
6632
 
6633
  if (fixP->fx_addsy
6634
      && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6635
      && (fixP->fx_subsy == NULL))
6636
    {
6637
      retval = 0;
6638
    }
6639
  else
6640
    {
6641
      retval = fixP->fx_where + fixP->fx_frag->fr_address;
6642
    }
6643
 
6644
  return retval;
6645
}
6646
 
6647
/* Round up a section size to the appropriate boundary.  */
6648
static valueT
6649
s7_section_align (segT segment, valueT size)
6650
{
6651
  int align = bfd_get_section_alignment (stdoutput, segment);
6652
 
6653
  return ((size + (1 << align) - 1) & (-1 << align));
6654
}
6655
 
6656
static void
6657
s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6658
{
6659
  offsetT value = *valP;
6660
  offsetT abs_value = 0;
6661
  offsetT newval;
6662
  offsetT content;
6663
  unsigned short HI, LO;
6664
 
6665
  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6666
 
6667
  gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6668
  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6669
    {
6670
      if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6671
        fixP->fx_done = 1;
6672
    }
6673
 
6674
  /* If this symbol is in a different section then we need to leave it for
6675
     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
6676
     so we have to undo it's effects here.  */
6677
  if (fixP->fx_pcrel)
6678
    {
6679
      if (fixP->fx_addsy != NULL
6680
          && S_IS_DEFINED (fixP->fx_addsy)
6681
          && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6682
        value += md_pcrel_from (fixP);
6683
    }
6684
 
6685
  /* Remember value for emit_reloc.  */
6686
  fixP->fx_addnumber = value;
6687
 
6688
  switch (fixP->fx_r_type)
6689
    {
6690
    case BFD_RELOC_HI16_S:
6691
      if (fixP->fx_done)
6692
        {                       /* For la rd, imm32.  */
6693
          newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6694
          HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
6695
          newval |= (HI & 0x3fff) << 1;
6696
          newval |= ((HI >> 14) & 0x3) << 16;
6697
          s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6698
        }
6699
      break;
6700
    case BFD_RELOC_LO16:
6701
      if (fixP->fx_done)        /* For la rd, imm32.  */
6702
        {
6703
          newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6704
          LO = (value) & 0xffff;
6705
          newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
6706
          newval |= ((LO >> 14) & 0x3) << 16;
6707
          s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6708
        }
6709
      break;
6710
    case BFD_RELOC_SCORE_JMP:
6711
      {
6712
        content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6713
        value = fixP->fx_offset;
6714
        if (!(value >= 0 && value <= 0x1ffffff))
6715
          {
6716
            as_bad_where (fixP->fx_file, fixP->fx_line,
6717
                          _("j or jl truncate (0x%x)  [0 ~ 2^25-1]"), (unsigned int) value);
6718
            return;
6719
          }
6720
        content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6721
        s7_number_to_chars (buf, content, s7_INSN_SIZE);
6722
      }
6723
      break;
6724
    case BFD_RELOC_SCORE_BRANCH:
6725
      if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6726
        value = fixP->fx_offset;
6727
      else
6728
        fixP->fx_done = 1;
6729
 
6730
      content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6731
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6732
        {
6733
          if ((value & 0x80000000) == 0x80000000)
6734
            abs_value = 0xffffffff - value + 1;
6735
          if ((abs_value & 0xffffff00) != 0)
6736
            {
6737
              as_bad_where (fixP->fx_file, fixP->fx_line,
6738
                            _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6739
              return;
6740
            }
6741
          content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6742
          content &= 0xff00;
6743
          content = (content & 0xff00) | ((value >> 1) & 0xff);
6744
          s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6745
          fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6746
          fixP->fx_size = 2;
6747
        }
6748
      else
6749
        {
6750
          if ((value & 0x80000000) == 0x80000000)
6751
            abs_value = 0xffffffff - value + 1;
6752
          if ((abs_value & 0xfff80000) != 0)
6753
            {
6754
              as_bad_where (fixP->fx_file, fixP->fx_line,
6755
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6756
                            (unsigned int) value);
6757
              return;
6758
            }
6759
          content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6760
          content &= 0xfc00fc01;
6761
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6762
          s7_number_to_chars (buf, content, s7_INSN_SIZE);
6763
        }
6764
      break;
6765
    case BFD_RELOC_SCORE16_JMP:
6766
      content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6767
      content &= 0xf001;
6768
      value = fixP->fx_offset;
6769
      if (!(value >= 0 && value <= 0xfff))
6770
        {
6771
          as_bad_where (fixP->fx_file, fixP->fx_line,
6772
                        _("j! or jl! truncate (0x%x)  [0 ~ 2^12-1]"), (unsigned int) value);
6773
          return;
6774
        }
6775
      value = fixP->fx_offset & 0xfff;
6776
      content = (content & 0xfc01) | (value & 0xffe);
6777
      s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6778
      break;
6779
    case BFD_RELOC_SCORE16_BRANCH:
6780
      content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6781
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6782
        {
6783
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6784
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6785
            value = fixP->fx_offset;
6786
          else
6787
            fixP->fx_done = 1;
6788
 
6789
          if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6790
            {
6791
              as_bad_where (fixP->fx_file, fixP->fx_line,
6792
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6793
                            (unsigned int) value);
6794
              return;
6795
            }
6796
          content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6797
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6798
          s7_number_to_chars (buf, content, s7_INSN_SIZE);
6799
          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6800
          fixP->fx_size = 4;
6801
          break;
6802
        }
6803
      else
6804
        {
6805
          /* In differnt section.  */
6806
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6807
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6808
            value = fixP->fx_offset;
6809
          else
6810
            fixP->fx_done = 1;
6811
 
6812
          if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6813
            {
6814
              as_bad_where (fixP->fx_file, fixP->fx_line,
6815
                            _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"),
6816
                            (unsigned int) value);
6817
              return;
6818
            }
6819
          content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6820
          content = (content & 0xff00) | ((value >> 1) & 0xff);
6821
          s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6822
          break;
6823
        }
6824
    case BFD_RELOC_8:
6825
      if (fixP->fx_done || fixP->fx_pcrel)
6826
        s7_number_to_chars (buf, value, 1);
6827
#ifdef OBJ_ELF
6828
      else
6829
        {
6830
          value = fixP->fx_offset;
6831
          s7_number_to_chars (buf, value, 1);
6832
        }
6833
#endif
6834
      break;
6835
 
6836
    case BFD_RELOC_16:
6837
      if (fixP->fx_done || fixP->fx_pcrel)
6838
        s7_number_to_chars (buf, value, 2);
6839
#ifdef OBJ_ELF
6840
      else
6841
        {
6842
          value = fixP->fx_offset;
6843
          s7_number_to_chars (buf, value, 2);
6844
        }
6845
#endif
6846
      break;
6847
    case BFD_RELOC_RVA:
6848
    case BFD_RELOC_32:
6849
      if (fixP->fx_done || fixP->fx_pcrel)
6850
        s7_number_to_chars (buf, value, 4);
6851
#ifdef OBJ_ELF
6852
      else
6853
        {
6854
          value = fixP->fx_offset;
6855
          s7_number_to_chars (buf, value, 4);
6856
        }
6857
#endif
6858
      break;
6859
    case BFD_RELOC_VTABLE_INHERIT:
6860
      fixP->fx_done = 0;
6861
      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6862
        S_SET_WEAK (fixP->fx_addsy);
6863
      break;
6864
    case BFD_RELOC_VTABLE_ENTRY:
6865
      fixP->fx_done = 0;
6866
      break;
6867
    case BFD_RELOC_SCORE_GPREL15:
6868
      content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6869
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6870
        fixP->fx_r_type = BFD_RELOC_NONE;
6871
      fixP->fx_done = 0;
6872
      break;
6873
    case BFD_RELOC_SCORE_GOT15:
6874
    case BFD_RELOC_SCORE_DUMMY_HI16:
6875
    case BFD_RELOC_SCORE_GOT_LO16:
6876
    case BFD_RELOC_SCORE_CALL15:
6877
    case BFD_RELOC_GPREL32:
6878
      break;
6879
    case BFD_RELOC_NONE:
6880
    default:
6881
      as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6882
    }
6883
}
6884
 
6885
/* Translate internal representation of relocation info to BFD target format.  */
6886
 
6887
static arelent **
6888
s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6889
{
6890
  static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
6891
  arelent *reloc;
6892
  bfd_reloc_code_real_type code;
6893
  char *type;
6894
  fragS *f;
6895
  symbolS *s;
6896
  expressionS e;
6897
 
6898
  reloc = retval[0] = xmalloc (sizeof (arelent));
6899
  retval[1] = NULL;
6900
 
6901
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6902
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6903
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6904
  reloc->addend = fixp->fx_offset;
6905
 
6906
  /* If this is a variant frag, we may need to adjust the existing
6907
     reloc and generate a new one.  */
6908
  if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6909
    {
6910
      /* Update instruction imm bit.  */
6911
      offsetT newval;
6912
      unsigned short off;
6913
      char *buf;
6914
 
6915
      buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6916
      newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6917
      off = fixp->fx_offset >> 16;
6918
      newval |= (off & 0x3fff) << 1;
6919
      newval |= ((off >> 14) & 0x3) << 16;
6920
      s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6921
 
6922
      buf += s7_INSN_SIZE;
6923
      newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6924
      off = fixp->fx_offset & 0xffff;
6925
      newval |= ((off & 0x3fff) << 1);
6926
      newval |= (((off >> 14) & 0x3) << 16);
6927
      s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6928
 
6929
      retval[1] = xmalloc (sizeof (arelent));
6930
      retval[2] = NULL;
6931
      retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6932
      *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6933
      retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6934
 
6935
      f = fixp->fx_frag;
6936
      s = f->fr_symbol;
6937
      e = s->sy_value;
6938
 
6939
      retval[1]->addend = 0;
6940
      retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6941
      gas_assert (retval[1]->howto != NULL);
6942
 
6943
      fixp->fx_r_type = BFD_RELOC_HI16_S;
6944
    }
6945
 
6946
  code = fixp->fx_r_type;
6947
  switch (fixp->fx_r_type)
6948
    {
6949
    case BFD_RELOC_32:
6950
      if (fixp->fx_pcrel)
6951
        {
6952
          code = BFD_RELOC_32_PCREL;
6953
          break;
6954
        }
6955
    case BFD_RELOC_HI16_S:
6956
    case BFD_RELOC_LO16:
6957
    case BFD_RELOC_SCORE_JMP:
6958
    case BFD_RELOC_SCORE_BRANCH:
6959
    case BFD_RELOC_SCORE16_JMP:
6960
    case BFD_RELOC_SCORE16_BRANCH:
6961
    case BFD_RELOC_VTABLE_ENTRY:
6962
    case BFD_RELOC_VTABLE_INHERIT:
6963
    case BFD_RELOC_SCORE_GPREL15:
6964
    case BFD_RELOC_SCORE_GOT15:
6965
    case BFD_RELOC_SCORE_DUMMY_HI16:
6966
    case BFD_RELOC_SCORE_GOT_LO16:
6967
    case BFD_RELOC_SCORE_CALL15:
6968
    case BFD_RELOC_GPREL32:
6969
    case BFD_RELOC_NONE:
6970
      code = fixp->fx_r_type;
6971
      break;
6972
    default:
6973
      type = _("<unknown>");
6974
      as_bad_where (fixp->fx_file, fixp->fx_line,
6975
                    _("cannot represent %s relocation in this object file format"), type);
6976
      return NULL;
6977
    }
6978
 
6979
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6980
  if (reloc->howto == NULL)
6981
    {
6982
      as_bad_where (fixp->fx_file, fixp->fx_line,
6983
                    _("cannot represent %s relocation in this object file format1"),
6984
                    bfd_get_reloc_code_name (code));
6985
      return NULL;
6986
    }
6987
  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6988
     vtable entry to be used in the relocation's section offset.  */
6989
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6990
    reloc->address = fixp->fx_offset;
6991
 
6992
  return retval;
6993
}

powered by: WebSVN 2.1.0

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