+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <limits.h>
+#include "xmalloc.h"
#include "tv.h"
#include "iredges.h"
#include "debug.h"
static const arch_env_t *arch_env = NULL;
+char *ia32_emit_binop(ir_node *irn) {
+ return "R1, R2";
+}
+
+char *ia32_emit_unop(ir_node *irn) {
+ return "R";
+}
+
+char *ia32_emit_am(ir_node *irn) {
+ return "AM";
+}
/*************************************************************
* _ _ __ _ _
* Return node's tarval as string.
*/
const char *node_const_to_str(ir_node *n) {
- char *buf;
- tarval *tv = get_ia32_Immop_tarval(n);
+ char *s = get_ia32_cnst(n);
- if (tv) {
- buf = malloc(SNPRINTF_BUF_LEN);
- tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
- return buf;
- }
- else if (get_ia32_old_ir(n)) {
- return get_sc_name(get_ia32_old_ir(n));
- }
- else
- return "0";
+ if (!s)
+ s = "NULL";
+
+ return s;
}
/**
* Returns node's offset as string.
*/
char *node_offset_to_str(ir_node *n) {
- char *buf;
- tarval *tv = get_ia32_am_offs(n);
+ char *s = get_ia32_am_offs(n);
- if (tv) {
- buf = malloc(SNPRINTF_BUF_LEN);
- tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
- return buf;
- }
- else
- return "";
+ if (!s)
+ s = "";
+
+ return s;
}
/* We always pass the ir_node which is a pointer. */
*/
int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
const arch_register_t *reg;
- ir_node *op;
if (in_out == 1) {
- /* special case Proj P_fame_base */
- op = get_irn_n(irn, pos);
- if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
- return 10;
- }
-
reg = get_in_reg(irn, pos);
}
else {
*/
const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
const arch_register_t *reg;
- ir_node *op;
if (in_out == 1) {
- /* special case Proj P_fame_base */
- op = get_irn_n(irn, pos);
- if (is_Proj(op) && get_Proj_proj(op) == pn_Start_P_frame_base) {
- return "x(esp)";
- }
reg = get_in_reg(irn, pos);
}
else {
FILE *F = emit_env->out;
/* fill the table structure */
- tbl.label = malloc(SNPRINTF_BUF_LEN);
+ tbl.label = xmalloc(SNPRINTF_BUF_LEN);
tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
tbl.defProj = NULL;
tbl.num_branches = get_irn_n_edges(irn);
- tbl.branches = calloc(tbl.num_branches, sizeof(tbl.branches[0]));
+ tbl.branches = xcalloc(tbl.num_branches, sizeof(tbl.branches[0]));
tbl.min_value = INT_MAX;
tbl.max_value = INT_MIN;
void emit_Proj(ir_node *irn, emit_env_t *env) {
ir_node *pred = get_Proj_pred(irn);
- if (get_irn_opcode(pred) == iro_Start) {
+ if (get_irn_op(pred) == op_Start) {
switch(get_Proj_proj(irn)) {
case pn_Start_X_initial_exec:
emit_Jmp(irn, env);
}
}
+/********************
+ * _____ _ _
+ * / ____| | | |
+ * | | __ _| | |
+ * | | / _` | | |
+ * | |___| (_| | | |
+ * \_____\__,_|_|_|
+ *
+ ********************/
+
+void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) {
+ int i, n = get_irn_arity(irn);
+ int args_size = 0;
+ ir_node *sync = get_irn_n(irn, n - 1);
+ FILE *F = emit_env->out;
+ const lc_arg_env_t *env = ia32_get_arg_env();
+
+ if (get_irn_op(sync) == op_Sync) {
+ /* We have stack arguments */
+ ir_node **args = get_Sync_preds_arr(sync);
+
+ for (i = 0; i < get_Sync_n_preds(sync); i++) {
+ ir_node *n = get_irn_n(args[i], 1);
+ lc_efprintf(env, F, "\tpush %1D\t\t\t\t/* push %+F(%+F) on stack */\n", n, args[i], n);
+
+ if (mode_is_float(get_irn_mode(n))) {
+ args_size += 4;
+ }
+ else {
+ args_size += 16;
+ }
+ }
+ }
+
+ lc_efprintf(env, F, "\tcall %C\t\t\t/* %+F */\n", irn, irn);
+
+ if (get_irn_op(sync) == op_Sync) {
+ /* We had stack arguments: clear the stack */
+ fprintf(F, "\tadd %d, ", args_size);
+ if (emit_env->cg->has_alloca) {
+ fprintf(F, "%%ebp");
+ }
+ else {
+ fprintf(F, "%%esp");
+ }
+ fprintf(F, "\t\t\t\t/* clear stack after call */\n");
+ }
+}
+
+
+
+/**
+ * Emits code for Alloca (increase stack pointer, cpoy to destination)
+ */
+void emit_Alloca(ir_node *irn, emit_env_t *emit_env, int is_imm) {
+ const lc_arg_env_t *env = ia32_get_arg_env();
+ FILE *F = emit_env->out;
+ char *sp;
+
+ if (emit_env->cg->has_alloca) {
+ sp = "%ebp";
+ }
+ else {
+ sp = "%esp";
+ }
+
+
+ /* allocate the memory */
+ fprintf(F, "\tsub %s", sp);
+
+ if (is_imm) {
+ lc_efprintf(env, F, "%C", irn);
+ }
+ else {
+ lc_efprintf(env, F, "%1S", irn);
+ }
+
+ fprintf(F, "\t\t\t\t/* reserve memory on stack */\n");
+
+ /* copy the new stack pointer to destination register */
+ lc_efprintf(env, F, "\tmov %s, %1D\t\t\t/* copy stack pointer to destination */\n", sp, irn);
+}
+
+void emit_ia32_Alloca(ir_node *irn, emit_env_t *emit_env) {
+ emit_Alloca(irn, emit_env, 0);
+}
+
+void emit_ia32_Alloca_i(ir_node *irn, emit_env_t *emit_env) {
+ emit_Alloca(irn, emit_env, 1);
+}
/***********************************************************************************
#define EMIT(a) if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
/* generated int emitter functions */
- IA32_EMIT(Copy);
- IA32_EMIT(Perm);
-
IA32_EMIT(Const);
IA32_EMIT(Add);
- IA32_EMIT(Add_i);
IA32_EMIT(Sub);
- IA32_EMIT(Sub_i);
IA32_EMIT(Minus);
IA32_EMIT(Inc);
IA32_EMIT(Dec);
IA32_EMIT(Min);
IA32_EMIT(And);
- IA32_EMIT(And_i);
IA32_EMIT(Or);
- IA32_EMIT(Or_i);
IA32_EMIT(Eor);
- IA32_EMIT(Eor_i);
IA32_EMIT(Not);
IA32_EMIT(Shl);
- IA32_EMIT(Shl_i);
IA32_EMIT(Shr);
- IA32_EMIT(Shr_i);
IA32_EMIT(Shrs);
- IA32_EMIT(Shrs_i);
IA32_EMIT(RotL);
- IA32_EMIT(RotL_i);
IA32_EMIT(RotR);
IA32_EMIT(Lea);
- IA32_EMIT(Lea_i);
IA32_EMIT(Mul);
- IA32_EMIT(Mul_i);
- IA32_EMIT(Cltd);
+ IA32_EMIT(Cdq);
IA32_EMIT(DivMod);
IA32_EMIT(Store);
IA32_EMIT(fAdd);
IA32_EMIT(fSub);
- IA32_EMIT(fMinus);
IA32_EMIT(fMul);
IA32_EMIT(fDiv);
/* other emitter functions */
IA32_EMIT(CondJmp);
- IA32_EMIT(CondJmp_i);
IA32_EMIT(SwitchJmp);
+ IA32_EMIT(Call);
EMIT(Jmp);
EMIT(Proj);
/**
* Main driver
*/
-void ia32_gen_routine(FILE *F, ir_graph *irg, const arch_env_t *env) {
+void ia32_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
emit_env_t emit_env;
emit_env.mod = firm_dbg_register("ir.be.codegen.ia32");
emit_env.out = F;
- emit_env.arch_env = env;
+ emit_env.arch_env = cg->arch_env;
+ emit_env.cg = cg;
- arch_env = env;
+ /* set the global arch_env (needed by print hooks) */
+ arch_env = cg->arch_env;
ia32_emit_start(F, irg);
irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);