From: Aleksey Demakov Date: Sun, 23 Apr 2006 07:56:59 +0000 (+0000) Subject: register allocator now supports register set constraints X-Git-Tag: before.move.to.git~251 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=3d40ef5372fcbf481c19e7eb49f3352ce67ffd5c;p=francis%2Flibjit.git register allocator now supports register set constraints --- diff --git a/ChangeLog b/ChangeLog index 1c8c76d..6703ff8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-04-23 Aleksey Demakov + + * jit/jit-reg-alloc.h, jit/jit-reg-alloc.c: register allocator now + supports register sets that constrain the register assignment. + + * tools/gen-rules-parser.y: extend grammar to support register sets. + Fix bugs. + 2006-04-20 Aleksey Demakov * tools/gen-rules-parser.y: fix generation of `if' pattern code. diff --git a/jit/jit-reg-alloc.c b/jit/jit-reg-alloc.c index b884fbc..1ce2494 100644 --- a/jit/jit-reg-alloc.c +++ b/jit/jit-reg-alloc.c @@ -1842,6 +1842,37 @@ value_clobbers_register(jit_gencode_t gen, _jit_regs_t *regs, int index, int reg return desc->clobber; } +/* + * Initialize register descriptor. + */ +static void +init_desc(_jit_regs_t *regs, int index, jit_value_t value, int flags, int live, int used) +{ + _jit_regdesc_t *desc; + + desc = ®s->descs[index]; + + desc->value = value; + if(index > 0 || regs->ternary) + { + if((flags & _JIT_REGS_EARLY_CLOBBER) != 0) + { + desc->clobber = 1; + desc->early_clobber = 1; + } + else if((flags & _JIT_REGS_CLOBBER) != 0) + { + desc->clobber = 1; + } + } + desc->live = live; + desc->used = used; + if(regs->on_stack) + { + desc->on_stack = 1; + } +} + /* * Set assigned and clobbered flags for register. */ @@ -2067,7 +2098,7 @@ compute_spill_cost(jit_gencode_t gen, _jit_regs_t *regs, int reg, int other_reg) * */ static int -use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index) +use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index, jit_regused_t regset) { _jit_regdesc_t *desc; int output; @@ -2121,7 +2152,8 @@ use_cheapest_register(jit_gencode_t gen, _jit_regs_t *regs, int index) other_reg = -1; } - if(jit_reg_is_used(gen->inhibit, reg) + if(!jit_reg_is_used(regset, reg) + || jit_reg_is_used(gen->inhibit, reg) || jit_reg_is_used(regs->assigned, reg)) { continue; @@ -2975,6 +3007,7 @@ _jit_regs_init(_jit_regs_t *regs, int flags) regs->descs[index].value = 0; regs->descs[index].reg = -1; regs->descs[index].other_reg = -1; + regs->descs[index].regset = jit_regused_init_used; regs->descs[index].clobber = 0; regs->descs[index].early_clobber = 0; regs->descs[index].live = 0; @@ -2982,11 +3015,11 @@ _jit_regs_init(_jit_regs_t *regs, int flags) regs->descs[index].on_stack = 0; regs->descs[index].duplicate = 0; } - regs->num_descs = 0; for(index = 0; index < _JIT_REGS_SCRATCH_MAX; index++) { - regs->scratch[index] = -1; + regs->scratch[index].reg = -1; + regs->scratch[index].regset = jit_regused_init_used; } regs->num_scratch = 0; @@ -3001,140 +3034,65 @@ _jit_regs_init(_jit_regs_t *regs, int flags) } void -_jit_regs_set_dest(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg) +_jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags) { - if((insn->flags & JIT_INSN_DEST_OTHER_FLAGS) != 0) - { - return; - } - - if(regs->num_descs < 1) + if((insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0) { - regs->num_descs = 1; - } - - regs->descs[0].value = insn->dest; - if(reg >= 0) - { - regs->descs[0].reg = reg; - regs->descs[0].other_reg = other_reg; - } - if(regs->ternary) - { - if((flags & _JIT_REGS_EARLY_CLOBBER) != 0) - { - regs->descs[0].clobber = 1; - regs->descs[0].early_clobber = 1; - } - else if((flags & _JIT_REGS_CLOBBER) != 0) - { - regs->descs[0].clobber = 1; - } - } - if((insn->flags & JIT_INSN_DEST_LIVE) != 0) - { - regs->descs[0].live = 1; - } - if((insn->flags & JIT_INSN_DEST_NEXT_USE) != 0) - { - regs->descs[0].used = 1; - } - if(regs->on_stack) - { - regs->descs[0].on_stack = 1; + init_desc(regs, 0, insn->dest, flags, + (insn->flags & JIT_INSN_DEST_LIVE) != 0, + (insn->flags & JIT_INSN_DEST_NEXT_USE) != 0); } } void -_jit_regs_set_value1(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg) +_jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags) { - if((insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) != 0) + if((insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0) { - return; - } - - if(regs->num_descs < 2) - { - regs->num_descs = 2; + init_desc(regs, 1, insn->value1, flags, + (insn->flags & JIT_INSN_VALUE1_LIVE) != 0, + (insn->flags & JIT_INSN_VALUE1_NEXT_USE) != 0); } +} - regs->descs[1].value = insn->value1; - if(reg >= 0) - { - regs->descs[1].reg = reg; - regs->descs[1].other_reg = other_reg; - } - if((flags & _JIT_REGS_EARLY_CLOBBER) != 0) - { - regs->descs[1].clobber = 1; - regs->descs[1].early_clobber = 1; - } - else if((flags & _JIT_REGS_CLOBBER) != 0) - { - regs->descs[1].clobber = 1; - } - if((insn->flags & JIT_INSN_VALUE1_LIVE) != 0) - { - regs->descs[1].live = 1; - } - if((insn->flags & JIT_INSN_VALUE1_NEXT_USE) != 0) - { - regs->descs[1].used = 1; - } - if(regs->on_stack) +void +_jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags) +{ + if((insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) == 0) { - regs->descs[1].on_stack = 1; + init_desc(regs, 2, insn->value2, flags, + (insn->flags & JIT_INSN_VALUE2_LIVE) != 0, + (insn->flags & JIT_INSN_VALUE2_NEXT_USE) != 0); } } void -_jit_regs_set_value2(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg) +_jit_regs_set_dest(_jit_regs_t *regs, int reg, int other_reg) { - if((insn->flags & JIT_INSN_VALUE2_OTHER_FLAGS) != 0) - { - return; - } + regs->descs[0].reg = reg; + regs->descs[0].other_reg = other_reg; +} - if(regs->num_descs < 3) - { - regs->num_descs = 3; - } +void +_jit_regs_set_value1(_jit_regs_t *regs, int reg, int other_reg) +{ + regs->descs[1].reg = reg; + regs->descs[1].other_reg = other_reg; +} - regs->descs[2].value = insn->value2; - if(reg >= 0) - { - regs->descs[2].reg = reg; - regs->descs[2].other_reg = other_reg; - } - if((flags & _JIT_REGS_EARLY_CLOBBER) != 0) - { - regs->descs[2].clobber = 1; - regs->descs[2].early_clobber = 1; - } - else if((flags & _JIT_REGS_CLOBBER) != 0) - { - regs->descs[2].clobber = 1; - } - if((insn->flags & JIT_INSN_VALUE2_LIVE) != 0) - { - regs->descs[2].live = 1; - } - if((insn->flags & JIT_INSN_VALUE2_NEXT_USE) != 0) - { - regs->descs[2].used = 1; - } - if(regs->on_stack) - { - regs->descs[2].on_stack = 1; - } +void +_jit_regs_set_value2(_jit_regs_t *regs, int reg, int other_reg) +{ + regs->descs[2].reg = reg; + regs->descs[2].other_reg = other_reg; } void -_jit_regs_set_scratch(_jit_regs_t *regs, int reg) +_jit_regs_add_scratch(_jit_regs_t *regs, int reg) { if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX) { - regs->scratch[regs->num_scratch++] = reg; + regs->scratch[regs->num_scratch++].reg = reg; } } @@ -3144,6 +3102,33 @@ _jit_regs_set_clobber(_jit_regs_t *regs, int reg) jit_reg_set_used(regs->clobber, reg); } +void +_jit_regs_set_dest_from(_jit_regs_t *regs, jit_regused_t regset) +{ + regs->descs[0].regset = regset; +} + +void +_jit_regs_set_value1_from(_jit_regs_t *regs, jit_regused_t regset) +{ + regs->descs[1].regset = regset; +} + +void +_jit_regs_set_value2_from(_jit_regs_t *regs, jit_regused_t regset) +{ + regs->descs[2].regset = regset; +} + +void +_jit_regs_add_scratch_from(_jit_regs_t *regs, jit_regused_t regset) +{ + if(regs->num_scratch < _JIT_REGS_SCRATCH_MAX) + { + regs->scratch[regs->num_scratch++].regset = regset; + } +} + int _jit_regs_dest(_jit_regs_t *regs) { @@ -3185,7 +3170,7 @@ _jit_regs_scratch(_jit_regs_t *regs, int index) { if(index < regs->num_scratch && index >= 0) { - return regs->scratch[index]; + return regs->scratch[index].reg; } return -1; } @@ -3224,14 +3209,25 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) for(index = 0; index < regs->num_scratch; index++) { - if(regs->scratch[index] >= 0) + if(regs->scratch[index].reg >= 0) + { + if(IS_STACK_REG(regs->scratch[index].reg)) + { + return 0; + } + jit_reg_set_used(regs->assigned, regs->scratch[index].reg); + jit_reg_set_used(regs->clobber, regs->scratch[index].reg); + } + else if(regs->scratch[index].regset != jit_regused_init_used) { - if(IS_STACK_REG(regs->scratch[index])) + regs->scratch[index].reg = use_cheapest_register( + gen, regs, -1, regs->scratch[index].regset); + if(regs->scratch[index].reg < 0) { return 0; } - jit_reg_set_used(regs->assigned, regs->scratch[index]); - jit_reg_set_used(regs->clobber, regs->scratch[index]); + jit_reg_set_used(regs->assigned, regs->scratch[index].reg); + jit_reg_set_used(regs->clobber, regs->scratch[index].reg); } } @@ -3257,7 +3253,7 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) { if(regs->descs[0].value && regs->descs[0].reg < 0) { - use_cheapest_register(gen, regs, 0); + use_cheapest_register(gen, regs, 0, regs->descs[0].regset); if(regs->descs[0].reg < 0) { return 0; @@ -3274,7 +3270,8 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) && gen->contents[regs->descs[out_index].value->reg].num_values == 1 && !(regs->descs[out_index].live || regs->descs[out_index].used)) { - use_cheapest_register(gen, regs, out_index); + use_cheapest_register( + gen, regs, out_index, regs->descs[out_index].regset); if(regs->descs[out_index].reg < 0) { return 0; @@ -3284,7 +3281,7 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) || (regs->descs[0].value->in_register && gen->contents[regs->descs[0].value->reg].num_values == 1)) { - use_cheapest_register(gen, regs, 0); + use_cheapest_register(gen, regs, 0, regs->descs[0].regset); if(regs->descs[0].reg < 0) { return 0; @@ -3300,7 +3297,7 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) } if(regs->descs[1].value && regs->descs[1].reg < 0) { - use_cheapest_register(gen, regs, 1); + use_cheapest_register(gen, regs, 1, regs->descs[1].regset); if(regs->descs[1].reg < 0) { return 0; @@ -3309,7 +3306,7 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) check_duplicate_value(regs, ®s->descs[1], ®s->descs[2]); if(regs->descs[2].value && regs->descs[2].reg < 0) { - use_cheapest_register(gen, regs, 2); + use_cheapest_register(gen, regs, 2, regs->descs[2].regset); if(regs->descs[2].reg < 0) { return 0; @@ -3319,7 +3316,7 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) { if(regs->descs[out_index].reg < 0) { - use_cheapest_register(gen, regs, 0); + use_cheapest_register(gen, regs, 0, regs->descs[0].regset); if(regs->descs[0].reg < 0) { return 0; @@ -3335,15 +3332,16 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) for(index = 0; index < regs->num_scratch; index++) { - if(regs->scratch[index] < 0) + if(regs->scratch[index].reg < 0) { - regs->scratch[index] = use_cheapest_register(gen, regs, -1); - if(regs->scratch[index] < 0) + regs->scratch[index].reg = use_cheapest_register( + gen, regs, -1, jit_regused_init_used); + if(regs->scratch[index].reg < 0) { return 0; } - jit_reg_set_used(regs->assigned, regs->scratch[index]); - jit_reg_set_used(regs->clobber, regs->scratch[index]); + jit_reg_set_used(regs->assigned, regs->scratch[index].reg); + jit_reg_set_used(regs->clobber, regs->scratch[index].reg); } } @@ -3596,6 +3594,11 @@ _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs) } } +/*@ + * @deftypefun void _jit_regs_lookup (char *name) + * Get register by name. + * @end deftypefun +@*/ int _jit_regs_lookup(char *name) { diff --git a/jit/jit-reg-alloc.h b/jit/jit-reg-alloc.h index 1047ca8..f6b8c01 100644 --- a/jit/jit-reg-alloc.h +++ b/jit/jit-reg-alloc.h @@ -92,7 +92,8 @@ void _jit_regs_get_reg_pair(jit_gencode_t gen, int not_this1, int not_this2, #define _JIT_REGS_REVERSIBLE 0x0080 /* - * Flags for _jit_regs_set_dest(), _jit_regs_set_value1(), _jit_regs_set_value2(). + * Flags for _jit_regs_init_dest(), _jit_regs_init_value1(), and + * _jit_regs_init_value2(). */ #define _JIT_REGS_CLOBBER 0x0001 #define _JIT_REGS_EARLY_CLOBBER 0x0002 @@ -104,13 +105,6 @@ void _jit_regs_get_reg_pair(jit_gencode_t gen, int not_this1, int not_this2, #define _JIT_REGS_REVERSE_DEST 0x0002 #define _JIT_REGS_REVERSE_ARGS 0x0004 -/* - * This value is used internally to assign a stack register. - * It indicates that we are going to use the next free stack - * regsiter but we do not yet know which one it is. -#define _JIT_REGS_NEXT_STACK_REG 0x7fff - */ - /* * Contains register assignment data for single operand. */ @@ -119,6 +113,7 @@ typedef struct jit_value_t value; int reg; int other_reg; + jit_regused_t regset; unsigned live : 1; unsigned used : 1; unsigned clobber : 1; @@ -128,6 +123,16 @@ typedef struct } _jit_regdesc_t; +/* + * Contains scratch register assignment data. + */ +typedef struct +{ + int reg; + jit_regused_t regset; + +} _jit_scratch_t; + /* * Contains register assignment data for instruction. */ @@ -147,9 +152,7 @@ typedef struct unsigned reverse_args : 1; _jit_regdesc_t descs[_JIT_REGS_VALUE_MAX]; - int num_descs; - - int scratch[_JIT_REGS_SCRATCH_MAX]; + _jit_scratch_t scratch[_JIT_REGS_SCRATCH_MAX]; int num_scratch; jit_regused_t assigned; @@ -164,15 +167,26 @@ typedef struct } _jit_regs_t; void _jit_regs_init(_jit_regs_t *regs, int flags); -void _jit_regs_set_dest(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg); -void _jit_regs_set_value1(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg); -void _jit_regs_set_value2(_jit_regs_t *regs, jit_insn_t insn, int flags, int reg, int other_reg); -void _jit_regs_set_scratch(_jit_regs_t *regs, int reg); +void _jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags); +void _jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags); +void _jit_regs_init_value2(_jit_regs_t *regs, jit_insn_t insn, int flags); + +void _jit_regs_set_dest(_jit_regs_t *regs, int reg, int other_reg); +void _jit_regs_set_value1(_jit_regs_t *regs, int reg, int other_reg); +void _jit_regs_set_value2(_jit_regs_t *regs, int reg, int other_reg); +void _jit_regs_add_scratch(_jit_regs_t *regs, int reg); void _jit_regs_set_clobber(_jit_regs_t *regs, int reg); + +void _jit_regs_set_dest_from(_jit_regs_t *regs, jit_regused_t regset); +void _jit_regs_set_value1_from(_jit_regs_t *regs, jit_regused_t regset); +void _jit_regs_set_value2_from(_jit_regs_t *regs, jit_regused_t regset); +void _jit_regs_add_scratch_from(_jit_regs_t *regs, jit_regused_t regset); + int _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs); int _jit_regs_gen(jit_gencode_t gen, _jit_regs_t *regs); int _jit_regs_select(_jit_regs_t *regs); void _jit_regs_commit(jit_gencode_t gen, _jit_regs_t *regs); + int _jit_regs_dest(_jit_regs_t *regs); int _jit_regs_value1(_jit_regs_t *regs); int _jit_regs_value2(_jit_regs_t *regs); @@ -180,6 +194,7 @@ int _jit_regs_dest_other(_jit_regs_t *regs); int _jit_regs_value1_other(_jit_regs_t *regs); int _jit_regs_value2_other(_jit_regs_t *regs); int _jit_regs_scratch(_jit_regs_t *regs, int index); + int _jit_regs_lookup(char *name); #ifdef __cplusplus diff --git a/tools/gen-rules-parser.y b/tools/gen-rules-parser.y index af5beda..5132ca3 100644 --- a/tools/gen-rules-parser.y +++ b/tools/gen-rules-parser.y @@ -148,13 +148,24 @@ static int gensel_first_stack_reg = 8; /* st0 under x86 */ #define GENSEL_FLAG_CLOBBER 1 #define GENSEL_FLAG_EARLY_CLOBBER 2 +/* + * Value Type. + */ +#define GENSEL_VALUE_STRING 1 +#define GENSEL_VALUE_CHOICE 2 + /* * Option value. */ typedef struct gensel_value *gensel_value_t; struct gensel_value { - char *value; + int type; + union + { + char *value; + gensel_value_t children; + }; gensel_value_t next; }; @@ -199,6 +210,51 @@ static char *gensel_reg_flags[] = { "0", "_JIT_REGS_CLOBBER", "_JIT_REGS_EARLY_CLOBBER" }; +/* + * Create a value. + */ +static gensel_value_t +gensel_create_value(int type) +{ + gensel_value_t vp; + + vp = (gensel_value_t) malloc(sizeof(struct gensel_value)); + if(!vp) + { + exit(1); + } + + vp->type = type; + vp->next = 0; + return vp; +} + +/* + * Create string value. + */ +static gensel_value_t +gensel_create_string(char *value) +{ + gensel_value_t vp; + + vp = gensel_create_value(GENSEL_VALUE_STRING); + vp->value = value; + return vp; +} + +/* + * Create choice value. + */ +static gensel_value_t +gensel_create_choice(gensel_value_t children) +{ + gensel_value_t vp; + + vp = gensel_create_value(GENSEL_VALUE_CHOICE); + vp->children = children; + return vp; +} + /* * Create an option. */ @@ -221,7 +277,7 @@ gensel_create_option_2(int option, int flags, gensel_value_t values) } /* - * Create an option. + * Create an option with no flags. */ static gensel_option_t gensel_create_option(int option, gensel_value_t values) @@ -239,7 +295,14 @@ gensel_free_values(gensel_value_t values) while(values) { next = values->next; - free(values->value); + if(values->type == GENSEL_VALUE_STRING) + { + free(values->value); + } + else + { + gensel_free_values(values->children); + } free(values); values = next; } @@ -303,13 +366,13 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options int imms, max_imms; int have_local; int scratch, others; - int have_clobber; + int have_regset; max_regs = 0; other_regs_mask = 0; max_imms = 0; have_local = 0; - have_clobber = 0; + have_regset = 0; while(clauses != 0) { regs = 0; @@ -328,11 +391,21 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options case GENSEL_PATT_REG: case GENSEL_PATT_FREG: ++regs; + if(pattern->values + && pattern->values->type != GENSEL_VALUE_STRING) + { + have_regset = 1; + } break; case GENSEL_PATT_LREG: other_regs_mask |= (1 << regs); ++regs; + if(pattern->values + && pattern->values->type != GENSEL_VALUE_STRING) + { + have_regset = 1; + } break; case GENSEL_PATT_IMMZERO: @@ -357,17 +430,9 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options while(values) { ++scratch; - values = values->next; - } - - case GENSEL_PATT_CLOBBER: - values = pattern->values; - while(values) - { - if(values->value && strcmp(values->value, "*") != 0) + if(values->type != GENSEL_VALUE_STRING) { - have_clobber = 1; - break; + have_regset = 1; } values = values->next; } @@ -450,9 +515,9 @@ static void gensel_declare_regs(gensel_clause_t clauses, gensel_option_t options { printf("\tjit_nint local_offset;\n"); } - if(have_clobber) + if(have_regset) { - printf("\tint clobber;\n"); + printf("\tjit_regused_t regset;\n"); } } @@ -736,12 +801,11 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio char *other_names[9]; gensel_clause_t clause; gensel_option_t pattern; - gensel_value_t values; + gensel_value_t values, child; int first, seen_option; - int regs, imms, index; - int scratch, clobber_all; + int regs, imms, scratch, index; + int clobber_all, ternary; int contains_registers; - int ternary; /* If the clause is manual, then output it as-is */ if(gensel_search_option(options, GENSEL_OPT_MANUAL)) @@ -1097,7 +1161,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio || gensel_search_option(options, GENSEL_OPT_UNARY_NOTE) || gensel_search_option(options, GENSEL_OPT_UNARY_BRANCH))) { - printf("\t\t_jit_regs_set_dest(®s, insn, 0, -1, -1);\n"); + printf("\t\t_jit_regs_init_dest(®s, insn, 0);\n"); } } @@ -1114,61 +1178,71 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio case GENSEL_PATT_REG: case GENSEL_PATT_FREG: + printf("\t\t_jit_regs_init_%s(®s, insn, %s);\n", + args[index], gensel_reg_flags[pattern->flags]); if(pattern->values && pattern->values->value) { - printf("\t\t%s = _jit_regs_lookup(\"%s\");\n", - gensel_reg_names[regs], - pattern->values->value); - printf("\t\t_jit_regs_set_%s(®s, insn, %s, %s, -1);\n", - args[index], - gensel_reg_flags[pattern->flags], - gensel_reg_names[regs]); - } - else - { - printf("\t\t_jit_regs_set_%s(®s, insn, %s, -1, -1);\n", - args[index], - gensel_reg_flags[pattern->flags]); + if(pattern->values->type == GENSEL_VALUE_STRING) + { + printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"), -1);\n", + args[index], pattern->values->value); + } + else + { + printf("\t\tregset = jit_regused_init;\n"); + child = pattern->values->children; + while(child) + { + printf("\t\t%s = _jit_regs_lookup(\"%s\");\n", + gensel_reg_names[regs], child->value); + printf("\t\tif(%s >= 0)\n", gensel_reg_names[regs]); + printf("\t\t\tjit_reg_set_used(regset, %s);\n", + gensel_reg_names[regs]); + child = child->next; + } + printf("\t\t_jit_regs_set_%s_from(®s, regset);\n", + args[index]); + } } ++regs; ++index; break; case GENSEL_PATT_LREG: + printf("\t\t_jit_regs_init_%s(®s, insn, %s);\n", + args[index], gensel_reg_flags[pattern->flags]); if(pattern->values && pattern->values->value) { - if(pattern->values->next - && pattern->values->next->value) + if(pattern->values->type == GENSEL_VALUE_STRING) { - printf("\t\t%s = _jit_regs_lookup(\"%s\")];\n", - gensel_reg_names[regs], - pattern->values->value); - printf("\t\t%s = _jit_regs_lookup(\"%s\")];\n", - gensel_other_reg_names[regs], - pattern->values->next->value); - printf("\t\t_jit_regs_set_%s(®s, insn, %s, %s, %s);\n", - args[index], - gensel_reg_flags[pattern->flags], - gensel_reg_names[regs], - gensel_other_reg_names[regs]); + if(pattern->values->next && pattern->values->next->value) + { + printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"), _jit_regs_lookup(\"%s\"));\n", + args[index], pattern->values->value, pattern->values->next->value); + } + else + { + printf("\t\t_jit_regs_set_%s(®s, _jit_regs_lookup(\"%s\"), -1);\n", + args[index], pattern->values->value); + } } else { - printf("\t\t%s = _jit_regs_lookup(\"%s\")];\n", - gensel_reg_names[regs], - pattern->values->value); - printf("\t\t_jit_regs_set_%s(®s, insn, %s, %s, -1);\n", - args[index], - gensel_reg_flags[pattern->flags], - gensel_reg_names[regs]); + printf("\t\tregset = jit_regused_init;\n"); + child = pattern->values->children; + while(child) + { + printf("\t\t%s = _jit_regs_lookup(\"%s\");\n", + gensel_reg_names[regs], child->value); + printf("\t\tif(%s >= 0)\n", gensel_reg_names[regs]); + printf("\t\t\tjit_reg_set_used(regset, %s);\n", + gensel_reg_names[regs]); + child = child->next; + } + printf("\t\t_jit_regs_set_%s_from(®s, regset);\n", + args[index]); } } - else - { - printf("\t\t_jit_regs_set_%s(®s, insn, %s, -1, -1);\n", - args[index], - gensel_reg_flags[pattern->flags]); - } ++regs; ++index; break; @@ -1187,17 +1261,34 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio values = pattern->values; while(values) { - if(values->value && strcmp(values->value, "?") != 0) + if(values->value + && (values->type != GENSEL_VALUE_STRING + || strcmp(values->value, "?") != 0)) { - printf("\t\t%s = _jit_regs_lookup(\"%s\")];\n", - gensel_reg_names[regs], - values->value); - printf("\t\t_jit_regs_set_scratch(®s, %s);\n", - gensel_reg_names[regs]); + if(values->type == GENSEL_VALUE_STRING) + { + printf("\t\t_jit_regs_add_scratch(®s, _jit_regs_lookup(\"%s\"));\n", + values->value); + } + else + { + printf("\t\tregset = jit_regused_init;\n"); + child = values->children; + while(child) + { + printf("\t\t%s = _jit_regs_lookup(\"%s\");\n", + gensel_reg_names[regs], child->value); + printf("\t\tif(%s >= 0)\n", gensel_reg_names[regs]); + printf("\t\t\tjit_reg_set_used(regset, %s);\n", + gensel_reg_names[regs]); + child = child->next; + } + printf("\t\t_jit_regs_add_scratch_from(®s, regset);\n"); + } } else { - printf("\t\t_jit_regs_set_scratch(®s, -1);\n"); + printf("\t\t_jit_regs_add_scratch(®s, -1);\n"); } ++regs; ++index; @@ -1211,9 +1302,8 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio { if(values->value && strcmp(values->value, "*") != 0) { - printf("\t\tclobber = _jit_regs_lookup(\"%s\");\n", + printf("\t\t_jit_regs_set_clobber(®s, _jit_regs_lookup(\"%s\"));\n", values->value); - printf("\t\t_jit_regs_set_clobber(®s, clobber);\n"); } values = values->next; } @@ -1289,7 +1379,7 @@ static void gensel_output_clauses(gensel_clause_t clauses, gensel_option_t optio values = pattern->values; while(values) { - printf("\t\t%s = _jit_regs_scratch(®s, %d);\n", + printf("\t\t%s = _jit_reg_info[_jit_regs_scratch(®s, %d)].cpu_reg;\n", gensel_reg_names[regs], scratch); ++regs; ++scratch; @@ -1462,7 +1552,7 @@ static void gensel_output_supported(void) %type Clauses Clause %type Options OptionList Pattern Pattern2 %type