aboutsummaryrefslogtreecommitdiff
path: root/risugen
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-03-10 11:00:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2011-03-10 16:07:00 +0000
commit9b2697a2dc664d94854112876fe57ad070b17115 (patch)
treeb2e7bd527ec4ef8dbce391cd6266f75f1a2c0e86 /risugen
parentccc31c762028f84d5334147171092090f3dcd0e3 (diff)
risugen: Support reg minus immediate addressing mode
Diffstat (limited to 'risugen')
-rwxr-xr-xrisugen28
1 files changed, 21 insertions, 7 deletions
diff --git a/risugen b/risugen
index 7c43371..9b2c4c4 100755
--- a/risugen
+++ b/risugen
@@ -185,28 +185,36 @@ sub write_mov_rr($$)
}
}
-sub write_mov_ri($$)
+sub write_mov_ri16($$$)
{
- my ($rd, $imm) = @_;
- # Note that this doesn't allow -ve constants. To do that
- # we'd need to support more encodings than the simple imm16 ones.
- die "write_mov_ri: immediate $imm out of range\n" if (($imm & 0xffff0000) != 0);
+ # Write 16 bits of immediate to register, using either MOVW or MOVT
+ my ($rd, $imm, $is_movt) = @_;
+ die "write_mov_ri16: immediate $imm out of range\n" if (($imm & 0xffff0000) != 0);
if ($is_thumb) {
# enc T3
my ($imm4, $i, $imm3, $imm8) = (($imm & 0xf000) >> 12,
($imm & 0x0800) >> 11,
($imm & 0x0700) >> 8,
($imm & 0x00ff));
- insn16(0xf240 | ($i << 10) | $imm4);
+ insn16(0xf240 | ($is_movt << 7) | ($i << 10) | $imm4);
insn16(($imm3 << 12) | ($rd << 8) | $imm8);
} else {
# enc A2
my ($imm4, $imm12) = (($imm & 0xf000) >> 12,
($imm & 0x0fff));
- insn32(0xe3000000 | ($imm4 << 16) | ($rd << 12) | $imm12);
+ insn32(0xe3000000 | ($is_movt << 22) | ($imm4 << 16) | ($rd << 12) | $imm12);
}
}
+sub write_mov_ri($$)
+{
+ # We always use a MOVW/MOVT pair, for simplicity
+ my ($rd, $imm) = @_;
+ write_mov_ri16($rd, ($imm & 0xffff), 0);
+ my $highhalf = ($imm >> 16) & 0xffff;
+ write_mov_ri16($rd, $highhalf, 1) if $highhalf;
+}
+
sub write_random_double_fpreg()
{
my ($low, $high);
@@ -448,6 +456,12 @@ sub reg_plus_imm($$@)
return $base;
}
+sub reg_minus_imm($$@)
+{
+ my ($base, $imm, @trashed) = @_;
+ return reg_plus_imm($base, -$imm, @trashed);
+}
+
sub reg_plus_reg_shifted($$$@)
{
# handle reg + reg LSL imm addressing mode