void bingen(int lower, int avg, int higher,AMODE *ap1, int deflab, int size,long * switchids,int * switchlabels,int *switchbinlabels) { AMODE *ap2 = make_immed(switchids[avg]); AMODE *ap3 = make_label(switchlabels[avg]); if (switchbinlabels[avg] != -1) gen_label(switchbinlabels[avg]); gen_code(op_cmp,4,ap1,ap2); gen_code(op_je,0,ap3,0); if (avg == lower) { ap3 = make_label(deflab); gen_code(op_jmp,0,ap3,0); } else { int avg1 = (lower + avg)/2; int avg2 = (higher + avg+1)/2; if (avg+1 < higher) ap3 = make_label(switchbinlabels[avg2]=nextlabel++); else ap3 = make_label(deflab); if (size < 0) gen_code(op_jg,0,ap3,0); else gen_code(op_ja,0,ap3,0); bingen(lower,avg1,avg,ap1,deflab,size,switchids,switchlabels,switchbinlabels); if (avg+1 < higher) bingen(avg+1,avg2,higher,ap1,deflab,size,switchids,switchlabels,switchbinlabels); } }
void bingen(int lower, int avg, int higher, AMODE *ap1, struct cases *cs, int size) { AMODE *ap2 = make_immed(cs->ptrs[avg].id); AMODE *ap3 = make_label(cs->ptrs[avg].label); if (cs->ptrs[avg].binlabel != - 1) gen_label(cs->ptrs[avg].binlabel); gen_coden(op_cmp, size, ap1, ap2); gen_code(op_je, ap3, 0); if (avg == lower) { if (cs->deflab < 0) cs->deflab = nextlabel++; ap3 = make_label(cs->deflab); gen_code(op_jmp, ap3, 0); } else { int avg1 = (lower + avg) / 2; int avg2 = (higher + avg + 1) / 2; if (avg + 1 < higher) ap3 = make_label(cs->ptrs[avg2].binlabel = nextlabel++); else ap3 = make_label(cs->deflab); if (size < 0) gen_code(op_jg, ap3, 0); else gen_code(op_ja, ap3, 0); bingen(lower, avg1, avg, ap1, cs, size); if (avg + 1 < higher) bingen(avg + 1, avg2, higher, ap1, cs, size); } }
void genbinaryswitch(SNODE *stmt, struct cases *cs) { AMODE *ap1; int size = natural_size(stmt->exp); InitRegs(); ap1 = gen_expr_external(stmt->exp, FALSE, F_DREG, BESZ_DWORD); gather_cases(stmt->s1,cs,FALSE); qsort(cs->ptrs,cs->count, sizeof(cs->ptrs[0]), size < 0 ? sortcmpsigned : sortcmpunsigned); bingen(0, (cs->count) / 2, cs->count, ap1, cs, size); }
void genbinaryswitch(SNODE *stmt, int deflab) { int curlab, i=0,j,size = natural_size(stmt->exp); AMODE *ap1; long switchbottom=gswitchbottom, switchcount=gswitchcount; long switchtop=gswitchtop; int *switchlabels=0; long *switchids=0; int *switchbinlabels=0; curlab = nextlabel++; initstack(); ap1 = gen_expr(stmt->exp,F_DREG,4); global_flag++; switchlabels = xalloc((switchcount) * sizeof(int)); switchbinlabels = xalloc((switchcount) * sizeof(int)); switchids = xalloc((switchcount) * sizeof(long)); global_flag--; stmt = stmt->s1; while (stmt) { if( stmt->s2 ) /* default case ? */ { stmt->label = (SNODE *) deflab; diddef = TRUE; } else { switchlabels[i] = curlab; switchbinlabels[i] = -1; switchids[i++] = (int)stmt->label; stmt->label = (SNODE *)curlab; } if( stmt->next != 0 ) curlab = nextlabel++; stmt = stmt->next; } for (i=0; i < switchcount; i++) for (j=i+1; j < switchcount; j++) if (switchids[j] < switchids[i]) { int temp = switchids[i]; switchids[i] = switchids[j]; switchids[j] = temp; temp = switchlabels[i]; switchlabels[i] = switchlabels[j]; switchlabels[j] = temp; } bingen(0,(switchcount)/2,switchcount,ap1,deflab,size,switchids,switchlabels,switchbinlabels); freeop(ap1); }