123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- /* tc-xc16x.c -- Assembler for the Infineon XC16X.
- Copyright (C) 2006-2022 Free Software Foundation, Inc.
- Contributed by KPIT Cummins Infosystems
- This file is part of GAS, the GNU Assembler.
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
- #include "as.h"
- #include "safe-ctype.h"
- #include "subsegs.h"
- #include "symcat.h"
- #include "opcodes/xc16x-desc.h"
- #include "opcodes/xc16x-opc.h"
- #include "cgen.h"
- #include "dwarf2dbg.h"
- #ifdef OBJ_ELF
- #include "elf/xc16x.h"
- #endif
- /* Structure to hold all of the different components describing
- an individual instruction. */
- typedef struct
- {
- const CGEN_INSN * insn;
- const CGEN_INSN * orig_insn;
- CGEN_FIELDS fields;
- #if CGEN_INT_INSN_P
- CGEN_INSN_INT buffer [1];
- #define INSN_VALUE(buf) (*(buf))
- #else
- unsigned char buffer [CGEN_MAX_INSN_SIZE];
- #define INSN_VALUE(buf) (buf)
- #endif
- char * addr;
- fragS * frag;
- int num_fixups;
- fixS * fixups [GAS_CGEN_MAX_FIXUPS];
- int indices [MAX_OPERAND_INSTANCES];
- }
- xc16x_insn;
- const char comment_chars[] = ";";
- const char line_comment_chars[] = "#";
- const char line_separator_chars[] = "";
- const char EXP_CHARS[] = "eE";
- const char FLT_CHARS[] = "dD";
- #define XC16X_SHORTOPTS ""
- const char * md_shortopts = XC16X_SHORTOPTS;
- struct option md_longopts[] =
- {
- {NULL, no_argument, NULL, 0}
- };
- size_t md_longopts_size = sizeof (md_longopts);
- static void
- xc16xlmode (int arg ATTRIBUTE_UNUSED)
- {
- if (stdoutput != NULL)
- if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16xl))
- as_warn (_("could not set architecture and machine"));
- }
- static void
- xc16xsmode (int arg ATTRIBUTE_UNUSED)
- {
- if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16xs))
- as_warn (_("could not set architecture and machine"));
- }
- static void
- xc16xmode (int arg ATTRIBUTE_UNUSED)
- {
- if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16x))
- as_warn (_("could not set architecture and machine"));
- }
- /* The target specific pseudo-ops which we support. */
- const pseudo_typeS md_pseudo_table[] =
- {
- { "word", cons, 2 },
- {"xc16xl", xc16xlmode, 0},
- {"xc16xs", xc16xsmode, 0},
- {"xc16x", xc16xmode, 0},
- { NULL, NULL, 0 }
- };
- void
- md_begin (void)
- {
- /* Initialize the `cgen' interface. */
- /* Set the machine number and endian. */
- gas_cgen_cpu_desc = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
- CGEN_CPU_OPEN_ENDIAN,
- CGEN_ENDIAN_LITTLE,
- CGEN_CPU_OPEN_END);
- xc16x_cgen_init_asm (gas_cgen_cpu_desc);
- /* This is a callback from cgen to gas to parse operands. */
- cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
- }
- void
- md_assemble (char *str)
- {
- xc16x_insn insn;
- char *errmsg;
- /* Initialize GAS's cgen interface for a new instruction. */
- gas_cgen_init_parse ();
- insn.insn = xc16x_cgen_assemble_insn
- (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
- if (!insn.insn)
- {
- as_bad ("%s", errmsg);
- return;
- }
- /* Doesn't really matter what we pass for RELAX_P here. */
- gas_cgen_finish_insn (insn.insn, insn.buffer,
- CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
- }
- /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
- Returns BFD_RELOC_NONE if no reloc type can be found.
- *FIXP may be modified if desired. */
- bfd_reloc_code_real_type
- md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
- const CGEN_OPERAND *operand,
- fixS *fixP)
- {
- switch (operand->type)
- {
- case XC16X_OPERAND_REL:
- /* ??? Adjust size? */
- fixP->fx_where += 1;
- fixP->fx_pcrel = 1;
- return BFD_RELOC_8_PCREL;
- case XC16X_OPERAND_CADDR:
- fixP->fx_size = 2;
- fixP->fx_where += 2;
- return BFD_RELOC_16;
- case XC16X_OPERAND_UIMM7:
- /* ??? Adjust size? */
- fixP->fx_where += 1;
- fixP->fx_pcrel = 1;
- return BFD_RELOC_8_PCREL;
- case XC16X_OPERAND_UIMM16:
- case XC16X_OPERAND_MEMORY:
- fixP->fx_size = 2;
- fixP->fx_where += 2;
- return BFD_RELOC_16;
- case XC16X_OPERAND_UPOF16:
- fixP->fx_size = 2;
- fixP->fx_where += 2;
- return BFD_RELOC_XC16X_POF;
- case XC16X_OPERAND_UPAG16:
- fixP->fx_size = 2;
- fixP->fx_where += 2;
- return BFD_RELOC_XC16X_PAG;
- case XC16X_OPERAND_USEG8:
- /* ??? This is an 8 bit field, why the 16 bit reloc? */
- fixP->fx_where += 1;
- return BFD_RELOC_XC16X_SEG;
- case XC16X_OPERAND_USEG16:
- case XC16X_OPERAND_USOF16:
- fixP->fx_size = 2;
- fixP->fx_where += 2;
- return BFD_RELOC_XC16X_SOF;
- default : /* Avoid -Wall warning. */
- break;
- }
- return BFD_RELOC_NONE;
- }
- /* Write a value out to the object file, using the appropriate endianness. */
- void
- md_number_to_chars (char * buf, valueT val, int n)
- {
- number_to_chars_littleendian (buf, val, n);
- }
- void
- md_show_usage (FILE * stream)
- {
- fprintf (stream, _(" XC16X specific command line options:\n"));
- }
- int
- md_parse_option (int c ATTRIBUTE_UNUSED,
- const char *arg ATTRIBUTE_UNUSED)
- {
- return 0;
- }
- const char *
- md_atof (int type, char *litP, int *sizeP)
- {
- return ieee_md_atof (type, litP, sizeP, false);
- }
- valueT
- md_section_align (segT segment, valueT size)
- {
- int align = bfd_section_alignment (segment);
- return ((size + (1 << align) - 1) & -(1 << align));
- }
- symbolS *
- md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
- {
- return NULL;
- }
- int
- md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
- segT segment_type ATTRIBUTE_UNUSED)
- {
- printf (_("call to md_estimate_size_before_relax \n"));
- abort ();
- }
- long
- md_pcrel_from (fixS *fixP)
- {
- long temp_val;
- temp_val=fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
- return temp_val;
- }
- long
- md_pcrel_from_section (fixS *fixP, segT sec)
- {
- if (fixP->fx_addsy != (symbolS *) NULL
- && (! S_IS_DEFINED (fixP->fx_addsy)
- || S_GET_SEGMENT (fixP->fx_addsy) != sec
- || S_IS_EXTERNAL (fixP->fx_addsy)
- || S_IS_WEAK (fixP->fx_addsy)))
- {
- return 0;
- }
- return md_pcrel_from (fixP);
- }
- arelent *
- tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
- {
- arelent *rel;
- bfd_reloc_code_real_type r_type;
- if (fixp->fx_subsy)
- {
- if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
- || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
- {
- as_bad_subtract (fixp);
- return NULL;
- }
- }
- rel = XNEW (arelent);
- rel->sym_ptr_ptr = XNEW (asymbol *);
- *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
- rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
- rel->addend = fixp->fx_offset;
- r_type = fixp->fx_r_type;
- #define DEBUG 0
- #if DEBUG
- fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
- fflush (stderr);
- #endif
- rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
- if (rel->howto == NULL)
- {
- as_bad_where (fixp->fx_file, fixp->fx_line,
- _("Cannot represent relocation type %s"),
- bfd_get_reloc_code_name (r_type));
- return NULL;
- }
- return rel;
- }
- void
- md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
- {
- /* FIXME: This absolute nonsense apparently is to make relative
- jumps "work". Of course, it breaks any other type of fixup. */
- if (!strstr (seg->name,".debug"))
- {
- if (*valP < 128)
- *valP /= 2;
- if (*valP>268435455)
- {
- *valP = *valP * (-1);
- *valP /= 2;
- *valP = 256 - (*valP);
- }
- }
- gas_cgen_md_apply_fix (fixP, valP, seg);
- return;
- }
- void
- md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
- segT seg ATTRIBUTE_UNUSED,
- fragS *fragP ATTRIBUTE_UNUSED)
- {
- printf (_("call to md_convert_frag \n"));
- abort ();
- }
|