#include "irprintf.h"
#include "irop_t.h"
#include "irargs_t.h"
+#include "irprog_t.h"
#include "../besched.h"
# define obstack_chunk_free free
#endif
+extern int obstack_printf(struct obstack *obst, char *fmt, ...);
+
#define SNPRINTF_BUF_LEN 128
static const arch_env_t *arch_env = NULL;
+/**
+ * Emits registers and/or address mode of a binary operation.
+ */
char *ia32_emit_binop(const ir_node *n) {
static char *buf = NULL;
return buf;
}
+/**
+ * Emits registers and/or address mode of a unary operation.
+ */
char *ia32_emit_unop(const ir_node *n) {
static char *buf = NULL;
return buf;
}
+/**
+ * Emits adressmode.
+ */
char *ia32_emit_am(const ir_node *n) {
ia32_am_flavour_t am_flav = get_ia32_am_flavour(n);
int had_output = 0;
lc_eoprintf(ia32_get_arg_env(), obst, "%2S", n);
if (am_flav & ia32_S) {
- obstack_printf(obst, "*%d", get_ia32_am_scale(n));
+ obstack_printf(obst, "*%d", 1 << get_ia32_am_scale(n));
}
had_output = 1;
return arch_register_get_index(reg);
}
+enum io_direction {
+ IN_REG,
+ OUT_REG
+};
+
/**
* Returns the name of the in register at position pos.
*/
-const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
+static const char *get_ia32_reg_name(ir_node *irn, int pos, enum io_direction in_out) {
const arch_register_t *reg;
- if (in_out == 1) {
+ if (in_out == IN_REG) {
reg = get_in_reg(irn, pos);
}
else {
if (!X)
return lc_arg_append(app, occ, "(null)", 6);
- if (occ->conversion == 'S') {
- buf = get_ia32_reg_name(X, nr, 1);
- }
- else { /* 'D' */
- buf = get_ia32_reg_name(X, nr, 0);
- }
+ buf = get_ia32_reg_name(X, nr, occ->conversion == 'S' ? IN_REG : OUT_REG);
lc_appendable_chadd(app, '%');
return lc_arg_append(app, occ, buf, strlen(buf));
***********************************************************************************/
/**
- * Emits code for a node.
+ * Enters the emitter functions for handled nodes into the generic
+ * pointer of an opcode.
*/
-void ia32_emit_node(ir_node *irn, void *env) {
- emit_env_t *emit_env = env;
- firm_dbg_module_t *mod = emit_env->mod;
- FILE *F = emit_env->out;
+void ia32_register_emitters(void) {
+ int i;
- DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
+#define BEGIN() if (0)
+#define IA32_EMIT(a) else if (op_ia32_##a == op) op->ops.generic = (op_func)emit_ia32_##a
+#define EMIT(a) else if (op_##a == op) op->ops.generic = (op_func)emit_##a
+#define END() else op->ops.generic = (op_func)NULL
+
+ for (i = get_irp_n_opcodes() - 1; i >= 0; --i) {
+ ir_op *op = get_irp_opcode(i);
+
+ BEGIN();
+ /* generated int emitter functions */
+ IA32_EMIT(Const);
+
+ IA32_EMIT(Add);
+ IA32_EMIT(Sub);
+ IA32_EMIT(Minus);
+ IA32_EMIT(Inc);
+ IA32_EMIT(Dec);
-#define IA32_EMIT(a) if (is_ia32_##a(irn)) { emit_ia32_##a(irn, emit_env); return; }
-#define EMIT(a) if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
+ IA32_EMIT(Max);
+ IA32_EMIT(Min);
+ IA32_EMIT(CMov);
- /* generated int emitter functions */
- IA32_EMIT(Const);
+ IA32_EMIT(And);
+ IA32_EMIT(Or);
+ IA32_EMIT(Eor);
+ IA32_EMIT(Not);
- IA32_EMIT(Add);
- IA32_EMIT(Sub);
- IA32_EMIT(Minus);
- IA32_EMIT(Inc);
- IA32_EMIT(Dec);
+ IA32_EMIT(Shl);
+ IA32_EMIT(Shr);
+ IA32_EMIT(Shrs);
+ IA32_EMIT(RotL);
+ IA32_EMIT(RotR);
- IA32_EMIT(Max);
- IA32_EMIT(Min);
- IA32_EMIT(CMov);
+ IA32_EMIT(Lea);
- IA32_EMIT(And);
- IA32_EMIT(Or);
- IA32_EMIT(Eor);
- IA32_EMIT(Not);
+ IA32_EMIT(Mul);
- IA32_EMIT(Shl);
- IA32_EMIT(Shr);
- IA32_EMIT(Shrs);
- IA32_EMIT(RotL);
- IA32_EMIT(RotR);
+ IA32_EMIT(Cdq);
+ IA32_EMIT(DivMod);
- IA32_EMIT(Lea);
+ IA32_EMIT(Store);
+ IA32_EMIT(Load);
- IA32_EMIT(Mul);
+ IA32_EMIT(CopyB);
+ IA32_EMIT(CopyB_i);
- IA32_EMIT(Cdq);
- IA32_EMIT(DivMod);
+ /* generated floating point emitter */
+ IA32_EMIT(fConst);
- IA32_EMIT(Store);
- IA32_EMIT(Load);
+ IA32_EMIT(fAdd);
+ IA32_EMIT(fSub);
- IA32_EMIT(CopyB);
- IA32_EMIT(CopyB_i);
+ IA32_EMIT(fMul);
+ IA32_EMIT(fDiv);
- /* generated floating point emitter */
- IA32_EMIT(fConst);
+ IA32_EMIT(fMin);
+ IA32_EMIT(fMax);
- IA32_EMIT(fAdd);
- IA32_EMIT(fSub);
+ IA32_EMIT(fLoad);
+ IA32_EMIT(fStore);
- IA32_EMIT(fMul);
- IA32_EMIT(fDiv);
+ /* other emitter functions */
+ IA32_EMIT(CondJmp);
+ IA32_EMIT(SwitchJmp);
+ IA32_EMIT(Call);
- IA32_EMIT(fMin);
- IA32_EMIT(fMax);
+ EMIT(Jmp);
+ EMIT(Proj);
- IA32_EMIT(fLoad);
- IA32_EMIT(fStore);
+ END();
+ }
- /* other emitter functions */
- IA32_EMIT(CondJmp);
- IA32_EMIT(SwitchJmp);
- IA32_EMIT(Call);
+#undef BEGIN
+#undef IA32_EMIT
+#undef EMIT
+#undef END
+
+}
+
+/**
+ * Emits code for a node.
+ */
+static void ia32_emit_node(ir_node *irn, void *env) {
+ emit_env_t *emit_env = env;
+ firm_dbg_module_t *mod = emit_env->mod;
+ FILE *F = emit_env->out;
+ ir_op *op = get_irn_op(irn);
+
+ DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
- EMIT(Jmp);
- EMIT(Proj);
+ if (op->ops.generic) {
+ void (*emit)(ir_node *, void *) = (void (*)(ir_node *, void *))op->ops.generic;
+ (*emit)(irn, env);
+ }
ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
}
* Walks over the nodes in a block connected by scheduling edges
* and emits code for each node.
*/
-void ia32_gen_block(ir_node *block, void *env) {
+static void ia32_gen_block(ir_node *block, void *env) {
ir_node *irn;
if (! is_Block(block))
}
/**
- * Main driver
+ * Main driver. Emits the code for one routine.
*/
void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
emit_env_t emit_env;