*** 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},
14119072 538 {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, do_rdi16},
1c0d3aa6
NC
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 {
14119072 857 as_warn (_("Using temp register(r1)"));
1c0d3aa6
NC
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 {
14119072 1210 static char err_msg[100];
1c0d3aa6
NC
1211
1212 if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
1213 {
1214 sprintf (err_msg,
14119072 1215 _("invalid constant: %d bit expression not in range %d..%d"),
1c0d3aa6
NC
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,
14119072 1222 _("invalid constant: %d bit expression not in range %d..%d"),
1c0d3aa6
NC
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 {
14119072 1262 static char err_msg[100];
1c0d3aa6 1263
14119072 1264 sprintf (err_msg, _("invalid constant: bit expression not defined"));
1c0d3aa6
NC
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
14119072 1420/* Handle addis/andi/ori/andis/oris/ldis. */
1c0d3aa6
NC
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;
14119072 1431 /*
1c0d3aa6
NC
1432 if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
1433 inst.relax_inst = 0x8000;
1434 else
1435 inst.relax_size = 2;
14119072 1436 */
1c0d3aa6
NC
1437}
1438
1439static void
1440do_macro_rdi32hi (char *str)
1441{
1442 skip_whitespace (str);
1443
1444 /* Do not handle end_of_line(). */
1445 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1446 && skip_past_comma (&str) != (int) FAIL)
1447 data_op2 (&str, 1, _VALUE_HI16);
1448}
1449
1450static void
1451do_macro_rdi32lo (char *str)
1452{
1453 skip_whitespace (str);
1454
1455 /* Do not handle end_of_line(). */
1456 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1457 && skip_past_comma (&str) != (int) FAIL)
1458 data_op2 (&str, 1, _VALUE_LO16);
1459}
1460
1461/* Handle ldis_pic. */
1462
1463static void
1464do_rdi16_pic (char *str)
1465{
1466 skip_whitespace (str);
1467
1468 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1469 && skip_past_comma (&str) != (int) FAIL
1470 && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
1471 end_of_line (str);
1472}
1473
1474/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
1475
1476static void
1477do_addi_s_pic (char *str)
1478{
1479 skip_whitespace (str);
1480
1481 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1482 && skip_past_comma (&str) != (int) FAIL
1483 && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
1484 end_of_line (str);
1485}
1486
1487/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
1488
1489static void
1490do_addi_u_pic (char *str)
1491{
1492 skip_whitespace (str);
1493
1494 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1495 && skip_past_comma (&str) != (int) FAIL
1496 && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
1497 end_of_line (str);
1498}
1499
1500/* Handle mfceh/mfcel/mtceh/mtchl. */
1501
1502static void
1503do_rd (char *str)
1504{
1505 skip_whitespace (str);
1506
1507 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
1508 end_of_line (str);
1509}
1510
1511static void
1512do_rs (char *str)
1513{
1514 skip_whitespace (str);
1515
1516 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1517 || end_of_line (str) == (int) FAIL)
1518 return;
1519
1520 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
1521 {
1522 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
1523 inst.relax_size = 2;
1524 }
1525 else
1526 inst.relax_inst = 0x8000;
1527}
1528
1529static void
1530do_i15 (char *str)
1531{
1532 skip_whitespace (str);
1533
1534 if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
1535 end_of_line (str);
1536}
1537
1538static void
1539do_xi5x (char *str)
1540{
1541 skip_whitespace (str);
1542
1543 if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
1544 return;
1545
1546 if (inst.relax_inst != 0x8000)
1547 {
1548 inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
1549 inst.relax_size = 2;
1550 }
1551}
1552
1553static void
1554do_rdrs (char *str)
1555{
1556 skip_whitespace (str);
1557
1558 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1559 || skip_past_comma (&str) == (int) FAIL
1560 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1561 || end_of_line (str) == (int) FAIL)
1562 return;
1563
1564 if (inst.relax_inst != 0x8000)
1565 {
1566 if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */
1567 {
1568 /* mlfh */
1569 if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1570 {
1571 inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
1572 | (((inst.instruction >> 20) & 0xf) << 8);
1573 inst.relax_size = 2;
1574 }
1575 /* mhfl */
1576 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
1577 {
1578 inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
1579 | (((inst.instruction >> 20) & 0xf) << 8);
1580 inst.relax_size = 2;
1581 }
1582 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1583 {
1584 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1585 | (((inst.instruction >> 20) & 0xf) << 8);
1586 inst.relax_size = 2;
1587 }
1588 else
1589 {
1590 inst.relax_inst = 0x8000;
1591 }
1592 }
1593 else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
1594 {
1595 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
1596 | (((inst.instruction >> 20) & 0xf) << 8);
1597 inst.relax_size = 2;
1598 }
1599 else
1600 {
1601 inst.relax_inst = 0x8000;
1602 }
1603 }
1604}
1605
1606/* Handle mfcr/mtcr. */
1607static void
1608do_rdcrs (char *str)
1609{
1610 skip_whitespace (str);
1611
1612 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1613 && skip_past_comma (&str) != (int) FAIL
1614 && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
1615 end_of_line (str);
1616}
1617
1618/* Handle mfsr/mtsr. */
1619
1620static void
1621do_rdsrs (char *str)
1622{
1623 skip_whitespace (str);
1624
1625 /* mfsr */
1626 if ((inst.instruction & 0xff) == 0x50)
1627 {
1628 if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
1629 && skip_past_comma (&str) != (int) FAIL
1630 && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
1631 end_of_line (str);
1632 }
1633 else
1634 {
1635 if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
1636 && skip_past_comma (&str) != (int) FAIL)
1637 reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
1638 }
1639}
1640
1641/* Handle neg. */
1642
1643static void
1644do_rdxrs (char *str)
1645{
1646 skip_whitespace (str);
1647
1648 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
1649 || skip_past_comma (&str) == (int) FAIL
1650 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1651 || end_of_line (str) == (int) FAIL)
1652 return;
1653
1654 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
1655 && (((inst.instruction >> 20) & 0x10) == 0))
1656 {
1657 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
1658 inst.relax_size = 2;
1659 }
1660 else
1661 inst.relax_inst = 0x8000;
1662}
1663
1664/* Handle cmp.c/cmp<cond>. */
1665static void
1666do_rsrs (char *str)
1667{
1668 skip_whitespace (str);
1669
1670 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1671 || skip_past_comma (&str) == (int) FAIL
1672 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1673 || end_of_line (str) == (int) FAIL)
1674 return;
1675
1676 if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
1677 && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
1678 {
1679 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
1680 inst.relax_size = 2;
1681 }
1682 else
1683 inst.relax_inst = 0x8000;
1684}
1685
1686static void
1687do_ceinst (char *str)
1688{
1689 char *strbak;
1690
1691 strbak = str;
1692 skip_whitespace (str);
1693
1694 if (data_op2 (&str, 20, _IMM5) == (int) FAIL
1695 || skip_past_comma (&str) == (int) FAIL
1696 || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
1697 || skip_past_comma (&str) == (int) FAIL
1698 || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
1699 || skip_past_comma (&str) == (int) FAIL
1700 || data_op2 (&str, 5, _IMM5) == (int) FAIL
1701 || skip_past_comma (&str) == (int) FAIL
1702 || data_op2 (&str, 0, _IMM5) == (int) FAIL
1703 || end_of_line (str) == (int) FAIL)
1704 {
1705 return;
1706 }
1707 else
1708 {
1709 str = strbak;
1710 if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
1711 return;
1712 }
1713}
1714
1715static int
1716reglow_required_here (char **str, int shift)
1717{
1718 static char buff[MAX_LITERAL_POOL_SIZE];
1719 int reg;
1720 char *start = *str;
1721
1722 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1723 {
1724 if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
1725 {
14119072 1726 as_warn (_("Using temp register(r1)"));
1c0d3aa6
NC
1727 inst.bwarn = 1;
1728 }
1729 if (reg < 16)
1730 {
1731 if (shift >= 0)
1732 inst.instruction |= reg << shift;
1733
1734 return reg;
1735 }
1736 }
1737
1738 /* Restore the start point, we may have got a reg of the wrong class. */
1739 *str = start;
1740 sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
1741 inst.error = buff;
1742 return (int) FAIL;
1743}
1744
1745/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */
1746static void
1747do16_rdrs (char *str)
1748{
1749 skip_whitespace (str);
1750
1751 if (reglow_required_here (&str, 8) == (int) FAIL
1752 || skip_past_comma (&str) == (int) FAIL
1753 || reglow_required_here (&str, 4) == (int) FAIL
1754 || end_of_line (str) == (int) FAIL)
1755 {
1756 return;
1757 }
1758 else
1759 {
1760 if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */
1761 {
1762 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
1763 | (((inst.instruction >> 4) & 0xf) << 10);
1764 }
06d2da93
NC
1765 else if ((inst.instruction & 0x700f) == 0x2006) /* not! */
1766 {
1767 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1768 | (((inst.instruction >> 4) & 0xf) << 15);
1769 }
1c0d3aa6
NC
1770 else
1771 {
1772 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1773 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
1774 }
1775 inst.relax_size = 4;
1776 }
1777}
1778
1779static void
1780do16_rs (char *str)
1781{
1782 int rd = 0;
1783
1784 skip_whitespace (str);
1785
1786 if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
1787 || end_of_line (str) == (int) FAIL)
1788 {
1789 return;
1790 }
1791 else
1792 {
1793 inst.relax_inst |= rd << 20;
1794 inst.relax_size = 4;
1795 }
1796}
1797
1798/* Handle br!/brl!. */
1799static void
1800do16_xrs (char *str)
1801{
1802 skip_whitespace (str);
1803
1804 if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
1805 {
1806 return;
1807 }
1808 else
1809 {
1810 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
1811 | (((inst.instruction >> 4) & 0xf) << 15);
1812 inst.relax_size = 4;
1813 }
1814}
1815
1816static int
1817reghigh_required_here (char **str, int shift)
1818{
1819 static char buff[MAX_LITERAL_POOL_SIZE];
1820 int reg;
1821 char *start = *str;
1822
1823 if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
1824 {
1825 if (15 < reg && reg < 32)
1826 {
1827 if (shift >= 0)
1828 inst.instruction |= (reg & 0xf) << shift;
1829
1830 return reg;
1831 }
1832 }
1833
1834 *str = start;
1835 sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
1836 inst.error = buff;
1837 return (int) FAIL;
1838}
1839
1840/* Handle mhfl!. */
1841static void
1842do16_hrdrs (char *str)
1843{
1844 skip_whitespace (str);
1845
1846 if (reghigh_required_here (&str, 8) != (int) FAIL
1847 && skip_past_comma (&str) != (int) FAIL
1848 && reglow_required_here (&str, 4) != (int) FAIL
1849 && end_of_line (str) != (int) FAIL)
1850 {
1851 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
1852 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
1853 inst.relax_size = 4;
1854 }
1855}
1856
1857/* Handle mlfh!. */
1858static void
1859do16_rdhrs (char *str)
1860{
1861 skip_whitespace (str);
1862
1863 if (reglow_required_here (&str, 8) != (int) FAIL
1864 && skip_past_comma (&str) != (int) FAIL
1865 && reghigh_required_here (&str, 4) != (int) FAIL
1866 && end_of_line (str) != (int) FAIL)
1867 {
1868 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
1869 | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
1870 inst.relax_size = 4;
1871 }
1872}
1873
1874/* We need to be able to fix up arbitrary expressions in some statements.
1875 This is so that we can handle symbols that are an arbitrary distance from
1876 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
1877 which returns part of an address in a form which will be valid for
1878 a data instruction. We do this by pushing the expression into a symbol
1879 in the expr_section, and creating a fix for that. */
1880static fixS *
1881fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
1882{
1883 fixS *new_fix;
1884
1885 switch (exp->X_op)
1886 {
1887 case O_constant:
1888 case O_symbol:
1889 case O_add:
1890 case O_subtract:
1891 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
1892 break;
1893 default:
1894 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
1895 break;
1896 }
1897 return new_fix;
1898}
1899
1900static void
1901init_dependency_vector (void)
1902{
1903 int i;
1904
1905 for (i = 0; i < vector_size; i++)
1906 memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
1907
1908 return;
1909}
1910
1911static enum insn_type_for_dependency
1912dependency_type_from_insn (char *insn_name)
1913{
1914 char name[INSN_NAME_LEN];
1915 const struct insn_to_dependency *tmp;
1916
1917 strcpy (name, insn_name);
1918 tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
1919
1920 if (tmp)
1921 return tmp->type;
1922
1923 return D_all_insn;
1924}
1925
1926static int
1927check_dependency (char *pre_insn, char *pre_reg,
1928 char *cur_insn, char *cur_reg, int *warn_or_error)
1929{
1930 int bubbles = 0;
1931 unsigned int i;
1932 enum insn_type_for_dependency pre_insn_type;
1933 enum insn_type_for_dependency cur_insn_type;
1934
1935 pre_insn_type = dependency_type_from_insn (pre_insn);
1936 cur_insn_type = dependency_type_from_insn (cur_insn);
1937
1938 for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
1939 {
1940 if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
1941 && (D_all_insn == data_dependency_table[i].cur_insn_type
1942 || cur_insn_type == data_dependency_table[i].cur_insn_type)
1943 && (strcmp (data_dependency_table[i].pre_reg, "") == 0
1944 || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
1945 && (strcmp (data_dependency_table[i].cur_reg, "") == 0
1946 || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
1947 {
1948 bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
1949 *warn_or_error = data_dependency_table[i].warn_or_error;
1950 break;
1951 }
1952 }
1953
1954 return bubbles;
1955}
1956
1957static void
1958build_one_frag (struct score_it one_inst)
1959{
1960 char *p;
1961 int relaxable_p = g_opt;
1962 int relax_size = 0;
1963
1964 /* Start a new frag if frag_now is not empty. */
1965 if (frag_now_fix () != 0)
1966 {
1967 if (!frag_now->tc_frag_data.is_insn)
1968 frag_wane (frag_now);
1969
1970 frag_new (0);
1971 }
1972 frag_grow (20);
1973
1974 p = frag_more (one_inst.size);
1975 md_number_to_chars (p, one_inst.instruction, one_inst.size);
1976
1977#ifdef OBJ_ELF
1978 dwarf2_emit_insn (one_inst.size);
1979#endif
1980
1981 relaxable_p &= (one_inst.relax_size != 0);
1982 relax_size = relaxable_p ? one_inst.relax_size : 0;
1983
1984 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
1985 RELAX_ENCODE (one_inst.size, one_inst.relax_size,
1986 one_inst.type, 0, 0, relaxable_p),
1987 NULL, 0, NULL);
1988
1989 if (relaxable_p)
1990 md_number_to_chars (p, one_inst.relax_inst, relax_size);
1991}
1992
1993static void
1994handle_dependency (struct score_it *theinst)
1995{
1996 int i;
1997 int warn_or_error = 0; /* warn - 0; error - 1 */
1998 int bubbles = 0;
1999 int remainder_bubbles = 0;
2000 char cur_insn[INSN_NAME_LEN];
2001 char pre_insn[INSN_NAME_LEN];
2002 struct score_it nop_inst;
2003 struct score_it pflush_inst;
2004
2005 nop_inst.instruction = 0x0000;
2006 nop_inst.size = 2;
2007 nop_inst.relax_inst = 0x80008000;
2008 nop_inst.relax_size = 4;
2009 nop_inst.type = NO16_OPD;
2010
2011 pflush_inst.instruction = 0x8000800a;
2012 pflush_inst.size = 4;
2013 pflush_inst.relax_inst = 0x8000;
2014 pflush_inst.relax_size = 0;
2015 pflush_inst.type = NO_OPD;
2016
2017 /* pflush will clear all data dependency. */
2018 if (strcmp (theinst->name, "pflush") == 0)
2019 {
2020 init_dependency_vector ();
2021 return;
2022 }
2023
2024 /* Push current instruction to dependency_vector[0]. */
2025 for (i = vector_size - 1; i > 0; i--)
2026 memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
2027
2028 memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
2029
2030 /* There is no dependency between nop and any instruction. */
2031 if (strcmp (dependency_vector[0].name, "nop") == 0
2032 || strcmp (dependency_vector[0].name, "nop!") == 0)
2033 return;
2034
2035 /* "pce" is defined in insn_to_dependency_table. */
2036#define PCE_NAME "pce"
2037
2038 if (dependency_vector[0].type == Insn_Type_PCE)
2039 strcpy (cur_insn, PCE_NAME);
2040 else
2041 strcpy (cur_insn, dependency_vector[0].name);
2042
2043 for (i = 1; i < vector_size; i++)
2044 {
2045 /* The element of dependency_vector is NULL. */
2046 if (dependency_vector[i].name[0] == '\0')
2047 continue;
2048
2049 if (dependency_vector[i].type == Insn_Type_PCE)
2050 strcpy (pre_insn, PCE_NAME);
2051 else
2052 strcpy (pre_insn, dependency_vector[i].name);
2053
2054 bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
2055 cur_insn, dependency_vector[0].reg, &warn_or_error);
2056 remainder_bubbles = bubbles - i + 1;
2057
2058 if (remainder_bubbles > 0)
2059 {
2060 int j;
2061
2062 if (fix_data_dependency == 1)
2063 {
2064 if (remainder_bubbles <= 2)
2065 {
2066 if (warn_fix_data_dependency)
14119072 2067 as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
1c0d3aa6
NC
2068 dependency_vector[i].name, dependency_vector[i].reg,
2069 dependency_vector[0].name, dependency_vector[0].reg,
2070 remainder_bubbles, bubbles);
2071
2072 for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
2073 memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
2074 sizeof (dependency_vector[j]));
2075
2076 for (j = 1; j <= remainder_bubbles; j++)
2077 {
2078 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2079 /* Insert nop!. */
2080 build_one_frag (nop_inst);
2081 }
2082 }
2083 else
2084 {
2085 if (warn_fix_data_dependency)
14119072 2086 as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
1c0d3aa6
NC
2087 dependency_vector[i].name, dependency_vector[i].reg,
2088 dependency_vector[0].name, dependency_vector[0].reg,
2089 bubbles);
2090
2091 for (j = 1; j < vector_size; j++)
2092 memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
2093
2094 /* Insert pflush. */
2095 build_one_frag (pflush_inst);
2096 }
2097 }
2098 else
2099 {
2100 if (warn_or_error)
2101 {
14119072 2102 as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
1c0d3aa6
NC
2103 dependency_vector[i].name, dependency_vector[i].reg,
2104 dependency_vector[0].name, dependency_vector[0].reg,
2105 remainder_bubbles, bubbles);
2106 }
2107 else
2108 {
14119072 2109 as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
1c0d3aa6
NC
2110 dependency_vector[i].name, dependency_vector[i].reg,
2111 dependency_vector[0].name, dependency_vector[0].reg,
2112 remainder_bubbles, bubbles);
2113 }
2114 }
2115 }
2116 }
2117}
2118
2119static enum insn_class
2120get_insn_class_from_type (enum score_insn_type type)
2121{
2122 enum insn_class retval = (int) FAIL;
2123
2124 switch (type)
2125 {
2126 case Rd_I4:
2127 case Rd_I5:
2128 case Rd_rvalueBP_I5:
2129 case Rd_lvalueBP_I5:
2130 case Rd_I8:
2131 case PC_DISP8div2:
2132 case PC_DISP11div2:
2133 case Rd_Rs:
2134 case Rd_HighRs:
2135 case Rd_lvalueRs:
2136 case Rd_rvalueRs:
2137 case x_Rs:
2138 case Rd_LowRs:
2139 case NO16_OPD:
2140 retval = INSN_CLASS_16;
2141 break;
2142 case Rd_Rs_I5:
2143 case x_Rs_I5:
2144 case x_I5_x:
2145 case Rd_Rs_I14:
2146 case I15:
2147 case Rd_I16:
2148 case Rd_SI16:
2149 case Rd_rvalueRs_SI10:
2150 case Rd_lvalueRs_SI10:
2151 case Rd_rvalueRs_preSI12:
2152 case Rd_rvalueRs_postSI12:
2153 case Rd_lvalueRs_preSI12:
2154 case Rd_lvalueRs_postSI12:
2155 case Rd_Rs_SI14:
2156 case Rd_rvalueRs_SI15:
2157 case Rd_lvalueRs_SI15:
2158 case PC_DISP19div2:
2159 case PC_DISP24div2:
2160 case Rd_Rs_Rs:
2161 case x_Rs_x:
2162 case x_Rs_Rs:
2163 case Rd_Rs_x:
2164 case Rd_x_Rs:
2165 case Rd_x_x:
2166 case OP5_rvalueRs_SI15:
2167 case I5_Rs_Rs_I5_OP5:
2168 case x_rvalueRs_post4:
2169 case Rd_rvalueRs_post4:
2170 case Rd_x_I5:
2171 case Rd_lvalueRs_post4:
2172 case x_lvalueRs_post4:
2173 case Rd_Rs_Rs_imm:
2174 case NO_OPD:
2175 case Rd_lvalue32Rs:
2176 case Rd_rvalue32Rs:
2177 case Insn_GP:
2178 case Insn_PIC:
b138abaa 2179 case Insn_internal:
1c0d3aa6
NC
2180 retval = INSN_CLASS_32;
2181 break;
2182 case Insn_Type_PCE:
2183 retval = INSN_CLASS_PCE;
2184 break;
2185 case Insn_Type_SYN:
2186 retval = INSN_CLASS_SYN;
2187 break;
2188 default:
2189 abort ();
2190 break;
2191 }
2192 return retval;
2193}
2194
2195static unsigned long
2196adjust_paritybit (unsigned long m_code, enum insn_class class)
2197{
2198 unsigned long result = 0;
2199 unsigned long m_code_high = 0;
2200 unsigned long m_code_low = 0;
2201 unsigned long pb_high = 0;
2202 unsigned long pb_low = 0;
2203
2204 if (class == INSN_CLASS_32)
2205 {
2206 pb_high = 0x80000000;
2207 pb_low = 0x00008000;
2208 }
2209 else if (class == INSN_CLASS_16)
2210 {
2211 pb_high = 0;
2212 pb_low = 0;
2213 }
2214 else if (class == INSN_CLASS_PCE)
2215 {
2216 pb_high = 0;
2217 pb_low = 0x00008000;
2218 }
2219 else if (class == INSN_CLASS_SYN)
2220 {
2221 /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
2222 be changed if macro instruction has been expanded. */
2223 pb_high = 0x80000000;
2224 pb_low = 0x00008000;
2225 }
2226 else
2227 {
2228 abort ();
2229 }
2230
2231 m_code_high = m_code & 0x3fff8000;
2232 m_code_low = m_code & 0x00007fff;
2233 result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
2234 return result;
2235
2236}
2237
2238static void
2239gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
2240{
2241 char *p;
2242 bfd_boolean pce_p = FALSE;
2243 int relaxable_p = g_opt;
2244 int relax_size = 0;
2245 struct score_it *inst1 = part_1;
2246 struct score_it *inst2 = part_2;
2247 struct score_it backup_inst1;
2248
2249 pce_p = (inst2) ? TRUE : FALSE;
2250 memcpy (&backup_inst1, inst1, sizeof (struct score_it));
2251
2252 /* Adjust instruction opcode and to be relaxed instruction opcode. */
2253 if (pce_p)
2254 {
2255 backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
2256 | (inst2->instruction & 0x7FFF);
2257 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
2258 backup_inst1.relax_inst = 0x8000;
2259 backup_inst1.size = INSN_SIZE;
2260 backup_inst1.relax_size = 0;
2261 backup_inst1.type = Insn_Type_PCE;
2262 }
2263 else
2264 {
2265 backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
2266 GET_INSN_CLASS (backup_inst1.type));
2267 }
2268
2269 if (backup_inst1.relax_size != 0)
2270 {
2271 enum insn_class tmp;
2272
2273 tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
2274 backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
2275 }
2276
2277 /* Check data dependency. */
2278 handle_dependency (&backup_inst1);
2279
2280 /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
2281 data produced by .ascii etc. Doing this is to make one instruction per frag. */
2282 if (frag_now_fix () != 0)
2283 {
2284 if (!frag_now->tc_frag_data.is_insn)
2285 frag_wane (frag_now);
2286
2287 frag_new (0);
2288 }
2289
2290 /* Here, we must call frag_grow in order to keep the instruction frag type is
2291 rs_machine_dependent.
2292 For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
2293 acturally will call frag_wane.
2294 Calling frag_grow first will create a new frag_now which free size is 20 that is enough
2295 for frag_var. */
2296 frag_grow (20);
2297
2298 p = frag_more (backup_inst1.size);
2299 md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
2300
2301#ifdef OBJ_ELF
2302 dwarf2_emit_insn (backup_inst1.size);
2303#endif
2304
2305 /* Generate fixup structure. */
2306 if (pce_p)
2307 {
2308 if (inst1->reloc.type != BFD_RELOC_NONE)
2309 fix_new_score (frag_now, p - frag_now->fr_literal,
2310 inst1->size, &inst1->reloc.exp,
2311 inst1->reloc.pc_rel, inst1->reloc.type);
2312
2313 if (inst2->reloc.type != BFD_RELOC_NONE)
2314 fix_new_score (frag_now, p - frag_now->fr_literal + 2,
2315 inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
2316 }
2317 else
2318 {
2319 if (backup_inst1.reloc.type != BFD_RELOC_NONE)
2320 fix_new_score (frag_now, p - frag_now->fr_literal,
2321 backup_inst1.size, &backup_inst1.reloc.exp,
2322 backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
2323 }
2324
2325 /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
2326 relaxable_p &= (backup_inst1.relax_size != 0);
2327 relax_size = relaxable_p ? backup_inst1.relax_size : 0;
2328
2329 p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
2330 RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
2331 backup_inst1.type, 0, 0, relaxable_p),
2332 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
2333
2334 if (relaxable_p)
2335 md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
2336
2337 memcpy (inst1, &backup_inst1, sizeof (struct score_it));
2338}
2339
2340static void
2341parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
2342{
2343 char c;
2344 char *p;
2345 char *operator = insnstr;
2346 const struct asm_opcode *opcode;
2347
2348 /* Parse operator and operands. */
2349 skip_whitespace (operator);
2350
2351 for (p = operator; *p != '\0'; p++)
2352 if ((*p == ' ') || (*p == '!'))
2353 break;
2354
2355 if (*p == '!')
2356 p++;
2357
2358 c = *p;
2359 *p = '\0';
2360
2361 opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
2362 *p = c;
2363
2364 memset (&inst, '\0', sizeof (inst));
2365 sprintf (inst.str, "%s", insnstr);
2366 if (opcode)
2367 {
2368 inst.instruction = opcode->value;
2369 inst.relax_inst = opcode->relax_value;
2370 inst.type = opcode->type;
2371 inst.size = GET_INSN_SIZE (inst.type);
2372 inst.relax_size = 0;
2373 inst.bwarn = 0;
2374 sprintf (inst.name, "%s", opcode->template);
2375 strcpy (inst.reg, "");
2376 inst.error = NULL;
2377 inst.reloc.type = BFD_RELOC_NONE;
2378
2379 (*opcode->parms) (p);
2380
2381 /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */
2382 if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
2383 gen_insn_frag (&inst, NULL);
2384 }
2385 else
2386 inst.error = _("unrecognized opcode");
2387}
2388
2389static int
2390append_insn (char *str, bfd_boolean gen_frag_p)
2391{
2392 int retval = SUCCESS;
2393
2394 parse_16_32_inst (str, gen_frag_p);
2395
2396 if (inst.error)
2397 {
2398 retval = (int) FAIL;
14119072 2399 as_bad (_("%s -- `%s'"), inst.error, inst.str);
1c0d3aa6
NC
2400 inst.error = NULL;
2401 }
2402
2403 return retval;
2404}
2405
2406/* Handle mv! reg_high, reg_low;
2407 mv! reg_low, reg_high;
2408 mv! reg_low, reg_low; */
2409static void
2410do16_mv_rdrs (char *str)
2411{
2412 int reg_rd;
2413 int reg_rs;
2414 char *backupstr = NULL;
2415
2416 backupstr = str;
2417 skip_whitespace (str);
2418
2419 if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
2420 || skip_past_comma (&str) == (int) FAIL
2421 || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
2422 || end_of_line (str) == (int) FAIL)
2423 {
2424 return;
2425 }
2426 else
2427 {
2428 /* Case 1 : mv! or mlfh!. */
2429 if (reg_rd < 16)
2430 {
2431 if (reg_rs < 16)
2432 {
2433 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2434 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
2435 inst.relax_size = 4;
2436 }
2437 else
2438 {
2439 char append_str[MAX_LITERAL_POOL_SIZE];
2440
14119072 2441 sprintf (append_str, _("mlfh! %s"), backupstr);
1c0d3aa6
NC
2442 if (append_insn (append_str, TRUE) == (int) FAIL)
2443 return;
2444 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2445 inst.bwarn = -1;
2446 }
2447 }
2448 /* Case 2 : mhfl!. */
2449 else
2450 {
2451 if (reg_rs > 16)
2452 {
2453 SET_INSN_ERROR (BAD_ARGS);
2454 return;
2455 }
2456 else
2457 {
2458 char append_str[MAX_LITERAL_POOL_SIZE];
2459
14119072 2460 sprintf (append_str, _("mhfl! %s"), backupstr);
1c0d3aa6
NC
2461 if (append_insn (append_str, TRUE) == (int) FAIL)
2462 return;
2463
2464 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
2465 inst.bwarn = -1;
2466 }
2467 }
2468 }
2469}
2470
2471static void
2472do16_rdi4 (char *str)
2473{
2474 skip_whitespace (str);
2475
2476 if (reglow_required_here (&str, 8) == (int) FAIL
2477 || skip_past_comma (&str) == (int) FAIL
2478 || data_op2 (&str, 3, _IMM4) == (int) FAIL
2479 || end_of_line (str) == (int) FAIL)
2480 {
2481 return;
2482 }
2483 else
2484 {
2485 if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */
2486 {
2487 if (((inst.instruction >> 3) & 0xf) != 0xf)
2488 {
2489 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2490 | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
2491 inst.relax_size = 4;
2492 }
2493 else
2494 {
2495 inst.relax_inst = 0x8000;
2496 }
2497 }
2498 else
2499 {
2500 if (((inst.instruction >> 3) & 0xf) != 0xf)
2501 {
2502 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2503 | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
2504 inst.relax_size = 4;
2505 }
2506 else
2507 {
2508 inst.relax_inst = 0x8000;
2509 }
2510 }
2511 }
2512}
2513
2514static void
2515do16_rdi5 (char *str)
2516{
2517 skip_whitespace (str);
2518
2519 if (reglow_required_here (&str, 8) == (int) FAIL
2520 || skip_past_comma (&str) == (int) FAIL
2521 || data_op2 (&str, 3, _IMM5) == (int) FAIL
2522 || end_of_line (str) == (int) FAIL)
2523 return;
2524 else
2525 {
2526 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
2527 | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
2528 inst.relax_size = 4;
2529 }
2530}
2531
2532/* Handle sdbbp. */
2533static void
2534do16_xi5 (char *str)
2535{
2536 skip_whitespace (str);
2537
2538 if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
2539 return;
2540 else
2541 {
2542 inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
2543 inst.relax_size = 4;
2544 }
2545}
2546
2547/* Check that an immediate is word alignment or half word alignment.
2548 If so, convert it to the right format. */
2549static int
2550validate_immediate_align (int val, unsigned int data_type)
2551{
2552 if (data_type == _IMM5_RSHIFT_1)
2553 {
2554 if (val % 2)
2555 {
2556 inst.error = _("address offset must be half word alignment");
2557 return (int) FAIL;
2558 }
2559 }
2560 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2561 {
2562 if (val % 4)
2563 {
2564 inst.error = _("address offset must be word alignment");
2565 return (int) FAIL;
2566 }
2567 }
2568
2569 return SUCCESS;
2570}
2571
2572static int
2573exp_ldst_offset (char **str, int shift, unsigned int data_type)
2574{
2575 char *dataptr;
2576
2577 dataptr = * str;
2578
2579 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2580 && (data_type != _SIMM16_LA)
2581 && (data_type != _VALUE_HI16)
2582 && (data_type != _VALUE_LO16)
2583 && (data_type != _IMM16)
2584 && (data_type != _IMM15)
2585 && (data_type != _IMM14)
2586 && (data_type != _IMM4)
2587 && (data_type != _IMM5)
2588 && (data_type != _IMM8)
2589 && (data_type != _IMM5_RSHIFT_1)
2590 && (data_type != _IMM5_RSHIFT_2)
2591 && (data_type != _SIMM14_NEG)
2592 && (data_type != _IMM10_RSHIFT_2))
2593 {
2594 data_type += 24;
2595 }
2596
2597 if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
2598 return (int) FAIL;
2599
2600 if (inst.reloc.exp.X_op == O_constant)
2601 {
2602 /* Need to check the immediate align. */
2603 int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
2604
2605 if (value == (int) FAIL)
2606 return (int) FAIL;
2607
2608 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2609 if (value == (int) FAIL)
2610 {
14119072 2611 static char err_msg[255];
1c0d3aa6
NC
2612
2613 if (data_type < 30)
2614 sprintf (err_msg,
14119072 2615 _("invalid constant: %d bit expression not in range %d..%d"),
1c0d3aa6
NC
2616 score_df_range[data_type].bits,
2617 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2618 else
2619 sprintf (err_msg,
14119072 2620 _("invalid constant: %d bit expression not in range %d..%d"),
1c0d3aa6
NC
2621 score_df_range[data_type - 24].bits,
2622 score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
2623 inst.error = _(err_msg);
2624 return (int) FAIL;
2625 }
2626
2627 if (data_type == _IMM5_RSHIFT_1)
2628 {
2629 value >>= 1;
2630 }
2631 else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
2632 {
2633 value >>= 2;
2634 }
2635
2636 if (score_df_range[data_type].range[0] != 0)
2637 {
2638 value &= (1 << score_df_range[data_type].bits) - 1;
2639 }
2640
2641 inst.instruction |= value << shift;
2642 }
2643 else
2644 {
2645 inst.reloc.pc_rel = 0;
2646 }
2647
2648 return SUCCESS;
2649}
2650
2651static void
2652do_ldst_insn (char *str)
2653{
2654 int pre_inc = 0;
2655 int conflict_reg;
2656 int value;
2657 char * temp;
2658 char *strbak;
2659 char *dataptr;
2660 int reg;
2661 int ldst_idx = 0;
2662
2663 strbak = str;
2664 skip_whitespace (str);
2665
2666 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
2667 || (skip_past_comma (&str) == (int) FAIL))
2668 return;
2669
2670 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
2671 if (*str == '[')
2672 {
2673 str++;
2674 skip_whitespace (str);
2675
2676 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
2677 return;
2678
2679 /* Conflicts can occur on stores as well as loads. */
2680 conflict_reg = (conflict_reg == reg);
2681 skip_whitespace (str);
2682 temp = str + 1; /* The latter will process decimal/hex expression. */
2683
2684 /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
2685 if (*str == ']')
2686 {
2687 str++;
2688 if (*str == '+')
2689 {
2690 str++;
2691 /* ld/sw rD, [rA]+, simm12. */
2692 if (skip_past_comma (&str) == SUCCESS)
2693 {
2694 if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
2695 || (end_of_line (str) == (int) FAIL))
2696 return;
2697
2698 if (conflict_reg)
2699 {
2700 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2701
2702 if ((ldst_func == INSN_LH)
2703 || (ldst_func == INSN_LHU)
2704 || (ldst_func == INSN_LW)
2705 || (ldst_func == INSN_LB)
2706 || (ldst_func == INSN_LBU))
2707 {
2708 inst.error = _("register same as write-back base");
2709 return;
2710 }
2711 }
2712
2713 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2714 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2715 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
2716
2717 /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
2718 if ((inst.instruction & 0x3e000007) == 0x0e000000)
2719 {
2720 /* rs = r0-r7, offset = 4 */
2721 if ((((inst.instruction >> 15) & 0x18) == 0)
2722 && (((inst.instruction >> 3) & 0xfff) == 4))
2723 {
2724 /* Relax to pophi. */
2725 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2726 {
2727 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2728 << 8) | 1 << 7 |
2729 (((inst.instruction >> 15) & 0x7) << 4);
2730 }
2731 /* Relax to pop. */
2732 else
2733 {
2734 inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
2735 << 8) | 0 << 7 |
2736 (((inst.instruction >> 15) & 0x7) << 4);
2737 }
2738 inst.relax_size = 2;
2739 }
2740 }
2741 return;
2742 }
2743 /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
2744 else
2745 {
2746 SET_INSN_ERROR (NULL);
2747 if (end_of_line (str) == (int) FAIL)
2748 {
2749 return;
2750 }
2751
2752 pre_inc = 1;
2753 value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12);
2754 value &= (1 << score_df_range[_SIMM12].bits) - 1;
2755 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2756 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2757 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2758 inst.instruction |= value << 3;
2759 inst.relax_inst = 0x8000;
2760 return;
2761 }
2762 }
2763 /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
2764 else
2765 {
2766 if (end_of_line (str) == (int) FAIL)
2767 return;
2768
2769 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2770 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2771 inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
2772
2773 /* lbu rd, [rs] -> lbu! rd, [rs] */
2774 if (ldst_idx == INSN_LBU)
2775 {
2776 inst.relax_inst = INSN16_LBU;
2777 }
2778 else if (ldst_idx == INSN_LH)
2779 {
2780 inst.relax_inst = INSN16_LH;
2781 }
2782 else if (ldst_idx == INSN_LW)
2783 {
2784 inst.relax_inst = INSN16_LW;
2785 }
2786 else if (ldst_idx == INSN_SB)
2787 {
2788 inst.relax_inst = INSN16_SB;
2789 }
2790 else if (ldst_idx == INSN_SH)
2791 {
2792 inst.relax_inst = INSN16_SH;
2793 }
2794 else if (ldst_idx == INSN_SW)
2795 {
2796 inst.relax_inst = INSN16_SW;
2797 }
2798 else
2799 {
2800 inst.relax_inst = 0x8000;
2801 }
2802
2803 /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
2804 if ((ldst_idx == INSN_LBU)
2805 || (ldst_idx == INSN_LH)
2806 || (ldst_idx == INSN_LW)
2807 || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
2808 {
2809 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2810 {
2811 inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
2812 (((inst.instruction >> 15) & 0xf) << 4);
2813 inst.relax_size = 2;
2814 }
2815 }
2816
2817 return;
2818 }
2819 }
2820 /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
2821 else
2822 {
2823 if (skip_past_comma (&str) == (int) FAIL)
2824 {
2825 inst.error = _("pre-indexed expression expected");
2826 return;
2827 }
2828
2829 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
2830 return;
2831
2832 skip_whitespace (str);
2833 if (*str++ != ']')
2834 {
2835 inst.error = _("missing ]");
2836 return;
2837 }
2838
2839 skip_whitespace (str);
2840 /* ld/sw rD, [rA, simm12]+. */
2841 if (*str == '+')
2842 {
2843 str++;
2844 pre_inc = 1;
2845 if (conflict_reg)
2846 {
2847 unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
2848
2849 if ((ldst_func == INSN_LH)
2850 || (ldst_func == INSN_LHU)
2851 || (ldst_func == INSN_LW)
2852 || (ldst_func == INSN_LB)
2853 || (ldst_func == INSN_LBU))
2854 {
2855 inst.error = _("register same as write-back base");
2856 return;
2857 }
2858 }
2859 }
2860
2861 if (end_of_line (str) == (int) FAIL)
2862 return;
2863
2864 if (inst.reloc.exp.X_op == O_constant)
2865 {
2866 int value;
2867 unsigned int data_type;
2868
2869 if (pre_inc == 1)
2870 data_type = _SIMM12;
2871 else
2872 data_type = _SIMM15;
2873 dataptr = temp;
2874
2875 if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
2876 && (data_type != _SIMM16_LA)
2877 && (data_type != _VALUE_HI16)
2878 && (data_type != _VALUE_LO16)
2879 && (data_type != _IMM16)
2880 && (data_type != _IMM15)
2881 && (data_type != _IMM14)
2882 && (data_type != _IMM4)
2883 && (data_type != _IMM5)
2884 && (data_type != _IMM8)
2885 && (data_type != _IMM5_RSHIFT_1)
2886 && (data_type != _IMM5_RSHIFT_2)
2887 && (data_type != _SIMM14_NEG)
2888 && (data_type != _IMM10_RSHIFT_2))
2889 {
2890 data_type += 24;
2891 }
2892
2893 value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
2894 if (value == (int) FAIL)
2895 {
14119072 2896 static char err_msg[255];
1c0d3aa6 2897
b138abaa 2898 if (data_type < 30)
1c0d3aa6 2899 sprintf (err_msg,
14119072 2900 _("invalid constant: %d bit expression not in range %d..%d"),
1c0d3aa6
NC
2901 score_df_range[data_type].bits,
2902 score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
2903 else
2904 sprintf (err_msg,
14119072 2905 _("invalid constant: %d bit expression not in range %d..%d"),
b138abaa
NC
2906 score_df_range[data_type - 24].bits,
2907 score_df_range[data_type - 24].range[0],
2908 score_df_range[data_type - 24].range[1]);
1c0d3aa6
NC
2909 inst.error = _(err_msg);
2910 return;
2911 }
2912
2913 value &= (1 << score_df_range[data_type].bits) - 1;
2914 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
2915 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
2916 inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
2917 if (pre_inc == 1)
2918 inst.instruction |= value << 3;
2919 else
2920 inst.instruction |= value;
2921
2922 /* lw rD, [rA, simm15] */
2923 if ((inst.instruction & 0x3e000000) == 0x20000000)
2924 {
2925 /* Both rD and rA are in [r0 - r15]. */
2926 if ((((inst.instruction >> 15) & 0x10) == 0)
2927 && (((inst.instruction >> 20) & 0x10) == 0))
2928 {
2929 /* simm15 = 0, lw -> lw!. */
2930 if ((inst.instruction & 0x7fff) == 0)
2931 {
2932 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2933 | (((inst.instruction >> 20) & 0xf) << 8);
2934 inst.relax_size = 2;
2935 }
2936 /* rA = r2, lw -> lwp!. */
2937 else if ((((inst.instruction >> 15) & 0xf) == 2)
2938 && ((inst.instruction & 0x3) == 0)
2939 && ((inst.instruction & 0x7fff) < 128))
2940 {
2941 inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
2942 | (((inst.instruction & 0x7fff) >> 2) << 3);
2943 inst.relax_size = 2;
2944 }
2945 else
2946 {
2947 inst.relax_inst = 0x8000;
2948 }
2949 }
2950 else
2951 {
2952 inst.relax_inst = 0x8000;
2953 }
2954 }
2955 /* sw rD, [rA, simm15] */
2956 else if ((inst.instruction & 0x3e000000) == 0x28000000)
2957 {
2958 /* Both rD and rA are in [r0 - r15]. */
2959 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
2960 {
2961 /* simm15 = 0, sw -> sw!. */
2962 if ((inst.instruction & 0x7fff) == 0)
2963 {
2964 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
2965 | (((inst.instruction >> 20) & 0xf) << 8);
2966 inst.relax_size = 2;
2967 }
2968 /* rA = r2, sw -> swp!. */
2969 else if ((((inst.instruction >> 15) & 0xf) == 2)
2970 && ((inst.instruction & 0x3) == 0)
2971 && ((inst.instruction & 0x7fff) < 128))
2972 {
2973 inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
2974 | (((inst.instruction & 0x7fff) >> 2) << 3);
2975 inst.relax_size = 2;
2976 }
2977 else
2978 {
2979 inst.relax_inst = 0x8000;
2980 }
2981 }
2982 else
2983 {
2984 inst.relax_inst = 0x8000;
2985 }
2986 }
2987 /* sw rD, [rA, simm15]+ sw pre. */
2988 else if ((inst.instruction & 0x3e000007) == 0x06000004)
2989 {
2990 /* rA is in [r0 - r7], and simm15 = -4. */
2991 if ((((inst.instruction >> 15) & 0x18) == 0)
2992 && (((inst.instruction >> 3) & 0xfff) == 0xffc))
2993 {
2994 /* sw -> pushhi!. */
2995 if ((((inst.instruction >> 20) & 0x10) == 0x10))
2996 {
2997 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
2998 | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
2999 inst.relax_size = 2;
3000 }
3001 /* sw -> push!. */
3002 else
3003 {
3004 inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
3005 | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
3006 inst.relax_size = 2;
3007 }
3008 }
3009 else
3010 {
3011 inst.relax_inst = 0x8000;
3012 }
3013 }
3014 /* lh rD, [rA, simm15] */
3015 else if ((inst.instruction & 0x3e000000) == 0x22000000)
3016 {
3017 /* Both rD and rA are in [r0 - r15]. */
3018 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3019 {
3020 /* simm15 = 0, lh -> lh!. */
3021 if ((inst.instruction & 0x7fff) == 0)
3022 {
3023 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3024 | (((inst.instruction >> 20) & 0xf) << 8);
3025 inst.relax_size = 2;
3026 }
3027 /* rA = r2, lh -> lhp!. */
3028 else if ((((inst.instruction >> 15) & 0xf) == 2)
3029 && ((inst.instruction & 0x1) == 0)
3030 && ((inst.instruction & 0x7fff) < 64))
3031 {
3032 inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
3033 | (((inst.instruction & 0x7fff) >> 1) << 3);
3034 inst.relax_size = 2;
3035 }
3036 else
3037 {
3038 inst.relax_inst = 0x8000;
3039 }
3040 }
3041 else
3042 {
3043 inst.relax_inst = 0x8000;
3044 }
3045 }
3046 /* sh rD, [rA, simm15] */
3047 else if ((inst.instruction & 0x3e000000) == 0x2a000000)
3048 {
3049 /* Both rD and rA are in [r0 - r15]. */
3050 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3051 {
3052 /* simm15 = 0, sh -> sh!. */
3053 if ((inst.instruction & 0x7fff) == 0)
3054 {
3055 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3056 | (((inst.instruction >> 20) & 0xf) << 8);
3057 inst.relax_size = 2;
3058 }
3059 /* rA = r2, sh -> shp!. */
3060 else if ((((inst.instruction >> 15) & 0xf) == 2)
3061 && ((inst.instruction & 0x1) == 0)
3062 && ((inst.instruction & 0x7fff) < 64))
3063 {
3064 inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
3065 | (((inst.instruction & 0x7fff) >> 1) << 3);
3066 inst.relax_size = 2;
3067 }
3068 else
3069 {
3070 inst.relax_inst = 0x8000;
3071 }
3072 }
3073 else
3074 {
3075 inst.relax_inst = 0x8000;
3076 }
3077 }
3078 /* lbu rD, [rA, simm15] */
3079 else if ((inst.instruction & 0x3e000000) == 0x2c000000)
3080 {
3081 /* Both rD and rA are in [r0 - r15]. */
3082 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3083 {
3084 /* simm15 = 0, lbu -> lbu!. */
3085 if ((inst.instruction & 0x7fff) == 0)
3086 {
3087 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3088 | (((inst.instruction >> 20) & 0xf) << 8);
3089 inst.relax_size = 2;
3090 }
3091 /* rA = r2, lbu -> lbup!. */
3092 else if ((((inst.instruction >> 15) & 0xf) == 2)
3093 && ((inst.instruction & 0x7fff) < 32))
3094 {
3095 inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
3096 | ((inst.instruction & 0x7fff) << 3);
3097 inst.relax_size = 2;
3098 }
3099 else
3100 {
3101 inst.relax_inst = 0x8000;
3102 }
3103 }
3104 else
3105 {
3106 inst.relax_inst = 0x8000;
3107 }
3108 }
3109 /* sb rD, [rA, simm15] */
3110 else if ((inst.instruction & 0x3e000000) == 0x2e000000)
3111 {
3112 /* Both rD and rA are in [r0 - r15]. */
3113 if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
3114 {
3115 /* simm15 = 0, sb -> sb!. */
3116 if ((inst.instruction & 0x7fff) == 0)
3117 {
3118 inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
3119 | (((inst.instruction >> 20) & 0xf) << 8);
3120 inst.relax_size = 2;
3121 }
3122 /* rA = r2, sb -> sb!. */
3123 else if ((((inst.instruction >> 15) & 0xf) == 2)
3124 && ((inst.instruction & 0x7fff) < 32))
3125 {
3126 inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
3127 | ((inst.instruction & 0x7fff) << 3);
3128 inst.relax_size = 2;
3129 }
3130 else
3131 {
3132 inst.relax_inst = 0x8000;
3133 }
3134 }
3135 else
3136 {
3137 inst.relax_inst = 0x8000;
3138 }
3139 }
3140 else
3141 {
3142 inst.relax_inst = 0x8000;
3143 }
3144
3145 return;
3146 }
3147 else
3148 {
3149 /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3150 inst.reloc.pc_rel = 0;
3151 }
3152 }
3153 }
3154 else
3155 {
3156 inst.error = BAD_ARGS;
3157 }
3158}
3159
3160/* Handle cache. */
3161
3162static void
3163do_cache (char *str)
3164{
3165 skip_whitespace (str);
3166
3167 if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3168 {
3169 return;
3170 }
3171 else
3172 {
3173 int cache_op;
3174
3175 cache_op = (inst.instruction >> 20) & 0x1F;
14119072 3176 sprintf (inst.name, _("cache %d"), cache_op);
1c0d3aa6
NC
3177 }
3178
3179 if (*str == '[')
3180 {
3181 str++;
3182 skip_whitespace (str);
3183
3184 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3185 return;
3186
3187 skip_whitespace (str);
3188
3189 /* cache op, [rA] */
3190 if (skip_past_comma (&str) == (int) FAIL)
3191 {
3192 SET_INSN_ERROR (NULL);
3193 if (*str != ']')
3194 {
3195 inst.error = _("missing ]");
3196 return;
3197 }
3198 str++;
3199 }
3200 /* cache op, [rA, simm15] */
3201 else
3202 {
3203 if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
3204 {
3205 return;
3206 }
3207
3208 skip_whitespace (str);
3209 if (*str++ != ']')
3210 {
3211 inst.error = _("missing ]");
3212 return;
3213 }
3214 }
3215
3216 if (end_of_line (str) == (int) FAIL)
3217 return;
3218 }
3219 else
3220 {
3221 inst.error = BAD_ARGS;
3222 }
3223}
3224
3225static void
3226do_crdcrscrsimm5 (char *str)
3227{
3228 char *strbak;
3229
3230 strbak = str;
3231 skip_whitespace (str);
3232
3233 if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
3234 || skip_past_comma (&str) == (int) FAIL
3235 || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
3236 || skip_past_comma (&str) == (int) FAIL
3237 || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
3238 || skip_past_comma (&str) == (int) FAIL)
3239 {
3240 str = strbak;
3241 /* cop1 cop_code20. */
3242 if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
3243 return;
3244 }
3245 else
3246 {
3247 if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
3248 return;
3249 }
3250
3251 end_of_line (str);
3252}
3253
3254/* Handle ldc/stc. */
3255static void
3256do_ldst_cop (char *str)
3257{
3258 skip_whitespace (str);
3259
3260 if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
3261 || (skip_past_comma (&str) == (int) FAIL))
3262 return;
3263
3264 if (*str == '[')
3265 {
3266 str++;
3267 skip_whitespace (str);
3268
3269 if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3270 return;
3271
3272 skip_whitespace (str);
3273
3274 if (*str++ != ']')
3275 {
3276 if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
3277 return;
3278
3279 skip_whitespace (str);
3280 if (*str++ != ']')
3281 {
3282 inst.error = _("missing ]");
3283 return;
3284 }
3285 }
3286
3287 end_of_line (str);
3288 }
3289 else
3290 inst.error = BAD_ARGS;
3291}
3292
3293static void
3294do16_ldst_insn (char *str)
3295{
3296 skip_whitespace (str);
3297
3298 if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
3299 return;
3300
3301 if (*str == '[')
3302 {
3303 int reg;
3304
3305 str++;
3306 skip_whitespace (str);
3307
3308 if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
3309 return;
3310
3311 skip_whitespace (str);
3312 if (*str++ == ']')
3313 {
3314 if (end_of_line (str) == (int) FAIL)
3315 return;
3316 else
3317 {
3318 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3319 | (((inst.instruction >> 4) & 0xf) << 15);
3320 inst.relax_size = 4;
3321 }
3322 }
3323 else
3324 {
3325 inst.error = _("missing ]");
3326 }
3327 }
3328 else
3329 {
3330 inst.error = BAD_ARGS;
3331 }
3332}
3333
3334/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */
3335static void
3336do16_ldst_imm_insn (char *str)
3337{
3338 char data_exp[MAX_LITERAL_POOL_SIZE];
3339 int reg_rd;
3340 char *dataptr = NULL, *pp = NULL;
3341 int cnt = 0;
3342 int assign_data = (int) FAIL;
3343 unsigned int ldst_func;
3344
3345 skip_whitespace (str);
3346
3347 if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
3348 || (skip_past_comma (&str) == (int) FAIL))
3349 return;
3350
3351 skip_whitespace (str);
3352 dataptr = str;
3353
3354 while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
3355 {
3356 data_exp[cnt] = *dataptr;
3357 dataptr++;
3358 cnt++;
3359 }
3360
3361 data_exp[cnt] = '\0';
3362 pp = &data_exp[0];
3363
3364 str = dataptr;
3365
3366 ldst_func = inst.instruction & LDST16_RI_MASK;
3367 if (ldst_func == N16_LIU)
3368 assign_data = exp_ldst_offset (&pp, 0, _IMM8);
3369 else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3370 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3371 else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3372 assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3373 else
3374 assign_data = exp_ldst_offset (&pp, 3, _IMM5);
3375
3376 if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
3377 return;
3378 else
3379 {
3380 if ((inst.instruction & 0x7000) == N16_LIU)
3381 {
3382 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
3383 | ((inst.instruction & 0xff) << 1);
3384 }
3385 else if (((inst.instruction & 0x7007) == N16_LHP)
3386 || ((inst.instruction & 0x7007) == N16_SHP))
3387 {
3388 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3389 | (((inst.instruction >> 3) & 0x1f) << 1);
3390 }
3391 else if (((inst.instruction & 0x7007) == N16_LWP)
3392 || ((inst.instruction & 0x7007) == N16_SWP))
3393 {
3394 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3395 | (((inst.instruction >> 3) & 0x1f) << 2);
3396 }
3397 else if (((inst.instruction & 0x7007) == N16_LBUP)
3398 || ((inst.instruction & 0x7007) == N16_SBP))
3399 {
3400 inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3401 | (((inst.instruction >> 3) & 0x1f));
3402 }
3403
3404 inst.relax_size = 4;
3405 }
3406}
3407
3408static void
3409do16_push_pop (char *str)
3410{
3411 int reg_rd;
3412 int H_bit_mask = 0;
3413
3414 skip_whitespace (str);
3415 if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
3416 || (skip_past_comma (&str) == (int) FAIL))
3417 return;
3418
3419 if (reg_rd >= 16)
3420 H_bit_mask = 1;
3421
3422 /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */
3423 inst.instruction &= ~(1 << 12);
3424
3425 inst.instruction |= H_bit_mask << 7;
3426
3427 if (*str == '[')
3428 {
3429 int reg;
3430
3431 str++;
3432 skip_whitespace (str);
3433 if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
3434 return;
3435 else if (reg > 7)
3436 {
3437 if (!inst.error)
3438 inst.error = _("base register nums are over 3 bit");
3439
3440 return;
3441 }
3442
3443 skip_whitespace (str);
3444 if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
3445 {
3446 if (!inst.error)
3447 inst.error = _("missing ]");
3448
3449 return;
3450 }
3451
3452 /* pop! */
3453 if ((inst.instruction & 0xf) == 0xa)
3454 {
3455 if (H_bit_mask)
3456 {
3457 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3458 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3459 }
3460 else
3461 {
3462 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3463 | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3464 }
3465 }
3466 /* push! */
3467 else
3468 {
3469 if (H_bit_mask)
3470 {
3471 inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
3472 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3473 }
3474 else
3475 {
3476 inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
3477 | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3478 }
3479 }
3480 inst.relax_size = 4;
3481 }
3482 else
3483 {
3484 inst.error = BAD_ARGS;
3485 }
3486}
3487
3488/* Handle lcb/lcw/lce/scb/scw/sce. */
3489static void
3490do_ldst_unalign (char *str)
3491{
3492 int conflict_reg;
3493
3494 if (university_version == 1)
3495 {
3496 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3497 return;
3498 }
3499
3500 skip_whitespace (str);
3501
3502 /* lcb/scb [rA]+. */
3503 if (*str == '[')
3504 {
3505 str++;
3506 skip_whitespace (str);
3507
3508 if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
3509 return;
3510
3511 if (*str++ == ']')
3512 {
3513 if (*str++ != '+')
3514 {
3515 inst.error = _("missing +");
3516 return;
3517 }
3518 }
3519 else
3520 {
3521 inst.error = _("missing ]");
3522 return;
3523 }
3524
3525 if (end_of_line (str) == (int) FAIL)
3526 return;
3527 }
3528 /* lcw/lce/scb/sce rD, [rA]+. */
3529 else
3530 {
3531 if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
3532 || (skip_past_comma (&str) == (int) FAIL))
3533 {
3534 return;
3535 }
3536
3537 skip_whitespace (str);
3538 if (*str++ == '[')
3539 {
3540 int reg;
3541
3542 skip_whitespace (str);
3543 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3544 {
3545 return;
3546 }
3547
3548 /* Conflicts can occur on stores as well as loads. */
3549 conflict_reg = (conflict_reg == reg);
3550 skip_whitespace (str);
3551 if (*str++ == ']')
3552 {
3553 unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
3554
3555 if (*str++ == '+')
3556 {
3557 if (conflict_reg)
3558 {
3559 as_warn (_("%s register same as write-back base"),
3560 ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
3561 ? _("destination") : _("source")));
3562 }
3563 }
3564 else
3565 {
3566 inst.error = _("missing +");
3567 return;
3568 }
3569
3570 if (end_of_line (str) == (int) FAIL)
3571 return;
3572 }
3573 else
3574 {
3575 inst.error = _("missing ]");
3576 return;
3577 }
3578 }
3579 else
3580 {
3581 inst.error = BAD_ARGS;
3582 return;
3583 }
3584 }
3585}
3586
3587/* Handle alw/asw. */
3588static void
3589do_ldst_atomic (char *str)
3590{
3591 if (university_version == 1)
3592 {
3593 inst.error = ERR_FOR_SCORE5U_ATOMIC;
3594 return;
3595 }
3596
3597 skip_whitespace (str);
3598
3599 if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
3600 || (skip_past_comma (&str) == (int) FAIL))
3601 {
3602 return;
3603 }
3604 else
3605 {
3606
3607 skip_whitespace (str);
3608 if (*str++ == '[')
3609 {
3610 int reg;
3611
3612 skip_whitespace (str);
3613 if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
3614 {
3615 return;
3616 }
3617
3618 skip_whitespace (str);
3619 if (*str++ != ']')
3620 {
3621 inst.error = _("missing ]");
3622 return;
3623 }
3624
3625 end_of_line (str);
3626 }
3627 else
3628 inst.error = BAD_ARGS;
3629 }
3630}
3631
3632static void
3633build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
3634 struct score_it var_insts[RELAX_INST_NUM], int var_num,
3635 symbolS *add_symbol)
3636{
3637 int i;
3638 char *p;
3639 fixS *fixp = NULL;
b3549761 3640 fixS *cur_fixp = NULL;
1c0d3aa6
NC
3641 long where;
3642 struct score_it inst_main;
3643
3644 memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
3645
3646 /* Adjust instruction opcode and to be relaxed instruction opcode. */
3647 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
3648 inst_main.type = Insn_PIC;
3649
3650 for (i = 0; i < var_num; i++)
3651 {
3652 inst_main.relax_size += var_insts[i].size;
3653 var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
3654 GET_INSN_CLASS (var_insts[i].type));
3655 }
3656
3657 /* Check data dependency. */
3658 handle_dependency (&inst_main);
3659
3660 /* Start a new frag if frag_now is not empty. */
3661 if (frag_now_fix () != 0)
3662 {
3663 if (!frag_now->tc_frag_data.is_insn)
3664 {
3665 frag_wane (frag_now);
3666 }
3667 frag_new (0);
3668 }
3669 frag_grow (20);
3670
3671 /* Write fr_fix part. */
3672 p = frag_more (inst_main.size);
3673 md_number_to_chars (p, inst_main.instruction, inst_main.size);
3674
3675 if (inst_main.reloc.type != BFD_RELOC_NONE)
b3549761
NC
3676 fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
3677 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
1c0d3aa6 3678
b3549761
NC
3679 frag_now->tc_frag_data.fixp = fixp;
3680 cur_fixp = frag_now->tc_frag_data.fixp;
1c0d3aa6
NC
3681
3682#ifdef OBJ_ELF
3683 dwarf2_emit_insn (inst_main.size);
3684#endif
3685
3686 where = p - frag_now->fr_literal + inst_main.size;
3687 for (i = 0; i < var_num; i++)
3688 {
3689 if (i > 0)
3690 where += var_insts[i - 1].size;
3691
3692 if (var_insts[i].reloc.type != BFD_RELOC_NONE)
3693 {
3694 fixp = fix_new_score (frag_now, where, var_insts[i].size,
3695 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
3696 var_insts[i].reloc.type);
3697 if (fixp)
3698 {
b3549761
NC
3699 if (cur_fixp)
3700 {
3701 cur_fixp->fx_next = fixp;
3702 cur_fixp = cur_fixp->fx_next;
3703 }
3704 else
3705 {
3706 frag_now->tc_frag_data.fixp = fixp;
3707 cur_fixp = frag_now->tc_frag_data.fixp;
3708 }
1c0d3aa6
NC
3709 }
3710 }
3711 }
3712
1c0d3aa6
NC
3713 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
3714 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
3715 0, inst_main.size, 0), add_symbol, 0, NULL);
3716
3717 /* Write fr_var part.
3718 no calling gen_insn_frag, no fixS will be generated. */
3719 for (i = 0; i < var_num; i++)
3720 {
3721 md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
3722 p += var_insts[i].size;
3723 }
3724 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3725 inst.bwarn = -1;
3726}
3727
3728/* Build a relax frag for la instruction when generating PIC,
3729 external symbol first and local symbol second. */
3730
3731static void
3732build_la_pic (int reg_rd, expressionS exp)
3733{
3734 symbolS *add_symbol = exp.X_add_symbol;
3735 offsetT add_number = exp.X_add_number;
3736 struct score_it fix_insts[RELAX_INST_NUM];
3737 struct score_it var_insts[RELAX_INST_NUM];
3738 int fix_num = 0;
3739 int var_num = 0;
3740 char tmp[MAX_LITERAL_POOL_SIZE];
3741 int r1_bak;
3742
3743 r1_bak = nor1;
3744 nor1 = 0;
3745
3746 if (add_number == 0)
3747 {
3748 fix_num = 1;
3749 var_num = 2;
3750
8fce5f8c
ML
3751 /* For an external symbol, only one insn is generated;
3752 For a local symbol, two insns are generated. */
1c0d3aa6 3753 /* Fix part
8fce5f8c 3754 For an external symbol: lw rD, <sym>($gp)
1c0d3aa6 3755 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
14119072 3756 sprintf (tmp, _("lw_pic r%d, %s"), reg_rd, add_symbol->bsym->name);
1c0d3aa6
NC
3757 if (append_insn (tmp, FALSE) == (int) FAIL)
3758 return;
3759
3760 if (reg_rd == PIC_CALL_REG)
3761 inst.reloc.type = BFD_RELOC_SCORE_CALL15;
3762 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3763
3764 /* Var part
3765 For a local symbol :
3766 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
3767 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
3768 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
3769 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
14119072 3770 sprintf (tmp, _("addi_s_pic r%d, %s"), reg_rd, add_symbol->bsym->name);
1c0d3aa6
NC
3771 if (append_insn (tmp, FALSE) == (int) FAIL)
3772 return;
3773
3774 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
3775 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3776 }
3777 else if (add_number >= -0x8000 && add_number <= 0x7fff)
3778 {
3779 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
14119072 3780 sprintf (tmp, _("lw_pic r%d, %s"), reg_rd, add_symbol->bsym->name);
1c0d3aa6
NC
3781 if (append_insn (tmp, TRUE) == (int) FAIL)
3782 return;
3783
3784 /* Insn 2 */
3785 fix_num = 1;
3786 var_num = 1;
3787 /* Fix part
3788 For an external symbol: addi rD, <constant> */
14119072 3789 sprintf (tmp, _("addi r%d, %d"), reg_rd, (int)add_number);
1c0d3aa6
NC
3790 if (append_insn (tmp, FALSE) == (int) FAIL)
3791 return;
3792
3793 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3794
3795 /* Var part
3796 For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
14119072 3797 sprintf (tmp, _("addi_s_pic r%d, %s + %d"), reg_rd, add_symbol->bsym->name, (int)add_number);
1c0d3aa6
NC
3798 if (append_insn (tmp, FALSE) == (int) FAIL)
3799 return;
3800
3801 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3802 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3803 }
3804 else
3805 {
3806 int hi = (add_number >> 16) & 0x0000FFFF;
3807 int lo = add_number & 0x0000FFFF;
3808
3809 /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
14119072 3810 sprintf (tmp, _("lw_pic r%d, %s"), reg_rd, add_symbol->bsym->name);
1c0d3aa6
NC
3811 if (append_insn (tmp, TRUE) == (int) FAIL)
3812 return;
3813
3814 /* Insn 2 */
3815 fix_num = 1;
3816 var_num = 1;
3817 /* Fix part
3818 For an external symbol: ldis r1, HI%<constant> */
14119072 3819 sprintf (tmp, _("ldis %s, %d"), _("r1"), hi);
1c0d3aa6
NC
3820 if (append_insn (tmp, FALSE) == (int) FAIL)
3821 return;
3822
3823 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3824
3825 /* Var part
3826 For a local symbol: ldis r1, HI%<constant>
3827 but, if lo is outof 16 bit, make hi plus 1 */
3828 if ((lo < -0x8000) || (lo > 0x7fff))
3829 {
3830 hi += 1;
3831 }
14119072 3832 sprintf (tmp, _("ldis_pic %s, %d"), _("r1"), hi);
1c0d3aa6
NC
3833 if (append_insn (tmp, FALSE) == (int) FAIL)
3834 return;
3835
3836 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3837 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3838
3839 /* Insn 3 */
3840 fix_num = 1;
3841 var_num = 1;
3842 /* Fix part
3843 For an external symbol: ori r1, LO%<constant> */
14119072 3844 sprintf (tmp, _("ori %s, %d"), _("r1"), lo);
1c0d3aa6
NC
3845 if (append_insn (tmp, FALSE) == (int) FAIL)
3846 return;
3847
3848 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
3849
3850 /* Var part
3851 For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
14119072 3852 sprintf (tmp, _("addi_u_pic %s, %s + %d"), _("r1"), add_symbol->bsym->name, lo);
1c0d3aa6
NC
3853 if (append_insn (tmp, FALSE) == (int) FAIL)
3854 return;
3855
3856 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
3857 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
3858
3859 /* Insn 4: add rD, rD, r1 */
14119072 3860 sprintf (tmp, _("add r%d, r%d, %s"), reg_rd, reg_rd, _("r1"));
1c0d3aa6
NC
3861 if (append_insn (tmp, TRUE) == (int) FAIL)
3862 return;
3863
3864 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3865 inst.bwarn = -1;
3866 }
3867
3868 nor1 = r1_bak;
3869}
3870
3871/* Handle la. */
3872static void
3873do_macro_la_rdi32 (char *str)
3874{
3875 int reg_rd;
3876
3877 skip_whitespace (str);
3878 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3879 || skip_past_comma (&str) == (int) FAIL)
3880 {
3881 return;
3882 }
3883 else
3884 {
3885 char append_str[MAX_LITERAL_POOL_SIZE];
3886 char *keep_data = str;
3887
3888 /* la rd, simm16. */
3889 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3890 {
3891 end_of_line (str);
3892 return;
3893 }
3894 /* la rd, imm32 or la rd, label. */
3895 else
3896 {
3897 SET_INSN_ERROR (NULL);
3898 str = keep_data;
3899 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3900 || (end_of_line (str) == (int) FAIL))
3901 {
3902 return;
3903 }
3904 else
3905 {
3906 if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
14119072
ML
3907 {
3908 sprintf (append_str, _("ld_i32hi r%d, %s"), reg_rd, keep_data);
3909 if (append_insn (append_str, TRUE) == (int) FAIL)
1c0d3aa6
NC
3910 return;
3911
14119072
ML
3912 sprintf (append_str, _("ld_i32lo r%d, %s"), reg_rd, keep_data);
3913 if (append_insn (append_str, TRUE) == (int) FAIL)
1c0d3aa6
NC
3914 return;
3915 }
3916 else
3917 {
3918 assert (inst.reloc.exp.X_add_symbol);
3919 build_la_pic (reg_rd, inst.reloc.exp);
3920 }
3921
3922 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3923 inst.bwarn = -1;
3924 }
3925 }
3926 }
3927}
3928
3929/* Handle li. */
3930static void
3931do_macro_li_rdi32 (char *str){
3932
3933 int reg_rd;
3934
3935 skip_whitespace (str);
3936 if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
3937 || skip_past_comma (&str) == (int) FAIL)
3938 {
3939 return;
3940 }
3941 else
3942 {
3943 char *keep_data = str;
3944
3945 /* li rd, simm16. */
3946 if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
3947 {
3948 end_of_line (str);
3949 return;
3950 }
3951 /* li rd, imm32. */
3952 else
3953 {
3954 char append_str[MAX_LITERAL_POOL_SIZE];
3955
3956 str = keep_data;
3957
3958 if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
3959 || (end_of_line (str) == (int) FAIL))
3960 {
3961 return;
3962 }
3963 else if (inst.reloc.exp.X_add_symbol)
3964 {
3965 inst.error = _("li rd label isn't correct instruction form");
3966 return;
3967 }
3968 else
3969 {
14119072 3970 sprintf (append_str, _("ld_i32hi r%d, %s"), reg_rd, keep_data);
1c0d3aa6
NC
3971
3972 if (append_insn (append_str, TRUE) == (int) FAIL)
3973 return;
3974 else
3975 {
14119072 3976 sprintf (append_str, _("ld_i32lo r%d, %s"), reg_rd, keep_data);
1c0d3aa6
NC
3977 if (append_insn (append_str, TRUE) == (int) FAIL)
3978 return;
3979
3980 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
3981 inst.bwarn = -1;
3982 }
3983 }
3984 }
3985 }
3986}
3987
3988/* Handle mul/mulu/div/divu/rem/remu. */
3989static void
3990do_macro_mul_rdrsrs (char *str)
3991{
3992 int reg_rd;
3993 int reg_rs1;
3994 int reg_rs2;
3995 char *backupstr;
3996 char append_str[MAX_LITERAL_POOL_SIZE];
3997
3998 if (university_version == 1)
3999 as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
4000
4001 strcpy (append_str, str);
4002 backupstr = append_str;
4003 skip_whitespace (backupstr);
4004 if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4005 || (skip_past_comma (&backupstr) == (int) FAIL)
4006 || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
4007 {
4008 inst.error = BAD_ARGS;
4009 return;
4010 }
4011
4012 if (skip_past_comma (&backupstr) == (int) FAIL)
4013 {
4014 /* rem/remu rA, rB is error format. */
4015 if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
4016 {
4017 SET_INSN_ERROR (BAD_ARGS);
4018 }
4019 else
4020 {
4021 SET_INSN_ERROR (NULL);
4022 do_rsrs (str);
4023 }
4024 return;
4025 }
4026 else
4027 {
4028 SET_INSN_ERROR (NULL);
4029 if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4030 || (end_of_line (backupstr) == (int) FAIL))
4031 {
4032 return;
4033 }
4034 else
4035 {
4036 char append_str1[MAX_LITERAL_POOL_SIZE];
4037
4038 if (strcmp (inst.name, "rem") == 0)
4039 {
14119072
ML
4040 sprintf (append_str, _("%s r%d, r%d"), _("mul"), reg_rs1, reg_rs2);
4041 sprintf (append_str1, _("mfceh r%d"), reg_rd);
1c0d3aa6
NC
4042 }
4043 else if (strcmp (inst.name, "remu") == 0)
4044 {
14119072
ML
4045 sprintf (append_str, _("%s r%d, r%d"), _("mulu"), reg_rs1, reg_rs2);
4046 sprintf (append_str1, _("mfceh r%d"), reg_rd);
1c0d3aa6
NC
4047 }
4048 else
4049 {
14119072
ML
4050 sprintf (append_str, _("%s r%d, r%d"), inst.name, reg_rs1, reg_rs2);
4051 sprintf (append_str1, _("mfcel r%d"), reg_rd);
1c0d3aa6
NC
4052 }
4053
4054 /* Output mul/mulu or div/divu or rem/remu. */
4055 if (append_insn (append_str, TRUE) == (int) FAIL)
4056 return;
4057
4058 /* Output mfcel or mfceh. */
4059 if (append_insn (append_str1, TRUE) == (int) FAIL)
4060 return;
4061
4062 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4063 inst.bwarn = -1;
4064 }
4065 }
4066}
4067
4068static void
4069exp_macro_ldst_abs (char *str)
4070{
4071 int reg_rd;
4072 char *backupstr, *tmp;
4073 char append_str[MAX_LITERAL_POOL_SIZE];
4074 char verifystr[MAX_LITERAL_POOL_SIZE];
4075 struct score_it inst_backup;
4076 int r1_bak = 0;
4077
4078 r1_bak = nor1;
4079 nor1 = 0;
4080 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4081
4082 strcpy (verifystr, str);
4083 backupstr = verifystr;
4084 skip_whitespace (backupstr);
4085 if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
4086 return;
4087
4088 tmp = backupstr;
4089 if (skip_past_comma (&backupstr) == (int) FAIL)
4090 return;
4091
4092 backupstr = tmp;
14119072 4093 sprintf (append_str, _("li r1 %s"), backupstr);
1c0d3aa6
NC
4094 append_insn (append_str, TRUE);
4095
4096 memcpy (&inst, &inst_backup, sizeof (struct score_it));
14119072 4097 sprintf (append_str, _(" r%d, [r1,0]"), reg_rd);
1c0d3aa6
NC
4098 do_ldst_insn (append_str);
4099
4100 nor1 = r1_bak;
4101}
4102
4103static int
4104nopic_need_relax (symbolS * sym, int before_relaxing)
4105{
4106 if (sym == NULL)
4107 return 0;
4108 else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
4109 {
4110 const char *symname;
4111 const char *segname;
4112
4113 /* Find out whether this symbol can be referenced off the $gp
4114 register. It can be if it is smaller than the -G size or if
4115 it is in the .sdata or .sbss section. Certain symbols can
4116 not be referenced off the $gp, although it appears as though
4117 they can. */
4118 symname = S_GET_NAME (sym);
4119 if (symname != (const char *)NULL
4120 && (strcmp (symname, "eprol") == 0
4121 || strcmp (symname, "etext") == 0
4122 || strcmp (symname, "_gp") == 0
4123 || strcmp (symname, "edata") == 0
4124 || strcmp (symname, "_fbss") == 0
4125 || strcmp (symname, "_fdata") == 0
4126 || strcmp (symname, "_ftext") == 0
4127 || strcmp (symname, "end") == 0
4128 || strcmp (symname, GP_DISP_LABEL) == 0))
4129 {
4130 return 1;
4131 }
4132 else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4133 /* We must defer this decision until after the whole file has been read,
4134 since there might be a .extern after the first use of this symbol. */
4135 || (before_relaxing
4136 && S_GET_VALUE (sym) == 0)
4137 || (S_GET_VALUE (sym) != 0
4138 && S_GET_VALUE (sym) <= g_switch_value)))
4139 {
4140 return 0;
4141 }
4142
4143 segname = segment_name (S_GET_SEGMENT (sym));
4144 return (strcmp (segname, ".sdata") != 0
4145 && strcmp (segname, ".sbss") != 0
4146 && strncmp (segname, ".sdata.", 7) != 0
4147 && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4148 }
4149 /* We are not optimizing for the $gp register. */
4150 else
4151 return 1;
4152}
4153
8fce5f8c 4154/* Build a relax frag for lw/st instruction when generating PIC,
1c0d3aa6
NC
4155 external symbol first and local symbol second. */
4156
4157static void
8fce5f8c 4158build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
1c0d3aa6
NC
4159{
4160 symbolS *add_symbol = exp.X_add_symbol;
4161 int add_number = exp.X_add_number;
4162 struct score_it fix_insts[RELAX_INST_NUM];
4163 struct score_it var_insts[RELAX_INST_NUM];
4164 int fix_num = 0;
4165 int var_num = 0;
4166 char tmp[MAX_LITERAL_POOL_SIZE];
4167 int r1_bak;
4168
4169 r1_bak = nor1;
4170 nor1 = 0;
4171
4172 if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4173 {
4174 fix_num = 1;
4175 var_num = 2;
4176
8fce5f8c
ML
4177 /* For an external symbol, two insns are generated;
4178 For a local symbol, three insns are generated. */
1c0d3aa6 4179 /* Fix part
8fce5f8c 4180 For an external symbol: lw rD, <sym>($gp)
1c0d3aa6 4181 (BFD_RELOC_SCORE_GOT15) */
14119072 4182 sprintf (tmp, _("lw_pic %s, %s"), _("r1"), add_symbol->bsym->name);
1c0d3aa6 4183 if (append_insn (tmp, FALSE) == (int) FAIL)
8fce5f8c 4184 return;
1c0d3aa6
NC
4185
4186 memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
4187
4188 /* Var part
4189 For a local symbol :
4190 lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
4191 addi rD, <sym> (BFD_RELOC_GOT_LO16) */
4192 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4193 memcpy (&var_insts[0], &inst, sizeof (struct score_it));
14119072 4194 sprintf (tmp, _("addi_s_pic %s, %s"), _("r1"), add_symbol->bsym->name);
1c0d3aa6 4195 if (append_insn (tmp, FALSE) == (int) FAIL)
8fce5f8c 4196 return;
1c0d3aa6
NC
4197
4198 memcpy (&var_insts[1], &inst, sizeof (struct score_it));
4199 build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4200
8fce5f8c 4201 /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
14119072 4202 sprintf (tmp, _("%s r%d, [%s, %d]"), insn_name, reg_rd, _("r1"), add_number);
1c0d3aa6 4203 if (append_insn (tmp, TRUE) == (int) FAIL)
8fce5f8c 4204 return;
1c0d3aa6 4205
8fce5f8c
ML
4206 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4207 inst.bwarn = -1;
1c0d3aa6
NC
4208 }
4209 else
4210 {
8fce5f8c
ML
4211 inst.error = _("PIC code offset overflow (max 16 signed bits)");
4212 return;
1c0d3aa6
NC
4213 }
4214
4215 nor1 = r1_bak;
4216}
4217
4218static void
4219do_macro_ldst_label (char *str)
4220{
4221 int i;
4222 int ldst_gp_p = 0;
4223 int reg_rd;
4224 int r1_bak;
4225 char *backup_str;
4226 char *label_str;
4227 char *absolute_value;
4228 char append_str[3][MAX_LITERAL_POOL_SIZE];
4229 char verifystr[MAX_LITERAL_POOL_SIZE];
4230 struct score_it inst_backup;
4231 struct score_it inst_expand[3];
4232 struct score_it inst_main;
4233
4234 memcpy (&inst_backup, &inst, sizeof (struct score_it));
4235 strcpy (verifystr, str);
4236 backup_str = verifystr;
4237
4238 skip_whitespace (backup_str);
4239 if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
4240 return;
4241
4242 if (skip_past_comma (&backup_str) == (int) FAIL)
4243 return;
4244
4245 label_str = backup_str;
4246
4247 /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
4248 if (*backup_str == '[')
4249 {
b138abaa 4250 inst.type = Rd_rvalueRs_preSI12;
1c0d3aa6
NC
4251 do_ldst_insn (str);
4252 return;
4253 }
4254
4255 /* Ld/st rD, imm. */
4256 absolute_value = backup_str;
b138abaa 4257 inst.type = Rd_rvalueRs_SI15;
1c0d3aa6
NC
4258 if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
4259 || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE) == (int) FAIL)
4260 || (end_of_line (backup_str) == (int) FAIL))
4261 {
4262 return;
4263 }
4264 else
4265 {
4266 if (inst.reloc.exp.X_add_symbol == 0)
4267 {
4268 memcpy (&inst, &inst_backup, sizeof (struct score_it));
4269 exp_macro_ldst_abs (str);
4270 return;
4271 }
4272 }
4273
4274 /* Ld/st rD, label. */
b138abaa 4275 inst.type = Rd_rvalueRs_SI15;
1c0d3aa6
NC
4276 backup_str = absolute_value;
4277 if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
4278 || (end_of_line (backup_str) == (int) FAIL))
4279 {
4280 return;
4281 }
4282 else
4283 {
4284 if (inst.reloc.exp.X_add_symbol == 0)
4285 {
4286 if (!inst.error)
4287 inst.error = BAD_ARGS;
4288
4289 return;
4290 }
4291
4292 if (score_pic == PIC)
4293 {
8fce5f8c
ML
4294 int ldst_idx = 0;
4295 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4296 build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
4297 return;
1c0d3aa6
NC
4298 }
4299 else
4300 {
4301 if ((inst.reloc.exp.X_add_number <= 0x3fff)
4302 && (inst.reloc.exp.X_add_number >= -0x4000)
4303 && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
4304 {
4305 int ldst_idx = 0;
4306
4307 /* Assign the real opcode. */
4308 ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
4309 inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4310 inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
4311 inst.instruction |= reg_rd << 20;
4312 inst.instruction |= GP << 15;
4313 inst.relax_inst = 0x8000;
4314 inst.relax_size = 0;
4315 ldst_gp_p = 1;
4316 }
4317 }
4318 }
4319
4320 /* Backup inst. */
4321 memcpy (&inst_main, &inst, sizeof (struct score_it));
4322 r1_bak = nor1;
4323 nor1 = 0;
4324
4325 /* Determine which instructions should be output. */
14119072
ML
4326 sprintf (append_str[0], _("ld_i32hi r1, %s"), label_str);
4327 sprintf (append_str[1], _("ld_i32lo r1, %s"), label_str);
4328 sprintf (append_str[2], _("%s r%d, [r1, 0]"), inst_backup.name, reg_rd);
1c0d3aa6
NC
4329
4330 /* Generate three instructions.
4331 la r1, label
4332 ld/st rd, [r1, 0] */
4333 for (i = 0; i < 3; i++)
4334 {
4335 if (append_insn (append_str[i], FALSE) == (int) FAIL)
4336 return;
4337
4338 memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
4339 }
4340
4341 if (ldst_gp_p)
4342 {
4343 char *p;
4344
4345 /* Adjust instruction opcode and to be relaxed instruction opcode. */
4346 inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
4347 inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4348 inst_main.type = Insn_GP;
4349
4350 for (i = 0; i < 3; i++)
4351 inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
4352 , GET_INSN_CLASS (inst_expand[i].type));
4353
4354 /* Check data dependency. */
4355 handle_dependency (&inst_main);
4356
4357 /* Start a new frag if frag_now is not empty. */
4358 if (frag_now_fix () != 0)
4359 {
4360 if (!frag_now->tc_frag_data.is_insn)
4361 frag_wane (frag_now);
4362
4363 frag_new (0);
4364 }
4365 frag_grow (20);
4366
4367 /* Write fr_fix part. */
4368 p = frag_more (inst_main.size);
4369 md_number_to_chars (p, inst_main.instruction, inst_main.size);
4370
4371 if (inst_main.reloc.type != BFD_RELOC_NONE)
4372 {
4373 fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4374 &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4375 }
4376
4377#ifdef OBJ_ELF
4378 dwarf2_emit_insn (inst_main.size);
4379#endif
4380
4381 /* GP instruction can not do optimization, only can do relax between
4382 1 instruction and 3 instructions. */
4383 p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
4384 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4385 inst_main.reloc.exp.X_add_symbol, 0, NULL);
4386
4387 /* Write fr_var part.
4388 no calling gen_insn_frag, no fixS will be generated. */
4389 md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4390 p += inst_expand[0].size;
4391 md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4392 p += inst_expand[1].size;
4393 md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4394 }
4395 else
4396 {
4397 gen_insn_frag (&inst_expand[0], NULL);
4398 gen_insn_frag (&inst_expand[1], NULL);
4399 gen_insn_frag (&inst_expand[2], NULL);
4400 }
4401 nor1 = r1_bak;
4402
4403 /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
4404 inst.bwarn = -1;
4405}
4406
4407static void
4408do_lw_pic (char *str)
4409{
4410 int reg_rd;
4411
4412 skip_whitespace (str);
4413 if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
4414 || (skip_past_comma (&str) == (int) FAIL)
4415 || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
4416 || (end_of_line (str) == (int) FAIL))
4417 {
4418 return;
4419 }
4420 else
4421 {
4422 if (inst.reloc.exp.X_add_symbol == 0)
4423 {
4424 if (!inst.error)
4425 inst.error = BAD_ARGS;
4426
4427 return;
4428 }
4429
4430 inst.instruction |= GP << 15;
4431 inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4432 }
4433}
4434
4435static void
4436do_empty (char *str)
4437{
4438 str = str;
4439 if (university_version == 1)
4440 {
4441 if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
4442 || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
4443 || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
4444 || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
4445 {
4446 inst.error = ERR_FOR_SCORE5U_MMU;
4447 return;
4448 }
4449 }
4450 if (end_of_line (str) == (int) FAIL)
4451 return;
4452
4453 if (inst.relax_inst != 0x8000)
4454 {
4455 if (inst.type == NO_OPD)
4456 {
4457 inst.relax_size = 2;
4458 }
4459 else
4460 {
4461 inst.relax_size = 4;
4462 }
4463 }
4464}
4465
4466static void
4467do_jump (char *str)
4468{
4469 char *save_in;
14119072 4470 static char err_msg[100];
1c0d3aa6
NC
4471
4472 skip_whitespace (str);
4473 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4474 || end_of_line (str) == (int) FAIL)
4475 return;
4476
4477 if (inst.reloc.exp.X_add_symbol == 0)
4478 {
4479 inst.error = _("lacking label ");
4480 return;
4481 }
4482
4483 if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4484 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4485 {
14119072 4486 sprintf (err_msg, _("invalid constant: 25 bit expression not in range -2^24..2^24"));
1c0d3aa6
NC
4487 inst.error = _(err_msg);
4488 return;
4489 }
4490
4491 save_in = input_line_pointer;
4492 input_line_pointer = str;
4493 inst.reloc.type = BFD_RELOC_SCORE_JMP;
4494 inst.reloc.pc_rel = 1;
4495 input_line_pointer = save_in;
4496}
4497
4498static void
4499do16_jump (char *str)
4500{
4501 skip_whitespace (str);
4502 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4503 || end_of_line (str) == (int) FAIL)
4504 {
4505 return;
4506 }
4507 else if (inst.reloc.exp.X_add_symbol == 0)
4508 {
4509 inst.error = _("lacking label ");
4510 return;
4511 }
4512 else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
4513 && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
4514 {
4515 inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
4516 return;
4517 }
4518
4519 inst.reloc.type = BFD_RELOC_SCORE16_JMP;
4520 inst.reloc.pc_rel = 1;
4521}
4522
4523static void
4524do_branch (char *str)
4525{
4526 unsigned long abs_value = 0;
4527
4528 if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4529 || end_of_line (str) == (int) FAIL)
4530 {
4531 return;
4532 }
4533 else if (inst.reloc.exp.X_add_symbol == 0)
4534 {
4535 inst.error = _("lacking label ");
4536 return;
4537 }
4538 else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
4539 && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
4540 {
14119072 4541 inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
1c0d3aa6
NC
4542 return;
4543 }
4544
4545 inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
4546 inst.reloc.pc_rel = 1;
4547
4548 /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
4549 inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
4550
41c55c87
ML
4551 /* Compute 16 bit branch instruction. */
4552 if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
1c0d3aa6 4553 {
41c55c87 4554 inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
1c0d3aa6
NC
4555 inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4556 inst.relax_size = 2;
4557 }
4558 else
4559 {
4560 inst.relax_inst = 0x8000;
4561 }
1c0d3aa6
NC
4562}
4563
4564static void
4565do16_branch (char *str)
4566{
4567 if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
4568 || end_of_line (str) == (int) FAIL))
4569 {
4570 ;
4571 }
4572 else if (inst.reloc.exp.X_add_symbol == 0)
4573 {
4574 inst.error = _("lacking label");
4575 }
4576 else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
4577 && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
4578 {
4579 inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
4580 }
4581 else
4582 {
4583 inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
4584 inst.reloc.pc_rel = 1;
4585 inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
4586 }
4587}
4588
4589/* Iterate over the base tables to create the instruction patterns. */
4590static void
4591build_score_ops_hsh (void)
4592{
4593 unsigned int i;
4594 static struct obstack insn_obstack;
4595
4596 obstack_begin (&insn_obstack, 4000);
4597 for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
4598 {
4599 const struct asm_opcode *insn = score_insns + i;
4600 unsigned len = strlen (insn->template);
4601 struct asm_opcode *new;
4602 char *template;
4603 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
4604 template = obstack_alloc (&insn_obstack, len + 1);
4605
4606 strcpy (template, insn->template);
4607 new->template = template;
4608 new->parms = insn->parms;
4609 new->value = insn->value;
4610 new->relax_value = insn->relax_value;
4611 new->type = insn->type;
4612 new->bitmask = insn->bitmask;
4613 hash_insert (score_ops_hsh, new->template, (void *) new);
4614 }
4615}
4616
4617static void
4618build_dependency_insn_hsh (void)
4619{
4620 unsigned int i;
4621 static struct obstack dependency_obstack;
4622
4623 obstack_begin (&dependency_obstack, 4000);
4624 for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
4625 {
4626 const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
4627 unsigned len = strlen (tmp->insn_name);
4628 struct insn_to_dependency *new;
4629
4630 new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
4631 new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
4632
4633 strcpy (new->insn_name, tmp->insn_name);
4634 new->type = tmp->type;
4635 hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
4636 }
4637}
4638
4639/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4640 for use in the a.out file, and stores them in the array pointed to by buf.
4641 This knows about the endian-ness of the target machine and does
4642 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4643 2 (short) and 4 (long) Floating numbers are put out as a series of
4644 LITTLENUMS (shorts, here at least). */
4645
4646void
4647md_number_to_chars (char *buf, valueT val, int n)
4648{
4649 if (target_big_endian)
4650 number_to_chars_bigendian (buf, val, n);
4651 else
4652 number_to_chars_littleendian (buf, val, n);
4653}
4654
4655static valueT
4656md_chars_to_number (char *buf, int n)
4657{
4658 valueT result = 0;
4659 unsigned char *where = (unsigned char *)buf;
4660
4661 if (target_big_endian)
4662 {
4663 while (n--)
4664 {
4665 result <<= 8;
4666 result |= (*where++ & 255);
4667 }
4668 }
4669 else
4670 {
4671 while (n--)
4672 {
4673 result <<= 8;
4674 result |= (where[n] & 255);
4675 }
4676 }
4677
4678 return result;
4679}
4680
4681/* Turn a string in input_line_pointer into a floating point constant
4682 of type TYPE, and store the appropriate bytes in *LITP. The number
4683 of LITTLENUMS emitted is stored in *SIZEP. An error message is
4684 returned, or NULL on OK.
4685
4686 Note that fp constants aren't represent in the normal way on the ARM.
4687 In big endian mode, things are as expected. However, in little endian
4688 mode fp constants are big-endian word-wise, and little-endian byte-wise
4689 within the words. For example, (double) 1.1 in big endian mode is
4690 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4691 the byte sequence 99 99 f1 3f 9a 99 99 99. */
4692
4693char *
4694md_atof (int type, char *litP, int *sizeP)
4695{
4696 int prec;
4697 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4698 char *t;
4699 int i;
4700
4701 switch (type)
4702 {
4703 case 'f':
4704 case 'F':
4705 case 's':
4706 case 'S':
4707 prec = 2;
4708 break;
4709 case 'd':
4710 case 'D':
4711 case 'r':
4712 case 'R':
4713 prec = 4;
4714 break;
4715 case 'x':
4716 case 'X':
4717 case 'p':
4718 case 'P':
4719 prec = 6;
4720 break;
4721 default:
4722 *sizeP = 0;
4723 return _("bad call to MD_ATOF()");
4724 }
4725
4726 t = atof_ieee (input_line_pointer, type, words);
4727 if (t)
4728 input_line_pointer = t;
4729 *sizeP = prec * 2;
4730
4731 if (target_big_endian)
4732 {
4733 for (i = 0; i < prec; i++)
4734 {
4735 md_number_to_chars (litP, (valueT) words[i], 2);
4736 litP += 2;
4737 }
4738 }
4739 else
4740 {
4741 for (i = 0; i < prec; i += 2)
4742 {
4743 md_number_to_chars (litP, (valueT) words[i + 1], 2);
4744 md_number_to_chars (litP + 2, (valueT) words[i], 2);
4745 litP += 4;
4746 }
4747 }
4748
4749 return 0;
4750}
4751
4752/* Return true if the given symbol should be considered local for PIC. */
4753
4754static bfd_boolean
4755pic_need_relax (symbolS *sym, asection *segtype)
4756{
4757 asection *symsec;
4758 bfd_boolean linkonce;
4759
4760 /* Handle the case of a symbol equated to another symbol. */
4761 while (symbol_equated_reloc_p (sym))
4762 {
4763 symbolS *n;
4764
4765 /* It's possible to get a loop here in a badly written
4766 program. */
4767 n = symbol_get_value_expression (sym)->X_add_symbol;
4768 if (n == sym)
4769 break;
4770 sym = n;
4771 }
4772
4773 symsec = S_GET_SEGMENT (sym);
4774
4775 /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
4776 linkonce = FALSE;
4777 if (symsec != segtype && ! S_IS_LOCAL (sym))
4778 {
4779 if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
4780 linkonce = TRUE;
4781
4782 /* The GNU toolchain uses an extension for ELF: a section
4783 beginning with the magic string .gnu.linkonce is a linkonce
4784 section. */
4785 if (strncmp (segment_name (symsec), ".gnu.linkonce",
4786 sizeof ".gnu.linkonce" - 1) == 0)
4787 linkonce = TRUE;
4788 }
4789
4790 /* This must duplicate the test in adjust_reloc_syms. */
4791 return (symsec != &bfd_und_section
4792 && symsec != &bfd_abs_section
4793 && ! bfd_is_com_section (symsec)
4794 && !linkonce
4795#ifdef OBJ_ELF
4796 /* A global or weak symbol is treated as external. */
4797 && (OUTPUT_FLAVOR != bfd_target_elf_flavour
4798 || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
4799#endif
4800 );
4801}
4802
4803static int
4804judge_size_before_relax (fragS * fragp, asection *sec)
4805{
4806 int change = 0;
4807
4808 if (score_pic == NO_PIC)
4809 change = nopic_need_relax (fragp->fr_symbol, 0);
4810 else
4811 change = pic_need_relax (fragp->fr_symbol, sec);
4812
4813 if (change == 1)
4814 {
4815 /* Only at the first time determining whether GP instruction relax should be done,
4816 return the difference between insntruction size and instruction relax size. */
4817 if (fragp->fr_opcode == NULL)
4818 {
4819 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
4820 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
4821 return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
4822 }
4823 }
4824
4825 return 0;
4826}
4827
4828/* In this function, we determine whether GP instruction should do relaxation,
4829 for the label being against was known now.
4830 Doing this here but not in md_relax_frag() can induce iteration times
4831 in stage of doing relax. */
4832int
4833md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
4834{
4835 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4836 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4837 return judge_size_before_relax (fragp, sec);
4838
4839 return 0;
4840}
4841
4842static int
4843b32_relax_to_b16 (fragS * fragp)
4844{
4845 int grows = 0;
4846 int relaxable_p = 0;
4847 int old;
4848 int new;
4849 int frag_addr = fragp->fr_address + fragp->insn_addr;
4850
4851 addressT symbol_address = 0;
4852 symbolS *s;
4853 offsetT offset;
4854 unsigned long value;
4855 unsigned long abs_value;
4856
4857 /* FIXME : here may be able to modify better .
4858 I don't know how to get the fragp's section ,
4859 so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
4860 is different from the symbol's. */
4861
4862 old = RELAX_OLD (fragp->fr_subtype);
4863 new = RELAX_NEW (fragp->fr_subtype);
4864 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4865
4866 s = fragp->fr_symbol;
4867 /* b/bl immediate */
4868 if (s == NULL)
4869 frag_addr = 0;
4870 else
4871 {
4872 if (s->bsym != 0)
4873 symbol_address = (addressT) s->sy_frag->fr_address;
4874 }
4875
4876 value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
4877
4878 /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */
4879 offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
4880 if ((offset & 0x80000) == 0x80000)
4881 offset |= 0xfff00000;
4882
4883 abs_value = offset + symbol_address - frag_addr;
4884 if ((abs_value & 0x80000000) == 0x80000000)
4885 abs_value = 0xffffffff - abs_value + 1;
4886
4887 /* Relax branch 32 to branch 16. */
4888 if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
4889 && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
4890 {
4891 /* do nothing. */
4892 }
4893 else
4894 {
4895 /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */
4896 fragp->fr_opcode = NULL;
4897 fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
4898 }
4899
4900 return grows;
4901}
4902
4903/* Main purpose is to determine whether one frag should do relax.
4904 frag->fr_opcode indicates this point. */
4905
4906int
4907score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
4908{
4909 int grows = 0;
4910 int insn_size;
4911 int insn_relax_size;
4912 int do_relax_p = 0; /* Indicate doing relaxation for this frag. */
4913 int relaxable_p = 0;
4914 bfd_boolean word_align_p = FALSE;
4915 fragS *next_fragp;
4916
4917 /* If the instruction address is odd, make it half word align first. */
4918 if ((fragp->fr_address) % 2 != 0)
4919 {
4920 if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
4921 {
4922 fragp->insn_addr = 1;
4923 grows += 1;
4924 }
4925 }
4926
4927 word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
4928
4929 /* Get instruction size and relax size after the last relaxation. */
4930 if (fragp->fr_opcode)
4931 {
4932 insn_size = RELAX_NEW (fragp->fr_subtype);
4933 insn_relax_size = RELAX_OLD (fragp->fr_subtype);
4934 }
4935 else
4936 {
4937 insn_size = RELAX_OLD (fragp->fr_subtype);
4938 insn_relax_size = RELAX_NEW (fragp->fr_subtype);
4939 }
4940
4941 /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine
4942 whether the GP instruction should do relax. */
4943 if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
4944 || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
4945 {
4946 if (!word_align_p)
4947 {
8fce5f8c
ML
4948 if (fragp->insn_addr < 2)
4949 {
4950 fragp->insn_addr += 2;
4951 grows += 2;
4952 }
4953 else
4954 {
4955 fragp->insn_addr -= 2;
4956 grows -= 2;
4957 }
4958 }
1c0d3aa6
NC
4959
4960 if (fragp->fr_opcode)
4961 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
4962 else
4963 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
4964 }
4965 else
4966 {
4967 if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
4968 b32_relax_to_b16 (fragp);
4969
4970 relaxable_p = RELAX_OPT (fragp->fr_subtype);
4971 next_fragp = fragp->fr_next;
4972 while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
4973 {
4974 next_fragp = next_fragp->fr_next;
4975 }
4976
4977 if (next_fragp)
4978 {
4979 int n_insn_size;
4980 int n_relaxable_p = 0;
4981
4982 if (next_fragp->fr_opcode)
4983 {
4984 n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
4985 }
4986 else
4987 {
4988 n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
4989 }
4990
41c55c87
ML
4991 if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
4992 b32_relax_to_b16 (next_fragp);
4993 n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
1c0d3aa6
NC
4994
4995 if (word_align_p)
4996 {
4997 if (insn_size == 4)
4998 {
4999 /* 32 -> 16. */
5000 if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
5001 {
5002 grows -= 2;
5003 do_relax_p = 1;
5004 }
5005 }
5006 else if (insn_size == 2)
5007 {
5008 /* 16 -> 32. */
41c55c87 5009 if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
1c0d3aa6
NC
5010 {
5011 grows += 2;
5012 do_relax_p = 1;
5013 }
5014 }
5015 else
5016 {
5017 abort ();
5018 }
5019 }
5020 else
5021 {
5022 if (insn_size == 4)
5023 {
5024 /* 32 -> 16. */
5025 if (relaxable_p)
5026 {
5027 grows -= 2;
5028 do_relax_p = 1;
5029 }
5030 /* Make the 32 bit insturction word align. */
5031 else
5032 {
5033 fragp->insn_addr += 2;
5034 grows += 2;
5035 }
5036 }
5037 else if (insn_size == 2)
5038 {
5039 /* Do nothing. */
5040 }
5041 else
5042 {
5043 abort ();
5044 }
5045 }
5046 }
5047 else
5048 {
5049 /* Here, try best to do relax regardless fragp->fr_next->fr_type. */
5050 if (word_align_p == FALSE)
5051 {
5052 if (insn_size % 4 == 0)
5053 {
5054 /* 32 -> 16. */
5055 if (relaxable_p)
5056 {
5057 grows -= 2;
5058 do_relax_p = 1;
5059 }
5060 else
5061 {
5062 fragp->insn_addr += 2;
5063 grows += 2;
5064 }
5065 }
5066 }
5067 else
5068 {
5069 /* Do nothing. */
5070 }
5071 }
5072
5073 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5074 if (do_relax_p)
5075 {
5076 if (fragp->fr_opcode)
5077 {
5078 fragp->fr_opcode = NULL;
5079 /* Guarantee estimate stage is correct. */
5080 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5081 fragp->fr_fix += fragp->insn_addr;
5082 }
5083 else
5084 {
5085 fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
5086 /* Guarantee estimate stage is correct. */
5087 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5088 fragp->fr_fix += fragp->insn_addr;
5089 }
5090 }
5091 else
5092 {
5093 if (fragp->fr_opcode)
5094 {
5095 /* Guarantee estimate stage is correct. */
5096 fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
5097 fragp->fr_fix += fragp->insn_addr;
5098 }
5099 else
5100 {
5101 /* Guarantee estimate stage is correct. */
5102 fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
5103 fragp->fr_fix += fragp->insn_addr;
5104 }
5105 }
5106 }
5107
5108 return grows;
5109}
5110
5111void
5112md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
5113{
5114 int old;
5115 int new;
5116 char backup[20];
5117 fixS *fixp;
5118
5119 old = RELAX_OLD (fragp->fr_subtype);
5120 new = RELAX_NEW (fragp->fr_subtype);
5121
5122 /* fragp->fr_opcode indicates whether this frag should be relaxed. */
5123 if (fragp->fr_opcode == NULL)
5124 {
5125 memcpy (backup, fragp->fr_literal, old);
5126 fragp->fr_fix = old;
5127 }
5128 else
5129 {
5130 memcpy (backup, fragp->fr_literal + old, new);
5131 fragp->fr_fix = new;
5132 }
5133
5134 fixp = fragp->tc_frag_data.fixp;
5135 while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
5136 {
5137 if (fragp->fr_opcode)
5138 fixp->fx_done = 1;
5139 fixp = fixp->fx_next;
5140 }
5141 while (fixp && fixp->fx_frag == fragp)
5142 {
5143 if (fragp->fr_opcode)
5144 fixp->fx_where -= old + fragp->insn_addr;
5145 else
5146 fixp->fx_done = 1;
5147 fixp = fixp->fx_next;
5148 }
5149
5150 if (fragp->insn_addr)
5151 {
5152 md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
5153 }
5154 memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
5155 fragp->fr_fix += fragp->insn_addr;
5156}
5157
5158/* Implementation of md_frag_check.
5159 Called after md_convert_frag(). */
5160
5161void
5162score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
5163{
5164 know (fragp->insn_addr <= RELAX_PAD_BYTE);
5165}
5166
5167bfd_boolean
5168score_fix_adjustable (fixS * fixP)
5169{
5170 if (fixP->fx_addsy == NULL)
5171 {
5172 return 1;
5173 }
5174 else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
5175 && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
5176 {
5177 return 0;
5178 }
5179 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5180 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5181 {
5182 return 0;
5183 }
5184
5185 return 1;
5186}
5187
5188/* Implementation of TC_VALIDATE_FIX.
5189 Called before md_apply_fix() and after md_convert_frag(). */
5190void
5191score_validate_fix (fixS *fixP)
5192{
5193 fixP->fx_where += fixP->fx_frag->insn_addr;
5194}
5195
5196long
5197md_pcrel_from (fixS * fixP)
5198{
5199 long retval = 0;
5200
5201 if (fixP->fx_addsy
5202 && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
5203 && (fixP->fx_subsy == NULL))
5204 {
5205 retval = 0;
5206 }
5207 else
5208 {
5209 retval = fixP->fx_where + fixP->fx_frag->fr_address;
5210 }
5211
5212 return retval;
5213}
5214
5215int
5216score_force_relocation (struct fix *fixp)
5217{
5218 int retval = 0;
5219
5220 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
5221 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
5222 || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
5223 || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
5224 || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
5225 || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
5226 {
5227 retval = 1;
5228 }
5229
5230 return retval;
5231}
5232
5233/* Round up a section size to the appropriate boundary. */
5234valueT
5235md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
5236{
5237 int align = bfd_get_section_alignment (stdoutput, segment);
5238
1c0d3aa6
NC
5239 return ((size + (1 << align) - 1) & (-1 << align));
5240}
5241
5242void
5243md_apply_fix (fixS *fixP, valueT *valP, segT seg)
5244{
5245 offsetT value = *valP;
5246 offsetT abs_value = 0;
5247 offsetT newval;
5248 offsetT content;
5249 unsigned short HI, LO;
5250
5251 char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
5252
5253 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5254 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
5255 {
5256 if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
5257 fixP->fx_done = 1;
5258 }
5259
5260 /* If this symbol is in a different section then we need to leave it for
5261 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5262 so we have to undo it's effects here. */
5263 if (fixP->fx_pcrel)
5264 {
5265 if (fixP->fx_addsy != NULL
5266 && S_IS_DEFINED (fixP->fx_addsy)
5267 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
5268 value += md_pcrel_from (fixP);
5269 }
5270
5271 /* Remember value for emit_reloc. */
5272 fixP->fx_addnumber = value;
5273
5274 switch (fixP->fx_r_type)
5275 {
5276 case BFD_RELOC_HI16_S:
5277 if (fixP->fx_done)
5278 { /* For la rd, imm32. */
5279 newval = md_chars_to_number (buf, INSN_SIZE);
5280 HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
5281 newval |= (HI & 0x3fff) << 1;
5282 newval |= ((HI >> 14) & 0x3) << 16;
5283 md_number_to_chars (buf, newval, INSN_SIZE);
5284 }
5285 break;
5286 case BFD_RELOC_LO16:
5287 if (fixP->fx_done) /* For la rd, imm32. */
5288 {
5289 newval = md_chars_to_number (buf, INSN_SIZE);
5290 LO = (value) & 0xffff;
5291 newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
5292 newval |= ((LO >> 14) & 0x3) << 16;
5293 md_number_to_chars (buf, newval, INSN_SIZE);
5294 }
5295 break;
5296 case BFD_RELOC_SCORE_JMP:
5297 {
5298 content = md_chars_to_number (buf, INSN_SIZE);
5299 value = fixP->fx_offset;
5300 content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
5301 md_number_to_chars (buf, content, INSN_SIZE);
5302 }
5303 break;
5304 case BFD_RELOC_SCORE_BRANCH:
5305 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5306 value = fixP->fx_offset;
5307 else
5308 fixP->fx_done = 1;
5309
5310 content = md_chars_to_number (buf, INSN_SIZE);
5311 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
5312 {
5313 if ((value & 0x80000000) == 0x80000000)
5314 abs_value = 0xffffffff - value + 1;
5315 if ((abs_value & 0xffffff00) != 0)
5316 {
5317 as_bad_where (fixP->fx_file, fixP->fx_line,
5318 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5319 return;
5320 }
5321 content = md_chars_to_number (buf, INSN16_SIZE);
5322 content &= 0xff00;
5323 content = (content & 0xff00) | ((value >> 1) & 0xff);
5324 md_number_to_chars (buf, content, INSN16_SIZE);
5325 fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
5326 fixP->fx_size = 2;
5327 }
5328 else
5329 {
5330 if ((value & 0x80000000) == 0x80000000)
5331 abs_value = 0xffffffff - value + 1;
5332 if ((abs_value & 0xfff80000) != 0)
5333 {
5334 as_bad_where (fixP->fx_file, fixP->fx_line,
5335 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5336 return;
5337 }
5338 content = md_chars_to_number (buf, INSN_SIZE);
5339 content &= 0xfc00fc01;
5340 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5341 md_number_to_chars (buf, content, INSN_SIZE);
5342 }
5343 break;
5344 case BFD_RELOC_SCORE16_JMP:
5345 content = md_chars_to_number (buf, INSN16_SIZE);
5346 content &= 0xf001;
5347 value = fixP->fx_offset & 0xfff;
5348 content = (content & 0xfc01) | (value & 0xffe);
5349 md_number_to_chars (buf, content, INSN16_SIZE);
5350 break;
5351 case BFD_RELOC_SCORE16_BRANCH:
5352 content = md_chars_to_number (buf, INSN_SIZE);
5353 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
5354 {
5355 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5356 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5357 value = fixP->fx_offset;
5358 else
5359 fixP->fx_done = 1;
5360 if ((value & 0x80000000) == 0x80000000)
5361 abs_value = 0xffffffff - value + 1;
5362 if ((abs_value & 0xfff80000) != 0)
5363 {
5364 as_bad_where (fixP->fx_file, fixP->fx_line,
5365 _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
5366 return;
5367 }
5368 content = md_chars_to_number (buf, INSN_SIZE);
5369 content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
5370 md_number_to_chars (buf, content, INSN_SIZE);
5371 fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
5372 fixP->fx_size = 4;
5373 break;
5374 }
5375 else
5376 {
5377 /* In differnt section. */
5378 if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
5379 (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
5380 value = fixP->fx_offset;
5381 else
5382 fixP->fx_done = 1;
5383
5384 if ((value & 0x80000000) == 0x80000000)
5385 abs_value = 0xffffffff - value + 1;
5386 if ((abs_value & 0xffffff00) != 0)
5387 {
5388 as_bad_where (fixP->fx_file, fixP->fx_line,
5389 _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
5390 return;
5391 }
5392 content = md_chars_to_number (buf, INSN16_SIZE);
5393 content = (content & 0xff00) | ((value >> 1) & 0xff);
5394 md_number_to_chars (buf, content, INSN16_SIZE);
5395 break;
5396 }
5397 case BFD_RELOC_8:
5398 if (fixP->fx_done || fixP->fx_pcrel)
5399 md_number_to_chars (buf, value, 1);
5400#ifdef OBJ_ELF
5401 else
5402 {
5403 value = fixP->fx_offset;
5404 md_number_to_chars (buf, value, 1);
5405 }
5406#endif
5407 break;
5408
5409 case BFD_RELOC_16:
5410 if (fixP->fx_done || fixP->fx_pcrel)
5411 md_number_to_chars (buf, value, 2);
5412#ifdef OBJ_ELF
5413 else
5414 {
5415 value = fixP->fx_offset;
5416 md_number_to_chars (buf, value, 2);
5417 }
5418#endif
5419 break;
5420 case BFD_RELOC_RVA:
5421 case BFD_RELOC_32:
5422 if (fixP->fx_done || fixP->fx_pcrel)
5423 md_number_to_chars (buf, value, 4);
5424#ifdef OBJ_ELF
5425 else
5426 {
5427 value = fixP->fx_offset;
5428 md_number_to_chars (buf, value, 4);
5429 }
5430#endif
5431 break;
5432 case BFD_RELOC_VTABLE_INHERIT:
5433 fixP->fx_done = 0;
5434 if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
5435 S_SET_WEAK (fixP->fx_addsy);
5436 break;
5437 case BFD_RELOC_VTABLE_ENTRY:
5438 fixP->fx_done = 0;
5439 break;
5440 case BFD_RELOC_SCORE_GPREL15:
5441 content = md_chars_to_number (buf, INSN_SIZE);
5442 if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
5443 fixP->fx_r_type = BFD_RELOC_NONE;
5444 fixP->fx_done = 0;
5445 break;
5446 case BFD_RELOC_SCORE_GOT15:
5447 case BFD_RELOC_SCORE_DUMMY_HI16:
5448 case BFD_RELOC_SCORE_GOT_LO16:
5449 case BFD_RELOC_SCORE_CALL15:
5450 case BFD_RELOC_GPREL32:
5451 break;
5452 case BFD_RELOC_NONE:
5453 default:
5454 as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
5455 }
5456}
5457
5458/* Translate internal representation of relocation info to BFD target format. */
5459arelent **
5460tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
5461{
5462 static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
5463 arelent *reloc;
5464 bfd_reloc_code_real_type code;
5465 char *type;
5466 fragS *f;
5467 symbolS *s;
5468 expressionS e;
5469
5470 reloc = retval[0] = xmalloc (sizeof (arelent));
5471 retval[1] = NULL;
5472
5473 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5474 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5475 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5476 reloc->addend = fixp->fx_offset;
5477
5478 /* If this is a variant frag, we may need to adjust the existing
5479 reloc and generate a new one. */
5480 if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
5481 {
5482 /* Update instruction imm bit. */
5483 offsetT newval;
5484 unsigned short off;
5485 char *buf;
5486
5487 buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
5488 newval = md_chars_to_number (buf, INSN_SIZE);
5489 off = fixp->fx_offset >> 16;
5490 newval |= (off & 0x3fff) << 1;
5491 newval |= ((off >> 14) & 0x3) << 16;
5492 md_number_to_chars (buf, newval, INSN_SIZE);
5493
5494 buf += INSN_SIZE;
5495 newval = md_chars_to_number (buf, INSN_SIZE);
5496 off = fixp->fx_offset & 0xffff;
5497 newval |= ((off & 0x3fff) << 1);
5498 newval |= (((off >> 14) & 0x3) << 16);
5499 md_number_to_chars (buf, newval, INSN_SIZE);
5500
5501 retval[1] = xmalloc (sizeof (arelent));
5502 retval[2] = NULL;
5503 retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
5504 *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
5505 retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
5506
5507 f = fixp->fx_frag;
5508 s = f->fr_symbol;
5509 e = s->sy_value;
5510
5511 retval[1]->addend = 0;
5512 retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
5513 assert (retval[1]->howto != NULL);
5514
5515 fixp->fx_r_type = BFD_RELOC_HI16_S;
5516 }
5517
5518 code = fixp->fx_r_type;
5519 switch (fixp->fx_r_type)
5520 {
5521 case BFD_RELOC_32:
5522 if (fixp->fx_pcrel)
5523 {
5524 code = BFD_RELOC_32_PCREL;
5525 break;
5526 }
5527 case BFD_RELOC_HI16_S:
5528 case BFD_RELOC_LO16:
5529 case BFD_RELOC_SCORE_JMP:
5530 case BFD_RELOC_SCORE_BRANCH:
5531 case BFD_RELOC_SCORE16_JMP:
5532 case BFD_RELOC_SCORE16_BRANCH:
5533 case BFD_RELOC_VTABLE_ENTRY:
5534 case BFD_RELOC_VTABLE_INHERIT:
5535 case BFD_RELOC_SCORE_GPREL15:
5536 case BFD_RELOC_SCORE_GOT15:
5537 case BFD_RELOC_SCORE_DUMMY_HI16:
5538 case BFD_RELOC_SCORE_GOT_LO16:
5539 case BFD_RELOC_SCORE_CALL15:
5540 case BFD_RELOC_GPREL32:
5541 case BFD_RELOC_NONE:
5542 code = fixp->fx_r_type;
5543 break;
5544 default:
5545 type = _("<unknown>");
5546 as_bad_where (fixp->fx_file, fixp->fx_line,
5547 _("cannot represent %s relocation in this object file format"), type);
5548 return NULL;
5549 }
5550
5551 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
5552 if (reloc->howto == NULL)
5553 {
5554 as_bad_where (fixp->fx_file, fixp->fx_line,
5555 _("cannot represent %s relocation in this object file format1"),
5556 bfd_get_reloc_code_name (code));
5557 return NULL;
5558 }
5559 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
5560 vtable entry to be used in the relocation's section offset. */
5561 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
5562 reloc->address = fixp->fx_offset;
5563
5564 return retval;
5565}
5566
5567void
5568score_elf_final_processing (void)
5569{
5570 if (fix_data_dependency == 1)
5571 {
5572 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
5573 }
5574 if (score_pic == PIC)
5575 {
5576 elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
5577 }
5578}
5579
5580static void
5581parse_pce_inst (char *insnstr)
5582{
5583 char c;
5584 char *p;
5585 char first[MAX_LITERAL_POOL_SIZE];
5586 char second[MAX_LITERAL_POOL_SIZE];
5587 struct score_it pec_part_1;
5588
5589 /* Get first part string of PCE. */
5590 p = strstr (insnstr, "||");
5591 c = *p;
5592 *p = '\0';
5593 sprintf (first, "%s", insnstr);
5594
5595 /* Get second part string of PCE. */
5596 *p = c;
5597 p += 2;
5598 sprintf (second, "%s", p);
5599
5600 parse_16_32_inst (first, FALSE);
5601 if (inst.error)
5602 return;
5603
5604 memcpy (&pec_part_1, &inst, sizeof (inst));
5605
5606 parse_16_32_inst (second, FALSE);
5607 if (inst.error)
5608 return;
5609
5610 if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
5611 || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
5612 || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
5613 {
5614 inst.error = _("pce instruction error (16 bit || 16 bit)'");
5615 sprintf (inst.str, "%s", insnstr);
5616 return;
5617 }
5618
5619 if (!inst.error)
5620 gen_insn_frag (&pec_part_1, &inst);
5621}
5622
5623void
5624md_assemble (char *str)
5625{
5626 know (str);
5627 know (strlen (str) < MAX_LITERAL_POOL_SIZE);
5628
5629 memset (&inst, '\0', sizeof (inst));
5630 if (INSN_IS_PCE_P (str))
5631 parse_pce_inst (str);
5632 else
5633 parse_16_32_inst (str, TRUE);
5634
5635 if (inst.error)
14119072 5636 as_bad (_("%s -- `%s'"), inst.error, inst.str);
1c0d3aa6
NC
5637}
5638
5639/* We handle all bad expressions here, so that we can report the faulty
5640 instruction in the error message. */
5641void
5642md_operand (expressionS * expr)
5643{
5644 if (in_my_get_expression)
5645 {
5646 expr->X_op = O_illegal;
5647 if (inst.error == NULL)
5648 {
5649 inst.error = _("bad expression");
5650 }
5651 }
5652}
5653
5654const char *md_shortopts = "nO::g::G:";
5655
5656#ifdef SCORE_BI_ENDIAN
5657#define OPTION_EB (OPTION_MD_BASE + 0)
5658#define OPTION_EL (OPTION_MD_BASE + 1)
5659#else
5660#if TARGET_BYTES_BIG_ENDIAN
5661#define OPTION_EB (OPTION_MD_BASE + 0)
5662#else
5663#define OPTION_EL (OPTION_MD_BASE + 1)
5664#endif
5665#endif
5666#define OPTION_FIXDD (OPTION_MD_BASE + 2)
5667#define OPTION_NWARN (OPTION_MD_BASE + 3)
5668#define OPTION_SCORE5 (OPTION_MD_BASE + 4)
5669#define OPTION_SCORE5U (OPTION_MD_BASE + 5)
5670#define OPTION_SCORE7 (OPTION_MD_BASE + 6)
5671#define OPTION_R1 (OPTION_MD_BASE + 7)
5672#define OPTION_O0 (OPTION_MD_BASE + 8)
5673#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
5674#define OPTION_PIC (OPTION_MD_BASE + 10)
5675
5676struct option md_longopts[] =
5677{
5678#ifdef OPTION_EB
5679 {"EB" , no_argument, NULL, OPTION_EB},
5680#endif
5681#ifdef OPTION_EL
5682 {"EL" , no_argument, NULL, OPTION_EL},
5683#endif
5684 {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
5685 {"NWARN" , no_argument, NULL, OPTION_NWARN},
5686 {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
5687 {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
5688 {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
5689 {"USE_R1" , no_argument, NULL, OPTION_R1},
5690 {"O0" , no_argument, NULL, OPTION_O0},
5691 {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
5692 {"KPIC" , no_argument, NULL, OPTION_PIC},
5693 {NULL , no_argument, NULL, 0}
5694};
5695
5696size_t md_longopts_size = sizeof (md_longopts);
5697
5698int
5699md_parse_option (int c, char *arg)
5700{
5701 switch (c)
5702 {
5703#ifdef OPTION_EB
5704 case OPTION_EB:
5705 target_big_endian = 1;
5706 break;
5707#endif
5708#ifdef OPTION_EL
5709 case OPTION_EL:
5710 target_big_endian = 0;
5711 break;
5712#endif
5713 case OPTION_FIXDD:
5714 fix_data_dependency = 1;
5715 break;
5716 case OPTION_NWARN:
5717 warn_fix_data_dependency = 0;
5718 break;
5719 case OPTION_SCORE5:
5720 score7 = 0;
5721 university_version = 0;
5722 vector_size = SCORE5_PIPELINE;
5723 break;
5724 case OPTION_SCORE5U:
5725 score7 = 0;
5726 university_version = 1;
5727 vector_size = SCORE5_PIPELINE;
5728 break;
5729 case OPTION_SCORE7:
5730 score7 = 1;
5731 university_version = 0;
5732 vector_size = SCORE7_PIPELINE;
5733 break;
5734 case OPTION_R1:
5735 nor1 = 0;
5736 break;
5737 case 'G':
5738 g_switch_value = atoi (arg);
5739 break;
5740 case OPTION_O0:
5741 g_opt = 0;
5742 break;
5743 case OPTION_SCORE_VERSION:
5744 printf (_("Sunplus-v2-0-0-20060510\n"));
5745 break;
5746 case OPTION_PIC:
5747 score_pic = PIC;
5748 g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */
5749 break;
5750 default:
5751 /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */
5752 return 0;
5753 }
5754 return 1;
5755}
5756
5757void
5758md_show_usage (FILE * fp)
5759{
5760 fprintf (fp, _(" Score-specific assembler options:\n"));
5761#ifdef OPTION_EB
5762 fprintf (fp, _("\
5763 -EB\t\tassemble code for a big-endian cpu\n"));
5764#endif
5765
5766#ifdef OPTION_EL
5767 fprintf (fp, _("\
5768 -EL\t\tassemble code for a little-endian cpu\n"));
5769#endif
5770
5771 fprintf (fp, _("\
5772 -FIXDD\t\tassemble code for fix data dependency\n"));
5773 fprintf (fp, _("\
5774 -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
5775 fprintf (fp, _("\
5776 -SCORE5\t\tassemble code for target is SCORE5\n"));
5777 fprintf (fp, _("\
5778 -SCORE5U\tassemble code for target is SCORE5U\n"));
5779 fprintf (fp, _("\
5780 -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
5781 fprintf (fp, _("\
5782 -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
5783 fprintf (fp, _("\
ec6e49f4 5784 -KPIC\t\tassemble code for PIC\n"));
1c0d3aa6 5785 fprintf (fp, _("\
ec6e49f4
NC
5786 -O0\t\tassembler will not perform any optimizations\n"));
5787 fprintf (fp, _("\
5788 -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
1c0d3aa6
NC
5789 fprintf (fp, _("\
5790 -V \t\tSunplus release version \n"));
5791}
5792
5793
5794/* Pesudo handling functions. */
5795
5796/* If we change section we must dump the literal pool first. */
5797static void
5798s_score_bss (int ignore ATTRIBUTE_UNUSED)
5799{
5800 subseg_set (bss_section, (subsegT) get_absolute_expression ());
5801 demand_empty_rest_of_line ();
5802}
5803
5804static void
5805s_score_text (int ignore)
5806{
5807 obj_elf_text (ignore);
5808 record_alignment (now_seg, 2);
5809}
5810
5811static void
5812score_s_section (int ignore)
5813{
5814 obj_elf_section (ignore);
5815 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5816 record_alignment (now_seg, 2);
5817
5818}
5819
5820static void
5821s_change_sec (int sec)
5822{
5823 segT seg;
5824
5825#ifdef OBJ_ELF
5826 /* The ELF backend needs to know that we are changing sections, so
5827 that .previous works correctly. We could do something like check
5828 for an obj_section_change_hook macro, but that might be confusing
5829 as it would not be appropriate to use it in the section changing
5830 functions in read.c, since obj-elf.c intercepts those. FIXME:
5831 This should be cleaner, somehow. */
5832 obj_elf_section_change_hook ();
5833#endif
5834 switch (sec)
5835 {
5836 case 'r':
5837 seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5838 bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5839 if (strcmp (TARGET_OS, "elf") != 0)
5840 record_alignment (seg, 4);
5841 demand_empty_rest_of_line ();
5842 break;
5843 case 's':
5844 seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5845 bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5846 if (strcmp (TARGET_OS, "elf") != 0)
5847 record_alignment (seg, 4);
5848 demand_empty_rest_of_line ();
5849 break;
5850 }
5851}
5852
5853static void
5854s_score_mask (int reg_type ATTRIBUTE_UNUSED)
5855{
5856 long mask, off;
5857
5858 if (cur_proc_ptr == (procS *) NULL)
5859 {
5860 as_warn (_(".mask outside of .ent"));
5861 demand_empty_rest_of_line ();
5862 return;
5863 }
5864 if (get_absolute_expression_and_terminator (&mask) != ',')
5865 {
5866 as_warn (_("Bad .mask directive"));
5867 --input_line_pointer;
5868 demand_empty_rest_of_line ();
5869 return;
5870 }
5871 off = get_absolute_expression ();
5872 cur_proc_ptr->reg_mask = mask;
5873 cur_proc_ptr->reg_offset = off;
5874 demand_empty_rest_of_line ();
5875}
5876
5877static symbolS *
5878get_symbol (void)
5879{
5880 int c;
5881 char *name;
5882 symbolS *p;
5883
5884 name = input_line_pointer;
5885 c = get_symbol_end ();
5886 p = (symbolS *) symbol_find_or_make (name);
5887 *input_line_pointer = c;
5888 return p;
5889}
5890
5891static long
5892get_number (void)
5893{
5894 int negative = 0;
5895 long val = 0;
5896
5897 if (*input_line_pointer == '-')
5898 {
5899 ++input_line_pointer;
5900 negative = 1;
5901 }
5902 if (!ISDIGIT (*input_line_pointer))
5903 as_bad (_("expected simple number"));
5904 if (input_line_pointer[0] == '0')
5905 {
5906 if (input_line_pointer[1] == 'x')
5907 {
5908 input_line_pointer += 2;
5909 while (ISXDIGIT (*input_line_pointer))
5910 {
5911 val <<= 4;
5912 val |= hex_value (*input_line_pointer++);
5913 }
5914 return negative ? -val : val;
5915 }
5916 else
5917 {
5918 ++input_line_pointer;
5919 while (ISDIGIT (*input_line_pointer))
5920 {
5921 val <<= 3;
5922 val |= *input_line_pointer++ - '0';
5923 }
5924 return negative ? -val : val;
5925 }
5926 }
5927 if (!ISDIGIT (*input_line_pointer))
5928 {
5929 printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5930 as_warn (_("invalid number"));
5931 return -1;
5932 }
5933 while (ISDIGIT (*input_line_pointer))
5934 {
5935 val *= 10;
5936 val += *input_line_pointer++ - '0';
5937 }
5938 return negative ? -val : val;
5939}
5940
5941/* The .aent and .ent directives. */
5942
5943static void
5944s_score_ent (int aent)
5945{
5946 symbolS *symbolP;
5947 int maybe_text;
5948
5949 symbolP = get_symbol ();
5950 if (*input_line_pointer == ',')
5951 ++input_line_pointer;
5952 SKIP_WHITESPACE ();
5953 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5954 get_number ();
5955
5956#ifdef BFD_ASSEMBLER
5957 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5958 maybe_text = 1;
5959 else
5960 maybe_text = 0;
5961#else
5962 if (now_seg != data_section && now_seg != bss_section)
5963 maybe_text = 1;
5964 else
5965 maybe_text = 0;
5966#endif
5967 if (!maybe_text)
5968 as_warn (_(".ent or .aent not in text section."));
5969 if (!aent && cur_proc_ptr)
5970 as_warn (_("missing .end"));
5971 if (!aent)
5972 {
5973 cur_proc_ptr = &cur_proc;
5974 cur_proc_ptr->reg_mask = 0xdeadbeaf;
5975 cur_proc_ptr->reg_offset = 0xdeadbeaf;
5976 cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5977 cur_proc_ptr->leaf = 0xdeafbeaf;
5978 cur_proc_ptr->frame_offset = 0xdeafbeaf;
5979 cur_proc_ptr->frame_reg = 0xdeafbeaf;
5980 cur_proc_ptr->pc_reg = 0xdeafbeaf;
5981 cur_proc_ptr->isym = symbolP;
5982 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5983 ++numprocs;
5984 if (debug_type == DEBUG_STABS)
5985 stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5986 }
5987 demand_empty_rest_of_line ();
5988}
5989
5990static void
5991s_score_frame (int ignore ATTRIBUTE_UNUSED)
5992{
5993 char *backupstr;
5994 char str[30];
5995 long val;
5996 int i = 0;
5997
5998 backupstr = input_line_pointer;
5999
6000#ifdef OBJ_ELF
6001 if (cur_proc_ptr == (procS *) NULL)
6002 {
6003 as_warn (_(".frame outside of .ent"));
6004 demand_empty_rest_of_line ();
6005 return;
6006 }
6007 cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6008 SKIP_WHITESPACE ();
6009 skip_past_comma (&backupstr);
6010 while (*backupstr != ',')
6011 {
6012 str[i] = *backupstr;
6013 i++;
6014 backupstr++;
6015 }
6016 str[i] = '\0';
6017 val = atoi (str);
6018
6019 SKIP_WHITESPACE ();
6020 skip_past_comma (&backupstr);
6021 cur_proc_ptr->frame_offset = val;
6022 cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
6023
6024 SKIP_WHITESPACE ();
6025 skip_past_comma (&backupstr);
6026 i = 0;
6027 while (*backupstr != '\n')
6028 {
6029 str[i] = *backupstr;
6030 i++;
6031 backupstr++;
6032 }
6033 str[i] = '\0';
6034 val = atoi (str);
6035 cur_proc_ptr->leaf = val;
6036 SKIP_WHITESPACE ();
6037 skip_past_comma (&backupstr);
6038
6039#endif /* OBJ_ELF */
6040 while (input_line_pointer != backupstr)
6041 input_line_pointer++;
6042}
6043
6044/* The .end directive. */
6045static void
6046s_score_end (int x ATTRIBUTE_UNUSED)
6047{
6048 symbolS *p;
6049 int maybe_text;
6050
6051 /* Generate a .pdr section. */
6052 segT saved_seg = now_seg;
6053 subsegT saved_subseg = now_subseg;
6054 valueT dot;
6055 expressionS exp;
6056 char *fragp;
6057
6058 if (!is_end_of_line[(unsigned char)*input_line_pointer])
6059 {
6060 p = get_symbol ();
6061 demand_empty_rest_of_line ();
6062 }
6063 else
6064 p = NULL;
6065
6066#ifdef BFD_ASSEMBLER
6067 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
6068 maybe_text = 1;
6069 else
6070 maybe_text = 0;
6071#else
6072 if (now_seg != data_section && now_seg != bss_section)
6073 maybe_text = 1;
6074 else
6075 maybe_text = 0;
6076#endif
6077
6078 if (!maybe_text)
6079 as_warn (_(".end not in text section"));
6080 if (!cur_proc_ptr)
6081 {
6082 as_warn (_(".end directive without a preceding .ent directive."));
6083 demand_empty_rest_of_line ();
6084 return;
6085 }
6086 if (p != NULL)
6087 {
6088 assert (S_GET_NAME (p));
6089 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
6090 as_warn (_(".end symbol does not match .ent symbol."));
6091 if (debug_type == DEBUG_STABS)
6092 stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
6093 }
6094 else
6095 as_warn (_(".end directive missing or unknown symbol"));
6096
6097 if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
6098 (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
6099 (cur_proc_ptr->leaf == 0xdeafbeaf) ||
6100 (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
6101 (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
6102
6103 else
6104 {
6105 dot = frag_now_fix ();
6106 assert (pdr_seg);
6107 subseg_set (pdr_seg, 0);
6108 /* Write the symbol. */
6109 exp.X_op = O_symbol;
6110 exp.X_add_symbol = p;
6111 exp.X_add_number = 0;
6112 emit_expr (&exp, 4);
6113 fragp = frag_more (7 * 4);
6114 md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
6115 md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
6116 md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
6117 md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
6118 md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
6119 md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
6120 md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
6121 subseg_set (saved_seg, saved_subseg);
6122
6123 }
6124 cur_proc_ptr = NULL;
6125}
6126
6127/* Handle the .set pseudo-op. */
6128static void
6129s_score_set (int x ATTRIBUTE_UNUSED)
6130{
6131 int i = 0;
6132 char name[MAX_LITERAL_POOL_SIZE];
6133 char * orig_ilp = input_line_pointer;
6134
6135 while (!is_end_of_line[(unsigned char)*input_line_pointer])
6136 {
6137 name[i] = (char) * input_line_pointer;
6138 i++;
6139 ++input_line_pointer;
6140 }
6141
6142 name[i] = '\0';
6143
6144 if (strcmp (name, "nwarn") == 0)
6145 {
6146 warn_fix_data_dependency = 0;
6147 }
6148 else if (strcmp (name, "fixdd") == 0)
6149 {
6150 fix_data_dependency = 1;
6151 }
6152 else if (strcmp (name, "nofixdd") == 0)
6153 {
6154 fix_data_dependency = 0;
6155 }
6156 else if (strcmp (name, "r1") == 0)
6157 {
6158 nor1 = 0;
6159 }
6160 else if (strcmp (name, "nor1") == 0)
6161 {
6162 nor1 = 1;
6163 }
6164 else if (strcmp (name, "optimize") == 0)
6165 {
6166 g_opt = 1;
6167 }
6168 else if (strcmp (name, "volatile") == 0)
6169 {
6170 g_opt = 0;
6171 }
6172 else if (strcmp (name, "pic") == 0)
6173 {
6174 score_pic = PIC;
6175 }
6176 else
6177 {
6178 input_line_pointer = orig_ilp;
6179 s_set (0);
6180 }
6181}
6182
6183/* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the
6184 $gp register for the function based on the function address, which is in the register
6185 named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
6186 specially by the linker. The result is:
6187 ldis gp, %hi(GP_DISP_LABEL)
6188 ori gp, %low(GP_DISP_LABEL)
6189 add gp, gp, .cpload argument
6190 The .cpload argument is normally r29. */
6191
6192static void
6193s_score_cpload (int ignore ATTRIBUTE_UNUSED)
6194{
6195 int reg;
6196 char insn_str[MAX_LITERAL_POOL_SIZE];
6197
6198 /* If we are not generating PIC code, .cpload is ignored. */
6199 if (score_pic == NO_PIC)
6200 {
6201 s_ignore (0);
6202 return;
6203 }
6204
6205 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6206 return;
6207
6208 demand_empty_rest_of_line ();
6209
14119072 6210 sprintf (insn_str, _("ld_i32hi r%d, %s"), GP, GP_DISP_LABEL);
1c0d3aa6
NC
6211 if (append_insn (insn_str, TRUE) == (int) FAIL)
6212 return;
6213
14119072 6214 sprintf (insn_str, _("ld_i32lo r%d, %s"), GP, GP_DISP_LABEL);
1c0d3aa6
NC
6215 if (append_insn (insn_str, TRUE) == (int) FAIL)
6216 return;
6217
14119072 6218 sprintf (insn_str, _("add r%d, r%d, r%d"), GP, GP, reg);
1c0d3aa6
NC
6219 if (append_insn (insn_str, TRUE) == (int) FAIL)
6220 return;
6221}
6222
6223/* Handle the .cprestore pseudo-op. This stores $gp into a given
6224 offset from $sp. The offset is remembered, and after making a PIC
6225 call $gp is restored from that location. */
6226
6227static void
6228s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
6229{
8fce5f8c 6230 int reg;
1c0d3aa6
NC
6231 int cprestore_offset;
6232 char insn_str[MAX_LITERAL_POOL_SIZE];
6233
6234 /* If we are not generating PIC code, .cprestore is ignored. */
6235 if (score_pic == NO_PIC)
6236 {
6237 s_ignore (0);
6238 return;
6239 }
6240
8fce5f8c
ML
6241 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
6242 || skip_past_comma (&input_line_pointer) == (int) FAIL)
6243 {
6244 return;
6245 }
6246
1c0d3aa6
NC
6247 cprestore_offset = get_absolute_expression ();
6248
8fce5f8c
ML
6249 if (cprestore_offset <= 0x3fff)
6250 {
14119072 6251 sprintf (insn_str, _("sw r%d, [r%d, %d]"), GP, reg, cprestore_offset);
8fce5f8c
ML
6252 if (append_insn (insn_str, TRUE) == (int) FAIL)
6253 return;
6254 }
6255 else
6256 {
6257 int r1_bak;
6258
6259 r1_bak = nor1;
6260 nor1 = 0;
6261
14119072 6262 sprintf (insn_str, _("li r1, %d"), cprestore_offset);
8fce5f8c
ML
6263 if (append_insn (insn_str, TRUE) == (int) FAIL)
6264 return;
6265
14119072 6266 sprintf (insn_str, _("add r1, r1, r%d"), reg);
8fce5f8c
ML
6267 if (append_insn (insn_str, TRUE) == (int) FAIL)
6268 return;
6269
14119072 6270 sprintf (insn_str, _("sw r%d, [r1]"), GP);
8fce5f8c
ML
6271 if (append_insn (insn_str, TRUE) == (int) FAIL)
6272 return;
6273
6274 nor1 = r1_bak;
6275 }
6276
6277 demand_empty_rest_of_line ();
1c0d3aa6
NC
6278}
6279
6280/* Handle the .gpword pseudo-op. This is used when generating PIC
6281 code. It generates a 32 bit GP relative reloc. */
6282static void
6283s_score_gpword (int ignore ATTRIBUTE_UNUSED)
6284{
6285 expressionS ex;
6286 char *p;
6287
6288 /* When not generating PIC code, this is treated as .word. */
6289 if (score_pic == NO_PIC)
6290 {
6291 cons (4);
6292 return;
6293 }
6294 expression (&ex);
6295 if (ex.X_op != O_symbol || ex.X_add_number != 0)
6296 {
6297 as_bad (_("Unsupported use of .gpword"));
6298 ignore_rest_of_line ();
6299 }
6300 p = frag_more (4);
6301 md_number_to_chars (p, (valueT) 0, 4);
6302 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
6303 demand_empty_rest_of_line ();
6304}
6305
6306/* Handle the .cpadd pseudo-op. This is used when dealing with switch
6307 tables in PIC code. */
6308
6309static void
6310s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
6311{
6312 int reg;
6313 char insn_str[MAX_LITERAL_POOL_SIZE];
6314
6315 /* If we are not generating PIC code, .cpload is ignored. */
6316 if (score_pic == NO_PIC)
6317 {
6318 s_ignore (0);
6319 return;
6320 }
6321
6322 if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
6323 {
6324 return;
6325 }
6326 demand_empty_rest_of_line ();
6327
6328 /* Add $gp to the register named as an argument. */
14119072 6329 sprintf (insn_str, _("add r%d, r%d, r%d"), reg, reg, GP);
1c0d3aa6
NC
6330 if (append_insn (insn_str, TRUE) == (int) FAIL)
6331 return;
6332}
6333
6334#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
6335#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
6336 do \
6337 { \
6338 if ((SIZE) >= 8) \
6339 (P2VAR) = 3; \
6340 else if ((SIZE) >= 4) \
6341 (P2VAR) = 2; \
6342 else if ((SIZE) >= 2) \
6343 (P2VAR) = 1; \
6344 else \
6345 (P2VAR) = 0; \
6346 } \
6347 while (0)
6348#endif
6349
6350static void
6351s_score_lcomm (int bytes_p)
6352{
6353 char *name;
6354 char c;
6355 char *p;
6356 int temp;
6357 symbolS *symbolP;
6358 segT current_seg = now_seg;
6359 subsegT current_subseg = now_subseg;
6360 const int max_alignment = 15;
6361 int align = 0;
6362 segT bss_seg = bss_section;
6363 int needs_align = 0;
6364
6365 name = input_line_pointer;
6366 c = get_symbol_end ();
6367 p = input_line_pointer;
6368 *p = c;
6369
6370 if (name == p)
6371 {
6372 as_bad (_("expected symbol name"));
6373 discard_rest_of_line ();
6374 return;
6375 }
6376
6377 SKIP_WHITESPACE ();
6378
6379 /* Accept an optional comma after the name. The comma used to be
6380 required, but Irix 5 cc does not generate it. */
6381 if (*input_line_pointer == ',')
6382 {
6383 ++input_line_pointer;
6384 SKIP_WHITESPACE ();
6385 }
6386
6387 if (is_end_of_line[(unsigned char)*input_line_pointer])
6388 {
6389 as_bad (_("missing size expression"));
6390 return;
6391 }
6392
6393 if ((temp = get_absolute_expression ()) < 0)
6394 {
6395 as_warn (_("BSS length (%d) < 0 ignored"), temp);
6396 ignore_rest_of_line ();
6397 return;
6398 }
6399
6400#if defined (TC_SCORE)
6401 if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6402 {
6403 /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
6404 if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
6405 {
6406 bss_seg = subseg_new (".sbss", 1);
6407 seg_info (bss_seg)->bss = 1;
6408#ifdef BFD_ASSEMBLER
6409 if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6410 as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6411#endif
6412 }
6413 }
6414#endif
6415
6416 SKIP_WHITESPACE ();
6417 if (*input_line_pointer == ',')
6418 {
6419 ++input_line_pointer;
6420 SKIP_WHITESPACE ();
6421
6422 if (is_end_of_line[(unsigned char)*input_line_pointer])
6423 {
6424 as_bad (_("missing alignment"));
6425 return;
6426 }
6427 else
6428 {
6429 align = get_absolute_expression ();
6430 needs_align = 1;
6431 }
6432 }
6433
6434 if (!needs_align)
6435 {
6436 TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6437
6438 /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
6439 if (align)
6440 record_alignment (bss_seg, align);
6441 }
6442
6443 if (needs_align)
6444 {
6445 if (bytes_p)
6446 {
6447 /* Convert to a power of 2. */
6448 if (align != 0)
6449 {
6450 unsigned int i;
6451
6452 for (i = 0; align != 0; align >>= 1, ++i)
6453 ;
6454 align = i - 1;
6455 }
6456 }
6457
6458 if (align > max_alignment)
6459 {
6460 align = max_alignment;
6461 as_warn (_("alignment too large; %d assumed"), align);
6462 }
6463 else if (align < 0)
6464 {
6465 align = 0;
6466 as_warn (_("alignment negative; 0 assumed"));
6467 }
6468
6469 record_alignment (bss_seg, align);
6470 }
6471 else
6472 {
6473 /* Assume some objects may require alignment on some systems. */
6474#if defined (TC_ALPHA) && ! defined (VMS)
6475 if (temp > 1)
6476 {
6477 align = ffs (temp) - 1;
6478 if (temp % (1 << align))
6479 abort ();
6480 }
6481#endif
6482 }
6483
6484 *p = 0;
6485 symbolP = symbol_find_or_make (name);
6486 *p = c;
6487
6488 if (
6489#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6490 || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6491#ifdef BFD_ASSEMBLER
6492 (OUTPUT_FLAVOR != bfd_target_aout_flavour
6493 || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6494#else
6495 (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6496#endif
6497#endif
6498 (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6499 {
6500 char *pfrag;
6501
6502 subseg_set (bss_seg, 1);
6503
6504 if (align)
6505 frag_align (align, 0, 0);
6506
6507 /* Detach from old frag. */
6508 if (S_GET_SEGMENT (symbolP) == bss_seg)
6509 symbol_get_frag (symbolP)->fr_symbol = NULL;
6510
6511 symbol_set_frag (symbolP, frag_now);
6512 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6513 *pfrag = 0;
6514
6515
6516 S_SET_SEGMENT (symbolP, bss_seg);
6517
6518#ifdef OBJ_COFF
6519 /* The symbol may already have been created with a preceding
6520 ".globl" directive -- be careful not to step on storage class
6521 in that case. Otherwise, set it to static. */
6522 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6523 {
6524 S_SET_STORAGE_CLASS (symbolP, C_STAT);
6525 }
6526#endif /* OBJ_COFF */
6527
6528#ifdef S_SET_SIZE
6529 S_SET_SIZE (symbolP, temp);
6530#endif
6531 }
6532 else
6533 as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6534
6535 subseg_set (current_seg, current_subseg);
6536
6537 demand_empty_rest_of_line ();
6538}
6539
6540static void
6541insert_reg (const struct reg_entry *r, struct hash_control *htab)
6542{
6543 int i = 0;
6544 int len = strlen (r->name) + 2;
6545 char *buf = xmalloc (len);
6546 char *buf2 = xmalloc (len);
6547
6548 strcpy (buf + i, r->name);
6549 for (i = 0; buf[i]; i++)
6550 {
6551 buf2[i] = TOUPPER (buf[i]);
6552 }
6553 buf2[i] = '\0';
6554
6555 hash_insert (htab, buf, (void *) r);
6556 hash_insert (htab, buf2, (void *) r);
6557}
6558
6559static void
6560build_reg_hsh (struct reg_map *map)
6561{
6562 const struct reg_entry *r;
6563
6564 if ((map->htab = hash_new ()) == NULL)
6565 {
6566 as_fatal (_("virtual memory exhausted"));
6567 }
6568 for (r = map->names; r->name != NULL; r++)
6569 {
6570 insert_reg (r, map->htab);
6571 }
6572}
6573
6574void
6575md_begin (void)
6576{
6577 unsigned int i;
6578 segT seg;
6579 subsegT subseg;
6580
6581 if ((score_ops_hsh = hash_new ()) == NULL)
6582 as_fatal (_("virtual memory exhausted"));
6583
6584 build_score_ops_hsh ();
6585
6586 if ((dependency_insn_hsh = hash_new ()) == NULL)
6587 as_fatal (_("virtual memory exhausted"));
6588
6589 build_dependency_insn_hsh ();
6590
6591 for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
6592 build_reg_hsh (all_reg_maps + i);
6593
6594 /* Initialize dependency vector. */
6595 init_dependency_vector ();
6596
6597 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6598 seg = now_seg;
6599 subseg = now_subseg;
6600 pdr_seg = subseg_new (".pdr", (subsegT) 0);
6601 (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6602 (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
6603 subseg_set (seg, subseg);
6604
6605 if (USE_GLOBAL_POINTER_OPT)
6606 bfd_set_gp_size (stdoutput, g_switch_value);
6607}
6608
6609
6610const pseudo_typeS md_pseudo_table[] =
6611{
6612 {"bss", s_score_bss, 0},
6613 {"text", s_score_text, 0},
6614 {"word", cons, 4},
6615 {"long", cons, 4},
6616 {"extend", float_cons, 'x'},
6617 {"ldouble", float_cons, 'x'},
6618 {"packed", float_cons, 'p'},
6619 {"end", s_score_end, 0},
6620 {"ent", s_score_ent, 0},
6621 {"frame", s_score_frame, 0},
6622 {"rdata", s_change_sec, 'r'},
6623 {"sdata", s_change_sec, 's'},
6624 {"set", s_score_set, 0},
6625 {"mask", s_score_mask, 'R'},
6626 {"dword", cons, 8},
6627 {"lcomm", s_score_lcomm, 1},
6628 {"section", score_s_section, 0},
6629 {"cpload", s_score_cpload, 0},
6630 {"cprestore", s_score_cprestore, 0},
6631 {"gpword", s_score_gpword, 0},
6632 {"cpadd", s_score_cpadd, 0},
6633 {0, 0, 0}
6634};
6635
This page took 0.289199 seconds and 4 git commands to generate.