tcg conditional set, round 5
cover tcg conditional set, round 5
Changes since round 4:
* Document double-word support opcodes in a new section of the README, as requested by Aurelien.
* Shorten the branch-to-next in the EQ case of i386 brcond2, as pointed out by Laurent.
r~
Richard Henderson (6):
tcg: Document double-word support opcodes.
tcg: Generic support for conditional set
tcg: Add tcg_invert_cond.
tcg-i386: Implement small forward branches.
tcg-i386: Implement setcond.
tcg-x86_64: Implement setcond.
elf.h | 2 + tcg/README | 36 +++++++++ tcg/i386/tcg-target.c | 187 +++++++++++++++++++++++++++++++++++++---------- tcg/tcg-op.h | 47 ++++++++++++ tcg/tcg-opc.h | 3 + tcg/tcg.c | 21 ++++-- tcg/tcg.h | 5 + tcg/x86_64/tcg-target.c | 38 ++++++++- 8 files changed, 288 insertions(+), 51 deletions(-)
PATCH 2/6 tcg: Generic support for conditional set
Defines setcond_{i32,i64} and setcond2_i32 for 64-on-32-bit.
--- tcg/README | 13 +++++++++++++ tcg/tcg-op.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ tcg/tcg-opc.h | 3 +++ tcg/tcg.c | 21 +++++++++++++++------ 4 files changed, 78 insertions(+), 6 deletions(-)
tcg/README +13 -0
@@ -282,6 +282,14 @@ order bytes must be set to zero. Indicate that the value of t0 won't be used later. It is useful to force dead code elimination. +********* Conditional moves + +* setcond_i32/i64 cond, dest, t1, t2 + +dest = (t1 cond t2) + +Set DEST to 1 if (T1 cond T2) is true, otherwise set to 0. + ********* Type conversions * ext_i32_i64 t0, t1
@@ -346,6 +354,11 @@ is returned in two 32-bit outputs. Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding the full 64-bit product T0. The later is returned in two 32-bit outputs. +* setcond2_i32 cond, dest, t1_low, t1_high, t2_low, t2_high + +Similar to setcond, except that the 64-bit values T1 and T2 are +formed from two 32-bit arguments. The result is a 32-bit value. + ********* QEMU specific operations * tb_exit t0
tcg/tcg-op.h +47 -0
71 lines not on this page · raw message
tcg/tcg-opc.h +3 -0
@@ -42,6 +42,7 @@ DEF2(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) DEF2(mov_i32, 1, 1, 0, 0) DEF2(movi_i32, 1, 0, 1, 0) +DEF2 (setcond_i32,1 ,2 ,1 ,0 ) /* load/store */ DEF2(ld8u_i32, 1, 1, 1, 0)DEF2 (ld8s_i32,1 ,1 ,1 ,0 )
@@ -82,6 +83,7 @@ DEF2(add2_i32, 2, 4, 0, 0) DEF2(sub2_i32, 2, 4, 0, 0) DEF2(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS) DEF2(mulu2_i32, 2, 2, 0, 0) +DEF2(setcond2_i32, 1, 4, 1, 0)#endif #ifdef TCG_TARGET_HAS_ext8s_i32DEF2 (ext8s_i32,1 ,1 ,0 ,0 )
@@ -111,6 +113,7 @@ DEF2(neg_i32, 1, 1, 0, 0)#if TCG_TARGET_REG_BITS ==64 DEF2(mov_i64, 1, 1, 0, 0) DEF2(movi_i64, 1, 0, 1, 0) +DEF2 (setcond_i64,1 ,2 ,1 ,0 ) /* load/store */ DEF2(ld8u_i64, 1, 1, 1, 0)DEF2 (ld8s_i64,1 ,1 ,1 ,0 )
tcg/tcg.c +15 -6
@@ -670,6 +670,7 @@ void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, }#endif +static void tcg_reg_alloc_start (TCGContext *s) {int i;
@@ -888,21 +889,29 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile)fprintf (outfile,"%s" ,tcg_get_arg_str_idx (s, buf,sizeof (buf), args[k++])); } -if (c == INDEX_op_brcond_i32 +switch (c) { +case INDEX_op_brcond_i32: +#if TCG_TARGET_REG_BITS ==32 +case INDEX_op_brcond2_i32: +#elif TCG_TARGET_REG_BITS ==64 +case INDEX_op_brcond_i64: +#endif +case INDEX_op_setcond_i32:#if TCG_TARGET_REG_BITS ==32 - || c == INDEX_op_brcond2_i32 +case INDEX_op_setcond2_i32:#elif TCG_TARGET_REG_BITS ==64 - || c == INDEX_op_brcond_i64 +case INDEX_op_setcond_i64:#endif - ) {if (args[k] <ARRAY_SIZE (cond_name) && cond_name[args[k]])fprintf (outfile,",%s" , cond_name[args[k++]]);else fprintf (outfile,",$0x%" TCG_PRIlx, args[k++]); i =1 ; - } -else +break ; +default : i =0 ; +break ; + }for (; i < nb_cargs; i++) {if (k !=0 )fprintf (outfile,"," );
Signature · 1 line
1.6.5.2
PATCH 3/6 tcg: Add tcg_invert_cond.
In reply to Richard HendersonIt is very handy to have a reliable mapping of a condition to its inverse.
--- tcg/tcg.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
tcg/tcg.h +5 -0
@@ -205,6 +205,11 @@ typedef enum {TCG_COND_GTU , } TCGCond; +static inline TCGCond tcg_invert_cond (TCGCond c) +{ +return (TCGCond)(c ^1 ); +} +static inline TCGCond tcg_unsigned_cond (TCGCond c) {return (c >=TCG_COND_LT && c <=TCG_COND_GT ? c +4 : c);
Signature · 1 line
1.6.5.2
PATCH 4/6 tcg-i386: Implement small forward branches.
In reply to Richard HendersonThere are places, like brcond2, where we know that the destination of a forward branch will be within 127 bytes.
Add the R_386_PC8 relocation type to support this. Add a flag to tcg_out_jxx and tcg_out_brcond* to enable it. Set the flag in the brcond2 label_next branches; pass along the input flag otherwise.
--- elf.h | 2 + tcg/i386/tcg-target.c | 116 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 80 insertions(+), 38 deletions(-)
elf.h +2 -0
@@ -243,6 +243,8 @@ typedef struct {#define R_386_GOTOFF 9#define R_386_GOTPC 10#define R_386_NUM 11 +/* Not a dynamic reloc, so not included in R_386_NUM. Used in TCG. */ +#define R_386_PC8 23#define R_MIPS_NONE 0#define R_MIPS_16 1
tcg/i386/tcg-target.c +78 -38
197 lines not on this page · raw message
Signature · 1 line
1.6.5.2
PATCH 5/6 tcg-i386: Implement setcond.
In reply to Richard Henderson--- tcg/i386/tcg-target.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 70 insertions(+), 3 deletions(-)
tcg/i386/tcg-target.c +70 -3
@@ -360,9 +360,8 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small) } } -static void tcg_out_brcond (TCGContext *s,int cond, -TCGArg arg1,TCGArg arg2,int const_arg2, -int label_index,int small) +static void tcg_out_cmp (TCGContext *s,TCGArg arg1,TCGArg arg2, +int const_arg2) {if (const_arg2) {if (arg2 ==0 ) {
@@ -374,6 +373,13 @@ static void tcg_out_brcond(TCGContext *s, int cond, }else {tcg_out_modrm (s,0x01 | (ARITH_CMP <<3 ), arg2, arg1); } +} + +static void tcg_out_brcond (TCGContext *s,int cond, +TCGArg arg1,TCGArg arg2,int const_arg2, +int label_index,int small) +{ +tcg_out_cmp (s, arg1, arg2, const_arg2);tcg_out_jxx (s, tcg_cond_to_jcc[cond], label_index, small); }
@@ -459,6 +465,57 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,tcg_out_label (s, label_next, (tcg_target_long )s->code_ptr); } +static void tcg_out_setcond (TCGContext *s,int cond,TCGArg dest, +TCGArg arg1,TCGArg arg2,int const_arg2) +{ +tcg_out_cmp (s, arg1, arg2, const_arg2); +/* setcc */ +tcg_out_modrm (s,0x90 | tcg_cond_to_jcc[cond] |P_EXT ,0 , dest); +tgen_arithi (s,ARITH_AND , dest,0xff ,0 ); +} + +static void tcg_out_setcond2 (TCGContext *s,const TCGArg *args, +const int *const_args) +{ +TCGArg new_args[6 ]; +int label_true, label_over; + +memcpy (new_args, args+1 ,5 *sizeof (TCGArg)); + +if (args[0 ] == args[1 ] || args[0 ] == args[2 ] + || (!const_args[3 ] && args[0 ] == args[3 ]) + || (!const_args[4 ] && args[0 ] == args[4 ])) { +/* When the destination overlaps with one of the argument +registers, don't do anything tricky. */ + label_true =gen_new_label (); + label_over =gen_new_label (); + + new_args[5 ] = label_true; +tcg_out_brcond2 (s, new_args, const_args+1 ,1 ); + +tcg_out_movi (s,TCG_TYPE_I32 , args[0 ],0 ); +tcg_out_jxx (s,JCC_JMP , label_over,1 ); +tcg_out_label (s, label_true, (tcg_target_long )s->code_ptr); + +tcg_out_movi (s,TCG_TYPE_I32 , args[0 ],1 ); +tcg_out_label (s, label_over, (tcg_target_long )s->code_ptr); + }else { +/* When the destination does not overlap one of the arguments, +clear the destination first, jump if cond false, and emit an +increment in the true case. This results in smaller code. */ + +tcg_out_movi (s,TCG_TYPE_I32 , args[0 ],0 ); + + label_over =gen_new_label (); + new_args[4 ] =tcg_invert_cond (new_args[4 ]); + new_args[5 ] = label_over; +tcg_out_brcond2 (s, new_args, const_args+1 ,1 ); + +tgen_arithi (s,ARITH_ADD , args[0 ],1 ,0 ); +tcg_out_label (s, label_over, (tcg_target_long )s->code_ptr); + } +} +#if defined(CONFIG_SOFTMMU )#include "../../softmmu_defs.h"
@@ -1120,6 +1177,13 @@ static inline void tcg_out_op(TCGContext *s, int opc,tcg_out_modrm (s,0xb7 |P_EXT , args[0 ], args[1 ]);break ; +case INDEX_op_setcond_i32: +tcg_out_setcond (s, args[3 ], args[0 ], args[1 ], args[2 ], const_args[2 ]); +break ; +case INDEX_op_setcond2_i32: +tcg_out_setcond2 (s, args, const_args); +break ; +case INDEX_op_qemu_ld8u:tcg_out_qemu_ld (s, args,0 );break ;
@@ -1208,6 +1272,9 @@ static const TCGTargetOpDef x86_op_defs[] = { { INDEX_op_ext8u_i32, { "r", "q"} }, { INDEX_op_ext16u_i32, { "r", "r"} }, + { INDEX_op_setcond_i32, { "q", "r", "ri" } }, + { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } }, + #if TARGET_LONG_BITS == 32 { INDEX_op_qemu_ld8u, { "r", "L" } }, { INDEX_op_qemu_ld8s, { "r", "L" } },
Signature · 1 line
1.6.5.2
PATCH 6/6 tcg-x86_64: Implement setcond.
In reply to Richard Henderson--- tcg/x86_64/tcg-target.c | 38 +++++++++++++++++++++++++++++++++----- 1 files changed, 33 insertions(+), 5 deletions(-)
tcg/x86_64/tcg-target.c +33 -5
@@ -491,26 +491,42 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index) } } -static void tcg_out_brcond (TCGContext *s,int cond, -TCGArg arg1,TCGArg arg2,int const_arg2, -int label_index,int rexw) +static void tcg_out_cmp (TCGContext *s,TCGArg arg1,TCGArg arg2, +int const_arg2,int rexw) {if (const_arg2) {if (arg2 ==0 ) {/* test r, r */ tcg_out_modrm (s,0x85 | rexw, arg1, arg1); }else { -if (rexw) +if (rexw) {tgen_arithi64 (s,ARITH_CMP , arg1, arg2); -else + }else {tgen_arithi32 (s,ARITH_CMP , arg1, arg2); + } } }else {tcg_out_modrm (s,0x01 | (ARITH_CMP <<3 ) | rexw, arg2, arg1); } +} + +static void tcg_out_brcond (TCGContext *s,int cond, +TCGArg arg1,TCGArg arg2,int const_arg2, +int label_index,int rexw) +{ +tcg_out_cmp (s, arg1, arg2, const_arg2, rexw);tcg_out_jxx (s, tcg_cond_to_jcc[cond], label_index); } +static void tcg_out_setcond (TCGContext *s,int cond,TCGArg dest, +TCGArg arg1,TCGArg arg2,int const_arg2,int rexw) +{ +tcg_out_cmp (s, arg1, arg2, const_arg2, rexw); +/* setcc */ +tcg_out_modrm (s,0x90 | tcg_cond_to_jcc[cond] |P_EXT |P_REXB ,0 , dest); +tgen_arithi32 (s,ARITH_AND , dest,0xff ); +} +#if defined(CONFIG_SOFTMMU )#include "../../softmmu_defs.h"
@@ -1197,6 +1213,15 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,tcg_out_modrm (s,0x8b , args[0 ], args[1 ]);break ; +case INDEX_op_setcond_i32: +tcg_out_setcond (s, args[3 ], args[0 ], args[1 ], args[2 ], + const_args[2 ],0 ); +break ; +case INDEX_op_setcond_i64: +tcg_out_setcond (s, args[3 ], args[0 ], args[1 ], args[2 ], + const_args[2 ],P_REXW ); +break ; +case INDEX_op_qemu_ld8u:tcg_out_qemu_ld (s, args,0 );break ;
@@ -1376,6 +1401,9 @@ static const TCGTargetOpDef x86_64_op_defs[] = { { INDEX_op_ext16u_i64, { "r", "r"} }, { INDEX_op_ext32u_i64, { "r", "r"} }, + { INDEX_op_setcond_i32, { "r", "r", "ri" } }, + { INDEX_op_setcond_i64, { "r", "r", "re" } }, + { INDEX_op_qemu_ld8u, { "r", "L" } }, { INDEX_op_qemu_ld8s, { "r", "L" } }, { INDEX_op_qemu_ld16u, { "r", "L" } },
Signature · 1 line
1.6.5.2
PATCH 1/6 tcg: Document double-word support opcodes.
In reply to Richard HendersonThe internal opcodes brcond2, add2, sub2, mulu2 were undocumented. Place these in a new section that clearly indicates that they are not to be emitted by translators.
--- tcg/README | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-)
tcg/README +23 -0
@@ -323,6 +323,29 @@ st32_i64 t0, t1, offset write(t0, t1 + offset) Write 8, 16, 32 or 64 bits to host memory. +********* 64-bit target on 32-bit host support + +The following opcodes are internal to TCG. Thus they are to be implemented by +32-bit host code generators, but are not to be emitted by guest translators. +They are emitted as needed by inline functions within "tcg-op.h". + +* brcond2_i32 cond, t0_low, t0_high, t1_low, t1_high, label + +Similar to brcond, except that the 64-bit values T0 and T1 +are formed from two 32-bit arguments. + +* add2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high +* sub2_i32 t0_low, t0_high, t1_low, t1_high, t2_low, t2_high + +Similar to add/sub, except that the 64-bit inputs T1 and T2 are +formed from two 32-bit arguments, and the 64-bit output T0 +is returned in two 32-bit outputs. + +* mulu2_i32 t0_low, t0_high, t1, t2 + +Similar to mul, except two 32-bit (unsigned) inputs T1 and T2 yielding +the full 64-bit product T0. The later is returned in two 32-bit outputs. + ********* QEMU specific operations * tb_exit t0
Signature · 1 line
1.6.5.2
Re: [Qemu-devel] [PATCH 4/6] tcg-i386: Implement small forward branches.
In reply to Richard HendersonQuoted 31 lines · Richard Henderson
There are places, like brcond2, where we know that the destination of a forward branch will be within 127 bytes.
Add the
R_386_PC8relocation type to support this. Add a flag totcg_out_jxxand tcg_out_brcond* to enable it. Set the flag in the brcond2label_nextbranches; pass along the input flag otherwise.Signed-off-by Richard Henderson <[email protected]>--- elf.h | 2 + tcg/i386/tcg-target.c | 116 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 80 insertions(+), 38 deletions(-)elf.h +2
-0@@ -243,6 +243,8 @@ typedef struct {#define R_386_GOTOFF 9#define R_386_GOTPC 10#define R_386_NUM 11 +/* Not a dynamic reloc, so not included in R_386_NUM. Used in TCG. */ +#define R_386_PC8 23#define R_MIPS_NONE 0#define R_MIPS_16 1tcg/i386/tcg-target.c +0
-0
tcg/i386/tcg-target.c static void patch_reloc(uint8_t *code_ptr, int type, · line 67
Quoted 7 lines
tcg/i386/tcg-target.c +4
-0@@ -61,6 +61,12 @@ static void patch_reloc(uint8_t *code_ptr, int type,case R_386_PC32 : *(uint32_t *)code_ptr = value - (long )code_ptr;break ; +case R_386_PC8 : + value -= (long )code_ptr; +if (value != (int8_t )value) +tcg_abort ();
This does not conforms to CODING_STYLE, curly brackets are missing.
Signature · 2 lines
Aurelien Jarno GPG: 1024D/F1BCDB73 [email protected] http://www.aurel32.net
Quoted 8 lines · Richard Henderson
Changes since round 4:
* Document double-word support opcodes in a new section of the README, as requested by Aurelien.
* Shorten the branch-to-next in the EQ case of i386 brcond2, as pointed out by Laurent.
Quoted 8 lines
Richard Henderson (6):
tcg: Document double-word support opcodes.
tcg: Generic support for conditional set
tcg: Addtcg_invert_cond.
tcg-i386: Implement small forward branches.
tcg-i386: Implement setcond.
tcg-x86_64: Implement setcond.
Thanks, I have applied patches 1, 2, 3 and 6, and made a comment on patch 4.
Signature · 2 lines
Aurelien Jarno GPG: 1024D/F1BCDB73 [email protected] http://www.aurel32.net