+/* Copy SIZE bits from FROM to TO at address ADDR. */
+
+static void
+tilegx_copy_bits (bfd_byte *addr, int from, int to, int size)
+{
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ int from_byte = (from + i) / 8;
+ int from_bit = (from + i) % 8;
+ int to_byte = (to + i) / 8;
+ int to_bit = (to + i) % 8;
+ bfd_byte to_mask = 1 << to_bit;
+ addr[to_byte] = (addr[to_byte] & ~to_mask)
+ | ((addr[from_byte] >> from_bit << to_bit) & to_mask);
+ }
+}
+
+/* Replace the MASK bits in ADDR with those in INSN, for the next
+ TILEGX_BUNDLE_SIZE_IN_BYTES bytes. */
+
+static void
+tilegx_replace_insn (bfd_byte *addr, const bfd_byte *mask,
+ const bfd_byte *insn)
+{
+ int i;
+ for (i = 0; i < TILEGX_BUNDLE_SIZE_IN_BYTES; i++)
+ {
+ addr[i] = (addr[i] & ~mask[i]) | (insn[i] & mask[i]);
+ }
+}
+
+/* Mask to extract the bits corresponding to an instruction in a
+ specific pipe of a bundle. */
+static const bfd_byte insn_mask_X1[] = {
+ 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f
+};
+
+/* Mask to extract the bits corresponding to an instruction in a
+ specific pipe of a bundle, minus the destination operand and the
+ first source operand. */
+static const bfd_byte insn_mask_X0_no_dest_no_srca[] = {
+ 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00
+};
+
+static const bfd_byte insn_mask_X1_no_dest_no_srca[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f
+};
+
+static const bfd_byte insn_mask_Y0_no_dest_no_srca[] = {
+ 0x00, 0xf0, 0x0f, 0x78, 0x00, 0x00, 0x00, 0x00
+};
+static const bfd_byte insn_mask_Y1_no_dest_no_srca[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x3c
+};
+
+/* Mask to extract the bits corresponding to an instruction in a
+ specific pipe of a bundle, minus the register operands. */
+static const bfd_byte insn_mask_X0_no_operand[] = {
+ 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00
+};
+
+static const bfd_byte insn_mask_X1_no_operand[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f
+};
+
+static const bfd_byte insn_mask_Y0_no_operand[] = {
+ 0x00, 0x00, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00
+};
+
+static const bfd_byte insn_mask_Y1_no_operand[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x3c
+};
+
+/* Various instructions synthesized to support tls references. */
+
+/* ld r0, r0 in the X1 pipe, used for tls ie. */
+static const bfd_byte insn_tls_ie_ld_X1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6a, 0x28
+};
+
+/* ld4s r0, r0 in the X1 pipe, used for tls ie. */
+static const bfd_byte insn_tls_ie_ld4s_X1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x6a, 0x28
+};
+
+/* add r0, r0, tp in various pipes, used for tls ie. */
+static const bfd_byte insn_tls_ie_add_X0X1[] = {
+ 0x00, 0x50, 0x0f, 0x50, 0x00, 0xa8, 0x07, 0x28
+};
+static const bfd_byte insn_tls_ie_add_Y0Y1[] = {
+ 0x00, 0x50, 0x27, 0x2c, 0x00, 0xa8, 0x13, 0x9a
+};
+
+/* addx r0, r0, tp in various pipes, used for tls ie. */
+static const bfd_byte insn_tls_ie_addx_X0X1[] = {
+ 0x00, 0x50, 0x0b, 0x50, 0x00, 0xa8, 0x05, 0x28
+};
+static const bfd_byte insn_tls_ie_addx_Y0Y1[] = {
+ 0x00, 0x50, 0x03, 0x2c, 0x00, 0xa8, 0x01, 0x9a
+};
+
+/* move r0, r0 in various pipes, used for tls gd. */
+static const bfd_byte insn_tls_gd_add_X0X1[] = {
+ 0x00, 0xf0, 0x07, 0x51, 0x00, 0xf8, 0x3b, 0x28
+};
+static const bfd_byte insn_tls_gd_add_Y0Y1[] = {
+ 0x00, 0xf0, 0x0b, 0x54, 0x00, 0xf8, 0x05, 0xae
+};
+
+static const bfd_byte *insn_move_X0X1 = insn_tls_gd_add_X0X1;
+static const bfd_byte *insn_move_Y0Y1 = insn_tls_gd_add_Y0Y1;
+
+static const bfd_byte *insn_add_X0X1 = insn_tls_ie_add_X0X1;
+static const bfd_byte *insn_add_Y0Y1 = insn_tls_ie_add_Y0Y1;
+
+static const bfd_byte *insn_addx_X0X1 = insn_tls_ie_addx_X0X1;
+static const bfd_byte *insn_addx_Y0Y1 = insn_tls_ie_addx_Y0Y1;
+