@@ -312,10 +312,10 @@ static bool reloc_pc8(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
312
312
{
313
313
const tcg_insn_unit *src_rx = tcg_splitwx_to_rx (src_rw);
314
314
ptrdiff_t offset = tcg_ptr_byte_diff (target, src_rx) - 8 ;
315
- int rot = encode_imm (offset);
315
+ int imm12 = encode_imm (offset);
316
316
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 );
319
319
return true ;
320
320
}
321
321
return false ;
@@ -369,33 +369,52 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
369
369
(ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1)))
370
370
#endif
371
371
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
+ */
379
378
static int encode_imm (uint32_t imm)
380
379
{
381
- int shift ;
380
+ uint32_t rot, imm8 ;
382
381
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. */
398
406
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;
399
418
}
400
419
401
420
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)
782
801
783
802
static void tcg_out_movi32 (TCGContext *s, int cond, int rd, uint32_t arg)
784
803
{
785
- int rot , diff, opc, sh1, sh2;
804
+ int imm12 , diff, opc, sh1, sh2;
786
805
uint32_t tt0, tt1, tt2;
787
806
788
807
/* 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);
793
811
return ;
794
812
}
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);
799
816
return ;
800
817
}
801
818
802
819
/* Check for a pc-relative address. This will usually be the TB,
803
820
or within the TB, which is immediately before the code block. */
804
821
diff = tcg_pcrel_diff (s, (void *)arg) - 8 ;
805
822
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);
810
826
return ;
811
827
}
812
828
} 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);
817
832
return ;
818
833
}
819
834
}
@@ -845,6 +860,8 @@ static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
845
860
sh2 = ctz32 (tt1) & ~1 ;
846
861
tt2 = tt1 & ~(0xff << sh2);
847
862
if (tt2 == 0 ) {
863
+ int rot;
864
+
848
865
rot = ((32 - sh1) << 7 ) & 0xf00 ;
849
866
tcg_out_dat_imm (s, cond, opc, rd, 0 , ((tt0 >> sh1) & 0xff ) | rot);
850
867
rot = ((32 - sh2) << 7 ) & 0xf00 ;
@@ -857,37 +874,35 @@ static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
857
874
tcg_out_movi_pool (s, cond, rd, arg);
858
875
}
859
876
877
+ /*
878
+ * Emit either the reg,imm or reg,reg form of a data-processing insn.
879
+ * rhs must satisfy the "rI" constraint.
880
+ */
860
881
static inline void tcg_out_dat_rI (TCGContext *s, int cond, int opc, TCGArg dst,
861
882
TCGArg lhs, TCGArg rhs, int rhs_is_const)
862
883
{
863
- /* Emit either the reg,imm or reg,reg form of a data-processing insn.
864
- * rhs must satisfy the "rI" constraint.
865
- */
866
884
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));
870
886
} else {
871
887
tcg_out_dat_reg (s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL (0 ));
872
888
}
873
889
}
874
890
891
+ /*
892
+ * Emit either the reg,imm or reg,reg form of a data-processing insn.
893
+ * rhs must satisfy the "rIK" constraint.
894
+ */
875
895
static void tcg_out_dat_rIK (TCGContext *s, int cond, int opc, int opinv,
876
896
TCGReg dst, TCGReg lhs, TCGArg rhs,
877
897
bool rhs_is_const)
878
898
{
879
- /* Emit either the reg,imm or reg,reg form of a data-processing insn.
880
- * rhs must satisfy the "rIK" constraint.
881
- */
882
899
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);
888
903
opc = opinv;
889
904
}
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 );
891
906
} else {
892
907
tcg_out_dat_reg (s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL (0 ));
893
908
}
@@ -901,14 +916,12 @@ static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
901
916
* rhs must satisfy the "rIN" constraint.
902
917
*/
903
918
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);
909
922
opc = opneg;
910
923
}
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 );
912
925
} else {
913
926
tcg_out_dat_reg (s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL (0 ));
914
927
}
0 commit comments