/**
* ISA implementation for Firm IR nodes.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include "bitset.h"
+#include "obst.h"
+
#include "bearch.h"
-#define N_REGS 1024
+#include "irreflect.h"
+
+#define N_REGS 64
-static arch_register_t gp_regs[N_REGS];
-static arch_register_t fp_regs[N_REGS];
+static arch_register_t datab_regs[N_REGS];
static arch_register_class_t reg_classes[] = {
- { "gp", NULL, N_REGS, gp_regs },
- { "fp", NULL, N_REGS, fp_regs }
+ { "datab", N_REGS, datab_regs },
};
#define N_CLASSES \
(sizeof(reg_classes) / sizeof(reg_classes[0]))
-#define CLS_GP 0
-#define CLS_FP 0
+#define CLS_DATAB 0
static void firm_init(void)
{
return ®_classes[i];
}
-static const arch_register_class_t *firm_get_irn_reg_class(const ir_node *irn)
+static const arch_register_req_t firm_std_reg_req = {
+ arch_register_req_type_normal,
+ ®_classes[CLS_DATAB],
+ { NULL }
+};
+
+static const rflct_arg_t *get_arg(const ir_node *irn, int pos)
+{
+ int sig = rflct_get_signature(irn);
+ const rflct_arg_t *args =
+ rflct_get_args(get_irn_opcode(irn), sig, arch_pos_is_in(pos));
+ return &args[arch_pos_get_index(pos)];
+}
+
+static const arch_register_req_t *
+firm_get_irn_reg_req(const arch_irn_ops_t *self,
+ arch_register_req_t *req, const ir_node *irn, int pos)
{
- ir_mode *mode = get_irn_mode(irn);
+ if(mode_is_datab(get_irn_mode(irn)))
+ memcpy(req, &firm_std_reg_req, sizeof(*req));
+ else
+ req = NULL;
- if(mode_is_float(mode))
- return ®_classes[CLS_FP];
- else if(mode_is_datab(mode))
- return ®_classes[CLS_GP];
+ return req;
+}
- return NULL;
+static int firm_get_n_operands(const arch_irn_ops_t *self, const ir_node *irn, int in_out)
+{
+ int sig = rflct_get_signature(irn);
+ return rflct_get_args_count(get_irn_opcode(irn), sig, in_out >= 0);
}
-static int firm_is_reg_allocatable(const ir_node *irn, const arch_register_t *reg)
+struct irn_reg_assoc {
+ const ir_node *irn;
+ int pos;
+ const arch_register_t *reg;
+};
+
+static int cmp_irn_reg_assoc(const void *a, const void *b, size_t len)
{
- return arch_register_get_class(reg) == firm_get_irn_reg_class(irn);
+ const struct irn_reg_assoc *x = a;
+ const struct irn_reg_assoc *y = b;
+
+ return !(x->irn == y->irn && x->pos == y->pos);
}
-static int firm_get_allocatable_regs(const ir_node *irn,
- const arch_register_class_t *cls, bitset_t *bs)
+static struct irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, int pos)
{
- int i;
+ static set *reg_set = NULL;
+ struct irn_reg_assoc templ;
+ unsigned int hash;
- if(firm_get_irn_reg_class(irn) != cls) {
- bitset_clear_all(bs);
- return 0;
- }
+ if(!reg_set)
+ reg_set = new_set(cmp_irn_reg_assoc, 1024);
+
+ templ.irn = irn;
+ templ.pos = pos;
+ templ.reg = NULL;
+ hash = HASH_PTR(irn) + 7 * pos;
- for(i = 0; i < cls->n_regs; ++i)
- bitset_set_all(bs);
+ return set_insert(reg_set, &templ, sizeof(templ), hash);
+}
- return cls->n_regs;
+static void firm_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn,
+ int pos, const arch_register_t *reg)
+{
+ struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
+ assoc->reg = reg;
}
-const arch_isa_if_t arch_isa_if_firm = {
+static const arch_register_t *firm_get_irn_reg(const arch_irn_ops_t *self,
+ const ir_node *irn, int pos)
+{
+ struct irn_reg_assoc *assoc = get_irn_reg_assoc(irn, pos);
+ return assoc->reg;
+}
+
+static arch_irn_class_t firm_classify(const arch_irn_ops_t *self, const ir_node *irn)
+{
+ arch_irn_class_t res;
+
+ switch(get_irn_opcode(irn)) {
+ case iro_Cond:
+ case iro_Jmp:
+ res = arch_irn_class_branch;
+ break;
+ default:
+ res = arch_irn_class_normal;
+ }
+
+ return res;
+}
+
+static const arch_irn_ops_t irn_ops = {
+ firm_get_irn_reg_req,
+ firm_get_n_operands,
+ firm_set_irn_reg,
+ firm_get_irn_reg,
+ firm_classify
+};
+
+const arch_isa_if_t firm_isa = {
firm_init,
firm_get_n_reg_class,
- firm_get_reg_class,
- firm_is_reg_allocatable,
- firm_get_allocatable_regs,
- firm_get_irn_reg_class,
- NULL
+ firm_get_reg_class
+};
+
+static const arch_irn_ops_t *firm_get_irn_ops(const arch_irn_handler_t *self,
+ const ir_node *irn)
+{
+ return &irn_ops;
+}
+
+const arch_irn_handler_t firm_irn_handler = {
+ firm_get_irn_ops,
};