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