Message ID | 1267738597-26248-1-git-send-email-aurelien@aurel32.net |
---|---|
State | New |
Headers | show |
On 3/4/10, Aurelien Jarno <aurelien@aurel32.net> wrote: > Some targets like ARM would benefit to use 32-bit helpers for > div/rem/divu/remu. > > Create a #define for div2 so that targets can select between > div, div2 and helper implementation. Use the helper version if none > of the #define are present. > > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> > --- > tcg-runtime.c | 24 +++++++++++++++++++ > tcg/arm/tcg-target.h | 1 + > tcg/hppa/tcg-target.h | 1 + > tcg/i386/tcg-target.h | 1 + > tcg/tcg-op.h | 57 +++++++++++++++++++++++++++++++++++++++++++++- > tcg/tcg-runtime.h | 5 ++++ > tcg/x86_64/tcg-target.h | 2 + > 7 files changed, 89 insertions(+), 2 deletions(-) > > diff --git a/tcg-runtime.c b/tcg-runtime.c > index 219cade..abfc364 100644 > --- a/tcg-runtime.c > +++ b/tcg-runtime.c > @@ -25,6 +25,30 @@ > > #include "tcg/tcg-runtime.h" > > +/* 32-bit helpers */ > + > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) > +{ > + return arg1 / arg2; > +} > + > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) > +{ > + return arg1 % arg2; > +} > + > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) > +{ > + return arg1 / arg2; > +} > + > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) > +{ > + return arg1 % arg2; > +} > + > +/* 64-bit helpers */ > + > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) > { > return arg1 << arg2; > diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h > index 4cad967..4b2b0be 100644 > --- a/tcg/arm/tcg-target.h > +++ b/tcg/arm/tcg-target.h > @@ -56,6 +56,7 @@ enum { > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > /* optional instructions */ > +#define TCG_TARGET_HAS_div2_i32 Please also add commented out #defines for targets that do not implement div2 yet. > #define TCG_TARGET_HAS_ext8s_i32 > #define TCG_TARGET_HAS_ext16s_i32 > // #define TCG_TARGET_HAS_ext8u_i32 > diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h > index 7ab6f0c..fa39bfc 100644 > --- a/tcg/hppa/tcg-target.h > +++ b/tcg/hppa/tcg-target.h > @@ -75,6 +75,7 @@ enum { > #define TCG_TARGET_STACK_GROWSUP > > /* optional instructions */ > +#define TCG_TARGET_HAS_div2_i32 > //#define TCG_TARGET_HAS_ext8s_i32 > //#define TCG_TARGET_HAS_ext16s_i32 > //#define TCG_TARGET_HAS_bswap16_i32 > diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h > index f97034c..e994fd5 100644 > --- a/tcg/i386/tcg-target.h > +++ b/tcg/i386/tcg-target.h > @@ -45,6 +45,7 @@ enum { > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > /* optional instructions */ > +#define TCG_TARGET_HAS_div2_i32 > #define TCG_TARGET_HAS_rot_i32 > #define TCG_TARGET_HAS_ext8s_i32 > #define TCG_TARGET_HAS_ext16s_i32 > diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h > index 6ae1760..c71e1a8 100644 > --- a/tcg/tcg-op.h > +++ b/tcg/tcg-op.h > @@ -365,6 +365,19 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, > } > > /* FIXME: Should this be pure? */ > +static inline void tcg_gen_helper32(void *func, TCGv_i32 ret, > + TCGv_i32 a, TCGv_i32 b) > +{ > + TCGv_ptr fn; > + TCGArg args[2]; > + fn = tcg_const_ptr((tcg_target_long)func); > + args[0] = GET_TCGV_I32(a); > + args[1] = GET_TCGV_I32(b); > + tcg_gen_callN(&tcg_ctx, fn, 0, 0, GET_TCGV_I32(ret), 2, args); > + tcg_temp_free_ptr(fn); > +} > + > +/* FIXME: Should this be pure? */ > static inline void tcg_gen_helper64(void *func, TCGv_i64 ret, > TCGv_i64 a, TCGv_i64 b) > { > @@ -635,7 +648,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > { > tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); > } > -#else > +#elif defined(TCG_TARGET_HAS_div2_i32) > static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > { > TCGv_i32 t0; > @@ -671,6 +684,26 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); > tcg_temp_free_i32(t0); > } > +#else > +static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > +{ > + tcg_gen_helper32(tcg_helper_div_i32, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > +{ > + tcg_gen_helper32(tcg_helper_rem_i32, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > +{ > + tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > +{ > + tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2); > +} > #endif > > #if TCG_TARGET_REG_BITS == 32 > @@ -1135,7 +1168,7 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > { > tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); > } > -#else > +#elif defined(TCG_TARGET_HAS_div2_i64) > static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > { > TCGv_i64 t0; > @@ -1171,6 +1204,26 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); > tcg_temp_free_i64(t0); > } > +#else > +static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > +{ > + tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > +{ > + tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > +{ > + tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2); > +} > + > +static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > +{ > + tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2); > +} > #endif > > #endif > diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h > index e750cc1..5615b13 100644 > --- a/tcg/tcg-runtime.h > +++ b/tcg/tcg-runtime.h > @@ -2,6 +2,11 @@ > #define TCG_RUNTIME_H > > /* tcg-runtime.c */ > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); > + > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); > int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); > int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); > diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h > index 765f0b4..d1e8b9e 100644 > --- a/tcg/x86_64/tcg-target.h > +++ b/tcg/x86_64/tcg-target.h > @@ -56,6 +56,8 @@ enum { > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > /* optional instructions */ > +#define TCG_TARGET_HAS_div2_i32 > +#define TCG_TARGET_HAS_div2_i64 > #define TCG_TARGET_HAS_bswap16_i32 > #define TCG_TARGET_HAS_bswap16_i64 > #define TCG_TARGET_HAS_bswap32_i32 > > -- > 1.7.0 > > > >
On Sat, Mar 06, 2010 at 09:15:38AM +0200, Blue Swirl wrote: > On 3/4/10, Aurelien Jarno <aurelien@aurel32.net> wrote: > > Some targets like ARM would benefit to use 32-bit helpers for > > div/rem/divu/remu. > > > > Create a #define for div2 so that targets can select between > > div, div2 and helper implementation. Use the helper version if none > > of the #define are present. > > > > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> > > --- > > tcg-runtime.c | 24 +++++++++++++++++++ > > tcg/arm/tcg-target.h | 1 + > > tcg/hppa/tcg-target.h | 1 + > > tcg/i386/tcg-target.h | 1 + > > tcg/tcg-op.h | 57 +++++++++++++++++++++++++++++++++++++++++++++- > > tcg/tcg-runtime.h | 5 ++++ > > tcg/x86_64/tcg-target.h | 2 + > > 7 files changed, 89 insertions(+), 2 deletions(-) > > > > diff --git a/tcg-runtime.c b/tcg-runtime.c > > index 219cade..abfc364 100644 > > --- a/tcg-runtime.c > > +++ b/tcg-runtime.c > > @@ -25,6 +25,30 @@ > > > > #include "tcg/tcg-runtime.h" > > > > +/* 32-bit helpers */ > > + > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) > > +{ > > + return arg1 / arg2; > > +} > > + > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) > > +{ > > + return arg1 % arg2; > > +} > > + > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) > > +{ > > + return arg1 / arg2; > > +} > > + > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) > > +{ > > + return arg1 % arg2; > > +} > > + > > +/* 64-bit helpers */ > > + > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) > > { > > return arg1 << arg2; > > diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h > > index 4cad967..4b2b0be 100644 > > --- a/tcg/arm/tcg-target.h > > +++ b/tcg/arm/tcg-target.h > > @@ -56,6 +56,7 @@ enum { > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > /* optional instructions */ > > +#define TCG_TARGET_HAS_div2_i32 > > Please also add commented out #defines for targets that do not > implement div2 yet. I don't really see the point. The targets should implement either div/rem or div2, depending on their instruction set. Implementing div2 on a targets which have separate instructions to compute div and rem will impact the performances negatively. > > #define TCG_TARGET_HAS_ext8s_i32 > > #define TCG_TARGET_HAS_ext16s_i32 > > // #define TCG_TARGET_HAS_ext8u_i32 > > diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h > > index 7ab6f0c..fa39bfc 100644 > > --- a/tcg/hppa/tcg-target.h > > +++ b/tcg/hppa/tcg-target.h > > @@ -75,6 +75,7 @@ enum { > > #define TCG_TARGET_STACK_GROWSUP > > > > /* optional instructions */ > > +#define TCG_TARGET_HAS_div2_i32 > > //#define TCG_TARGET_HAS_ext8s_i32 > > //#define TCG_TARGET_HAS_ext16s_i32 > > //#define TCG_TARGET_HAS_bswap16_i32 > > diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h > > index f97034c..e994fd5 100644 > > --- a/tcg/i386/tcg-target.h > > +++ b/tcg/i386/tcg-target.h > > @@ -45,6 +45,7 @@ enum { > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > /* optional instructions */ > > +#define TCG_TARGET_HAS_div2_i32 > > #define TCG_TARGET_HAS_rot_i32 > > #define TCG_TARGET_HAS_ext8s_i32 > > #define TCG_TARGET_HAS_ext16s_i32 > > diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h > > index 6ae1760..c71e1a8 100644 > > --- a/tcg/tcg-op.h > > +++ b/tcg/tcg-op.h > > @@ -365,6 +365,19 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, > > } > > > > /* FIXME: Should this be pure? */ > > +static inline void tcg_gen_helper32(void *func, TCGv_i32 ret, > > + TCGv_i32 a, TCGv_i32 b) > > +{ > > + TCGv_ptr fn; > > + TCGArg args[2]; > > + fn = tcg_const_ptr((tcg_target_long)func); > > + args[0] = GET_TCGV_I32(a); > > + args[1] = GET_TCGV_I32(b); > > + tcg_gen_callN(&tcg_ctx, fn, 0, 0, GET_TCGV_I32(ret), 2, args); > > + tcg_temp_free_ptr(fn); > > +} > > + > > +/* FIXME: Should this be pure? */ > > static inline void tcg_gen_helper64(void *func, TCGv_i64 ret, > > TCGv_i64 a, TCGv_i64 b) > > { > > @@ -635,7 +648,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > { > > tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); > > } > > -#else > > +#elif defined(TCG_TARGET_HAS_div2_i32) > > static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > { > > TCGv_i32 t0; > > @@ -671,6 +684,26 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); > > tcg_temp_free_i32(t0); > > } > > +#else > > +static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > +{ > > + tcg_gen_helper32(tcg_helper_div_i32, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > +{ > > + tcg_gen_helper32(tcg_helper_rem_i32, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > +{ > > + tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > +{ > > + tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2); > > +} > > #endif > > > > #if TCG_TARGET_REG_BITS == 32 > > @@ -1135,7 +1168,7 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > { > > tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); > > } > > -#else > > +#elif defined(TCG_TARGET_HAS_div2_i64) > > static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > { > > TCGv_i64 t0; > > @@ -1171,6 +1204,26 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); > > tcg_temp_free_i64(t0); > > } > > +#else > > +static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > +{ > > + tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > +{ > > + tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > +{ > > + tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2); > > +} > > + > > +static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > +{ > > + tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2); > > +} > > #endif > > > > #endif > > diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h > > index e750cc1..5615b13 100644 > > --- a/tcg/tcg-runtime.h > > +++ b/tcg/tcg-runtime.h > > @@ -2,6 +2,11 @@ > > #define TCG_RUNTIME_H > > > > /* tcg-runtime.c */ > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); > > + > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); > > int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); > > int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); > > diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h > > index 765f0b4..d1e8b9e 100644 > > --- a/tcg/x86_64/tcg-target.h > > +++ b/tcg/x86_64/tcg-target.h > > @@ -56,6 +56,8 @@ enum { > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > /* optional instructions */ > > +#define TCG_TARGET_HAS_div2_i32 > > +#define TCG_TARGET_HAS_div2_i64 > > #define TCG_TARGET_HAS_bswap16_i32 > > #define TCG_TARGET_HAS_bswap16_i64 > > #define TCG_TARGET_HAS_bswap32_i32 > > > > -- > > 1.7.0 > > > > > > > > > > >
On Sat, 6 Mar 2010, Aurelien Jarno wrote: > On Sat, Mar 06, 2010 at 09:15:38AM +0200, Blue Swirl wrote: > > On 3/4/10, Aurelien Jarno <aurelien@aurel32.net> wrote: > > > Some targets like ARM would benefit to use 32-bit helpers for > > > div/rem/divu/remu. > > > > > > Create a #define for div2 so that targets can select between > > > div, div2 and helper implementation. Use the helper version if none > > > of the #define are present. > > > > > > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> > > > --- > > > tcg-runtime.c | 24 +++++++++++++++++++ > > > tcg/arm/tcg-target.h | 1 + > > > tcg/hppa/tcg-target.h | 1 + > > > tcg/i386/tcg-target.h | 1 + > > > tcg/tcg-op.h | 57 +++++++++++++++++++++++++++++++++++++++++++++- > > > tcg/tcg-runtime.h | 5 ++++ > > > tcg/x86_64/tcg-target.h | 2 + > > > 7 files changed, 89 insertions(+), 2 deletions(-) > > > > > > diff --git a/tcg-runtime.c b/tcg-runtime.c > > > index 219cade..abfc364 100644 > > > --- a/tcg-runtime.c > > > +++ b/tcg-runtime.c > > > @@ -25,6 +25,30 @@ > > > > > > #include "tcg/tcg-runtime.h" > > > > > > +/* 32-bit helpers */ > > > + > > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) > > > +{ > > > + return arg1 / arg2; > > > +} > > > + > > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) > > > +{ > > > + return arg1 % arg2; > > > +} > > > + > > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) > > > +{ > > > + return arg1 / arg2; > > > +} > > > + > > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) > > > +{ > > > + return arg1 % arg2; > > > +} > > > + > > > +/* 64-bit helpers */ > > > + > > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) > > > { > > > return arg1 << arg2; > > > diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h > > > index 4cad967..4b2b0be 100644 > > > --- a/tcg/arm/tcg-target.h > > > +++ b/tcg/arm/tcg-target.h > > > @@ -56,6 +56,7 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > > Please also add commented out #defines for targets that do not > > implement div2 yet. > > I don't really see the point. The targets should implement either > div/rem or div2, depending on their instruction set. Implementing div2 > on a targets which have separate instructions to compute div and rem > will impact the performances negatively. Seconded. > > > > #define TCG_TARGET_HAS_ext8s_i32 > > > #define TCG_TARGET_HAS_ext16s_i32 > > > // #define TCG_TARGET_HAS_ext8u_i32 > > > diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h > > > index 7ab6f0c..fa39bfc 100644 > > > --- a/tcg/hppa/tcg-target.h > > > +++ b/tcg/hppa/tcg-target.h > > > @@ -75,6 +75,7 @@ enum { > > > #define TCG_TARGET_STACK_GROWSUP > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > //#define TCG_TARGET_HAS_ext8s_i32 > > > //#define TCG_TARGET_HAS_ext16s_i32 > > > //#define TCG_TARGET_HAS_bswap16_i32 > > > diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h > > > index f97034c..e994fd5 100644 > > > --- a/tcg/i386/tcg-target.h > > > +++ b/tcg/i386/tcg-target.h > > > @@ -45,6 +45,7 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > #define TCG_TARGET_HAS_rot_i32 > > > #define TCG_TARGET_HAS_ext8s_i32 > > > #define TCG_TARGET_HAS_ext16s_i32 > > > diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h > > > index 6ae1760..c71e1a8 100644 > > > --- a/tcg/tcg-op.h > > > +++ b/tcg/tcg-op.h > > > @@ -365,6 +365,19 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, > > > } > > > > > > /* FIXME: Should this be pure? */ > > > +static inline void tcg_gen_helper32(void *func, TCGv_i32 ret, > > > + TCGv_i32 a, TCGv_i32 b) > > > +{ > > > + TCGv_ptr fn; > > > + TCGArg args[2]; > > > + fn = tcg_const_ptr((tcg_target_long)func); > > > + args[0] = GET_TCGV_I32(a); > > > + args[1] = GET_TCGV_I32(b); > > > + tcg_gen_callN(&tcg_ctx, fn, 0, 0, GET_TCGV_I32(ret), 2, args); > > > + tcg_temp_free_ptr(fn); > > > +} > > > + > > > +/* FIXME: Should this be pure? */ > > > static inline void tcg_gen_helper64(void *func, TCGv_i64 ret, > > > TCGv_i64 a, TCGv_i64 b) > > > { > > > @@ -635,7 +648,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > { > > > tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); > > > } > > > -#else > > > +#elif defined(TCG_TARGET_HAS_div2_i32) > > > static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > { > > > TCGv_i32 t0; > > > @@ -671,6 +684,26 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); > > > tcg_temp_free_i32(t0); > > > } > > > +#else > > > +static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_div_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_rem_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2); > > > +} > > > #endif > > > > > > #if TCG_TARGET_REG_BITS == 32 > > > @@ -1135,7 +1168,7 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > { > > > tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); > > > } > > > -#else > > > +#elif defined(TCG_TARGET_HAS_div2_i64) > > > static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > { > > > TCGv_i64 t0; > > > @@ -1171,6 +1204,26 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); > > > tcg_temp_free_i64(t0); > > > } > > > +#else > > > +static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2); > > > +} > > > #endif > > > > > > #endif > > > diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h > > > index e750cc1..5615b13 100644 > > > --- a/tcg/tcg-runtime.h > > > +++ b/tcg/tcg-runtime.h > > > @@ -2,6 +2,11 @@ > > > #define TCG_RUNTIME_H > > > > > > /* tcg-runtime.c */ > > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); > > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); > > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); > > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); > > > + > > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); > > > int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); > > > int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); > > > diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h > > > index 765f0b4..d1e8b9e 100644 > > > --- a/tcg/x86_64/tcg-target.h > > > +++ b/tcg/x86_64/tcg-target.h > > > @@ -56,6 +56,8 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > +#define TCG_TARGET_HAS_div2_i64 > > > #define TCG_TARGET_HAS_bswap16_i32 > > > #define TCG_TARGET_HAS_bswap16_i64 > > > #define TCG_TARGET_HAS_bswap32_i32 > > > > > > -- > > > 1.7.0 > > > > > > > > > > > > > > > > > > > >
On 3/6/10, Aurelien Jarno <aurelien@aurel32.net> wrote: > On Sat, Mar 06, 2010 at 09:15:38AM +0200, Blue Swirl wrote: > > On 3/4/10, Aurelien Jarno <aurelien@aurel32.net> wrote: > > > Some targets like ARM would benefit to use 32-bit helpers for > > > div/rem/divu/remu. > > > > > > Create a #define for div2 so that targets can select between > > > div, div2 and helper implementation. Use the helper version if none > > > of the #define are present. > > > > > > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> > > > --- > > > tcg-runtime.c | 24 +++++++++++++++++++ > > > tcg/arm/tcg-target.h | 1 + > > > tcg/hppa/tcg-target.h | 1 + > > > tcg/i386/tcg-target.h | 1 + > > > tcg/tcg-op.h | 57 +++++++++++++++++++++++++++++++++++++++++++++- > > > tcg/tcg-runtime.h | 5 ++++ > > > tcg/x86_64/tcg-target.h | 2 + > > > 7 files changed, 89 insertions(+), 2 deletions(-) > > > > > > diff --git a/tcg-runtime.c b/tcg-runtime.c > > > index 219cade..abfc364 100644 > > > --- a/tcg-runtime.c > > > +++ b/tcg-runtime.c > > > @@ -25,6 +25,30 @@ > > > > > > #include "tcg/tcg-runtime.h" > > > > > > +/* 32-bit helpers */ > > > + > > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) > > > +{ > > > + return arg1 / arg2; > > > +} > > > + > > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) > > > +{ > > > + return arg1 % arg2; > > > +} > > > + > > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) > > > +{ > > > + return arg1 / arg2; > > > +} > > > + > > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) > > > +{ > > > + return arg1 % arg2; > > > +} > > > + > > > +/* 64-bit helpers */ > > > + > > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) > > > { > > > return arg1 << arg2; > > > diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h > > > index 4cad967..4b2b0be 100644 > > > --- a/tcg/arm/tcg-target.h > > > +++ b/tcg/arm/tcg-target.h > > > @@ -56,6 +56,7 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > > Please also add commented out #defines for targets that do not > > implement div2 yet. > > > I don't really see the point. The targets should implement either > div/rem or div2, depending on their instruction set. Implementing div2 > on a targets which have separate instructions to compute div and rem > will impact the performances negatively. On second thought, fully agree. > > > #define TCG_TARGET_HAS_ext8s_i32 > > > #define TCG_TARGET_HAS_ext16s_i32 > > > // #define TCG_TARGET_HAS_ext8u_i32 > > > diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h > > > index 7ab6f0c..fa39bfc 100644 > > > --- a/tcg/hppa/tcg-target.h > > > +++ b/tcg/hppa/tcg-target.h > > > @@ -75,6 +75,7 @@ enum { > > > #define TCG_TARGET_STACK_GROWSUP > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > //#define TCG_TARGET_HAS_ext8s_i32 > > > //#define TCG_TARGET_HAS_ext16s_i32 > > > //#define TCG_TARGET_HAS_bswap16_i32 > > > diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h > > > index f97034c..e994fd5 100644 > > > --- a/tcg/i386/tcg-target.h > > > +++ b/tcg/i386/tcg-target.h > > > @@ -45,6 +45,7 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > #define TCG_TARGET_HAS_rot_i32 > > > #define TCG_TARGET_HAS_ext8s_i32 > > > #define TCG_TARGET_HAS_ext16s_i32 > > > diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h > > > index 6ae1760..c71e1a8 100644 > > > --- a/tcg/tcg-op.h > > > +++ b/tcg/tcg-op.h > > > @@ -365,6 +365,19 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, > > > } > > > > > > /* FIXME: Should this be pure? */ > > > +static inline void tcg_gen_helper32(void *func, TCGv_i32 ret, > > > + TCGv_i32 a, TCGv_i32 b) > > > +{ > > > + TCGv_ptr fn; > > > + TCGArg args[2]; > > > + fn = tcg_const_ptr((tcg_target_long)func); > > > + args[0] = GET_TCGV_I32(a); > > > + args[1] = GET_TCGV_I32(b); > > > + tcg_gen_callN(&tcg_ctx, fn, 0, 0, GET_TCGV_I32(ret), 2, args); > > > + tcg_temp_free_ptr(fn); > > > +} > > > + > > > +/* FIXME: Should this be pure? */ > > > static inline void tcg_gen_helper64(void *func, TCGv_i64 ret, > > > TCGv_i64 a, TCGv_i64 b) > > > { > > > @@ -635,7 +648,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > { > > > tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); > > > } > > > -#else > > > +#elif defined(TCG_TARGET_HAS_div2_i32) > > > static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > { > > > TCGv_i32 t0; > > > @@ -671,6 +684,26 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); > > > tcg_temp_free_i32(t0); > > > } > > > +#else > > > +static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_div_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_rem_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) > > > +{ > > > + tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2); > > > +} > > > #endif > > > > > > #if TCG_TARGET_REG_BITS == 32 > > > @@ -1135,7 +1168,7 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > { > > > tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); > > > } > > > -#else > > > +#elif defined(TCG_TARGET_HAS_div2_i64) > > > static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > { > > > TCGv_i64 t0; > > > @@ -1171,6 +1204,26 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); > > > tcg_temp_free_i64(t0); > > > } > > > +#else > > > +static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2); > > > +} > > > + > > > +static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) > > > +{ > > > + tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2); > > > +} > > > #endif > > > > > > #endif > > > diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h > > > index e750cc1..5615b13 100644 > > > --- a/tcg/tcg-runtime.h > > > +++ b/tcg/tcg-runtime.h > > > @@ -2,6 +2,11 @@ > > > #define TCG_RUNTIME_H > > > > > > /* tcg-runtime.c */ > > > +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); > > > +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); > > > +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); > > > +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); > > > + > > > int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); > > > int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); > > > int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); > > > diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h > > > index 765f0b4..d1e8b9e 100644 > > > --- a/tcg/x86_64/tcg-target.h > > > +++ b/tcg/x86_64/tcg-target.h > > > @@ -56,6 +56,8 @@ enum { > > > #define TCG_TARGET_CALL_STACK_OFFSET 0 > > > > > > /* optional instructions */ > > > +#define TCG_TARGET_HAS_div2_i32 > > > +#define TCG_TARGET_HAS_div2_i64 > > > #define TCG_TARGET_HAS_bswap16_i32 > > > #define TCG_TARGET_HAS_bswap16_i64 > > > #define TCG_TARGET_HAS_bswap32_i32 > > > > > > -- > > > 1.7.0 > > > > > > > > > > > > > > > > > > > > > -- > Aurelien Jarno GPG: 1024D/F1BCDB73 > aurelien@aurel32.net http://www.aurel32.net >
diff --git a/tcg-runtime.c b/tcg-runtime.c index 219cade..abfc364 100644 --- a/tcg-runtime.c +++ b/tcg-runtime.c @@ -25,6 +25,30 @@ #include "tcg/tcg-runtime.h" +/* 32-bit helpers */ + +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2) +{ + return arg1 / arg2; +} + +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2) +{ + return arg1 % arg2; +} + +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2) +{ + return arg1 / arg2; +} + +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2) +{ + return arg1 % arg2; +} + +/* 64-bit helpers */ + int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2) { return arg1 << arg2; diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 4cad967..4b2b0be 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -56,6 +56,7 @@ enum { #define TCG_TARGET_CALL_STACK_OFFSET 0 /* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 #define TCG_TARGET_HAS_ext8s_i32 #define TCG_TARGET_HAS_ext16s_i32 // #define TCG_TARGET_HAS_ext8u_i32 diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index 7ab6f0c..fa39bfc 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -75,6 +75,7 @@ enum { #define TCG_TARGET_STACK_GROWSUP /* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 //#define TCG_TARGET_HAS_ext8s_i32 //#define TCG_TARGET_HAS_ext16s_i32 //#define TCG_TARGET_HAS_bswap16_i32 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index f97034c..e994fd5 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -45,6 +45,7 @@ enum { #define TCG_TARGET_CALL_STACK_OFFSET 0 /* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 #define TCG_TARGET_HAS_rot_i32 #define TCG_TARGET_HAS_ext8s_i32 #define TCG_TARGET_HAS_ext16s_i32 diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 6ae1760..c71e1a8 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -365,6 +365,19 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, } /* FIXME: Should this be pure? */ +static inline void tcg_gen_helper32(void *func, TCGv_i32 ret, + TCGv_i32 a, TCGv_i32 b) +{ + TCGv_ptr fn; + TCGArg args[2]; + fn = tcg_const_ptr((tcg_target_long)func); + args[0] = GET_TCGV_I32(a); + args[1] = GET_TCGV_I32(b); + tcg_gen_callN(&tcg_ctx, fn, 0, 0, GET_TCGV_I32(ret), 2, args); + tcg_temp_free_ptr(fn); +} + +/* FIXME: Should this be pure? */ static inline void tcg_gen_helper64(void *func, TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) { @@ -635,7 +648,7 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); } -#else +#elif defined(TCG_TARGET_HAS_div2_i32) static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { TCGv_i32 t0; @@ -671,6 +684,26 @@ static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2); tcg_temp_free_i32(t0); } +#else +static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) +{ + tcg_gen_helper32(tcg_helper_div_i32, ret, arg1, arg2); +} + +static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) +{ + tcg_gen_helper32(tcg_helper_rem_i32, ret, arg1, arg2); +} + +static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) +{ + tcg_gen_helper32(tcg_helper_divu_i32, ret, arg1, arg2); +} + +static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) +{ + tcg_gen_helper32(tcg_helper_remu_i32, ret, arg1, arg2); +} #endif #if TCG_TARGET_REG_BITS == 32 @@ -1135,7 +1168,7 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); } -#else +#elif defined(TCG_TARGET_HAS_div2_i64) static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { TCGv_i64 t0; @@ -1171,6 +1204,26 @@ static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2); tcg_temp_free_i64(t0); } +#else +static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) +{ + tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2); +} + +static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) +{ + tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2); +} + +static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) +{ + tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2); +} + +static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) +{ + tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2); +} #endif #endif diff --git a/tcg/tcg-runtime.h b/tcg/tcg-runtime.h index e750cc1..5615b13 100644 --- a/tcg/tcg-runtime.h +++ b/tcg/tcg-runtime.h @@ -2,6 +2,11 @@ #define TCG_RUNTIME_H /* tcg-runtime.c */ +int32_t tcg_helper_div_i32(int32_t arg1, int32_t arg2); +int32_t tcg_helper_rem_i32(int32_t arg1, int32_t arg2); +uint32_t tcg_helper_divu_i32(uint32_t arg1, uint32_t arg2); +uint32_t tcg_helper_remu_i32(uint32_t arg1, uint32_t arg2); + int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2); int64_t tcg_helper_sar_i64(int64_t arg1, int64_t arg2); diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h index 765f0b4..d1e8b9e 100644 --- a/tcg/x86_64/tcg-target.h +++ b/tcg/x86_64/tcg-target.h @@ -56,6 +56,8 @@ enum { #define TCG_TARGET_CALL_STACK_OFFSET 0 /* optional instructions */ +#define TCG_TARGET_HAS_div2_i32 +#define TCG_TARGET_HAS_div2_i64 #define TCG_TARGET_HAS_bswap16_i32 #define TCG_TARGET_HAS_bswap16_i64 #define TCG_TARGET_HAS_bswap32_i32
Some targets like ARM would benefit to use 32-bit helpers for div/rem/divu/remu. Create a #define for div2 so that targets can select between div, div2 and helper implementation. Use the helper version if none of the #define are present. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> --- tcg-runtime.c | 24 +++++++++++++++++++ tcg/arm/tcg-target.h | 1 + tcg/hppa/tcg-target.h | 1 + tcg/i386/tcg-target.h | 1 + tcg/tcg-op.h | 57 +++++++++++++++++++++++++++++++++++++++++++++- tcg/tcg-runtime.h | 5 ++++ tcg/x86_64/tcg-target.h | 2 + 7 files changed, 89 insertions(+), 2 deletions(-)