diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index a0ca10771..9458c33aa 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval_expr.c,v 1.72 2002/08/28 17:15:35 steve Exp $" +#ident "$Id: eval_expr.c,v 1.73 2002/08/28 18:38:07 steve Exp $" #endif # include "vvp_priv.h" @@ -715,6 +715,27 @@ static struct vector_info draw_add_immediate(ivl_expr_t le, 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; + + lv = draw_eval_expr_wid(le, wid); + assert(lv.wid == wid); + + imm = get_number_immediate(re); + assert( (imm & ~0xffff) == 0 ); + + fprintf(vvp_out, " %%subi %u, %lu, %u;\n", lv.base, imm, wid); + + return lv; +} + static struct vector_info draw_mul_immediate(ivl_expr_t le, ivl_expr_t re, unsigned wid) @@ -752,6 +773,16 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid) && number_is_immediate(re, 8*sizeof(unsigned long))) return draw_add_immediate(le, re, wid); + if ((ivl_expr_opcode(exp) == '-') + && (ivl_expr_type(re) == IVL_EX_ULONG)) + return draw_sub_immediate(le, re, wid); + + if ((ivl_expr_opcode(exp) == '-') + && (ivl_expr_type(re) == IVL_EX_NUMBER) + && (! number_is_unknown(re)) + && number_is_immediate(re, 16)) + return draw_sub_immediate(le, re, wid); + if ((ivl_expr_opcode(exp) == '*') && (ivl_expr_type(re) == IVL_EX_NUMBER) && (! number_is_unknown(re)) @@ -1760,6 +1791,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp) /* * $Log: eval_expr.c,v $ + * Revision 1.73 2002/08/28 18:38:07 steve + * Add the %subi instruction, and use it where possible. + * * Revision 1.72 2002/08/28 17:15:35 steve * Generate %load/nx for indexed load of nets. * diff --git a/vvp/codes.h b/vvp/codes.h index 9b1764834..8f0e7a74b 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: codes.h,v 1.48 2002/08/28 17:15:06 steve Exp $" +#ident "$Id: codes.h,v 1.49 2002/08/28 18:38:07 steve Exp $" #endif @@ -91,6 +91,7 @@ extern bool of_SET_X(vthread_t thr, vvp_code_t code); extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code); extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code); extern bool of_SUB(vthread_t thr, vvp_code_t code); +extern bool of_SUBI(vthread_t thr, vvp_code_t code); extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code); extern bool of_WAIT(vthread_t thr, vvp_code_t code); extern bool of_XNOR(vthread_t thr, vvp_code_t code); @@ -154,6 +155,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr); /* * $Log: codes.h,v $ + * Revision 1.49 2002/08/28 18:38:07 steve + * Add the %subi instruction, and use it where possible. + * * Revision 1.48 2002/08/28 17:15:06 steve * Add the %load/nx opcode to index vpi nets. * diff --git a/vvp/compile.cc b/vvp/compile.cc index 38bc65f73..1286f0574 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: compile.cc,v 1.139 2002/08/28 17:15:06 steve Exp $" +#ident "$Id: compile.cc,v 1.140 2002/08/28 18:38:07 steve Exp $" #endif # include "arith.h" @@ -136,6 +136,7 @@ const static struct opcode_table_s opcode_table[] = { { "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} }, { "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%subi", of_SUBI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} }, { "%xnor", of_XNOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%xnor/r", of_XNORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, @@ -1448,6 +1449,9 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag, /* * $Log: compile.cc,v $ + * Revision 1.140 2002/08/28 18:38:07 steve + * Add the %subi instruction, and use it where possible. + * * Revision 1.139 2002/08/28 17:15:06 steve * Add the %load/nx opcode to index vpi nets. * diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 89f5e10c4..99ebda6ab 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1,7 +1,7 @@ /* * Copyright (c) 2001 Stephen Williams (steve@icarus.com) * - * $Id: opcodes.txt,v 1.39 2002/08/28 17:15:06 steve Exp $ + * $Id: opcodes.txt,v 1.40 2002/08/28 18:38:07 steve Exp $ */ @@ -461,6 +461,13 @@ operand are x, then the entire result is x. See also the %add instruction. +* %subi , , + +This instruction arithmetically subtracts the immediate value from the +left vector. The value is a 16bit unsigned value zer-extended to +the of the left vector. The result replaces the left vector. + +See also the %addi instruction. * %vpi_call [, ...] diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 5ab9bc6c3..c526bc05a 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vthread.cc,v 1.83 2002/08/28 17:15:06 steve Exp $" +#ident "$Id: vthread.cc,v 1.84 2002/08/28 18:38:07 steve Exp $" #endif # include "vthread.h" @@ -2128,6 +2128,58 @@ bool of_SUB(vthread_t thr, vvp_code_t cp) return true; } +bool of_SUBI(vthread_t thr, vvp_code_t cp) +{ + assert(cp->bit_idx[0] >= 4); + + unsigned word_count = (cp->number+CPU_WORD_BITS-1)/CPU_WORD_BITS; + + unsigned long*lva = vector_to_array(thr, cp->bit_idx[0], cp->number); + unsigned long*lvb; + if (lva == 0) + goto x_out; + + lvb = new unsigned long[word_count]; + + lvb[0] = ~ cp->bit_idx[1]; + for (unsigned idx = 1 ; idx < word_count ; idx += 1) + lvb[idx] = ~0; + + unsigned long carry; + carry = 1; + for (unsigned idx = 0 ; (idx*CPU_WORD_BITS) < cp->number ; idx += 1) { + + unsigned long tmp = lvb[idx] + carry; + unsigned long sum = lva[idx] + tmp; + carry = 0; + if (tmp < lvb[idx]) + carry = 1; + if (sum < tmp) + carry = 1; + if (sum < lva[idx]) + carry = 1; + lva[idx] = sum; + } + + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) { + unsigned bit = lva[idx/CPU_WORD_BITS] >> (idx % CPU_WORD_BITS); + thr_put_bit(thr, cp->bit_idx[0]+idx, (bit&1) ? 1 : 0); + } + + delete[]lva; + delete[]lvb; + + return true; + + x_out: + delete[]lva; + + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) + thr_put_bit(thr, cp->bit_idx[0]+idx, 2); + + return true; +} + bool of_VPI_CALL(vthread_t thr, vvp_code_t cp) { // printf("thread %p: %%vpi_call\n", thr); @@ -2267,6 +2319,9 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp) /* * $Log: vthread.cc,v $ + * Revision 1.84 2002/08/28 18:38:07 steve + * Add the %subi instruction, and use it where possible. + * * Revision 1.83 2002/08/28 17:15:06 steve * Add the %load/nx opcode to index vpi nets. *