ia32_emitter.c 4.17 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "tv.h"
#include "iredges.h"
#include "ia32_emitter.h"
#include "ia32_nodes_attr.h"
#include "ia32_new_nodes.h"

#define TARVAL_SNPRINTF_BUF_LEN 1024

const char *get_dest_reg_name(ir_node *n, int num) {
  return get_ia32_out_reg_name(n, --num);
}

const char *get_source_reg_name(ir_node *n, int num) {
  return get_ia32_in_reg_name(n, --num);
}

char *node_const_to_str(ir_node *n) {
  char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
  tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_Immop_tarval(n));
  return buf;
}

char *node_offset_to_str(ir_node *n) {
  char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
  tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_offs(n));
  return buf;
}

void equalize_dest_src(FILE *F, ir_node *n) {
  if (get_ia32_out_regnr(n, 0) != get_ia32_in_regnr(n, 0))
    fprintf(F, "\tmovl %%%s, %%%s\t\t\t/* src -> dest for 2 address code */\n", get_source_reg_name(n, 1), get_dest_reg_name(n, 1));
}

/*
 * coding of conditions
 */
struct cmp2conditon_t {
  const char *name;
  pn_Cmp      num;
};

/*
 * positive conditions for signed compares
 */
static const struct cmp2conditon_t cmp2condition_s[] = {
  { NULL,              pn_Cmp_False },  /* always false */
  { "e",               pn_Cmp_Eq },     /* == */
  { "l",               pn_Cmp_Lt },     /* < */
  { "le",              pn_Cmp_Le },     /* <= */
  { "g",               pn_Cmp_Gt },     /* > */
  { "ge",              pn_Cmp_Ge },     /* >= */
  { "ne",              pn_Cmp_Lg },     /* != */
  { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
  { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
  { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
  { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
  { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
  { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
  { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
  { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
  { NULL,              pn_Cmp_True },   /* always true */
};

/*
 * positive conditions for unsigned compares
 */
static const struct cmp2conditon_t cmp2condition_u[] = {
  { NULL,              pn_Cmp_False },  /* always false */
  { "e",               pn_Cmp_Eq },     /* == */
  { "b",               pn_Cmp_Lt },     /* < */
  { "be",              pn_Cmp_Le },     /* <= */
  { "a",               pn_Cmp_Gt },     /* > */
  { "ae",              pn_Cmp_Ge },     /* >= */
  { "ne",              pn_Cmp_Lg },     /* != */
  { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
  { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
  { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
  { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
  { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
  { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
  { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
  { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
  { NULL,              pn_Cmp_True },   /* always true */
};

/*
 * returns the condition code
 */
const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
{
  assert(cmp2condition_s[cmp_code].num == cmp_code);
  assert(cmp2condition_u[cmp_code].num == cmp_code);

  return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
}

void emit_ia32_Proj_Cond(FILE *F, ir_node *n, ir_node *cond) {
  ir_node *succ_block = get_edge_src_irn(get_irn_out_edge_first(n));
  ir_node *sel        = get_Cond_selector(cond);
  ir_mode *sel_mode   = get_irn_mode(sel);

  assert(succ_block && "Target block of Proj_Cond missing!");

  if (sel_mode == mode_b) { // Boolean condition
    int label = get_irn_node_nr(succ_block);
    int nr    = get_Proj_proj(n);
    fprintf(F, "j%s%s Label%d\t\t\t/* if (%sCond) goto Label */\n",
          nr == pn_Cond_true ? "" : "n",
          get_cmp_suffix(get_Proj_proj(sel), mode_is_signed(sel_mode)),
          label,
          nr == pn_Cond_true ? "" : "!");
  }
}