/*
- * Copyright (C) 2013-2022 Free Software Foundation, Inc.
+ * Copyright (C) 2013-2023 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
static void _f3a(jit_state_t*,jit_int32_t,
jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t)
maybe_unused;
+# define f2c1(op,rd,op3,rs1,opf,rs2) _f2c1(_jit,op,rd,op3,rs1,opf,rs2)
+static void
+_f2c1(jit_state_t*,jit_int32_t, jit_int32_t,
+ jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t)
+ maybe_unused;
# define LDSB(rs1, rs2, rd) f3r(3, rd, 9, rs1, rs2)
# define LDSBI(rs1, imm, rd) f3i(3, rd, 9, rs1, imm)
# define LDSH(rs1, rs2, rd) f3r(3, rd, 10, rs1, rs2)
# define UNIMP(imm) f2r(0, 0, 0, imm)
# define FLUSH(rs1, rs2) f3r(2, 0, 59, rs1, rs2)
# define FLUSHI(rs1, im) f3i(2, 0, 59, rs1, imm)
+# define LZCNT(rs2, rd) f2c1(2, rd, 54, 0, 23, rs2)
# define nop(i0) _nop(_jit, i0)
static void _nop(jit_state_t*, jit_int32_t);
# define movr(r0, r1) _movr(_jit, r0, r1)
#define casi(r0, i0, r1, r2) casx(r0, _NOREG, r1, r2, i0)
# define comr(r0, r1) XNOR(r1, 0, r0)
# define negr(r0, r1) NEG(r1, r0)
+# define bitswap(r0, r1) _bitswap(_jit, r0, r1)
+static void _bitswap(jit_state_t*, jit_int32_t, jit_int32_t);
+# define clor(r0, r1) _clor(_jit, r0, r1)
+static void _clor(jit_state_t*, jit_int32_t, jit_int32_t);
+# define clzr(r0, r1) _clzr(_jit, r0, r1)
+static void _clzr(jit_state_t*, jit_int32_t, jit_int32_t);
+# define ctor(r0, r1) _ctor(_jit, r0, r1)
+static void _ctor(jit_state_t*, jit_int32_t, jit_int32_t);
+# define ctzr(r0, r1) _ctzr(_jit, r0, r1)
+static void _ctzr(jit_state_t*, jit_int32_t, jit_int32_t);
# define addr(r0, r1, r2) ADD(r1, r2, r0)
# 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 jmpr(r0) _jmpr(_jit, r0)
static void _jmpr(jit_state_t*,jit_int32_t);
# define jmpi(i0) _jmpi(_jit, i0)
-static void _jmpi(jit_state_t*,jit_word_t);
+static jit_word_t _jmpi(jit_state_t*,jit_word_t);
# define jmpi_p(i0) _jmpi_p(_jit, i0)
static jit_word_t _jmpi_p(jit_state_t*,jit_word_t);
# define callr(r0) _callr(_jit, r0)
static void _callr(jit_state_t*,jit_int32_t);
# define calli(i0) _calli(_jit, i0)
-static void _calli(jit_state_t*,jit_word_t);
+static jit_word_t _calli(jit_state_t*,jit_word_t);
# define calli_p(i0) _calli_p(_jit, i0)
static jit_word_t _calli_p(jit_state_t*,jit_word_t);
# define prolog(node) _prolog(_jit, node)
ii(v.v);
}
+static void
+_f2c1(jit_state_t *_jit, jit_int32_t op, jit_int32_t rd,
+ jit_int32_t op3, jit_int32_t rs1, jit_int32_t opf, jit_int32_t rs2)
+{
+ jit_instr_t v;
+ assert(!(op & 0xfffffffc));
+ assert(!(rd & 0xffffffe0));
+ assert(!(res & 0xffffffc0));
+ assert(!(rs1 & 0xffffffe0));
+ assert(!(opf & 0xfffffe00));
+ assert(!(rs2 & 0xfffffe00));
+ v.op.b = op;
+ v.rd.b = rd;
+ v.op3.b = op3;
+ v.rs1.b = rs1;
+ v.opf.b = opf;
+ v.rs2.b = rs2;
+ ii(v.v);
+}
+
static void
_nop(jit_state_t *_jit, jit_int32_t i0)
{
jit_unget_reg(r1_reg);
}
+static void
+_bitswap(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ jit_int32_t t0, t1, t2, t3, t4;
+ movr(r0, r1);
+ t0 = jit_get_reg(jit_class_gpr);
+ t1 = jit_get_reg(jit_class_gpr);
+ t2 = jit_get_reg(jit_class_gpr);
+ movi(rn(t0), __WORDSIZE == 32 ? 0x55555555L : 0x5555555555555555L);
+ rshi_u(rn(t1), r0, 1); /* t1 = v >> 1 */
+ andr(rn(t1), rn(t1), rn(t0)); /* t1 &= t0 */
+ andr(rn(t2), r0, rn(t0)); /* t2 = v & t0*/
+ lshi(rn(t2), rn(t2), 1); /* t2 <<= 1 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+ movi(rn(t0), __WORDSIZE == 32 ? 0x33333333L : 0x3333333333333333L);
+ rshi_u(rn(t1), r0, 2); /* t1 = v >> 2 */
+ andr(rn(t1), rn(t1), rn(t0)); /* t1 &= t0 */
+ andr(rn(t2), r0, rn(t0)); /* t2 = v & t0*/
+ lshi(rn(t2), rn(t2), 2); /* t2 <<= 2 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+ movi(rn(t0), __WORDSIZE == 32 ? 0x0f0f0f0fL : 0x0f0f0f0f0f0f0f0fL);
+ rshi_u(rn(t1), r0, 4); /* t1 = v >> 4 */
+ andr(rn(t1), rn(t1), rn(t0)); /* t1 &= t0 */
+ andr(rn(t2), r0, rn(t0)); /* t2 = v & t0*/
+ lshi(rn(t2), rn(t2), 4); /* t2 <<= 4 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+ movi(rn(t0), __WORDSIZE == 32 ? 0x00ff00ffL : 0x00ff00ff00ff00ffL);
+ rshi_u(rn(t1), r0, 8); /* t1 = v >> 8 */
+ andr(rn(t1), rn(t1), rn(t0)); /* t1 &= t0 */
+ andr(rn(t2), r0, rn(t0)); /* t2 = v & t0*/
+ lshi(rn(t2), rn(t2), 8); /* t2 <<= 8 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+# if __WORDSIZE == 32
+ rshi_u(rn(t1), r0, 16); /* t1 = v >> 16 */
+ lshi(rn(t2), r0, 16); /* t2 = v << 16 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+# else
+ movi(rn(t0), 0x0000ffff0000ffffL);
+ rshi_u(rn(t1), r0, 16); /* t1 = v >> 16 */
+ andr(rn(t1), rn(t1), rn(t0)); /* t1 &= t0 */
+ andr(rn(t2), r0, rn(t0)); /* t2 = v & t0*/
+ lshi(rn(t2), rn(t2), 16); /* t2 <<= 16 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+ rshi_u(rn(t1), r0, 32); /* t1 = v >> 32 */
+ lshi(rn(t2), r0, 32); /* t2 = v << 32 */
+ orr(r0, rn(t1), rn(t2)); /* v = t1 | t2 */
+# endif
+ jit_unget_reg(t2);
+ jit_unget_reg(t1);
+ jit_unget_reg(t0);
+}
+
+static void
+_clor(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ if (jit_cpu.lzcnt) {
+ comr(r0, r1);
+ clzr(r0, r0);
+ }
+ else
+ fallback_clo(r0, r1);
+}
+
+static void
+_clzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ if (jit_cpu.lzcnt) {
+#if __WORDSIZE == 32
+ jit_word_t w;
+ SLLXI(r1, 32, r0);
+ LZCNT(r0, r0);
+#if __WORDSIZE == 32
+ w = blei(_jit->pc.w, r0, 31);
+ rshi(r0, r0, 1); /* r0 is 64 */
+ patch_at(w, _jit->pc.w);
+#endif
+#else
+ LZCNT(r1, r0);
+ }
+ else
+ fallback_clz(r0, r1);
+}
+
+static void
+_ctor(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ if (jit_cpu.lzcnt) {
+ bitswap(r0, r1);
+ clor(r0, r0);
+ }
+ else
+ fallback_cto(r0, r1);
+}
+
+static void
+_ctzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
+{
+ if (jit_cpu.lzcnt) {
+ bitswap(r0, r1);
+ clzr(r0, r0);
+ }
+ else
+ fallback_ctz(r0, r1);
+}
+
static void
_addi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
# if __WORDSIZE == 32
B(cc, (i0 - w) >> 2);
# else
- B(cc, (i0 - w) >> 2);
+ BP(cc, (i0 - w) >> 2);
# endif
NOP();
}
NOP();
}
-static void
+static jit_word_t
_jmpi(jit_state_t *_jit, jit_word_t i0)
{
- jit_word_t w;
jit_int32_t reg;
- w = (i0 - _jit->pc.w) >> 2;
- if (s22_p(w)) {
- BA(w);
+ jit_word_t d, w;
+ w = _jit->pc.w;
+ d = (i0 - w) >> 2;
+ if (s22_p(d)) {
+ BA(d);
NOP();
}
else {
jmpr(rn(reg));
jit_unget_reg(reg);
}
+ return (w);
}
static jit_word_t
NOP();
}
-static void
+static jit_word_t
_calli(jit_state_t *_jit, jit_word_t i0)
{
- jit_word_t w;
- w = (i0 - _jit->pc.w) >> 2;
- if (s30_p(w)) {
- CALLI(w);
+ jit_word_t d, w;
+ w = _jit->pc.w;
+ d = (i0 - w) >> 2;
+ if (s30_p(d)) {
+ CALLI(d);
NOP();
}
else
- (void)calli_p(i0);
+ w = calli_p(i0);
+ return (w);
}
static jit_word_t
{
if (_jitc->function->assume_frame)
return;
- /* (most) other backends do not save incoming arguments, so,
- * only save locals here */
+ if (_jitc->function->allocar)
+ subi(_SP_REGNO, _FP_REGNO, _jitc->function->stack);
if (jit_regset_tstbit(&_jitc->function->regset, _L0))
- ldxi(_L0_REGNO, _FP_REGNO, _jitc->function->stack + OFF(0));
+ ldxi(_L0_REGNO, _SP_REGNO, _jitc->function->stack + OFF(0));
if (jit_regset_tstbit(&_jitc->function->regset, _L1))
- ldxi(_L1_REGNO, _FP_REGNO, _jitc->function->stack + OFF(1));
+ ldxi(_L1_REGNO, _SP_REGNO, _jitc->function->stack + OFF(1));
if (jit_regset_tstbit(&_jitc->function->regset, _L2))
- ldxi(_L2_REGNO, _FP_REGNO, _jitc->function->stack + OFF(2));
+ ldxi(_L2_REGNO, _SP_REGNO, _jitc->function->stack + OFF(2));
if (jit_regset_tstbit(&_jitc->function->regset, _L3))
- ldxi(_L3_REGNO, _FP_REGNO, _jitc->function->stack + OFF(3));
+ ldxi(_L3_REGNO, _SP_REGNO, _jitc->function->stack + OFF(3));
if (jit_regset_tstbit(&_jitc->function->regset, _L4))
- ldxi(_L4_REGNO, _FP_REGNO, _jitc->function->stack + OFF(4));
+ ldxi(_L4_REGNO, _SP_REGNO, _jitc->function->stack + OFF(4));
if (jit_regset_tstbit(&_jitc->function->regset, _L5))
- ldxi(_L5_REGNO, _FP_REGNO, _jitc->function->stack + OFF(5));
+ ldxi(_L5_REGNO, _SP_REGNO, _jitc->function->stack + OFF(5));
if (jit_regset_tstbit(&_jitc->function->regset, _L6))
- ldxi(_L6_REGNO, _FP_REGNO, _jitc->function->stack + OFF(6));
+ ldxi(_L6_REGNO, _SP_REGNO, _jitc->function->stack + OFF(6));
if (jit_regset_tstbit(&_jitc->function->regset, _L7))
- ldxi(_L7_REGNO, _FP_REGNO, _jitc->function->stack + OFF(7));
+ ldxi(_L7_REGNO, _SP_REGNO, _jitc->function->stack + OFF(7));
RESTOREI(0, 0, 0);
RETL();
NOP();
else
abort();
}
+ else if (i.op.b == 1) {
+ assert(s30_p((label - instr) >> 2));
+ i.disp30.b = (label - instr) >> 2;
+ u.i[0] = i.v;
+ }
else
abort();
}