static unsigned elf_flags = 0;
+/* Indicate whether we are already assembling any instructions. */
+static bool start_assemble = false;
+
static bool probing_insn_operands;
/* Set the default_isa_spec. Return 0 if the spec isn't supported.
if (rvc_value)
elf_flags |= EF_RISCV_RVC;
+ if (start_assemble && subseg_text_p (now_seg)
+ && riscv_opts.rvc && !rvc_value)
+ {
+ struct riscv_segment_info_type *info
+ = &seg_info(now_seg)->tc_segment_info_data;
+
+ info->last_insn16 = true;
+ info->rvc = rvc_value;
+ }
+
riscv_opts.rvc = rvc_value;
}
riscv_set_arch_str (&file_arch_str);
riscv_set_arch_str (&riscv_rps_as.subset_list->arch_str);
- riscv_set_rvc (false);
- if (riscv_subset_supports (&riscv_rps_as, "c")
- || riscv_subset_supports (&riscv_rps_as, "zca"))
- riscv_set_rvc (true);
+ riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c")
+ || riscv_subset_supports (&riscv_rps_as, "zca"));
if (riscv_subset_supports (&riscv_rps_as, "ztso"))
riscv_set_tso ();
As in 0f12.456 or 0d1.2345e12. */
const char FLT_CHARS[] = "rRsSfFdDxXpPhH";
-/* Indicate we are already assemble any instructions or not. */
-static bool start_assemble = false;
-
/* Indicate ELF attributes are explicitly set. */
static bool explicit_attr = false;
valueT value = (valueT) (frag_now_fix () - max_chars);
seg_info (now_seg)->tc_segment_info_data.map_state = to_state;
+ seg_info (now_seg)->tc_segment_info_data.last_insn16 = false;
const char *arch_str = reset_seg_arch_str
? riscv_rps_as.subset_list->arch_str : NULL;
make_mapping_symbol (to_state, value, frag_now, arch_str,
generic_bignum[num],
llen);
memset(ip->insn_long_opcode + repr_bytes, 0, bytes - repr_bytes);
- return NULL;
}
-
- if (bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
+ else if (bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
return _("value conflicts with instruction length");
+ if (!riscv_opts.rvc && (bytes & 2))
+ seg_info (now_seg)->tc_segment_info_data.last_insn16 = true;
+
return NULL;
}
riscv_update_subset (&riscv_rps_as, name);
riscv_set_arch_str (&riscv_rps_as.subset_list->arch_str);
- riscv_set_rvc (false);
- if (riscv_subset_supports (&riscv_rps_as, "c")
- || riscv_subset_supports (&riscv_rps_as, "zca"))
- riscv_set_rvc (true);
+ riscv_set_rvc (riscv_subset_supports (&riscv_rps_as, "c")
+ || riscv_subset_supports (&riscv_rps_as, "zca"));
if (riscv_subset_supports (&riscv_rps_as, "ztso"))
riscv_set_tso ();
char *nops;
expressionS ex;
- /* If we are moving to a smaller alignment than the instruction size, then no
- alignment is required. */
+ /* If we are moving to alignment no larger than the instruction size, then
+ no special alignment handling is required. */
if (bytes <= insn_alignment)
- return true;
+ {
+ if (bytes == insn_alignment)
+ seg_info (now_seg)->tc_segment_info_data.last_insn16 = false;
+ return false;
+ }
/* When not relaxing, riscv_handle_align handles code alignment. */
if (!riscv_opts.relax)
return false;
+ /* If the last item emitted was not an ordinary insn, first align back to
+ insn granularity. Don't do this unconditionally, to avoid altering frags
+ when that's not actually needed. */
+ if (seg_info (now_seg)->tc_segment_info_data.map_state != MAP_INSN
+ || seg_info (now_seg)->tc_segment_info_data.last_insn16)
+ frag_align_code (riscv_opts.rvc ? 1 : 2, 0);
+ seg_info (now_seg)->tc_segment_info_data.last_insn16 = false;
+
/* Maybe we should use frag_var to create a new rs_align_code fragment,
rather than just use frag_more to handle an alignment here? So that we
don't need to call riscv_mapping_state again later, and then only need
return -1;
}
+void
+riscv_elf_section_change_hook (void)
+{
+ struct riscv_segment_info_type *info
+ = &seg_info(now_seg)->tc_segment_info_data;
+
+ if (info->rvc && !riscv_opts.rvc)
+ info->last_insn16 = true;
+
+ info->rvc = riscv_opts.rvc;
+}
+
void
riscv_elf_final_processing (void)
{
--- /dev/null
+#as: -mrelax
+#objdump: -drw
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <rvc_func>:
+[ ]+0:[ ]+8082[ ]+ret
+[ ]+2:[ ]+0001[ ]+nop
+[ ]+4:[ ]+00000013[ ]+nop[ ]+4: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+
+0+008 <non_rvc_func>:
+[ ]+8:[ ]+00008067[ ]+ret
+
+0+00c <insn>:
+[ ]+c:[ ]+00000013[ ]+nop
+[ ]+10:[ ]+0000[ ]+\.insn 2, 0x0+
+[ ]+12:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+14:[ ]+00000013[ ]+nop[ ]+14: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+[ ]+18:[ ]+00008067[ ]+ret
+
+0+001c <hword>:
+[ ]+1c:[ ]+00000013[ ]+nop
+[ ]+20:[ ]+0000[ ]+\.short 0x0+
+[ ]+22:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+24:[ ]+00000013[ ]+nop[ ]+24: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+[ ]+28:[ ]+00008067[ ]+ret
+
+0+002c <byte>:
+[ ]+2c:[ ]+00000013[ ]+nop
+[ ]+30:[ ]+00[ ]+\.byte 0x0+
+[ ]+31:[ ]+00[ ]+\.byte 0x0+
+[ ]+32:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+34:[ ]+00000013[ ]+nop[ ]+34: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+[ ]+38:[ ]+00008067[ ]+ret
+[ ]+3c:[ ]+00000013[ ]+nop[ ]+3c: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+
+0+0040 <func1>:
+[ ]+40:[ ]+00000013[ ]+nop
+[ ]+44:[ ]+00008067[ ]+ret
+
+0+0048 <func2>:
+[ ]+48:[ ]+8082[ ]+ret
+[ ]+4a:[ ]+0001[ ]+nop
+[ ]+4c:[ ]+00000013[ ]+nop[ ]+4c: R_RISCV_ALIGN[ ]+\*ABS\*\+0x4
+
+0+0050 <func3>:
+[ ]+50:[ ]+00000013[ ]+nop
+[ ]+54:[ ]+00008067[ ]+ret
+#pass
--- /dev/null
+#as: -mrelax
+#objdump: -dr
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <rvc_func>:
+[ ]+0:[ ]+8082[ ]+ret
+[ ]+2:[ ]+0001[ ]+nop
+
+0+004 <non_rvc_func>:
+[ ]+4:[ ]+00008067[ ]+ret
+
+0+008 <insn>:
+[ ]+8:[ ]+00000013[ ]+nop
+[ ]+c:[ ]+0000[ ]+\.insn 2, 0x0+
+[ ]+e:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+10:[ ]+00008067[ ]+ret
+
+0+0014 <hword>:
+[ ]+14:[ ]+00000013[ ]+nop
+[ ]+18:[ ]+0000[ ]+\.short 0x0+
+[ ]+1a:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+1c:[ ]+00008067[ ]+ret
+
+0+0020 <byte>:
+[ ]+20:[ ]+00000013[ ]+nop
+[ ]+24:[ ]+00[ ]+\.byte 0x0+
+[ ]+25:[ ]+00[ ]+\.byte 0x0+
+[ ]+26:[ ]+0001[ ]+\.insn 2, 0x0*1
+[ ]+28:[ ]+00008067[ ]+ret
+#pass