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