#endif
int op;
} jit_instr_t;
-/* FIXME */
+#if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
+# define jit_mips2_p() 1
+#else
# define jit_mips2_p() 0
+#endif
# define _ZERO_REGNO 0
# define _T0_REGNO 0x08
# define _T1_REGNO 0x09
# endif
# define can_sign_extend_short_p(im) ((im) >= -32678 && (im) <= 32767)
# define can_zero_extend_short_p(im) ((im) >= 0 && (im) <= 65535)
+# define is_low_mask(im) (((im) & 1) ? (__builtin_popcountl((im) + 1) <= 1) : 0)
+# define is_middle_mask(im) ((im) ? (__builtin_popcountl((im) + (1 << __builtin_ctzl(im))) <= 1) : 0)
+# define is_high_mask(im) ((im) ? (__builtin_popcountl((im) + (1 << __builtin_ctzl(im))) == 0) : 0)
+# define masked_bits_count(im) __builtin_popcountl(im)
+# define unmasked_bits_count(im) (__WORDSIZE - masked_bits_count(im))
# if __WORDSIZE == 32
# define can_sign_extend_int_p(im) 1
# define can_zero_extend_int_p(im) 1
# define DADDIU(rt,rs,im) hrri(MIPS_DADDIU,rs,rt,im)
# define SUBU(rd,rs,rt) rrr_t(rs,rt,rd,MIPS_SUBU)
# define DSUBU(rd,rs,rt) rrr_t(rs,rt,rd,MIPS_DSUBU)
+# define MUL(rd,rs,rt) hrrr_t(MIPS_SPECIAL2,rs,rt,rd,MIPS_MUL)
# define MULT(rs,rt) rrr_t(rs,rt,_ZERO_REGNO,MIPS_MULT)
# define MULTU(rs,rt) rrr_t(rs,rt,_ZERO_REGNO,MIPS_MULTU)
# define DMULT(rs,rt) rrr_t(rs,rt,_ZERO_REGNO,MIPS_DMULT)
# define DSRLV(rd,rt,rs) rrr_t(rs,rt,rd,MIPS_DSRLV)
# define DSRL(rd,rt,sa) rrit(rt,rd,sa,MIPS_DSRL)
# define DSRL32(rd,rt,sa) rrit(rt,rd,sa,MIPS_DSRL32)
-# define INS(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos,pos+size-1,MIPS_INS)
-# define DINS(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos,pos+size-1,MIPS_DINS)
+# define INS(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos+size-1,pos,MIPS_INS)
+# define DINS(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos+size-1,pos,MIPS_DINS)
+# define DINSU(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos+size-32-1,pos-32,MIPS_DINSU)
+# define DINSM(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,pos+size-32-1,pos,MIPS_DINSM)
+# define EXT(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,size-1,pos,MIPS_EXT)
+# define DEXT(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,size-1,pos,MIPS_DEXT)
+# define DEXTU(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,size-1,pos-32,MIPS_DEXTU)
+# define DEXTM(rt,rs,pos,size) hrrrit(MIPS_SPECIAL3,rs,rt,size-32-1,pos,MIPS_DEXTM)
# define ROTR(rd,rt,sa) hrrrit(MIPS_SPECIAL,1,rt,rd,sa,MIPS_SRL)
# define DROTR(rd,rt,sa) hrrrit(MIPS_SPECIAL,1,rt,rd,sa,MIPS_DSRL)
# define MFHI(rd) rrr_t(_ZERO_REGNO,_ZERO_REGNO,rd,MIPS_MFHI)
# define JR(r0) hrrrit(MIPS_SPECIAL,r0,0,0,0,MIPS_JR)
# endif
# define J(i0) hi(MIPS_J,i0)
+# define MOVN(rd,rs,rt) hrrrit(0,rs,rt,rd,0,MIPS_MOVN)
# define MOVZ(rd,rs,rt) hrrrit(0,rs,rt,rd,0,MIPS_MOVZ)
# define comr(r0,r1) xori(r0,r1,-1)
# define negr(r0,r1) subr(r0,_ZERO_REGNO,r1)
# define div(rs,rt) DDIV(rs,rt)
# define divu(rs,rt) DDIVU(rs,rt)
# endif
+# define extr(rd,rt,lsb,nb) _extr(_jit,rd,rt,lsb,nb)
+static void _extr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
+# define insr(rd,rt,lsb,nb) _insr(_jit,rd,rt,lsb,nb)
+static void _insr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t);
# define addi(r0,r1,i0) _addi(_jit,r0,r1,i0)
static void _addi(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
#define addcr(r0,r1,r2) _addcr(_jit,r0,r1,r2)
# define xorr(r0,r1,r2) XOR(r0,r1,r2)
# define xori(r0,r1,i0) _xori(_jit,r0,r1,i0)
static void _xori(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t);
-# define movr(r0,r1) orr(r0,r1,_ZERO_REGNO)
+# define movr(r0,r1) _movr(_jit,r0,r1)
+static void _movr(jit_state_t*,jit_int32_t,jit_int32_t);
# define movi(r0,i0) _movi(_jit,r0,i0)
static void _movi(jit_state_t*,jit_int32_t,jit_word_t);
# define movi_p(r0,i0) _movi_p(_jit,r0,i0)
static jit_word_t _movi_p(jit_state_t*,jit_int32_t,jit_word_t);
+# define movnr(r0,r1,r2) MOVN(r0, r1, r2)
+# define movzr(r0,r1,r2) MOVZ(r0, r1, r2)
# define ldr_c(r0,r1) LB(r0,0,r1)
# define ldi_c(r0,i0) _ldi_c(_jit,r0,i0)
static void _ldi_c(jit_state_t*,jit_int32_t,jit_word_t);
# define stxi_l(i0,r0,r1) _stxi_l(_jit,i0,r0,r1)
static void _stxi_l(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
# endif
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-# define htonr_us(r0,r1) _htonr_us(_jit,r0,r1)
-static void _htonr_us(jit_state_t*,jit_int32_t,jit_int32_t);
-# define htonr_ui(r0,r1) _htonr_ui(_jit,r0,r1)
-static void _htonr_ui(jit_state_t*,jit_int32_t,jit_int32_t);
-# if __WORDSIZE == 64
-# define htonr_ul(r0,r1) _htonr_ul(_jit,r0,r1)
-static void _htonr_ul(jit_state_t*,jit_int32_t,jit_int32_t);
-# endif
-# else
-# define htonr_us(r0,r1) extr_us(r0,r1)
-# if __WORDSIZE == 32
-# define htonr_ui(r0,r1) movr(r0,r1)
-# else
-# define htonr_ui(r0,r1) extr_ui(r0,r1)
-# define htonr_ul(r0,r1) movr(r0,r1)
-# endif
+# define bswapr_us(r0,r1) _bswapr_us(_jit,r0,r1)
+static void _bswapr_us(jit_state_t*,jit_int32_t,jit_int32_t);
+# define bswapr_ui(r0,r1) _bswapr_ui(_jit,r0,r1)
+static void _bswapr_ui(jit_state_t*,jit_int32_t,jit_int32_t);
+# if __WORDSIZE == 64
+# define bswapr_ul(r0,r1) generic_bswapr_ul(_jit,r0,r1)
# endif
# define extr_c(r0,r1) _extr_c(_jit,r0,r1)
static void _extr_c(jit_state_t*,jit_int32_t,jit_int32_t);
assert(i0 == 0);
}
+static void
+_extr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
+ jit_int32_t pos, jit_int32_t size)
+{
+ assert(size > 0);
+
+ if (__WORDSIZE == 32)
+ EXT(r0, r1, pos, size);
+ else if (pos >= 32)
+ DEXTU(r0, r1, pos, size);
+ else if (size > 32)
+ DEXTM(r0, r1, pos, size);
+ else
+ DEXT(r0, r1, pos, size);
+}
+
+static void
+_insr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
+ jit_int32_t pos, jit_int32_t size)
+{
+ assert(size > 0);
+
+ if (__WORDSIZE == 32)
+ INS(r0, r1, pos, size);
+ else if (pos >= 32)
+ DINSU(r0, r1, pos, size);
+ else if (size > 32)
+ DINSM(r0, r1, pos, size);
+ else
+ DINS(r0, r1, pos, size);
+}
+
static void
_addi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
static void
_mulr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
- multu(r1, r2);
- MFLO(r0);
+ if (__WORDSIZE == 32)
+ MUL(r0, r1, r2);
+ else {
+ multu(r1, r2);
+ MFLO(r0);
+ }
}
static void
{
jit_int32_t reg;
if (can_zero_extend_short_p(i0))
- ANDI(r0, r1, i0);
- else {
- reg = jit_get_reg(jit_class_gpr);
- movi(rn(reg), i0);
- AND(r0, r1, rn(reg));
- jit_unget_reg(reg);
+ ANDI(r0, r1, i0);
+ else if (is_low_mask(i0)) {
+ if (jit_mips2_p())
+ extr(r0, r1, 0, masked_bits_count(i0));
+ else {
+ lshi(r0, r1, unmasked_bits_count(i0));
+ rshi_u(r0, r0, unmasked_bits_count(i0));
+ }
+ } else if (is_high_mask(i0)) {
+ if (jit_mips2_p() && r0 == r1)
+ insr(r0, _ZERO_REGNO, 0, unmasked_bits_count(i0));
+ else {
+ rshi(r0, r1, unmasked_bits_count(i0));
+ lshi(r0, r0, unmasked_bits_count(i0));
+ }
+ } else if (jit_mips2_p() && is_middle_mask(i0)) {
+ extr(r0, r1, __builtin_ctzl(i0), masked_bits_count(i0));
+ lshi(r0, r0, __builtin_ctzl(i0));
+ } else if (jit_mips2_p() && is_middle_mask(~i0)) {
+ if (r0 != r1)
+ movr(r0, r1);
+ insr(r0, _ZERO_REGNO, __builtin_ctzl(~i0), masked_bits_count(~i0));
+ } else {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), i0);
+ AND(r0, r1, rn(reg));
+ jit_unget_reg(reg);
}
}
}
}
+static void
+_movr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ if (r0 != r1)
+ orr(r0, r1, _ZERO_REGNO);
+}
+
static void
_movi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
}
#endif
-# if __BYTE_ORDER == __LITTLE_ENDIAN
static void
-_htonr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+_bswapr_us(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
- jit_int32_t t0;
- t0 = jit_get_reg(jit_class_gpr);
- rshi(rn(t0), r1, 8);
- andi(r0, r1, 0xff);
- andi(rn(t0), rn(t0), 0xff);
- lshi(r0, r0, 8);
- orr(r0, r0, rn(t0));
- jit_unget_reg(t0);
-}
-
-static void
-_htonr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
-{
- jit_int32_t t0;
- jit_int32_t t1;
- jit_int32_t t2;
- t0 = jit_get_reg(jit_class_gpr);
- t1 = jit_get_reg(jit_class_gpr);
- t2 = jit_get_reg(jit_class_gpr);
- rshi(rn(t0), r1, 24);
- rshi(rn(t1), r1, 16);
- rshi(rn(t2), r1, 8);
- andi(rn(t0), rn(t0), 0xff);
- andi(rn(t1), rn(t1), 0xff);
- andi(rn(t2), rn(t2), 0xff);
- andi(r0, r1, 0xff);
- lshi(r0, r0, 24);
- lshi(rn(t1), rn(t1), 8);
- orr(r0, r0, rn(t0));
- lshi(rn(t2), rn(t2), 16);
- orr(r0, r0, rn(t1));
- orr(r0, r0, rn(t2));
- jit_unget_reg(t2);
- jit_unget_reg(t1);
- jit_unget_reg(t0);
+ if (jit_mips2_p()) {
+ extr_us(r0, r1);
+ WSBH(r0, r0);
+ } else {
+ generic_bswapr_us(_jit, r0, r1);
+ }
}
static void
-_htonr_ul(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+_bswapr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
- jit_int32_t reg;
- reg = jit_get_reg(jit_class_gpr);
- rshi_u(rn(reg), r1, 32);
- htonr_ui(r0, r1);
- htonr_ui(rn(reg), rn(reg));
- lshi(r0, r0, 32);
- orr(r0, r0, rn(reg));
- jit_unget_reg(reg);
+ if (jit_mips2_p()) {
+ if (__WORDSIZE == 64) {
+ SLL(r0, r1, 0);
+ WSBH(r0, r0);
+ ROTR(r0, r0, 16);
+ extr(r0, r0, 0, 32);
+ } else {
+ WSBH(r0, r1);
+ ROTR(r0, r0, 16);
+ }
+ } else {
+ generic_bswapr_ui(_jit, r0, r1);
+ }
}
-# endif
static void
_extr_c(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
static void
_extr_ui(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
- lshi(r0, r1, 32);
- rshi_u(r0, r0, 32);
+ if (jit_mips2_p())
+ DEXT(r0, r1, 0, 32);
+ else {
+ lshi(r0, r1, 32);
+ rshi_u(r0, r0, 32);
+ }
}
# endif
{
jit_int32_t reg;
- if (i0 == 0) {
- SLT(r0, _ZERO_REGNO, r1);
- XORI(r0, r0, 1);
- }
+ if (can_sign_extend_short_p(i0 + 1))
+ SLTI(r0, r1, i0 + 1);
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
{
jit_int32_t reg;
- if (i0 == 0) {
- SLTU(r0, _ZERO_REGNO, r1);
- XORI(r0, r0, 1);
- }
+ if (can_sign_extend_short_p(i0 + 1))
+ SLTIU(r0, r1, i0 + 1);
else {
reg = jit_get_reg(jit_class_gpr);
movi(rn(reg), i0);
{
jit_int32_t reg;
- reg = jit_get_reg(jit_class_gpr);
- movi(rn(reg), i0);
- ger(r0, r1, rn(reg));
- jit_unget_reg(reg);
+ if (can_sign_extend_short_p(i0)) {
+ SLTI(r0, r1, i0);
+ XORI(r0, r0, 1);
+ } else {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), i0);
+ ger(r0, r1, rn(reg));
+ jit_unget_reg(reg);
+ }
}
static void
{
jit_int32_t reg;
- reg = jit_get_reg(jit_class_gpr);
- movi(rn(reg), i0);
- ger_u(r0, r1, rn(reg));
- jit_unget_reg(reg);
+ if (can_sign_extend_short_p(i0)) {
+ SLTIU(r0, r1, i0);
+ XORI(r0, r0, 1);
+ } else {
+ reg = jit_get_reg(jit_class_gpr);
+ movi(rn(reg), i0);
+ ger_u(r0, r1, rn(reg));
+ jit_unget_reg(reg);
+ }
}
static void
jit_word_t w;
jit_int32_t t0;
t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
- if (can_zero_extend_short_p(i1)) {
- ANDI(rn(t0), r0, i1);
- w = _jit->pc.w;
- BNE(_ZERO_REGNO, rn(t0), ((i0 - w) >> 2) - 1);
- NOP(1);
- }
- else {
- movi(rn(t0), i1);
- w = bmsr(i0, r0, rn(t0));
- }
+
+ andi(rn(t0), r0, i1);
+ w = _jit->pc.w;
+ BNE(_ZERO_REGNO, rn(t0), ((i0 - w) >> 2) - 1);
+ NOP(1);
+
jit_unget_reg(t0);
return (w);
}
jit_word_t w;
jit_int32_t t0;
t0 = jit_get_reg(jit_class_gpr|jit_class_nospill);
- if (can_zero_extend_short_p(i1)) {
- ANDI(rn(t0), r0, i1);
- w = _jit->pc.w;
- BEQ(_ZERO_REGNO, rn(t0), ((i0 - w) >> 2) - 1);
- NOP(1);
- }
- else {
- movi(rn(t0), i1);
- w = bmcr(i0, r0, rn(t0));
- }
+
+ andi(rn(t0), r0, i1);
+ w = _jit->pc.w;
+ BEQ(_ZERO_REGNO, rn(t0), ((i0 - w) >> 2) - 1);
+ NOP(1);
+
jit_unget_reg(t0);
return (w);
}
static void
_callr(jit_state_t *_jit, jit_int32_t r0)
{
+ JALR(r0);
if (r0 != _T9_REGNO)
movr(_T9_REGNO, r0);
- JALR(r0);
- NOP(1);
+ else
+ NOP(1);
}
static void