Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Typedefs | Enumerations | Functions | Variables
tc-m68hc11.c File Reference
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "opcode/m68hc11.h"
#include "dwarf2dbg.h"
#include "elf/m68hc11.h"

Go to the source code of this file.

Classes

struct  operand
struct  m68hc11_opcode_def
struct  alias

Defines

#define STATE_CONDITIONAL_BRANCH   (1)
#define STATE_PC_RELATIVE   (2)
#define STATE_INDEXED_OFFSET   (3)
#define STATE_INDEXED_PCREL   (4)
#define STATE_XBCC_BRANCH   (5)
#define STATE_CONDITIONAL_BRANCH_6812   (6)
#define STATE_BYTE   (0)
#define STATE_BITS5   (0)
#define STATE_WORD   (1)
#define STATE_BITS9   (1)
#define STATE_LONG   (2)
#define STATE_BITS16   (2)
#define STATE_UNDF   (3) /* Symbol undefined in pass1 */
#define ENCODE_RELAX(what, length)   (((what) << 2) + (length))
#define RELAX_STATE(s)   ((s) >> 2)
#define RELAX_LENGTH(s)   ((s) & 3)
#define IS_OPCODE(C1, C2)   (((C1) & 0x0FF) == ((C2) & 0x0FF))
#define OPTION_FORCE_LONG_BRANCH   (OPTION_MD_BASE)
#define OPTION_SHORT_BRANCHES   (OPTION_MD_BASE + 1)
#define OPTION_STRICT_DIRECT_MODE   (OPTION_MD_BASE + 2)
#define OPTION_PRINT_INSN_SYNTAX   (OPTION_MD_BASE + 3)
#define OPTION_PRINT_OPCODES   (OPTION_MD_BASE + 4)
#define OPTION_GENERATE_EXAMPLE   (OPTION_MD_BASE + 5)
#define OPTION_MSHORT   (OPTION_MD_BASE + 6)
#define OPTION_MLONG   (OPTION_MD_BASE + 7)
#define OPTION_MSHORT_DOUBLE   (OPTION_MD_BASE + 8)
#define OPTION_MLONG_DOUBLE   (OPTION_MD_BASE + 9)
#define MAX_LITTLENUMS   6
#define IS_CALL_SYMBOL(MODE)
#define M6811_OP_CALL_ADDR   0x00800000
#define M6811_OP_PAGE_ADDR   0x04000000
#define M6812_AUTO_INC_DEC
#define OP_EXTENDED   (M6811_OP_PAGE2 | M6811_OP_PAGE3 | M6811_OP_PAGE4)
#define M6812_XBCC_MARKER

Typedefs

typedef enum register_id register_id
typedef struct operand operand
typedef struct alias alias

Enumerations

enum  register_id {
  REG_NONE = -1, REG_A = 0, REG_B = 1, REG_CCR = 2,
  REG_D = 4, REG_X = 5, REG_Y = 6, REG_SP = 7,
  REG_PC = 8
}

Functions

static register_id reg_name_search (char *)
static register_id register_name (void)
static int cmp_opcode (struct m68hc11_opcode *, struct m68hc11_opcode *)
static char * print_opcode_format (struct m68hc11_opcode *, int)
static char * skip_whites (char *)
static int check_range (long, int)
static void print_opcode_list (void)
static void get_default_target (void)
static void print_insn_format (char *)
static int get_operand (operand *, int, long)
static void fixup8 (expressionS *, int, int)
static void fixup16 (expressionS *, int, int)
static void fixup24 (expressionS *, int, int)
static unsigned char convert_branch (unsigned char)
static char * m68hc11_new_insn (int)
static void build_dbranch_insn (struct m68hc11_opcode *, operand *, int, int)
static int build_indexed_byte (operand *, int, int)
static int build_reg_mode (operand *, int)
static struct m68hc11_opcodefind (struct m68hc11_opcode_def *, operand *, int)
static struct m68hc11_opcodefind_opcode (struct m68hc11_opcode_def *, operand *, int *)
static void build_jump_insn (struct m68hc11_opcode *, operand *, int, int)
static void build_insn (struct m68hc11_opcode *, operand *, int)
static int relaxable_symbol (symbolS *)
static void s_m68hc11_relax (int)
static void s_m68hc11_mode (int)
static void s_m68hc11_mark_symbol (int)
const char * m68hc11_arch_format (void)
enum bfd_architecture m68hc11_arch (void)
int m68hc11_mach (void)
const char * m68hc11_listing_header (void)
void md_show_usage (FILE *stream)
void m68hc11_print_statistics (FILE *file)
int md_parse_option (int c, char *arg)
symbolS * md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
char * md_atof (int type, char *litP, int *sizeP)
valueT md_section_align (asection *seg, valueT addr)
void md_begin (void)
void m68hc11_init_after_args (void)
static void fixup16 (expressionS *oper, int mode, int opmode ATTRIBUTE_UNUSED)
static void fixup24 (expressionS *oper, int mode, int opmode ATTRIBUTE_UNUSED)
static void build_jump_insn (struct m68hc11_opcode *opcode, operand operands[], int nb_operands, int jmp_mode)
static void build_dbranch_insn (struct m68hc11_opcode *opcode, operand operands[], int nb_operands, int jmp_mode)
static int build_indexed_byte (operand *op, int format ATTRIBUTE_UNUSED, int move_insn)
static void build_insn (struct m68hc11_opcode *opcode, operand operands[], int nb_operands ATTRIBUTE_UNUSED)
static struct m68hc11_opcodefind (struct m68hc11_opcode_def *opc, operand operands[], int nb_operands)
static struct m68hc11_opcodefind_opcode (struct m68hc11_opcode_def *opc, operand operands[], int *nb_operands)
void md_assemble (char *str)
static void s_m68hc11_mode (int x ATTRIBUTE_UNUSED)
static void s_m68hc11_relax (int ignore ATTRIBUTE_UNUSED)
long md_pcrel_from (fixS *fixP)
arelenttc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
long m68hc11_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
void md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED, fragS *fragP)
int md_estimate_size_before_relax (fragS *fragP, asection *segment)
int tc_m68hc11_force_relocation (fixS *fixP)
int tc_m68hc11_fix_adjustable (fixS *fixP)
void md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
void m68hc11_elf_final_processing (void)

Variables

const char comment_chars [] = ";!"
const char line_comment_chars [] = "#*"
const char line_separator_chars [] = ""
const char EXP_CHARS [] = "eE"
const char FLT_CHARS [] = "dD"
relax_typeS md_relax_table []
static struct m68hc11_opcode_defm68hc11_opcode_defs = 0
static int m68hc11_nb_opcode_defs = 0
static alias alias_opcodes []
static short flag_fixed_branches = 0
static short flag_force_long_jumps = 0
static short flag_strict_direct_addressing = 1
static short flag_print_insn_syntax = 0
static short flag_print_opcodes = 0
static struct hash_controlm68hc11_hash
static int current_architecture = 0
static const char * default_cpu
static int num_opcodes
static struct m68hc11_opcodem68hc11_sorted_opcodes
static int elf_flags = E_M68HC11_F64
const pseudo_typeS md_pseudo_table []
const char * md_shortopts = "Sm:"
size_t md_longopts_size = sizeof (md_longopts)

Class Documentation

struct operand

Definition at line 131 of file tc-m68hc11.c.

Collaboration diagram for operand:
Class Members
struct operand direct
expressionS exp
struct operand immediate
struct operand indirect
int mode
unsigned op_type
struct operand reg
register_id reg1
register_id reg2
struct m68hc11_opcode_def

Definition at line 138 of file tc-m68hc11.c.

Collaboration diagram for m68hc11_opcode_def:
Class Members
long format
int max_operands
int min_operands
int nb_modes
struct m68hc11_opcode * opcode
int used
struct alias

Definition at line 11864 of file tc-ia64.c.

Class Members
const char * alias
char * file
unsigned int line
const char * name

Define Documentation

#define ENCODE_RELAX (   what,
  length 
)    (((what) << 2) + (length))

Definition at line 53 of file tc-m68hc11.c.

#define IS_CALL_SYMBOL (   MODE)
Value:

Definition at line 588 of file tc-m68hc11.c.

#define IS_OPCODE (   C1,
  C2 
)    (((C1) & 0x0FF) == ((C2) & 0x0FF))

Definition at line 57 of file tc-m68hc11.c.

#define M6811_OP_CALL_ADDR   0x00800000

Definition at line 971 of file tc-m68hc11.c.

#define M6811_OP_PAGE_ADDR   0x04000000

Definition at line 972 of file tc-m68hc11.c.

Value:

Definition at line 1319 of file tc-m68hc11.c.

#define MAX_LITTLENUMS   6

Definition at line 518 of file tc-m68hc11.c.

Definition at line 1806 of file tc-m68hc11.c.

#define OPTION_MLONG   (OPTION_MD_BASE + 7)
#define OPTION_MLONG_DOUBLE   (OPTION_MD_BASE + 9)
#define OPTION_MSHORT   (OPTION_MD_BASE + 6)
#define RELAX_LENGTH (   s)    ((s) & 3)

Definition at line 55 of file tc-m68hc11.c.

#define RELAX_STATE (   s)    ((s) >> 2)

Definition at line 54 of file tc-m68hc11.c.

#define STATE_BITS16   (2)

Definition at line 49 of file tc-m68hc11.c.

#define STATE_BITS5   (0)

Definition at line 45 of file tc-m68hc11.c.

#define STATE_BITS9   (1)

Definition at line 47 of file tc-m68hc11.c.

#define STATE_BYTE   (0)

Definition at line 44 of file tc-m68hc11.c.

#define STATE_CONDITIONAL_BRANCH   (1)

Definition at line 37 of file tc-m68hc11.c.

Definition at line 42 of file tc-m68hc11.c.

#define STATE_INDEXED_OFFSET   (3)

Definition at line 39 of file tc-m68hc11.c.

#define STATE_INDEXED_PCREL   (4)

Definition at line 40 of file tc-m68hc11.c.

#define STATE_LONG   (2)

Definition at line 48 of file tc-m68hc11.c.

#define STATE_PC_RELATIVE   (2)

Definition at line 38 of file tc-m68hc11.c.

#define STATE_UNDF   (3) /* Symbol undefined in pass1 */

Definition at line 50 of file tc-m68hc11.c.

#define STATE_WORD   (1)

Definition at line 46 of file tc-m68hc11.c.

#define STATE_XBCC_BRANCH   (5)

Definition at line 41 of file tc-m68hc11.c.


Typedef Documentation

typedef struct alias alias
static segT operand

Definition at line 713 of file expr.c.

{
  char c;
  symbolS *symbolP;  /* Points to symbol.  */
  char *name;        /* Points to name of symbol.  */
  segT segment;

  /* All integers are regarded as unsigned unless they are negated.
     This is because the only thing which cares whether a number is
     unsigned is the code in emit_expr which extends constants into
     bignums.  It should only sign extend negative numbers, so that
     something like ``.quad 0x80000000'' is not sign extended even
     though it appears negative if valueT is 32 bits.  */
  expressionP->X_unsigned = 1;

  /* Digits, assume it is a bignum.  */

  SKIP_WHITESPACE ();              /* Leading whitespace is part of operand.  */
  c = *input_line_pointer++;       /* input_line_pointer -> past char in c.  */

  if (is_end_of_line[(unsigned char) c])
    goto eol;

  switch (c)
    {
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      input_line_pointer--;

      integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)
                     ? 0 : 10,
                     expressionP);
      break;

#ifdef LITERAL_PREFIXDOLLAR_HEX
    case '$':
      /* $L is the start of a local label, not a hex constant.  */
      if (* input_line_pointer == 'L')
      goto isname;
      integer_constant (16, expressionP);
      break;
#endif

#ifdef LITERAL_PREFIXPERCENT_BIN
    case '%':
      integer_constant (2, expressionP);
      break;
#endif

    case '0':
      /* Non-decimal radix.  */

      if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)
       {
         char *s;

         /* Check for a hex or float constant.  */
         for (s = input_line_pointer; hex_p (*s); s++)
           ;
         if (*s == 'h' || *s == 'H' || *input_line_pointer == '.')
           {
             --input_line_pointer;
             integer_constant (0, expressionP);
             break;
           }
       }
      c = *input_line_pointer;
      switch (c)
       {
       case 'o':
       case 'O':
       case 'q':
       case 'Q':
       case '8':
       case '9':
         if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)
           {
             integer_constant (0, expressionP);
             break;
           }
         /* Fall through.  */
       default:
       default_case:
         if (c && strchr (FLT_CHARS, c))
           {
             input_line_pointer++;
             floating_constant (expressionP);
             expressionP->X_add_number = - TOLOWER (c);
           }
         else
           {
             /* The string was only zero.  */
             expressionP->X_op = O_constant;
             expressionP->X_add_number = 0;
           }

         break;

       case 'x':
       case 'X':
         if (flag_m68k_mri)
           goto default_case;
         input_line_pointer++;
         integer_constant (16, expressionP);
         break;

       case 'b':
         if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX))
           {
             /* This code used to check for '+' and '-' here, and, in
               some conditions, fall through to call
               integer_constant.  However, that didn't make sense,
               as integer_constant only accepts digits.  */
             /* Some of our code elsewhere does permit digits greater
               than the expected base; for consistency, do the same
               here.  */
             if (input_line_pointer[1] < '0'
                || input_line_pointer[1] > '9')
              {
                /* Parse this as a back reference to label 0.  */
                input_line_pointer--;
                integer_constant (10, expressionP);
                break;
              }
             /* Otherwise, parse this as a binary number.  */
           }
         /* Fall through.  */
       case 'B':
         input_line_pointer++;
         if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)
           goto default_case;
         integer_constant (2, expressionP);
         break;

       case '0':
       case '1':
       case '2':
       case '3':
       case '4':
       case '5':
       case '6':
       case '7':
         integer_constant ((flag_m68k_mri || NUMBERS_WITH_SUFFIX)
                         ? 0 : 8,
                         expressionP);
         break;

       case 'f':
         if (LOCAL_LABELS_FB)
           {
             /* If it says "0f" and it could possibly be a floating point
               number, make it one.  Otherwise, make it a local label,
               and try to deal with parsing the rest later.  */
             if (!input_line_pointer[1]
                || (is_end_of_line[0xff & input_line_pointer[1]])
                || strchr (FLT_CHARS, 'f') == NULL)
              goto is_0f_label;
             {
              char *cp = input_line_pointer + 1;
              int r = atof_generic (&cp, ".", EXP_CHARS,
                                  &generic_floating_point_number);
              switch (r)
                {
                case 0:
                case ERROR_EXPONENT_OVERFLOW:
                  if (*cp == 'f' || *cp == 'b')
                    /* Looks like a difference expression.  */
                    goto is_0f_label;
                  else if (cp == input_line_pointer + 1)
                    /* No characters has been accepted -- looks like
                      end of operand.  */
                    goto is_0f_label;
                  else
                    goto is_0f_float;
                default:
                  as_fatal (_("expr.c(operand): bad atof_generic return val %d"),
                           r);
                }
             }

             /* Okay, now we've sorted it out.  We resume at one of these
               two labels, depending on what we've decided we're probably
               looking at.  */
           is_0f_label:
             input_line_pointer--;
             integer_constant (10, expressionP);
             break;

           is_0f_float:
             /* Fall through.  */
             ;
           }

       case 'd':
       case 'D':
         if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)
           {
             integer_constant (0, expressionP);
             break;
           }
         /* Fall through.  */
       case 'F':
       case 'r':
       case 'e':
       case 'E':
       case 'g':
       case 'G':
         input_line_pointer++;
         floating_constant (expressionP);
         expressionP->X_add_number = - TOLOWER (c);
         break;

       case '$':
         if (LOCAL_LABELS_DOLLAR)
           {
             integer_constant (10, expressionP);
             break;
           }
         else
           goto default_case;
       }

      break;

    case '(':
#ifndef NEED_INDEX_OPERATOR
    case '[':
#endif
      /* Didn't begin with digit & not a name.  */
      if (mode != expr_defer)
       segment = expression (expressionP);
      else
       segment = deferred_expression (expressionP);
      /* expression () will pass trailing whitespace.  */
      if ((c == '(' && *input_line_pointer != ')')
         || (c == '[' && *input_line_pointer != ']'))
       as_bad (_("missing '%c'"), c == '(' ? ')' : ']');
      else
       input_line_pointer++;
      SKIP_WHITESPACE ();
      /* Here with input_line_pointer -> char after "(...)".  */
      return segment;

#ifdef TC_M68K
    case 'E':
      if (! flag_m68k_mri || *input_line_pointer != '\'')
       goto de_fault;
      as_bad (_("EBCDIC constants are not supported"));
      /* Fall through.  */
    case 'A':
      if (! flag_m68k_mri || *input_line_pointer != '\'')
       goto de_fault;
      ++input_line_pointer;
      /* Fall through.  */
#endif
    case '\'':
      if (! flag_m68k_mri)
       {
         /* Warning: to conform to other people's assemblers NO
            ESCAPEMENT is permitted for a single quote.  The next
            character, parity errors and all, is taken as the value
            of the operand.  VERY KINKY.  */
         expressionP->X_op = O_constant;
         expressionP->X_add_number = *input_line_pointer++;
         break;
       }

      mri_char_constant (expressionP);
      break;

#ifdef TC_M68K
    case '"':
      /* Double quote is the bitwise not operator in MRI mode.  */
      if (! flag_m68k_mri)
       goto de_fault;
      /* Fall through.  */
#endif
    case '~':
      /* '~' is permitted to start a label on the Delta.  */
      if (is_name_beginner (c))
       goto isname;
    case '!':
    case '-':
    case '+':
      {
       operand (expressionP, mode);
       if (expressionP->X_op == O_constant)
         {
           /* input_line_pointer -> char after operand.  */
           if (c == '-')
             {
              expressionP->X_add_number = - expressionP->X_add_number;
              /* Notice: '-' may overflow: no warning is given.
                 This is compatible with other people's
                 assemblers.  Sigh.  */
              expressionP->X_unsigned = 0;
             }
           else if (c == '~' || c == '"')
             expressionP->X_add_number = ~ expressionP->X_add_number;
           else if (c == '!')
             expressionP->X_add_number = ! expressionP->X_add_number;
         }
       else if (expressionP->X_op == O_big
               && expressionP->X_add_number <= 0
               && c == '-'
               && (generic_floating_point_number.sign == '+'
                   || generic_floating_point_number.sign == 'P'))
         {
           /* Negative flonum (eg, -1.000e0).  */
           if (generic_floating_point_number.sign == '+')
             generic_floating_point_number.sign = '-';
           else
             generic_floating_point_number.sign = 'N';
         }
       else if (expressionP->X_op == O_big
               && expressionP->X_add_number > 0)
         {
           int i;

           if (c == '~' || c == '-')
             {
              for (i = 0; i < expressionP->X_add_number; ++i)
                generic_bignum[i] = ~generic_bignum[i];
              if (c == '-')
                for (i = 0; i < expressionP->X_add_number; ++i)
                  {
                    generic_bignum[i] += 1;
                    if (generic_bignum[i])
                     break;
                  }
             }
           else if (c == '!')
             {
              int nonzero = 0;
              for (i = 0; i < expressionP->X_add_number; ++i)
                {
                  if (generic_bignum[i])
                    nonzero = 1;
                  generic_bignum[i] = 0;
                }
              generic_bignum[0] = nonzero;
             }
         }
       else if (expressionP->X_op != O_illegal
               && expressionP->X_op != O_absent)
         {
           if (c != '+')
             {
              expressionP->X_add_symbol = make_expr_symbol (expressionP);
              if (c == '-')
                expressionP->X_op = O_uminus;
              else if (c == '~' || c == '"')
                expressionP->X_op = O_bit_not;
              else
                expressionP->X_op = O_logical_not;
              expressionP->X_add_number = 0;
             }
         }
       else
         as_warn (_("Unary operator %c ignored because bad operand follows"),
                 c);
      }
      break;

#if defined (DOLLAR_DOT) || defined (TC_M68K)
    case '$':
      /* '$' is the program counter when in MRI mode, or when
        DOLLAR_DOT is defined.  */
#ifndef DOLLAR_DOT
      if (! flag_m68k_mri)
       goto de_fault;
#endif
      if (DOLLAR_AMBIGU && hex_p (*input_line_pointer))
       {
         /* In MRI mode and on Z80, '$' is also used as the prefix
            for a hexadecimal constant.  */
         integer_constant (16, expressionP);
         break;
       }

      if (is_part_of_name (*input_line_pointer))
       goto isname;

      current_location (expressionP);
      break;
#endif

    case '.':
      if (!is_part_of_name (*input_line_pointer))
       {
         current_location (expressionP);
         break;
       }
      else if ((strncasecmp (input_line_pointer, "startof.", 8) == 0
              && ! is_part_of_name (input_line_pointer[8]))
              || (strncasecmp (input_line_pointer, "sizeof.", 7) == 0
                 && ! is_part_of_name (input_line_pointer[7])))
       {
         int start;

         start = (input_line_pointer[1] == 't'
                 || input_line_pointer[1] == 'T');
         input_line_pointer += start ? 8 : 7;
         SKIP_WHITESPACE ();
         if (*input_line_pointer != '(')
           as_bad (_("syntax error in .startof. or .sizeof."));
         else
           {
             char *buf;

             ++input_line_pointer;
             SKIP_WHITESPACE ();
             name = input_line_pointer;
             c = get_symbol_end ();

             buf = (char *) xmalloc (strlen (name) + 10);
             if (start)
              sprintf (buf, ".startof.%s", name);
             else
              sprintf (buf, ".sizeof.%s", name);
             symbolP = symbol_make (buf);
             free (buf);

             expressionP->X_op = O_symbol;
             expressionP->X_add_symbol = symbolP;
             expressionP->X_add_number = 0;

             *input_line_pointer = c;
             SKIP_WHITESPACE ();
             if (*input_line_pointer != ')')
              as_bad (_("syntax error in .startof. or .sizeof."));
             else
              ++input_line_pointer;
           }
         break;
       }
      else
       {
         goto isname;
       }

    case ',':
    eol:
      /* Can't imagine any other kind of operand.  */
      expressionP->X_op = O_absent;
      input_line_pointer--;
      break;

#ifdef TC_M68K
    case '%':
      if (! flag_m68k_mri)
       goto de_fault;
      integer_constant (2, expressionP);
      break;

    case '@':
      if (! flag_m68k_mri)
       goto de_fault;
      integer_constant (8, expressionP);
      break;

    case ':':
      if (! flag_m68k_mri)
       goto de_fault;

      /* In MRI mode, this is a floating point constant represented
        using hexadecimal digits.  */

      ++input_line_pointer;
      integer_constant (16, expressionP);
      break;

    case '*':
      if (! flag_m68k_mri || is_part_of_name (*input_line_pointer))
       goto de_fault;

      current_location (expressionP);
      break;
#endif

    default:
#ifdef TC_M68K
    de_fault:
#endif
      if (is_name_beginner (c))    /* Here if did not begin with a digit.  */
       {
         /* Identifier begins here.
            This is kludged for speed, so code is repeated.  */
       isname:
         name = --input_line_pointer;
         c = get_symbol_end ();

#ifdef md_parse_name
         /* This is a hook for the backend to parse certain names
            specially in certain contexts.  If a name always has a
            specific value, it can often be handled by simply
            entering it in the symbol table.  */
         if (md_parse_name (name, expressionP, mode, &c))
           {
             *input_line_pointer = c;
             break;
           }
#endif

#ifdef TC_I960
         /* The MRI i960 assembler permits
                lda sizeof code,g13
            FIXME: This should use md_parse_name.  */
         if (flag_mri
             && (strcasecmp (name, "sizeof") == 0
                || strcasecmp (name, "startof") == 0))
           {
             int start;
             char *buf;

             start = (name[1] == 't'
                     || name[1] == 'T');

             *input_line_pointer = c;
             SKIP_WHITESPACE ();

             name = input_line_pointer;
             c = get_symbol_end ();

             buf = (char *) xmalloc (strlen (name) + 10);
             if (start)
              sprintf (buf, ".startof.%s", name);
             else
              sprintf (buf, ".sizeof.%s", name);
             symbolP = symbol_make (buf);
             free (buf);

             expressionP->X_op = O_symbol;
             expressionP->X_add_symbol = symbolP;
             expressionP->X_add_number = 0;

             *input_line_pointer = c;
             SKIP_WHITESPACE ();

             break;
           }
#endif

         symbolP = symbol_find_or_make (name);

         /* If we have an absolute symbol or a reg, then we know its
            value now.  */
         segment = S_GET_SEGMENT (symbolP);
         if (mode != expr_defer && segment == absolute_section)
           {
             expressionP->X_op = O_constant;
             expressionP->X_add_number = S_GET_VALUE (symbolP);
           }
         else if (mode != expr_defer && segment == reg_section)
           {
             expressionP->X_op = O_register;
             expressionP->X_add_number = S_GET_VALUE (symbolP);
           }
         else
           {
             expressionP->X_op = O_symbol;
             expressionP->X_add_symbol = symbolP;
             expressionP->X_add_number = 0;
           }
         *input_line_pointer = c;
       }
      else
       {
         /* Let the target try to parse it.  Success is indicated by changing
            the X_op field to something other than O_absent and pointing
            input_line_pointer past the expression.  If it can't parse the
            expression, X_op and input_line_pointer should be unchanged.  */
         expressionP->X_op = O_absent;
         --input_line_pointer;
         md_operand (expressionP);
         if (expressionP->X_op == O_absent)
           {
             ++input_line_pointer;
             as_bad (_("bad expression"));
             expressionP->X_op = O_constant;
             expressionP->X_add_number = 0;
           }
       }
      break;
    }

  /* It is more 'efficient' to clean up the expressionS when they are
     created.  Doing it here saves lines of code.  */
  clean_up_expression (expressionP);
  SKIP_WHITESPACE ();              /* -> 1st char after operand.  */
  know (*input_line_pointer != ' ');

  /* The PA port needs this information.  */
  if (expressionP->X_add_symbol)
    symbol_mark_used (expressionP->X_add_symbol);

  expressionP->X_add_symbol = symbol_clone_if_forward_ref (expressionP->X_add_symbol);
  expressionP->X_op_symbol = symbol_clone_if_forward_ref (expressionP->X_op_symbol);

  switch (expressionP->X_op)
    {
    default:
      return absolute_section;
    case O_symbol:
      return S_GET_SEGMENT (expressionP->X_add_symbol);
    case O_register:
      return reg_section;
    }
}
typedef enum register_id register_id

Enumeration Type Documentation

Enumerator:
REG_NONE 
REG_A 
REG_B 
REG_CCR 
REG_D 
REG_X 
REG_Y 
REG_SP 
REG_PC 

Definition at line 119 of file tc-m68hc11.c.

                         {
  REG_NONE = -1,
  REG_A = 0,
  REG_B = 1,
  REG_CCR = 2,
  REG_D = 4,
  REG_X = 5,
  REG_Y = 6,
  REG_SP = 7,
  REG_PC = 8
} register_id;

Function Documentation

static void build_dbranch_insn ( struct m68hc11_opcode ,
operand ,
int  ,
int   
) [static]

Here is the caller graph for this function:

static void build_dbranch_insn ( struct m68hc11_opcode opcode,
operand  operands[],
int  nb_operands,
int  jmp_mode 
) [static]

Definition at line 1718 of file tc-m68hc11.c.

{
  unsigned char code;
  char *f;
  unsigned long n;

  /* The relative branch conversion is not supported for
     brclr and brset.  */
  assert ((opcode->format & M6811_OP_BITMASK) == 0);
  assert (nb_operands == 2);
  assert (operands[0].reg1 != REG_NONE);

  code = opcode->opcode & 0x0FF;

  f = m68hc11_new_insn (1);
  number_to_chars_bigendian (f, code, 1);

  n = operands[1].exp.X_add_number;
  code = operands[0].reg1;

  if (operands[0].reg1 == REG_NONE || operands[0].reg1 == REG_CCR
      || operands[0].reg1 == REG_PC)
    as_bad (_("Invalid register for dbcc/tbcc instruction."));

  if (opcode->format & M6812_OP_IBCC_MARKER)
    code |= 0x80;
  else if (opcode->format & M6812_OP_TBCC_MARKER)
    code |= 0x40;

  if (!(opcode->format & M6812_OP_EQ_MARKER))
    code |= 0x20;

  /* Turn into a long branch:
     - when force long branch option (and not for jbcc pseudos),
     - when jdbcc and the constant is out of -256..255 range,
     - when branch optimization is allowed and branch out of range.  */
  if ((jmp_mode == 0 && flag_force_long_jumps)
      || (operands[1].exp.X_op == O_constant
         && (!check_range (n, M6812_OP_IBCC_MARKER) &&
             (jmp_mode == 1 || flag_fixed_branches == 0))))
    {
      f = frag_more (2);
      code ^= 0x20;
      number_to_chars_bigendian (f, code, 1);
      number_to_chars_bigendian (f + 1, M6812_JMP, 1);
      fixup16 (&operands[0].exp, M6811_OP_IND16, M6811_OP_IND16);
      return;
    }

  /* Branch with a constant that must fit in 9-bits.  */
  if (operands[1].exp.X_op == O_constant)
    {
      if (!check_range (n, M6812_OP_IBCC_MARKER))
       {
         as_bad (_("Operand out of range for a relative branch: `%ld'"),
                  n);
       }
      else
       {
         if ((long) n < 0)
           code |= 0x10;

         f = frag_more (2);
         number_to_chars_bigendian (f, code, 1);
         number_to_chars_bigendian (f + 1, n & 0x0FF, 1);
       }
    }
  else
    {
      /* Branch offset must fit in 8-bits, don't do some relax.  */
      if (jmp_mode == 0 && flag_fixed_branches)
       {
         fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);
       }

      else
       {
         f = frag_more (2);
         number_to_chars_bigendian (f, code, 1);
         number_to_chars_bigendian (f + 1, 0, 1);
         frag_var (rs_machine_dependent, 3, 3,
                  ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_UNDF),
                  operands[1].exp.X_add_symbol, (offsetT) n, f);
       }
    }
}

Here is the call graph for this function:

static int build_indexed_byte ( operand ,
int  ,
int   
) [static]

Here is the caller graph for this function:

static int build_indexed_byte ( operand op,
int format  ATTRIBUTE_UNUSED,
int  move_insn 
) [static]

Definition at line 1810 of file tc-m68hc11.c.

{
  unsigned char byte = 0;
  char *f;
  int mode;
  long val;

  val = op->exp.X_add_number;
  mode = op->mode;
  if (mode & M6812_AUTO_INC_DEC)
    {
      byte = 0x20;
      if (mode & (M6812_POST_INC | M6812_POST_DEC))
       byte |= 0x10;

      if (op->exp.X_op == O_constant)
       {
         if (!check_range (val, mode))
           {
             as_bad (_("Increment/decrement value is out of range: `%ld'."),
                    val);
           }
         if (mode & (M6812_POST_INC | M6812_PRE_INC))
           byte |= (val - 1) & 0x07;
         else
           byte |= (8 - ((val) & 7)) | 0x8;
       }
      switch (op->reg1)
       {
       case REG_NONE:
         as_fatal (_("Expecting a register."));

       case REG_X:
         byte |= 0;
         break;

       case REG_Y:
         byte |= 0x40;
         break;

       case REG_SP:
         byte |= 0x80;
         break;

       default:
         as_bad (_("Invalid register for post/pre increment."));
         break;
       }

      f = frag_more (1);
      number_to_chars_bigendian (f, byte, 1);
      return 1;
    }

  if (mode & (M6812_OP_IDX | M6812_OP_D_IDX_2))
    {
      switch (op->reg1)
       {
       case REG_X:
         byte = 0;
         break;

       case REG_Y:
         byte = 1;
         break;

       case REG_SP:
         byte = 2;
         break;

       case REG_PC:
         byte = 3;
         break;

       default:
         as_bad (_("Invalid register."));
         break;
       }
      if (op->exp.X_op == O_constant)
       {
         if (!check_range (val, M6812_OP_IDX))
           {
             as_bad (_("Offset out of 16-bit range: %ld."), val);
           }

         if (move_insn && !(val >= -16 && val <= 15))
           {
             as_bad (_("Offset out of 5-bit range for movw/movb insn: %ld."),
                    val);
             return -1;
           }

         if (val >= -16 && val <= 15 && !(mode & M6812_OP_D_IDX_2))
           {
             byte = byte << 6;
             byte |= val & 0x1f;
             f = frag_more (1);
             number_to_chars_bigendian (f, byte, 1);
             return 1;
           }
         else if (val >= -256 && val <= 255 && !(mode & M6812_OP_D_IDX_2))
           {
             byte = byte << 3;
             byte |= 0xe0;
             if (val < 0)
              byte |= 0x1;
             f = frag_more (2);
             number_to_chars_bigendian (f, byte, 1);
             number_to_chars_bigendian (f + 1, val & 0x0FF, 1);
             return 2;
           }
         else
           {
             byte = byte << 3;
             if (mode & M6812_OP_D_IDX_2)
              byte |= 0xe3;
             else
              byte |= 0xe2;

             f = frag_more (3);
             number_to_chars_bigendian (f, byte, 1);
             number_to_chars_bigendian (f + 1, val & 0x0FFFF, 2);
             return 3;
           }
       }
      if (mode & M6812_OP_D_IDX_2)
        {
          byte = (byte << 3) | 0xe3;
          f = frag_more (1);
          number_to_chars_bigendian (f, byte, 1);

          fixup16 (&op->exp, 0, 0);
        }
      else if (op->reg1 != REG_PC)
       {
          symbolS *sym;
          offsetT off;

         f = frag_more (1);
         number_to_chars_bigendian (f, byte, 1);
          sym = op->exp.X_add_symbol;
          off = op->exp.X_add_number;
          if (op->exp.X_op != O_symbol)
            {
              sym = make_expr_symbol (&op->exp);
              off = 0;
            }
         /* movb/movw cannot be relaxed.  */
         if (move_insn)
           {
             byte <<= 6;
             number_to_chars_bigendian (f, byte, 1);
             fix_new (frag_now, f - frag_now->fr_literal, 1,
                     sym, off, 0, BFD_RELOC_M68HC12_5B);
             return 1;
           }
         else
           {
             number_to_chars_bigendian (f, byte, 1);
             frag_var (rs_machine_dependent, 2, 2,
                     ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
                     sym, off, f);
           }
       }
      else
       {
         f = frag_more (1);
         /* movb/movw cannot be relaxed.  */
         if (move_insn)
           {
             byte <<= 6;
             number_to_chars_bigendian (f, byte, 1);
             fix_new (frag_now, f - frag_now->fr_literal, 1,
                     op->exp.X_add_symbol, op->exp.X_add_number, 0, BFD_RELOC_M68HC12_5B);
             return 1;
           }
         else
           {
             number_to_chars_bigendian (f, byte, 1);
             frag_var (rs_machine_dependent, 2, 2,
                     ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_UNDF),
                     op->exp.X_add_symbol,
                     op->exp.X_add_number, f);
           }
       }
      return 3;
    }

  if (mode & (M6812_OP_REG | M6812_OP_D_IDX))
    {
      if (mode & M6812_OP_D_IDX)
       {
         if (op->reg1 != REG_D)
           as_bad (_("Expecting register D for indexed indirect mode."));
         if (move_insn)
           as_bad (_("Indexed indirect mode is not allowed for movb/movw."));

         byte = 0xE7;
       }
      else
       {
         switch (op->reg1)
           {
           case REG_A:
             byte = 0xE4;
             break;

           case REG_B:
             byte = 0xE5;
             break;

           default:
             as_bad (_("Invalid accumulator register."));

           case REG_D:
             byte = 0xE6;
             break;
           }
       }
      switch (op->reg2)
       {
       case REG_X:
         break;

       case REG_Y:
         byte |= (1 << 3);
         break;

       case REG_SP:
         byte |= (2 << 3);
         break;

       case REG_PC:
         byte |= (3 << 3);
         break;

       default:
         as_bad (_("Invalid indexed register."));
         break;
       }
      f = frag_more (1);
      number_to_chars_bigendian (f, byte, 1);
      return 1;
    }

  as_fatal (_("Addressing mode not implemented yet."));
  return 0;
}

Here is the call graph for this function:

static void build_insn ( struct m68hc11_opcode ,
operand ,
int   
) [static]
static void build_insn ( struct m68hc11_opcode opcode,
operand  operands[],
int nb_operands  ATTRIBUTE_UNUSED 
) [static]

Definition at line 2093 of file tc-m68hc11.c.

{
  int i;
  char *f;
  long format;
  int move_insn = 0;

  /* Put the page code instruction if there is one.  */
  format = opcode->format;

  if (format & M6811_OP_BRANCH)
    fix_new (frag_now, frag_now_fix (), 0,
             &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);

  if (format & OP_EXTENDED)
    {
      int page_code;

      f = m68hc11_new_insn (2);
      if (format & M6811_OP_PAGE2)
       page_code = M6811_OPCODE_PAGE2;
      else if (format & M6811_OP_PAGE3)
       page_code = M6811_OPCODE_PAGE3;
      else
       page_code = M6811_OPCODE_PAGE4;

      number_to_chars_bigendian (f, page_code, 1);
      f++;
    }
  else
    f = m68hc11_new_insn (1);

  number_to_chars_bigendian (f, opcode->opcode, 1);

  i = 0;

  /* The 68HC12 movb and movw instructions are special.  We have to handle
     them in a special way.  */
  if (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
    {
      move_insn = 1;
      if (format & M6812_OP_IDX)
       {
         build_indexed_byte (&operands[0], format, 1);
         i = 1;
         format &= ~M6812_OP_IDX;
       }
      if (format & M6812_OP_IDX_P2)
       {
         build_indexed_byte (&operands[1], format, 1);
         i = 0;
         format &= ~M6812_OP_IDX_P2;
       }
    }

  if (format & (M6811_OP_DIRECT | M6811_OP_IMM8))
    {
      fixup8 (&operands[i].exp,
             format & (M6811_OP_DIRECT | M6811_OP_IMM8 | M6812_OP_TRAP_ID),
             operands[i].mode);
      i++;
    }
  else if (IS_CALL_SYMBOL (format) && nb_operands == 1)
    {
      format &= ~M6812_OP_PAGE;
      fixup24 (&operands[i].exp, format & M6811_OP_IND16,
              operands[i].mode);
      i++;
    }
  else if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
    {
      fixup16 (&operands[i].exp,
               format & (M6811_OP_IMM16 | M6811_OP_IND16 | M6812_OP_PAGE),
              operands[i].mode);
      i++;
    }
  else if (format & (M6811_OP_IX | M6811_OP_IY))
    {
      if ((format & M6811_OP_IX) && (operands[0].reg1 != REG_X))
       as_bad (_("Invalid indexed register, expecting register X."));
      if ((format & M6811_OP_IY) && (operands[0].reg1 != REG_Y))
       as_bad (_("Invalid indexed register, expecting register Y."));

      fixup8 (&operands[0].exp, M6811_OP_IX, operands[0].mode);
      i = 1;
    }
  else if (format &
          (M6812_OP_IDX | M6812_OP_IDX_2 | M6812_OP_IDX_1
            | M6812_OP_D_IDX | M6812_OP_D_IDX_2))
    {
      build_indexed_byte (&operands[i], format, move_insn);
      i++;
    }
  else if (format & M6812_OP_REG && current_architecture & cpu6812)
    {
      build_reg_mode (&operands[i], format);
      i++;
    }
  if (format & M6811_OP_BITMASK)
    {
      fixup8 (&operands[i].exp, M6811_OP_BITMASK, operands[i].mode);
      i++;
    }
  if (format & M6811_OP_JUMP_REL)
    {
      fixup8 (&operands[i].exp, M6811_OP_JUMP_REL, operands[i].mode);
    }
  else if (format & M6812_OP_IND16_P2)
    {
      fixup16 (&operands[1].exp, M6811_OP_IND16, operands[1].mode);
    }
  if (format & M6812_OP_PAGE)
    {
      fixup8 (&operands[i].exp, M6812_OP_PAGE, operands[i].mode);
    }
}

Here is the call graph for this function:

static void build_jump_insn ( struct m68hc11_opcode ,
operand ,
int  ,
int   
) [static]

Here is the caller graph for this function:

static void build_jump_insn ( struct m68hc11_opcode opcode,
operand  operands[],
int  nb_operands,
int  jmp_mode 
) [static]

Definition at line 1566 of file tc-m68hc11.c.

{
  unsigned char code;
  char *f;
  unsigned long n;
  fragS *frag;
  int where;

  /* The relative branch conversion is not supported for
     brclr and brset.  */
  assert ((opcode->format & M6811_OP_BITMASK) == 0);
  assert (nb_operands == 1);
  assert (operands[0].reg1 == REG_NONE && operands[0].reg2 == REG_NONE);

  code = opcode->opcode;

  n = operands[0].exp.X_add_number;

  /* Turn into a long branch:
     - when force long branch option (and not for jbcc pseudos),
     - when jbcc and the constant is out of -128..127 range,
     - when branch optimization is allowed and branch out of range.  */
  if ((jmp_mode == 0 && flag_force_long_jumps)
      || (operands[0].exp.X_op == O_constant
         && (!check_range (n, opcode->format) &&
             (jmp_mode == 1 || flag_fixed_branches == 0))))
    {
      frag = frag_now;
      where = frag_now_fix ();

      fix_new (frag_now, frag_now_fix (), 0,
               &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);

      if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)
       {
         code = convert_branch (code);

         f = m68hc11_new_insn (1);
         number_to_chars_bigendian (f, code, 1);
       }
      else if (current_architecture & cpu6812)
       {
         /* 68HC12: translate the bcc into a lbcc.  */
         f = m68hc11_new_insn (2);
         number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
         number_to_chars_bigendian (f + 1, code, 1);
         fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16,
                 M6812_OP_JUMP_REL16);
         return;
       }
      else
       {
         /* 68HC11: translate the bcc into b!cc +3; jmp <L>.  */
         f = m68hc11_new_insn (3);
         code ^= 1;
         number_to_chars_bigendian (f, code, 1);
         number_to_chars_bigendian (f + 1, 3, 1);
         number_to_chars_bigendian (f + 2, M6811_JMP, 1);
       }
      fixup16 (&operands[0].exp, M6811_OP_IND16, M6811_OP_IND16);
      return;
    }

  /* Branch with a constant that must fit in 8-bits.  */
  if (operands[0].exp.X_op == O_constant)
    {
      if (!check_range (n, opcode->format))
       {
         as_bad (_("Operand out of range for a relative branch: `%ld'"),
                  n);
       }
      else if (opcode->format & M6812_OP_JUMP_REL16)
       {
         f = m68hc11_new_insn (4);
         number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
         number_to_chars_bigendian (f + 1, code, 1);
         number_to_chars_bigendian (f + 2, n & 0x0ffff, 2);
       }
      else
       {
         f = m68hc11_new_insn (2);
         number_to_chars_bigendian (f, code, 1);
         number_to_chars_bigendian (f + 1, n & 0x0FF, 1);
       }
    }
  else if (opcode->format & M6812_OP_JUMP_REL16)
    {
      frag = frag_now;
      where = frag_now_fix ();

      fix_new (frag_now, frag_now_fix (), 0,
               &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);

      f = m68hc11_new_insn (2);
      number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
      number_to_chars_bigendian (f + 1, code, 1);
      fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16, M6812_OP_JUMP_REL16);
    }
  else
    {
      char *opcode;

      frag = frag_now;
      where = frag_now_fix ();
      
      fix_new (frag_now, frag_now_fix (), 0,
               &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);

      /* Branch offset must fit in 8-bits, don't do some relax.  */
      if (jmp_mode == 0 && flag_fixed_branches)
       {
         opcode = m68hc11_new_insn (1);
         number_to_chars_bigendian (opcode, code, 1);
         fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);
       }

      /* bra/bsr made be changed into jmp/jsr.  */
      else if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)
       {
          /* Allocate worst case storage.  */
         opcode = m68hc11_new_insn (3);
         number_to_chars_bigendian (opcode, code, 1);
         number_to_chars_bigendian (opcode + 1, 0, 1);
         frag_variant (rs_machine_dependent, 1, 1,
                        ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
                        operands[0].exp.X_add_symbol, (offsetT) n,
                        opcode);
       }
      else if (current_architecture & cpu6812)
       {
         opcode = m68hc11_new_insn (2);
         number_to_chars_bigendian (opcode, code, 1);
         number_to_chars_bigendian (opcode + 1, 0, 1);
         frag_var (rs_machine_dependent, 2, 2,
                  ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_UNDF),
                  operands[0].exp.X_add_symbol, (offsetT) n, opcode);
       }
      else
       {
         opcode = m68hc11_new_insn (2);
         number_to_chars_bigendian (opcode, code, 1);
         number_to_chars_bigendian (opcode + 1, 0, 1);
         frag_var (rs_machine_dependent, 3, 3,
                  ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF),
                  operands[0].exp.X_add_symbol, (offsetT) n, opcode);
       }
    }
}

Here is the call graph for this function:

static int build_reg_mode ( operand op,
int  format 
) [static]

Definition at line 2061 of file tc-m68hc11.c.

{
  unsigned char byte;
  char *f;

  if (format & M6812_OP_SEX_MARKER
      && op->reg1 != REG_A && op->reg1 != REG_B && op->reg1 != REG_CCR)
    as_bad (_("Invalid source register for this instruction, use 'tfr'."));
  else if (op->reg1 == REG_NONE || op->reg1 == REG_PC)
    as_bad (_("Invalid source register."));

  if (format & M6812_OP_SEX_MARKER
      && op->reg2 != REG_D
      && op->reg2 != REG_X && op->reg2 != REG_Y && op->reg2 != REG_SP)
    as_bad (_("Invalid destination register for this instruction, use 'tfr'."));
  else if (op->reg2 == REG_NONE || op->reg2 == REG_PC)
    as_bad (_("Invalid destination register."));

  byte = (op->reg1 << 4) | (op->reg2);
  if (format & M6812_OP_EXG_MARKER)
    byte |= 0x80;

  f = frag_more (1);
  number_to_chars_bigendian (f, byte, 1);
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_range ( long  num,
int  mode 
) [static]

Definition at line 1324 of file tc-m68hc11.c.

{
  /* Auto increment and decrement are ok for [-8..8] without 0.  */
  if (mode & M6812_AUTO_INC_DEC)
    return (num != 0 && num <= 8 && num >= -8);

  /* The 68HC12 supports 5, 9 and 16-bit offsets.  */
  if (mode & (M6812_INDEXED_IND | M6812_INDEXED | M6812_OP_IDX))
    mode = M6811_OP_IND16;

  if (mode & M6812_OP_JUMP_REL16)
    mode = M6811_OP_IND16;

  mode &= ~M6811_OP_BRANCH;
  switch (mode)
    {
    case M6811_OP_IX:
    case M6811_OP_IY:
    case M6811_OP_DIRECT:
      return (num >= 0 && num <= 255) ? 1 : 0;

    case M6811_OP_BITMASK:
    case M6811_OP_IMM8:
    case M6812_OP_PAGE:
      return (((num & 0xFFFFFF00) == 0) || ((num & 0xFFFFFF00) == 0xFFFFFF00))
       ? 1 : 0;

    case M6811_OP_JUMP_REL:
      return (num >= -128 && num <= 127) ? 1 : 0;

    case M6811_OP_IND16:
    case M6811_OP_IND16 | M6812_OP_PAGE:
    case M6811_OP_IMM16:
      return (((num & 0xFFFF0000) == 0) || ((num & 0xFFFF0000) == 0xFFFF0000))
       ? 1 : 0;

    case M6812_OP_IBCC_MARKER:
    case M6812_OP_TBCC_MARKER:
    case M6812_OP_DBCC_MARKER:
      return (num >= -256 && num <= 255) ? 1 : 0;

    case M6812_OP_TRAP_ID:
      return ((num >= 0x30 && num <= 0x39)
             || (num >= 0x40 && num <= 0x0ff)) ? 1 : 0;

    default:
      return 0;
    }
}

Here is the caller graph for this function:

static int cmp_opcode ( struct m68hc11_opcode op1,
struct m68hc11_opcode op2 
) [static]

Definition at line 583 of file tc-m68hc11.c.

{
  return strcmp (op1->name, op2->name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned char convert_branch ( unsigned char  code) [static]

Definition at line 1535 of file tc-m68hc11.c.

{
  if (IS_OPCODE (code, M6812_BSR))
    return M6812_JSR;
  else if (IS_OPCODE (code, M6811_BSR))
    return M6811_JSR;
  else if (IS_OPCODE (code, M6811_BRA))
    return (current_architecture & cpu6812) ? M6812_JMP : M6811_JMP;
  else
    as_fatal (_("Unexpected branch conversion with `%x'"), code);

  /* Keep gcc happy.  */
  return M6811_JSR;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct m68hc11_opcode* find ( struct m68hc11_opcode_def ,
operand ,
int   
) [static, read]
static struct m68hc11_opcode* find ( struct m68hc11_opcode_def opc,
operand  operands[],
int  nb_operands 
) [static, read]

Definition at line 2217 of file tc-m68hc11.c.

{
  int i, match, pos;
  struct m68hc11_opcode *opcode;
  struct m68hc11_opcode *op_indirect;

  op_indirect = 0;
  opcode = opc->opcode;

  /* Now search the opcode table table for one with operands
     that matches what we've got.  We're only done if the operands matched so
     far AND there are no more to check.  */
  for (pos = match = 0; match == 0 && pos < opc->nb_modes; pos++, opcode++)
    {
      int poss_indirect = 0;
      long format = opcode->format;
      int expect;

      expect = 0;
      if (opcode->format & M6811_OP_MASK)
       expect++;
      if (opcode->format & M6811_OP_BITMASK)
       expect++;
      if (opcode->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
       expect++;
      if (opcode->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
       expect++;
      if ((opcode->format & M6812_OP_PAGE)
          && (!IS_CALL_SYMBOL (opcode->format) || nb_operands == 2))
        expect++;

      for (i = 0; expect == nb_operands && i < nb_operands; i++)
       {
         int mode = operands[i].mode;

         if (mode & M6811_OP_IMM16)
           {
             if (format &
                (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK))
              continue;
             break;
           }
         if (mode == M6811_OP_DIRECT)
           {
             if (format & M6811_OP_DIRECT)
              continue;

             /* If the operand is a page 0 operand, remember a
                possible <abs-16> addressing mode.  We mark
                this and continue to check other operands.  */
             if (format & M6811_OP_IND16
                && flag_strict_direct_addressing && op_indirect == 0)
              {
                poss_indirect = 1;
                continue;
              }
             break;
           }
         if (mode & M6811_OP_IND16)
           {
             if (i == 0 && (format & M6811_OP_IND16) != 0)
              continue;
              if (i != 0 && (format & M6812_OP_PAGE) != 0)
                continue;
             if (i != 0 && (format & M6812_OP_IND16_P2) != 0)
              continue;
             if (i == 0 && (format & M6811_OP_BITMASK))
              break;
           }
         if (mode & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
           {
             if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
              continue;
           }
         if (mode & M6812_OP_REG)
           {
             if (i == 0
                && (format & M6812_OP_REG)
                && (operands[i].reg2 == REG_NONE))
              continue;
             if (i == 0
                && (format & M6812_OP_REG)
                && (format & M6812_OP_REG_2)
                && (operands[i].reg2 != REG_NONE))
              continue;
             if (i == 0
                && (format & M6812_OP_IDX)
                && (operands[i].reg2 != REG_NONE))
              continue;
             if (i == 0
                && (format & M6812_OP_IDX)
                && (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)))
              continue;
             if (i == 1
                && (format & M6812_OP_IDX_P2))
              continue;
             break;
           }
         if (mode & M6812_OP_IDX)
           {
             if (format & M6811_OP_IX && operands[i].reg1 == REG_X)
              continue;
             if (format & M6811_OP_IY && operands[i].reg1 == REG_Y)
              continue;
             if (i == 0
                && format & (M6812_OP_IDX | M6812_OP_IDX_1 | M6812_OP_IDX_2)
                && (operands[i].reg1 == REG_X
                    || operands[i].reg1 == REG_Y
                    || operands[i].reg1 == REG_SP
                    || operands[i].reg1 == REG_PC))
              continue;
             if (i == 1 && format & M6812_OP_IDX_P2)
              continue;
           }
          if (mode & format & (M6812_OP_D_IDX | M6812_OP_D_IDX_2))
            {
              if (i == 0)
                continue;
            }
         if (mode & M6812_AUTO_INC_DEC)
           {
             if (i == 0
                && format & (M6812_OP_IDX | M6812_OP_IDX_1 |
                            M6812_OP_IDX_2))
              continue;
             if (i == 1 && format & M6812_OP_IDX_P2)
              continue;
           }
         break;
       }
      match = i == nb_operands;

      /* Operands are ok but an operand uses page 0 addressing mode
         while the insn supports abs-16 mode.  Keep a reference to this
         insns in case there is no insn supporting page 0 addressing.  */
      if (match && poss_indirect)
       {
         op_indirect = opcode;
         match = 0;
       }
      if (match)
       break;
    }

  /* Page 0 addressing is used but not supported by any insn.
     If absolute addresses are supported, we use that insn.  */
  if (match == 0 && op_indirect)
    {
      opcode = op_indirect;
      match = 1;
    }

  if (!match)
    {
      return (0);
    }

  return opcode;
}

Here is the call graph for this function:

static struct m68hc11_opcode* find_opcode ( struct m68hc11_opcode_def ,
operand ,
int  
) [static, read]
static struct m68hc11_opcode* find_opcode ( struct m68hc11_opcode_def opc,
operand  operands[],
int nb_operands 
) [static, read]

Definition at line 2387 of file tc-m68hc11.c.

{
  struct m68hc11_opcode *opcode;
  int i;

  if (opc->max_operands == 0)
    {
      *nb_operands = 0;
      return opc->opcode;
    }

  for (i = 0; i < opc->max_operands;)
    {
      int result;

      result = get_operand (&operands[i], i, opc->format);
      if (result <= 0)
       return 0;

      /* Special case where the bitmask of the bclr/brclr
         instructions is not introduced by #.
         Example: bclr 3,x $80.  */
      if (i == 1 && (opc->format & M6811_OP_BITMASK)
         && (operands[i].mode & M6811_OP_IND16))
       {
         operands[i].mode = M6811_OP_IMM16;
       }

      i += result;
      *nb_operands = i;
      if (i >= opc->min_operands)
       {
         opcode = find (opc, operands, i);

          /* Another special case for 'call foo,page' instructions.
             Since we support 'call foo' and 'call foo,page' we must look
             if the optional page specification is present otherwise we will
             assemble immediately and treat the page spec as garbage.  */
          if (opcode && !(opcode->format & M6812_OP_PAGE))
             return opcode;

         if (opcode && *input_line_pointer != ',')
           return opcode;
       }

      if (*input_line_pointer == ',')
       input_line_pointer++;
    }

  return 0;
}

Here is the call graph for this function:

static void fixup16 ( expressionS ,
int  ,
int   
) [static]

Here is the caller graph for this function:

static void fixup16 ( expressionS oper,
int  mode,
int opmode  ATTRIBUTE_UNUSED 
) [static]

Definition at line 1452 of file tc-m68hc11.c.

{
  char *f;

  f = frag_more (2);

  if (oper->X_op == O_constant)
    {
      if (!check_range (oper->X_add_number, mode))
       {
         as_bad (_("Operand out of 16-bit range: `%ld'."),
                oper->X_add_number);
       }
      number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFF, 2);
    }
  else if (oper->X_op != O_register)
    {
      fixS *fixp;
      int reloc;

      if ((opmode & M6811_OP_CALL_ADDR) && (mode & M6811_OP_IMM16))
        reloc = BFD_RELOC_M68HC11_LO16;
      else if (mode & M6812_OP_JUMP_REL16)
        reloc = BFD_RELOC_16_PCREL;
      else if (mode & M6812_OP_PAGE)
        reloc = BFD_RELOC_M68HC11_LO16;
      else
        reloc = BFD_RELOC_16;

      /* Now create a 16-bit fixup.  */
      fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
                       oper,
                       reloc == BFD_RELOC_16_PCREL,
                          reloc);
      number_to_chars_bigendian (f, 0, 2);
      if (reloc == BFD_RELOC_16_PCREL)
       fixp->fx_pcrel_adjust = 2;
      if (reloc == BFD_RELOC_M68HC11_LO16)
        fixp->fx_no_overflow = 1;
    }
  else
    {
      as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
    }
}

Here is the call graph for this function:

static void fixup24 ( expressionS ,
int  ,
int   
) [static]

Here is the caller graph for this function:

static void fixup24 ( expressionS oper,
int  mode,
int opmode  ATTRIBUTE_UNUSED 
) [static]

Definition at line 1501 of file tc-m68hc11.c.

{
  char *f;

  f = frag_more (3);

  if (oper->X_op == O_constant)
    {
      if (!check_range (oper->X_add_number, mode))
       {
         as_bad (_("Operand out of 16-bit range: `%ld'."),
                oper->X_add_number);
       }
      number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFFFF, 3);
    }
  else if (oper->X_op != O_register)
    {
      fixS *fixp;

      /* Now create a 24-bit fixup.  */
      fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 3,
                       oper, FALSE, BFD_RELOC_M68HC11_24);
      number_to_chars_bigendian (f, 0, 3);
    }
  else
    {
      as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
    }
}

Here is the call graph for this function:

static void fixup8 ( expressionS oper,
int  mode,
int  opmode 
) [static]

Definition at line 1379 of file tc-m68hc11.c.

{
  char *f;

  f = frag_more (1);

  if (oper->X_op == O_constant)
    {
      if (mode & M6812_OP_TRAP_ID
         && !check_range (oper->X_add_number, M6812_OP_TRAP_ID))
       {
         static char trap_id_warn_once = 0;

         as_bad (_("Trap id `%ld' is out of range."), oper->X_add_number);
         if (trap_id_warn_once == 0)
           {
             trap_id_warn_once = 1;
             as_bad (_("Trap id must be within [0x30..0x39] or [0x40..0xff]."));
           }
       }

      if (!(mode & M6812_OP_TRAP_ID)
         && !check_range (oper->X_add_number, mode))
       {
         as_bad (_("Operand out of 8-bit range: `%ld'."), oper->X_add_number);
       }
      number_to_chars_bigendian (f, oper->X_add_number & 0x0FF, 1);
    }
  else if (oper->X_op != O_register)
    {
      if (mode & M6812_OP_TRAP_ID)
       as_bad (_("The trap id must be a constant."));

      if (mode == M6811_OP_JUMP_REL)
       {
         fixS *fixp;

         fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
                           oper, TRUE, BFD_RELOC_8_PCREL);
         fixp->fx_pcrel_adjust = 1;
       }
      else
       {
         fixS *fixp;
          int reloc;

         /* Now create an 8-bit fixup.  If there was some %hi, %lo
            or %page modifier, generate the reloc accordingly.  */
          if (opmode & M6811_OP_HIGH_ADDR)
            reloc = BFD_RELOC_M68HC11_HI8;
          else if (opmode & M6811_OP_LOW_ADDR)
            reloc = BFD_RELOC_M68HC11_LO8;
          else if (opmode & M6811_OP_PAGE_ADDR)
            reloc = BFD_RELOC_M68HC11_PAGE;
          else
            reloc = BFD_RELOC_8;

         fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
                              oper, FALSE, reloc);
          if (reloc != BFD_RELOC_8)
            fixp->fx_no_overflow = 1;
       }
      number_to_chars_bigendian (f, 0, 1);
    }
  else
    {
      as_fatal (_("Operand `%x' not recognized in fixup8."), oper->X_op);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void get_default_target ( void  ) [static]

Definition at line 393 of file tc-m68hc11.c.

{
  const bfd_target *target;
  bfd abfd;

  if (current_architecture != 0)
    return;

  default_cpu = "unknown";
  target = bfd_find_target (0, &abfd);
  if (target && target->name)
    {
      if (strcmp (target->name, "elf32-m68hc12") == 0)
       {
         current_architecture = cpu6812;
         default_cpu = "m68hc12";
       }
      else if (strcmp (target->name, "elf32-m68hc11") == 0)
       {
         current_architecture = cpu6811;
         default_cpu = "m68hc11";
       }
      else
       {
         as_bad (_("Default target `%s' is not supported."), target->name);
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_operand ( operand oper,
int  which,
long  opmode 
) [static]

Definition at line 990 of file tc-m68hc11.c.

{
  char *p = input_line_pointer;
  int mode;
  register_id reg;

  oper->exp.X_op = O_absent;
  oper->reg1 = REG_NONE;
  oper->reg2 = REG_NONE;
  mode = M6811_OP_NONE;

  p = skip_whites (p);

  if (*p == 0 || *p == '\n' || *p == '\r')
    {
      input_line_pointer = p;
      return 0;
    }

  if (*p == '*' && (opmode & (M6811_OP_DIRECT | M6811_OP_IND16)))
    {
      mode = M6811_OP_DIRECT;
      p++;
    }
  else if (*p == '#')
    {
      if (!(opmode & (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK)))
       {
         as_bad (_("Immediate operand is not allowed for operand %d."),
                which);
         return -1;
       }

      mode = M6811_OP_IMM16;
      p++;
      if (strncmp (p, "%hi", 3) == 0)
       {
         p += 3;
         mode |= M6811_OP_HIGH_ADDR;
       }
      else if (strncmp (p, "%lo", 3) == 0)
       {
         p += 3;
         mode |= M6811_OP_LOW_ADDR;
       }
      /* %page modifier is used to obtain only the page number
         of the address of a function.  */
      else if (strncmp (p, "%page", 5) == 0)
       {
         p += 5;
         mode |= M6811_OP_PAGE_ADDR;
       }

      /* %addr modifier is used to obtain the physical address part
         of the function (16-bit).  For 68HC12 the function will be
         mapped in the 16K window at 0x8000 and the value will be
         within that window (although the function address may not fit
         in 16-bit).  See bfd/elf32-m68hc12.c for the translation.  */
      else if (strncmp (p, "%addr", 5) == 0)
       {
         p += 5;
         mode |= M6811_OP_CALL_ADDR;
       }
    }
  else if (*p == '.' && (p[1] == '+' || p[1] == '-'))
    {
      p++;
      mode = M6811_OP_JUMP_REL;
    }
  else if (*p == '[')
    {
      if (current_architecture & cpu6811)
       as_bad (_("Indirect indexed addressing is not valid for 68HC11."));

      p++;
      mode = M6812_OP_D_IDX;
      p = skip_whites (p);
    }
  else if (*p == ',')              /* Special handling of ,x and ,y.  */
    {
      p++;
      input_line_pointer = p;

      reg = register_name ();
      if (reg != REG_NONE)
       {
         oper->reg1 = reg;
         oper->exp.X_op = O_constant;
         oper->exp.X_add_number = 0;
         oper->mode = M6812_OP_IDX;
         return 1;
       }
      as_bad (_("Spurious `,' or bad indirect register addressing mode."));
      return -1;
    }
  /* Handle 68HC12 page specification in 'call foo,%page(bar)'.  */
  else if ((opmode & M6812_OP_PAGE) && strncmp (p, "%page", 5) == 0)
    {
      p += 5;
      mode = M6811_OP_PAGE_ADDR | M6812_OP_PAGE | M6811_OP_IND16;
    }
  input_line_pointer = p;

  if (mode == M6811_OP_NONE || mode == M6812_OP_D_IDX)
    reg = register_name ();
  else
    reg = REG_NONE;

  if (reg != REG_NONE)
    {
      p = skip_whites (input_line_pointer);
      if (*p == ']' && mode == M6812_OP_D_IDX)
       {
         as_bad
           (_("Missing second register or offset for indexed-indirect mode."));
         return -1;
       }

      oper->reg1 = reg;
      oper->mode = mode | M6812_OP_REG;
      if (*p != ',')
       {
         if (mode == M6812_OP_D_IDX)
           {
             as_bad (_("Missing second register for indexed-indirect mode."));
             return -1;
           }
         return 1;
       }

      p++;
      input_line_pointer = p;
      reg = register_name ();
      if (reg != REG_NONE)
       {
         p = skip_whites (input_line_pointer);
         if (mode == M6812_OP_D_IDX)
           {
             if (*p != ']')
              {
                as_bad (_("Missing `]' to close indexed-indirect mode."));
                return -1;
              }
             p++;
              oper->mode = M6812_OP_D_IDX;
           }
         input_line_pointer = p;

         oper->reg2 = reg;
         return 1;
       }
      return 1;
    }

  /* In MRI mode, isolate the operand because we can't distinguish
     operands from comments.  */
  if (flag_mri)
    {
      char c = 0;

      p = skip_whites (p);
      while (*p && *p != ' ' && *p != '\t')
       p++;

      if (*p)
       {
         c = *p;
         *p = 0;
       }

      /* Parse as an expression.  */
      expression (&oper->exp);

      if (c)
       {
         *p = c;
       }
    }
  else
    {
      expression (&oper->exp);
    }

  if (oper->exp.X_op == O_illegal)
    {
      as_bad (_("Illegal operand."));
      return -1;
    }
  else if (oper->exp.X_op == O_absent)
    {
      as_bad (_("Missing operand."));
      return -1;
    }

  p = input_line_pointer;

  if (mode == M6811_OP_NONE || mode == M6811_OP_DIRECT
      || mode == M6812_OP_D_IDX)
    {
      p = skip_whites (input_line_pointer);

      if (*p == ',')
       {
         int possible_mode = M6811_OP_NONE;
         char *old_input_line;

         old_input_line = p;
         p++;

         /* 68HC12 pre increment or decrement.  */
         if (mode == M6811_OP_NONE)
           {
             if (*p == '-')
              {
                possible_mode = M6812_PRE_DEC;
                p++;
              }
             else if (*p == '+')
              {
                possible_mode = M6812_PRE_INC;
                p++;
              }
             p = skip_whites (p);
           }
         input_line_pointer = p;
         reg = register_name ();

         /* Backtrack if we have a valid constant expression and
            it does not correspond to the offset of the 68HC12 indexed
            addressing mode (as in N,x).  */
         if (reg == REG_NONE && mode == M6811_OP_NONE
             && possible_mode != M6811_OP_NONE)
           {
             oper->mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
             input_line_pointer = skip_whites (old_input_line);
             return 1;
           }

         if (possible_mode != M6811_OP_NONE)
           mode = possible_mode;

         if ((current_architecture & cpu6811)
             && possible_mode != M6811_OP_NONE)
           as_bad (_("Pre-increment mode is not valid for 68HC11"));
         /* Backtrack.  */
         if (which == 0 && opmode & M6812_OP_IDX_P2
             && reg != REG_X && reg != REG_Y
             && reg != REG_PC && reg != REG_SP)
           {
             reg = REG_NONE;
             input_line_pointer = p;
           }

         if (reg == REG_NONE && mode != M6811_OP_DIRECT
             && !(mode == M6811_OP_NONE && opmode & M6811_OP_IND16))
           {
             as_bad (_("Wrong register in register indirect mode."));
             return -1;
           }
         if (mode == M6812_OP_D_IDX)
           {
             p = skip_whites (input_line_pointer);
             if (*p++ != ']')
              {
                as_bad (_("Missing `]' to close register indirect operand."));
                return -1;
              }
             input_line_pointer = p;
              oper->reg1 = reg;
              oper->mode = M6812_OP_D_IDX_2;
              return 1;
           }
         if (reg != REG_NONE)
           {
             oper->reg1 = reg;
             if (mode == M6811_OP_NONE)
              {
                p = input_line_pointer;
                if (*p == '-')
                  {
                    mode = M6812_POST_DEC;
                    p++;
                    if (current_architecture & cpu6811)
                     as_bad
                       (_("Post-decrement mode is not valid for 68HC11."));
                  }
                else if (*p == '+')
                  {
                    mode = M6812_POST_INC;
                    p++;
                    if (current_architecture & cpu6811)
                     as_bad
                       (_("Post-increment mode is not valid for 68HC11."));
                  }
                else
                  mode = M6812_OP_IDX;

                input_line_pointer = p;
              }
             else
              mode |= M6812_OP_IDX;

             oper->mode = mode;
             return 1;
           }
          input_line_pointer = old_input_line;
       }

      if (mode == M6812_OP_D_IDX_2)
       {
         as_bad (_("Invalid indexed indirect mode."));
         return -1;
       }
    }

  /* If the mode is not known until now, this is either a label
     or an indirect address.  */
  if (mode == M6811_OP_NONE)
    mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;

  p = input_line_pointer;
  while (*p == ' ' || *p == '\t')
    p++;
  input_line_pointer = p;
  oper->mode = mode;

  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

enum bfd_architecture m68hc11_arch ( void  )

Definition at line 342 of file tc-m68hc11.c.

Here is the call graph for this function:

const char* m68hc11_arch_format ( void  )

Definition at line 332 of file tc-m68hc11.c.

{
  get_default_target ();
  if (current_architecture & cpu6811)
    return "elf32-m68hc11";
  else
    return "elf32-m68hc12";
}

Here is the call graph for this function:

void m68hc11_init_after_args ( void  )

Definition at line 700 of file tc-m68hc11.c.

{
}
const char* m68hc11_listing_header ( void  )

Definition at line 359 of file tc-m68hc11.c.

{
  if (current_architecture & cpu6811)
    return "M68HC11 GAS ";
  else
    return "M68HC12 GAS ";
}
int m68hc11_mach ( void  )

Definition at line 352 of file tc-m68hc11.c.

{
  return 0;
}
static char * m68hc11_new_insn ( int  size) [static]

Definition at line 1553 of file tc-m68hc11.c.

{
  char *f;

  f = frag_more (size);

  dwarf2_emit_insn (size);

  return f;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void m68hc11_print_statistics ( FILE *  file)

Definition at line 423 of file tc-m68hc11.c.

{
  int i;
  struct m68hc11_opcode_def *opc;

  hash_print_statistics (file, "opcode table", m68hc11_hash);

  opc = m68hc11_opcode_defs;
  if (opc == 0 || m68hc11_nb_opcode_defs == 0)
    return;

  /* Dump the opcode statistics table.  */
  fprintf (file, _("Name   # Modes  Min ops  Max ops  Modes mask  # Used\n"));
  for (i = 0; i < m68hc11_nb_opcode_defs; i++, opc++)
    {
      fprintf (file, "%-7.7s  %5d  %7d  %7d  0x%08lx  %7d\n",
              opc->opcode->name,
              opc->nb_modes,
              opc->min_operands, opc->max_operands, opc->format, opc->used);
    }
}

Here is the call graph for this function:

long m68hc11_relax_frag ( segT seg  ATTRIBUTE_UNUSED,
fragS *  fragP,
long stretch  ATTRIBUTE_UNUSED 
)

Definition at line 2768 of file tc-m68hc11.c.

{
  long growth;
  offsetT aim = 0;
  symbolS *symbolP;
  const relax_typeS *this_type;
  const relax_typeS *start_type;
  relax_substateT next_state;
  relax_substateT this_state;
  const relax_typeS *table = TC_GENERIC_RELAX_TABLE;

  /* We only have to cope with frags as prepared by
     md_estimate_size_before_relax.  The STATE_BITS16 case may geet here
     because of the different reasons that it's not relaxable.  */
  switch (fragP->fr_subtype)
    {
    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16):
    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
      /* When we get to this state, the frag won't grow any more.  */
      return 0;

    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5):
    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9):
    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
      if (fragP->fr_symbol == NULL
         || S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
       as_fatal (_("internal inconsistency problem in %s: fr_symbol %lx"),
                __FUNCTION__, (long) fragP->fr_symbol);
      symbolP = fragP->fr_symbol;
      if (symbol_resolved_p (symbolP))
       as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
                __FUNCTION__);
      aim = S_GET_VALUE (symbolP);
      break;

    default:
      as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"),
                __FUNCTION__, fragP->fr_subtype);
    }

  /* The rest is stolen from relax_frag.  There's no obvious way to
     share the code, but fortunately no requirement to keep in sync as
     long as fragP->fr_symbol does not have its segment changed.  */

  this_state = fragP->fr_subtype;
  start_type = this_type = table + this_state;

  if (aim < 0)
    {
      /* Look backwards.  */
      for (next_state = this_type->rlx_more; next_state;)
       if (aim >= this_type->rlx_backward)
         next_state = 0;
       else
         {
           /* Grow to next state.  */
           this_state = next_state;
           this_type = table + this_state;
           next_state = this_type->rlx_more;
         }
    }
  else
    {
      /* Look forwards.  */
      for (next_state = this_type->rlx_more; next_state;)
       if (aim <= this_type->rlx_forward)
         next_state = 0;
       else
         {
           /* Grow to next state.  */
           this_state = next_state;
           this_type = table + this_state;
           next_state = this_type->rlx_more;
         }
    }

  growth = this_type->rlx_length - start_type->rlx_length;
  if (growth != 0)
    fragP->fr_subtype = this_state;
  return growth;
}

Here is the call graph for this function:

void md_apply_fix ( fixS *  fixP,
valueT valP,
segT seg  ATTRIBUTE_UNUSED 
)

Definition at line 3233 of file tc-m68hc11.c.

{
  char *where;
  long value = * valP;
  int op_type;

  if (fixP->fx_addsy == (symbolS *) NULL)
    fixP->fx_done = 1;

  /* We don't actually support subtracting a symbol.  */
  if (fixP->fx_subsy != (symbolS *) NULL)
    as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));

  op_type = fixP->fx_r_type;

  /* Patch the instruction with the resolved operand.  Elf relocation
     info will also be generated to take care of linker/loader fixups.
     The 68HC11 addresses only 64Kb, we are only concerned by 8 and 16-bit
     relocs.  BFD_RELOC_8 is basically used for .page0 access (the linker
     will warn for overflows).  BFD_RELOC_8_PCREL should not be generated
     because it's either resolved or turned out into non-relative insns (see
     relax table, bcc, bra, bsr transformations)

     The BFD_RELOC_32 is necessary for the support of --gstabs.  */
  where = fixP->fx_frag->fr_literal + fixP->fx_where;

  switch (fixP->fx_r_type)
    {
    case BFD_RELOC_32:
      bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
      break;

    case BFD_RELOC_24:
    case BFD_RELOC_M68HC11_24:
      bfd_putb16 ((bfd_vma) (value & 0x0ffff), (unsigned char *) where);
      ((bfd_byte*) where)[2] = ((value >> 16) & 0x0ff);
      break;

    case BFD_RELOC_16:
    case BFD_RELOC_16_PCREL:
    case BFD_RELOC_M68HC11_LO16:
      bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
      if (value < -65537 || value > 65535)
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Value out of 16-bit range."));
      break;

    case BFD_RELOC_M68HC11_HI8:
      value = value >> 8;
      /* Fall through.  */

    case BFD_RELOC_M68HC11_LO8:
    case BFD_RELOC_8:
    case BFD_RELOC_M68HC11_PAGE:
      ((bfd_byte *) where)[0] = (bfd_byte) value;
      break;

    case BFD_RELOC_8_PCREL:
      ((bfd_byte *) where)[0] = (bfd_byte) value;

      if (value < -128 || value > 127)
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Value %ld too large for 8-bit PC-relative branch."),
                    value);
      break;

    case BFD_RELOC_M68HC11_3B:
      if (value <= 0 || value > 8)
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Auto increment/decrement offset '%ld' is out of range."),
                    value);
      if (where[0] & 0x8)
       value = 8 - value;
      else
       value--;

      where[0] = where[0] | (value & 0x07);
      break;

    case BFD_RELOC_M68HC12_5B:
      if (value < -16 || value > 15)
       as_bad_where (fixP->fx_file, fixP->fx_line,
                    _("Offset out of 5-bit range for movw/movb insn: %ld"),
                    value);
      if (value >= 0)
       where[0] |= value;
      else 
       where[0] |= (0x10 | (16 + value));
      break;

    case BFD_RELOC_M68HC11_RL_JUMP:
    case BFD_RELOC_M68HC11_RL_GROUP:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
      fixP->fx_done = 0;
      return;

    default:
      as_fatal (_("Line %d: unknown relocation type: 0x%x."),
              fixP->fx_line, fixP->fx_r_type);
    }
}

Here is the call graph for this function:

void md_assemble ( char *  str)

Definition at line 2450 of file tc-m68hc11.c.

{
  struct m68hc11_opcode_def *opc;
  struct m68hc11_opcode *opcode;

  unsigned char *op_start, *op_end;
  char *save;
  char name[20];
  int nlen = 0;
  operand operands[M6811_MAX_OPERANDS];
  int nb_operands = 0;
  int branch_optimize = 0;
  int alias_id = -1;

  /* Drop leading whitespace.  */
  while (*str == ' ')
    str++;

  /* Find the opcode end and get the opcode in 'name'.  The opcode is forced
     lower case (the opcode table only has lower case op-codes).  */
  for (op_start = op_end = (unsigned char *) str;
       *op_end && nlen < 20 && !is_end_of_line[*op_end] && *op_end != ' ';
       op_end++)
    {
      name[nlen] = TOLOWER (op_start[nlen]);
      nlen++;
    }
  name[nlen] = 0;

  if (nlen == 0)
    {
      as_bad (_("No instruction or missing opcode."));
      return;
    }

  /* Find the opcode definition given its name.  */
  opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name);

  /* If it's not recognized, look for 'jbsr' and 'jbxx'.  These are
     pseudo insns for relative branch.  For these branches, we always
     optimize them (turned into absolute branches) even if --short-branches
     is given.  */
  if (opc == NULL && name[0] == 'j' && name[1] == 'b')
    {
      opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, &name[1]);
      if (opc
         && (!(opc->format & M6811_OP_JUMP_REL)
             || (opc->format & M6811_OP_BITMASK)))
       opc = 0;
      if (opc)
       branch_optimize = 1;
    }

  /* The following test should probably be removed.  This is not conform
     to Motorola assembler specs.  */
  if (opc == NULL && flag_mri)
    {
      if (*op_end == ' ' || *op_end == '\t')
       {
         while (*op_end == ' ' || *op_end == '\t')
           op_end++;

         if (nlen < 19
             && (*op_end &&
                (is_end_of_line[op_end[1]]
                 || op_end[1] == ' ' || op_end[1] == '\t'
                 || !ISALNUM (op_end[1])))
             && (*op_end == 'a' || *op_end == 'b'
                || *op_end == 'A' || *op_end == 'B'
                || *op_end == 'd' || *op_end == 'D'
                || *op_end == 'x' || *op_end == 'X'
                || *op_end == 'y' || *op_end == 'Y'))
           {
             name[nlen++] = TOLOWER (*op_end++);
             name[nlen] = 0;
             opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash,
                                                      name);
           }
       }
    }

  /* Identify a possible instruction alias.  There are some on the
     68HC12 to emulate a few 68HC11 instructions.  */
  if (opc == NULL && (current_architecture & cpu6812))
    {
      int i;

      for (i = 0; i < m68hc12_num_alias; i++)
       if (strcmp (m68hc12_alias[i].name, name) == 0)
         {
           alias_id = i;
           break;
         }
    }
  if (opc == NULL && alias_id < 0)
    {
      as_bad (_("Opcode `%s' is not recognized."), name);
      return;
    }
  save = input_line_pointer;
  input_line_pointer = (char *) op_end;

  if (opc)
    {
      opc->used++;
      opcode = find_opcode (opc, operands, &nb_operands);
    }
  else
    opcode = 0;

  if ((opcode || alias_id >= 0) && !flag_mri)
    {
      char *p = input_line_pointer;

      while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
       p++;

      if (*p != '\n' && *p)
       as_bad (_("Garbage at end of instruction: `%s'."), p);
    }

  input_line_pointer = save;

  if (alias_id >= 0)
    {
      char *f = m68hc11_new_insn (m68hc12_alias[alias_id].size);

      number_to_chars_bigendian (f, m68hc12_alias[alias_id].code1, 1);
      if (m68hc12_alias[alias_id].size > 1)
       number_to_chars_bigendian (f + 1, m68hc12_alias[alias_id].code2, 1);

      return;
    }

  /* Opcode is known but does not have valid operands.  Print out the
     syntax for this opcode.  */
  if (opcode == 0)
    {
      if (flag_print_insn_syntax)
       print_insn_format (name);

      as_bad (_("Invalid operand for `%s'"), name);
      return;
    }

  /* Treat dbeq/ibeq/tbeq instructions in a special way.  The branch is
     relative and must be in the range -256..255 (9-bits).  */
  if ((opcode->format & M6812_XBCC_MARKER)
      && (opcode->format & M6811_OP_JUMP_REL))
    build_dbranch_insn (opcode, operands, nb_operands, branch_optimize);

  /* Relative jumps instructions are taken care of separately.  We have to make
     sure that the relative branch is within the range -128..127.  If it's out
     of range, the instructions are changed into absolute instructions.
     This is not supported for the brset and brclr instructions.  */
  else if ((opcode->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
          && !(opcode->format & M6811_OP_BITMASK))
    build_jump_insn (opcode, operands, nb_operands, branch_optimize);
  else
    build_insn (opcode, operands, nb_operands);
}

Here is the call graph for this function:

char* md_atof ( int type  ,
char *  litP,
int sizeP 
)

Definition at line 525 of file tc-m68hc11.c.

{
  int prec;
  LITTLENUM_TYPE words[MAX_LITTLENUMS];
  LITTLENUM_TYPE *wordP;
  char *t;

  switch (type)
    {
    case 'f':
    case 'F':
    case 's':
    case 'S':
      prec = 2;
      break;

    case 'd':
    case 'D':
    case 'r':
    case 'R':
      prec = 4;
      break;

    case 'x':
    case 'X':
      prec = 6;
      break;

    case 'p':
    case 'P':
      prec = 6;
      break;

    default:
      *sizeP = 0;
      return _("Bad call to MD_ATOF()");
    }
  t = atof_ieee (input_line_pointer, type, words);
  if (t)
    input_line_pointer = t;

  *sizeP = prec * sizeof (LITTLENUM_TYPE);
  for (wordP = words; prec--;)
    {
      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
      litP += sizeof (LITTLENUM_TYPE);
    }
  return 0;
}

Here is the call graph for this function:

void md_begin ( void  )

Definition at line 596 of file tc-m68hc11.c.

{
  char *prev_name = "";
  struct m68hc11_opcode *opcodes;
  struct m68hc11_opcode_def *opc = 0;
  int i, j;

  get_default_target ();

  m68hc11_hash = hash_new ();

  /* Get a writable copy of the opcode table and sort it on the names.  */
  opcodes = (struct m68hc11_opcode *) xmalloc (m68hc11_num_opcodes *
                                          sizeof (struct
                                                 m68hc11_opcode));
  m68hc11_sorted_opcodes = opcodes;
  num_opcodes = 0;
  for (i = 0; i < m68hc11_num_opcodes; i++)
    {
      if (m68hc11_opcodes[i].arch & current_architecture)
       {
         opcodes[num_opcodes] = m68hc11_opcodes[i];
         if (opcodes[num_opcodes].name[0] == 'b'
             && opcodes[num_opcodes].format & M6811_OP_JUMP_REL
             && !(opcodes[num_opcodes].format & M6811_OP_BITMASK))
           {
             num_opcodes++;
             opcodes[num_opcodes] = m68hc11_opcodes[i];
           }
         num_opcodes++;
         for (j = 0; alias_opcodes[j].name != 0; j++)
           if (strcmp (m68hc11_opcodes[i].name, alias_opcodes[j].name) == 0)
             {
              opcodes[num_opcodes] = m68hc11_opcodes[i];
              opcodes[num_opcodes].name = alias_opcodes[j].alias;
              num_opcodes++;
              break;
             }
       }
    }
  qsort (opcodes, num_opcodes, sizeof (struct m68hc11_opcode),
         (int (*) (const void*, const void*)) cmp_opcode);

  opc = (struct m68hc11_opcode_def *)
    xmalloc (num_opcodes * sizeof (struct m68hc11_opcode_def));
  m68hc11_opcode_defs = opc--;

  /* Insert unique names into hash table.  The M6811 instruction set
     has several identical opcode names that have different opcodes based
     on the operands.  This hash table then provides a quick index to
     the first opcode with a particular name in the opcode table.  */
  for (i = 0; i < num_opcodes; i++, opcodes++)
    {
      int expect;

      if (strcmp (prev_name, opcodes->name))
       {
         prev_name = (char *) opcodes->name;

         opc++;
         opc->format = 0;
         opc->min_operands = 100;
         opc->max_operands = 0;
         opc->nb_modes = 0;
         opc->opcode = opcodes;
         opc->used = 0;
         hash_insert (m68hc11_hash, opcodes->name, opc);
       }
      opc->nb_modes++;
      opc->format |= opcodes->format;

      /* See how many operands this opcode needs.  */
      expect = 0;
      if (opcodes->format & M6811_OP_MASK)
       expect++;
      if (opcodes->format & M6811_OP_BITMASK)
       expect++;
      if (opcodes->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
       expect++;
      if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
       expect++;
      /* Special case for call instruction.  */
      if ((opcodes->format & M6812_OP_PAGE)
          && !(opcodes->format & M6811_OP_IND16))
        expect++;

      if (expect < opc->min_operands)
       opc->min_operands = expect;
      if (IS_CALL_SYMBOL (opcodes->format))
         expect++;
      if (expect > opc->max_operands)
       opc->max_operands = expect;
    }
  opc++;
  m68hc11_nb_opcode_defs = opc - m68hc11_opcode_defs;

  if (flag_print_opcodes)
    {
      print_opcode_list ();
      exit (EXIT_SUCCESS);
    }
}

Here is the call graph for this function:

void md_convert_frag ( bfd *abfd  ATTRIBUTE_UNUSED,
asection *sec  ATTRIBUTE_UNUSED,
fragS *  fragP 
)

Definition at line 2853 of file tc-m68hc11.c.

{
  fixS *fixp;
  long value;
  long disp;
  char *buffer_address = fragP->fr_literal;

  /* Address in object code of the displacement.  */
  register int object_address = fragP->fr_fix + fragP->fr_address;

  buffer_address += fragP->fr_fix;

  /* The displacement of the address, from current location.  */
  value = S_GET_VALUE (fragP->fr_symbol);
  disp = (value + fragP->fr_offset) - object_address;

  switch (fragP->fr_subtype)
    {
    case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
      fragP->fr_opcode[1] = disp;
      break;

    case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
      /* This relax is only for bsr and bra.  */
      assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
             || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
             || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));

      fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);

      fix_new (fragP, fragP->fr_fix - 1, 2,
              fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
      fragP->fr_fix += 1;
      break;

    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_BYTE):
      fragP->fr_opcode[1] = disp;
      break;

    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
      /* Invert branch.  */
      fragP->fr_opcode[0] ^= 1;
      fragP->fr_opcode[1] = 3;     /* Branch offset.  */
      buffer_address[0] = M6811_JMP;
      fix_new (fragP, fragP->fr_fix + 1, 2,
              fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
      fragP->fr_fix += 3;
      break;

    case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_WORD):
      /* Translate branch into a long branch.  */
      fragP->fr_opcode[1] = fragP->fr_opcode[0];
      fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;

      fixp = fix_new (fragP, fragP->fr_fix, 2,
                    fragP->fr_symbol, fragP->fr_offset, 1,
                    BFD_RELOC_16_PCREL);
      fixp->fx_pcrel_adjust = 2;
      fragP->fr_fix += 2;
      break;

    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5):
      if (fragP->fr_symbol != 0
          && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
        value = disp;
      /* fall through  */

    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
      fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6;
      fragP->fr_opcode[0] |= value & 0x1f;
      break;

    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9):
      /* For a PC-relative offset, use the displacement with a -1 correction
         to take into account the additional byte of the insn.  */
      if (fragP->fr_symbol != 0
          && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
        value = disp - 1;
      /* fall through  */

    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
      fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
      fragP->fr_opcode[0] |= 0xE0;
      fragP->fr_opcode[0] |= (value >> 8) & 1;
      fragP->fr_opcode[1] = value;
      fragP->fr_fix += 1;
      break;

    case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16):
    case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
      fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
      fragP->fr_opcode[0] |= 0xe2;
      if ((fragP->fr_opcode[0] & 0x0ff) == 0x0fa
          && fragP->fr_symbol != 0
          && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
       {
         fixp = fix_new (fragP, fragP->fr_fix, 2,
                       fragP->fr_symbol, fragP->fr_offset,
                       1, BFD_RELOC_16_PCREL);
       }
      else
       {
         fix_new (fragP, fragP->fr_fix, 2,
                 fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
       }
      fragP->fr_fix += 2;
      break;

    case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE):
      if (disp < 0)
       fragP->fr_opcode[0] |= 0x10;

      fragP->fr_opcode[1] = disp & 0x0FF;
      break;

    case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_WORD):
      /* Invert branch.  */
      fragP->fr_opcode[0] ^= 0x20;
      fragP->fr_opcode[1] = 3;     /* Branch offset.  */
      buffer_address[0] = M6812_JMP;
      fix_new (fragP, fragP->fr_fix + 1, 2,
              fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
      fragP->fr_fix += 3;
      break;

    default:
      break;
    }
}

Here is the call graph for this function:

int md_estimate_size_before_relax ( fragS *  fragP,
asection * segment   
)

Definition at line 2998 of file tc-m68hc11.c.

{
  if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF)
    {
      if (S_GET_SEGMENT (fragP->fr_symbol) != segment
         || !relaxable_symbol (fragP->fr_symbol)
          || (segment != absolute_section
              && RELAX_STATE (fragP->fr_subtype) == STATE_INDEXED_OFFSET))
       {
         /* Non-relaxable cases.  */
         int old_fr_fix;
         char *buffer_address;

         old_fr_fix = fragP->fr_fix;
         buffer_address = fragP->fr_fix + fragP->fr_literal;

         switch (RELAX_STATE (fragP->fr_subtype))
           {
           case STATE_PC_RELATIVE:

             /* This relax is only for bsr and bra.  */
             assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
                    || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
                    || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));

             if (flag_fixed_branches)
              as_bad_where (fragP->fr_file, fragP->fr_line,
                           _("bra or bsr with undefined symbol."));

             /* The symbol is undefined or in a separate section.
               Turn bra into a jmp and bsr into a jsr.  The insn
               becomes 3 bytes long (instead of 2).  A fixup is
               necessary for the unresolved symbol address.  */
             fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);

             fix_new (fragP, fragP->fr_fix - 1, 2, fragP->fr_symbol,
                     fragP->fr_offset, 0, BFD_RELOC_16);
             fragP->fr_fix++;
             break;

           case STATE_CONDITIONAL_BRANCH:
             assert (current_architecture & cpu6811);

             fragP->fr_opcode[0] ^= 1;    /* Reverse sense of branch.  */
             fragP->fr_opcode[1] = 3;     /* Skip next jmp insn (3 bytes).  */

             /* Don't use fr_opcode[2] because this may be
               in a different frag.  */
             buffer_address[0] = M6811_JMP;

             fragP->fr_fix++;
             fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                     fragP->fr_offset, 0, BFD_RELOC_16);
             fragP->fr_fix += 2;
             break;

           case STATE_INDEXED_OFFSET:
             assert (current_architecture & cpu6812);

              if (fragP->fr_symbol
                  && S_GET_SEGMENT (fragP->fr_symbol) == absolute_section)
                {
                   fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
                                                     STATE_BITS5);
                   /* Return the size of the variable part of the frag. */
                   return md_relax_table[fragP->fr_subtype].rlx_length;
                }
              else
                {
                   /* Switch the indexed operation to 16-bit mode.  */
                   fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
                   fragP->fr_opcode[0] |= 0xe2;
                   fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                            fragP->fr_offset, 0, BFD_RELOC_16);
                   fragP->fr_fix += 2;
                }
             break;

           case STATE_INDEXED_PCREL:
             assert (current_architecture & cpu6812);

              if (fragP->fr_symbol
                  && S_GET_SEGMENT (fragP->fr_symbol) == absolute_section)
                {
                   fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL,
                                                     STATE_BITS5);
                   /* Return the size of the variable part of the frag. */
                   return md_relax_table[fragP->fr_subtype].rlx_length;
                }
              else
                {
                   fixS* fixp;

                   fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
                   fragP->fr_opcode[0] |= 0xe2;
                   fixp = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                                   fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
                   fragP->fr_fix += 2;
                }
             break;

           case STATE_XBCC_BRANCH:
             assert (current_architecture & cpu6812);

             fragP->fr_opcode[0] ^= 0x20; /* Reverse sense of branch.  */
             fragP->fr_opcode[1] = 3;     /* Skip next jmp insn (3 bytes).  */

             /* Don't use fr_opcode[2] because this may be
               in a different frag.  */
             buffer_address[0] = M6812_JMP;

             fragP->fr_fix++;
             fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                     fragP->fr_offset, 0, BFD_RELOC_16);
             fragP->fr_fix += 2;
             break;

           case STATE_CONDITIONAL_BRANCH_6812:
             assert (current_architecture & cpu6812);

             /* Translate into a lbcc branch.  */
             fragP->fr_opcode[1] = fragP->fr_opcode[0];
             fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;

             fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
                       fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
             fragP->fr_fix += 2;
             break;

           default:
             as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
           }
         frag_wane (fragP);

         /* Return the growth in the fixed part of the frag.  */
         return fragP->fr_fix - old_fr_fix;
       }

      /* Relaxable cases.  */
      switch (RELAX_STATE (fragP->fr_subtype))
       {
       case STATE_PC_RELATIVE:
         /* This relax is only for bsr and bra.  */
         assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
                || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
                || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));

         fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
         break;

       case STATE_CONDITIONAL_BRANCH:
         assert (current_architecture & cpu6811);

         fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
                                       STATE_BYTE);
         break;

       case STATE_INDEXED_OFFSET:
         assert (current_architecture & cpu6812);

         fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
                                       STATE_BITS5);
         break;

       case STATE_INDEXED_PCREL:
         assert (current_architecture & cpu6812);

         fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL,
                                       STATE_BITS5);
         break;

       case STATE_XBCC_BRANCH:
         assert (current_architecture & cpu6812);

         fragP->fr_subtype = ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE);
         break;

       case STATE_CONDITIONAL_BRANCH_6812:
         assert (current_architecture & cpu6812);

         fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812,
                                       STATE_BYTE);
         break;
       }
    }

  if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
    as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);

  /* Return the size of the variable part of the frag.  */
  return md_relax_table[fragP->fr_subtype].rlx_length;
}

Here is the call graph for this function:

int md_parse_option ( int c  ,
char *  arg 
)

Definition at line 446 of file tc-m68hc11.c.

{
  get_default_target ();
  switch (c)
    {
      /* -S means keep external to 2 bit offset rather than 16 bit one.  */
    case OPTION_SHORT_BRANCHES:
    case 'S':
      flag_fixed_branches = 1;
      break;

    case OPTION_FORCE_LONG_BRANCH:
      flag_force_long_jumps = 1;
      break;

    case OPTION_PRINT_INSN_SYNTAX:
      flag_print_insn_syntax = 1;
      break;

    case OPTION_PRINT_OPCODES:
      flag_print_opcodes = 1;
      break;

    case OPTION_STRICT_DIRECT_MODE:
      flag_strict_direct_addressing = 0;
      break;

    case OPTION_GENERATE_EXAMPLE:
      flag_print_opcodes = 2;
      break;

    case OPTION_MSHORT:
      elf_flags &= ~E_M68HC11_I32;
      break;

    case OPTION_MLONG:
      elf_flags |= E_M68HC11_I32;
      break;

    case OPTION_MSHORT_DOUBLE:
      elf_flags &= ~E_M68HC11_F64;
      break;

    case OPTION_MLONG_DOUBLE:
      elf_flags |= E_M68HC11_F64;
      break;

    case 'm':
      if (strcasecmp (arg, "68hc11") == 0)
       current_architecture = cpu6811;
      else if (strcasecmp (arg, "68hc12") == 0)
       current_architecture = cpu6812;
      else if (strcasecmp (arg, "68hcs12") == 0)
       current_architecture = cpu6812 | cpu6812s;
      else
       as_bad (_("Option `%s' is not recognized."), arg);
      break;

    default:
      return 0;
    }

  return 1;
}

Here is the call graph for this function:

long md_pcrel_from ( fixS *  fixP)

Definition at line 2720 of file tc-m68hc11.c.

{
  if (fixP->fx_r_type == BFD_RELOC_M68HC11_RL_JUMP)
    return 0;

  return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
}

Definition at line 576 of file tc-m68hc11.c.

{
  int align = bfd_get_section_alignment (stdoutput, seg);
  return ((addr + (1 << align) - 1) & (-1 << align));
}

Here is the call graph for this function:

void md_show_usage ( FILE *  stream)

Definition at line 368 of file tc-m68hc11.c.

{
  get_default_target ();
  fprintf (stream, _("\
Motorola 68HC11/68HC12/68HCS12 options:\n\
  -m68hc11 | -m68hc12 |\n\
  -m68hcs12               specify the processor [default %s]\n\
  -mshort                 use 16-bit int ABI (default)\n\
  -mlong                  use 32-bit int ABI\n\
  -mshort-double          use 32-bit double ABI\n\
  -mlong-double           use 64-bit double ABI (default)\n\
  --force-long-branches   always turn relative branches into absolute ones\n\
  -S,--short-branches     do not turn relative branches into absolute ones\n\
                          when the offset is out of range\n\
  --strict-direct-mode    do not turn the direct mode into extended mode\n\
                          when the instruction does not support direct mode\n\
  --print-insn-syntax     print the syntax of instruction in case of error\n\
  --print-opcodes         print the list of instructions with syntax\n\
  --generate-example      generate an example of each instruction\n\
                          (used for testing)\n"), default_cpu);

}

Here is the call graph for this function:

symbolS* md_undefined_symbol ( char *name  ATTRIBUTE_UNUSED)

Definition at line 512 of file tc-m68hc11.c.

{
  return 0;
}
static void print_insn_format ( char *  name) [static]

Definition at line 874 of file tc-m68hc11.c.

{
  struct m68hc11_opcode_def *opc;
  struct m68hc11_opcode *opcode;
  char buf[128];

  opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name);
  if (opc == NULL)
    {
      as_bad (_("Instruction `%s' is not recognized."), name);
      return;
    }
  opcode = opc->opcode;

  as_bad (_("Instruction formats for `%s':"), name);
  do
    {
      char *fmt;

      fmt = print_opcode_format (opcode, 0);
      sprintf (buf, "\t%-5.5s %s", opcode->name, fmt);

      as_bad ("%s", buf);
      opcode++;
    }
  while (strcmp (opcode->name, name) == 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char * print_opcode_format ( struct m68hc11_opcode opcode,
int  example 
) [static]

Definition at line 710 of file tc-m68hc11.c.

{
  static char buf[128];
  int format = opcode->format;
  char *p;

  p = buf;
  buf[0] = 0;
  if (format & M6811_OP_IMM8)
    {
      if (example)
       sprintf (p, "#%d", rand () & 0x0FF);
      else
       strcpy (p, _("#<imm8>"));
      p = &p[strlen (p)];
    }

  if (format & M6811_OP_IMM16)
    {
      if (example)
       sprintf (p, "#%d", rand () & 0x0FFFF);
      else
       strcpy (p, _("#<imm16>"));
      p = &p[strlen (p)];
    }

  if (format & M6811_OP_IX)
    {
      if (example)
       sprintf (p, "%d,X", rand () & 0x0FF);
      else
       strcpy (p, _("<imm8>,X"));
      p = &p[strlen (p)];
    }

  if (format & M6811_OP_IY)
    {
      if (example)
       sprintf (p, "%d,X", rand () & 0x0FF);
      else
       strcpy (p, _("<imm8>,X"));
      p = &p[strlen (p)];
    }

  if (format & M6812_OP_IDX)
    {
      if (example)
       sprintf (p, "%d,X", rand () & 0x0FF);
      else
       strcpy (p, "n,r");
      p = &p[strlen (p)];
    }

  if (format & M6812_OP_PAGE)
    {
      if (example)
       sprintf (p, ", %d", rand () & 0x0FF);
      else
       strcpy (p, ", <page>");
      p = &p[strlen (p)];
    }

  if (format & M6811_OP_DIRECT)
    {
      if (example)
       sprintf (p, "*Z%d", rand () & 0x0FF);
      else
       strcpy (p, _("*<abs8>"));
      p = &p[strlen (p)];
    }

  if (format & M6811_OP_BITMASK)
    {
      if (buf[0])
       *p++ = ' ';

      if (example)
       sprintf (p, "#$%02x", rand () & 0x0FF);
      else
       strcpy (p, _("#<mask>"));

      p = &p[strlen (p)];
      if (format & M6811_OP_JUMP_REL)
       *p++ = ' ';
    }

  if (format & M6811_OP_IND16)
    {
      if (example)
       sprintf (p, _("symbol%d"), rand () & 0x0FF);
      else
       strcpy (p, _("<abs>"));

      p = &p[strlen (p)];
    }

  if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
    {
      if (example)
       {
         if (format & M6811_OP_BITMASK)
           {
             sprintf (p, ".+%d", rand () & 0x7F);
           }
         else
           {
             sprintf (p, "L%d", rand () & 0x0FF);
           }
       }
      else
       strcpy (p, _("<label>"));
    }

  return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_opcode_list ( void  ) [static]

Definition at line 828 of file tc-m68hc11.c.

{
  int i;
  char *prev_name = "";
  struct m68hc11_opcode *opcodes;
  int example = flag_print_opcodes == 2;

  if (example)
    printf (_("# Example of `%s' instructions\n\t.sect .text\n_start:\n"),
           default_cpu);

  opcodes = m68hc11_sorted_opcodes;

  /* Walk the list sorted on names (by md_begin).  We only report
     one instruction per line, and we collect the different operand
     formats.  */
  for (i = 0; i < num_opcodes; i++, opcodes++)
    {
      char *fmt = print_opcode_format (opcodes, example);

      if (example)
       {
         printf ("L%d:\t", i);
         printf ("%s %s\n", opcodes->name, fmt);
       }
      else
       {
         if (strcmp (prev_name, opcodes->name))
           {
             if (i > 0)
              printf ("\n");

             printf ("%-5.5s ", opcodes->name);
             prev_name = (char *) opcodes->name;
           }
         if (fmt[0])
           printf ("  [%s]", fmt);
       }
    }
  printf ("\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static register_id reg_name_search ( char *  name) [static]

Definition at line 907 of file tc-m68hc11.c.

{
  if (strcasecmp (name, "x") == 0 || strcasecmp (name, "ix") == 0)
    return REG_X;
  if (strcasecmp (name, "y") == 0 || strcasecmp (name, "iy") == 0)
    return REG_Y;
  if (strcasecmp (name, "a") == 0)
    return REG_A;
  if (strcasecmp (name, "b") == 0)
    return REG_B;
  if (strcasecmp (name, "d") == 0)
    return REG_D;
  if (strcasecmp (name, "sp") == 0)
    return REG_SP;
  if (strcasecmp (name, "pc") == 0)
    return REG_PC;
  if (strcasecmp (name, "ccr") == 0)
    return REG_CCR;

  return REG_NONE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static register_id register_name ( void  ) [static]

Definition at line 941 of file tc-m68hc11.c.

{
  register_id reg_number;
  char c, *p = input_line_pointer;

  if (!is_name_beginner (*p++))
    return REG_NONE;

  while (is_part_of_name (*p++))
    continue;

  c = *--p;
  if (c)
    *p++ = 0;

  /* Look to see if it's in the register table.  */
  reg_number = reg_name_search (input_line_pointer);
  if (reg_number != REG_NONE)
    {
      if (c)
       *--p = c;

      input_line_pointer = p;
      return reg_number;
    }
  if (c)
    *--p = c;

  return reg_number;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int relaxable_symbol ( symbolS *  symbol) [static]

Definition at line 2990 of file tc-m68hc11.c.

{
  return ! S_IS_WEAK (symbol);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void s_m68hc11_mark_symbol ( int  mark) [static]

Definition at line 2653 of file tc-m68hc11.c.

{
  char *name;
  int c;
  symbolS *symbolP;
  asymbol *bfdsym;
  elf_symbol_type *elfsym;

  do
    {
      name = input_line_pointer;
      c = get_symbol_end ();
      symbolP = symbol_find_or_make (name);
      *input_line_pointer = c;

      SKIP_WHITESPACE ();

      bfdsym = symbol_get_bfdsym (symbolP);
      elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);

      assert (elfsym);

      /* Mark the symbol far (using rtc for function return).  */
      elfsym->internal_elf_sym.st_other |= mark;

      if (c == ',')
       {
         input_line_pointer ++;

         SKIP_WHITESPACE ();

         if (*input_line_pointer == '\n')
           c = '\n';
       }
    }
  while (c == ',');

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void s_m68hc11_mode ( int  ) [static]
static void s_m68hc11_mode ( int x  ATTRIBUTE_UNUSED) [static]

Definition at line 2615 of file tc-m68hc11.c.

{
  char *name = input_line_pointer, ch;

  while (!is_end_of_line[(unsigned char) *input_line_pointer])
    input_line_pointer++;
  ch = *input_line_pointer;
  *input_line_pointer = '\0';

  if (strcmp (name, "mshort") == 0)
    {
      elf_flags &= ~E_M68HC11_I32;
    }
  else if (strcmp (name, "mlong") == 0)
    {
      elf_flags |= E_M68HC11_I32;
    }
  else if (strcmp (name, "mshort-double") == 0)
    {
      elf_flags &= ~E_M68HC11_F64;
    }
  else if (strcmp (name, "mlong-double") == 0)
    {
      elf_flags |= E_M68HC11_F64;
    }
  else
    {
      as_warn (_("Invalid mode: %s\n"), name);
    }
  *input_line_pointer = ch;
  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static void s_m68hc11_relax ( int  ) [static]
static void s_m68hc11_relax ( int ignore  ATTRIBUTE_UNUSED) [static]

Definition at line 2694 of file tc-m68hc11.c.

{
  expressionS ex;

  expression (&ex);

  if (ex.X_op != O_symbol || ex.X_add_number != 0)
    {
      as_bad (_("bad .relax format"));
      ignore_rest_of_line ();
      return;
    }

  fix_new_exp (frag_now, frag_now_fix (), 0, &ex, 1,
               BFD_RELOC_M68HC11_RL_GROUP);

  demand_empty_rest_of_line ();
}

Here is the call graph for this function:

static char * skip_whites ( char *  p) [static]

Definition at line 930 of file tc-m68hc11.c.

{
  while (*p == ' ' || *p == '\t')
    p++;

  return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

arelent* tc_gen_reloc ( asection *section  ATTRIBUTE_UNUSED,
fixS *  fixp 
)

Definition at line 2731 of file tc-m68hc11.c.

{
  arelent *reloc;

  reloc = (arelent *) xmalloc (sizeof (arelent));
  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  if (fixp->fx_r_type == 0)
    reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16);
  else
    reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
  if (reloc->howto == (reloc_howto_type *) NULL)
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
                  _("Relocation %d is not supported by object file format."),
                  (int) fixp->fx_r_type);
      return NULL;
    }

  /* Since we use Rel instead of Rela, encode the vtable entry to be
     used in the relocation's section offset.  */
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    reloc->address = fixp->fx_offset;

  reloc->addend = 0;
  return reloc;
}

Here is the call graph for this function:

int tc_m68hc11_fix_adjustable ( fixS *  fixP)

Definition at line 3207 of file tc-m68hc11.c.

{
  switch (fixP->fx_r_type)
    {
      /* For the linker relaxation to work correctly, these relocs
         need to be on the symbol itself.  */
    case BFD_RELOC_16:
    case BFD_RELOC_M68HC11_RL_JUMP:
    case BFD_RELOC_M68HC11_RL_GROUP:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_32:

      /* The memory bank addressing translation also needs the original
         symbol.  */
    case BFD_RELOC_M68HC11_LO16:
    case BFD_RELOC_M68HC11_PAGE:
    case BFD_RELOC_M68HC11_24:
      return 0;

    default:
      return 1;
    }
}
int tc_m68hc11_force_relocation ( fixS *  fixP)

Definition at line 3193 of file tc-m68hc11.c.

{
  if (fixP->fx_r_type == BFD_RELOC_M68HC11_RL_GROUP)
    return 1;

  return generic_force_reloc (fixP);
}

Here is the call graph for this function:


Variable Documentation

alias alias_opcodes[] [static]
Initial value:
 {
  {"cpd", "cmpd"},
  {"cpx", "cmpx"},
  {"cpy", "cmpy"},
  {0, 0}
}

Definition at line 155 of file tc-m68hc11.c.

const char comment_chars[] = ";!"

Definition at line 30 of file tc-m68hc11.c.

int current_architecture = 0 [static]

Definition at line 239 of file tc-m68hc11.c.

const char* default_cpu [static]

Definition at line 242 of file tc-m68hc11.c.

Definition at line 251 of file tc-m68hc11.c.

const char EXP_CHARS[] = "eE"

Definition at line 34 of file tc-m68hc11.c.

short flag_fixed_branches = 0 [static]

Definition at line 213 of file tc-m68hc11.c.

short flag_force_long_jumps = 0 [static]

Definition at line 216 of file tc-m68hc11.c.

short flag_print_insn_syntax = 0 [static]

Definition at line 226 of file tc-m68hc11.c.

short flag_print_opcodes = 0 [static]

Definition at line 231 of file tc-m68hc11.c.

short flag_strict_direct_addressing = 1 [static]

Definition at line 222 of file tc-m68hc11.c.

const char FLT_CHARS[] = "dD"

Definition at line 35 of file tc-m68hc11.c.

const char line_comment_chars[] = "#*"

Definition at line 31 of file tc-m68hc11.c.

Definition at line 32 of file tc-m68hc11.c.

Definition at line 234 of file tc-m68hc11.c.

Definition at line 148 of file tc-m68hc11.c.

Definition at line 147 of file tc-m68hc11.c.

Definition at line 248 of file tc-m68hc11.c.

size_t md_longopts_size = sizeof (md_longopts)

Definition at line 326 of file tc-m68hc11.c.

const pseudo_typeS md_pseudo_table[]
Initial value:
 {
  
  {"fcb", cons, 1},
  {"fdb", cons, 2},
  {"fcc", stringer, 1},
  {"rmb", s_space, 0},

  
  {"xrefb", s_ignore, 0}, 

  
  {"relax", s_m68hc11_relax, 0},

  
  {"mode", s_m68hc11_mode, 0},

  
  {"far", s_m68hc11_mark_symbol, STO_M68HC12_FAR},

  
  {"interrupt", s_m68hc11_mark_symbol, STO_M68HC12_INTERRUPT},

  {0, 0, 0}
}

Definition at line 262 of file tc-m68hc11.c.

relax_typeS md_relax_table[]

Definition at line 68 of file tc-m68hc11.c.

const char* md_shortopts = "Sm:"

Definition at line 289 of file tc-m68hc11.c.

int num_opcodes [static]

Definition at line 245 of file tc-m68hc11.c.