]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-pj.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-pj.c
CommitLineData
ec2655a6 1/* tc-pj.c -- Assemble code for Pico Java
250d07de 2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
041dd5a9
ILT
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
ec2655a6 8 the Free Software Foundation; either version 3, or (at your option)
041dd5a9
ILT
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
4b4da160
NC
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
041dd5a9 20
a2429eb5 21/* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
041dd5a9
ILT
22
23#include "as.h"
3882b010 24#include "safe-ctype.h"
041dd5a9
ILT
25#include "opcode/pj.h"
26
041dd5a9
ILT
27extern const pj_opc_info_t pj_opc_info[512];
28
ea1562b3 29const char comment_chars[] = "!/";
041dd5a9 30const char line_separator_chars[] = ";";
ea1562b3 31const char line_comment_chars[] = "/!#";
041dd5a9
ILT
32
33static int pending_reloc;
629310ab 34static htab_t opcode_hash_control;
041dd5a9
ILT
35
36static void
ea1562b3 37little (int ignore ATTRIBUTE_UNUSED)
041dd5a9
ILT
38{
39 target_big_endian = 0;
40}
41
42static void
ea1562b3 43big (int ignore ATTRIBUTE_UNUSED)
041dd5a9
ILT
44{
45 target_big_endian = 1;
46}
47
ea1562b3
NC
48const pseudo_typeS md_pseudo_table[] =
49{
041dd5a9
ILT
50 {"ml", little, 0},
51 {"mb", big, 0},
52 {0, 0, 0}
53};
54
041dd5a9
ILT
55const char FLT_CHARS[] = "rRsSfFdDxXpP";
56const char EXP_CHARS[] = "eE";
57
58void
ea1562b3 59md_operand (expressionS *op)
041dd5a9
ILT
60{
61 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
62 {
63 if (pending_reloc)
a2429eb5 64 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
65 pending_reloc = BFD_RELOC_PJ_CODE_HI16;
66 input_line_pointer += 5;
67 expression (op);
68 }
ea1562b3 69
041dd5a9
ILT
70 if (strncmp (input_line_pointer, "%lo16", 5) == 0)
71 {
72 if (pending_reloc)
a2429eb5 73 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
74 pending_reloc = BFD_RELOC_PJ_CODE_LO16;
75 input_line_pointer += 5;
76 expression (op);
77 }
78}
79
a2429eb5 80/* Parse an expression and then restore the input line pointer. */
041dd5a9
ILT
81
82static char *
ea1562b3 83parse_exp_save_ilp (char *s, expressionS *op)
041dd5a9
ILT
84{
85 char *save = input_line_pointer;
ea1562b3 86
041dd5a9
ILT
87 input_line_pointer = s;
88 expression (op);
89 s = input_line_pointer;
90 input_line_pointer = save;
91 return s;
92}
93
94/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
95 reloc for a cons. We could use the definition there, except that
96 we want to handle magic pending reloc expressions specially. */
97
98void
62ebcb5c
AM
99pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp,
100 bfd_reloc_code_real_type r ATTRIBUTE_UNUSED)
041dd5a9 101{
a2429eb5 102 static int rv[5][2] =
041dd5a9
ILT
103 { { 0, 0 },
104 { BFD_RELOC_8, BFD_RELOC_8 },
105 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
106 { 0, 0 },
107 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
108
a2429eb5 109 fix_new_exp (frag, where, nbytes, exp, 0,
041dd5a9 110 pending_reloc ? pending_reloc
a2429eb5 111 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
041dd5a9
ILT
112
113 pending_reloc = 0;
114}
115
041dd5a9 116/* Turn a reloc description character from the pj-opc.h table into
a2429eb5 117 code which BFD can handle. */
041dd5a9
ILT
118
119static int
ea1562b3 120c_to_r (int x)
041dd5a9
ILT
121{
122 switch (x)
123 {
124 case O_R8:
125 return BFD_RELOC_8_PCREL;
126 case O_U8:
127 case O_8:
128 return BFD_RELOC_8;
129 case O_R16:
130 return BFD_RELOC_PJ_CODE_REL16;
131 case O_U16:
132 case O_16:
133 return BFD_RELOC_PJ_CODE_DIR16;
134 case O_R32:
135 return BFD_RELOC_PJ_CODE_REL32;
136 case O_32:
137 return BFD_RELOC_PJ_CODE_DIR32;
138 }
139 abort ();
140 return 0;
141}
142
041dd5a9 143/* Handler for the ipush fake opcode,
a2429eb5 144 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
041dd5a9
ILT
145
146static void
ea1562b3 147ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str)
041dd5a9 148{
041dd5a9
ILT
149 char *b = frag_more (6);
150 expressionS arg;
a2429eb5 151
041dd5a9
ILT
152 b[0] = 0x11;
153 b[3] = 0xed;
0e073f4c
AM
154 parse_exp_save_ilp (str + 1, &arg);
155 if (pending_reloc)
156 {
157 as_bad (_("can't have relocation for ipush"));
158 pending_reloc = 0;
159 }
041dd5a9 160
a2429eb5
NC
161 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
162 &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
041dd5a9 163 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
a2429eb5 164 &arg, 0, BFD_RELOC_PJ_CODE_HI16);
041dd5a9
ILT
165}
166
167/* Insert names into the opcode table which are really mini macros,
67c1ffbe 168 not opcodes. The fakeness is indicated with an opcode of -1. */
041dd5a9
ILT
169
170static void
ea1562b3
NC
171fake_opcode (const char *name,
172 void (*func) (struct pj_opc_info_t *, char *))
041dd5a9 173{
325801bd 174 pj_opc_info_t * fake = XNEW (pj_opc_info_t);
041dd5a9
ILT
175
176 fake->opcode = -1;
177 fake->opcode_next = -1;
0e073f4c 178 fake->u.func = func;
fe0e921f 179 str_hash_insert (opcode_hash_control, name, fake, 0);
041dd5a9
ILT
180}
181
041dd5a9 182/* Enter another entry into the opcode hash table so the same opcode
a2429eb5
NC
183 can have another name. */
184
041dd5a9 185static void
d3ce72d0 186alias (const char *new_name, const char *old)
041dd5a9 187{
629310ab 188 str_hash_insert (opcode_hash_control, new_name,
fe0e921f 189 str_hash_find (opcode_hash_control, old), 0);
041dd5a9
ILT
190}
191
041dd5a9
ILT
192/* This function is called once, at assembler startup time. It sets
193 up the hash table with all the opcodes in it, and also initializes
a2429eb5 194 some aliases for compatibility with other assemblers. */
041dd5a9
ILT
195
196void
ea1562b3 197md_begin (void)
041dd5a9
ILT
198{
199 const pj_opc_info_t *opcode;
629310ab 200 opcode_hash_control = str_htab_create ();
041dd5a9 201
a2429eb5 202 /* Insert names into hash table. */
0e073f4c 203 for (opcode = pj_opc_info; opcode->u.name; opcode++)
fe0e921f 204 str_hash_insert (opcode_hash_control, opcode->u.name, opcode, 0);
041dd5a9 205
a2429eb5 206 /* Insert the only fake opcode. */
041dd5a9
ILT
207 fake_opcode ("ipush", ipush_code);
208
a2429eb5 209 /* Add some aliases for opcode names. */
041dd5a9
ILT
210 alias ("ifeq_s", "ifeq");
211 alias ("ifne_s", "ifne");
212 alias ("if_icmpge_s", "if_icmpge");
213 alias ("if_icmpne_s", "if_icmpne");
214 alias ("if_icmpeq_s", "if_icmpeq");
215 alias ("if_icmpgt_s", "if_icmpgt");
216 alias ("goto_s", "goto");
217
218 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
219}
220
a2429eb5
NC
221/* This is the guts of the machine-dependent assembler. STR points to
222 a machine dependent instruction. This function is supposed to emit
223 the frags/bytes it assembles to. */
041dd5a9
ILT
224
225void
ea1562b3 226md_assemble (char *str)
041dd5a9 227{
2132e3a3
AM
228 char *op_start;
229 char *op_end;
041dd5a9 230
041dd5a9
ILT
231 pj_opc_info_t *opcode;
232 char *output;
233 int idx = 0;
234 char pend;
235
236 int nlen = 0;
237
a2429eb5 238 /* Drop leading whitespace. */
041dd5a9
ILT
239 while (*str == ' ')
240 str++;
241
a2429eb5 242 /* Find the op code end. */
2132e3a3
AM
243 op_start = str;
244 for (op_end = str;
245 *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
a2429eb5 246 op_end++)
041dd5a9
ILT
247 nlen++;
248
249 pend = *op_end;
250 *op_end = 0;
251
252 if (nlen == 0)
a2429eb5 253 as_bad (_("can't find opcode "));
041dd5a9 254
629310ab 255 opcode = (pj_opc_info_t *) str_hash_find (opcode_hash_control, op_start);
041dd5a9
ILT
256 *op_end = pend;
257
258 if (opcode == NULL)
259 {
a2429eb5 260 as_bad (_("unknown opcode %s"), op_start);
041dd5a9
ILT
261 return;
262 }
263
d4f4f3fb 264 dwarf2_emit_insn (0);
041dd5a9
ILT
265 if (opcode->opcode == -1)
266 {
a2429eb5
NC
267 /* It's a fake opcode. Dig out the args and pretend that was
268 what we were passed. */
0e073f4c 269 (*opcode->u.func) (opcode, op_end);
041dd5a9
ILT
270 }
271 else
272 {
8a267ea8 273 unsigned int an;
041dd5a9
ILT
274
275 output = frag_more (opcode->len);
276 output[idx++] = opcode->opcode;
277
278 if (opcode->opcode_next != -1)
279 output[idx++] = opcode->opcode_next;
280
8a267ea8 281 for (an = 0; an < ARRAY_SIZE (opcode->arg) && opcode->arg[an]; an++)
041dd5a9
ILT
282 {
283 expressionS arg;
284
285 if (*op_end == ',' && an != 0)
286 op_end++;
287
288 if (*op_end == 0)
9fd07943 289 as_bad (_("expected expression"));
041dd5a9
ILT
290
291 op_end = parse_exp_save_ilp (op_end, &arg);
292
a2429eb5 293 fix_new_exp (frag_now,
041dd5a9
ILT
294 output - frag_now->fr_literal + idx,
295 ASIZE (opcode->arg[an]),
296 &arg,
a2429eb5 297 PCREL (opcode->arg[an]),
041dd5a9
ILT
298 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
299
300 idx += ASIZE (opcode->arg[an]);
301 pending_reloc = 0;
302 }
303
3882b010 304 while (ISSPACE (*op_end))
041dd5a9
ILT
305 op_end++;
306
307 if (*op_end != 0)
20203fb9 308 as_warn (_("extra stuff on line ignored"));
041dd5a9
ILT
309
310 }
311
312 if (pending_reloc)
20203fb9 313 as_bad (_("Something forgot to clean up\n"));
041dd5a9
ILT
314}
315
6d4af3c2 316const char *
ea1562b3 317md_atof (int type, char *litP, int *sizeP)
041dd5a9 318{
499ac353 319 return ieee_md_atof (type, litP, sizeP, target_big_endian);
041dd5a9
ILT
320}
321\f
5a38dc70 322const char *md_shortopts = "";
041dd5a9 323
ea1562b3
NC
324struct option md_longopts[] =
325{
041dd5a9
ILT
326#define OPTION_LITTLE (OPTION_MD_BASE)
327#define OPTION_BIG (OPTION_LITTLE + 1)
328
329 {"little", no_argument, NULL, OPTION_LITTLE},
330 {"big", no_argument, NULL, OPTION_BIG},
331 {NULL, no_argument, NULL, 0}
332};
333size_t md_longopts_size = sizeof (md_longopts);
334
335int
17b9d67d 336md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
041dd5a9
ILT
337{
338 switch (c)
339 {
340 case OPTION_LITTLE:
0e073f4c 341 little (0);
041dd5a9
ILT
342 break;
343 case OPTION_BIG:
0e073f4c 344 big (0);
041dd5a9
ILT
345 break;
346 default:
347 return 0;
348 }
349 return 1;
350}
351
352void
ea1562b3 353md_show_usage (FILE *stream)
041dd5a9 354{
a2429eb5 355 fprintf (stream, _("\
041dd5a9
ILT
356PJ options:\n\
357-little generate little endian code\n\
358-big generate big endian code\n"));
359}
360
041dd5a9
ILT
361/* Apply a fixup to the object file. */
362
94f592af 363void
55cf6793 364md_apply_fix (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
041dd5a9
ILT
365{
366 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
a161fe53 367 long val = *valP;
041dd5a9 368 long max, min;
041dd5a9 369
041dd5a9 370 max = min = 0;
041dd5a9
ILT
371 switch (fixP->fx_r_type)
372 {
373 case BFD_RELOC_VTABLE_INHERIT:
374 case BFD_RELOC_VTABLE_ENTRY:
375 fixP->fx_done = 0;
94f592af 376 return;
041dd5a9
ILT
377
378 case BFD_RELOC_PJ_CODE_REL16:
379 if (val < -0x8000 || val >= 0x7fff)
a2429eb5 380 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
041dd5a9
ILT
381 buf[0] |= (val >> 8) & 0xff;
382 buf[1] = val & 0xff;
383 break;
384
385 case BFD_RELOC_PJ_CODE_HI16:
386 *buf++ = val >> 24;
387 *buf++ = val >> 16;
388 fixP->fx_addnumber = val & 0xffff;
389 break;
390
391 case BFD_RELOC_PJ_CODE_DIR16:
392 case BFD_RELOC_PJ_CODE_LO16:
393 *buf++ = val >> 8;
394 *buf++ = val >> 0;
395
396 max = 0xffff;
397 min = -0xffff;
398 break;
399
400 case BFD_RELOC_8:
401 max = 0xff;
402 min = -0xff;
403 *buf++ = val;
404 break;
405
406 case BFD_RELOC_PJ_CODE_DIR32:
407 *buf++ = val >> 24;
408 *buf++ = val >> 16;
409 *buf++ = val >> 8;
410 *buf++ = val >> 0;
411 break;
412
413 case BFD_RELOC_32:
414 if (target_big_endian)
415 {
416 *buf++ = val >> 24;
417 *buf++ = val >> 16;
418 *buf++ = val >> 8;
419 *buf++ = val >> 0;
420 }
a2429eb5 421 else
041dd5a9
ILT
422 {
423 *buf++ = val >> 0;
424 *buf++ = val >> 8;
425 *buf++ = val >> 16;
426 *buf++ = val >> 24;
427 }
428 break;
429
430 case BFD_RELOC_16:
431 if (target_big_endian)
432 {
433 *buf++ = val >> 8;
434 *buf++ = val >> 0;
435 }
436 else
437 {
438 *buf++ = val >> 0;
439 *buf++ = val >> 8;
440 }
441 break;
442
3ee6e4fb
NC
443 case BFD_RELOC_PJ_CODE_REL32:
444 fixP->fx_done = 0;
445 return;
446
041dd5a9
ILT
447 default:
448 abort ();
449 }
450
451 if (max != 0 && (val < min || val > max))
a2429eb5 452 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
041dd5a9 453
94f592af
NC
454 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
455 fixP->fx_done = 1;
041dd5a9
ILT
456}
457
458/* Put number into target byte order. Always put values in an
a2429eb5 459 executable section into big endian order. */
041dd5a9
ILT
460
461void
ea1562b3 462md_number_to_chars (char *ptr, valueT use, int nbytes)
041dd5a9
ILT
463{
464 if (target_big_endian || now_seg->flags & SEC_CODE)
465 number_to_chars_bigendian (ptr, use, nbytes);
466 else
467 number_to_chars_littleendian (ptr, use, nbytes);
468}
469
041dd5a9 470/* Translate internal representation of relocation info to BFD target
a2429eb5 471 format. */
041dd5a9
ILT
472
473arelent *
ea1562b3 474tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
041dd5a9
ILT
475{
476 arelent *rel;
477 bfd_reloc_code_real_type r_type;
478
325801bd
TS
479 rel = XNEW (arelent);
480 rel->sym_ptr_ptr = XNEW (asymbol *);
041dd5a9
ILT
481 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
482 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
483
484 r_type = fixp->fx_r_type;
485 rel->addend = fixp->fx_addnumber;
486 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
487
488 if (rel->howto == NULL)
489 {
490 as_bad_where (fixp->fx_file, fixp->fx_line,
a2429eb5 491 _("Cannot represent relocation type %s"),
041dd5a9
ILT
492 bfd_get_reloc_code_name (r_type));
493 /* Set howto to a garbage value so that we can keep going. */
494 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
9c2799c2 495 gas_assert (rel->howto != NULL);
041dd5a9
ILT
496 }
497
498 return rel;
499}