On 9/17/22 00:43, Song Gao wrote:
+sub write_mov_positive_ri($$)
+{
+ # Use lu12i.w and ori instruction
+ my ($rd, $imm) = @_;
+ my $high_20 = ($imm >> 12) & 0xfffff;
+
+ if ($high_20) {
+ # lu12i.w rd, si20
+ insn32(0x14000000 | $high_20 << 5 | $rd);
This isn't necessarily positive -- lu12i.w sign-extends from 32-bits.
+ # ori rd, rd, ui12
+ insn32(0x03800000 | ($imm & 0xfff) << 10 | $rd << 5 | $rd);
+ } else {
+ # ori rd, 0, ui12
+ insn32(0x03800000 | ($imm & 0xfff) << 10 | 0 << 5 | $rd);
+ }
+}
+
+sub write_mov_ri($$)
+{
+ my ($rd, $imm) = @_;
+
+ if ($imm < 0) {
+ my $tmp = 0 - $imm ;
+ write_mov_positive_ri($rd, $tmp);
+ write_sub_rrr($rd, 0, $rd);
+ } else {
+ write_mov_positive_ri($rd, $imm);
+ }
+}
OTOH, I'm not sure why you'd need to split out write_mov_positive_ri and negate. I don't
*think* we need to handle completely arbitrary constants. From the aarch64 code we
certainly don't.
I might write
if ($imm >= -0x1000 && $imm <= 0xfff) {
addi.w
} elsif ($imm >= -0x80000000 && $imm <= 0x7fffffff) {
lu12i.w
ori
} else {
die "unhandled immediate load";
}
Otherwise,
Reviewed-by: Richard Henderson <[email protected]>
r~