mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 16:40:27 +00:00
Port some cfunctions in math.c to corelib as
assembled functions.
This commit is contained in:
parent
423ebc937a
commit
b860b0a3c5
@ -150,6 +150,9 @@ static DstSlot do_rshift(DstFopts opts, DstSlot *args) {
|
||||
static DstSlot do_rshiftu(DstFopts opts, DstSlot *args) {
|
||||
return opreduce(opts, args, DOP_SHIFT_RIGHT, dst_wrap_integer(1));
|
||||
}
|
||||
static DstSlot do_bnot(DstFopts opts, DstSlot *args) {
|
||||
return genericSS(opts, DOP_BNOT, args[0]);
|
||||
}
|
||||
|
||||
/* Arranged by tag */
|
||||
static const DstFunOptimizer optimizers[] = {
|
||||
@ -170,7 +173,8 @@ static const DstFunOptimizer optimizers[] = {
|
||||
{NULL, do_bxor},
|
||||
{NULL, do_lshift},
|
||||
{NULL, do_rshift},
|
||||
{NULL, do_rshiftu}
|
||||
{NULL, do_rshiftu},
|
||||
{fixarity1, do_bnot}
|
||||
};
|
||||
|
||||
const DstFunOptimizer *dstc_funopt(uint32_t flags) {
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define DST_FUN_LSHIFT 16
|
||||
#define DST_FUN_RSHIFT 17
|
||||
#define DST_FUN_RSHIFTU 18
|
||||
#define DST_FUN_BNOT 19
|
||||
|
||||
/* Compiler typedefs */
|
||||
typedef struct DstCompiler DstCompiler;
|
||||
|
@ -344,57 +344,11 @@ static void dst_quick_asm(
|
||||
}
|
||||
|
||||
/* Macros for easier inline dst assembly */
|
||||
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
|
||||
#define SS(op, a, b) (op | (a << 8) | (b << 16))
|
||||
#define SSI(op, a, b, I) (op | (a << 8) | (b << 16) | ((uint32_t)(I) << 24))
|
||||
#define S(op, a) (op | (a << 8))
|
||||
#define SI(op, a, I) (op | (a << 8) | ((uint32_t)(I) << 16))
|
||||
|
||||
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
||||
/* Reg 0: Argument tuple (args) */
|
||||
/* Reg 1: Argument count (argn) */
|
||||
/* Reg 2: Jump flag (jump?) */
|
||||
/* Reg 3: Accumulator (accum) */
|
||||
/* Reg 4: Next operand (operand) */
|
||||
/* Reg 5: Loop iterator (i) */
|
||||
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
|
||||
SS(DOP_LENGTH, 1, 0), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||
|
||||
/* Check nullary */
|
||||
SSS(DOP_EQUALS_IMMEDIATE, 2, 1, 0), /* Check if numargs equal to 0 */
|
||||
SI(DOP_JUMP_IF_NOT, 2, 3), /* If not 0, jump to next check */
|
||||
/* Nullary */
|
||||
SI(DOP_LOAD_INTEGER, 3, 0), /* accum = nullary value */
|
||||
S(DOP_RETURN, 3), /* return accum */
|
||||
|
||||
/* Check unary */
|
||||
SSI(DOP_EQUALS_IMMEDIATE, 2, 1, 1), /* Check if numargs equal to 1 */
|
||||
SI(DOP_JUMP_IF_NOT, 2, 5), /* If not 1, jump to next check */
|
||||
/* Unary */
|
||||
S(DOP_LOAD_INTEGER, 3), /* accum = unary value */
|
||||
SSI(DOP_GET_INDEX, 4, 0, 0), /* operand = args[0] */
|
||||
SSS(DOP_NOOP, 3, 3, 4), /* accum = accum op operand */
|
||||
S(DOP_RETURN, 3), /* return accum */
|
||||
|
||||
/* Mutli (2 or more) arity */
|
||||
/* Prime loop */
|
||||
SSI(DOP_GET_INDEX, 3, 0, 0), /* accum = args[0] */
|
||||
SI(DOP_LOAD_INTEGER, 5, 1), /* i = 1 */
|
||||
/* Main loop */
|
||||
SSS(DOP_GET, 4, 0, 5), /* operand = args[i] */
|
||||
SSS(DOP_NOOP, 3, 3, 4), /* accum = accum op operand */
|
||||
SSI(DOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */
|
||||
SSI(DOP_EQUALS_INTEGER, 2, 5, 1), /* jump? = (i == argn) */
|
||||
SI(DOP_JUMP_IF_NOT, 2, -4), /* if not jump? go back 4 */
|
||||
|
||||
/* Done, do last and return accumulator */
|
||||
S(DOP_RETURN, 3) /* return accum */
|
||||
};
|
||||
|
||||
#define VAROP_NULLARY_LOC 3
|
||||
#define VAROP_UNARY_LOC 7
|
||||
#define VAROP_OP_LOC1 9
|
||||
#define VAROP_OP_LOC2 14
|
||||
#define SSS(op, a, b, c) ((op) | ((a) << 8) | ((b) << 16) | ((c) << 24))
|
||||
#define SS(op, a, b) ((op) | ((a) << 8) | ((b) << 16))
|
||||
#define SSI(op, a, b, I) ((op) | ((a) << 8) | ((b) << 16) | ((uint32_t)(I) << 24))
|
||||
#define S(op, a) ((op) | ((a) << 8))
|
||||
#define SI(op, a, I) ((op) | ((a) << 8) | ((uint32_t)(I) << 16))
|
||||
|
||||
/* Templatize a varop */
|
||||
static void templatize_varop(
|
||||
@ -404,10 +358,48 @@ static void templatize_varop(
|
||||
int32_t nullary,
|
||||
int32_t unary,
|
||||
uint32_t op) {
|
||||
varop_asm[VAROP_NULLARY_LOC] = SS(DOP_LOAD_INTEGER, 3, nullary);
|
||||
varop_asm[VAROP_UNARY_LOC] = SS(DOP_LOAD_INTEGER, 3, unary);
|
||||
varop_asm[VAROP_OP_LOC1] = SSS(op, 3, 3, 4);
|
||||
varop_asm[VAROP_OP_LOC2] = SSS(op, 3, 3, 4);
|
||||
|
||||
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
||||
/* Reg 0: Argument tuple (args) */
|
||||
/* Reg 1: Argument count (argn) */
|
||||
/* Reg 2: Jump flag (jump?) */
|
||||
/* Reg 3: Accumulator (accum) */
|
||||
/* Reg 4: Next operand (operand) */
|
||||
/* Reg 5: Loop iterator (i) */
|
||||
uint32_t varop_asm[] = {
|
||||
SS(DOP_LENGTH, 1, 0), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||
|
||||
/* Check nullary */
|
||||
SSS(DOP_EQUALS_IMMEDIATE, 2, 1, 0), /* Check if numargs equal to 0 */
|
||||
SI(DOP_JUMP_IF_NOT, 2, 3), /* If not 0, jump to next check */
|
||||
/* Nullary */
|
||||
SI(DOP_LOAD_INTEGER, 3, nullary), /* accum = nullary value */
|
||||
S(DOP_RETURN, 3), /* return accum */
|
||||
|
||||
/* Check unary */
|
||||
SSI(DOP_EQUALS_IMMEDIATE, 2, 1, 1), /* Check if numargs equal to 1 */
|
||||
SI(DOP_JUMP_IF_NOT, 2, 5), /* If not 1, jump to next check */
|
||||
/* Unary */
|
||||
SI(DOP_LOAD_INTEGER, 3, unary), /* accum = unary value */
|
||||
SSI(DOP_GET_INDEX, 4, 0, 0), /* operand = args[0] */
|
||||
SSS(op, 3, 3, 4), /* accum = accum op operand */
|
||||
S(DOP_RETURN, 3), /* return accum */
|
||||
|
||||
/* Mutli (2 or more) arity */
|
||||
/* Prime loop */
|
||||
SSI(DOP_GET_INDEX, 3, 0, 0), /* accum = args[0] */
|
||||
SI(DOP_LOAD_INTEGER, 5, 1), /* i = 1 */
|
||||
/* Main loop */
|
||||
SSS(DOP_GET, 4, 0, 5), /* operand = args[i] */
|
||||
SSS(op, 3, 3, 4), /* accum = accum op operand */
|
||||
SSI(DOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */
|
||||
SSI(DOP_EQUALS_INTEGER, 2, 5, 1), /* jump? = (i == argn) */
|
||||
SI(DOP_JUMP_IF_NOT, 2, -4), /* if not jump? go back 4 */
|
||||
|
||||
/* Done, do last and return accumulator */
|
||||
S(DOP_RETURN, 3) /* return accum */
|
||||
};
|
||||
|
||||
dst_quick_asm(
|
||||
env,
|
||||
flags | DST_FUNCDEF_FLAG_VARARG,
|
||||
@ -418,38 +410,93 @@ static void templatize_varop(
|
||||
sizeof(varop_asm));
|
||||
}
|
||||
|
||||
/* Templatize variadic comparators */
|
||||
static void templatize_comparator(
|
||||
DstTable *env,
|
||||
int32_t flags,
|
||||
const char *name,
|
||||
int invert,
|
||||
uint32_t op) {
|
||||
|
||||
/* Reg 0: Argument tuple (args) */
|
||||
/* Reg 1: Argument count (argn) */
|
||||
/* Reg 2: Jump flag (jump?) */
|
||||
/* Reg 3: Last value (last) */
|
||||
/* Reg 4: Next operand (next) */
|
||||
/* Reg 5: Loop iterator (i) */
|
||||
uint32_t comparator_asm[] = {
|
||||
SS(DOP_LENGTH, 1, 0), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||
SSS(DOP_LESS_THAN_IMMEDIATE, 2, 1, 2), /* Check if numargs less than 2 */
|
||||
SI(DOP_JUMP_IF, 2, 10), /* If numargs < 2, jump to done */
|
||||
|
||||
/* Prime loop */
|
||||
SSI(DOP_GET_INDEX, 3, 0, 0), /* last = args[0] */
|
||||
SI(DOP_LOAD_INTEGER, 5, 1), /* i = 1 */
|
||||
|
||||
/* Main loop */
|
||||
SSS(DOP_GET, 4, 0, 5), /* next = args[i] */
|
||||
SSS(op, 2, 3, 4), /* jump? = last compare next */
|
||||
SI(DOP_JUMP_IF_NOT, 2, 7), /* if not jump? goto fail (return false) */
|
||||
SSI(DOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */
|
||||
SS(DOP_MOVE_NEAR, 3, 4), /* last = next */
|
||||
SSI(DOP_EQUALS_INTEGER, 2, 5, 1), /* jump? = (i == argn) */
|
||||
SI(DOP_JUMP_IF_NOT, 2, -6), /* if not jump? go back 6 */
|
||||
|
||||
/* Done, return true */
|
||||
S(invert ? DOP_LOAD_FALSE : DOP_LOAD_TRUE, 3),
|
||||
S(DOP_RETURN, 3),
|
||||
|
||||
/* Failed, return false */
|
||||
S(invert ? DOP_LOAD_TRUE : DOP_LOAD_FALSE, 3),
|
||||
S(DOP_RETURN, 3)
|
||||
};
|
||||
|
||||
dst_quick_asm(
|
||||
env,
|
||||
flags | DST_FUNCDEF_FLAG_VARARG,
|
||||
name,
|
||||
0,
|
||||
6,
|
||||
comparator_asm,
|
||||
sizeof(comparator_asm));
|
||||
}
|
||||
|
||||
DstTable *dst_core_env(void) {
|
||||
static uint32_t error_asm[] = {
|
||||
static const uint32_t error_asm[] = {
|
||||
DOP_ERROR
|
||||
};
|
||||
static uint32_t apply_asm[] = {
|
||||
static const uint32_t apply_asm[] = {
|
||||
DOP_PUSH_ARRAY | (1 << 8),
|
||||
DOP_TAILCALL
|
||||
};
|
||||
static uint32_t debug_asm[] = {
|
||||
static const uint32_t debug_asm[] = {
|
||||
DOP_SIGNAL | (2 << 24),
|
||||
DOP_RETURN_NIL
|
||||
};
|
||||
static uint32_t yield_asm[] = {
|
||||
static const uint32_t yield_asm[] = {
|
||||
DOP_SIGNAL | (3 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t resume_asm[] = {
|
||||
static const uint32_t resume_asm[] = {
|
||||
DOP_RESUME | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t get_asm[] = {
|
||||
static const uint32_t get_asm[] = {
|
||||
DOP_GET | (1 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t put_asm[] = {
|
||||
static const uint32_t put_asm[] = {
|
||||
DOP_PUT | (1 << 16) | (2 << 24),
|
||||
DOP_RETURN
|
||||
};
|
||||
static uint32_t length_asm[] = {
|
||||
static const uint32_t length_asm[] = {
|
||||
DOP_LENGTH,
|
||||
DOP_RETURN
|
||||
};
|
||||
static const uint32_t bnot_asm[] = {
|
||||
DOP_BNOT,
|
||||
DOP_RETURN
|
||||
};
|
||||
|
||||
DstTable *env = dst_table(0);
|
||||
Dst ret = dst_wrap_table(env);
|
||||
@ -465,6 +512,7 @@ DstTable *dst_core_env(void) {
|
||||
dst_quick_asm(env, DST_FUN_GET, "get", 2, 2, get_asm, sizeof(get_asm));
|
||||
dst_quick_asm(env, DST_FUN_PUT, "put", 3, 3, put_asm, sizeof(put_asm));
|
||||
dst_quick_asm(env, DST_FUN_LENGTH, "length", 1, 1, length_asm, sizeof(length_asm));
|
||||
dst_quick_asm(env, DST_FUN_BNOT, "~", 1, 1, bnot_asm, sizeof(bnot_asm));
|
||||
|
||||
/* Variadic ops */
|
||||
templatize_varop(env, DST_FUN_ADD, "+", 0, 0, DOP_ADD);
|
||||
@ -478,6 +526,14 @@ DstTable *dst_core_env(void) {
|
||||
templatize_varop(env, DST_FUN_RSHIFT, ">>", 1, 1, DOP_SHIFT_RIGHT);
|
||||
templatize_varop(env, DST_FUN_RSHIFTU, ">>>", 1, 1, DOP_SHIFT_RIGHT_UNSIGNED);
|
||||
|
||||
/* Variadic comparators */
|
||||
templatize_comparator(env, 0, "order>", 0, DOP_GREATER_THAN);
|
||||
templatize_comparator(env, 0, "order<", 0, DOP_LESS_THAN);
|
||||
templatize_comparator(env, 0, "order>=", 1, DOP_LESS_THAN);
|
||||
templatize_comparator(env, 0, "order<=", 1, DOP_GREATER_THAN);
|
||||
templatize_comparator(env, 0, "=", 0, DOP_EQUALS);
|
||||
templatize_comparator(env, 0, "not=", 1, DOP_EQUALS);
|
||||
|
||||
dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION));
|
||||
|
||||
/* Set as gc root */
|
||||
|
@ -71,19 +71,6 @@ int dst_real(DstArgs args) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_bnot(DstArgs args) {
|
||||
if (args.n != 1) {
|
||||
*args.ret = dst_cstringv("expected 1 argument");
|
||||
return 1;
|
||||
}
|
||||
if (!dst_checktype(args.v[0], DST_INTEGER)) {
|
||||
*args.ret = dst_cstringv("expected integer");
|
||||
return 1;
|
||||
}
|
||||
*args.ret = dst_wrap_integer(~dst_unwrap_integer(args.v[0]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_remainder(DstArgs args) {
|
||||
DST_FIXARITY(args, 2);
|
||||
if (dst_checktype(args.v[0], DST_INTEGER) &&
|
||||
@ -137,44 +124,6 @@ int dst_##name(DstArgs args) {\
|
||||
DST_DEFINE_MATH2OP(atan2, atan2)
|
||||
DST_DEFINE_MATH2OP(pow, pow)
|
||||
|
||||
/* Comparison */
|
||||
#define DST_DEFINE_COMPARATOR(name, pred)\
|
||||
static int dst_##name(DstArgs args) {\
|
||||
int32_t i;\
|
||||
for (i = 0; i < args.n - 1; i++) {\
|
||||
if (dst_compare(args.v[i], args.v[i+1]) pred) {\
|
||||
DST_RETURN_FALSE(args);\
|
||||
}\
|
||||
}\
|
||||
DST_RETURN_TRUE(args);\
|
||||
}
|
||||
|
||||
DST_DEFINE_COMPARATOR(ascending, >= 0)
|
||||
DST_DEFINE_COMPARATOR(descending, <= 0)
|
||||
DST_DEFINE_COMPARATOR(notdescending, > 0)
|
||||
DST_DEFINE_COMPARATOR(notascending, < 0)
|
||||
|
||||
/* Boolean logic */
|
||||
static int dst_strict_equal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (!dst_equals(args.v[i], args.v[i+1])) {
|
||||
DST_RETURN_FALSE(args);
|
||||
}
|
||||
}
|
||||
DST_RETURN_TRUE(args);
|
||||
}
|
||||
|
||||
static int dst_strict_notequal(DstArgs args) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n - 1; i++) {
|
||||
if (!dst_equals(args.v[i], args.v[i+1])) {
|
||||
DST_RETURN_TRUE(args);
|
||||
}
|
||||
}
|
||||
DST_RETURN_FALSE(args);
|
||||
}
|
||||
|
||||
static int dst_not(DstArgs args) {
|
||||
DST_FIXARITY(args, 1);
|
||||
DST_RETURN_BOOLEAN(args, !dst_truthy(args.v[0]));
|
||||
@ -203,19 +152,12 @@ DEF_NUMERIC_COMP(neq, !=)
|
||||
|
||||
static const DstReg cfuns[] = {
|
||||
{"%", dst_remainder},
|
||||
{"=", dst_strict_equal},
|
||||
{"not=", dst_strict_notequal},
|
||||
{"order<", dst_ascending},
|
||||
{"order>", dst_descending},
|
||||
{"order<=", dst_notdescending},
|
||||
{"order>=", dst_notascending},
|
||||
{"==", dst_numeric_eq},
|
||||
{"not==", dst_numeric_neq},
|
||||
{"<", dst_numeric_lt},
|
||||
{">", dst_numeric_gt},
|
||||
{"<=", dst_numeric_lte},
|
||||
{">=", dst_numeric_gte},
|
||||
{"~", dst_bnot},
|
||||
{"not", dst_not},
|
||||
{"int", dst_int},
|
||||
{"real", dst_real},
|
||||
|
@ -385,6 +385,7 @@ static void *op_lookup[255] = {
|
||||
|
||||
VM_OP(DOP_BNOT)
|
||||
stack[oparg(1, 0xFF)] = dst_wrap_integer(~dst_unwrap_integer(stack[oparg(2, 0xFFFF)]));
|
||||
++pc;
|
||||
vm_next();
|
||||
|
||||
VM_OP(DOP_SHIFT_RIGHT_UNSIGNED)
|
||||
|
Loading…
Reference in New Issue
Block a user