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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "vvp_priv.h"
|
# include "vvp_priv.h"
|
||||||
|
|
@ -94,16 +94,158 @@ unsigned short allocate_vector(unsigned short wid)
|
||||||
return base;
|
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)
|
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 le = ivl_expr_oper1(exp);
|
||||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||||
|
|
||||||
|
unsigned wid;
|
||||||
|
|
||||||
struct vector_info lv;
|
struct vector_info lv;
|
||||||
struct vector_info rv;
|
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)
|
if (ivl_expr_width(re) > wid)
|
||||||
wid = ivl_expr_width(re);
|
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;
|
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,
|
static struct vector_info draw_add_immediate(ivl_expr_t le,
|
||||||
ivl_expr_t re,
|
ivl_expr_t re,
|
||||||
unsigned wid)
|
unsigned wid)
|
||||||
|
|
@ -1648,6 +1722,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: eval_expr.c,v $
|
* $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
|
* Revision 1.62 2002/05/31 20:04:57 steve
|
||||||
* Generate %muli instructions when possible.
|
* Generate %muli instructions when possible.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "ivl_target.h"
|
# 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 unsigned short allocate_vector(unsigned short wid);
|
||||||
extern void clr_vector(struct vector_info vec);
|
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.
|
* These are used to count labels as I generate code.
|
||||||
*/
|
*/
|
||||||
|
|
@ -89,6 +93,9 @@ extern unsigned thread_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vvp_priv.h,v $
|
* $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
|
* Revision 1.13 2002/04/22 02:41:30 steve
|
||||||
* Reduce the while loop expression if needed.
|
* Reduce the while loop expression if needed.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "vvp_priv.h"
|
# include "vvp_priv.h"
|
||||||
|
|
@ -444,6 +444,26 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||||
continue;
|
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);
|
cvec = draw_eval_expr_wid(cex, cond.wid);
|
||||||
assert(cvec.wid == cond.wid);
|
assert(cvec.wid == cond.wid);
|
||||||
|
|
||||||
|
|
@ -1200,6 +1220,9 @@ int draw_func_definition(ivl_scope_t scope)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: vvp_process.c,v $
|
* $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
|
* Revision 1.58 2002/05/27 00:08:45 steve
|
||||||
* Support carrying the scope of named begin-end
|
* Support carrying the scope of named begin-end
|
||||||
* blocks down to the code generator, and have
|
* blocks down to the code generator, and have
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue