Skip to content

Commit 9060671

Browse files
committed
tcg/arm: Simplify usage of encode_imm
We have already computed the rotated value of the imm8 portion of the complete imm12 encoding. No sense leaving the combination of rot + rotation to the caller. Create an encode_imm12_nofail helper that performs an assert. This removes the final use of the local "rotl" function, which duplicated our generic "rol32" function. Reviewed-by: Peter Maydell <[email protected]> Signed-off-by: Richard Henderson <[email protected]>
1 parent 31d160a commit 9060671

File tree

1 file changed

+77
-64
lines changed

1 file changed

+77
-64
lines changed

tcg/arm/tcg-target.c.inc

Lines changed: 77 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,10 @@ static bool reloc_pc8(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
312312
{
313313
const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
314314
ptrdiff_t offset = tcg_ptr_byte_diff(target, src_rx) - 8;
315-
int rot = encode_imm(offset);
315+
int imm12 = encode_imm(offset);
316316

317-
if (rot >= 0) {
318-
*src_rw = deposit32(*src_rw, 0, 12, rol32(offset, rot) | (rot << 7));
317+
if (imm12 >= 0) {
318+
*src_rw = deposit32(*src_rw, 0, 12, imm12);
319319
return true;
320320
}
321321
return false;
@@ -369,33 +369,52 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
369369
(ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1)))
370370
#endif
371371

372-
static inline uint32_t rotl(uint32_t val, int n)
373-
{
374-
return (val << n) | (val >> (32 - n));
375-
}
376-
377-
/* ARM immediates for ALU instructions are made of an unsigned 8-bit
378-
right-rotated by an even amount between 0 and 30. */
372+
/*
373+
* ARM immediates for ALU instructions are made of an unsigned 8-bit
374+
* right-rotated by an even amount between 0 and 30.
375+
*
376+
* Return < 0 if @imm cannot be encoded, else the entire imm12 field.
377+
*/
379378
static int encode_imm(uint32_t imm)
380379
{
381-
int shift;
380+
uint32_t rot, imm8;
382381

383-
/* simple case, only lower bits */
384-
if ((imm & ~0xff) == 0)
385-
return 0;
386-
/* then try a simple even shift */
387-
shift = ctz32(imm) & ~1;
388-
if (((imm >> shift) & ~0xff) == 0)
389-
return 32 - shift;
390-
/* now try harder with rotations */
391-
if ((rotl(imm, 2) & ~0xff) == 0)
392-
return 2;
393-
if ((rotl(imm, 4) & ~0xff) == 0)
394-
return 4;
395-
if ((rotl(imm, 6) & ~0xff) == 0)
396-
return 6;
397-
/* imm can't be encoded */
382+
/* Simple case, no rotation required. */
383+
if ((imm & ~0xff) == 0) {
384+
return imm;
385+
}
386+
387+
/* Next, try a simple even shift. */
388+
rot = ctz32(imm) & ~1;
389+
imm8 = imm >> rot;
390+
rot = 32 - rot;
391+
if ((imm8 & ~0xff) == 0) {
392+
goto found;
393+
}
394+
395+
/*
396+
* Finally, try harder with rotations.
397+
* The ctz test above will have taken care of rotates >= 8.
398+
*/
399+
for (rot = 2; rot < 8; rot += 2) {
400+
imm8 = rol32(imm, rot);
401+
if ((imm8 & ~0xff) == 0) {
402+
goto found;
403+
}
404+
}
405+
/* Fail: imm cannot be encoded. */
398406
return -1;
407+
408+
found:
409+
/* Note that rot is even, and we discard bit 0 by shifting by 7. */
410+
return rot << 7 | imm8;
411+
}
412+
413+
static int encode_imm_nofail(uint32_t imm)
414+
{
415+
int ret = encode_imm(imm);
416+
tcg_debug_assert(ret >= 0);
417+
return ret;
399418
}
400419

401420
static inline int check_fit_imm(uint32_t imm)
@@ -782,38 +801,34 @@ static void tcg_out_movi_pool(TCGContext *s, int cond, int rd, uint32_t arg)
782801

783802
static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
784803
{
785-
int rot, diff, opc, sh1, sh2;
804+
int imm12, diff, opc, sh1, sh2;
786805
uint32_t tt0, tt1, tt2;
787806

788807
/* Check a single MOV/MVN before anything else. */
789-
rot = encode_imm(arg);
790-
if (rot >= 0) {
791-
tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
792-
rotl(arg, rot) | (rot << 7));
808+
imm12 = encode_imm(arg);
809+
if (imm12 >= 0) {
810+
tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, imm12);
793811
return;
794812
}
795-
rot = encode_imm(~arg);
796-
if (rot >= 0) {
797-
tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
798-
rotl(~arg, rot) | (rot << 7));
813+
imm12 = encode_imm(~arg);
814+
if (imm12 >= 0) {
815+
tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, imm12);
799816
return;
800817
}
801818

802819
/* Check for a pc-relative address. This will usually be the TB,
803820
or within the TB, which is immediately before the code block. */
804821
diff = tcg_pcrel_diff(s, (void *)arg) - 8;
805822
if (diff >= 0) {
806-
rot = encode_imm(diff);
807-
if (rot >= 0) {
808-
tcg_out_dat_imm(s, cond, ARITH_ADD, rd, TCG_REG_PC,
809-
rotl(diff, rot) | (rot << 7));
823+
imm12 = encode_imm(diff);
824+
if (imm12 >= 0) {
825+
tcg_out_dat_imm(s, cond, ARITH_ADD, rd, TCG_REG_PC, imm12);
810826
return;
811827
}
812828
} else {
813-
rot = encode_imm(-diff);
814-
if (rot >= 0) {
815-
tcg_out_dat_imm(s, cond, ARITH_SUB, rd, TCG_REG_PC,
816-
rotl(-diff, rot) | (rot << 7));
829+
imm12 = encode_imm(-diff);
830+
if (imm12 >= 0) {
831+
tcg_out_dat_imm(s, cond, ARITH_SUB, rd, TCG_REG_PC, imm12);
817832
return;
818833
}
819834
}
@@ -845,6 +860,8 @@ static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
845860
sh2 = ctz32(tt1) & ~1;
846861
tt2 = tt1 & ~(0xff << sh2);
847862
if (tt2 == 0) {
863+
int rot;
864+
848865
rot = ((32 - sh1) << 7) & 0xf00;
849866
tcg_out_dat_imm(s, cond, opc, rd, 0, ((tt0 >> sh1) & 0xff) | rot);
850867
rot = ((32 - sh2) << 7) & 0xf00;
@@ -857,37 +874,35 @@ static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
857874
tcg_out_movi_pool(s, cond, rd, arg);
858875
}
859876

877+
/*
878+
* Emit either the reg,imm or reg,reg form of a data-processing insn.
879+
* rhs must satisfy the "rI" constraint.
880+
*/
860881
static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
861882
TCGArg lhs, TCGArg rhs, int rhs_is_const)
862883
{
863-
/* Emit either the reg,imm or reg,reg form of a data-processing insn.
864-
* rhs must satisfy the "rI" constraint.
865-
*/
866884
if (rhs_is_const) {
867-
int rot = encode_imm(rhs);
868-
tcg_debug_assert(rot >= 0);
869-
tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
885+
tcg_out_dat_imm(s, cond, opc, dst, lhs, encode_imm_nofail(rhs));
870886
} else {
871887
tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
872888
}
873889
}
874890

891+
/*
892+
* Emit either the reg,imm or reg,reg form of a data-processing insn.
893+
* rhs must satisfy the "rIK" constraint.
894+
*/
875895
static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
876896
TCGReg dst, TCGReg lhs, TCGArg rhs,
877897
bool rhs_is_const)
878898
{
879-
/* Emit either the reg,imm or reg,reg form of a data-processing insn.
880-
* rhs must satisfy the "rIK" constraint.
881-
*/
882899
if (rhs_is_const) {
883-
int rot = encode_imm(rhs);
884-
if (rot < 0) {
885-
rhs = ~rhs;
886-
rot = encode_imm(rhs);
887-
tcg_debug_assert(rot >= 0);
900+
int imm12 = encode_imm(rhs);
901+
if (imm12 < 0) {
902+
imm12 = encode_imm_nofail(~rhs);
888903
opc = opinv;
889904
}
890-
tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
905+
tcg_out_dat_imm(s, cond, opc, dst, lhs, imm12);
891906
} else {
892907
tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
893908
}
@@ -901,14 +916,12 @@ static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
901916
* rhs must satisfy the "rIN" constraint.
902917
*/
903918
if (rhs_is_const) {
904-
int rot = encode_imm(rhs);
905-
if (rot < 0) {
906-
rhs = -rhs;
907-
rot = encode_imm(rhs);
908-
tcg_debug_assert(rot >= 0);
919+
int imm12 = encode_imm(rhs);
920+
if (imm12 < 0) {
921+
imm12 = encode_imm_nofail(-rhs);
909922
opc = opneg;
910923
}
911-
tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
924+
tcg_out_dat_imm(s, cond, opc, dst, lhs, imm12);
912925
} else {
913926
tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
914927
}

0 commit comments

Comments
 (0)