/* tc-pdp11.c - pdp11-specific -
- Copyright 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "as.h"
#include "safe-ctype.h"
/* A representation for PDP-11 machine code. */
struct pdp11_code
{
- char *error;
+ const char *error;
int code;
int additional; /* Is there an additional word? */
int word; /* Additional word, if any. */
{ 0, 0, 0 },
};
-static struct hash_control *insn_hash = NULL;
+static htab_t insn_hash = NULL;
\f
static int
-set_option (char *arg)
+set_option (const char *arg)
{
int yes = 1;
arg += 3;
}
- /* Commersial instructions. */
+ /* Commercial instructions. */
if (strcmp (arg, "cis") == 0)
pdp11_extension[PDP11_CIS] = yes;
/* Call supervisor mode. */
init_defaults ();
- insn_hash = hash_new ();
- if (insn_hash == NULL)
- as_fatal ("Virtual memory exhausted");
+ insn_hash = str_htab_create ();
for (i = 0; i < pdp11_num_opcodes; i++)
- hash_insert (insn_hash, pdp11_opcodes[i].name, (void *) (pdp11_opcodes + i));
+ str_hash_insert (insn_hash, pdp11_opcodes[i].name, pdp11_opcodes + i, 0);
for (i = 0; i < pdp11_num_aliases; i++)
- hash_insert (insn_hash, pdp11_aliases[i].name, (void *) (pdp11_aliases + i));
+ str_hash_insert (insn_hash, pdp11_aliases[i].name, pdp11_aliases + i, 0);
}
void
{
/* On a PDP-11, 0x1234 is stored as "\x12\x34", and
0x12345678 is stored as "\x56\x78\x12\x34". It's
- anyones guess what 0x123456 would be stored like. */
+ anyone's guess what 0x123456 would be stored like. */
switch (nbytes)
{
con[2] = value & 0xff;
con[3] = (value >> 8) & 0xff;
break;
+ case 8:
+ con[0] = (value >> 48) & 0xff;
+ con[1] = (value >> 56) & 0xff;
+ con[2] = (value >> 32) & 0xff;
+ con[3] = (value >> 40) & 0xff;
+ con[4] = (value >> 16) & 0xff;
+ con[5] = (value >> 24) & 0xff;
+ con[6] = value & 0xff;
+ con[7] = (value >> 8) & 0xff;
+ break;
default:
BAD_CASE (nbytes);
}
that they reference. Knows about order of bytes in address. */
void
-md_apply_fix3 (fixS *fixP,
+md_apply_fix (fixS *fixP,
valueT * valP,
segT seg ATTRIBUTE_UNUSED)
{
buf = fixP->fx_where + fixP->fx_frag->fr_literal;
size = fixP->fx_size;
- code = md_chars_to_number (buf, size);
+ code = md_chars_to_number ((unsigned char *) buf, size);
switch (fixP->fx_r_type)
{
+ case BFD_RELOC_8:
+ mask = 0xff;
+ shift = 0;
+ break;
case BFD_RELOC_16:
case BFD_RELOC_16_PCREL:
mask = 0xffff;
shift = 0;
break;
+ case BFD_RELOC_32:
+ mask = 0xffffffff;
+ shift = 0;
+ break;
case BFD_RELOC_PDP11_DISP_8_PCREL:
mask = 0x00ff;
shift = 1;
}
long
-md_chars_to_number (con, nbytes)
- unsigned char con[]; /* Low order byte 1st. */
- int nbytes; /* Number of bytes in the input. */
+md_chars_to_number (unsigned char *con, int nbytes)
{
/* On a PDP-11, 0x1234 is stored as "\x12\x34", and
0x12345678 is stored as "\x56\x78\x12\x34". It's
- anyones guess what 0x123456 would be stored like. */
+ anyone's guess what 0x123456 would be stored like. */
switch (nbytes)
{
case 0:
str++;
break;
default:
- operand->error = "Bad register name";
+ operand->error = _("Bad register name");
return str - 1;
}
}
}
else
{
- operand->error = "Bad register name";
+ operand->error = _("Bad register name");
return str;
}
+ if (ISALNUM (*str) || *str == '_' || *str == '.')
+ {
+ operand->error = _("Bad register name");
+ str -= 2;
+ }
+
return str;
}
str++;
break;
default:
- operand->error = "Bad register name";
+ operand->error = _("Bad register name");
return str - 2;
}
}
else
{
- operand->error = "Bad register name";
+ operand->error = _("Bad register name");
return str;
}
str = parse_ac5 (str, operand);
if (!operand->error && operand->code > 3)
{
- operand->error = "Bad register name";
+ operand->error = _("Bad register name");
return str - 3;
}
if (seg == NULL)
{
input_line_pointer = save_input_line_pointer;
- operand->error = "Error in expression";
+ operand->error = _("Error in expression");
return str;
}
str = skip_whitespace (str);
if (*str != ')')
{
- operand->error = "Missing ')'";
+ operand->error = _("Missing ')'");
return str;
}
str++;
case O_big:
if (operand->reloc.exp.X_add_number > 0)
{
- operand->error = "Error in expression";
+ operand->error = _("Error in expression");
break;
}
/* It's a floating literal... */
as_warn (_("Low order bits truncated in immediate float operand"));
break;
default:
- operand->error = "Error in expression";
+ operand->error = _("Error in expression");
break;
}
operand->code = 027;
/* label, d(rn), -(rn) */
default:
{
- char *old = str;
-
if (strncmp (str, "-(", 2) == 0) /* -(rn) */
{
str = parse_reg (str + 2, operand);
str = skip_whitespace (str);
if (*str != ')')
{
- operand->error = "Missing ')'";
+ operand->error = _("Missing ')'");
return str;
}
operand->code |= 040;
if (*str != '(')
{
- if (operand->reloc.exp.X_op != O_symbol)
- {
- operand->error = "Label expected";
- return old;
- }
operand->code = 067;
operand->additional = 1;
operand->word = 0;
if (*str != ')')
{
- operand->error = "Missing ')'";
+ operand->error = _("Missing ')'");
return str;
}
switch (operand->reloc.exp.X_op)
{
case O_symbol:
- operand->word = 0;
- operand->reloc.pc_rel = 1;
+ operand->reloc.type = BFD_RELOC_16;
+ operand->reloc.pc_rel = 0;
break;
case O_constant:
if ((operand->code & 7) == 7)
if (*str == '@' || *str == '*')
{
- str = parse_op_no_deferred (str + 1, operand);
+ /* @(Rn) == @0(Rn): Mode 7, Indexed deferred.
+ Check for auto-increment deferred. */
+ if (str[1] == '('
+ && str[2] != 0
+ && str[3] != 0
+ && str[4] != 0
+ && str[5] != '+')
+ {
+ /* Change implied to explicit index deferred. */
+ *str = '0';
+ str = parse_op_no_deferred (str, operand);
+ }
+ else
+ {
+ /* @Rn == (Rn): Register deferred. */
+ str = parse_reg (str + 1, operand);
+
+ /* Not @Rn */
+ if (operand->error)
+ {
+ operand->error = NULL;
+ str = parse_op_no_deferred (str, operand);
+ }
+ }
+
if (operand->error)
return str;
+
operand->code |= 010;
}
else
parse_ac5 (str, operand);
if (!operand->error)
{
- operand->error = "Float AC not legal as integer operand";
+ operand->error = _("Float AC not legal as integer operand");
return str;
}
parse_reg (str, operand);
if (!operand->error)
{
- operand->error = "General register not legal as float operand";
+ operand->error = _("General register not legal as float operand");
return str;
}
struct pdp11_code insn, op1, op2;
int error;
int size;
- char *err = NULL;
+ const char *err = NULL;
char *str;
char *p;
char c;
p = find_whitespace (str);
if (p - str == 0)
{
- as_bad ("No instruction found");
+ as_bad (_("No instruction found"));
return;
}
c = *p;
*p = '\0';
- op = (struct pdp11_opcode *)hash_find (insn_hash, str);
+ op = (struct pdp11_opcode *)str_hash_find (insn_hash, str);
*p = c;
if (op == 0)
{
if (!pdp11_extension[op->extension])
{
- as_warn ("Unsupported instruction set extension: %s", op->name);
+ as_warn (_("Unsupported instruction set extension: %s"), op->name);
return;
}
{
case PDP11_OPCODE_NO_OPS:
str = skip_whitespace (str);
- if (*str == 0)
- str = "";
break;
case PDP11_OPCODE_IMM3:
break;
if (op1.reloc.exp.X_op != O_constant || op1.reloc.type != BFD_RELOC_NONE)
{
- op1.error = "operand is not an absolute constant";
+ op1.error = _("operand is not an absolute constant");
break;
}
switch (op->type)
case PDP11_OPCODE_IMM3:
if (op1.reloc.exp.X_add_number & ~7)
{
- op1.error = "3-bit immediate out of range";
+ op1.error = _("3-bit immediate out of range");
break;
}
break;
case PDP11_OPCODE_IMM6:
if (op1.reloc.exp.X_add_number & ~0x3f)
{
- op1.error = "6-bit immediate out of range";
+ op1.error = _("6-bit immediate out of range");
break;
}
break;
case PDP11_OPCODE_IMM8:
if (op1.reloc.exp.X_add_number & ~0xff)
{
- op1.error = "8-bit immediate out of range";
+ op1.error = _("8-bit immediate out of range");
break;
}
break;
case PDP11_OPCODE_DISPL:
{
- char *new;
- new = parse_expression (str, &op1);
+ char *new_pointer;
+ new_pointer = parse_expression (str, &op1);
op1.code = 0;
op1.reloc.pc_rel = 1;
op1.reloc.type = BFD_RELOC_PDP11_DISP_8_PCREL;
if (op1.reloc.exp.X_op != O_symbol)
{
- op1.error = "Symbol expected";
+ op1.error = _("Symbol expected");
break;
}
if (op1.code & ~0xff)
{
- err = "8-bit displacement out of range";
+ err = _("8-bit displacement out of range");
break;
}
- str = new;
+ str = new_pointer;
insn.code |= op1.code;
insn.reloc = op1.reloc;
}
str = parse_separator (str, &error);
if (error)
{
- op2.error = "Missing ','";
+ op2.error = _("Missing ','");
break;
}
str = parse_op (str, &op1);
str = parse_separator (str, &error);
if (error)
{
- op2.error = "Missing ','";
+ op2.error = _("Missing ','");
break;
}
str = parse_reg (str, &op2);
str = parse_separator (str, &error);
if (error)
{
- op1.error = "Missing ','";
+ op1.error = _("Missing ','");
break;
}
str = parse_fop (str, &op1);
str = parse_separator (str, &error);
if (error)
{
- op1.error = "Missing ','";
+ op1.error = _("Missing ','");
break;
}
str = parse_ac (str, &op2);
str = parse_separator (str, &error);
if (error)
{
- op1.error = "Missing ','";
+ op1.error = _("Missing ','");
break;
}
str = parse_op (str, &op1);
str = parse_separator (str, &error);
if (error)
{
- op1.error = "Missing ','";
+ op1.error = _("Missing ','");
break;
}
str = parse_ac (str, &op2);
str = parse_separator (str, &error);
if (error)
{
- op2.error = "Missing ','";
+ op2.error = _("Missing ','");
break;
}
str = parse_op (str, &op2);
case PDP11_OPCODE_REG_DISPL:
{
- char *new;
+ char *new_pointer;
str = parse_reg (str, &op2);
if (op2.error)
break;
str = parse_separator (str, &error);
if (error)
{
- op1.error = "Missing ','";
+ op1.error = _("Missing ','");
break;
}
- new = parse_expression (str, &op1);
+ new_pointer = parse_expression (str, &op1);
op1.code = 0;
op1.reloc.pc_rel = 1;
op1.reloc.type = BFD_RELOC_PDP11_DISP_6_PCREL;
if (op1.reloc.exp.X_op != O_symbol)
{
- op1.error = "Symbol expected";
+ op1.error = _("Symbol expected");
break;
}
if (op1.code & ~0x3f)
{
- err = "6-bit displacement out of range";
+ err = _("6-bit displacement out of range");
break;
}
- str = new;
+ str = new_pointer;
insn.code |= op1.code;
insn.reloc = op1.reloc;
}
{
str = skip_whitespace (str);
if (*str)
- err = "Too many operands";
+ err = _("Too many operands");
}
{
if (err)
{
- as_bad (err);
+ as_bad ("%s", err);
return;
}
}
static int
-set_cpu_model (char *arg)
+set_cpu_model (const char *arg)
{
char buf[4];
char *model = buf;
}
static int
-set_machine_model (char *arg)
+set_machine_model (const char *arg)
{
if (strncmp (arg, "pdp-11/", 7) != 0
&& strncmp (arg, "pdp11/", 6) != 0
See if it's a processor-specific option. */
int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
{
init_defaults ();
{
fprintf (stream, "\
\n\
-PDP-11 instruction set extentions:\n\
+PDP-11 instruction set extensions:\n\
\n\
--m(no-)cis allow (disallow) commersial instruction set\n\
+-m(no-)cis allow (disallow) commercial instruction set\n\
-m(no-)csm allow (disallow) CSM instruction\n\
-m(no-)eis allow (disallow) full extended instruction set\n\
-m(no-)fis allow (disallow) KEV11 floating-point instructions\n\
-m(no-)ucode allow (disallow) microcode instructions\n\
-mall-extensions allow all instruction set extensions\n\
(this is the default)\n\
--mno-extentions disallow all instruction set extensions\n\
--pic generate position-indepenent code\n\
+-mno-extensions disallow all instruction set extensions\n\
+-pic generate position-independent code\n\
\n\
PDP-11 CPU model options:\n\
\n\
arelent *reloc;
bfd_reloc_code_real_type code;
- reloc = xmalloc (sizeof (* reloc));
+ reloc = XNEW (arelent);
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
- /* This is taken account for in md_apply_fix3(). */
+ /* This is taken account for in md_apply_fix(). */
reloc->addend = -symbol_get_bfdsym (fixp->fx_addsy)->section->vma;
- switch (fixp->fx_r_type)
+ code = fixp->fx_r_type;
+ if (fixp->fx_pcrel)
{
- case BFD_RELOC_16:
- if (fixp->fx_pcrel)
- code = BFD_RELOC_16_PCREL;
- else
- code = BFD_RELOC_16;
- break;
+ switch (code)
+ {
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
- case BFD_RELOC_16_PCREL:
- code = BFD_RELOC_16_PCREL;
- break;
+ case BFD_RELOC_16_PCREL:
+ break;
- default:
- BAD_CASE (fixp->fx_r_type);
- return NULL;
+ default:
+ BAD_CASE (code);
+ return NULL;
+ }
}
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
if (reloc->howto == NULL)
{
as_bad_where (fixp->fx_file, fixp->fx_line,
- "Can not represent %s relocation in this object file format",
+ _("Can not represent %s relocation in this object file format"),
bfd_get_reloc_code_name (code));
return NULL;
}
frag_align (alignment, 0, 1);
record_alignment (now_seg, alignment);
}
+
+const char *
+md_atof (int type, char * litP, int * sizeP)
+{
+ return vax_md_atof (type, litP, sizeP);
+}