+static void bemit_switchjmp(const ir_node *node)
+{
+ unsigned long interval;
+ int last_value;
+ int i;
+ jmp_tbl_t tbl;
+ const arch_register_t *in;
+
+ /* fill the table structure */
+ generate_jump_table(&tbl, node);
+
+ /* two-complement's magic make this work without overflow */
+ interval = tbl.max_value - tbl.min_value;
+
+ in = get_in_reg(node, 0);
+ /* emit the table */
+ if (get_signed_imm_size(interval) == 1) {
+ bemit8(0x83); // cmpl $imm8, %in
+ bemit_modru(in, 7);
+ bemit8(interval);
+ } else {
+ bemit8(0x81); // cmpl $imm32, %in
+ bemit_modru(in, 7);
+ bemit32(interval);
+ }
+ bemit8(0x0F); // ja tbl.defProj
+ bemit8(0x87);
+ ia32_emitf(tbl.defProj, ".long %L - . - 4\n");
+
+ if (tbl.num_branches > 1) {
+ /* create table */
+ bemit8(0xFF); // jmp *tbl.label(,%in,4)
+ bemit8(MOD_IND | ENC_REG(4) | ENC_RM(0x04));
+ bemit8(ENC_SIB(2, reg_gp_map[in->index], 0x05));
+ be_emit_irprintf("\t.long %s\n", tbl.label);
+
+ be_gas_emit_switch_section(GAS_SECTION_RODATA);
+ be_emit_cstring(".align 4\n");
+ be_emit_irprintf("%s:\n", tbl.label);
+
+ last_value = tbl.branches[0].value;
+ for (i = 0; i != tbl.num_branches; ++i) {
+ while (last_value != tbl.branches[i].value) {
+ ia32_emitf(tbl.defProj, ".long %L\n");
+ ++last_value;
+ }
+ ia32_emitf(tbl.branches[i].target, ".long %L\n");
+ ++last_value;
+ }
+ be_gas_emit_switch_section(GAS_SECTION_TEXT);
+ } else {
+ /* one jump is enough */
+ panic("switch only has one case");
+ //ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
+ }
+
+ be_emit_write_line();
+
+ free(tbl.branches);
+}
+