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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gas/] [config/] [tc-score7.c] - Blame information for rev 205

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

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

powered by: WebSVN 2.1.0

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