libclosure/lightning/fp-common.h
2004-08-18 12:59:40 +00:00

261 lines
9.5 KiB
C

/******************************** -*- C -*- ****************************
*
* Platform-independent layer floating-point interface
*
***********************************************************************/
/***********************************************************************
*
* Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
* Written by Paolo Bonzini.
*
* This file is part of GNU lightning.
*
* GNU lightning is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1, or (at your option)
* any later version.
*
* GNU lightning is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
* Free Software Foundation, 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*
***********************************************************************/
struct jit_fp {
char kind;
char subkind;
union {
struct {
int displ;
char reg1;
char reg2;
} addr;
union {
double number;
long split[sizeof(double) / sizeof(long)];
} imm;
struct {
struct jit_fp *lhs, *rhs;
} ops;
} d;
};
#ifdef jit_trunc
enum { JIT_NULL, /* unused */
JIT_CMP, JIT_FLOOR, JIT_CEIL, JIT_ROUND, JIT_TRUNC, /* integer */
JIT_XI, JIT_ADD, JIT_XR, JIT_SUB, /* subkinds */
JIT_I, JIT_MUL, JIT_R, JIT_DIV,
JIT_INT,
JIT_ABS, JIT_SIN, JIT_COS, JIT_TAN, JIT_ATN, /* functions */
JIT_EXP, JIT_LOG, JIT_NEG, JIT_SQRT,
JIT_OP, JIT_FN, JIT_LD, JIT_IMM }; /* kinds */
/* Declarations */
static void _jit_emit(jit_state *, struct jit_fp *,
int, int, int, int) JIT_UNUSED;
static struct jit_fp *_jit_op(struct jit_fp *, int,
struct jit_fp *, struct jit_fp *) JIT_UNUSED;
static struct jit_fp *_jit_ld(struct jit_fp *, int,
int, int) JIT_UNUSED;
static struct jit_fp *_jit_fn(struct jit_fp *, int,
struct jit_fp *) JIT_UNUSED;
static struct jit_fp *_jit_imm(struct jit_fp *, double) JIT_UNUSED;
/* Internal function to walk the tree */
void
_jit_emit(jit_state *jit, struct jit_fp *head,
int store_kind, int store1, int store2, int reg0)
{
#define _jit (*jit)
switch (head->kind) {
case JIT_OP:
_jit_emit(jit, head->d.ops.lhs, JIT_NULL, 0, 0, reg0);
_jit_emit(jit, head->d.ops.rhs, JIT_NULL, 0, 0, reg0 + 1);
switch (head->subkind) {
case JIT_ADD: jit_add_two(reg0); break;
case JIT_SUB: jit_sub_two(reg0); break;
case JIT_MUL: jit_mul_two(reg0); break;
case JIT_DIV: jit_div_two(reg0); break;
}
break;
case JIT_IMM:
#ifdef JIT_LONG_IS_INT
jit_fpimm(reg0, head->d.imm.split[0], head->d.imm.split[1]);
#else
jit_fpimm(reg0, head->d.imm.split[0]);
#endif
break;
case JIT_FN:
_jit_emit(jit, head->d.ops.lhs, JIT_NULL, 0, 0, reg0);
switch (head->subkind) {
case JIT_ABS: jit_abs(reg0); break;
#ifdef JIT_TRANSCENDENTAL
case JIT_SIN: jit_sin(reg0); break;
case JIT_SQRT: jit_sqrt(reg0); break;
case JIT_COS: jit_cos(reg0); break;
case JIT_TAN: jit_tan(reg0); break;
case JIT_ATN: jit_atn(reg0); break;
case JIT_EXP: jit_exp(reg0); break;
case JIT_LOG: jit_log(reg0); break;
case JIT_NEG: jit_neg(reg0); break;
#endif
}
break;
case JIT_LD:
switch (head->subkind) {
case JIT_INT: jit_exti_d(reg0, head->d.addr.reg1); break;
case JIT_XI: jit_ldxi_f(reg0, head->d.addr.reg1, head->d.addr.displ); break;
case JIT_XR: jit_ldxr_f(reg0, head->d.addr.reg1, head->d.addr.reg2); break;
case JIT_XI | 1: jit_ldxi_d(reg0, head->d.addr.reg1, head->d.addr.displ); break;
case JIT_XR | 1: jit_ldxr_d(reg0, head->d.addr.reg1, head->d.addr.reg2); break;
#ifndef JIT_RZERO
case JIT_I: jit_ldi_f(reg0, head->d.addr.displ); break;
case JIT_R: jit_ldr_f(reg0, head->d.addr.reg1); break;
case JIT_I | 1: jit_ldi_d(reg0, head->d.addr.displ); break;
case JIT_R | 1: jit_ldr_d(reg0, head->d.addr.reg1); break;
#endif
}
break;
}
switch (store_kind) {
case JIT_FLOOR: jit_floor(store1, reg0); break;
case JIT_CEIL: jit_ceil(store1, reg0); break;
case JIT_TRUNC: jit_trunc(store1, reg0); break;
case JIT_ROUND: jit_round(store1, reg0); break;
case JIT_CMP: jit_cmp(store1, store2, reg0); break;
case JIT_XI: jit_stxi_f(store2, store1, reg0); break;
case JIT_XR: jit_stxr_f(store2, store1, reg0); break;
case JIT_XI | 1: jit_stxi_d(store2, store1, reg0); break;
case JIT_XR | 1: jit_stxr_d(store2, store1, reg0); break;
#ifndef JIT_RZERO
case JIT_I: jit_sti_f(store2, reg0); break;
case JIT_R: jit_str_f(store2, reg0); break;
case JIT_I | 1: jit_sti_d(store2, reg0); break;
case JIT_R | 1: jit_str_d(store2, reg0); break;
case JIT_NULL: break;
#endif
}
#undef _jit
}
/* Internal functions to build the tree */
struct jit_fp *
_jit_op(struct jit_fp *where, int which,
struct jit_fp *op1, struct jit_fp *op2)
{
where->kind = JIT_OP;
where->subkind = which;
where->d.ops.lhs = op1;
where->d.ops.rhs = op2;
return (where);
}
struct jit_fp *
_jit_ld(struct jit_fp *where, int which, int op1, int op2)
{
where->kind = JIT_LD;
where->subkind = which;
switch (which & ~1) {
case JIT_XI: where->d.addr.reg1 = op1;
case JIT_I: where->d.addr.displ = op2; break;
case JIT_XR: where->d.addr.reg2 = op2;
case JIT_INT:
case JIT_R: where->d.addr.reg1 = op1; break;
}
return (where);
}
struct jit_fp *
_jit_fn(struct jit_fp *where, int which, struct jit_fp *op1)
{
where->kind = JIT_FN;
where->subkind = which;
where->d.ops.lhs = op1;
return (where);
}
struct jit_fp *
_jit_imm(struct jit_fp *where, double number)
{
where->kind = JIT_IMM;
where->d.imm.number = number;
return (where);
}
#define jitfp_begin(buf) (_jit.fp = (buf), --_jit.fp)
#define jitfp_add(op1, op2) _jit_op(++_jit.fp, JIT_ADD, (op1), (op2))
#define jitfp_sub(op1, op2) _jit_op(++_jit.fp, JIT_SUB, (op1), (op2))
#define jitfp_mul(op1, op2) _jit_op(++_jit.fp, JIT_MUL, (op1), (op2))
#define jitfp_div(op1, op2) _jit_op(++_jit.fp, JIT_DIV, (op1), (op2))
#define jitfp_imm(imm) _jit_imm(++_jit.fp, (imm))
#define jitfp_exti_d(reg1) _jit_ld(++_jit.fp, JIT_INT, (reg1), 0)
#define jitfp_ldxi_f(reg1, imm) _jit_ld(++_jit.fp, JIT_XI, (reg1), (long)(imm))
#define jitfp_ldxr_f(reg1, reg2) _jit_ld(++_jit.fp, JIT_XR, (reg1), (reg2))
#define jitfp_ldxi_d(reg1, imm) _jit_ld(++_jit.fp, JIT_XI | 1, (reg1), (long)(imm))
#define jitfp_ldxr_d(reg1, reg2) _jit_ld(++_jit.fp, JIT_XR | 1, (reg1), (reg2))
#define jitfp_abs(op1) _jit_fn(++_jit.fp, JIT_ABS, (op1))
#define jitfp_sqrt(op1) _jit_fn(++_jit.fp, JIT_SQRT, (op1))
#define jitfp_neg(op1) _jit_fn(++_jit.fp, JIT_NEG, (op1))
#define jitfp_stxi_f(imm, reg1, op1) _jit_emit(&_jit, (op1), JIT_XI, (reg1), (long)(imm), 0)
#define jitfp_stxr_f(reg1, reg2, op2) _jit_emit(&_jit, (op1), JIT_XR, (reg1), (reg2), 0)
#define jitfp_stxi_d(imm, reg1, op1) _jit_emit(&_jit, (op1), JIT_XI | 1, (reg1), (long)(imm), 0)
#define jitfp_stxr_d(reg1, reg2, op2) _jit_emit(&_jit, (op1), JIT_XR | 1, (reg1), (reg2), 0)
#define jitfp_cmp(regle, regge, op1) _jit_emit(&_jit, (op1), JIT_CMP, regle, regge, 0)
#define jitfp_floor(reg1, op1) _jit_emit(&_jit, (op1), JIT_FLOOR, reg1, 0, 0)
#define jitfp_ceil(reg1, op1) _jit_emit(&_jit, (op1), JIT_CEIL, reg1, 0, 0)
#define jitfp_trunc(reg1, op1) _jit_emit(&_jit, (op1), JIT_TRUNC, reg1, 0, 0)
#define jitfp_round(reg1, op1) _jit_emit(&_jit, (op1), JIT_ROUND, reg1, 0, 0)
#ifdef JIT_TRANSCENDENTAL
#define jitfp_sin(op1) _jit_fn(++_jit.fp, JIT_SIN, (op1))
#define jitfp_cos(op1) _jit_fn(++_jit.fp, JIT_COS, (op1))
#define jitfp_tan(op1) _jit_fn(++_jit.fp, JIT_TAN, (op1))
#define jitfp_atn(op1) _jit_fn(++_jit.fp, JIT_ATN, (op1))
#define jitfp_exp(op1) _jit_fn(++_jit.fp, JIT_EXP, (op1))
#define jitfp_log(op1) _jit_fn(++_jit.fp, JIT_LOG, (op1))
#endif
#ifdef JIT_RZERO
#define jitfp_ldi_f(imm) _jit_ld(++_jit.fp, JIT_XI, JIT_RZERO, (long)(imm))
#define jitfp_ldr_f(reg1) _jit_ld(++_jit.fp, JIT_XR, JIT_RZERO, (reg1))
#define jitfp_ldi_d(imm) _jit_ld(++_jit.fp, JIT_XI | 1, JIT_RZERO, (long)(imm))
#define jitfp_ldr_d(reg1) _jit_ld(++_jit.fp, JIT_XR | 1, JIT_RZERO, (reg1))
#define jitfp_sti_f(imm, op1) _jit_emit(&_jit, (op1), JIT_XI, JIT_RZERO, (long)(imm), 0)
#define jitfp_str_f(reg1, op1) _jit_emit(&_jit, (op1), JIT_XR, JIT_RZERO, (reg1), 0)
#define jitfp_sti_d(imm, op1) _jit_emit(&_jit, (op1), JIT_XI | 1, JIT_RZERO, (long)(imm), 0)
#define jitfp_str_d(reg1, op1) _jit_emit(&_jit, (op1), JIT_XR | 1, JIT_RZERO, (reg1), 0)
#else
#define jitfp_ldi_f(imm) _jit_ld(++_jit.fp, JIT_I, 0, (long)(imm))
#define jitfp_ldr_f(reg1) _jit_ld(++_jit.fp, JIT_R, 0, (reg1))
#define jitfp_ldi_d(imm) _jit_ld(++_jit.fp, JIT_I | 1, 0, (long)(imm))
#define jitfp_ldr_d(reg1) _jit_ld(++_jit.fp, JIT_R | 1, 0, (reg1))
#define jitfp_sti_f(imm, op1) _jit_emit(&_jit, (op1), JIT_I, 0, (long)(imm), 0)
#define jitfp_str_f(reg1, op1) _jit_emit(&_jit, (op1), JIT_R, 0, (reg1), 0)
#define jitfp_sti_d(imm, op1) _jit_emit(&_jit, (op1), JIT_I | 1, 0, (long)(imm), 0)
#define jitfp_str_d(reg1, op1) _jit_emit(&_jit, (op1), JIT_R | 1, 0, (reg1), 0)
#endif
#endif