/* TI PRU assembler.
- Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
Based on tc-nios2.c
static int pru_auto_align_on = 1;
/* The last seen label in the current section. This is used to auto-align
- labels preceeding instructions. */
+ labels preceding instructions. */
static symbolS *pru_last_label;
\f
static PRU_MODE pru_mode = PRU_MODE_ASSEMBLE;
/* This function is used to in self-checking mode
- to check the assembled instruction
- opcode should be the assembled opcode, and exp_opcode
+ to check the assembled instruction.
+ OPCODE should be the assembled opcode, and exp_opcode
the parsed string representing the expected opcode. */
+
static void
pru_check_assembly (unsigned int opcode, const char *exp_opcode)
{
/* As the only 64-bit "insn", LDI32 needs special handling. */
uint32_t insn1 = insn & 0xffffffff;
uint32_t insn2 = insn >> 32;
- SET_INSN_FIELD (IMM16, insn1, fixup & 0xffff);
- SET_INSN_FIELD (IMM16, insn2, fixup >> 16);
+ SET_INSN_FIELD (IMM16, insn1, fixup >> 16);
+ SET_INSN_FIELD (IMM16, insn2, fixup & 0xffff);
+
+ SET_INSN_FIELD (RDSEL, insn1, RSEL_31_16);
+ SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
md_number_to_chars (buf, insn1, 4);
md_number_to_chars (buf + 4, insn2, 4);
if (src2 == NULL)
{
unsigned long imm8 = pru_assemble_noreloc_expression (argstr);
+ if (imm8 >= 0x100)
+ as_bad (_("value %lu is too large for a byte operand"), imm8);
SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8);
SET_INSN_FIELD (IO, insn_info->insn_code, 1);
}
/* QUIRK: LDI must clear IO bit high, even though it has immediate arg. */
SET_INSN_FIELD (IO, insn_info->insn_code, 0);
- SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 & 0xffff);
+ SET_INSN_FIELD (RDSEL, insn_info->insn_code, RSEL_31_16);
+ SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 >> 16);
insn_info->ldi32_imm32 = imm32;
}
unsigned long insn2;
f = frag_more (8);
+ SET_INSN_FIELD (IMM16, insn->insn_code, insn->ldi32_imm32 >> 16);
+ SET_INSN_FIELD (RDSEL, insn->insn_code, RSEL_31_16);
md_number_to_chars (f, insn->insn_code, 4);
insn2 = insn->insn_code;
- SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 >> 16);
- SET_INSN_FIELD (RDSEL, insn2, RSEL_31_16);
+ SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 & 0xffff);
+ SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
md_number_to_chars (f + 4, insn2, 4);
/* Emit debug info. */
case 'E':
pru_check_assembly (insn->insn_code, *argtk++);
+ continue;
+
default:
BAD_CASE (*argp);
}
valueT
md_section_align (asection *seg, valueT addr)
{
- int align = bfd_get_section_alignment (stdoutput, seg);
+ int align = bfd_section_alignment (seg);
return ((addr + (1 << align) - 1) & (-((valueT) 1 << align)));
}
}
/* Implement tc_regname_to_dw2regnum, to convert REGNAME to a DWARF-2
- register number. */
+ register number. Return the starting HW byte-register number. */
+
int
pru_regname_to_dw2regnum (char *regname)
{
+ static const unsigned int regstart[RSEL_NUM_ITEMS] =
+ {
+ [RSEL_7_0] = 0,
+ [RSEL_15_8] = 1,
+ [RSEL_23_16] = 2,
+ [RSEL_31_24] = 3,
+ [RSEL_15_0] = 0,
+ [RSEL_23_8] = 1,
+ [RSEL_31_16] = 2,
+ [RSEL_31_0] = 0,
+ };
+
struct pru_reg *r = pru_reg_lookup (regname);
- if (r == NULL)
+
+ if (r == NULL || r->regsel >= RSEL_NUM_ITEMS)
return -1;
- return r->index;
+ return r->index * 4 + regstart[r->regsel];
}
/* Implement tc_cfi_frame_initial_instructions, to initialize the DWARF-2
void
pru_frame_initial_instructions (void)
{
- const unsigned fp_regno = 4;
+ const unsigned fp_regno = 4 * 4;
cfi_add_CFA_def_cfa (fp_regno, 0);
}