rewrite the ARM port of GNU lightning to a form compatible with the versions for the other CPUs

This commit is contained in:
kr.angelov
2013-09-11 20:17:50 +00:00
parent 9db040e0da
commit b3a644300c
8 changed files with 2525 additions and 3264 deletions

View File

@@ -102,7 +102,6 @@ typedef enum {
/* match vfpv3 result */
#define NAN_TO_INT_IS_ZERO 1
#define jit_thumb_p() jit_cpu.thumb
#define jit_armv6_p() (jit_cpu.version >= 6)
typedef union _jit_thumb_t {
int i;
@@ -110,13 +109,13 @@ typedef union _jit_thumb_t {
} jit_thumb_t;
#if __BYTE_ORDER == __LITTLE_ENDIAN
# define _jit_WW(i, j) do { _jit_W(j); _jit_W(i); } while (0)
# define code2thumb(t0, t1, c0, c1) do { t1 = c0; t0 = c1; } while (0)
# define thumb2code(t0, t1, c0, c1) do { c0 = t1; c1 = t0; } while (0)
# define _jit_WW(i, j) (_jit_W(j), _jit_W(i))
# define code2thumb(t0, t1, c0, c1) (t1 = c0, t0 = c1)
# define thumb2code(t0, t1, c0, c1) (c0 = t1, c1 = t0)
#else
# define _jit_WW(i, j) do { _jit_W(i); _jit_W(j); } while (0)
# define code2thumb(t0, t1, c0, c1) do { t0 = c0; t1 = c1; } while (0)
# define thumb2code(t0, t1, c0, c1) do { c0 = t0; c1 = t1; } while (0)
# define _jit_WW(i, j) (_jit_W(i), _jit_W(j))
# define code2thumb(t0, t1, c0, c1) (t0 = c0, t1 = c1)
# define thumb2code(t0, t1, c0, c1) (c0 = t0, c1 = t1)
#endif
#define ARM_CC_EQ 0x00000000 /* Z=1 */
@@ -625,318 +624,111 @@ success:
}
imm = ((imm & 0x80) << 17) | ((imm & 0x70) << 12) | (imm & 0x0f);
code |= mode | imm;
if (jit_thumb_p()) {
#ifdef USE_THUMB_CODE
if (code & 0x1000000)
code |= 0xff000000;
else
code |= 0xef000000;
}
else
#else
code |= ARM_CC_NV;
#endif
return (code);
}
#define arm_vodi(oi,r0) _arm_vodi(_jit,oi,r0)
__jit_inline void
_arm_vodi(jit_state_t _jit, int oi, int r0)
{
jit_thumb_t thumb;
assert(!(oi & 0x0000f000));
assert(!(r0 & 1)); r0 >>= 1;
thumb.i = oi|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#ifdef USE_THUMB_CODE
#define _jit_TI(I) (_jitl.thumb.i = (I), _jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#else
#define _jit_TI(I) _jit_I(I)
#endif
#define arm_voqi(oi,r0) _arm_voqi(_jit,oi,r0)
__jit_inline void
_arm_voqi(jit_state_t _jit, int oi, int r0)
{
jit_thumb_t thumb;
assert(!(oi & 0x0000f000));
assert(!(r0 & 3)); r0 >>= 1;
thumb.i = oi|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vodi(oi,r0) \
(assert(!((oi) & 0x0000f000) && !((r0) & 1)), \
_jit_TI((oi)|(_u4((r0) >> 1)<<12)))
#define arm_vo_ss(o,r0,r1) _arm_cc_vo_ss(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_ss(cc,o,r0,r1) _arm_cc_vo_ss(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vo_ss(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
if (r0 & 1) o |= ARM_V_D; r0 >>= 1;
if (r1 & 1) o |= ARM_V_M; r1 >>= 1;
thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_voqi(oi,r0) \
(assert(!((oi) & 0x0000f000) && !((r0) & 3)), \
_jit_TI((oi)|(_u4((r0) >> 1)<<12)))
#define arm_vo_dd(o,r0,r1) _arm_cc_vo_dd(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_dd(cc,o,r0,r1) _arm_cc_vo_dd(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vo_dd(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
assert(!(r0 & 1) && !(r1 & 1));
r0 >>= 1; r1 >>= 1;
thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vo_ss(o,r0,r1) _arm_cc_vo_ss(ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_ss(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f)), \
_jit_TI((cc)|(o) | (((r0) & 1) ? ARM_V_D : 0) | (((r1) & 1) ? ARM_V_M : 0)|(_u4((r0) >> 1)<<12)|_u4((r1) >> 1)))
#define arm_vo_qd(o,r0,r1) _arm_cc_vo_qd(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_qd(cc,o,r0,r1) _arm_cc_vo_qd(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vo_qd(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
assert(!(r0 & 3) && !(r1 & 1));
r0 >>= 1; r1 >>= 1;
thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vo_dd(o,r0,r1) _arm_cc_vo_dd(ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_dd(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f) && !((r0) & 1) && !((r1) & 1)), \
_jit_TI((cc)|(o)|(_u4((r0) >> 1)<<12)|_u4((r1) >> 1)))
#define arm_vo_qq(o,r0,r1) _arm_cc_vo_qq(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_qq(cc,o,r0,r1) _arm_cc_vo_qq(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vo_qq(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
assert(!(r0 & 3) && !(r1 & 3));
r0 >>= 1; r1 >>= 1;
thumb.i = cc|o|(_u4(r0)<<12)|_u4(r1);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vo_qd(o,r0,r1) arm_cc_vo_qd(ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_qd(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f) && !((r0) & 3) && !((r1) & 1)), \
_jit_TI((cc)|(o)|(_u4((r0) >> 1)<<12)|_u4((r1) >> 1)))
#define arm_vorr_(o,r0,r1) _arm_cc_vorr_(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vorr_(cc,o,r0,r1) _arm_cc_vorr_(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vorr_(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vo_qq(o,r0,r1) arm_cc_vo_qq(ARM_CC_NV,o,r0,r1)
#define arm_cc_vo_qq(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f) && !((r0) & 3) && !((r1) & 3)), \
_jit_TI((cc)|(o)|(_u4((r0) >> 1)<<12)|_u4((r1) >> 1)))
#define arm_vors_(o,r0,r1) _arm_cc_vors_(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vors_(cc,o,r0,r1) _arm_cc_vors_(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vors_(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
if (r1 & 1) o |= ARM_V_N; r1 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vorr_(o,r0,r1) arm_cc_vorr_(ARM_CC_NV,o,r0,r1)
#define arm_cc_vorr_(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f)), \
_jit_TI((cc)|(o)|(_u4(r1)<<16)|(_u4(r0)<<12)))
#define arm_vorv_(o,r0,r1) _arm_cc_vorv_(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vorv_(cc,o,r0,r1) _arm_cc_vorv_(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vorv_(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
if (r1 & 1) cc |= ARM_V_M; r1 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vors_(o,r0,r1) arm_cc_vors_(ARM_CC_NV,o,r0,r1)
#define arm_cc_vors_(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f)), \
_jit_TI((cc)|(o)|(((r1) & 1) ? ARM_V_N : 0)|(_u4(r1 >> 1)<<16)|(_u4(r0)<<12)))
#define arm_vori_(o,r0,r1) _arm_cc_vori_(_jit,ARM_CC_NV,o,r0,r1)
#define arm_cc_vori_(cc,o,r0,r1) _arm_cc_vori_(_jit,cc,o,r0,r1)
__jit_inline void
_arm_cc_vori_(jit_state_t _jit, int cc, int o, int r0, int r1)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
/* use same bit pattern, to set opc1... */
if (r1 & 1) o |= ARM_V_I32; r1 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vorv_(o,r0,r1) arm_cc_vorv_(ARM_CC_NV,o,r0,r1)
#define arm_cc_vorv_(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && ((o) & 0xf000f00f)), \
_jit_TI((cc)|(o)|(((r1) & 1) ? ARM_V_M : 0)|(_u4((r1) >> 1)<<16)|(_u4(r0)<<12)))
#define arm_vorrd(o,r0,r1,r2) _arm_cc_vorrd(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_vorrd(cc,o,r0,r1,r2) _arm_cc_vorrd(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_vorrd(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
assert(!(r2 & 1));
r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vori_(o,r0,r1) arm_cc_vori_(ARM_CC_NV,o,r0,r1)
#define arm_cc_vori_(cc,o,r0,r1) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f)), \
/* use same bit pattern, to set opc1... */ \
_jit_TI((cc)|(o)|((r1 & 1) ? ARM_V_I32 : 0)|(_u4((r1) >> 1)<<16)|(_u4(r0)<<12)))
#define arm_vosss(o,r0,r1,r2) _arm_cc_vosss(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_vosss(cc,o,r0,r1,r2) _arm_cc_vosss(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_vosss(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
if (r0 & 1) o |= ARM_V_D; r0 >>= 1;
if (r1 & 1) o |= ARM_V_N; r1 >>= 1;
if (r2 & 1) o |= ARM_V_M; r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vorrd(o,r0,r1,r2) arm_cc_vorrd(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_vorrd(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f) && !((r2) & 1)), \
_jit_TI((cc)|(o)|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4((r2) >> 1)))
#define arm_voddd(o,r0,r1,r2) _arm_cc_voddd(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voddd(cc,o,r0,r1,r2) _arm_cc_voddd(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_voddd(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
assert(!(r0 & 1) && !(r1 & 1) && !(r2 & 1));
r0 >>= 1; r1 >>= 1; r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_vosss(o,r0,r1,r2) arm_cc_vosss(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_vosss(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f)), \
_jit_TI((cc)|(o)|(((r0) & 1) ? ARM_V_D : 0)|(((r1) & 1) ? ARM_V_N : 0)|(((r2) & 1) ? ARM_V_M : 0)|(_u4((r1) >> 1)<<16)|(_u4((r0) >> 1)<<12)|_u4((r2) >> 1)))
#define arm_voqdd(o,r0,r1,r2) _arm_cc_voqdd(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqdd(cc,o,r0,r1,r2) _arm_cc_voqdd(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_voqdd(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
assert(!(r0 & 3) && !(r1 & 1) && !(r2 & 1));
r0 >>= 1; r1 >>= 1; r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_voddd(o,r0,r1,r2) arm_cc_voddd(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voddd(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f) && !((r0) & 1) && !((r1) & 1) && !((r2) & 1)), \
_jit_TI((cc)|(o)|(_u4((r1) >> 1)<<16)|(_u4((r0) >> 1)<<12)|_u4((r2) >> 1)))
#define arm_voqqd(o,r0,r1,r2) _arm_cc_voqqd(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqqd(cc,o,r0,r1,r2) _arm_cc_voqqd(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_voqqd(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 1));
r0 >>= 1; r1 >>= 1; r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_voqdd(o,r0,r1,r2) arm_cc_voqdd(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqdd(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f) && !((r0) & 3) && !((r1) & 1) && !((r2) & 1)), \
_jit_TI((cc)|(o)|(_u4((r1) >> 1)<<16)|(_u4((r0) >> 1)<<12)|_u4((r2) >> 1)))
#define arm_voqqq(o,r0,r1,r2) _arm_cc_voqqq(_jit,ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqqq(cc,o,r0,r1,r2) _arm_cc_voqqq(_jit,cc,o,r0,r1,r2)
__jit_inline void
_arm_cc_voqqq(jit_state_t _jit, int cc, int o, int r0, int r1, int r2)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
assert(!(r0 & 3) && !(r1 & 3) && !(r2 & 3));
r0 >>= 1; r1 >>= 1; r2 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u4(r2);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_voqqd(o,r0,r1,r2) arm_cc_voqqd(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqqd(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f) && !((r0) & 3) && !((r1) & 3) && !((r2) & 1)), \
_jit_TI((cc)|(o)|(_u4((r1) >> 1)<<16)|(_u4((r0) >> 1)<<12)|_u4((r2) >> 1)))
#define arm_cc_vldst(cc,o,r0,r1,i0) _arm_cc_vldst(_jit,cc,o,r0,r1,i0)
__jit_inline void
_arm_cc_vldst(jit_state_t _jit, int cc, int o, int r0, int r1, int i0)
{
jit_thumb_t thumb;
/* i0 << 2 is byte offset */
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff0ff));
if (r0 & 1) {
assert(!(o & ARM_V_F64));
o |= ARM_V_D;
}
r0 >>= 1;
thumb.i = cc|o|(_u4(r1)<<16)|(_u4(r0)<<12)|_u8(i0);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_voqqq(o,r0,r1,r2) arm_cc_voqqq(ARM_CC_NV,o,r0,r1,r2)
#define arm_cc_voqqq(cc,o,r0,r1,r2) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f) && !((r0) & 3) && !((r1) & 3) && !((r2) & 3)), \
_jit_TI((cc)|(o)|(_u4((r1) >> 1)<<16)|(_u4((r0) >> 1)<<12)|_u4((r2) >> 1)))
#define arm_cc_vorsl(cc,o,r0,r1,i0) _arm_cc_vorsl(_jit,cc,o,r0,r1,i0)
__jit_inline void
_arm_cc_vorsl(jit_state_t _jit, int cc, int o, int r0, int r1, int i0)
{
jit_thumb_t thumb;
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff0ff));
/* save i0 double precision registers */
if (o & ARM_V_F64) i0 <<= 1;
assert(i0 && !(i0 & 1) && r1 + i0 <= 32);
/* if (r1 & 1) cc & ARM_V_F64 must be false */
if (r1 & 1) o |= ARM_V_D; r1 >>= 1;
thumb.i = cc|o|(_u4(r0)<<16)|(_u4(r1)<<12)|_u8(i0);
if (jit_thumb_p())
_jit_WW(thumb.s[0], thumb.s[1]);
else
_jit_I(thumb.i);
}
#define arm_cc_vldst(cc,o,r0,r1,i0) \
/* i0 << 2 is byte offset */ \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff0ff) && (!((r0) & 1) | !((o) & ARM_V_F64))), \
_jit_TI((cc)|(o)|(((r0) & 1) ? ARM_V_D : 0)|(_u4(r1)<<16)|(_u4((r0) >> 1)<<12)|_u8(i0)))
#define arm_cc_vorsl(cc,o,r0,r1,i0) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff0ff)), \
/* save i0 double precision registers */ \
_jit_TI((cc)|((o) | ((r1) & 1) ? ARM_V_D : 0)|(_u4(r0)<<16)|(_u4((r1) >> 1)<<12)|_u8(((o) & ARM_V_F64) ? ((i0) << 1) : (i0))))
/***********************************************************************
* VFPv2 and VFPv3 (encoding T2/A2) instructions
@@ -1247,117 +1039,53 @@ encode_arm_immediate(unsigned int v)
return (-1);
}
#define corrr(cc,o,rn,rd,rm) _corrr(_jit,cc,o,rn,rd,rm)
__jit_inline void
_corrr(jit_state_t _jit, int cc, int o, int rn, int rd, int rm)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fff0f));
_jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u4(rm));
}
#define corrr(cc,o,rn,rd,rm) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fff0f)), \
_jit_I((cc)|(o)|(_u4(rn)<<16)|(_u4(rd)<<12)|_u4(rm)))
#define corri(cc,o,rn,rd,im) _corri(_jit,cc,o,rn,rd,im)
__jit_inline void
_corri(jit_state_t _jit, int cc, int o, int rn, int rd, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fffff));
assert(!(im & 0xfffff000));
_jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|_u12(im));
}
#define corri(cc,o,rn,rd,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fffff) && !((im) & 0xfffff000)), \
_jit_I((cc)|(o)|(_u4(rn)<<16)|(_u4(rd)<<12)|_u12(im)))
#define coriw(cc,o,rd,im) _coriw(_jit,cc,o,rd,im)
__jit_inline void
_coriw(jit_state_t _jit, int cc, int o, int rd, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fffff));
assert(!(im & 0xffff0000));
_jit_I(cc|o|((im&0xf000)<<4)|(_u4(rd)<<12)|(im&0xfff));
}
#define coriw(cc,o,rd,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fffff) && !(im & 0xffff0000)), \
_jit_I((cc)|(o)|((im&0xf000)<<4)|(_u4(rd)<<12)|(im&0xfff)))
#define corri8(cc,o,rn,rt,im) _corri8(_jit,cc,o,rn,rt,im)
__jit_inline void
_corri8(jit_state_t _jit, int cc, int o, int rn, int rt, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fff0f));
assert(!(im & 0xffffff00));
_jit_I(cc|o|(_u4(rn)<<16)|(_u4(rt)<<12)|((im&0xf0)<<4)|(im&0x0f));
}
#define corri8(cc,o,rn,rt,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fff0f) && !(im & 0xffffff00)), \
_jit_I((cc)|(o)|(_u4(rn)<<16)|(_u4(rt)<<12)|((im&0xf0)<<4)|(im&0x0f)))
#define corrrr(cc,o,rh,rl,rm,rn) _corrrr(_jit,cc,o,rh,rl,rm,rn)
__jit_inline void
_corrrr(jit_state_t _jit, int cc, int o, int rh, int rl, int rm, int rn)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fff0f));
_jit_I(cc|o|(_u4(rh)<<16)|(_u4(rl)<<12)|(_u4(rm)<<8)|_u4(rn));
}
#define corrrr(cc,o,rh,rl,rm,rn) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fff0f)), \
_jit_I((cc)|(o)|(_u4(rh)<<16)|(_u4(rl)<<12)|(_u4(rm)<<8)|_u4(rn)))
#define corrrs(cc,o,rn,rd,rm,im) _corrrs(_jit,cc,o,rn,rd,rm,im)
__jit_inline void
_corrrs(jit_state_t _jit, int cc, int o, int rn, int rd, int rm, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000ff8f));
_jit_I(cc|o|(_u4(rd)<<12)|(_u4(rn)<<16)|(im<<7)|_u4(rm));
}
#define corrrs(cc,o,rn,rd,rm,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000ff8f)), \
_jit_I((cc)|(o)|(_u4(rd)<<12)|(_u4(rn)<<16)|(im<<7)|_u4(rm)))
#define cshift(cc,o,rd,rm,rn,im) _cshift(_jit,cc,o,rd,rm,rn,im)
__jit_inline void
_cshift(jit_state_t _jit, int cc, int o, int rd, int rm, int rn, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xffe0ff8f));
assert(((_u4(rm)<<8)&(im<<7)) == 0);
_jit_I(cc|ARM_SHIFT|o|(_u4(rd)<<12)|(_u4(rm)<<8)|(im<<7)|_u4(rn));
}
#define cshift(cc,o,rd,rm,rn,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xffe0ff8f) && ((_u4(rm)<<8)&(im<<7)) == 0), \
_jit_I((cc)|ARM_SHIFT|(o)|(_u4(rd)<<12)|(_u4(rm)<<8)|(im<<7)|_u4(rn)))
#define cb(cc,o,im) _cb(_jit,cc,o,im)
__jit_inline void
_cb(jit_state_t _jit, int cc, int o, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf0ffffff));
_jit_I(cc|o|_u24(im));
}
#define cb(cc,o,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf0ffffff)), \
_jit_I((cc)|(o)|_u24(im)))
#define cbx(cc,o,rm) _cbx(_jit,cc,o,rm)
__jit_inline void
_cbx(jit_state_t _jit, int cc, int o, int rm)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000000f));
_jit_I(cc|o|_u4(rm));
}
#define cbx(cc,o,rm) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000000f)), \
_jit_I((cc)|(o)|_u4(rm)))
#define corl(cc,o,r0,i0) _corl(_jit,cc,o,r0,i0)
__jit_inline void
_corl(jit_state_t _jit, int cc, int o, int r0, int i0)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00fffff));
_jit_I(cc|o|(_u4(r0)<<16)|_u16(i0));
}
#define corl(cc,o,r0,i0) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00fffff)), \
_jit_I((cc)|(o)|(_u4(r0)<<16)|_u16(i0)))
#define c6orr(cc,o,rd,rm) _c6orr(_jit,cc,o,rd,rm)
__jit_inline void
_c6orr(jit_state_t _jit, int cc, int o, int rd, int rm)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf000f00f));
_jit_I(cc|o|(_u4(rd)<<12)|_u4(rm));
}
#define c6orr(cc,o,rd,rm) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf000f00f)), \
_jit_I((cc)|(o)|(_u4(rd)<<12)|_u4(rm)))
#define arm_cc_pkh(cc,o,rn,rd,rm,im) _arm_cc_pkh(_jit,cc,o,rn,rd,rm,im)
__jit_inline void
_arm_cc_pkh(jit_state_t _jit, int cc, int o, int rn, int rd, int rm, int im)
{
assert(!(cc & 0x0fffffff));
assert(!(o & 0xf00ff00f));
_jit_I(cc|o|(_u4(rn)<<16)|(_u4(rd)<<12)|(_u5(im)<<7)|_u4(rm));
}
#define arm_cc_pkh(cc,o,rn,rd,rm,im) \
(assert(!((cc) & 0x0fffffff) && !((o) & 0xf00ff00f)), \
_jit_I((cc)|(o)|(_u4(rn)<<16)|(_u4(rd)<<12)|(_u5(im)<<7)|_u4(rm)))
#define _CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm)
@@ -1887,223 +1615,106 @@ encode_thumb_shift(int v, int type)
}
#endif
#define thumb2_orri(o,rn,rd,im) _torri(_jit,o,rn,rd,im)
#define torri(o,rn,rt,im) _torri(_jit,o,rn,rt,im)
__jit_inline void
_torri(jit_state_t _jit, int o, int rn, int rd, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x0c0f7fff));
assert(!(im & 0xfbff8f00));
thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define thumb2_orri(o,rn,rd,im) torri(o,rn,rd,im)
#define torri(o,rn,rd,im) \
(assert(!((o) & 0x0c0f7fff) && !((im) & 0xfbff8f00)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rd)<<8)|(im)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torri8(o,rn,rt,im) _torri8(_jit,o,rn,rt,im)
__jit_inline void
_torri8(jit_state_t _jit, int o, int rn, int rt, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x000ff0ff));
assert(!(im & 0xffffff00));
thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torri8(o,rn,rt,im) \
(assert(!((o) & 0x000ff0ff) && !((im) & 0xffffff00)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rt)<<12)|im), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torri12(o,rn,rt,im) _torri12(_jit,o,rn,rt,im)
__jit_inline void
_torri12(jit_state_t _jit, int o, int rn, int rt, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x000fffff));
assert(!(im & 0xfffff000));
thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torri12(o,rn,rt,im) \
(assert(!((o) & 0x000fffff) && !((im) & 0xfffff000)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rt)<<12)|(im)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define toriw(o,rd,im) _toriw(_jit,o,rd,im)
__jit_inline void
_toriw(jit_state_t _jit, int o, int rd, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x40f7fff));
assert(!(im & 0xffff0000));
thumb.i = o|((im&0xf000)<<4)|((im&0x800)<<15)|((im&0x700)<<4)|(_u4(rd)<<8)|(im&0xff);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define toriw(o,rd,im) \
(assert(!((o) & 0x40f7fff) && !((im) & 0xffff0000)), \
_jitl.thumb.i = ((o)|(((im)&0xf000)<<4)|(((im)&0x800)<<15)|(((im)&0x700)<<4)|(_u4(rd)<<8)|((im)&0xff)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torrr(o,rn,rd,rm) _torrr(_jit,o,rn,rd,rm)
__jit_inline void
_torrr(jit_state_t _jit, int o, int rn, int rd, int rm)
{
jit_thumb_t thumb;
assert(!(o & 0xf0f0f));
thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torrr(o,rn,rd,rm) \
(assert(!((o) & 0xf0f0f)), \
_jit.jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rd)<<8)|_u4(rm)), \
_jit_WW(_jit.jitl.thumb.s[0], _jit.jitl.thumb.s[1]))
#define torrrs(o,rn,rd,rm,im) _torrrs(_jit,o,rn,rd,rm,im)
__jit_inline void
_torrrs(jit_state_t _jit, int o, int rn, int rd, int rm, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x000f0f0f));
assert(!(im & 0xffff8f0f));
thumb.i = o|(_u4(rn)<<16)|(_u4(rd)<<8)|im|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torrrs(o,rn,rd,rm,im) \
(assert(!((o) & 0x000f0f0f) && !((im) & 0xffff8f0f)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rd)<<8)|(im)|_u4(rm)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torxr(o,rn,rt,rm) _torxr(_jit,o,rn,rt,rm)
__jit_inline void
_torxr(jit_state_t _jit, int o, int rn, int rt, int rm)
{
jit_thumb_t thumb;
assert(!(o & 0xf0f0f));
thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torxr(o,rn,rt,rm) \
(assert(!((o) & 0xf0f0f)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rt)<<12)|_u4(rm)) \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torrrr(o,rn,rl,rh,rm) _torrrr(_jit,o,rn,rl,rh,rm)
__jit_inline void
_torrrr(jit_state_t _jit, int o, int rn, int rl, int rh, int rm)
{
jit_thumb_t thumb;
assert(!(o & 0x000fff0f));
thumb.i = o|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torrrr(o,rn,rl,rh,rm) \
(assert(!((o) & 0x000fff0f)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rl)<<12)|(_u4(rh)<<8)|_u4(rm)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define torrri8(o,rn,rt,rt2,im) _torrri8(_jit,o,rn,rt,rt2,im)
__jit_inline void
_torrri8(jit_state_t _jit, int o, int rn, int rt, int rt2, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x000fffff));
assert(!(im & 0xffffff00));
thumb.i = o|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torrri8(o,rn,rt,rt2,im) \
(assert(!((o) & 0x000fffff) && !((im) & 0xffffff00)), \
_jitl.thumb.i = ((o)|(_u4(rn)<<16)|(_u4(rt)<<12)|(_u4(rt2)<<8)|(im)), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define tc8(cc,im) _tc8(_jit,cc,im)
__jit_inline void
_tc8(jit_state_t _jit, int cc, int im)
{
assert(!(cc & 0x0fffffff));
assert(cc != ARM_CC_AL && cc != ARM_CC_NV);
assert(_s8P(im));
_jit_W(THUMB_CC_B|(cc>>20)|(im&0xff));
}
#define tc8(cc,im) \
(assert(!((cc) & 0x0fffffff) && ((cc) != ARM_CC_AL) && ((cc) != ARM_CC_NV) && _s8P(im)), \
_jit_W(THUMB_CC_B|((cc)>>20)|((im)&0xff)))
#define t11(im) _t11(_jit,im)
__jit_inline void
_t11(jit_state_t _jit, int im)
{
assert(!(im & 0xfffff800));
_jit_W(THUMB_B|im);
}
#define t11(im) \
(assert(!((im) & 0xfffff800)), \
_jit_W(THUMB_B|(im)))
#define tcb(cc,im) _tcb(_jit,cc,im)
__jit_inline void
_tcb(jit_state_t _jit, int cc, int im)
{
jit_thumb_t thumb;
assert(!(cc & 0xfffffff));
assert(cc != ARM_CC_AL && cc != ARM_CC_NV);
cc = ((unsigned)cc) >> 6;
assert(!(im & (THUMB2_CC_B|cc)));
thumb.i = THUMB2_CC_B|cc|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define tcb(cc,im) \
(assert(!((cc) & 0xfffffff) && ((cc) != ARM_CC_AL) && ((cc) != ARM_CC_NV) && !((im) & (THUMB2_CC_B|(((unsigned)cc) >> 6)))), \
_jitl.thumb.i = THUMB2_CC_B|(((unsigned)(cc)) >> 6)|(im), \
_jit_WW(_jitl.thumb.s[0], _jitl.thumb.s[1]))
#define blxi(im) _blxi(_jit,im)
__jit_inline void
_blxi(jit_state_t _jit, int im)
{
assert(!(im & 0xfe000000));
_jit_I(ARM_BLXI|im);
}
#define blxi(im) \
(assert(!((im) & 0xfe000000)), \
_jit_I(ARM_BLXI|(im)))
#define tb(o,im) _tb(_jit,o,im)
__jit_inline void
_tb(jit_state_t _jit, int o, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x07ff2fff));
assert(!(o & im));
thumb.i = o|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define tb(o,im) \
(assert(!((o) & 0x07ff2fff) && !((o) & (im))), \
jitl.thumb.i = (o)|(im), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define tshift(o,rd,rm,im) _tshift(_jit,o,rd,rm,im)
__jit_inline void
_tshift(jit_state_t _jit, int o, int rd, int rm, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x7fcf));
assert(im >= 0 && im < 32);
thumb.i = o|((im&0x1c)<<10)|(_u4(rd)<<8)|((im&3)<<6)|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define tshift(o,rd,rm,im) \
(assert(!((o) & 0x7fcf) && ((im) >= 0) && ((im) < 32)), \
thumb.i = (o|(((im)&0x1c)<<10)|(_u4(rd)<<8)|(((im)&3)<<6)|_u4(rm)), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define thumb2_orrr(o,rn,rd,rm) _thumb2_orrr(_jit,o,rn,rd,rm)
__jit_inline void
_thumb2_orrr(jit_state_t _jit, int o, int rn, int rd, int rm)
{
jit_thumb_t thumb;
assert(!(o & 0x000f0f0f));
thumb.i = o | (_u4(rn)<<16) | (_u4(rd)<<8) | _u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define thumb2_orrr(o,rn,rd,rm) \
(assert(!((o) & 0x000f0f0f)), \
thumb.i = (o) | (_u4(rn)<<16) | (_u4(rd)<<8) | _u4(rm), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define thumb2_bfx(o,rn,rd,lsb,width) _thumb2_bfx(_jit,o,rn,rd,lsb,width)
__jit_inline void
_thumb2_bfx(jit_state_t _jit, int o, int rn, int rd, int lsb, int width)
{
int msb;
jit_thumb_t thumb;
assert(!(o & 0x7fdf));
assert(lsb >= 0 && lsb < 32 && width >= 0 && width <= 32);
msb = lsb + width;
if (msb > 31)
msb = 31;
thumb.i = o | (_u4(rn) << 16) | (_u4(rd) << 8) |
((msb & 7) << 10) | ((msb & 3) << 5) | msb;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define thumb2_bfx(o,rn,rd,lsb,width) \
(assert(!((o) & 0x7fdf) && ((lsb) >= 0) && ((lsb) < 32) && ((width) >= 0) && ((width) <= 32)), \
thumb.i = (o) | (_u4(rn) << 16) | (_u4(rd) << 8) | \
(((((lsb) + (width) > 31) ? 31 : (lsb) + (width)) & 7) << 10) | \
(((((lsb) + (width) > 31) ? 31 : (lsb) + (width)) & 3) << 5) | \
(((lsb) + (width) > 31) ? 31 : (lsb) + (width)), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define thumb2_cbxz(o,rn,im) _thumb2_cbxz(_jit,o,rn,im)
__jit_inline void
_thumb2_cbxz(jit_state_t _jit, int o, int rn, int im)
{
assert(!(o & 0x2ff));
/* branch forward only */
assert(im >= 0 && im < 128 && !(im & 1));
im >>= 1;
_jit_W(o|((im&0x80)<<5)|((im&0x1f)<<3)|_u3(rn));
}
#define thumb2_cbxz(o,rn,im) \
(assert(!((o) & 0x2ff) && (im) >= 0 && (im) < 128 && !((im) & 1)), \
_jit_W((o)|((((im) >> 1)&0x80)<<5)|((((im) >> 1)&0x1f)<<3)|_u3(rn)))
#define thumb2_dbg(h,l,im) _thumb2_dbg(_jit,h,l,im)
__jit_inline void
_thumb2_dbg(jit_state_t _jit, int h, int l, int im)
{
assert(!(h & ~0xffff));
assert(!(l & 0xffff000f));
_jit_WW(h, l | _u4(im));
}
#define thumb2_dbg(h,l,im) \
(assert(!((h) & ~0xffff) && !((l) & 0xffff000f)), \
_jit_WW((h), (l) | _u4(im)))
#define tpp(o,im) _tpp(_jit,o,im)
__jit_inline void
_tpp(jit_state_t _jit, int o, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x0000ffff));
assert(!(im & 0xffff2000));
if (o == THUMB2_PUSH)
assert(!(im & 0x8000));
assert(__builtin_popcount(im & 0x1fff) > 1);
thumb.i = o|im;
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define tpp(o,im) \
(assert(!((o) & 0x0000ffff) && !((im) & 0xffff2000) && \
(!((o) == THUMB2_PUSH) || !((im) & 0x8000)) && \
(__builtin_popcount((im) & 0x1fff) > 1)), \
_jit.jitl.thumb.i = (o)|(im), \
_jit_WW(_jit.jitl.thumb.s[0], _jit.jitl.thumb.s[1]))
#define THUMB2_IT 0
#define THUMB2_ITT 1
@@ -2120,35 +1731,26 @@ _tpp(jit_state_t _jit, int o, int im)
#define THUMB2_ITETE 12
#define THUMB2_ITTEE 13
#define THUMB2_ITEEE 14
#define tcit(tc,it) _tcit(_jit,tc,it)
__jit_inline void
_tcit(jit_state_t _jit, unsigned int tc, int it)
{
int c;
int m;
c = (tc >> 28) & 1;
assert(!(tc & 0xfffffff) && tc != ARM_CC_NV);
switch (it) {
case THUMB2_IT: m = 1<<3; break;
case THUMB2_ITT: m = (c<<3)| (1<<2); break;
case THUMB2_ITE: m = (!c<<3)| (1<<2); break;
case THUMB2_ITTT: m = (c<<3)| (c<<2)| (1<<1); break;
case THUMB2_ITET: m = (!c<<3)| (c<<2)| (1<<1); break;
case THUMB2_ITTE: m = (c<<3)|(!c<<2)| (1<<1); break;
case THUMB2_ITEE: m = (!c<<3)|(!c<<2)| (1<<1); break;
case THUMB2_ITTTT: m = (c<<3)| (c<<2)| (c<<1)|1; break;
case THUMB2_ITETT: m = (!c<<3)| (c<<2)| (c<<1)|1; break;
case THUMB2_ITTET: m = (c<<3)|(!c<<2)| (c<<1)|1; break;
case THUMB2_ITEET: m = (!c<<3)|(!c<<2)| (c<<1)|1; break;
case THUMB2_ITTTE: m = (c<<3)| (c<<2)|(!c<<1)|1; break;
case THUMB2_ITETE: m = (!c<<3)| (c<<2)|(!c<<1)|1; break;
case THUMB2_ITTEE: m = (c<<3)|(!c<<2)|(!c<<1)|1; break;
case THUMB2_ITEEE: m = (!c<<3)|(!c<<2)|(!c<<1)|1; break;
default: assert(!"valid it code!");
}
assert(m && (tc != ARM_CC_AL || !(m & (m - 1))));
_jit_W(0xbf00 | (tc >> 24) | m);
}
#define tcit(tc,it) \
(assert(!(tc & 0xfffffff) && tc != ARM_CC_NV), \
_jit_W(0xbf00 | (tc >> 24) | \
((it == THUMB2_IT) ? 1<<3 : \
(it == THUMB2_ITT) ? ((((tc) >> 28) & 1)<<3)| (1<<2) : \
(it == THUMB2_ITE) ? (!(((tc) >> 28) & 1)<<3)| (1<<2) : \
(it == THUMB2_ITTT) ? ((((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)| (1<<1) : \
(it == THUMB2_ITET) ? (!(((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)| (1<<1) : \
(it == THUMB2_ITTE) ? ((((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)| (1<<1) : \
(it == THUMB2_ITEE) ? (!(((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)| (1<<1) : \
(it == THUMB2_ITTTT) ? ((((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)| ((((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITETT) ? (!(((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)| ((((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITTET) ? ((((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)| ((((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITEET) ? (!(((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)| ((((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITTTE) ? ((((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)|(!(((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITETE) ? (!(((tc) >> 28) & 1)<<3)| ((((tc) >> 28) & 1)<<2)|(!(((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITTEE) ? ((((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)|(!(((tc) >> 28) & 1)<<1)|1 : \
(it == THUMB2_ITEEE) ? (!(((tc) >> 28) & 1)<<3)|(!(((tc) >> 28) & 1)<<2)|(!(((tc) >> 28) & 1)<<1)|1 : \
assert(!"valid it code"))))
#define _IT(cc) tcit(cc,THUMB2_IT)
#define _ITT(cc) tcit(cc,THUMB2_ITT)
#define _ITE(cc) tcit(cc,THUMB2_ITE)
@@ -2165,38 +1767,23 @@ _tcit(jit_state_t _jit, unsigned int tc, int it)
#define _ITTEE(cc) tcit(cc,THUMB2_ITTEE)
#define _ITEEE(cc) tcit(cc,THUMB2_ITEEE)
#define torl(o,rn,im) _torl(_jit,o,rn,im)
__jit_inline void
_torl(jit_state_t _jit, int o, int rn, int im)
{
jit_thumb_t thumb;
assert(!(o & 0xf1fff));
assert(rn != _R15 || !im || ((o & 0xc000) == 0xc000));
assert(!(o & THUMB2_LDM_W) || !(im & (1 << rn)));
thumb.i = o | (_u4(rn)<<16) | _u13(im);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define torl(o,rn,im) \
(assert(!((o) & 0xf1fff) && \
((rn) != _R15 || !(im) || (((o) & 0xc000) == 0xc000)) && \
!((o) & THUMB2_LDM_W) || !((im) & (1 << (rn)))), \
thumb.i = ((o) | (_u4(rn)<<16) | _u13(im)), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define thumb2_mrrc(o,t2,t,cc,o1,m) _thumb2_mrrc(_jit,o,t2,t,cc,o1,m)
__jit_inline void
_thumb2_mrrc(jit_state_t _jit, int o, int t2, int t, int cc, int o1, int m)
{
jit_thumb_t thumb;
assert(!(o & 0x03afffff));
thumb.i = o|(_u4(t2)<<16)|(_u4(t)<<12)|(_u4(cc)<<8)|(_u4(o1)<<4)|_u4(m);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define thumb2_mrrc(o,t2,t,cc,o1,m) \
(assert(!((o) & 0x03afffff)), \
thumb.i = ((o)|(_u4(t2)<<16)|(_u4(t)<<12)|(_u4(cc)<<8)|(_u4(o1)<<4)|_u4(m)), \
_jit_WW(thumb.s[0], thumb.s[1]))
#define thumb2_pkh(o,rn,rd,rm,im) _thumb2_pkh(_jit,o,rn,rd,rm,im)
__jit_inline void
_thumb2_pkh(jit_state_t _jit, int o, int rn, int rd, int rm, int im)
{
jit_thumb_t thumb;
assert(!(o & 0x7ffcf));
thumb.i = o|(_u4(rn)<<16)|((_u5(im)&0x1c)<<10)|
(_u4(rd)<<12)|((im&3)<<6)|_u4(rm);
_jit_WW(thumb.s[0], thumb.s[1]);
}
#define thumb2_pkh(o,rn,rd,rm,im) \
(assert(!((o) & 0x7ffcf)), \
thumb.i = ((o)|(_u4(rn)<<16)|((_u5(im)&0x1c)<<10)| \
(_u4(rd)<<12)|(((im)&3)<<6)|_u4(rm)), \
_jit_WW(thumb.s[0], thumb.s[1]))
/* v6T2, v7 */
#define THUMB2_BFX 0xf3600000

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,7 @@
#ifndef __lightning_fp_swf_h
#define __lightning_fp_swf_h
#if 0
#include <math.h>
#define swf_off(rn) ((rn) << 2)
@@ -1249,5 +1250,5 @@ swf_retval_d(jit_state_t _jit, jit_fpr_t r0)
swf_strin(_R1, JIT_FP, swf_off(r0) + 4);
}
}
#endif
#endif /* __lightning_fp_swf_h */

View File

@@ -34,6 +34,8 @@
#ifndef __lightning_fp_vfp_h
#define __lightning_fp_vfp_h
#if 0
__jit_inline void
vfp_movr_f(jit_state_t _jit, jit_fpr_t r0, jit_fpr_t r1)
{
@@ -1084,5 +1086,6 @@ vfp_retval_d(jit_state_t _jit, jit_fpr_t r0)
#undef vfp_unget_tmp
#undef vfp_get_tmp
#endif
#endif /* __lightning_fp_vfp_h */

View File

@@ -45,9 +45,10 @@ jit_hard_order[6] = {
#define JIT_FPR(n) \
(jit_hardfp_p() ? jit_hard_order[n] : jit_soft_order[n])
#include "fp-swf.h"
#include "fp-vfp.h"
#include "arm/fp-swf.h"
#include "arm/fp-vfp.h"
#if 0
#define jit_movr_f(r0, r1) arm_movr_f(_jit, r0, r1)
__jit_inline void
arm_movr_f(jit_state_t _jit, jit_fpr_t r0, jit_fpr_t r1)
@@ -1103,5 +1104,5 @@ arm_retval_d(jit_state_t _jit, jit_fpr_t r0)
}
/* else assume chaining call to jit_retval_d as done in tests/funcfp.c */
}
#endif
#endif /* __lightning_fp_arm_h */

View File

@@ -51,8 +51,7 @@ jit_flush_code(void *start, void *end)
__clear_cache(start, end);
}
#define jit_get_cpu jit_get_cpu
__jit_constructor static void
__attribute__((constructor)) static void
jit_get_cpu(void)
{
#if defined(__linux__)
@@ -106,4 +105,279 @@ jit_get_cpu(void)
jit_cpu.thumb = 0;
}
static void
arm_patch_arguments(struct jit_local_state* jitl)
{
int reg;
int ioff;
int foff;
int size;
int index;
jit_thumb_t thumb;
int offset;
union {
_ui *i;
_us *s;
} u;
ioff = foff = 0;
for (index = jitl->nextarg_put - 1, offset = 0; index >= 0; index--) {
if (jitl->types[index >> 5] & (1 << (index & 31)))
size = sizeof(double);
else
size = sizeof(int);
u.i = jitl->arguments[index];
if (jit_thumb_p()) {
code2thumb(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
switch (thumb.i & 0xfff00f00) {
case ARM_CC_AL|ARM_VSTR|ARM_P:
if (jit_hardfp_p()) {
if (foff < 16) {
reg = (thumb.i >> 12) & 0xf;
thumb.i = (ARM_CC_AL|ARM_VMOV_F |
((foff >> 1) << 12) | reg);
if (foff & 1)
thumb.i |= ARM_V_D;
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
++foff;
continue;
}
}
else {
if (ioff < 4) {
thumb.i = ((thumb.i & 0xfff0ff00) |
(JIT_FP << 16) | ioff);
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
++ioff;
continue;
}
}
thumb.i = (thumb.i & 0xffffff00) | (offset >> 2);
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
break;
case ARM_CC_AL|ARM_VSTR|ARM_V_F64|ARM_P:
if (jit_hardfp_p()) {
if (foff & 1)
++foff;
if (foff < 16) {
reg = (thumb.i >> 12) & 0xf;
thumb.i = (ARM_CC_AL|ARM_VMOV_F|ARM_V_F64 |
((foff >> 1) << 12) | reg);
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
foff += 2;
continue;
}
}
else {
if (ioff & 1)
++ioff;
if (ioff < 4) {
thumb.i = ((thumb.i & 0xfff0ff00) |
(JIT_FP << 16) | ioff);
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
ioff += 2;
continue;
}
}
if (offset & 7)
offset += sizeof(int);
thumb.i = (thumb.i & 0xffffff00) | (offset >> 2);
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
break;
case THUMB2_STRWI:
thumb_stri:
if (size == 8 && (ioff & 1))
++ioff;
if (ioff < 4) {
thumb.i = ((thumb.i & 0xfff0f000) |
(JIT_FP << 16) | (ioff << 2));
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
++ioff;
if (size == 8) {
code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
thumb.i = ((thumb.i & 0xfff0f000) |
(JIT_FP << 16) | (ioff << 2));
thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
++ioff;
}
continue;
}
if (size == 8 && (offset & 7))
offset += sizeof(int);
thumb.i = (thumb.i & 0xfffff000) | offset;
thumb2code(thumb.s[0], thumb.s[1], u.s[0], u.s[1]);
if (size == 8) {
code2thumb(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
thumb.i = (thumb.i & 0xfffff000) | (offset + 4);
thumb2code(thumb.s[0], thumb.s[1], u.s[2], u.s[3]);
}
break;
default:
/* offset too large */
if ((thumb.i & 0xfff00000) == THUMB2_STRWI)
goto thumb_stri;
abort();
}
}
else {
switch (u.i[0] & 0xfff00f00) {
case ARM_CC_AL|ARM_VSTR|ARM_P:
if (jit_hardfp_p()) {
if (foff < 16) {
reg = (u.i[0] >> 12) & 0xf;
u.i[0] = (ARM_CC_AL|ARM_VMOV_F |
((foff >> 1) << 12) | reg);
if (foff & 1)
u.i[0] |= ARM_V_D;
++foff;
continue;
}
}
else {
if (ioff < 4) {
u.i[0] = ((u.i[0] & 0xfff0ff00) |
(JIT_FP << 16) | ioff);
++ioff;
continue;
}
}
u.i[0] = (u.i[0] & 0xffffff00) | (offset >> 2);
break;
case ARM_CC_AL|ARM_VSTR|ARM_V_F64|ARM_P:
if (jit_hardfp_p()) {
if (foff & 1)
++foff;
if (foff < 16) {
reg = (u.i[0] >> 12) & 0xf;
u.i[0] = (ARM_CC_AL|ARM_VMOV_F|ARM_V_F64 |
((foff >> 1) << 12) | reg);
foff += 2;
continue;
}
}
else {
if (ioff & 1)
++ioff;
if (ioff < 4) {
u.i[0] = ((u.i[0] & 0xfff0ff00) |
(JIT_FP << 16) | ioff);
ioff += 2;
continue;
}
}
if (offset & 7)
offset += sizeof(int);
u.i[0] = (u.i[0] & 0xffffff00) | (offset >> 2);
break;
case ARM_CC_AL|ARM_STRI|ARM_P:
arm_stri:
if (size == 8 && (ioff & 1))
++ioff;
if (ioff < 4) {
u.i[0] = ((u.i[0] & 0xfff0f000) |
(JIT_FP << 16) | (ioff << 2));
++ioff;
if (size == 8) {
u.i[1] = ((u.i[1] & 0xfff0f000) |
(JIT_FP << 16) | (ioff << 2));
++ioff;
}
continue;
}
if (size == 8 && (offset & 7))
offset += sizeof(int);
u.i[0] = (u.i[0] & 0xfffff000) | offset;
if (size == 8)
u.i[1] = (u.i[1] & 0xfffff000) | (offset + 4);
break;
default:
/* offset too large */
if ((u.i[0] & 0xfff00000) == (ARM_CC_AL|ARM_STRI|ARM_P))
goto arm_stri;
abort();
}
}
offset += size;
}
jitl->reglist = ((1 << ioff) - 1) & 0xf;
if (jitl->stack_length < offset) {
jitl->stack_length = offset;
jit_patch_movi(jitl->stack, (void *)
((jitl->alloca_offset + jitl->stack_length + 7) & -8));
}
}
extern int __aeabi_idivmod(int, int);
extern unsigned __aeabi_uidivmod(unsigned, unsigned);
#pragma push_macro("_jit")
#ifdef _jit
#undef _jit
#endif
#define _jit (*jit)
static void
arm_divmod(jit_state* jit, int div, int sign,
jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
{
int d;
int l;
void *p;
l = 0xf;
if ((int)r0 < 4)
/* bogus extra push to align at 8 bytes */
l = (l & ~(1 << r0)) | 0x10;
#ifdef USE_THUMB_CODE
T1_PUSH(l);
#else
_PUSH(l);
#endif
if (r1 == _R1 && r2 == _R0) {
jit_movr_i(JIT_FTMP, _R0);
jit_movr_i(_R0, _R1);
jit_movr_i(_R1, JIT_FTMP);
} else if (r2 == _R0) {
jit_movr_i(_R1, r2);
jit_movr_i(_R0, r1);
} else {
jit_movr_i(_R0, r1);
jit_movr_i(_R1, r2);
}
p = (sign) ? (void*) __aeabi_idivmod : (void*) __aeabi_uidivmod;
if (!jit_exchange_p()) {
#ifdef USE_THUMB_CODE
d = (((int)p - (int)_jit.x.pc) >> 1) - 2;
#else
d = (((int)p - (int)_jit.x.pc) >> 2) - 2;
#endif
if (_s24P(d)) {
#ifdef USE_THUMB_CODE
T2_BLI(encode_thumb_jump(d));
#else
_BLI(d & 0x00ffffff);
#endif
}
else
goto fallback;
} else {
fallback:
jit_movi_i(JIT_FTMP, (int)p);
#ifdef USE_THUMB_CODE
T1_BLX(JIT_FTMP);
#else
_BLX(JIT_FTMP);
#endif
}
if (div) {
jit_movr_i(r0, _R0);
} else {
jit_movr_i(r0, _R1);
}
#ifdef USE_THUMB_CODE
T1_POP(l);
#else
_POP(l);
#endif
}
#pragma pop_macro("_jit")
#endif /* __lightning_funcs_h */

View File

@@ -131,6 +131,8 @@ typedef unsigned long _ul;
#define _s0P(I) ((I)==0)
#define _s8P(I) _siP(8,I)
#define _s16P(I) _siP(16,I)
#define _s20P(I) _siP(20,I)
#define _s24P(I) _siP(24,I)
#define _s32P(I) _siP(32,I)
#define _u8P(I) _uiP(8,I)
#define _u16P(I) _uiP(16,I)

View File

@@ -198,13 +198,19 @@ typedef union jit_code {
#endif
/* Common 'shortcut' implementations */
#ifndef jit_subi_i
#define jit_subi_i(d, rs, is) jit_addi_i((d), (rs), -(is))
#endif
#define jit_subi_l(d, rs, is) jit_addi_l((d), (rs), -(is))
#ifndef jit_subci_i
#define jit_subci_i(d, rs, is) jit_addci_i((d), (rs), -(is))
#endif
#define jit_subci_l(d, rs, is) jit_addci_l((d), (rs), -(is))
#define jit_rsbr_f(d, s1, s2) jit_subr_f((d), (s2), (s1))
#define jit_rsbr_d(d, s1, s2) jit_subr_d((d), (s2), (s1))
#ifndef jit_rsbr_i
#define jit_rsbr_i(d, s1, s2) jit_subr_i((d), (s2), (s1))
#endif
#define jit_rsbr_l(d, s1, s2) jit_subr_l((d), (s2), (s1))
#define jit_rsbr_p(d, s1, s2) jit_subr_p((d), (s2), (s1))
@@ -213,7 +219,9 @@ typedef union jit_code {
#define jit_notr_uc(d, rs) jit_xori_c((d), (rs), 255)
#define jit_notr_s(d, rs) jit_xori_s((d), (rs), 65535)
#define jit_notr_us(d, rs) jit_xori_s((d), (rs), 65535)
#ifndef jit_notr_i
#define jit_notr_i(d, rs) jit_xori_i((d), (rs), ~0)
#endif
#define jit_notr_ui(d, rs) jit_xori_i((d), (rs), ~0)
#define jit_notr_l(d, rs) jit_xori_l((d), (rs), ~0L)
#define jit_notr_ul(d, rs) jit_xori_l((d), (rs), ~0L)