From 93d7bedc73e87e40d9d94ae093af38a1beb7b156 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 8 Jun 2004 05:33:37 +0000 Subject: [PATCH] Introduce conditional rules into "gen-sel" so that we can disable certain rules on ARM platforms that lack floating-point support. --- ChangeLog | 5 + jit/jit-rules-arm.sel | 387 ++++++++++++++++++++++++++++++++-------- tools/gen-sel-parser.y | 89 +++++++-- tools/gen-sel-scanner.l | 2 +- 4 files changed, 398 insertions(+), 85 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87b755a..b122170 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,11 @@ * jit/jit-gen-arm.h (arm_call): use a more efficient form of call for offsets beyond the simple target range. + * jit/jit-rules-arm.sel, tools/gen-sel-parser.y, + tools/gen-sel-scanner.l: introduce conditional rules into "gen-sel" + so that we can disable certain rules on ARM platforms that lack + floating-point support. + 2004-06-08 Miroslaw Dobrzanski-Neumann * jit/jit-alloc.c: fix ROUND_END_PTR so that it adds the size diff --git a/jit/jit-rules-arm.sel b/jit/jit-rules-arm.sel index 046359d..810cf08 100644 --- a/jit/jit-rules-arm.sel +++ b/jit/jit-rules-arm.sel @@ -149,77 +149,52 @@ JIT_OP_INEG: unary arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0); } -JIT_OP_FADD: binary +JIT_OP_FADD (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2); } -JIT_OP_FSUB: binary +JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2); } -JIT_OP_FMUL: binary +JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2); } -JIT_OP_FDIV: binary +JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2); } -JIT_OP_FNEG: unary +JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS): unary [freg] -> { arm_alu_freg_32(inst, ARM_MNF, $1, $1); } -JIT_OP_DADD: binary +JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2); } -JIT_OP_DSUB: binary +JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2); } -JIT_OP_DMUL: binary +JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2); } -JIT_OP_DDIV: binary +JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS): binary [freg, freg] -> { arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2); } -JIT_OP_DNEG: unary - [freg] -> { - arm_alu_freg(inst, ARM_MNF, $1, $1); - } - -JIT_OP_NFADD: binary - [freg, freg] -> { - arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2); - } - -JIT_OP_NFSUB: binary - [freg, freg] -> { - arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2); - } - -JIT_OP_NFMUL: binary - [freg, freg] -> { - arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2); - } - -JIT_OP_NFDIV: binary - [freg, freg] -> { - arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2); - } - -JIT_OP_NFNEG: unary +JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS): unary [freg] -> { arm_alu_freg(inst, ARM_MNF, $1, $1); } @@ -637,34 +612,142 @@ JIT_OP_RETURN_LONG: spill_before inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_FLOAT32: unary_note +JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_branch [freg] -> { if($1 != 0) { arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1); } + inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_FLOAT64: unary_note - [freg] -> { - if($1 != 0) +JIT_OP_RETURN_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual + [] -> { + arm_inst_ptr inst; + _jit_regs_spill_all(gen); + _jit_gen_fix_value(insn->value1); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) { - arm_alu_freg(inst, ARM_MVF, ARM_F0, $1); + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_R0, ((int *)(insn->value1->address))[0]); + } + else + { + arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset); } + inst = jump_to_epilog(gen, inst, block); + gen->posn.ptr = (unsigned char *)inst; } -JIT_OP_RETURN_NFLOAT: unary_note +JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT + (JIT_ARM_HAS_FLOAT_REGS): unary_branch [freg] -> { if($1 != 0) { arm_alu_freg(inst, ARM_MVF, ARM_F0, $1); } + inst = jump_to_epilog(gen, inst, block); } -JIT_OP_RETURN_SMALL_STRUCT: spill_before +JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual [] -> { - /* TODO: load the structure value into r0:r1 */ - TODO(); + arm_inst_ptr inst; + _jit_regs_spill_all(gen); + _jit_gen_fix_value(insn->value1); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_R0, ((int *)(insn->value1->address))[0]); + arm_mov_reg_imm(inst, ARM_R1, ((int *)(insn->value1->address))[1]); + } + else + { + arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset); + arm_load_membase(inst, ARM_R1, ARM_FP, + insn->value1->frame_offset + 4); + } + inst = jump_to_epilog(gen, inst, block); + gen->posn.ptr = (unsigned char *)inst; + } + +JIT_OP_RETURN_SMALL_STRUCT: unary_branch + [reg] -> { + int temp_reg = $1; + if(temp_reg < 3) + { + arm_mov_reg_reg(inst, ARM_WORK, temp_reg); + temp_reg = ARM_WORK; + } + switch(insn->value2->address) + { + case 1: + { + arm_load_membase_byte(inst, ARM_R0, temp_reg, 0); + } + break; + + case 2: + { + arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0); + } + break; + + case 3: + { + arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0); + arm_load_membase_byte(inst, ARM_R1, temp_reg, 2); + arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16); + arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1); + } + break; + + case 4: + { + arm_load_membase(inst, ARM_R0, temp_reg, 0); + } + break; + + case 5: + { + arm_load_membase(inst, ARM_R0, temp_reg, 0); + arm_load_membase_byte(inst, ARM_R1, temp_reg, 4); + } + break; + + case 6: + { + arm_load_membase(inst, ARM_R0, temp_reg, 0); + arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4); + } + break; + + case 7: + { + arm_load_membase(inst, ARM_R0, temp_reg, 0); + arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4); + arm_load_membase_byte(inst, ARM_R2, temp_reg, 6); + arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16); + arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2); + } + break; + + case 8: + { + arm_load_membase(inst, ARM_R0, temp_reg, 0); + arm_load_membase(inst, ARM_R1, temp_reg, 4); + } + break; + } inst = jump_to_epilog(gen, inst, block); } @@ -738,21 +821,115 @@ JIT_OP_COPY_LOAD_USHORT: unary JIT_OP_COPY_INT: unary [reg] -> {} -JIT_OP_COPY_LONG: spill_before +JIT_OP_COPY_LONG: manual [] -> { - /* TODO */ - TODO(); + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_regs_force_out(gen, insn->dest, 1); + _jit_gen_fix_value(insn->value1); + _jit_gen_fix_value(insn->dest); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset); + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[1]); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset + 4); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset); + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset + 4); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset + 4); + } + gen->posn.ptr = (unsigned char *)inst; } -JIT_OP_COPY_FLOAT32: unary +JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary [freg] -> {} -JIT_OP_COPY_FLOAT64: unary - [freg] -> {} +JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual + [] -> { + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_regs_force_out(gen, insn->dest, 1); + _jit_gen_fix_value(insn->value1); + _jit_gen_fix_value(insn->dest); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + } + arm_store_membase(inst, ARM_WORK, ARM_FP, insn->dest->frame_offset); + gen->posn.ptr = (unsigned char *)inst; + } -JIT_OP_COPY_NFLOAT: unary +JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary [freg] -> {} +JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual + [] -> { + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_regs_force_out(gen, insn->dest, 1); + _jit_gen_fix_value(insn->value1); + _jit_gen_fix_value(insn->dest); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset); + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[1]); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset + 4); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset); + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset + 4); + arm_store_membase(inst, ARM_WORK, ARM_FP, + insn->dest->frame_offset + 4); + } + gen->posn.ptr = (unsigned char *)inst; + } + JIT_OP_COPY_STRUCT: manual [] -> { /* TODO */ @@ -846,25 +1023,103 @@ JIT_OP_PUSH_INT: unary_note JIT_OP_PUSH_LONG: manual [] -> { - /* TODO */ - TODO(); + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_gen_fix_value(insn->value1); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[1]); + arm_push_reg(inst, ARM_WORK); + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + arm_push_reg(inst, ARM_WORK); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset + 4); + arm_push_reg(inst, ARM_WORK); + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + arm_push_reg(inst, ARM_WORK); + } + gen->posn.ptr = (unsigned char *)inst; } -JIT_OP_PUSH_FLOAT32: unary_note +JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note [freg] -> { arm_push_reg_float32(inst, $1); } -JIT_OP_PUSH_FLOAT64: unary_note - [freg] -> { - arm_push_reg_float64(inst, $1); +JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual + [] -> { + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_gen_fix_value(insn->value1); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + } + arm_push_reg(inst, ARM_WORK); + gen->posn.ptr = (unsigned char *)inst; } -JIT_OP_PUSH_NFLOAT: unary_note +JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary_note [freg] -> { arm_push_reg_float64(inst, $1); } +JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual + [] -> { + arm_inst_ptr inst; + _jit_regs_force_out(gen, insn->value1, 0); + _jit_gen_fix_value(insn->value1); + inst = (arm_inst_ptr)(gen->posn.ptr); + if(!jit_cache_check_for_n(&(gen->posn), 32)) + { + jit_cache_mark_full(&(gen->posn)); + return; + } + if(insn->value1->is_constant) + { + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[1]); + arm_push_reg(inst, ARM_WORK); + arm_mov_reg_imm(inst, ARM_WORK, + ((int *)(insn->value1->address))[0]); + arm_push_reg(inst, ARM_WORK); + } + else + { + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset + 4); + arm_push_reg(inst, ARM_WORK); + arm_load_membase(inst, ARM_WORK, ARM_FP, + insn->value1->frame_offset); + arm_push_reg(inst, ARM_WORK); + } + gen->posn.ptr = (unsigned char *)inst; + } + JIT_OP_PUSH_STRUCT: unary_note [reg] -> { /* TODO */ @@ -1009,13 +1264,7 @@ JIT_OP_LOAD_RELATIVE_FLOAT32: manual TODO(); } -JIT_OP_LOAD_RELATIVE_FLOAT64: manual - [] -> { - /* TODO */ - TODO(); - } - -JIT_OP_LOAD_RELATIVE_NFLOAT: manual +JIT_OP_LOAD_RELATIVE_FLOAT64, JIT_OP_LOAD_RELATIVE_NFLOAT: manual [] -> { /* TODO */ TODO(); @@ -1131,13 +1380,7 @@ JIT_OP_STORE_RELATIVE_FLOAT32: manual TODO(); } -JIT_OP_STORE_RELATIVE_FLOAT64: manual - [] -> { - /* TODO */ - TODO(); - } - -JIT_OP_STORE_RELATIVE_NFLOAT: manual +JIT_OP_STORE_RELATIVE_FLOAT64, JIT_OP_STORE_RELATIVE_NFLOAT: manual [] -> { /* TODO */ TODO(); diff --git a/tools/gen-sel-parser.y b/tools/gen-sel-parser.y index dd6e2c1..dfc2e99 100644 --- a/tools/gen-sel-parser.y +++ b/tools/gen-sel-parser.y @@ -21,6 +21,11 @@ #include #include +#ifdef HAVE_STRING_H + #include +#elif defined(HAVE_STRINGS_H) + #include +#endif #ifdef HAVE_STDLIB_H #include #endif @@ -601,12 +606,13 @@ static void gensel_output_clauses(gensel_clause_t clauses, int options) * List of opcodes that are supported by the input rules. */ static char **supported = 0; +static char **supported_options = 0; static int num_supported = 0; /* * Add an opcode to the supported list. */ -static void gensel_add_supported(char *name) +static void gensel_add_supported(char *name, char *option) { supported = (char **)realloc (supported, (num_supported + 1) * sizeof(char *)); @@ -614,7 +620,14 @@ static void gensel_add_supported(char *name) { exit(1); } - supported[num_supported++] = name; + supported[num_supported] = name; + supported_options = (char **)realloc + (supported_options, (num_supported + 1) * sizeof(char *)); + if(!supported_options) + { + exit(1); + } + supported_options[num_supported++] = option; } /* @@ -625,7 +638,23 @@ static void gensel_output_supported(void) int index; for(index = 0; index < num_supported; ++index) { - printf("case %s:\n", supported[index]); + if(supported_options[index]) + { + if(supported_options[index][0] == '!') + { + printf("#ifndef %s\n", supported_options[index] + 1); + } + else + { + printf("#ifdef %s\n", supported_options[index]); + } + printf("case %s:\n", supported[index]); + printf("#endif\n"); + } + else + { + printf("case %s:\n", supported[index]); + } } printf("\treturn 1;\n\n"); } @@ -691,7 +720,7 @@ static void gensel_output_supported(void) /* * Define the yylval types of the various non-terminals. */ -%type IDENTIFIER +%type IDENTIFIER IfClause IdentifierList %type CODE_BLOCK %type Options OptionList Option PatternElement %type Clauses Clause @@ -713,19 +742,30 @@ Rules ; Rule - : IDENTIFIER ':' Options Clauses { + : IdentifierList IfClause ':' Options Clauses { + if($2) + { + if(($2)[0] == '!') + { + printf("#ifndef %s\n\n", $2 + 1); + } + else + { + printf("#ifdef %s\n\n", $2); + } + } printf("case %s:\n{\n", $1); - if(($3 & GENSEL_OPT_MANUAL) == 0) + if(($4 & GENSEL_OPT_MANUAL) == 0) { printf("\t%s inst;\n", gensel_inst_type); } - gensel_declare_regs($4.head, $3); - if(($3 & GENSEL_OPT_SPILL_BEFORE) != 0) + gensel_declare_regs($5.head, $4); + if(($4 & GENSEL_OPT_SPILL_BEFORE) != 0) { printf("\t_jit_regs_spill_all(gen);\n"); } - gensel_output_clauses($4.head, $3); - if(($3 & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY)) != 0) + gensel_output_clauses($5.head, $4); + if(($4 & (GENSEL_OPT_BINARY | GENSEL_OPT_UNARY)) != 0) { printf("\tif((insn->flags & JIT_INSN_DEST_NEXT_USE) != 0)\n"); printf("\t{\n"); @@ -742,14 +782,39 @@ Rule printf("\t}\n"); } printf("}\nbreak;\n\n"); - gensel_free_clauses($4.head); - gensel_add_supported($1); + if($2) + { + printf("#endif /* %s */\n\n", $2); + } + gensel_free_clauses($5.head); + gensel_add_supported($1, $2); } | K_INST_TYPE IDENTIFIER { gensel_inst_type = $2; } ; +IdentifierList + : IDENTIFIER { $$ = $1; } + | IdentifierList ',' IDENTIFIER { + char *result = (char *)malloc(strlen($1) + strlen($3) + 16); + if(!result) + { + exit(1); + } + strcpy(result, $1); + strcat(result, ":\ncase "); + strcat(result, $3); + free($1); + free($3); + $$ = result; + } + +IfClause + : /* empty */ { $$ = 0; } + | '(' IDENTIFIER ')' { $$ = $2; } + ; + Options : /* empty */ { $$ = 0; } | OptionList { $$ = $1; } diff --git a/tools/gen-sel-scanner.l b/tools/gen-sel-scanner.l index 374a533..2aa44ee 100644 --- a/tools/gen-sel-scanner.l +++ b/tools/gen-sel-scanner.l @@ -106,7 +106,7 @@ WHITE [ \t\v\r\f] "more_space" { RETURNTOK(K_MORE_SPACE); } "%inst_type" { RETURNTOK(K_INST_TYPE); } -{IDALPHA}({DIGIT}|{IDALPHA})* { +"!"?{IDALPHA}({DIGIT}|{IDALPHA})* { yylval.name = gensel_strdup(yytext); if(!(yylval.name)) { -- 2.47.3