summaryrefslogtreecommitdiffstats
path: root/target/arm/translate.c
diff options
context:
space:
mode:
authorPeter Maydell2021-06-28 15:58:20 +0200
committerPeter Maydell2021-07-02 12:48:36 +0200
commitdfd66bc0f37dde37b8b2d7bad3a7075332e75fb4 (patch)
treee3c363f88c3b817a2574e750ee37a5e0dcd843a6 /target/arm/translate.c
parenttarget/arm: Fix bugs in MVE VRMLALDAVH, VRMLSLDAVH (diff)
downloadqemu-dfd66bc0f37dde37b8b2d7bad3a7075332e75fb4.tar.gz
qemu-dfd66bc0f37dde37b8b2d7bad3a7075332e75fb4.tar.xz
qemu-dfd66bc0f37dde37b8b2d7bad3a7075332e75fb4.zip
target/arm: Make asimd_imm_const() public
The function asimd_imm_const() in translate-neon.c is an implementation of the pseudocode AdvSIMDExpandImm(), which we will also want for MVE. Move the implementation to translate.c, with a prototype in translate.h. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210628135835.6690-4-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a0c6cfa902..95ceb24ec3 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -90,6 +90,63 @@ void arm_translate_init(void)
a64_translate_init();
}
+uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
+{
+ /* Expand the encoded constant as per AdvSIMDExpandImm pseudocode */
+ switch (cmode) {
+ case 0: case 1:
+ /* no-op */
+ break;
+ case 2: case 3:
+ imm <<= 8;
+ break;
+ case 4: case 5:
+ imm <<= 16;
+ break;
+ case 6: case 7:
+ imm <<= 24;
+ break;
+ case 8: case 9:
+ imm |= imm << 16;
+ break;
+ case 10: case 11:
+ imm = (imm << 8) | (imm << 24);
+ break;
+ case 12:
+ imm = (imm << 8) | 0xff;
+ break;
+ case 13:
+ imm = (imm << 16) | 0xffff;
+ break;
+ case 14:
+ if (op) {
+ /*
+ * This is the only case where the top and bottom 32 bits
+ * of the encoded constant differ.
+ */
+ uint64_t imm64 = 0;
+ int n;
+
+ for (n = 0; n < 8; n++) {
+ if (imm & (1 << n)) {
+ imm64 |= (0xffULL << (n * 8));
+ }
+ }
+ return imm64;
+ }
+ imm |= (imm << 8) | (imm << 16) | (imm << 24);
+ break;
+ case 15:
+ imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
+ | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
+ break;
+ }
+ if (op) {
+ imm = ~imm;
+ }
+ return dup_const(MO_32, imm);
+}
+
/* Generate a label used for skipping this instruction */
void arm_gen_condlabel(DisasContext *s)
{