Esempio n. 1
0
static void
newfix (int ptr, bfd_reloc_code_real_type type, int size, expressionS *operand)
{
  fixS *fixP;

  /* Size is in nibbles.  */
  if (operand->X_add_symbol
      || operand->X_op_symbol
      || operand->X_add_number)
    {
      int is_pcrel;
      switch(type)
        {
        case BFD_RELOC_8_PCREL:
        case BFD_RELOC_Z8K_CALLR:
        case BFD_RELOC_Z8K_DISP7:
          is_pcrel = 1;
	  break;
	default:
	  is_pcrel = 0;
	  break;
        }
      fixP = fix_new_exp (frag_now, ptr, size / 2,
                          operand, is_pcrel, type);
      if (is_pcrel)
	fixP->fx_no_overflow = 1;
    }
}
Esempio n. 2
0
void
pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp)
{
  static int rv[5][2] =
  { { 0, 0 },
    { BFD_RELOC_8, BFD_RELOC_8 },
    { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
    { 0, 0 },
    { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};

  fix_new_exp (frag, where, nbytes, exp, 0,
	       pending_reloc ? pending_reloc
	       : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);

  pending_reloc = 0;
}
Esempio n. 3
0
fixS *
gas_cgen_record_fixup_exp (fragS *frag, int where, const CGEN_INSN *insn,
			   int length, const CGEN_OPERAND *operand, int opinfo,
			   expressionS *exp)
{
  fixS *fixP;

  /* It may seem strange to use operand->attrs and not insn->attrs here,
     but it is the operand that has a pc relative relocation.  */
  fixP = fix_new_exp (frag, where, length / 8, exp,
		      CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
		      (bfd_reloc_code_real_type)
		        ((int) BFD_RELOC_UNUSED
			 + (int) operand->type));
  fixP->fx_cgen.insn = insn;
  fixP->fx_cgen.opinfo = opinfo;
  fixP->fx_cgen.field = NULL;
  fixP->fx_cgen.msb_field_p = 0;

  return fixP;
}
Esempio n. 4
0
void
md_assemble (char *str)
{
  char *op_start;
  char *op_end;

  moxie_opc_info_t *opcode;
  char *p;
  char pend;

  unsigned short iword = 0;

  int nlen = 0;

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

  /* Find the op code end.  */
  op_start = str;
  for (op_end = str;
       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
       op_end++)
    nlen++;

  pend = *op_end;
  *op_end = 0;

  if (nlen == 0)
    as_bad (_("can't find opcode "));
  opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start);
  *op_end = pend;

  if (opcode == NULL)
    {
      as_bad (_("unknown opcode %s"), op_start);
      return;
    }

  p = frag_more (2);

  switch (opcode->itype)
    {
    case MOXIE_F2_A8V:
      iword = (1<<15) | (opcode->opcode << 12);
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	int reg;
	reg = parse_register_operand (&op_end);
	iword += (reg << 8);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	op_end = parse_exp_save_ilp (op_end, &arg);
	fix_new_exp (frag_now,
		     ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
		     1,
		     &arg,
		     0,
		     BFD_RELOC_8);
      }
      break;
    case MOXIE_F1_AB:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int dest, src;
	dest = parse_register_operand (&op_end);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	src  = parse_register_operand (&op_end);
	iword += (dest << 4) + src;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_A4:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;
	int regnum;

 	regnum = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	iword += (regnum << 4);

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);
      }
      break;
    case MOXIE_F1_M:
    case MOXIE_F1_4:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);
      }
      break;
    case MOXIE_F1_NARG:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      if (*op_end != 0)
	as_warn (_("extra stuff on line ignored"));
      break;
    case MOXIE_F1_A:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int reg;
	reg = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
	iword += (reg << 4);
      }
      break;
    case MOXIE_F1_ABi:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int a, b;
	a = parse_register_operand (&op_end);
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rA)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	b = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	iword += (a << 4) + b;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_AiB:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	int a, b;
	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rA)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	a = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	if (*op_end != ',')
	  as_warn (_("expecting comma delimited register operands"));
	op_end++;
	b = parse_register_operand (&op_end);
	iword += (a << 4) + b;
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));
      }
      break;
    case MOXIE_F1_4A:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *where;
	int a;

	op_end = parse_exp_save_ilp (op_end, &arg);
	where = frag_more (4);
	fix_new_exp (frag_now,
		     (where - frag_now->fr_literal),
		     4,
		     &arg,
		     0,
		     BFD_RELOC_32);

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

 	a = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4);
      }
      break;
    case MOXIE_F1_ABi2:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *offset;
	int a, b;

 	a = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	op_end = parse_exp_save_ilp (op_end, &arg);
	offset = frag_more (2);
	fix_new_exp (frag_now,
		     (offset - frag_now->fr_literal),
		     2,
		     &arg,
		     0,
		     BFD_RELOC_16);

	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rX)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	b = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4) + b;
      }
      break;
    case MOXIE_F1_AiB2:
      iword = opcode->opcode << 8;
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;
	char *offset;
	int a, b;

	op_end = parse_exp_save_ilp (op_end, &arg);
	offset = frag_more (2);
	fix_new_exp (frag_now,
		     (offset - frag_now->fr_literal),
		     2,
		     &arg,
		     0,
		     BFD_RELOC_16);

	if (*op_end != '(')
	  {
	    as_bad (_("expecting indirect register `($rX)'"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;
	a = parse_register_operand (&op_end);
	if (*op_end != ')')
	  {
	    as_bad (_("missing closing parenthesis"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

	if (*op_end != ',')
	  {
	    as_bad (_("expecting comma delimited operands"));
	    ignore_rest_of_line ();
	    return;
	  }
	op_end++;

 	b = parse_register_operand (&op_end);
	while (ISSPACE (*op_end))
	  op_end++;

	while (ISSPACE (*op_end))
	  op_end++;
	if (*op_end != 0)
	  as_warn (_("extra stuff on line ignored"));

	iword += (a << 4) + b;
      }
      break;
    case MOXIE_F2_NARG:
      iword = opcode->opcode << 12;
      while (ISSPACE (*op_end))
	op_end++;
      if (*op_end != 0)
	as_warn (_("extra stuff on line ignored"));
      break;
    case MOXIE_F3_PCREL:
      iword = (3<<14) | (opcode->opcode << 10);
      while (ISSPACE (*op_end))
	op_end++;
      {
	expressionS arg;

	op_end = parse_exp_save_ilp (op_end, &arg);
	fix_new_exp (frag_now,
		     (p - frag_now->fr_literal),
		     2,
		     &arg,
		     TRUE,
		     BFD_RELOC_MOXIE_10_PCREL);
      }
      break;
    default:
      abort ();
    }

  md_number_to_chars (p, iword, 2);

  while (ISSPACE (*op_end))
    op_end++;

  if (*op_end != 0)
    as_warn (_("extra stuff on line ignored"));

  if (pending_reloc)
    as_bad (_("Something forgot to clean up\n"));
}
Esempio n. 5
0
/* Convert the instructions into frags and bytes */
void
md_assemble(char *str)
{
  char *op_start;
  char *op_end;
  char op_name[10];
  const bexkat1_opc_info_t *opcode;
  char *p;
  char pend;
  unsigned int iword;
  int nlen = 0;
  int regnum;
  expressionS arg;
  int offset;

  while (*str == ' ')
    str++;
  
  // mark opcode
  op_start = str;
  for (op_end = str;
       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
       op_end++)
    nlen++;
  
  pend = *op_end;
  *op_end = 0;
  strncpy(op_name, op_start, 10);
  *op_end = pend;

  if (nlen == 0)
    as_bad(_("can't find opcode "));
  
  while (ISSPACE(*op_end))
    op_end++;
  
  opcode = (bexkat1_opc_info_t *) hash_find(opcode_hash_control, op_name);
  if (opcode == NULL) {
    as_bad(_("unknown opcode %s"), op_name);
    return;
  }

  iword = (opcode->type << 28) | (opcode->opcode << 24) | opcode->size;

  p = frag_more(4);

  switch (opcode->type) {
  case BEXKAT1_INH:
    if (opcode->args == 0) {
      md_number_to_chars(p, iword, 4);
    }
    if (opcode->args == 1) {
      op_end = parse_exp_save_ilp(op_end, &arg);
      if (opcode->size) {
	md_number_to_chars(p, iword, 4);
	p = frag_more(4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_32);
      } else {
	if (arg.X_op != O_constant) {
	  as_bad(_("offset is not a constant expression"));
	  ignore_rest_of_line();
	  return;
	}
	offset = arg.X_add_number;
	if (offset < -16384 || offset > 16383) {
	  as_bad(_("offset is out of range: %d\n"), offset);
	  ignore_rest_of_line();
	  return;
	}
	
	md_number_to_chars(p, iword, 4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_BEXKAT1_15);
      }
    }
    break;
  case BEXKAT1_PUSH:
    if (opcode->args == 1 && opcode->opcode == 2) // bsr
      goto branch;
    if (opcode->args == 1) {
      if (opcode->size) {
	op_end = parse_exp_save_ilp(op_end, &arg);
	md_number_to_chars(p, iword, 4);
	p = frag_more(4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_32);
      } else {
	regnum = parse_regnum(&op_end);
	if (regnum == -1)
	  return; 
	while (ISSPACE(*op_end))
	  op_end++;
	iword |= (regnum & 0xf) << 20; // A
	md_number_to_chars(p, iword, 4);
      }
    }
    if (opcode->args == 2) {
      if (*op_end != '(')
	op_end = parse_exp_save_ilp(op_end, &arg);
      else { // Implicit 0 offset to allow for indirect
	arg.X_op = O_constant;
	arg.X_add_number = 0;
      }
      
      if (*op_end != '(') {
	as_bad(_("missing open paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++; // burn paren
      while (ISSPACE(*op_end))
	op_end++;
      
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 20; // A
      
      if (*op_end != ')') {
	as_bad(_("missing close paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++;
      
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset < -16384 || offset > 16383) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  case BEXKAT1_POP:
    if (opcode->args == 0) {
      md_number_to_chars(p, iword, 4);
    }
    if (opcode->args == 1) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 20; // A
      md_number_to_chars(p, iword, 4);
    }
    break;
  case BEXKAT1_MOV:
    if (opcode->opcode == 0) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
        return; 
      while (ISSPACE(*op_end))
        op_end++;
      iword |= (regnum & 0xf) << 20; // A
      md_number_to_chars(p, iword, 4);
      break;
    }
    /* __attribute__((fallthrough)); */
  case BEXKAT1_CMP:
  case BEXKAT1_FPU:
  case BEXKAT1_FP:
  case BEXKAT1_ALU:
  case BEXKAT1_INT:
  case BEXKAT1_INTU:
    if (opcode->args > 1) {
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
        return; 
      while (ISSPACE(*op_end))
        op_end++;
      iword |= (regnum & 0xf) << 20; // A

      if (*op_end != ',') {
        as_bad(_("missing comma: %s"), op_end);
        return;
      }
      op_end++;
      while (ISSPACE(*op_end))
        op_end++;
    
    }

    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 16; // B

    if (opcode->args > 2) {

      if (*op_end != ',') {
	as_bad(_("missing comma: %s"), op_end);
	return;
      }
      op_end++;
      while (ISSPACE(*op_end))
	op_end++;
      
      if (opcode->opcode < 8) {
	regnum = parse_regnum(&op_end);
	if (regnum == -1)
	  return; 
	while (ISSPACE(*op_end))
	  op_end++;
	iword |= (regnum & 0xf) << 12; // C
	md_number_to_chars(p, iword, 4);
      } else {
	op_end = parse_exp_save_ilp(op_end, &arg);
	if (arg.X_op != O_constant) {
	  as_bad(_("offset is not a constant expression"));
	  ignore_rest_of_line();
	  return;
	}
	offset = arg.X_add_number;
	if (offset < -16384 || offset > 16383) {
	  as_bad(_("offset is out of range: %d\n"), offset);
	  ignore_rest_of_line();
	  return;
	}
	md_number_to_chars(p, iword, 4);
	fix_new_exp(frag_now,
		    (p - frag_now->fr_literal),
		    4,
		    &arg,
		    0,
		    BFD_RELOC_BEXKAT1_15);
      }
    } else {
      md_number_to_chars(p, iword, 4);
    }
    break;
branch:
  case BEXKAT1_BRANCH:
    md_number_to_chars(p, iword, 4);
    op_end = parse_exp_save_ilp(op_end, &arg);
    if (target_big_endian)
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  TRUE,
		  BFD_RELOC_BEXKAT1_15_PCREL);
    else
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  TRUE,
		  BFD_RELOC_BEXKAT1_15_PCREL);
    break;
  case BEXKAT1_LOAD:
  case BEXKAT1_STORE:
    // A, 
    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 20; // A
    
    if (*op_end != ',') {
      as_bad(_("missing comma: %s"), op_end);
      return;
    }
    op_end++;
    while (ISSPACE(*op_end))
      op_end++;
    /* __attribute__((fallthrough)); */
  case BEXKAT1_JUMP:
    if (opcode->size) { // big address
      md_number_to_chars(p, iword, 4);
      op_end = parse_exp_save_ilp(op_end, &arg);
      p = frag_more(4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_32);
    } else { // exp(B)
      if (*op_end != '(')
	op_end = parse_exp_save_ilp(op_end, &arg);
      else { // Implicit 0 offset to allow for indirect
	arg.X_op = O_constant;
	arg.X_add_number = 0;
      }
      
      if (*op_end != '(') {
	as_bad(_("missing open paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++; // burn paren
      while (ISSPACE(*op_end))
	op_end++;
      
      regnum = parse_regnum(&op_end);
      if (regnum == -1)
	return; 
      while (ISSPACE(*op_end))
	op_end++;
      iword |= (regnum & 0xf) << 16; // B
      
      if (*op_end != ')') {
	as_bad(_("missing close paren: %s"), op_end);
	ignore_rest_of_line();
	return;
      }
      op_end++;
      
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset < -16384 || offset > 16383) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  case BEXKAT1_LDI:
    regnum = parse_regnum(&op_end);
    if (regnum == -1)
      return; 
    while (ISSPACE(*op_end))
      op_end++;
    iword |= (regnum & 0xf) << 20; // A
    
    if (*op_end != ',') {
      as_bad(_("missing comma: %s"), op_end);
      return;
    }
    op_end++;
    while (ISSPACE(*op_end))
      op_end++;
    op_end = parse_exp_save_ilp(op_end, &arg);
    if (opcode->size) {
      md_number_to_chars(p, iword, 4);
      p = frag_more(4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_32);
    } else {
      if (arg.X_op != O_constant) {
	as_bad(_("offset is not a constant expression"));
	ignore_rest_of_line();
	return;
      }
      offset = arg.X_add_number;
      if (offset >= 32768) {
	as_bad(_("offset is out of range: %d\n"), offset);
	ignore_rest_of_line();
	return;
      }

      md_number_to_chars(p, iword, 4);
      fix_new_exp(frag_now,
		  (p - frag_now->fr_literal),
		  4,
		  &arg,
		  0,
		  BFD_RELOC_BEXKAT1_15);
    }
    break;
  }

  while (ISSPACE(*op_end))
    op_end++;
  if (*op_end != 0)
    as_warn("extra stuff on line ignored %s %c", op_start, *op_end);
  if (pending_reloc)
    as_bad("Something forgot to clean up\n");
  return;
}