From 24a2487c1825a9b032c6fd58ba2f3b5714bd2052 Mon Sep 17 00:00:00 2001 From: steve Date: Sun, 2 Jun 2002 18:57:17 +0000 Subject: [PATCH] Generate %cmpi/u where appropriate. --- tgt-vvp/eval_expr.c | 217 ++++++++++++++++++++++++++++-------------- tgt-vvp/vvp_priv.h | 9 +- tgt-vvp/vvp_process.c | 25 ++++- 3 files changed, 179 insertions(+), 72 deletions(-) diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 78d168e94..869f2e64c 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: eval_expr.c,v 1.62 2002/05/31 20:04:57 steve Exp $" +#ident "$Id: eval_expr.c,v 1.63 2002/06/02 18:57:17 steve Exp $" #endif # include "vvp_priv.h" @@ -94,16 +94,158 @@ unsigned short allocate_vector(unsigned short wid) return base; } +int number_is_unknown(ivl_expr_t ex) +{ + const char*bits; + unsigned idx; + + assert(ivl_expr_type(ex) == IVL_EX_NUMBER); + + bits = ivl_expr_bits(ex); + for (idx = 0 ; idx < ivl_expr_width(ex) ; idx += 1) + if ((bits[idx] != '0') && (bits[idx] != '1')) + return 1; + + return 0; +} + +/* + * This function returns TRUE if the number can be represented in a + * 16bit immediate value. This amounts to looking for non-zero bits + * above bitX. The maximum size of the immediate may vary, so use + * lim_wid at the width limit to use. + */ +int number_is_immediate(ivl_expr_t ex, unsigned lim_wid) +{ + const char*bits; + unsigned idx; + + assert(ivl_expr_type(ex) == IVL_EX_NUMBER); + + bits = ivl_expr_bits(ex); + for (idx = lim_wid ; idx < ivl_expr_width(ex) ; idx += 1) + if (bits[idx] != '0') + return 0; + + return 1; +} + +unsigned long get_number_immediate(ivl_expr_t ex) +{ + unsigned long imm = 0; + unsigned idx; + + switch (ivl_expr_type(ex)) { + case IVL_EX_ULONG: + imm = ivl_expr_uvalue(ex); + break; + + case IVL_EX_NUMBER: { + const char*bits = ivl_expr_bits(ex); + unsigned nbits = ivl_expr_width(ex); + for (idx = 0 ; idx < nbits ; idx += 1) switch (bits[idx]){ + case '0': + break; + case '1': + imm |= 1 << idx; + break; + default: + assert(0); + } + break; + } + + default: + assert(0); + } + + return imm; +} + +static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid, + ivl_expr_t le, + ivl_expr_t re) +{ + unsigned wid; + struct vector_info lv; + unsigned long imm = get_number_immediate(re); + + wid = ivl_expr_width(le); + lv = draw_eval_expr_wid(le, wid); + + switch (ivl_expr_opcode(exp)) { + case 'E': /* === */ + fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", + lv.base, imm, wid); + clr_vector(lv); + lv.base = 6; + lv.wid = 1; + break; + + case 'e': /* == */ + fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", + lv.base, imm, wid); + clr_vector(lv); + lv.base = 4; + lv.wid = 1; + break; + + case 'N': /* !== */ + fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", + lv.base, imm, wid); + clr_vector(lv); + lv.base = 6; + lv.wid = 1; + fprintf(vvp_out, " %%inv 6, 1;\n"); + break; + + case 'n': /* != */ + fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", + lv.base, imm, wid); + clr_vector(lv); + lv.base = 4; + lv.wid = 1; + fprintf(vvp_out, " %%inv 4, 1;\n"); + break; + + default: + assert(0); + } + + /* Move the result out out the 4-7 bit that the compare + uses. This is because that bit may be clobbered by other + expressions. */ + { unsigned short base = allocate_vector(ewid); + fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base); + lv.base = base; + lv.wid = ewid; + if (ewid > 1) + fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1); + } + + return lv; +} static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid) { ivl_expr_t le = ivl_expr_oper1(exp); ivl_expr_t re = ivl_expr_oper2(exp); + unsigned wid; + struct vector_info lv; struct vector_info rv; - unsigned wid = ivl_expr_width(le); + if ((ivl_expr_type(re) == IVL_EX_ULONG) + && (0 == (ivl_expr_uvalue(re) & ~0xffff))) + return draw_eq_immediate(exp, ewid, le, re); + + if ((ivl_expr_type(re) == IVL_EX_NUMBER) + && (! number_is_unknown(re)) + && number_is_immediate(re, 16)) + return draw_eq_immediate(exp, ewid, le, re); + + wid = ivl_expr_width(le); if (ivl_expr_width(re) > wid) wid = ivl_expr_width(re); @@ -539,74 +681,6 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid) return lv; } -static int number_is_unknown(ivl_expr_t ex) -{ - const char*bits; - unsigned idx; - - assert(ivl_expr_type(ex) == IVL_EX_NUMBER); - - bits = ivl_expr_bits(ex); - for (idx = 0 ; idx < ivl_expr_width(ex) ; idx += 1) - if ((bits[idx] != '0') && (bits[idx] != '1')) - return 1; - - return 0; -} - -/* - * This function returns TRUE if the number can be represented in a - * 16bit immediate value. This amounts to looking for non-zero bits - * above bitX. The maximum size of the immediate may vary, so use - * lim_wid at the width limit to use. - */ -static int number_is_immediate(ivl_expr_t ex, unsigned lim_wid) -{ - const char*bits; - unsigned idx; - - assert(ivl_expr_type(ex) == IVL_EX_NUMBER); - - bits = ivl_expr_bits(ex); - for (idx = lim_wid ; idx < ivl_expr_width(ex) ; idx += 1) - if (bits[idx] != '0') - return 0; - - return 1; -} - -static unsigned long get_number_immediate(ivl_expr_t ex) -{ - unsigned long imm = 0; - unsigned idx; - - switch (ivl_expr_type(ex)) { - case IVL_EX_ULONG: - imm = ivl_expr_uvalue(ex); - break; - - case IVL_EX_NUMBER: { - const char*bits = ivl_expr_bits(ex); - unsigned nbits = ivl_expr_width(ex); - for (idx = 0 ; idx < nbits ; idx += 1) switch (bits[idx]){ - case '0': - break; - case '1': - imm |= 1 << idx; - break; - default: - assert(0); - } - break; - } - - default: - assert(0); - } - - return imm; -} - static struct vector_info draw_add_immediate(ivl_expr_t le, ivl_expr_t re, unsigned wid) @@ -1648,6 +1722,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp) /* * $Log: eval_expr.c,v $ + * Revision 1.63 2002/06/02 18:57:17 steve + * Generate %cmpi/u where appropriate. + * * Revision 1.62 2002/05/31 20:04:57 steve * Generate %muli instructions when possible. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index caad8ba7d..c06038a9d 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_priv.h,v 1.13 2002/04/22 02:41:30 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.14 2002/06/02 18:57:17 steve Exp $" #endif # include "ivl_target.h" @@ -81,6 +81,10 @@ extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp); extern unsigned short allocate_vector(unsigned short wid); extern void clr_vector(struct vector_info vec); +extern int number_is_unknown(ivl_expr_t ex); +extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid); +extern unsigned long get_number_immediate(ivl_expr_t ex); + /* * These are used to count labels as I generate code. */ @@ -89,6 +93,9 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.14 2002/06/02 18:57:17 steve + * Generate %cmpi/u where appropriate. + * * Revision 1.13 2002/04/22 02:41:30 steve * Reduce the while loop expression if needed. * diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 9ad7847e2..ccb2dcf62 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_process.c,v 1.58 2002/05/27 00:08:45 steve Exp $" +#ident "$Id: vvp_process.c,v 1.59 2002/06/02 18:57:17 steve Exp $" #endif # include "vvp_priv.h" @@ -444,6 +444,26 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) continue; } + /* Is the guard expression something I can pass to a + %cmpi/u instruction? If so, use that instead. */ + + if ((ivl_statement_type(net) == IVL_ST_CASE) + && (ivl_expr_type(cex) == IVL_EX_NUMBER) + && (! number_is_unknown(cex)) + && number_is_immediate(cex, 16)) { + + unsigned long imm = get_number_immediate(cex); + + fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n", + cond.base, imm, cond.wid); + fprintf(vvp_out, " %%jmp/1 T_%d.%d, 6;\n", + thread_count, local_base+idx); + + continue; + } + + /* Oh well, do this case the hard way. */ + cvec = draw_eval_expr_wid(cex, cond.wid); assert(cvec.wid == cond.wid); @@ -1200,6 +1220,9 @@ int draw_func_definition(ivl_scope_t scope) /* * $Log: vvp_process.c,v $ + * Revision 1.59 2002/06/02 18:57:17 steve + * Generate %cmpi/u where appropriate. + * * Revision 1.58 2002/05/27 00:08:45 steve * Support carrying the scope of named begin-end * blocks down to the code generator, and have