Commit fe2ddf0f authored by Christian Würdig's avatar Christian Würdig
Browse files

fixed Jump Tables

parent fe53f12c
......@@ -921,19 +921,9 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
interval = tbl.max_value - tbl.min_value;
/* emit the table */
if (tbl.min_value != 0) {
lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "sub [%1S-%d], %u", irn, tbl.min_value * 4, interval);
lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "cmp DWORD PTR [%1S-%d], %u", irn, tbl.min_value * 4, interval);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* first switch value is not 0 */");
IA32_DO_EMIT(irn);
}
else {
lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %u", irn, interval);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* compare for switch */");
IA32_DO_EMIT(irn);
}
lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %u", irn, interval);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* compare for switch */");
IA32_DO_EMIT(irn);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "ja %s", get_cfop_target(tbl.defProj, buf));
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* default jump if out of range */");
......@@ -952,7 +942,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
fprintf(F, "%s:\n", tbl.label);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, ".long %s", get_cfop_target(tbl.branches[0].target, buf));
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* case %d */\n", tbl.branches[0].value);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* case %d */", tbl.branches[0].value);
IA32_DO_EMIT(irn);
last_value = tbl.branches[0].value;
......@@ -967,7 +957,7 @@ static void emit_ia32_SwitchJmp(const ir_node *irn, ia32_emit_env_t *emit_env) {
IA32_DO_EMIT(irn);
}
fprintf(F, "\t.text");
fprintf(F, "\n\t.text\n\n");
}
else {
/* one jump is enough */
......
......@@ -9,6 +9,8 @@
#include "config.h"
#endif
#include <limits.h>
#include "irargs_t.h"
#include "irnode_t.h"
#include "irgraph_t.h"
......@@ -1475,7 +1477,28 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) {
set_ia32_am_support(res, ia32_am_Source);
}
else {
res = new_rd_ia32_SwitchJmp(dbg, irg, block, sel, mode_T);
/* determine the smallest switch case value */
int switch_min = INT_MAX;
const ir_edge_t *edge;
char buf[64];
foreach_out_edge(node, edge) {
int pn = get_Proj_proj(get_edge_src_irn(edge));
switch_min = pn < switch_min ? pn : switch_min;
}
if (switch_min) {
/* if smallest switch case is not 0 we need an additional sub */
snprintf(buf, sizeof(buf), "%d", switch_min);
res = new_rd_ia32_Lea(dbg, irg, block, sel, noreg, mode_Is);
SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn));
sub_ia32_am_offs(res, buf);
set_ia32_am_flavour(res, ia32_am_OB);
set_ia32_am_support(res, ia32_am_Source);
set_ia32_op_type(res, ia32_AddrModeS);
}
res = new_rd_ia32_SwitchJmp(dbg, irg, block, switch_min ? res : sel, mode_T);
set_ia32_pncode(res, get_Cond_defaultProj(node));
set_ia32_res_mode(res, get_irn_mode(sel));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment