Remove some dead code in tgt-vvp.
This commit is contained in:
parent
1905264061
commit
079065ea73
|
|
@ -414,6 +414,7 @@ static struct vector_info draw_eq_immediate(ivl_expr_t expr, unsigned ewid,
|
||||||
* This handles the special case that the operands of the comparison
|
* This handles the special case that the operands of the comparison
|
||||||
* are real valued expressions.
|
* are real valued expressions.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr)
|
static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
struct vector_info res;
|
struct vector_info res;
|
||||||
|
|
@ -443,6 +444,15 @@ static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr)
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static struct vector_info draw_binary_expr_eq_real(ivl_expr_t expr)
|
||||||
|
{
|
||||||
|
struct vector_info res = {0, 0};
|
||||||
|
fprintf(vvp_out, " ; draw_binary_expr_real: dead code\n");
|
||||||
|
vvp_errors += 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr_eq_string(ivl_expr_t expr)
|
static struct vector_info draw_binary_expr_eq_string(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
|
|
@ -753,117 +763,6 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t expr, unsigned wid)
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr_lor(ivl_expr_t expr, unsigned wid,
|
|
||||||
int stuff_ok_flag)
|
|
||||||
{
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
|
||||||
|
|
||||||
struct vector_info lv;
|
|
||||||
struct vector_info rv;
|
|
||||||
|
|
||||||
lv = draw_eval_expr(le, STUFF_OK_XZ);
|
|
||||||
|
|
||||||
/* if the left operand has width, then evaluate the single-bit
|
|
||||||
logical equivalent. */
|
|
||||||
if ((lv.base >= 4) && (lv.wid > 1)) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
clr_vector(lv);
|
|
||||||
tmp.base = allocate_vector(1);
|
|
||||||
tmp.wid = 1;
|
|
||||||
assert(tmp.base);
|
|
||||||
fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base,
|
|
||||||
lv.base, lv.wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The right expression may be left in registers 4-7 because
|
|
||||||
I'll be using it immediately. */
|
|
||||||
rv = draw_eval_expr(re, STUFF_OK_XZ|STUFF_OK_47);
|
|
||||||
|
|
||||||
/* if the right operand has width, then evaluate the single-bit
|
|
||||||
logical equivalent. */
|
|
||||||
if ((rv.base >= 4) && (rv.wid > 1)) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
clr_vector(rv);
|
|
||||||
tmp.base = allocate_vector(1);
|
|
||||||
tmp.wid = 1;
|
|
||||||
assert(tmp.base);
|
|
||||||
fprintf(vvp_out, " %%or/r %u, %u, %u;\n", tmp.base,
|
|
||||||
rv.base, rv.wid);
|
|
||||||
rv = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (lv.base < 4) {
|
|
||||||
if (rv.base < 4) {
|
|
||||||
unsigned lb = lv.base;
|
|
||||||
unsigned rb = rv.base;
|
|
||||||
|
|
||||||
if ((lb == 0) && (rb == 0)) {
|
|
||||||
lv.base = 0;
|
|
||||||
|
|
||||||
} else if ((lb == 1) || (rb == 1)) {
|
|
||||||
lv.base = 1;
|
|
||||||
} else {
|
|
||||||
lv.base = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (lv.base==0) {
|
|
||||||
lv = rv;
|
|
||||||
} else {
|
|
||||||
fprintf(vvp_out, " %%or %u, %u, 1;\n", rv.base, lv.base);
|
|
||||||
lv = rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (rv.base == 0) {
|
|
||||||
; /* Just return lv. */
|
|
||||||
} else {
|
|
||||||
if (rv.base >= 8 && lv.base < 8 && !(stuff_ok_flag&STUFF_OK_47)) {
|
|
||||||
/* If STUFF_OK_47 is false, and rv is not in the
|
|
||||||
47 area (and lv is) then plan to or the result
|
|
||||||
into the rv instead. This can case a %mov later. */
|
|
||||||
struct vector_info tmp = lv;
|
|
||||||
lv = rv;
|
|
||||||
rv = tmp;
|
|
||||||
}
|
|
||||||
fprintf(vvp_out, " %%or %u, %u, 1;\n", lv.base, rv.base);
|
|
||||||
if (rv.base >= 8) clr_vector(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wid==1 && (lv.base<4 || lv.base>=8 || (stuff_ok_flag&STUFF_OK_47)))
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
/* If we only want the single bit result, then we are done. */
|
|
||||||
if (wid == 1) {
|
|
||||||
if (lv.base >= 4 && lv.base < 8) {
|
|
||||||
unsigned tmp = allocate_vector(1);
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, 1;\n", tmp, lv.base);
|
|
||||||
lv.base = tmp;
|
|
||||||
}
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the result into a zero-padded result. */
|
|
||||||
{ unsigned base = allocate_vector(wid);
|
|
||||||
if (base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of padded logical OR.\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
|
|
||||||
if (lv.base >= 8) clr_vector(lv);
|
|
||||||
lv.base = base;
|
|
||||||
lv.wid = wid;
|
|
||||||
fprintf(vvp_out, " %%pad %u, 0, %u;\n", base+1, wid-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr_le_real(ivl_expr_t expr)
|
static struct vector_info draw_binary_expr_le_real(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
struct vector_info res;
|
struct vector_info res;
|
||||||
|
|
@ -1181,423 +1080,6 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t expr,
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vector_info draw_logic_immediate(ivl_expr_t expr,
|
|
||||||
ivl_expr_t le,
|
|
||||||
ivl_expr_t re,
|
|
||||||
unsigned wid)
|
|
||||||
{
|
|
||||||
struct vector_info lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
assert(number_is_immediate(re, IMM_WID, 0));
|
|
||||||
assert(! number_is_unknown(re));
|
|
||||||
unsigned long imm = get_number_immediate(re);
|
|
||||||
|
|
||||||
assert(lv.base >= 4);
|
|
||||||
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
fprintf(vvp_out, " %%andi %u, %lu, %u;\n", lv.base, imm, lv.wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr_logic(ivl_expr_t expr,
|
|
||||||
unsigned wid)
|
|
||||||
{
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
|
||||||
struct vector_info lv;
|
|
||||||
struct vector_info rv;
|
|
||||||
|
|
||||||
if (ivl_expr_opcode(expr) == '&') {
|
|
||||||
if (number_is_immediate(re, IMM_WID, 0) && !number_is_unknown(re))
|
|
||||||
return draw_logic_immediate(expr, le, re, wid);
|
|
||||||
if (number_is_immediate(le, IMM_WID, 0) && !number_is_unknown(le))
|
|
||||||
return draw_logic_immediate(expr, re, le, wid);
|
|
||||||
}
|
|
||||||
|
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
|
||||||
|
|
||||||
/* The result goes into the left operand, and that is returned
|
|
||||||
as the result. The instructions do not allow the lv value
|
|
||||||
to be a constant bit, so we either switch the operands, or
|
|
||||||
copy the vector into a new area. */
|
|
||||||
if (lv.base < 4) {
|
|
||||||
if (rv.base > 4) {
|
|
||||||
struct vector_info tmp = lv;
|
|
||||||
lv = rv;
|
|
||||||
rv = tmp;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct vector_info tmp;
|
|
||||||
tmp.base = allocate_vector(lv.wid);
|
|
||||||
tmp.wid = lv.wid;
|
|
||||||
if (tmp.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of binary logic.\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr),
|
|
||||||
wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
|
||||||
tmp.base, lv.base, tmp.wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
fprintf(vvp_out, " %%and %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '|':
|
|
||||||
fprintf(vvp_out, " %%or %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '^':
|
|
||||||
fprintf(vvp_out, " %%xor %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'A': /* NAND (~&) */
|
|
||||||
fprintf(vvp_out, " %%nand %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'O': /* NOR (~|) */
|
|
||||||
fprintf(vvp_out, " %%nor %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X': /* exclusive nor (~^) */
|
|
||||||
fprintf(vvp_out, " %%xnor %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
clr_vector(rv);
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct vector_info draw_load_add_immediate(ivl_expr_t le,
|
|
||||||
ivl_expr_t re,
|
|
||||||
unsigned wid,
|
|
||||||
int signed_flag)
|
|
||||||
{
|
|
||||||
struct vector_info lv;
|
|
||||||
long imm;
|
|
||||||
assert(! number_is_unknown(re));
|
|
||||||
assert(number_is_immediate(re, IMM_WID, 1));
|
|
||||||
imm = get_number_immediate(re);
|
|
||||||
lv.base = allocate_vector(wid);
|
|
||||||
lv.wid = wid;
|
|
||||||
if (lv.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of addition.\n",
|
|
||||||
ivl_expr_file(le), ivl_expr_lineno(le), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the signal value with a %load that adds the index
|
|
||||||
register to the value being loaded. */
|
|
||||||
draw_signal_dest(le, lv, signed_flag, imm);
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_add_immediate(ivl_expr_t le,
|
|
||||||
ivl_expr_t re,
|
|
||||||
unsigned wid)
|
|
||||||
{
|
|
||||||
struct vector_info lv;
|
|
||||||
unsigned long imm;
|
|
||||||
|
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
assert(lv.wid == wid);
|
|
||||||
|
|
||||||
assert(! number_is_unknown(re));
|
|
||||||
assert(number_is_immediate(re, IMM_WID, 0));
|
|
||||||
imm = get_number_immediate(re);
|
|
||||||
|
|
||||||
/* This shouldn't generally happen, because the elaborator
|
|
||||||
should take care of simple constant propagation like this,
|
|
||||||
but it doesn't have to and it is easy to catch here. */
|
|
||||||
if (imm == 0)
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
switch (lv.base) {
|
|
||||||
case 0: /* Left expression is 0. */
|
|
||||||
lv.base = allocate_vector(wid);
|
|
||||||
if (lv.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of addition.\n",
|
|
||||||
ivl_expr_file(re), ivl_expr_lineno(re), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
fprintf(vvp_out, " %%movi %u, %lu %u;\n", lv.base, imm, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: /* Left expression is 1...1 (i.e. -1) */
|
|
||||||
imm -= 1;
|
|
||||||
if (imm == 0) {
|
|
||||||
lv.base = 0;
|
|
||||||
} else {
|
|
||||||
lv.base = allocate_vector(wid);
|
|
||||||
if (lv.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of addition.\n",
|
|
||||||
ivl_expr_file(re), ivl_expr_lineno(re), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
fprintf(vvp_out, " %%movi %u, %lu %u;\n", lv.base, imm, wid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: /* Left expression is 'bx or 'bz */
|
|
||||||
case 3:
|
|
||||||
lv.base = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* The regular case. */
|
|
||||||
fprintf(vvp_out, " %%addi %u, %lu, %u;\n", lv.base, imm, wid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The subi is restricted to imm operands that are <= 16 bits wide.
|
|
||||||
*/
|
|
||||||
static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
|
||||||
ivl_expr_t re,
|
|
||||||
unsigned wid)
|
|
||||||
{
|
|
||||||
struct vector_info lv;
|
|
||||||
unsigned long imm;
|
|
||||||
unsigned tmp;
|
|
||||||
|
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
assert(lv.wid == wid);
|
|
||||||
|
|
||||||
assert(! number_is_unknown(re));
|
|
||||||
assert(number_is_immediate(re, IMM_WID, 0));
|
|
||||||
imm = get_number_immediate(re);
|
|
||||||
if (imm == 0)
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
switch (lv.base) {
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
tmp = allocate_vector(wid);
|
|
||||||
if (tmp == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of subtraction.\n",
|
|
||||||
ivl_expr_file(le), ivl_expr_lineno(le), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp, lv.base, wid);
|
|
||||||
lv.base = tmp;
|
|
||||||
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
case 3:
|
|
||||||
lv.base = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_mul_immediate(ivl_expr_t le,
|
|
||||||
ivl_expr_t re,
|
|
||||||
unsigned wid)
|
|
||||||
{
|
|
||||||
struct vector_info lv;
|
|
||||||
unsigned long imm;
|
|
||||||
|
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
assert(lv.wid == wid);
|
|
||||||
|
|
||||||
assert(! number_is_unknown(re));
|
|
||||||
assert(number_is_immediate(re, IMM_WID, 0));
|
|
||||||
imm = get_number_immediate(re);
|
|
||||||
if (imm == 0)
|
|
||||||
return lv;
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%muli %u, %lu, %u;\n", lv.base, imm, lv.wid);
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr_arith(ivl_expr_t expr, unsigned wid)
|
|
||||||
{
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
|
||||||
|
|
||||||
struct vector_info lv;
|
|
||||||
struct vector_info rv;
|
|
||||||
|
|
||||||
int signed_flag = ivl_expr_signed(le) && ivl_expr_signed(re) ? 1 : 0;
|
|
||||||
const char*sign_string = signed_flag ? "/s" : "";
|
|
||||||
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(le) == IVL_EX_SIGNAL)
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_ULONG)
|
|
||||||
&& number_is_immediate(re, IMM_WID, 1))
|
|
||||||
return draw_load_add_immediate(le, re, wid, signed_flag);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(le) == IVL_EX_SIGNAL)
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
|
||||||
&& (! number_is_unknown(re))
|
|
||||||
&& number_is_immediate(re, IMM_WID, 1))
|
|
||||||
return draw_load_add_immediate(le, re, wid, signed_flag);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_SIGNAL)
|
|
||||||
&& (ivl_expr_type(le) == IVL_EX_ULONG)
|
|
||||||
&& number_is_immediate(re, IMM_WID, 1))
|
|
||||||
return draw_load_add_immediate(re, le, wid, signed_flag);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_SIGNAL)
|
|
||||||
&& (ivl_expr_type(le) == IVL_EX_NUMBER)
|
|
||||||
&& (! number_is_unknown(le))
|
|
||||||
&& number_is_immediate(le, IMM_WID, 1))
|
|
||||||
return draw_load_add_immediate(re, le, wid, signed_flag);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_ULONG)
|
|
||||||
&& number_is_immediate(re, IMM_WID, 0))
|
|
||||||
return draw_add_immediate(le, re, wid);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '+')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
|
||||||
&& (! number_is_unknown(re))
|
|
||||||
&& number_is_immediate(re, IMM_WID, 0))
|
|
||||||
return draw_add_immediate(le, re, wid);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '-')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_ULONG)
|
|
||||||
&& number_is_immediate(re, IMM_WID, 0))
|
|
||||||
return draw_sub_immediate(le, re, wid);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '-')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
|
||||||
&& (! number_is_unknown(re))
|
|
||||||
&& number_is_immediate(re, IMM_WID, 0))
|
|
||||||
return draw_sub_immediate(le, re, wid);
|
|
||||||
|
|
||||||
if ((ivl_expr_opcode(expr) == '*')
|
|
||||||
&& (ivl_expr_type(re) == IVL_EX_NUMBER)
|
|
||||||
&& (! number_is_unknown(re))
|
|
||||||
&& number_is_immediate(re, IMM_WID, 0))
|
|
||||||
return draw_mul_immediate(le, re, wid);
|
|
||||||
|
|
||||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
|
||||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ|STUFF_OK_RO);
|
|
||||||
|
|
||||||
if (lv.wid != wid) {
|
|
||||||
fprintf(stderr, "XXXX ivl_expr_opcode(expr) = %c,"
|
|
||||||
" lv.wid=%u, wid=%u\n", ivl_expr_opcode(expr),
|
|
||||||
lv.wid, wid);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(lv.wid == wid);
|
|
||||||
assert(rv.wid == wid);
|
|
||||||
|
|
||||||
/* The arithmetic instructions replace the left operand with
|
|
||||||
the result. If the left operand is a replicated constant,
|
|
||||||
then I need to make a writable copy so that the
|
|
||||||
instruction can operate. */
|
|
||||||
if (lv.base < 4) {
|
|
||||||
struct vector_info tmp;
|
|
||||||
|
|
||||||
tmp.base = allocate_vector(wid);
|
|
||||||
tmp.wid = wid;
|
|
||||||
if (tmp.base == 0) {
|
|
||||||
fprintf(stderr, "%s:%u: vvp.tgt error: "
|
|
||||||
"Unable to allocate %u thread bits "
|
|
||||||
"for result of arithmetic expression.\n",
|
|
||||||
ivl_expr_file(expr), ivl_expr_lineno(expr), wid);
|
|
||||||
vvp_errors += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", tmp.base,
|
|
||||||
lv.base, wid);
|
|
||||||
lv = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ivl_expr_opcode(expr)) {
|
|
||||||
case '+':
|
|
||||||
fprintf(vvp_out, " %%add %u, %u, %u;\n", lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-':
|
|
||||||
fprintf(vvp_out, " %%sub %u, %u, %u;\n", lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '*':
|
|
||||||
fprintf(vvp_out, " %%mul %u, %u, %u;\n", lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '/':
|
|
||||||
fprintf(vvp_out, " %%div%s %u, %u, %u;\n", sign_string,
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '%':
|
|
||||||
fprintf(vvp_out, " %%mod%s %u, %u, %u;\n", sign_string,
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (ivl_expr_signed(le) || ivl_expr_signed(re)) {
|
|
||||||
fprintf(vvp_out, " %%pow/s %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
} else {
|
|
||||||
fprintf(vvp_out, " %%pow %u, %u, %u;\n",
|
|
||||||
lv.base, rv.base, wid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
clr_vector(rv);
|
|
||||||
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
||||||
unsigned wid,
|
unsigned wid,
|
||||||
int stuff_ok_flag)
|
int stuff_ok_flag)
|
||||||
|
|
@ -1626,29 +1108,6 @@ static struct vector_info draw_binary_expr(ivl_expr_t expr,
|
||||||
stuff_ok_used_flag = 1;
|
stuff_ok_used_flag = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
|
||||||
case '-':
|
|
||||||
case '*':
|
|
||||||
case '/':
|
|
||||||
case '%':
|
|
||||||
case 'p':
|
|
||||||
rv = draw_binary_expr_arith(expr, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'o': /* || (logical or) */
|
|
||||||
rv = draw_binary_expr_lor(expr, wid, stuff_ok_flag);
|
|
||||||
stuff_ok_used_flag = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
case '|':
|
|
||||||
case '^':
|
|
||||||
case 'A': /* NAND (~&) */
|
|
||||||
case 'O': /* NOR (~|) */
|
|
||||||
case 'X': /* XNOR (~^) */
|
|
||||||
rv = draw_binary_expr_logic(expr, wid);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "vvp.tgt error: draw_binary_expr: unsupported binary (%c)\n",
|
fprintf(stderr, "vvp.tgt error: draw_binary_expr: unsupported binary (%c)\n",
|
||||||
ivl_expr_opcode(expr));
|
ivl_expr_opcode(expr));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue