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
This commit is contained in:
parent
303db86fc7
commit
dfd66bc0f3
@ -1781,69 +1781,6 @@ DO_FP_2SH(VCVT_UH, gen_helper_gvec_vcvt_uh)
|
||||
DO_FP_2SH(VCVT_HS, gen_helper_gvec_vcvt_hs)
|
||||
DO_FP_2SH(VCVT_HU, gen_helper_gvec_vcvt_hu)
|
||||
|
||||
static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
|
||||
{
|
||||
/*
|
||||
* Expand the encoded constant.
|
||||
* Note that cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
|
||||
* We choose to not special-case this and will behave as if a
|
||||
* valid constant encoding of 0 had been given.
|
||||
* cmode = 15 op = 1 must UNDEF; we assume decode has handled that.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a,
|
||||
GVecGen2iFn *fn)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -532,4 +532,20 @@ static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
|
||||
return opc | s->be_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* asimd_imm_const: Expand an encoded SIMD constant value
|
||||
*
|
||||
* Expand a SIMD constant value. This is essentially the pseudocode
|
||||
* AdvSIMDExpandImm, except that we also perform the boolean NOT needed for
|
||||
* VMVN and VBIC (when cmode < 14 && op == 1).
|
||||
*
|
||||
* The combination cmode == 15 op == 1 is a reserved encoding for AArch32;
|
||||
* callers must catch this.
|
||||
*
|
||||
* cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 was UNPREDICTABLE in v7A but
|
||||
* is either not unpredictable or merely CONSTRAINED UNPREDICTABLE in v8A;
|
||||
* we produce an immediate constant value of 0 in these cases.
|
||||
*/
|
||||
uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
|
||||
|
||||
#endif /* TARGET_ARM_TRANSLATE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user