Generate %cmpi/u where appropriate.
This commit is contained in:
parent
d68153dea3
commit
24a2487c18
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue