1 /* Copyright (c) 1991-2007 Pragmatic C Software Corp. */
2 
3 /*
4    This program is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by the
6    Free Software Foundation; either version 2 of the License, or (at your
7    option) any later version.
8 
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation, Inc.,
16    59 Temple Place, Suite 330, Boston, MA, 02111-1307.
17 
18    We are selling our new Verilog compiler that compiles to X86 Linux
19    assembly language.  It is at least two times faster for accurate gate
20    level designs and much faster for procedural designs.  The new
21    commercial compiled Verilog product is called CVC.  For more information
22    on CVC visit our website at www.pragmatic-c.com/cvc.htm or contact
23    Andrew at avanvick@pragmatic-c.com
24 
25  */
26 
27 
28 /*
29  * run time execution routines - rhs evaluation and readmem
30  */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <limits.h>
35 #include <math.h>
36 #include <ctype.h>
37 
38 #ifdef __DBMALLOC__
39 #include "../malloc.h"
40 #endif
41 
42 /* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
43 #if defined(__sparc) && !defined(__SVR4) && !defined(__FreeBSD__)
44 extern int32 tolower(int32);
45 extern ungetc(int32 c, FILE *);
46 #endif
47 
48 #include "v.h"
49 #include "cvmacros.h"
50 
51 /* local prototypes */
52 static void prep_bld_monit_dces(struct expr_t *, int32);
53 static void linkon_monit_dce(struct net_t *, int32, int32, int32,
54  struct itree_t *);
55 static int32 chk_monits_chged(register struct dceauxlst_t *);
56 static int32 chk_rm_rng_legal(int32, int32, int32, char *);
57 static void push_bsel(struct expr_t *);
58 static void push_psel(register struct expr_t *);
59 static int32 mdata_gettok(FILE *, int32);
60 static int32 rmrd_comment(FILE *);
61 static int32 mdata_rdhex(FILE *, int32);
62 static int32 is_mdataxdigit(int32);
63 static int32 mdata_rdbin(FILE *, int32);
64 static int32 rm_getc(FILE *);
65 static void rm_ungetc(int32, FILE *);
66 static int32 is_mdatabit(int32);
67 static void do_srm_xtrct(struct expr_t *, int32, struct net_t *, int32, int32,
68  int32, int32, int32);
69 static double stdnorm_dev(int32 *);
70 static double gamma_dev(double, int32 *);
71 static int32 poisson_dev(int32, int32 *);
72 static double log_gamma(double);
73 static void lxqcol(register struct xstk_t *, register struct xstk_t *,
74  register struct xstk_t *, int32, int32, int32);
75 static void eval_unary(struct expr_t *);
76 static void eval_wide_unary(register struct expr_t *,
77  register struct xstk_t *);
78 static void eval_binary(struct expr_t *);
79 static void eval_wide_binary(struct expr_t *, register struct xstk_t *,
80  register struct xstk_t *);
81 static void bitmwrshift(register word32 *, register int32, register int32);
82 static void bitmwlshift(register word32 *, register int32, register int32);
83 static void wrdmwrshift(register word32 *, register int32, register int32);
84 static void wrdmwlshift(register word32 *, register int32, register int32);
85 static int32 sgn_linc(register word32 *, int32);
86 static int32 accmuladd32(word32 *, word32 *, word32, word32 *, int32);
87 static void mpexpr_zdiv(word32 *, word32 *, word32 *, int32, word32 *, int32);
88 static int32 ztrim(word32 *, int32);
89 static void dadd(word32 *, word32 *, int32, int32);
90 static int32 dsub(word32 *, int32, word32 *, int32, int32, int32);
91 static void dmul(word32 *, int32, word32 *, int32, word64);
92 static int32 ldiv_cmp(register word32 *, register word32 *, int32);
93 static void xchg_stk(int32, int32);
94 static double uniform(int32 *, sword32, sword32);
95 static sword32 rtl_dist_uniform(int32 *, sword32, sword32);
96 
97 /* extern prototypes (maybe defined in this module) */
98 extern char *__my_realloc(char *, int32, int32);
99 extern char *__my_malloc(int32);
100 extern void __my_free(char *, int32);
101 extern void __xmrpush_refgrp_to_targ(struct gref_t *);
102 extern struct xstk_t *__eval2_xpr(struct expr_t *);
103 extern char *__regab_tostr(char *, word32 *, word32 *, int32, int32, int32);
104 extern void __ld_stval(register word32 *, register word32 *, register byte *, int32);
105 extern char *__msgexpr_tostr(char *, struct expr_t *);
106 extern char __to_baselet(int32);
107 extern struct dcevnt_t *__alloc_dcevnt(struct net_t *);
108 extern FILE *__tilde_fopen(char *, char *);
109 extern word32 __wrd_redxor(word32);
110 extern double __cnvt_stk_to_real(struct xstk_t *, int32);
111 extern char *__bld_lineloc(char *, word32, int32);
112 extern char *__to_timstr(char *, word64 *);
113 extern char *__vval_to_vstr(word32 *, int32, int32 *);
114 extern char * __get_eval_cstr(struct expr_t *, int32 *);
115 extern word32 __lsub(register word32 *, register word32 *, register word32 *,
116  int32);
117 extern void __st_perinst_val(union pck_u pckv, int32, register word32 *,
118  register word32 *);
119 
120 extern void __start_monitor(struct st_t *);
121 extern void __start_fmonitor(struct st_t *);
122 extern void __alloc_1instdce_prevval(struct dcevnt_t *);
123 extern void __init_1instdce_prevval(struct dcevnt_t *);
124 extern int32 __get_dcewid(struct dcevnt_t *, struct net_t *);
125 extern int32 __get_pcku_chars(int32, int32);
126 extern void __exec_strobes(void);
127 extern void __exec_fmonits(void);
128 extern void __exec_monit(struct dceauxlst_t *, int32);
129 extern void __ld_wire_sect(word32 *, word32 *, struct net_t *, register int32,
130  register int32);
131 extern void __grow_tevtab(void);
132 extern void __grow_xstk(void);
133 extern void __chg_xstk_width(struct xstk_t *, int32);
134 extern void __alloc_xsval(struct xstk_t *, int32);
135 extern void __ld_wire_val(register word32 *, register word32 *,
136  struct net_t *);
137 extern void __ld_perinst_val(register word32 *, register word32 *,
138  union pck_u, int32);
139 extern int32 __comp_ndx(register struct net_t *, register struct expr_t *);
140 extern void __ld_bit(register word32 *, register word32 *,
141  register struct net_t *, int32);
142 extern void __ld_arr_val(register word32 *, register word32 *, union pck_u,
143  int32, int32, int32);
144 extern void __ld_psel(register word32 *, register word32 *,
145  register struct net_t *, int32, int32);
146 extern void __rhspsel(register word32 *, register word32 *, register int32,
147  register int32);
148 extern void __exec_readmem(struct expr_t *, int32);
149 extern void __exec_sreadmem(struct expr_t *, int32);
150 extern void __exec_sfrand(struct expr_t *);
151 extern void __ld_addr(word32 **, word32 **, register struct net_t *);
152 extern void __luminus(word32 *, word32 *, int32);
153 extern int32 __is_lnegative(word32 *, int32);
154 extern word32 __cp_lnegate(word32 *, register word32 *, int32);
155 extern word32 __inplace_lnegate(register word32 *, int32);
156 extern void __lunredand(int32 *, int32 *, word32 *, word32 *, int32);
157 extern void __lunredor(int32 *, int32 *, word32 *, word32 *, int32);
158 extern void __lunredxor(int32 *, int32 *, word32 *, word32 *, int32);
159 extern void __mwrshift(word32 *, word32, int32);
160 extern void __arith_mwrshift(word32 *, word32, int32);
161 extern void __mwlshift(word32 *, word32, int32);
162 extern int32 __cvt_lngbool(word32 *, word32 *, int32);
163 extern int32 __do_widecmp(int32 *, register word32 *, register word32 *,
164  register word32 *, register word32 *, int32);
165 extern int32 __do_sign_widecmp(int32 *, register word32 *, register word32 *,
166  register word32 *, register word32 *, int32);
167 extern int32 __do_xzwidecmp(register word32 *, register word32 *,
168  register word32 *, register word32 *, int32);
169 extern void __ladd(word32 *, word32 *, word32 *, int32);
170 extern void __lmult(register word32 *, register word32 *, register word32 *,
171  int32);
172 extern void __sgn_lmult(register word32 *, register word32 *,
173  register word32 *, int32);
174 extern void __ldivmod(word32 *, word32 *, word32 *, int32, int32);
175 extern void __sgn_ldivmod(register word32 *, register word32 *,
176  register word32 *, int32, int32);
177 extern void __ldivmod2(word32 *, word32 *, word32 *, word32 *, int32);
178 extern void __by16_ldivmod(word32 *, word32 *, word32 *, word32, int32);
179 
180 extern void __fio_do_disp(register struct expr_t *, int32, int32, char *);
181 extern void __do_disp(register struct expr_t *, int32);
182 extern void __get_cor_range(register int32, union intptr_u, register int32 *,
183  register int32 *);
184 extern int32 __get_arrwide(struct net_t *);
185 extern void __exec_sysfunc(register struct expr_t *);
186 extern void __exec_func(register struct expr_t *);
187 extern void __lhsbsel(register word32 *, register int32, word32);
188 extern void __cp_sofs_wval(register word32 *, register word32 *,
189  register int32, register int32);
190 extern void __getarr_range(struct net_t *, int32 *, int32 *, int32 *);
191 extern void __my_fclose(FILE *);
192 extern void __to_dhboval(int32, int32);
193 extern void __sizchgxs(register struct xstk_t *, int32);
194 extern void __sgn_xtnd_widen(struct xstk_t *, int32);
195 extern void __sgn_xtnd_wrd(struct xstk_t *, int32);
196 extern void __sizchg_widen(register struct xstk_t *, int32);
197 extern void __narrow_sizchg(register struct xstk_t *, int32);
198 extern void __narrow_to1bit(register struct xstk_t *);
199 
200 extern int32 __wide_vval_is0(register word32 *, int32);
201 extern int32 __trim1_0val(word32 *, int32);
202 extern void __lhspsel(register word32 *, register int32, register word32 *,
203  register int32);
204 extern int32 __vval_is1(register word32 *, int32);
205 extern int32 __get_eval_word(struct expr_t *, word32 *);
206 extern void __exec2_proc_assign(struct expr_t *, register word32 *,
207  register word32 *);
208 extern void __rhs_concat(struct expr_t *);
209 extern void __eval_qcol(register struct expr_t *);
210 extern void __eval_realrealqcol(register struct expr_t *);
211 extern void __eval_realregqcol(register struct expr_t *);
212 extern void __eval_regrealqcol(register struct expr_t *);
213 extern void __lunbitnot(word32 *, word32 *, int32);
214 extern int32 __set_binxresult(word32 *, word32 *, word32 *, word32 *, int32);
215 extern void __lbitand(word32 *, word32 *, word32 *, word32 *, int32);
216 extern void __lbitor(word32 *, word32 *, word32 *, word32 *, int32);
217 extern void __lbitxor(word32 *, word32 *, word32 *, word32 *, int32);
218 extern void __lbitxnor(word32 *, word32 *, word32 *, word32 *, int32);
219 extern void __push_wrkitstk(struct mod_t *, int32);
220 extern void __pop_wrkitstk(void);
221 extern int32 __omitxz_widenoteq(register word32 *, register word32 *,
222  register word32 *, register word32 *, int32);
223 extern void __dcelst_on(struct dceauxlst_t *);
224 extern void __dcelst_off(struct dceauxlst_t *);
225 extern void init_dcelst(struct dceauxlst_t *);
226 extern void __dce_turn_chg_store_on(struct mod_t *, struct dcevnt_t *, int32);
227 extern void __do_rm_reading(FILE *, int32, struct net_t *, int32, int32,
228  int32, int32, int32);
229 extern void __wakeup_delay_ctrls(register struct net_t *, register int32,
230  register int32);
231 extern void __add_select_nchglst_el(register struct net_t *, register int32,
232  register int32);
233 extern void __add_dmpv_chglst_el(struct net_t *);
234 extern void __st_arr_val(union pck_u, int32, int32, int32, register word32 *,
235  register word32 *);
236 extern void __chg_st_arr_val(union pck_u, int32, int32, int32,
237  register word32 *, register word32 *);
238 
239 extern void __cvsim_msg(char *, ...);
240 /* SJM - not used -extern void __pv_err(int32, char *, ...); */
241 extern void __pv_warn(int32, char *,...);
242 extern void __sgfwarn(int32, char *, ...);
243 extern void __pv_fwarn(int32, char *, ...);
244 extern void __sgferr(int32, char *, ...);
245 extern void __dbg_msg(char *, ...);
246 extern void __sgfinform(int32, char *, ...);
247 extern void __arg_terr(char *, int32);
248 extern void __case_terr(char *, int32);
249 extern void __misc_terr(char *, int32);
250 extern void __inform(int32, char *, ...);
251 
252 extern word32 __masktab[];
253 extern char __pv_ctab[];
254 
255 /*
256  * MONITOR/STROBE SETUP AND EXECUTION ROUTINES
257  */
258 
259 /*
260  * set up a new monitor argument list
261  * every expression in $monitor has event trigger added
262  *
263  * SJM 06/20/02 - change so this exec routine assumes dce's built if in
264  * source - only builds if from interactive
265  * this runs with itree context set
266  */
__start_monitor(struct st_t * stp)267 extern void __start_monitor(struct st_t *stp)
268 {
269  register struct expr_t *alxp;
270  int32 argi;
271  byte *argisvtab;
272  struct tskcall_t *tkcp;
273  struct mod_t *imdp;
274  struct monaux_t *mauxp;
275 
276  tkcp = &(stp->st.stkc);
277 
278  /* turn off all monitor events associated with previous monitor (1 inst.) */
279  /* LOOKATME - possible minor memory leak here */
280  if (__monit_dcehdr != NULL)
281   {
282    __dcelst_off(__monit_dcehdr);
283    __monit_dcehdr = NULL;
284   }
285 
286  /* turn off monitor by $monitor() - empty arg list */
287  if (tkcp->targs == NULL)
288   { __monit_stp = NULL; __monit_itp = NULL; return; }
289 
290  /* DBG remove -- */
291  if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
292   __arg_terr(__FILE__, __LINE__);
293  /* --- */
294  mauxp = tkcp->tkcaux.mauxp;
295  argisvtab = (byte *) mauxp->argisvtab;
296 
297  __monit_stp = stp;
298  /* if $monitor in multiply instantiated module, last one executed is */
299  /* current instance */
300  __monit_itp = __inst_ptr;
301  __cur_fmon = NULL;
302 
303  if (!mauxp->dces_blt)
304   {
305    register int32 ii;
306 
307    for (ii = 0; ii < __inst_mod->flatinum; ii++)
308     {
309      __push_itstk(__inst_mod->moditps[ii]);
310 
311      __monit_dcehdr = NULL;
312      alxp = tkcp->targs;
313      for (argi = 0; alxp != NULL; alxp = alxp->ru.x, argi++)
314       {
315        prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
316       }
317      mauxp->mon_dcehdr[ii] = __monit_dcehdr;
318 
319      __pop_itstk();
320     }
321    mauxp->dces_blt = TRUE;
322   }
323  __monit_dcehdr = mauxp->mon_dcehdr[__inum];
324  /* turn on (enable) all dces in list built during prep - off when built */
325  __dcelst_on(__monit_dcehdr);
326 
327  /* SJM 01/02/03 - must re-initialize monit dces previous value if present */
328  init_dcelst(__monit_dcehdr);
329 
330  /* changing $monitor (including 1st) always trigger 1 output */
331  /* no warning since normal to turn off monitoring with $monitor() */
332  __slotend_action |= SE_MONIT_CHG;
333  imdp = __inst_mod;
334  if (imdp->flatinum > 1)
335   __sgfinform(441,
336    "$monitor invoked in module %s that is instantiated multiple times",
337    imdp->msym->synam);
338 }
339 
340 /*
341  * initialize dce list for monitor form that is always one inst
342  */
init_dcelst(struct dceauxlst_t * dcehdr)343 extern void init_dcelst(struct dceauxlst_t *dcehdr)
344 {
345  register struct dceauxlst_t *dclp;
346 
347  for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
348   {
349    /* notice if no previous value, this detects it and does nothing */
350    if (dclp->ldcep->prevval.bp != NULL) __init_1instdce_prevval(dclp->ldcep);
351   }
352 }
353 
354 /*
355  * enable all dces in dceaux list
356  */
__dcelst_on(struct dceauxlst_t * dcehdr)357 extern void __dcelst_on(struct dceauxlst_t *dcehdr)
358 {
359  register struct dceauxlst_t *dclp;
360  register struct net_t *np;
361 
362  for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
363   {
364    dclp->ldcep->dce_off = FALSE;
365    np = dclp->ldcep->dce_np;
366    /* SJM 07/19/02 - turn on so now records chges - if nld nil won't record */
367    /* until first time here */
368    if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
369 
370    /* SJM 11/25/02 - never turn in src dces on/off */
371    /* DBG remove -- */
372    if (dclp->ldcep->dce_typ == DCE_INST
373     || dclp->ldcep->dce_typ == DCE_RNG_INST) __misc_terr(__FILE__, __LINE__);
374    /* --- */
375    /* DBG remove -- */
376    if (!dclp->ldcep->dce_1inst) __misc_terr(__FILE__, __LINE__);
377    /* --- */
378 
379    /* since adding dce, if wire and no lds, must turn off all chged */
380    /* that prevents recording since now must record for wire dce wakeup */
381    /* SJM 11/25/02 - since only 1 inst match forms can be turned on/off */
382    /* just turn on the match itp here */
383    if (np->nlds == NULL && np->ntyp < NONWIRE_ST)
384     {
385      np->nchgaction[dclp->ldcep->dce_matchitp->itinum] &= ~(NCHG_ALL_CHGED);
386     }
387   }
388 }
389 
390 /*
391  * disable all dces in dceaux list
392  *
393  * notice not stopping recording of changes since expect to be activated again
394  */
__dcelst_off(struct dceauxlst_t * dcehdr)395 extern void __dcelst_off(struct dceauxlst_t *dcehdr)
396 {
397  register struct dceauxlst_t *dclp;
398 
399  for (dclp = dcehdr; dclp != NULL; dclp = dclp->dclnxt)
400   {
401    dclp->ldcep->dce_off = TRUE;
402   }
403 }
404 
405 /*
406  * set up a new fmonitor argument list
407  *
408  * every expression in $fmonitor has event trigger added
409  * this runs with itree context set
410  */
__start_fmonitor(struct st_t * stp)411 extern void __start_fmonitor(struct st_t *stp)
412 {
413  register struct expr_t *alxp;
414  register struct dceauxlst_t *dclp;
415  int32 argi;
416  byte *argisvtab;
417  struct tskcall_t *tkcp;
418  struct fmonlst_t *fmonp;
419  struct fmselst_t *fmsep;
420  struct dceauxlst_t *sav_dclp;
421  struct dcevnt_t *dcep;
422  struct monaux_t *mauxp;
423 
424  tkcp = &(stp->st.stkc);
425  /* ignore first mc channel descripter since not involved in monitoring */
426  if (tkcp->targs != NULL) alxp = tkcp->targs->ru.x; else alxp = NULL;
427 
428  /* $fmonitor with no argument list does nothing - ignore with warn */
429  if (alxp == NULL)
430   {
431    __sgfwarn(639,
432     "execution of $fmonitor with one argument has no effect - ignored");
433    return;
434   }
435 
436  /* DBG remove -- */
437  if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
438   __arg_terr(__FILE__, __LINE__);
439  /* --- */
440  mauxp = tkcp->tkcaux.mauxp;
441  argisvtab = (byte *) mauxp->argisvtab;
442 
443  /* allocate and link on fmonitor record for this fmonitor */
444  fmonp = (struct fmonlst_t *) __my_malloc(sizeof(struct fmonlst_t));
445  fmonp->fmon_stp = stp;
446  fmonp->fmon_itp = __inst_ptr;
447  fmonp->fmonnxt = NULL;
448  if (__fmon_hdr == NULL) __fmon_hdr = fmonp; else __fmon_end->fmonnxt = fmonp;
449  __fmon_end = fmonp;
450  __cur_fmon = fmonp;
451 
452  /* SJM 06/20/02 - new algorithm only build if call from interactive mode */
453  /* works because if any vm insn gen, no interactive */
454  if (!mauxp->dces_blt)
455   {
456    register int32 ii;
457 
458    /* save $monit dce list */
459    sav_dclp = __monit_dcehdr;
460    __monit_dcehdr = NULL;
461 
462    for (ii = 0; ii < __inst_mod->flatinum; ii++)
463     {
464      /* build the dces - notice build now starts each monit dce off*/
465      __monit_dcehdr = NULL;
466      for (argi = 1; alxp != NULL; alxp = alxp->ru.x, argi++)
467        prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
468 
469      /* SJM 08/26/02 - need to indicate monit is fmonit */
470      for (dclp = __monit_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
471       {
472        dcep = dclp->ldcep;
473        dcep->is_fmon = TRUE;
474 
475       }
476 
477      mauxp->mon_dcehdr[ii] = __monit_dcehdr;
478     }
479    mauxp->dces_blt = TRUE;
480    __monit_dcehdr = sav_dclp;
481   }
482  fmonp->fmon_dcehdr = mauxp->mon_dcehdr[__inum];
483 
484  /* turn on - for fmonitor nothing to turn off */
485  __dcelst_on(mauxp->mon_dcehdr[__inum]);
486 
487  /* SJM 01/02/03 - must re-initialize fmonit dces previous value if presetn */
488  init_dcelst(mauxp->mon_dcehdr[__inum]);
489 
490  dclp = mauxp->mon_dcehdr[__inum];
491  for (; dclp != NULL; dclp = dclp->dclnxt)
492   {
493    dclp->ldcep->dceu2.dce_fmon = __cur_fmon;
494   }
495 
496  /* add to triggered this time list since always write first time seen */
497  if (__fmse_freelst == NULL)
498   fmsep = (struct fmselst_t *) __my_malloc(sizeof(struct fmselst_t));
499  else { fmsep = __fmse_freelst; __fmse_freelst = __fmse_freelst->fmsenxt; }
500  fmsep->fmsenxt = NULL;
501 
502  fmsep->fmon = fmonp;
503  fmonp->fmse_trig = fmsep;
504  fmonp->fmon_forcewrite = TRUE;
505  if (__fmonse_hdr == NULL) __fmonse_hdr = fmsep;
506  else __fmonse_end->fmsenxt = fmsep;
507  __fmonse_end = fmsep;
508  /* changing $fmonitor (including 1st) always trigger 1 output */
509  __slotend_action |= SE_FMONIT_TRIGGER;
510 }
511 
512 /*
513  * build the dces for each monit/fmonit in source once
514  * then assign list when enable and turn off list when replaced
515  *
516  * SJM 06/21/02 - new algorithm build dce list for all in src (f)monit
517  * during prep and activate/deactive from execution
518  */
__prep_insrc_monit(struct st_t * stp,int32 fmon_type)519 extern void __prep_insrc_monit(struct st_t *stp, int32 fmon_type)
520 {
521  register int32 ii;
522  register struct expr_t *alxp;
523  register struct dceauxlst_t *dclp;
524  int32 argi;
525  byte *argisvtab;
526  struct tskcall_t *tkcp;
527  struct monaux_t *mauxp;
528  char s1[RECLEN];
529 
530  tkcp = &(stp->st.stkc);
531  /* ignore first mc channel descripter since not involved in monitoring */
532  /* ignore first mc channel descripter since not involved in monitoring */
533  /* AIV 06/25/05 - must check if fmonit if not first arg is not decriptor */
534  /* was skipping first arg to $monitor */
535  if (fmon_type)
536   {
537    if (tkcp->targs != NULL) alxp = tkcp->targs->ru.x; else alxp = NULL;
538   }
539  else
540   {
541    if (tkcp->targs != NULL) alxp = tkcp->targs->lu.x; else alxp = NULL;
542   }
543 
544  if (fmon_type) strcpy(s1, "$fmonitor"); else strcpy(s1, "$monitor");
545 
546  /* $monitor/$fmonitor with no args - does nothing - ignore with warn */
547  if (alxp == NULL)
548   {
549    /* SJM - 05/14/04 - monitor with no args turns off monitor - no warn */
550    return;
551   }
552  /* DBG remove -- */
553  if (tkcp->tkcaux.mauxp == NULL || tkcp->tkcaux.mauxp->argisvtab == NULL)
554   __arg_terr(__FILE__, __LINE__);
555  /* --- */
556  mauxp = tkcp->tkcaux.mauxp;
557  argisvtab = (byte *) mauxp->argisvtab;
558 
559  for (ii = 0; ii < __inst_mod->flatinum; ii++)
560   {
561    __push_itstk(__inst_mod->moditps[ii]);
562 
563    __monit_dcehdr = NULL;
564    argi = 0;
565    for (alxp = tkcp->targs; alxp != NULL; alxp = alxp->ru.x, argi++)
566     {
567      prep_bld_monit_dces(alxp->lu.x, (int32) argisvtab[argi]);
568     }
569    if (fmon_type)
570     {
571      /* SJM 08/26/02 - need to indicate monit is fmonit */
572      for (dclp = __monit_dcehdr; dclp != NULL; dclp = dclp->dclnxt)
573       {
574        dclp->ldcep->is_fmon = TRUE;
575       }
576     }
577    mauxp->mon_dcehdr[ii] = __monit_dcehdr;
578 
579    __pop_itstk();
580   }
581  mauxp->dces_blt = TRUE;
582  __monit_dcehdr = NULL;
583 }
584 
585 /*
586  * during design preparation build monitor dces for every possible
587  * instance (also non prep version for when monit added from iact mode)
588  */
prep_bld_monit_dces(struct expr_t * xp,int32 argisvfmt)589 static void prep_bld_monit_dces(struct expr_t *xp, int32 argisvfmt)
590 {
591  struct net_t *np;
592  int32 biti, bitj;
593  word32 *wp;
594  struct expr_t *idndp, *ndx;
595  struct expr_t *fax;
596  struct itree_t *ref_itp;
597 
598  ref_itp = __inst_ptr;
599  switch ((byte) xp->optyp) {
600   case GLBREF:
601    idndp = xp;
602    /* for global - do not need ref. point - just link on 1 (because only 1 */
603    /* monit call from 1 inst.) target wire */
604    biti = bitj = -1;
605 glb_dce:
606    __xmrpush_refgrp_to_targ(idndp->ru.grp);
607    np = idndp->lu.sy->el.enp;
608    linkon_monit_dce(np, biti, bitj, argisvfmt, ref_itp);
609    __pop_itstk();
610    break;
611   case ID:
612    idndp = xp;
613    np = xp->lu.sy->el.enp;
614    linkon_monit_dce(np, -1, -1, argisvfmt, ref_itp);
615    break;
616   /* SJM 05/18/00 - must do nothing for reals */
617   case NUMBER: case ISNUMBER: case REALNUM: case ISREALNUM: case OPEMPTY:
618    return;
619   case LSB:
620    idndp = xp->lu.x;
621    np = idndp->lu.sy->el.enp;
622    ndx = xp->ru.x;
623    /* for monits, any reg or non scalared wire must trigger on any chg */
624    if (ndx->optyp == NUMBER)
625     {
626      wp = &(__contab[ndx->ru.xvi]);
627      if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
628     }
629    else if (ndx->optyp == ISNUMBER)
630     {
631      wp = &(__contab[ndx->ru.xvi]);
632      wp = &(wp[2*__inum]);
633      /* need length for IS number because can be wider - but get low */
634      if (wp[1] != 0L) biti = -1; else biti = (int32) wp[0];
635     }
636    else
637     {
638      /* notice for monitor and dctrl event change, variable here is legal */
639      /* and implies change for index and trigger on all bits of variable */
640      prep_bld_monit_dces(ndx, argisvfmt);
641      biti = -1;
642     }
643    bitj = biti;
644    if (biti != -1 && !np->vec_scalared) biti = bitj = -1;
645    if (idndp->optyp == GLBREF) goto glb_dce;
646    linkon_monit_dce(np, biti, biti, argisvfmt, ref_itp);
647    break;
648   case PARTSEL:
649    idndp = xp->lu.x;
650    np = idndp->lu.sy->el.enp;
651    ndx = xp->ru.x;
652    /* know part select never IS */
653    wp = &(__contab[ndx->lu.x->ru.xvi]);
654    biti = (int32) wp[0];
655    wp = &(__contab[ndx->ru.x->ru.xvi]);
656    bitj = (int32) wp[0];
657 
658    if (!np->vec_scalared) biti = bitj = -1;
659    if (idndp->optyp == GLBREF) goto glb_dce;
660    linkon_monit_dce(np, biti, bitj, argisvfmt, ref_itp);
661    break;
662   case FCALL:
663    /* if any arguments of system or user functions change, monitor triggers */
664    /* notice $time function do not have arguments */
665    for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
666     {
667      prep_bld_monit_dces(fax->lu.x, argisvfmt);
668     }
669    break;
670   case LCB:
671    for (fax = xp->ru.x; fax != NULL; fax = fax->ru.x)
672     {
673      prep_bld_monit_dces(fax->lu.x, argisvfmt);
674     }
675    break;
676   default:
677    if (xp->lu.x != NULL) prep_bld_monit_dces(xp->lu.x, argisvfmt);
678    if (xp->ru.x != NULL) prep_bld_monit_dces(xp->ru.x, argisvfmt);
679    break;
680  }
681 }
682 
683 /*
684  * link on a special (simplified) monitor dce
685  * IS form never possible here and always local, have moved to dest.
686  *
687  * if xmr know np is already dest. and itree place is dest.
688  *
689  * monitor dce must go on dest. since when value changed that wire
690  * is traced, final eval. is separate unrelated code
691  * this is never dce_itp since just put on one right xmr targ.
692  * and moved to xmr target above
693  * goes on front but after andy dmpvar dces
694  * also for fmonitor - different end of slot list
695  *
696  * SJM 01/06/03 - only callable during prep since all monit dces in src
697  * build here or from interactive mode
698  */
linkon_monit_dce(struct net_t * np,int32 biti,int32 bitj,int32 argisvfmt,struct itree_t * ref_itp)699 static void linkon_monit_dce(struct net_t *np, int32 biti, int32 bitj,
700  int32 argisvfmt, struct itree_t *ref_itp)
701 {
702  struct dcevnt_t *dcep;
703  struct dceauxlst_t *dclp;
704 
705  /* allocate, init, and fill the fields */
706  dcep = __alloc_dcevnt(np);
707  if (biti == -1) dcep->dce_typ = DCE_MONIT;
708  else
709   {
710    dcep->dce_typ = DCE_RNG_MONIT;
711    dcep->dci1 = biti;
712    dcep->dci2.i = bitj;
713   }
714  /* dce's assume on but here only turned on when activated by exec */
715  dcep->dce_off = TRUE;
716 
717  /* non v format strengths for monitor only output if value part changes */
718  if (np->n_stren && argisvfmt) dcep->dce_nomonstren = FALSE;
719 
720  /* this is instance where dce trigger must occur for xmr different from */
721  /* itree location in which (f)monitor execed */
722  dcep->dce_matchitp = __inst_ptr;
723  dcep->dce_refitp = ref_itp;
724  dcep->dce_1inst = TRUE;
725  dcep->dceu2.dce_fmon = __cur_fmon;
726 
727  /* link this on front */
728  dcep->dcenxt = np->dcelst;
729  np->dcelst = dcep;
730 
731  /* allocate the prev val fields and set to cur. value of wire for inst. */
732  /* for monits always need prev. val. field because set flag if any */
733  /* change and change may get filtered out later */
734  /* except for entire reg, do not need */
735  __alloc_1instdce_prevval(dcep);
736  /* SJM 05/04/05 - can initialize since for cver-cc, not linked to .bss yet */
737 
738  /* then link on undo/chg list - fmon's never undone except for :reset */
739  dclp = (struct dceauxlst_t *) __my_malloc(sizeof(struct dceauxlst_t));
740  dclp->ldcep = dcep;
741  dclp->dclnxt = __monit_dcehdr;
742  __monit_dcehdr = dclp;
743 
744  if (__iact_state)
745   {
746    /* since no dce, no loads, and no dmpvars must always turn chg store on */
747    if (!dcep->dce_np->nchg_nd_chgstore)
748     {
749      /* this also causes regen of all mod entire procedural iops since net */
750      /* need to be compiled with change form on everywhere */
751      __dce_turn_chg_store_on(__inst_mod, dcep, TRUE);
752     }
753    /* SJM 02/06/03 - may have npps but not dces so must turn this on */
754    /* since nchg nd chgstore on, know nchg action right */
755    if (np->ntyp >= NONWIRE_ST) np->nchg_has_dces = TRUE;
756   }
757 
758  /* -- DBG REMOVE
759  {
760   struct dceauxlst_t *dclp2, *dclp3;
761 
762   for (dclp2 = __monit_dcehdr; dclp2 != NULL; dclp2 = dclp2->dclnxt)
763    {
764     for (dclp3 = dclp2->dclnxt; dclp3 != NULL; dclp3 = dclp3->dclnxt)
765      if (dclp2 == dclp3)
766       {
767        __dbg_msg("^^^ monitor dclp duplicate addr %lx\n", dclp2);
768        __misc_terr(__FILE__, __LINE__);
769       }
770    }
771  }
772  --- */
773 }
774 
775 /*
776  * get width in bits of a dcep range or wire
777  */
__get_dcewid(struct dcevnt_t * dcep,struct net_t * np)778 extern int32 __get_dcewid(struct dcevnt_t *dcep, struct net_t *np)
779 {
780  if (dcep->dci1 == -2) return(1);
781  if (dcep->dci1 == -1) return(np->nwid);
782  return(dcep->dci1 - dcep->dci2.i + 1);
783 }
784 
785 /*
786  * get number of packed bytes for ld peri and st peri access
787  */
__get_pcku_chars(int32 blen,int32 insts)788 extern int32 __get_pcku_chars(int32 blen, int32 insts)
789 {
790  /* SJM 10/14/99 - now storing all scalars as one byte */
791  if (blen == 1) return(insts);
792  /* SJM 07/15/00 - no longer packing 2 to 16 bits */
793  return(2*insts*wlen_(blen)*WRDBYTES);
794 }
795 
796 /*
797  * execute the strobe statements at end of time slot
798  * only called if at least one and by end of time slot functionality
799  * of $display
800  *
801  * need fstrobes here too
802  */
__exec_strobes(void)803 extern void __exec_strobes(void)
804 {
805  register struct strblst_t *strblp;
806  int32 base, sav_slin_cnt, sav_sfnam_ind;
807  struct st_t *stp;
808  struct tskcall_t *tkcp;
809  struct expr_t *tkxp;
810  struct systsk_t *stbp;
811 
812  sav_slin_cnt = __slin_cnt;
813  sav_sfnam_ind = __sfnam_ind;
814  for (strblp = __strobe_hdr; strblp != NULL; strblp = strblp->strbnxt)
815   {
816    stp = strblp->strbstp;
817    __slin_cnt = stp->stlin_cnt;
818    __sfnam_ind = stp->stfnam_ind;
819 
820    /* notice here cur. itp does not need to be preserved */
821    __push_itstk(strblp->strb_itp);
822    tkcp = &(stp->st.stkc);
823    tkxp = tkcp->tsksyx;
824    stbp = tkxp->lu.sy->el.esytbp;
825 
826    switch (stbp->stsknum) {
827     case STN_STROBE: base = BDEC; goto nonf_write;
828     case STN_STROBEH: base = BHEX; goto nonf_write;
829     case STN_STROBEB: base = BBIN; goto nonf_write;
830     case STN_STROBEO: base = BOCT;
831 nonf_write:
832      __do_disp(tkcp->targs, base);
833      __cvsim_msg("\n");
834      break;
835     case STN_FSTROBE: base = BDEC; goto f_disp;
836     case STN_FSTROBEB: base = BBIN; goto f_disp;
837     case STN_FSTROBEH: base = BHEX; goto f_disp;
838     case STN_FSTROBEO:
839      base = BOCT;
840 f_disp:
841      __fio_do_disp(tkcp->targs, base, TRUE, tkxp->lu.sy->synam);
842      break;
843     default: __case_terr(__FILE__, __LINE__);
844    }
845    stp->strb_seen_now = FALSE;
846    __pop_itstk();
847   }
848  /* free strobes all at once */
849  if (__strobe_hdr != NULL)
850   { __strobe_end->strbnxt = __strb_freelst; __strb_freelst = __strobe_hdr; }
851  __strobe_hdr = __strobe_end = NULL;
852  __slin_cnt = sav_slin_cnt;
853  __sfnam_ind = sav_sfnam_ind;
854 }
855 
856 /*
857  * execute all triggered during this time slot fmonitors
858  * LOOKATME - for now $monitoroff (on) does not effect fmonitor and iact -[num]
859  * also impossible
860  */
__exec_fmonits(void)861 extern void __exec_fmonits(void)
862 {
863  register struct fmselst_t *fmsep;
864  struct fmonlst_t *fmonp;
865  struct st_t *sav_monit_stp;
866  struct itree_t *sav_monit_itp;
867 
868  if (__fmonse_hdr == NULL) __arg_terr(__FILE__, __LINE__);
869  sav_monit_stp = __monit_stp;
870  sav_monit_itp = __monit_itp;
871  for (fmsep = __fmonse_hdr; fmsep != NULL; fmsep = fmsep->fmsenxt)
872   {
873    fmonp = fmsep->fmon;
874    __monit_stp = fmonp->fmon_stp;
875    __monit_itp = fmonp->fmon_itp;
876    __exec_monit(fmonp->fmon_dcehdr, (int32) (fmonp->fmon_forcewrite == 1));
877    /* turn off triggered since this time slot end change processed */
878    fmonp->fmse_trig = NULL;
879    fmonp->fmon_forcewrite = FALSE;
880    /* DBG remove --
881    if (__debug_flg)
882     {
883      __dbg_msg("+++ time %s: executing fmonitor at %s\n", __to_timstr(__xs,
884       &__simtime), __bld_lineloc(__xs2, __monit_stp->stfnam_ind,
885       __monit_stp->stlin_cnt));
886     }
887    --- */
888   }
889  __monit_stp = sav_monit_stp;
890  __monit_itp = sav_monit_itp;
891  /* add entire list to se free list */
892  __fmonse_end->fmsenxt = __fmse_freelst;
893  __fmse_freelst = __fmonse_hdr;
894  __fmonse_hdr = __fmonse_end = NULL;
895 }
896 
897 /*
898  * execute the monitor statements at end of time slot
899  * only called if at least one and like dispay not write
900  * fmonp nil implies it is $monitor
901  */
__exec_monit(struct dceauxlst_t * monit_hd,int32 force_write)902 extern void __exec_monit(struct dceauxlst_t *monit_hd, int32 force_write)
903 {
904  int32 base, sav_slin_cnt, sav_sfnam_ind;
905  struct tskcall_t *tkcp;
906  struct expr_t *tkxp;
907  struct systsk_t *stbp;
908 
909  /* if execed "$monitor;" no monitoring but force write will be on */
910  if (__monit_stp == NULL) return;
911 
912  /* first make sure at least one changed (or just starting so must write) */
913  /* and update all dce values (not per inst.) to current value if chged */
914  if (!chk_monits_chged(monit_hd) && !force_write) return;
915 
916  sav_slin_cnt = __slin_cnt;
917  sav_sfnam_ind = __sfnam_ind;
918  __slin_cnt = __monit_stp->stlin_cnt;
919  __sfnam_ind = __monit_stp->stfnam_ind;
920 
921  tkcp = &(__monit_stp->st.stkc);
922  tkxp = tkcp->tsksyx;
923  stbp = tkxp->lu.sy->el.esytbp;
924  /* current instance does not need to be preserved here */
925  __push_itstk(__monit_itp);
926 
927  switch (stbp->stsknum) {
928   case STN_MONITOR: base = BDEC; goto nonf_write;
929   case STN_MONITORH: base = BHEX; goto nonf_write;
930   case STN_MONITORB: base = BBIN; goto nonf_write;
931   case STN_MONITORO: base = BOCT;
932 nonf_write:
933    __do_disp(tkcp->targs, base);
934    __cvsim_msg("\n");
935    break;
936   case STN_FMONITOR: base = BDEC; goto f_disp;
937   case STN_FMONITORB: base = BBIN; goto f_disp;
938   case STN_FMONITORH: base = BHEX; goto f_disp;
939   case STN_FMONITORO: base = BOCT;
940 f_disp:
941    __fio_do_disp(tkcp->targs, base, TRUE, tkxp->lu.sy->synam);
942    break;
943   default: __case_terr(__FILE__, __LINE__);
944  }
945  __pop_itstk();
946  __slin_cnt = sav_slin_cnt;
947  __sfnam_ind = sav_sfnam_ind;
948 }
949 
950 /*
951  * routine to go through entire monit dce list and see if any really changed
952  * if really changed, store new value
953  *
954  * know itree loc set
955  */
chk_monits_chged(register struct dceauxlst_t * dclp)956 static int32 chk_monits_chged(register struct dceauxlst_t *dclp)
957 {
958  register struct xstk_t *xsp, *xsp2;
959  byte *sbp, *sbp2;
960  int32 i1, i2, i, chged, dcewid;
961  struct dcevnt_t *dcep;
962  struct net_t *np;
963 
964  chged = FALSE;
965  for (; dclp != NULL; dclp = dclp->dclnxt)
966   {
967    dcep = dclp->ldcep;
968 
969    /* for array index or entire non wire (not constant range), no change */
970    /* previous value needed, if in list changed */
971    /* but notice must go thru entire list to update changed values */
972    if (dcep->prevval.wp == NULL) { chged = TRUE; continue; }
973 
974    np = dcep->dce_np;
975    dcewid = __get_dcewid(dcep, np);
976    __push_itstk(dcep->dce_matchitp);
977    __get_cor_range(dcep->dci1, dcep->dci2, &i1, &i2);
978    if (np->n_stren)
979     {
980      /* for monit know exactly one prevval */
981      sbp = dcep->prevval.bp;
982      /* this uses "real" iti num */
983      get_stwire_addr_(sbp2, np);
984      if (i1 != -1) sbp2 = &(sbp2[i2]);
985 
986      if (dcep->dce_nomonstren)
987       {
988        for (i = 0; i < dcewid; i++, sbp++, sbp2++)
989         {
990          if (*sbp != *sbp2)
991           {
992            /* here only changed if value (low 2 bits) differ */
993            if ((*sbp & 3) != (*sbp2 & 3)) chged = TRUE;
994            /* always copy even if values the same */
995            *sbp = *sbp2;
996           }
997         }
998       }
999      else
1000       {
1001        if (memcmp(sbp, sbp2, dcewid) != 0)
1002         { chged = TRUE; memcpy(sbp, sbp2, dcewid); }
1003       }
1004     }
1005    else
1006     {
1007      push_xstk_(xsp, dcewid);
1008 
1009      /* this need to access 0th instance since one inst form */
1010      __push_wrkitstk(__inst_mod, 0);
1011      __ld_perinst_val(xsp->ap, xsp->bp, dcep->prevval, dcewid);
1012      __pop_wrkitstk();
1013 
1014      /* now must load from correct inst and store into one inst. */
1015      push_xstk_(xsp2, dcewid);
1016      __ld_wire_sect(xsp2->ap, xsp2->bp, np, i1, i2);
1017      if (cmp_vval_(xsp->ap, xsp2->ap, dcewid) != 0 ||
1018       cmp_vval_(xsp->bp, xsp2->bp, dcewid) != 0)
1019       {
1020        chged = TRUE;
1021 
1022        /* know tmpitp unchanged since load */
1023        __push_wrkitstk(__inst_mod, 0);
1024        __st_perinst_val(dcep->prevval, dcewid, xsp2->ap, xsp2->bp);
1025        __pop_wrkitstk();
1026       }
1027      __pop_xstk();
1028      __pop_xstk();
1029     }
1030    __pop_itstk();
1031   }
1032  return(chged);
1033 }
1034 
1035 /*
1036  * load section of wirereg for monitor and dce change determination
1037  * know itree location correct and i1 and i2 set (-2 IS form fixed by here)
1038  * if bit select of array load array cell
1039  * this is for non strength wire case
1040  */
__ld_wire_sect(word32 * ap,word32 * bp,struct net_t * np,register int32 i1,register int32 i2)1041 extern void __ld_wire_sect(word32 *ap, word32 *bp, struct net_t *np,
1042  register int32 i1, register int32 i2)
1043 {
1044  int32 arrwid;
1045 
1046  if (i1 == -1) { __ld_wire_val(ap, bp, np); return; }
1047  if (i1 == i2)
1048   {
1049    if (!np->n_isarr) __ld_bit(ap, bp, np, i1);
1050    else
1051     {
1052      arrwid = __get_arrwide(np);
1053      __ld_arr_val(ap, bp, np->nva, arrwid, np->nwid, i1);
1054     }
1055    return;
1056   }
1057  __ld_psel(ap, bp, np, i1, i2);
1058 }
1059 
1060 /*
1061  * ROUTINES TO EVALUATE RHS EXPRESSIONS
1062  */
1063 
1064 /*
1065  * wrapper for eval_xpr that sets correct exec source location
1066  */
__src_rd_eval_xpr(struct expr_t * ndp)1067 extern struct xstk_t *__src_rd_eval_xpr(struct expr_t *ndp)
1068 {
1069  struct xstk_t *xsp;
1070  int32 sav_slin_cnt, sav_sfnam_ind;
1071 
1072  /* can assign specparam value immediately */
1073  /* SJM 06/17/99 - needs to run in run/fixup mode - statement loc set */
1074  sav_slin_cnt = __slin_cnt;
1075  sav_sfnam_ind = __sfnam_ind;
1076  __sfnam_ind = __cur_fnam_ind;
1077  __slin_cnt = __lin_cnt;
1078 
1079  xsp = __eval_xpr(ndp);
1080 
1081  /* must put back in case reading iact source */
1082  __slin_cnt = sav_slin_cnt;
1083  __sfnam_ind = sav_sfnam_ind;
1084  return(xsp);
1085 }
1086 
1087 /*
1088  * for debugging special interface to evaluate expression
1089  * so stack depth can be checked
1090  * -- notice where strength needed (even if non stren) use ndst eval xpr
1091  * this is normally macro see pvmacros.h
1092  */
1093 /* --- DBG add ---
1094 extern struct xstk_t *__eval_xpr(struct expr_t *ndp)
1095 {
1096  struct xstk_t *xsp;
1097 
1098  xsp = __eval2_xpr(ndp);
1099 
1100  -* ---
1101  if (__debug_flg)
1102   {
1103    if (__xspi != 0 && __fcspi == -1)
1104     {
1105      __sgfwarn(526,
1106      "INTERNAL - %d extra values on stack after expression evaluation", __xspi);
1107     }
1108   }
1109  --- *-
1110  return(xsp);
1111 }
1112 ---- */
1113 
1114 /*
1115  * evaluate a rhs expressions
1116  * pushes and pops temps and leaves result on top of reg stack
1117  * requires all expr. node widths to be set
1118  * both for constant folding and execution
1119  * caller must pop value from stack
1120  * know a and p parts always contiguous
1121  *
1122  * this is used for constant evaluation where already check for only values
1123  * parameters are converted to numbers by here and spec params are never in
1124  * expressions
1125  *
1126  * LOOKATME - since now have real cont table and real storage table
1127  *            could get rid of double copying even for interpreter
1128  */
__eval2_xpr(register struct expr_t * ndp)1129 extern struct xstk_t *__eval2_xpr(register struct expr_t *ndp)
1130 {
1131  register struct xstk_t *xsp;
1132  int32 wlen;
1133  register word32 *wp;
1134  struct net_t *np;
1135  struct gref_t *grp;
1136  struct sy_t *syp;
1137 
1138  /* DBG remove ---
1139  if (ndp == NULL) __arg_terr(__FILE__, __LINE__);
1140  --- */
1141 
1142  /* in this case, must put value on tos */
1143  switch ((byte) ndp->optyp) {
1144   case NUMBER:
1145    push_xstk_(xsp, ndp->szu.xclen);
1146    if (ndp->szu.xclen <= WBITS)
1147     {
1148      xsp->ap[0] = __contab[ndp->ru.xvi];
1149      xsp->bp[0] = __contab[ndp->ru.xvi + 1];
1150     }
1151    else memcpy(xsp->ap, &(__contab[ndp->ru.xvi]),
1152     2*WRDBYTES*wlen_(ndp->szu.xclen));
1153 
1154    return(xsp);
1155   case REALNUM:
1156    push_xstk_(xsp, ndp->szu.xclen);
1157    /* know high bits of num value already zeroed */
1158    memcpy(xsp->ap, &(__contab[ndp->ru.xvi]),
1159     2*WRDBYTES*wlen_(ndp->szu.xclen));
1160    return(xsp);
1161   case OPEMPTY:
1162    /* this evaluates to one space - for procedural (stask) ,, connections */
1163    push_xstk_(xsp, 8);
1164    xsp->bp[0] = 0L;
1165    xsp->ap[0] = ' ';
1166    return(xsp);
1167   case UNCONNPULL:
1168    /* only for inst. input where down must be marked strength */
1169    __case_terr(__FILE__, __LINE__);
1170    break;
1171   case ISNUMBER:
1172    push_xstk_(xsp, ndp->szu.xclen);
1173    wlen = wlen_(ndp->szu.xclen);
1174    wp = (word32 *) &(__contab[ndp->ru.xvi]);
1175    memcpy(xsp->ap, &(wp[2*wlen*__inum]), 2*WRDBYTES*wlen);
1176    return(xsp);
1177   case ISREALNUM:
1178    push_xstk_(xsp, ndp->szu.xclen);
1179    wlen = wlen_(ndp->szu.xclen);
1180    wp = &(__contab[ndp->ru.xvi + 2*__inum]);
1181    memcpy(xsp->ap, wp, 2*WRDBYTES*wlen);
1182    return(xsp);
1183   case GLBREF:
1184    /* if local fall through - symbol and cur. itp right */
1185    grp = ndp->ru.grp;
1186    __xmrpush_refgrp_to_targ(grp);
1187    push_xstk_(xsp, ndp->szu.xclen);
1188    /* know this is global wire or will not get here */
1189    /* cannot use short circuit xva for globals */
1190    np = grp->targsyp->el.enp;
1191    __ld_wire_val(xsp->ap, xsp->bp, np);
1192    __pop_itstk();
1193    goto done;
1194   case ID:
1195    push_xstk_(xsp, ndp->szu.xclen);
1196    np = ndp->lu.sy->el.enp;
1197    __ld_wire_val(xsp->ap, xsp->bp, np);
1198    goto done;
1199   case LSB:
1200    push_bsel(ndp);
1201    goto done;
1202   case PARTSEL:
1203    push_psel(ndp);
1204    goto done;
1205   case LCB:
1206    __rhs_concat(ndp);
1207    goto done;
1208   case FCALL:
1209    syp = ndp->lu.x->lu.sy;
1210    /* notice these routines in v_ex - result left on top of stack */
1211    /* as usual caller must free */
1212    if (syp->sytyp == SYM_SF) __exec_sysfunc(ndp); else __exec_func(ndp);
1213    /* function return value now on top of stack */
1214    goto done;
1215   case QUEST:
1216    /* notice that because of side effects, must evaluate in order */
1217    __eval_qcol(ndp);
1218    goto done;
1219   case REALREALQUEST:
1220    __eval_realrealqcol(ndp);
1221    goto done;
1222   case REALREGQUEST:
1223    __eval_realregqcol(ndp);
1224    goto done;
1225   case REGREALQCOL:
1226    __eval_regrealqcol(ndp);
1227    /* 1 value now on tos */
1228    goto done;
1229   }
1230  if (ndp->ru.x == NULL) eval_unary(ndp); else eval_binary(ndp);
1231 done:
1232  return(__xstk[__xspi]);
1233 }
1234 
1235 /*
1236  * routine to grow xstk
1237  */
__grow_xstk(void)1238 extern void __grow_xstk(void)
1239 {
1240  register int32 i;
1241  int32 old_maxxnest;
1242  int32 osize, nsize;
1243 
1244  old_maxxnest = __maxxnest;
1245  osize = old_maxxnest*sizeof(struct xstk_t *);
1246  if (__maxxnest >= XNESTFIXINC) __maxxnest += XNESTFIXINC;
1247  else __maxxnest *= 2;
1248  nsize = __maxxnest*sizeof(struct xstk_t *);
1249  __xstk = (struct xstk_t **) __my_realloc((char *) __xstk, osize, nsize);
1250  /* assume stack hold 1 work case at initialization */
1251  for (i = old_maxxnest; i < __maxxnest; i++)
1252   {
1253    __xstk[i] = (struct xstk_t *) __my_malloc(sizeof(struct xstk_t));
1254    __alloc_xsval(__xstk[i], 1);
1255   }
1256  if (__debug_flg)
1257   __dbg_msg("+++ expr. stack grew from %d bytes to %d\n", osize, nsize);
1258 }
1259 
1260 /*
1261  * routine to widen xstk element if wider than default words - rare
1262  */
__chg_xstk_width(struct xstk_t * xsp,int32 wlen)1263 extern void __chg_xstk_width(struct xstk_t *xsp, int32 wlen)
1264 {
1265  /* freeing in case of need for very wide expr. */
1266  __my_free((char *) xsp->ap, 2*WRDBYTES*xsp->xsawlen);
1267  __alloc_xsval(xsp, wlen);
1268 }
1269 
1270 /*
1271  * allocate stack entry value word32 array
1272  * only called after need to widen determined
1273  * this allocates wide enough stack value - caller must set width and value
1274  * this always makes a and b parts contiguous
1275  *
1276  * only allocate and free here
1277  * FIXME - why not use re-alloc?
1278  */
__alloc_xsval(struct xstk_t * xsp,int32 xstkwlen)1279 extern void __alloc_xsval(struct xstk_t *xsp, int32 xstkwlen)
1280 {
1281  word32 *ap;
1282  int32 awlen;
1283 
1284  awlen = (xstkwlen < DFLTIOWORDS) ? DFLTIOWORDS : xstkwlen;
1285  /* notice a and b parts must be allocated once contiguously */
1286  /* 4 words means 128 bits at 32 bits dependent per word32 */
1287  ap = (word32 *) __my_malloc(2*WRDBYTES*awlen);
1288  xsp->ap = ap;
1289  /* this makes 2 part contiguous */
1290  xsp->bp = &(ap[xstkwlen]);
1291  xsp->xsawlen = awlen;
1292 }
1293 
1294 /*
1295  * load (copy) an entire value into possibly separated rgap and rgbp from wp
1296  * of length blen instance cur. itp loaded with representation srep
1297  *
1298  * assumes cur. itp starts at 0
1299  * cannot be used to access array and removes any strengths (value only)
1300  * rgap and rgbp assumed to have enough room
1301  * also for params and specparams
1302  */
__ld_wire_val(register word32 * rgap,register word32 * rgbp,struct net_t * np)1303 extern void __ld_wire_val(register word32 *rgap, register word32 *rgbp,
1304  struct net_t *np)
1305 {
1306  register word32 uwrd, *rap, *wp;
1307  register int32 wlen;
1308  struct expr_t *xp;
1309  struct expr_t **pxparr;
1310  struct xstk_t *xsp;
1311 
1312  switch ((byte) np->srep) {
1313   case SR_VEC:
1314    /* rap is 2*wlen word32 section of vec array that stores cur. inst vec. */
1315    wlen = wlen_(np->nwid);
1316    /* DBG remove ---
1317    if (__inst_ptr == NULL) __arg_terr(__FILE__, __LINE__);
1318    --- */
1319    rap = &(np->nva.wp[2*wlen*__inum]);
1320    memcpy(rgap, rap, WRDBYTES*wlen);
1321    memcpy(rgbp, &(rap[wlen]), WRDBYTES*wlen);
1322    return;
1323   case SR_SVEC:
1324    __ld_stval(rgap, rgbp, &(np->nva.bp[np->nwid*__inum]), np->nwid);
1325    return;
1326   case SR_SCAL:
1327    ld_scalval_(rgap, rgbp, np->nva.bp);
1328    return;
1329   case SR_SSCAL:
1330    /* notice accessing byte value and assign so endian ok */
1331    uwrd = (word32) np->nva.bp[__inum];
1332    rgap[0] = uwrd & 1L;
1333    rgbp[0] = (uwrd >> 1) & 1L;
1334    return;
1335 
1336   /* PX representations are left for getting param value at run time */
1337   /* also for parameter forms never selects */
1338   case SR_PXPR:
1339    wlen = wlen_(np->nwid);
1340    /* this assumes for parameters expr. points to nva expr. field */
1341    xp = (struct expr_t *) np->nva.wp;
1342    xsp = __eval2_xpr(xp);
1343    memcpy(rgap, xsp->ap, WRDBYTES*wlen);
1344    memcpy(rgbp, xsp->bp, WRDBYTES*wlen);
1345    __pop_xstk();
1346    return;
1347   case SR_PISXPR:
1348    wlen = wlen_(np->nwid);
1349    /* this assumes for parameters expr. points to nva expr. field */
1350    /* caller sets iti num */
1351    pxparr = (struct expr_t **) np->nva.wp;
1352    xsp = __eval2_xpr(pxparr[__inum]);
1353    /* if real just copy */
1354    memcpy(rgap, xsp->ap, WRDBYTES*wlen);
1355    memcpy(rgbp, xsp->bp, WRDBYTES*wlen);
1356    __pop_xstk();
1357    return;
1358   case SR_PNUM:
1359    wlen = wlen_(np->nwid);
1360    wp = np->nva.wp;
1361    memcpy(rgap, wp, WRDBYTES*wlen);
1362    memcpy(rgbp, &(wp[wlen]), WRDBYTES*wlen);
1363    return;
1364   case SR_PISNUM:
1365    wlen = wlen_(np->nwid);
1366    wp = &(np->nva.wp[2*wlen*__inum]);
1367    memcpy(rgap, wp, WRDBYTES*wlen);
1368    memcpy(rgbp, &(wp[wlen]), WRDBYTES*wlen);
1369    return;
1370   default: __case_terr(__FILE__, __LINE__);
1371  }
1372 }
1373 
1374 /*
1375  * load per inst. value - allows packing etc.
1376  * mostly for continuous assign driver
1377  * not for strengths and needs __inst_ptr to be set
1378  * caller needs to push big enough area pointed to by rgap/rgbp
1379  *
1380  * know size change never needed here
1381  */
__ld_perinst_val(register word32 * rgap,register word32 * rgbp,union pck_u pckv,int32 vblen)1382 extern void __ld_perinst_val(register word32 *rgap, register word32 *rgbp,
1383  union pck_u pckv, int32 vblen)
1384 {
1385  word32 *rap;
1386  int32 wlen;
1387 
1388  if (vblen == 1) { ld_scalval_(rgap, rgbp, pckv.bp); return; }
1389  /* SJM - 07/15/00 - all per-inst vecs in at least 2 words */
1390  wlen = wlen_(vblen);
1391  rap = &(pckv.wp[2*wlen*__inum]);
1392  memcpy(rgap, rap, WRDBYTES*wlen);
1393  memcpy(rgbp, &(rap[wlen]), WRDBYTES*wlen);
1394 }
1395 
1396 /*
1397  * load value part of a strength scalar bytes array into an a/b vector
1398  * strength bytes (bits) stored low to high just like normal words
1399  *
1400  * notice this uses lhs selects into rgap/rgbp so must 0 to start
1401  * and cannot assume contiguous
1402  */
__ld_stval(register word32 * rgap,register word32 * rgbp,register byte * sbp,int32 blen)1403 extern void __ld_stval(register word32 *rgap, register word32 *rgbp,
1404  register byte *sbp, int32 blen)
1405 {
1406  register int32 bi;
1407  int32 wlen;
1408  word32 tmpw;
1409 
1410  /* zero unused high bits in high word32 only - rest will be selected into */
1411  wlen = wlen_(blen);
1412  rgap[wlen - 1] = 0L;
1413  rgbp[wlen - 1] = 0L;
1414  for (bi = 0; bi < blen; bi++)
1415   {
1416    tmpw = (word32) sbp[bi];
1417    __lhsbsel(rgap, bi, tmpw & 1L);
1418    __lhsbsel(rgbp, bi, (tmpw >> 1) & 1L);
1419   }
1420 }
1421 
1422 /*
1423  * push (access) a selected bit or array locaton on top of reg. stack
1424  * know width will be 1 if bit or array vector width if array
1425  *
1426  * this can be improved by assigning free reg not just pushing
1427  * for now not separating at compile time (stupid) so separate is done here
1428  */
push_bsel(struct expr_t * ndp)1429 static void push_bsel(struct expr_t *ndp)
1430 {
1431  register struct xstk_t *xsp;
1432  register struct net_t *np;
1433  register word32 *rap;
1434  int32 biti, arrwid, wlen;
1435  struct expr_t *idndp;
1436 
1437  idndp = ndp->lu.x;
1438  np = idndp->lu.sy->el.enp;
1439 
1440  /* can be either constant or expr. - both handled in comp. */
1441  biti = __comp_ndx(np, ndp->ru.x);
1442  push_xstk_(xsp, ndp->szu.xclen);
1443  if (biti == -1)
1444   {
1445    /* notice too many places where cannot emit warning - just change to x/z */
1446    set_regtox_(xsp->ap, xsp->bp, xsp->xslen);
1447    return;
1448   }
1449 
1450  /* notice load routines unwound into both paths */
1451  if (idndp->optyp != GLBREF)
1452   {
1453    /* if (!np->n_isarr) __ld_bit(xsp->ap, xsp->bp, np, biti); */
1454    if (!np->n_isarr)
1455     {
1456      if (np->srep == SR_VEC)
1457       {
1458        /* BEWARE - this is vectored rep. short circuit */
1459        wlen = wlen_(np->nwid);
1460        rap = &(np->nva.wp[2*wlen*__inum]);
1461        xsp->ap[0] = rhsbsel_(rap, biti);
1462        xsp->bp[0] = rhsbsel_(&(rap[wlen]), biti);
1463       }
1464      else __ld_bit(xsp->ap, xsp->bp, np, biti);
1465     }
1466    else
1467     {
1468      arrwid = __get_arrwide(np);
1469      __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, biti);
1470     }
1471    return;
1472   }
1473 
1474  __xmrpush_refgrp_to_targ(idndp->ru.grp);
1475  /* if (!np->n_isarr) __ld_bit(xsp->ap, xsp->bp, np, biti); */
1476  if (!np->n_isarr)
1477   {
1478    if (np->srep == SR_VEC)
1479     {
1480      /* BEWARE - this is vectored rep. short circuit */
1481      wlen = wlen_(np->nwid);
1482      rap = &(np->nva.wp[2*wlen*__inum]);
1483      xsp->ap[0] = rhsbsel_(rap, biti);
1484      xsp->bp[0] = rhsbsel_(&(rap[wlen]), biti);
1485     }
1486    else __ld_bit(xsp->ap, xsp->bp, np, biti);
1487   }
1488  else
1489   {
1490    arrwid = __get_arrwide(np);
1491    __ld_arr_val(xsp->ap, xsp->bp, np->nva, arrwid, np->nwid, biti);
1492   }
1493  __pop_itstk();
1494 }
1495 
1496 /*
1497  * compute a vector or array var or constant index value
1498  * returns -1 on x - caller must handle
1499  * if returns -1, globals __badind_a and __badind_b contain value
1500  *
1501  * if net is a array, array index else vector index
1502  *
1503  * just like C implied truncating index to 32 bit value
1504  * constants are already normalized during compilation
1505  * reals illegal and caught before here
1506  */
__comp_ndx(register struct net_t * np,register struct expr_t * ndx)1507 extern int32 __comp_ndx(register struct net_t *np,
1508  register struct expr_t *ndx)
1509 {
1510  register word32 *rap;
1511  register word32 *wp;
1512  int32 biti, ri1, ri2, biti2, obwid;
1513  struct net_t *xnp;
1514  struct xstk_t *xsp2;
1515 
1516  /* special case 0 - simple unpacked variable */
1517  /* SJM 05/21/04 - can only short circuit if fits in one word32 */
1518  if (ndx->optyp == ID && ndx->szu.xclen <= WBITS)
1519   {
1520    xnp = ndx->lu.sy->el.enp;
1521    if (xnp->srep != SR_VEC) goto nd_eval;
1522 
1523    /* BEWARE - this short circuit assumes particular SR_VEC d.s. */
1524    rap = &(xnp->nva.wp[2*__inum]);
1525    biti2 = rap[0];
1526    if (rap[1] == 0L) goto normalize;
1527 
1528    __badind_a = rap[0];
1529    __badind_b = rap[1];
1530    __badind_wid = xnp->nwid;
1531    return(-1);
1532   }
1533 
1534  /* case 1: constant */
1535  if (ndx->optyp == NUMBER)
1536   {
1537    wp = &(__contab[ndx->ru.xvi]);
1538    if (wp[1] != 0L)
1539     {
1540      __badind_a = wp[0];
1541      __badind_b = wp[1];
1542      __badind_wid = ndx->szu.xclen;
1543      return(-1);
1544     }
1545    return((int32) wp[0]);
1546   }
1547  /* case 2 IS constant */
1548  /* notice IS NUMBER form must be normalized at compile time */
1549  if (ndx->optyp == ISNUMBER)
1550   {
1551    wp = &(__contab[ndx->ru.xvi]);
1552    wp = &(wp[2*__inum]);
1553    if (wp[1] != 0L)
1554     {
1555      __badind_a = wp[0];
1556      __badind_b = wp[1];
1557      __badind_wid = ndx->szu.xclen;
1558      return(-1);
1559     }
1560    return((int32) wp[0]);
1561   }
1562  /* case 3 expression */
1563  /* case 3b - other expr. */
1564 nd_eval:
1565  xsp2 = __eval2_xpr(ndx);
1566 
1567  if (xsp2->bp[0] != 0L)
1568   {
1569    __badind_a = xsp2->ap[0];
1570    __badind_b = xsp2->bp[0];
1571    __badind_wid = ndx->szu.xclen;
1572    __pop_xstk();
1573    return(-1);
1574   }
1575  biti2 = (int32) xsp2->ap[0];
1576  __pop_xstk();
1577 
1578 normalize:
1579  /* convert index to h:0 normalized value */
1580  /* === SJM 11/16/03 - using inline code this is slower
1581  if (np->n_isarr) __getarr_range(np, &ri1, &ri2, &obwid);
1582  else { __getwir_range(np, &ri1, &ri2); obwid = np->nwid; }
1583  === */
1584 
1585  /* SJM 11/14/03 - use original code - MAYBE PUTMEBACK */
1586  if (np->n_isarr)
1587   {
1588    ri1 = np->nu.rngarr->ai1;
1589    ri2 = np->nu.rngarr->ai2;
1590    obwid = (ri1 >= ri2) ? (ri1 - ri2 + 1) : (ri2 - ri1 + 1);
1591   }
1592  else
1593   {
1594    if (np->nrngrep == NX_CT)
1595     {
1596      ri1 = (int32) __contab[np->nu.ct->nx1->ru.xvi];
1597      ri2 = (int32) __contab[np->nu.ct->nx2->ru.xvi];
1598     }
1599    else
1600     {
1601      ri1 = np->nu.rngdwir->ni1;
1602      ri2 = np->nu.rngdwir->ni2;
1603     }
1604    obwid = np->nwid;
1605   }
1606 
1607  biti = normalize_ndx_(biti2, ri1, ri2);
1608  /* SJM 05/21/04 - for 0:h - if above - value will be negative */
1609  if (biti >= obwid || biti < 0)
1610   { __badind_a = biti2; __badind_b = 0L; __badind_wid = WBITS; return(-1); }
1611  return(biti);
1612 }
1613 
1614 /*
1615  * pop the expression stack
1616  * DBG macro: #define __pop_xstk() xsp = __xstk[__xspi--]
1617  */
1618 /* -- ??? DBG ADD --
1619 extern void __pop_xstk(void)
1620 {
1621  struct xstk_t *xsp;
1622 
1623  if (__xspi < 0) __arg_terr(__FILE__, __LINE__);
1624  xsp = __xstk[__xspi];
1625  if (xsp->xsawlen > MUSTFREEWORDS) __chg_xstk_width(xsp, 1);
1626  __xspi--;
1627  -* ---
1628  if (__debug_flg)
1629   __dbg_msg("+++ popping stack to height %d, old bit length %d\n", __xspi + 1,
1630    xsp->xslen);
1631  ---*-
1632 }
1633 --- */
1634 
1635 /* BEWARE - a and b parts must be contiguous because often refed as only a */
1636 /* -- ??? DBG ADD --
1637 extern struct xstk_t *__push_xstk(int32 blen)
1638 {
1639  register struct xstk_t *xsp;
1640 
1641  if (++__xspi >= __maxxnest) __grow_xstk();
1642  xsp = __xstk[__xspi];
1643  if (wlen_(blen) > xsp->xsawlen) __chg_xstk_width(xsp, wlen_(blen));
1644  xsp->bp = &(xsp->ap[wlen_(blen)]);
1645  xsp->xslen = blen;
1646 
1647  -* --- *-
1648  if (__debug_flg)
1649   __dbg_msg("+++ pushing stack to height %d, bit length %d\n", __xspi + 1,
1650    xsp->xslen);
1651  -* ---*-
1652 
1653  return(xsp);
1654 }
1655 --- */
1656 
1657 /*
1658  * load one bit into low bit position of registers rgpa and rgpb from
1659  * coded wp of length blen from biti current instance stored using
1660  * representation srep;
1661  * biti must be corrected to normalized h:0 value before here
1662  * and biti of x also handled before here
1663  * know result will be isolated in low bit value (no need to mask)
1664  *
1665  * this differs from rhs bit select in accessing value for current inst and
1666  * adjusting place to select from according to storage representation
1667  * if value out of range sets result to x
1668  *
1669  * cannot be used to access array and ignores strength parts of stren values
1670  * at least for now this load makes a copy in normal ab vector form
1671  *
1672  * only run time SR forms possible here
1673  * BEWARE - this is sometimes used to load scalar so much leave scalar sreps
1674  */
__ld_bit(register word32 * rgap,register word32 * rgbp,register struct net_t * np,int32 biti)1675 extern void __ld_bit(register word32 *rgap, register word32 *rgbp,
1676  register struct net_t *np, int32 biti)
1677 {
1678  register word32 uwrd, *rap;
1679  register int32 wlen;
1680 
1681  /* out of range is x */
1682  if (biti > np->nwid) { rgap[0] = rgbp[0] = 1L; return; }
1683  /* this is number of words needed to hold a or b part not region */
1684  switch ((byte) np->srep) {
1685   case SR_VEC:
1686    wlen = wlen_(np->nwid);
1687    /* rap is start of instance coded vector a/b groups */
1688    rap = &(np->nva.wp[2*wlen*__inum]);
1689    rgap[0] = rhsbsel_(rap, biti);
1690    rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
1691    break;
1692   case SR_SVEC:
1693    /* strength vectors normalized to h:0 which means v[0] is index 0 */
1694    /* since h:0 means low bit to left in radix style notation */
1695    uwrd = (word32) np->nva.bp[__inum*np->nwid + biti];
1696 do_slb:
1697    rgap[0] = uwrd & 1L;
1698    rgbp[0] = (uwrd >> 1) & 1L;
1699    break;
1700   case SR_SCAL:
1701    /* LOOKATME - maybe load bit of scalar should be fatat err */
1702    /* this is same as full value load for 1 bit thing */
1703    /* notice biti will be 0 or will not get here */
1704    ld_scalval_(rgap, rgbp, np->nva.bp);
1705    break;
1706   case SR_SSCAL:
1707    uwrd = (word32) np->nva.bp[__inum];
1708    goto do_slb;
1709   case SR_PISNUM:
1710    wlen = wlen_(np->nwid);
1711    /* rap is start of instance coded vector a/b groups */
1712    rap = &(np->nva.wp[2*wlen*__inum]);
1713    rgap[0] = rhsbsel_(rap, biti);
1714    rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
1715    break;
1716   /* SJM 08/22/00 - also allowing part and bit selects from parameters */
1717   case SR_PNUM:
1718    wlen = wlen_(np->nwid);
1719    /* rap is start of instance coded vector a/b groups */
1720    rap = np->nva.wp;
1721    rgap[0] = rhsbsel_(rap, biti);
1722    rgbp[0] = rhsbsel_(&(rap[wlen]), biti);
1723    break;
1724   default: __case_terr(__FILE__, __LINE__);
1725  }
1726 }
1727 
1728 /*
1729  * load one indexed element of a array map, size mlen with each element
1730  * blen wide from index arri from current instance into rgap and rgbp
1731  *
1732  * arrays stored and normalized h:0 just like vectors
1733  *
1734  * vector (or scalar) are packed into 1 linear array of partial bit
1735  * elements - 4,8,16,32 with both a and b together - both array index
1736  * and instance index used to decode linear array
1737  *
1738  * arri here must be normalized to h:0 form
1739  * map is base of array area (np nva)
1740  */
__ld_arr_val(register word32 * rgap,register word32 * rgbp,union pck_u map,int32 mlen,int32 blen,int32 arri)1741 extern void __ld_arr_val(register word32 *rgap, register word32 *rgbp,
1742  union pck_u map, int32 mlen, int32 blen, int32 arri)
1743 {
1744  register int32 wlen;
1745  register word32 *rap;
1746  word32 tmpw;
1747  int32 indi;
1748 
1749  /* compute number of words used to store 1 array element */
1750  /* 17 or more bits cannot be packed with multiple elements per word32 */
1751  if (blen > WBITS/2)
1752   {
1753    /* case 1: each vector element of array needs multiple words */
1754    wlen = wlen_(blen);
1755    /* find array for inst i with each vector wlen words wide */
1756    rap = &(map.wp[2*wlen*mlen*__inum]);
1757    /* find element arri that may be a vector */
1758    rap = &(rap[arri*2*wlen]);
1759    cp_walign_(rgap, rap, blen);
1760    cp_walign_(rgbp, &(rap[wlen]), blen);
1761    return;
1762   }
1763  /* case 2: array of scalars */
1764  if (blen == 1)
1765   {
1766    /* here arri is real twice real index to get bit index */
1767    indi = 2*(mlen*__inum + arri);
1768    tmpw = map.wp[get_wofs_(indi)] >> (get_bofs_(indi));
1769    rgap[0] = tmpw & 1L;
1770    rgbp[0] = (tmpw >> 1) & 1L;
1771    return;
1772   }
1773  /* case 3: multiple elements packed per word32, half word32, or byte */
1774  indi = __inum*mlen + arri;
1775  /* SJM 12/16/99 - still need to really pack memories to bytes and hwords */
1776  tmpw = get_packintowrd_(map, indi, blen);
1777  rgap[0] = tmpw & __masktab[blen];
1778  /* know high unused bits of byte, hword, or word 0 */
1779  rgbp[0] = (tmpw >> blen);
1780 }
1781 
1782 /*
1783  * push (access) a selected part select range on top of reg. stack
1784  * know index values must be <= WBITS constants
1785  * notice for now only one representation for vector that can be part selected
1786  * from - one bit ok but cannot part select from scalar
1787  */
push_psel(register struct expr_t * ndp)1788 static void push_psel(register struct expr_t *ndp)
1789 {
1790  register struct expr_t *ndx1, *ndx2;
1791  int32 bi1, bi2;
1792  struct expr_t *idndp;
1793  struct xstk_t *xsp;
1794  struct net_t *np;
1795  struct gref_t *grp;
1796 
1797  idndp = ndp->lu.x;
1798  /* know these are both constant nodes */
1799  ndx1 = ndp->ru.x->lu.x;
1800  ndx2 = ndp->ru.x->ru.x;
1801  push_xstk_(xsp, ndp->szu.xclen);
1802 
1803  /* here never need to execute a part select with x range - what is meaning */
1804  bi1 = __contab[ndx1->ru.xvi];
1805  bi2 = __contab[ndx2->ru.xvi];
1806  /* notice calling of ld psel unwound to 2 paths */
1807  if (idndp->optyp == GLBREF)
1808   {
1809    grp = idndp->ru.grp;
1810    __xmrpush_refgrp_to_targ(grp);
1811    np = grp->targsyp->el.enp;
1812    __ld_psel(xsp->ap, xsp->bp, np, bi1, bi2);
1813    __pop_itstk();
1814    return;
1815   }
1816  /* part selects bit numbered from h:0 (i.e. 31..0) */
1817  np = idndp->lu.sy->el.enp;
1818  __ld_psel(xsp->ap, xsp->bp, np, bi1, bi2);
1819 }
1820 
1821 /*
1822  * load part select into low bit positions of registers rgap and rgbp from
1823  * coded wp of length blen from bit1 to bit2 current instance
1824  *
1825  * representation must be a vector
1826  * bit1 > bit2 according to normalized h:0 form
1827  * low bit is 0 and high bit is 31 in word
1828  * part select in range or will not get here
1829  *
1830  * notice perfectly legal to declare wire [1:1] x and psel the 1 bit
1831  */
__ld_psel(register word32 * rgap,register word32 * rgbp,register struct net_t * np,int32 bith,int32 bitl)1832 extern void __ld_psel(register word32 *rgap, register word32 *rgbp,
1833  register struct net_t *np, int32 bith, int32 bitl)
1834 {
1835  register word32 *rap;
1836  byte *netsbp;
1837  int32 wlen, numbits;
1838 
1839  numbits = bith - bitl + 1;
1840 
1841  switch ((byte) np->srep) {
1842   case SR_VEC:
1843    /* rap is start of current instance coded vector a b groups */
1844    wlen = wlen_(np->nwid);
1845    rap = &(np->nva.wp[2*wlen*__inum]);
1846    /* this routine expects select to start from bit in 1st word32 */
1847    __rhspsel(rgap, rap, bitl, numbits);
1848    rap = &(rap[wlen]);
1849    __rhspsel(rgbp, rap, bitl, numbits);
1850    break;
1851   case SR_SVEC:
1852    netsbp = &(np->nva.bp[__inum*np->nwid + bitl]);
1853    /* copy from low to high in array according to radix notation */
1854    __ld_stval(rgap, rgbp, netsbp, numbits);
1855    break;
1856   /* SJM 08/22/00 - also allowing part and bit selects from parameters */
1857   case SR_PNUM:
1858    /* rap is start of current instance coded vector a b groups */
1859    wlen = wlen_(np->nwid);
1860    rap = np->nva.wp;
1861    /* this routine expects select to start from bit in 1st word32 */
1862    __rhspsel(rgap, rap, bitl, numbits);
1863    rap = &(rap[wlen]);
1864    __rhspsel(rgbp, rap, bitl, numbits);
1865    break;
1866   case SR_PISNUM:
1867    /* rap is start of current instance coded vector a b groups */
1868    wlen = wlen_(np->nwid);
1869    rap = &(np->nva.wp[2*wlen*__inum]);
1870    /* this routine expects select to start from bit in 1st word32 */
1871    __rhspsel(rgap, rap, bitl, numbits);
1872    rap = &(rap[wlen]);
1873    __rhspsel(rgbp, rap, bitl, numbits);
1874    break;
1875   default: __case_terr(__FILE__, __LINE__);
1876  }
1877 }
1878 
1879 /*
1880  * right hand side part select from swp of len sblen at sbit1 into dwp
1881  *
1882  * selecting numbits long section
1883  * sbits must be in range 0 to [high bit]
1884  * notice for part select, range correction done at compile time
1885  * also notice that 1 bits things can go through here but not lhs psel
1886  */
__rhspsel(register word32 * dwp,register word32 * swp,register int32 sbit1,register int32 numbits)1887 extern void __rhspsel(register word32 *dwp, register word32 *swp,
1888  register int32 sbit1, register int32 numbits)
1889 {
1890  register int32 wi, corsbit1;
1891 
1892  /* case 1 - select within 1st word32 */
1893  if (sbit1 + numbits <= WBITS)
1894   {
1895    corsbit1 = sbit1;
1896 do_inword:
1897    if (corsbit1 == 0) *dwp = *swp & __masktab[numbits];
1898    else *dwp = (*swp >> corsbit1) & __masktab[numbits];
1899    return;
1900   }
1901 
1902  /* normalize so swp and corsbit1 start of src with corsbit1 in 1st word32 */
1903  wi = get_wofs_(sbit1);
1904  swp = &(swp[wi]);
1905  corsbit1 = ubits_(sbit1);
1906 
1907  /* case 2 - selection does not cross word32 boundary */
1908  if (corsbit1 + numbits <= WBITS) goto do_inword;
1909 
1910  /* case 3a - selection crosses word32 boundary but start on word32 boundary */
1911  if (corsbit1 == 0) { cp_walign_(dwp, swp, numbits); return; }
1912 
1913  /* case 3a - crosses 1 word32 boundary and <= WBITS long */
1914  if (numbits <= WBITS)
1915   {
1916    *dwp = (swp[0] >> corsbit1);
1917    *dwp |= swp[1] << (WBITS - corsbit1);
1918    *dwp &= __masktab[numbits];
1919    return;
1920   }
1921  __cp_sofs_wval(dwp, swp, corsbit1, numbits);
1922 }
1923 
1924 /*
1925  * ROUTINES TO IMPLEMENT READMEM
1926  */
1927 
1928 /*
1929  * execute the readmem[bh] system task
1930  * know 2nd argument array and from 2 to 4 args or will not get here
1931  * LOOKATME maybe a memory leak with __cur_fnam?
1932  */
__exec_readmem(struct expr_t * argxp,int32 base)1933 extern void __exec_readmem(struct expr_t *argxp, int32 base)
1934 {
1935  int32 slen, ri1, ri2, arrwid, arr1, arr2;
1936  int32 tmpi, sav_lincnt, nd_itpop;
1937  FILE *f;
1938  struct expr_t *axp;
1939  struct net_t *np;
1940  char *chp, *savfnam;
1941  char s1[RECLEN];
1942 
1943  axp = argxp->lu.x;
1944  /* if contains non printable ok, since will just not be able to open file */
1945  chp = __get_eval_cstr(axp, &slen);
1946  savfnam = __cur_fnam;
1947  sav_lincnt = __lin_cnt;
1948  /* notice must copy out of __exprline since reused below */
1949  __cur_fnam = chp;
1950  if ((f = __tilde_fopen(__cur_fnam, "r")) == NULL)
1951   {
1952    __sgferr(716, "unable to open $readmem%c input file %s",
1953     __to_baselet(base), __cur_fnam);
1954    goto no_fil_done;
1955   }
1956 
1957  /* 2nd arg. is array destination */
1958  argxp = argxp->ru.x;
1959  axp = argxp->lu.x;
1960 
1961  /* know will be array name ID or array name global reference */
1962  if (axp->optyp == GLBREF)
1963   {
1964    __xmrpush_refgrp_to_targ(axp->ru.grp);
1965    nd_itpop = TRUE;
1966   }
1967  else nd_itpop = FALSE;
1968 
1969  if (axp->is_real)
1970   {
1971    __sgferr(717, "$readmem%c of %s illegal no readmem of array of reals",
1972     __to_baselet(base), __msgexpr_tostr(__xs, axp));
1973    goto fil_done;
1974   }
1975  np = axp->lu.sy->el.enp;
1976 
1977  argxp = argxp->ru.x;
1978  /* know this is array so range is array range */
1979  __getarr_range(np, &ri1, &ri2, &arrwid);
1980  /* set up addresses */
1981  /* if no range - use array declaration range */
1982  arr1 = arr2 = -1;
1983  if (argxp != NULL)
1984   {
1985    axp = argxp->lu.x;
1986    if (axp->optyp != OPEMPTY)
1987     {
1988      if ((tmpi = __comp_ndx(np, axp)) == -1)
1989       {
1990        __sgferr(717,
1991         "$readmem%c start address expression %s unknown or out of range",
1992         __to_baselet(base), __msgexpr_tostr(__xs, axp));
1993        goto fil_done;
1994       }
1995      sprintf(s1, "$readmem%c start", __to_baselet(base));
1996      if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto fil_done;
1997      arr1 = tmpi;
1998     }
1999    argxp = argxp->ru.x;
2000    /* if no 2nd ending range (4th arg), use array decl. 2nd range */
2001    if (argxp != NULL)
2002     {
2003      axp = argxp->lu.x;
2004      if (axp->optyp != OPEMPTY)
2005       {
2006        if ((tmpi = __comp_ndx(np, axp)) == -1)
2007         {
2008          __sgferr(718,
2009           "$readmem%c end address expression %s unknown or out of range",
2010           __to_baselet(base), __msgexpr_tostr(__xs, axp));
2011          goto fil_done;
2012         }
2013        sprintf(s1, "$readmem%c end", __to_baselet(base));
2014        if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto fil_done;
2015        arr2 = tmpi;
2016        if (arr1 == -1)
2017         {
2018          __sgferr(718,
2019           "$readmem%c end address value %d illegal - no start address",
2020           __to_baselet(base), arr2);
2021          goto fil_done;
2022         }
2023       }
2024     }
2025   }
2026  __do_rm_reading(f, base, np, arr1, arr2, ri1, ri2, arrwid);
2027  /* DBG remove ---
2028  if (__debug_flg) __dmp_arr_all(np, __inum, __inum);
2029  --- */
2030 
2031 fil_done:
2032  if (nd_itpop) __pop_itstk();
2033  __my_fclose(f);
2034 no_fil_done:
2035  __lin_cnt = sav_lincnt;
2036  __cur_fnam = savfnam;
2037 }
2038 
2039 /*
2040  * check a readmem range value to make sure in range
2041  * return F on error
2042  */
chk_rm_rng_legal(int32 tmpi,int32 ri1,int32 ri2,char * msg)2043 static int32 chk_rm_rng_legal(int32 tmpi, int32 ri1, int32 ri2, char *msg)
2044 {
2045  if (ri1 <= ri2) { if (tmpi >= ri1 && tmpi <= ri2) return(TRUE); }
2046  else { if (tmpi <= ri1 && tmpi >= ri2) return(TRUE); }
2047  __sgferr(712, "%s address value %d outside memory range [%d:%d]",
2048   msg, tmpi, ri1, ri2);
2049  return(FALSE);
2050 }
2051 
2052 /*
2053  * do the readmem reading and filling
2054  *
2055  * SJM - 06/19/00 - LRM wrong fills from 0 to high unless
2056  * ranges arr1 and arr2 both given
2057  * -1 for arr1 and/or arr2 if not given if only arr1 given direction up
2058  * arr2 can only be set if arr1 is
2059  * only way array down (-1 direction) if arr1 > arr2
2060  *
2061  * this corrects each time for non h:0 form if needed
2062  * if readmem array is XMR itree loc changed before this call
2063  */
__do_rm_reading(FILE * f,int32 base,struct net_t * np,int32 arr1,int32 arr2,int32 ri1,int32 ri2,int32 arrwid)2064 extern void __do_rm_reading(FILE *f, int32 base, struct net_t *np,
2065  int32 arr1, int32 arr2, int32 ri1, int32 ri2, int32 arrwid)
2066 {
2067  register int32 arri, rmfr, rmto;
2068  int32 dir, nbytes, ttyp, h0_arri, no_rngwarn;
2069  struct xstk_t *xsp;
2070 
2071  /* fill the array */
2072  no_rngwarn = FALSE;
2073  __lin_cnt = 1;
2074  /* if only one starting range, direction toward high */
2075  /* only way for downward range is arr2 not -1 and arr2 > arr1 */
2076  if (arr2 != -1) { if (arr1 <= arr2) dir = 1; else dir = -1; }
2077  else dir = 1;
2078 
2079  if (arr1 == -1)
2080   {
2081    if (ri1 <= ri2) { rmfr = ri1; rmto = ri2; }
2082    else { rmfr = ri2; rmto = ri1; }
2083   }
2084  else if (arr2 == -1)
2085   {
2086    rmfr = arr1;
2087    if (ri1 <= ri2) rmto = ri2; else rmto = ri1;
2088   }
2089  else { rmfr = arr1; rmto = arr2; }
2090 
2091  for (arri = rmfr;;)
2092   {
2093    /* separate get tok that does not malloc value */
2094    ttyp = mdata_gettok(f, base);
2095    if (ttyp == TEOF)
2096     {
2097      /* only range not filled warning if range passed */
2098      if (!no_rngwarn && arr2 != -1 && arri != rmto)
2099       __sgfwarn(529,
2100        "$readmem%c fewer data elements than range size at **%s(%d)",
2101        __to_baselet(base), __cur_fnam, __lin_cnt);
2102      return;
2103     }
2104    if (ttyp == BADOBJ)
2105     {
2106      __sgferr(720,
2107       "illegal $readmem%c file value at **%s(%d) - loading terminated",
2108       __to_baselet(base), __cur_fnam, __lin_cnt);
2109      break;
2110     }
2111    if (ttyp == RMADDR)
2112     {
2113      /* convert to hex number - in __acwrk value - check number */
2114      /* no error possible in here for hex since digits checked during */
2115      /* token input */
2116      /* notice this puts in [a/b]cwrk but does not allocate */
2117      __to_dhboval(BHEX, TRUE);
2118      if (__bcwrk[0] != 0L)
2119       {
2120        __sgferr(721,
2121        "illegal $readmem%c address value %s at **%s(%d) - loading terminated",
2122         __to_baselet(base), __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen,
2123         BHEX, FALSE), __cur_fnam, __lin_cnt);
2124        return;
2125       }
2126      /* check for within specified range */
2127      arri = (int32) __acwrk[0];
2128      if ((dir == 1 && (arri < rmfr || arri > rmto))
2129       || (dir == -1 && (arri > rmfr || arri < rmto)))
2130       {
2131        __sgferr(722,
2132        "$readmem%c address value %lu out of range at **%s(%d) - loading terminated",
2133         __to_baselet(base), __acwrk[0], __cur_fnam, __lin_cnt);
2134        return;
2135       }
2136      no_rngwarn = TRUE;
2137      continue;
2138     }
2139    if ((dir == 1 && arri > rmto) || (dir == -1 && arri < rmto))
2140     {
2141      __sgfwarn(521, "$readmem%c extra data words at **%s(%d) ignored",
2142       __to_baselet(base), __cur_fnam, __lin_cnt);
2143      return;
2144     }
2145    __to_dhboval(base, TRUE);
2146    h0_arri = normalize_ndx_(arri, ri1, ri2);
2147    /* SJM 09/22/03 - modern P1364 algorithm requires chg stores for each */
2148    /* index if memory elements appear on any assign rhs */
2149    /* correct size if needed */
2150    if (np->nwid != __itoklen)
2151     {
2152      push_xstk_(xsp, __itoklen);
2153      nbytes = WRDBYTES*wlen_(__itoklen);
2154      memcpy(xsp->ap, __acwrk, nbytes);
2155      memcpy(xsp->bp, __bcwrk, nbytes);
2156 
2157      /* SJM 09/29/03 - change to handle sign extension and separate types */
2158      if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
2159      else if (xsp->xslen < np->nwid)
2160       {
2161        if (np->n_signed) __sgn_xtnd_widen(xsp, np->nwid);
2162        else __sizchg_widen(xsp, np->nwid);
2163       }
2164 
2165      if (np->nchg_nd_chgstore)
2166       {
2167        __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
2168         xsp->ap, xsp->bp);
2169 
2170        /* must only trigger change for right array index */
2171        if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
2172       }
2173      else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, xsp->ap, xsp->bp);
2174      __pop_xstk();
2175     }
2176    else
2177     {
2178      if (np->nchg_nd_chgstore)
2179       {
2180        __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
2181         __acwrk, __bcwrk);
2182 
2183        /* must only trigger change for right array index */
2184        if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
2185       }
2186      else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, __acwrk, __bcwrk);
2187     }
2188 
2189    /* finally increment index */
2190    if (dir > 0) { arri++; if (arri > rmto) break; }
2191    else { arri--; if (arri < rmto) break; }
2192   }
2193 }
2194 
2195 /*
2196  * read a readmem file style token
2197  * (modified from yylex in "The Unix Programming Environment" p. 337)
2198  * value in token of __itoklen bits
2199  * array width here limited to 1023 chars
2200  */
mdata_gettok(FILE * f,int32 base)2201 static int32 mdata_gettok(FILE *f, int32 base)
2202 {
2203  register int32 c;
2204 
2205 again:
2206  while ((c = rm_getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
2207  if (c == '\n') { __lin_cnt++; goto again; }
2208  if (c == EOF) return(TEOF);
2209 
2210  if (c == '/')
2211   { if (rmrd_comment(f) == UNDEF) goto again; else return(BADOBJ); }
2212  if (c == '@')
2213   {
2214    c = rm_getc(f);
2215    if (mdata_rdhex(f, c) == BADOBJ) return(BADOBJ);
2216    return(RMADDR);
2217   }
2218  if (base == BBIN)
2219   {
2220    if (mdata_rdbin(f, c) == BADOBJ) return(BADOBJ);
2221    return(NUMBER);
2222   }
2223  if (mdata_rdhex(f, c) == BADOBJ) return(BADOBJ);
2224  return(NUMBER);
2225 }
2226 
2227 /*
2228  * readmem form of get a comment
2229  */
rmrd_comment(FILE * f)2230 static int32 rmrd_comment(FILE *f)
2231 {
2232  register int32 c;
2233  int32 c2;
2234 
2235  /* // to EOL comment */
2236  if ((c2 = rm_getc(f)) == '/')
2237   {
2238    while ((c = rm_getc(f)) != '\n') if (c == EOF) return(TEOF);
2239    __lin_cnt++;
2240    return(UNDEF);
2241   }
2242  /* slash-star comments don't nest */
2243  if (c2 == '*')
2244   {
2245 more_comment:
2246    while ((c = rm_getc(f)) != '*')
2247     {
2248      /* error if / * comments nested */
2249      if (c == '/')
2250       {
2251        if ((c2 = rm_getc(f)) == '*')
2252         { __inform(407, "/* style comment nested in readmem"); continue; }
2253        c = c2;
2254       }
2255      if (c == EOF) return(TEOF);
2256      if (c == '\n') __lin_cnt++;
2257     }
2258 got_star:
2259    if ((c = rm_getc(f)) == '/') return(UNDEF);
2260    if (c == '*') goto got_star;
2261    if (c == '\n') __lin_cnt++;
2262    goto more_comment;
2263   }
2264  /* not a comment so treat as name token */
2265  rm_ungetc(c2, f);
2266  return(BADOBJ);
2267 }
2268 
2269 /*
2270  * routine to read readmem style hex number
2271  */
mdata_rdhex(FILE * f,int32 c)2272 static int32 mdata_rdhex(FILE *f, int32 c)
2273 {
2274  register char *chp;
2275  int32 len, nsize;
2276  int32 has_digit = FALSE;
2277  int32 toolong = FALSE;
2278 
2279  for (chp = __numtoken, len = 0;;)
2280   {
2281    if (c ==  '_') { c = rm_getc(f); continue; }
2282    if (!is_mdataxdigit(c))
2283     {
2284      *chp = '\0';
2285      if (!has_digit) return(BADOBJ);
2286      /* if white space good end */
2287      if (vis_white_(c))
2288       {
2289        /* if new line must push back for correct line counts */
2290        if (c == '\n') rm_ungetc(c, f);
2291        break;
2292       }
2293      /* end of string only good is reading smem */
2294      if (f == NULL && (c == '\0' || c == -1)) break;
2295      return(BADOBJ);
2296 
2297      /* end of string only good is reading smem */
2298      /* LOOKATME - think this can never happen */
2299      if (f == NULL && c == '\0') break;
2300      /* SJM 09/13/99 - EOF char returned for both files and strings */
2301      if (f != NULL && c == EOF) { rm_ungetc(c, f); break; }
2302     }
2303    if (c == '?') c = 'X';
2304    else if (isalpha(c) && isupper(c)) c = tolower(c);
2305 
2306    if (++len >= __numtok_wid)
2307     {
2308      /* since hex each digit takes 4 bits */
2309      if (len >= (MAXNUMBITS + 1)/4)
2310       {
2311        if (!toolong)
2312         {
2313          __pv_fwarn(522, "readmem value or address too wide (%d) - truncated",
2314           MAXNUMBITS);
2315          toolong = TRUE;
2316         }
2317        len--;
2318       }
2319      else
2320       {
2321        /* increase size and continue */
2322        /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
2323        nsize = 2*__numtok_wid;
2324        __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
2325        __numtok_wid = nsize;
2326        /* AIV 04/20/06 - need to reset chp pointer due to realloc */
2327        chp = &(__numtoken[len - 1]);
2328        *chp++ = c;
2329       }
2330     }
2331    else *chp++ = c;
2332 
2333    c = rm_getc(f);
2334    has_digit = TRUE;
2335   }
2336  __itoklen = 4*len;
2337  return(NUMBER);
2338 }
2339 
2340 /*
2341  * return T if readmem style hex digit
2342  */
is_mdataxdigit(int32 c)2343 static int32 is_mdataxdigit(int32 c)
2344 {
2345  switch ((byte) c) {
2346   case 'z': case 'Z': case 'x': case 'X': case '?': break;
2347   default: if (isxdigit(c)) return(TRUE); else return(FALSE);
2348  }
2349  return(TRUE);
2350 }
2351 
2352 /*
2353  * routine to read readmem style binary number
2354  */
mdata_rdbin(FILE * f,int32 c)2355 static int32 mdata_rdbin(FILE *f, int32 c)
2356 {
2357  register char *chp;
2358  register int32 len;
2359  int32 nsize;
2360  int32 has_bit = FALSE;
2361  int32 toolong = FALSE;
2362 
2363  for (len = 0, chp = __numtoken;;)
2364   {
2365    if (c ==  '_') { c = rm_getc(f); continue; }
2366    if (!is_mdatabit(c))
2367     {
2368      *chp = '\0';
2369      if (!has_bit) return(BADOBJ);
2370      /* if white space good end */
2371      if (vis_white_(c))
2372       {
2373        /* if new line must push back for correct line counts */
2374        /* impossible in string case */
2375        if (c == '\n') rm_ungetc(c, f);
2376        break;
2377       }
2378      /* SJM 09/13/99 - EOF char return for both files and strings */
2379      if (c == EOF) { rm_ungetc(c, f); break; }
2380      return(BADOBJ);
2381     }
2382    if (c == '?') c = 'X';
2383    else if (isalpha(c) && isupper(c)) c = tolower(c);
2384 
2385    if (++len >= __numtok_wid)
2386     {
2387      if (len >= MAXNUMBITS)
2388       {
2389        if (!toolong)
2390         {
2391          __pv_fwarn(523, "readmemb value too wide (%d) - truncated",
2392           MAXNUMBITS);
2393          toolong = TRUE;
2394         }
2395        len--;
2396       }
2397      else
2398       {
2399        /* increase size and continue */
2400        /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
2401        nsize = 2*__numtok_wid;
2402        __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
2403        __numtok_wid = nsize;
2404        /* AIV 04/20/06 - need to reset chp pointer due to realloc */
2405        chp = &(__numtoken[len - 1]);
2406        *chp++ = c;
2407       }
2408     }
2409    else *chp++ = c;
2410 
2411    c = rm_getc(f);
2412    has_bit = TRUE;
2413   }
2414  __itoklen = len;
2415  return(NUMBER);
2416 }
2417 
2418 /*
2419  * special get that allow reading from sreadmem c style string argument
2420  */
rm_getc(FILE * f)2421 static int32 rm_getc(FILE *f)
2422 {
2423  register int32 c;
2424  int32 blen;
2425 
2426  if (f == NULL)
2427   {
2428    c = *__srm_strp;
2429    /* end of string means white space */
2430    if (c == '\0')
2431     {
2432      struct xstk_t *xsp;
2433 
2434      if (__srm_strp_len != 0)
2435       __my_free(__srm_strp_beg, __srm_strp_len);
2436      __srm_strp_len = 0;
2437 
2438      /* need 2 cases for eof since, normally would push eof back first */
2439      /* but when reading strings cannot do that */
2440      if (__srm_xp == NULL) return(EOF);
2441      if ((__srm_xp = __srm_xp->ru.x) == NULL) return(EOF);
2442 
2443      /* eval to allow params and expressions */
2444      xsp = __eval_xpr(__srm_xp->lu.x);
2445      if (!vval_is0_(xsp->bp, xsp->xslen))
2446       {
2447        __pv_fwarn(579,
2448         "sreadmem required string is x/z number (pos. %d) - x/z's ignored",
2449         __srm_stargi);
2450       }
2451      /* must trim away high 0's since will cause leading \0 at start */
2452      blen = __trim1_0val(xsp->ap, xsp->xslen);
2453      blen = ((blen + 7)/8)*8;
2454 
2455      /* SJM 09/29/03 - change to handle sign extension and separate types */
2456      if (xsp->xslen > blen) __narrow_sizchg(xsp, blen);
2457      else if (xsp->xslen < blen)
2458       {
2459        if (__srm_xp->has_sign) __sgn_xtnd_widen(xsp, blen);
2460        else __sizchg_widen(xsp, blen);
2461       }
2462 
2463      /* notice this is actual Pascal style string len, no ending \0 */
2464      __srm_strp_beg = __vval_to_vstr(xsp->ap, xsp->xslen, &__srm_strp_len);
2465      __srm_strp = __srm_strp_beg;
2466      __pop_xstk();
2467      if (__debug_flg) __dbg_msg("new sreadmem string: %s\n", __srm_strp);
2468      __srm_stargi++;
2469      return(' ');
2470     }
2471    __srm_strp++;
2472    return(c);
2473   }
2474  return(getc(f));
2475 }
2476 
2477 /*
2478  * special get that allow reading from sreadmem c style string argument
2479  * caller's responsible to not back over front
2480  */
rm_ungetc(int32 c,FILE * f)2481 static void rm_ungetc(int32 c, FILE *f)
2482 {
2483  if (f != NULL) ungetc(c, f); else __srm_strp--;
2484 }
2485 
2486 /*
2487  * return T if readmem style bin digit
2488  */
is_mdatabit(int32 c)2489 static int32 is_mdatabit(int32 c)
2490 {
2491  switch ((byte) c) {
2492   case 'z': case 'Z': case 'x': case 'X': case '?': case '0': case '1':
2493    break;
2494   default:
2495   return(FALSE);
2496  }
2497  return(TRUE);
2498 }
2499 
2500 /*
2501  * execute the sreadmem[bh] system task
2502  * know 1st argument array, 2nd and 3nd range, rest strings
2503  */
__exec_sreadmem(struct expr_t * argxp,int32 base)2504 extern void __exec_sreadmem(struct expr_t *argxp, int32 base)
2505 {
2506  int32 ri1, ri2, arrwid, arr1, arr2, tmpi, nd_itpop;
2507  struct expr_t *axp;
2508  struct net_t *np;
2509  char s1[RECLEN];
2510 
2511  /* 1st arg. is array destination to read into */
2512  axp = argxp->lu.x;
2513  /* know will be array name ID or array name global reference */
2514  if (axp->optyp == GLBREF)
2515   {
2516    __xmrpush_refgrp_to_targ(axp->ru.grp);
2517    nd_itpop = TRUE;
2518   }
2519  else nd_itpop = FALSE;
2520 
2521  np = axp->lu.sy->el.enp;
2522  if (axp->is_real)
2523   {
2524    __sgferr(717, "$sreadmem%c of %s illegal - no readmem of array of reals",
2525     __to_baselet(base), __msgexpr_tostr(__xs, axp));
2526    goto done;
2527   }
2528  /* know this is array so range is array range */
2529  __getarr_range(np, &ri1, &ri2, &arrwid);
2530 
2531  arr1 = arr2 = -1;
2532  argxp = argxp->ru.x;
2533  /* set up addresses - start and end range must be present or fixup error */
2534  axp = argxp->lu.x;
2535  /* for system task arguments optyp empty not used - know arg present */
2536  if (axp->optyp != OPEMPTY)
2537   {
2538    if ((tmpi = __comp_ndx(np, axp)) == -1)
2539     {
2540      __sgferr(723,
2541       "$sreadmem%c start address expression %s unknown or out of range",
2542       __to_baselet(base), __msgexpr_tostr(__xs, axp));
2543      goto done;
2544     }
2545    sprintf(s1, "$sreadmem%c start", __to_baselet(base));
2546    if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto done;
2547    arr1 = tmpi;
2548   }
2549  argxp = argxp->ru.x;
2550  axp = argxp->lu.x;
2551  if (axp->optyp != OPEMPTY)
2552   {
2553    if ((tmpi = __comp_ndx(np, axp)) == -1)
2554     {
2555      __sgferr(724,
2556      "$sreadmem%c end address expression %s unknown or out of range",
2557       __to_baselet(base), __msgexpr_tostr(__xs, axp));
2558      goto done;
2559     }
2560    sprintf(s1, "$sreadmem%c end", __to_baselet(base));
2561    if (!chk_rm_rng_legal(tmpi, ri1, ri2, s1)) goto done;
2562    arr2 = tmpi;
2563    if (arr1 == -1)
2564     {
2565      __sgferr(724,
2566       "$sreadmem%c end address value %d illegal - no start address",
2567       __to_baselet(base), arr2);
2568      goto done;
2569     }
2570   }
2571  do_srm_xtrct(argxp->ru.x, base, np, arr1, arr2, ri1, ri2, arrwid);
2572  if (__srm_strp_len != 0) __my_free(__srm_strp_beg, __srm_strp_len);
2573  __srm_strp_beg = NULL;
2574  __srm_strp_len = 0;
2575 done:
2576  if (nd_itpop) __pop_itstk();
2577  /* DBG remove ---
2578  if (__debug_flg) __dmp_arr_all(np, __inum, __inum);
2579  --- */
2580 }
2581 
2582 /*
2583  * do the sreadmem string extraction and array filling
2584  *
2585  * this keeps arr1, arr2, and arri in original ranges and corrects each
2586  * time for non h:0 form - could use correct range and uncorrect for msgs
2587  *
2588  * string can be any expr. that evaluates to string
2589  */
do_srm_xtrct(struct expr_t * xp,int32 base,struct net_t * np,int32 arr1,int32 arr2,int32 ri1,int32 ri2,int32 arrwid)2590 static void do_srm_xtrct(struct expr_t *xp, int32 base, struct net_t *np,
2591  int32 arr1, int32 arr2, int32 ri1, int32 ri2, int32 arrwid)
2592 {
2593  register int32 arri;
2594  FILE *f;
2595  int32 dir, ttyp, h0_arri, nbytes, no_rngwarn, blen;
2596  int32 rmfr, rmto;
2597  struct xstk_t *xsp;
2598 
2599  no_rngwarn = FALSE;
2600 
2601  /* SJM - 06/19/00 - if only one starting range, direction toward high */
2602  /* only way for downward range is arr2 not -1 and arr2 > arr1 */
2603  if (arr2 != -1) { if (arr1 <= arr2) dir = 1; else dir = -1; }
2604  else dir = 1;
2605 
2606  if (arr1 == -1)
2607   {
2608    if (ri1 <= ri2) { rmfr = ri1; rmto = ri2; }
2609    else { rmfr = ri2; rmto = ri1; }
2610   }
2611  else if (arr2 == -1)
2612   {
2613    rmfr = arr1;
2614    if (ri1 <= ri2) rmto = ri2; else rmto = ri1;
2615   }
2616  else { rmfr = arr1; rmto = arr2; }
2617 
2618  __srm_stargi = 1;
2619  __srm_xp = xp;
2620  __srm_strp_len = 0;
2621  __srm_strp_beg = NULL;
2622 
2623  /* notice must leave non printing as is and add \0 - know there is room */
2624  xsp = __eval_xpr(__srm_xp->lu.x);
2625  /* check for x/z (not really string) */
2626  if (!vval_is0_(xsp->bp, xsp->xslen))
2627   {
2628    __pv_fwarn(579,
2629     "sreadmem required string value is x/z number (pos. 1) - x/z's ignored");
2630   }
2631  /* must trim away high 0's since will cause leading \0 at start */
2632  blen = __trim1_0val(xsp->ap, xsp->xslen);
2633  blen = ((blen + 7)/8)*8;
2634 
2635  /* SJM 09/29/03 - change to handle sign extension and separate types */
2636  if (xsp->xslen > blen) __narrow_sizchg(xsp, blen);
2637  else if (xsp->xslen < blen)
2638   {
2639    if (__srm_xp->has_sign) __sgn_xtnd_widen(xsp, blen);
2640    else __sizchg_widen(xsp, blen);
2641   }
2642 
2643  __srm_strp_beg = __vval_to_vstr(xsp->ap, xsp->xslen, &__srm_strp_len);
2644  __srm_strp = __srm_strp_beg;
2645  __pop_xstk();
2646  if (__debug_flg) __dbg_msg("first sreadmem string: %s\n", __srm_strp);
2647  f = NULL;
2648 
2649  for (arri = rmfr;;)
2650   {
2651    /* also for sreadmem, rm_getc will have freed string ptr needed */
2652    if (__srm_xp == NULL) ttyp = TEOF;
2653    else ttyp = mdata_gettok(f, base);
2654    if (ttyp == TEOF)
2655     {
2656      if (!no_rngwarn && arr2 != -1 && arri != rmto)
2657       __sgfwarn(524,
2658        "$sreadmem%c number of data words fewer than range size (pos. %d)",
2659         __to_baselet(base), __srm_stargi);
2660      return;
2661     }
2662    if (ttyp == BADOBJ)
2663     {
2664      __sgferr(725,
2665       "illegal $sreadmem%c string value (pos. %d) - loading terminated",
2666       __to_baselet(base), __srm_stargi);
2667      break;
2668     }
2669    if (ttyp == RMADDR)
2670     {
2671      /* convert to hex number - in __acwrk value - check number */
2672      /* no error possible in here for hex since digits checked during */
2673      /* token input */
2674      __to_dhboval(BHEX, TRUE);
2675      if (__bcwrk[0] != 0L)
2676       {
2677        __sgferr(726,
2678        "illegal $readmem%c address value %s (pos. %d) - loading terminated",
2679         __to_baselet(base), __regab_tostr(__xs, __acwrk, __bcwrk, __itoklen,
2680         BHEX, FALSE), __srm_stargi);
2681        return;
2682       }
2683      /* check for within specified range */
2684      arri = (int32) __acwrk[0];
2685      if ((dir == 1 && (arri < rmfr || arri > rmto))
2686       || (dir == -1 && (arri > rmfr || arri < rmto)))
2687       {
2688        __sgferr(727,
2689        "$sreadmem%c address value %lu out of range (pos. %d) - loading terminated",
2690         __to_baselet(base), __acwrk[0], __srm_stargi);
2691        return;
2692       }
2693      no_rngwarn = TRUE;
2694      continue;
2695     }
2696    if ((dir == 1 && arri > rmto) || (dir == -1 && arri < rmto))
2697     {
2698      __sgfwarn(525, "$sreadmem%c extra data words ignored (pos. %d)",
2699       __to_baselet(base), __srm_stargi);
2700      return;
2701     }
2702    __to_dhboval(base, TRUE);
2703 
2704    h0_arri = normalize_ndx_(arri, ri1, ri2);
2705 
2706    /* SJM 09/22/03 - modern P1364 algorithm requires chg stores for each */
2707    /* index if memory elements appear on any assign rhs */
2708    /* correct size if needed */
2709    if (np->nwid != __itoklen)
2710     {
2711      push_xstk_(xsp, __itoklen);
2712      nbytes = WRDBYTES*wlen_(__itoklen);
2713      memcpy(xsp->ap, __acwrk, nbytes);
2714      memcpy(xsp->bp, __bcwrk, nbytes);
2715 
2716      /* SJM 09/29/03 - change to handle sign extension and separate types */
2717      /* SJM 05/19/04 - notice read into memory can be signed - need net wid */
2718      if (xsp->xslen > np->nwid) __narrow_sizchg(xsp, np->nwid);
2719      else if (xsp->xslen < np->nwid)
2720       {
2721        if (np->n_signed) __sgn_xtnd_widen(xsp, np->nwid);
2722        else __sizchg_widen(xsp, np->nwid);
2723       }
2724 
2725      if (np->nchg_nd_chgstore)
2726       {
2727        __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
2728         xsp->ap, xsp->bp);
2729 
2730        /* must only trigger change for right array index */
2731        if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
2732       }
2733      else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, xsp->ap, xsp->bp);
2734      __pop_xstk();
2735     }
2736    else
2737     {
2738      if (np->nchg_nd_chgstore)
2739       {
2740        __chg_st_arr_val(np->nva, arrwid, np->nwid, h0_arri,
2741         __acwrk, __bcwrk);
2742 
2743        /* must only trigger change for right array index */
2744        if (__lhs_changed) record_sel_nchg_(np, h0_arri, h0_arri);
2745       }
2746      else __st_arr_val(np->nva, arrwid, np->nwid, h0_arri, __acwrk, __bcwrk);
2747     }
2748 
2749    /* finally increment index */
2750    if (dir > 0) arri++; else arri--;
2751   }
2752 }
2753 
2754 /*
2755  * RANDOM NUMBER GENERATION ROUTINES
2756  */
2757 
2758 #define MY_LONG_MAX2 0xffffffff
2759 /* SJM 11/19/03 - must use 32 bit range even for 64 bit systems */
2760 /* because Verilog WBITS (for now?) must be set to 32 */
2761 #define MY_LONG_MAX 2147483647L
2762 #define MY_LONG_MIN (-MY_LONG_MAX - 1L)
2763 
2764 /*
2765  * execute the random system function
2766  * this leaves new value on tos and uses a copy of the good Berkeley
2767  * unix style random number generator
2768  *
2769  * notice pli code no longer shares random number generator
2770  * this is 32 bit long int dependent
2771  *
2772  * SJM 11/18/03 - rewritten to make seed arg inout instead of input if used
2773  * SJM 01/27/04 - seed must be C global and initialized to 0 (guess) in
2774  *                case user never passes the seed argument
2775  */
__exec_sfrand(struct expr_t * ndp)2776 extern void __exec_sfrand(struct expr_t *ndp)
2777 {
2778  int32 ranv;
2779  int32 localseed;
2780  struct xstk_t *xsp;
2781  struct expr_t *fax;
2782 
2783  /* case 1 random with seed set - arg is inout */
2784  /* AIV 03/06/07 - case should not modify global seed - thanks SAS@ Tharas */
2785  if (ndp->ru.x != NULL && ndp->ru.x->optyp != OPEMPTY)
2786   {
2787    fax = ndp->ru.x->lu.x;
2788    /* even though evaling, previous error if seed is not simple WBIT reg */
2789    xsp = __eval_xpr(fax);
2790    /* know here the argument must be a reg. that is updated */
2791    /* by setting reg., user can change seed */
2792    if (xsp->bp[0] != 0)
2793     {
2794      __sgfwarn(588,
2795       "$random seed register value %s has x/z bits - a part used",
2796       __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
2797      xsp->bp[0] = 0L;
2798     }
2799    localseed = (int32) xsp->ap[0];
2800    __pop_xstk();
2801 
2802    /* this sets the seed (acutally a state) - 1 to reset to defl. sequence */
2803    /* generator returns only 31 (signed +) bits so high bit always 0 */
2804    ranv = rtl_dist_uniform(&localseed, MY_LONG_MIN, MY_LONG_MAX);
2805 
2806    push_xstk_(xsp, WBITS);
2807    xsp->bp[0] = 0L;
2808    xsp->ap[0] = ranv;
2809 
2810    /* SJM 11/19/03 - I misread LRM - if seed arg passed it is inout not in */
2811    /* temp use of top of stack - removed before return that needs tos */
2812    push_xstk_(xsp, WBITS);
2813    xsp->ap[0] = (word32) localseed;
2814    xsp->bp[0] = 0L;
2815 
2816    __exec2_proc_assign(fax, xsp->ap, xsp->bp);
2817    __pop_xstk();
2818    return;
2819   }
2820 
2821  /* case 2: no seed passed */
2822  /* SJM 01/27/04 - now if no seed passed uses last one */
2823  push_xstk_(xsp, WBITS);
2824  xsp->bp[0] = 0L;
2825  /* generator returns only 31 (signed +) bits so high bit always 0 */
2826  ranv = rtl_dist_uniform(&__seed, LONG_MIN, LONG_MAX);
2827  xsp->ap[0] = (word32) ranv;
2828 }
2829 
2830 /*
2831  * SJM 11/19/03 - replacing $random with LRM 2001 random as suggested
2832  * by standard - although BSD algorithm better (longer period), it
2833  * requires 8 words of state which can't be returned in seed
2834  */
2835 
2836 /*
2837  * uniform distribution low level routine from 2001 LRM
2838  *
2839  * this is wrapper handling edge cases and returns 32 bit signed not double
2840  * notice since uses double and maps back to word32 has good period
2841  */
rtl_dist_uniform(int32 * seed,sword32 start,sword32 end)2842 static sword32 rtl_dist_uniform(int32 *seed, sword32 start, sword32 end)
2843 {
2844  double r;
2845  sword32 i;
2846 
2847  if (start >= end) return(start);
2848  if (end != LONG_MAX)
2849   {
2850    end++;
2851    r = uniform(seed, start, end);
2852    if (r >= 0)
2853     {
2854      i = (sword32) r;
2855     }
2856    else
2857     {
2858      i = (sword32) (r - 1);
2859     }
2860    if (i < start) i = start;
2861    if (i >= end) i = end-1;
2862   }
2863  else if (start != LONG_MIN)
2864   {
2865    start--;
2866    r = uniform(seed, start, end) + 1.0;
2867    if (r >= 0)
2868     {
2869      i = (sword32) r;
2870     }
2871    else
2872     {
2873      i = (sword32) (r - 1);
2874     }
2875    if (i <= start) i = start+1;
2876    if (i > end) i = end;
2877   }
2878  else
2879   {
2880    r = (uniform(seed,start,end) + 2147483648.0)/4294967295.0;
2881    r = r*4294967296.0 - 2147483648.0;
2882    if (r >= 0)
2883     {
2884      i = (sword32) r;
2885     }
2886    else
2887     {
2888      i = (sword32) (r-1);
2889     }
2890   }
2891  return(i);
2892 }
2893 
2894 /*
2895  * uniform distribution low level routine from 2001 LRM
2896  * this returns double random number
2897  *
2898  * BEWARE - IEEE floating point format dependent
2899  */
uniform(int32 * seed,sword32 start,sword32 end)2900 static double uniform(int32 *seed, sword32 start, sword32 end)
2901 {
2902  union u_s
2903   {
2904    float s;
2905    word32 stemp;
2906   } u;
2907  double d = 0.00000011920928955078125;
2908  double a,b,c;
2909 
2910  if ((*seed) == 0) *seed = 259341593;
2911  if (start >= end)
2912   {
2913    a = 0.0;
2914    b = 2147483647.0;
2915   }
2916  else
2917   {
2918    a = (double) start;
2919    b = (double) end;
2920   }
2921  *seed = 69069 * (*seed) + 1;
2922  u.stemp = *seed;
2923 
2924  /* This relies on IEEE floating point format */
2925  u.stemp = (u.stemp >> 9) | 0x3f800000;
2926  c = (double) u.s;
2927  c = c + (c*d);
2928  c = ((b - a) * (c - 1.0)) + a;
2929  return(c);
2930 }
2931 
2932 /*
2933  * IMPLEMENT SPECIAL DISTRIBUTION ROUTINES
2934  */
2935 
2936 /*
2937  * return a randomly distributed integer between start and end
2938  *
2939  * notice requiring all 3 arguments - ,, illegal
2940  *
2941  * idea for left hand side seed is that normal random is returned
2942  * so can be used to repeat next normal dist.
2943  *
2944  * algorithm maps uniformly distributed random real in 0 to 1 range to int
2945  * in start to end range (integers where start or end can be negative)
2946  */
__exec_dist_uniform(struct expr_t * ndp)2947 extern void __exec_dist_uniform(struct expr_t *ndp)
2948 {
2949  int32 start, end, u2;
2950  word32 val;
2951  double rng, x;
2952  struct expr_t *fax, *a1xp, *a2xp, *a3xp;
2953  struct xstk_t *xsp, *xsp2;
2954 
2955  /* for func passed func node not first arg */
2956  fax = ndp->ru.x;
2957  /* access the required 3 arguments */
2958  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
2959  a1xp = fax->lu.x;
2960  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
2961  a2xp = fax->lu.x;
2962  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
2963  a3xp = fax->lu.x;
2964  if (fax->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
2965 
2966  /* all 3 arguments required */
2967  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY
2968   || a3xp->optyp == OPEMPTY)
2969   {
2970    __sgfwarn(588,
2971    "$dist_uniform arguments must not be missing (,, form) - returning 32'bx");
2972    goto ret_x;
2973   }
2974 
2975  /* even though evaling, previous error if seed is not simple WBIT reg */
2976  xsp = __eval_xpr(a1xp);
2977  if (xsp->bp[0] != 0)
2978   {
2979    __sgfwarn(588,
2980     "$dist_uniform seed value %s has x/z bits - returning 32'bx",
2981     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
2982    xsp->bp[0] = 0L;
2983    __pop_xstk();
2984 ret_x:
2985    push_xstk_(xsp, WBITS);
2986    xsp->ap[0] = ALL1W;
2987    xsp->bp[0] = ALL1W;
2988    return;
2989   }
2990  __seed = (int32) xsp->ap[0];
2991  __pop_xstk();
2992 
2993  if (!__get_eval_word(a2xp, &val))
2994   {
2995    __sgfwarn(588,
2996     "$dist_uniform argument 2, start value %s x/z - returning 32'bx",
2997     __msgexpr_tostr(__xs, a2xp));
2998    goto ret_x;
2999   }
3000  start = (int32) val;
3001  if (!__get_eval_word(a3xp, &val))
3002   {
3003    __sgfwarn(588,
3004     "$dist_uniform argument 3, end value %s x/z - returning 32'bx",
3005     __msgexpr_tostr(__xs, a2xp));
3006    goto ret_x;
3007   }
3008  end = (int32) val;
3009  x = uniform(&__seed, 0, 1);
3010 
3011  /* LOOKATME - maybe: rng = (double) (end - start); */
3012  rng = (double) (end - start + 1);
3013  /* FIXME - does this round right? */
3014  u2 = start + ((int32) (rng*x));
3015 
3016  push_xstk_(xsp, WBITS);
3017  xsp->bp[0] = 0L;
3018  /* notice generator returns only 31 (signed +) bits so high bit always 0 */
3019  xsp->ap[0] = (word32) u2;
3020 
3021  push_xstk_(xsp2, WBITS);
3022  xsp2->ap[0] = (word32) __seed;
3023  xsp2->bp[0] = 0L;
3024  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3025  __pop_xstk();
3026 }
3027 
3028 /*
3029  * return randomly distributed int std. normal dist - std. dev. 'standard_dev'
3030  * and mean 'mean'
3031  *
3032  * notice requiring all 3 arguments - ,, illegal
3033  *
3034  * algorithm uses ratio method to map uniform random real in 0 to 1 range
3035  * into standard normal with mean 0.0 and standard deviation 1.0
3036  * then convert to integer with translated standard_Dev and mean mean
3037  *
3038  * i.e. if mean is same 0 and standard_dev is same 1.0 only will return ints
3039  * -4 to 4 nearly all the time (>4 standard devs rare)
3040  */
__exec_dist_stdnorm(struct expr_t * ndp)3041 extern void __exec_dist_stdnorm(struct expr_t *ndp)
3042 {
3043  int32 mean, std_dev, u2;
3044  word32 val;
3045  double x, u;
3046  struct expr_t *fax, *a1xp, *a2xp, *a3xp;
3047  struct xstk_t *xsp, *xsp2;
3048 
3049  /* for func passed func node not first arg */
3050  fax = ndp->ru.x;
3051  /* access the required 3 arguments */
3052  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
3053  a1xp = fax->lu.x;
3054  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3055  a2xp = fax->lu.x;
3056  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3057  a3xp = fax->lu.x;
3058  if (fax->ru.x != NULL) __arg_terr(__FILE__, __LINE__);
3059 
3060  /* all 3 arguments required */
3061  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY
3062   || a3xp->optyp == OPEMPTY)
3063   {
3064    __sgfwarn(588,
3065    "$dist_normal arguments must not be missing (,, form) - returning 32'bx");
3066    goto ret_x;
3067   }
3068 
3069  /* even though evaling, previous error if seed is not simple WBIT reg */
3070  xsp = __eval_xpr(a1xp);
3071  if (xsp->bp[0] != 0)
3072   {
3073    __sgfwarn(588,
3074     "$dist_normal seed value %s has x/z bits - returning 32'bx",
3075     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
3076    xsp->bp[0] = 0L;
3077    __pop_xstk();
3078 ret_x:
3079    push_xstk_(xsp, WBITS);
3080    xsp->ap[0] = ALL1W;
3081    xsp->bp[0] = ALL1W;
3082    return;
3083   }
3084  __seed = (int32) xsp->ap[0];
3085  __pop_xstk();
3086 
3087  if (!__get_eval_word(a2xp, &val))
3088   {
3089    __sgfwarn(588,
3090     "$dist_normal argument 2, mean value %s x/z - returning 32'bx",
3091     __msgexpr_tostr(__xs, a2xp));
3092    goto ret_x;
3093   }
3094  mean = (int32) val;
3095  if (!__get_eval_word(a3xp, &val))
3096   {
3097    __sgfwarn(588,
3098     "$dist_normal argument 3, standard_dev value %s x/z - returning 32'bx",
3099     __msgexpr_tostr(__xs, a2xp));
3100    goto ret_x;
3101   }
3102  std_dev = (int32) val;
3103 
3104  /* get the standard normal deviate (stddev=1.0, mean = 0.0) */
3105  x = stdnorm_dev(&__seed);
3106 
3107  /* map to real with passed std_dev and mean */
3108  u = (double) mean + x*((double) std_dev);
3109  /* then to int32 using Verilog round rules */
3110  u2 = ver_rint_(u);
3111 
3112  push_xstk_(xsp, WBITS);
3113  xsp->bp[0] = 0L;
3114  /* notice generator returns only 31 (signed +) bits so high bit always 0 */
3115  xsp->ap[0] = (word32) u2;
3116 
3117  push_xstk_(xsp2, WBITS);
3118  xsp2->ap[0] = (word32) __seed;
3119  xsp2->bp[0] = 0L;
3120  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3121  __pop_xstk();
3122 }
3123 
3124 /*
3125  * generate standard norm with median 0 and standard deviation 1
3126  *
3127  * from Knuth - Seminumerical algorithms - uses ratio method
3128  */
stdnorm_dev(int32 * seed)3129 static double stdnorm_dev(int32 *seed)
3130 {
3131  double u, v, x;
3132 
3133  /* generate two uniform deviates in 0.0 to 1.0 (u non 0) */
3134  for (;;)
3135   {
3136    do { u = uniform(seed, 0, 1); } while (u == 0.0);
3137    v = uniform(seed, 0, 1);
3138 
3139    x = (sqrt(8.0/M_E)*(v - 0.5))/u;
3140    if (x*x <= -4.0/log(u)) return(x);
3141   }
3142 }
3143 
3144 /*
3145  * return randomly distributed exponential with mean 'mean'
3146  * returns values with average mean
3147  *
3148  * notice requiring both arguments - ,, illegal
3149  *
3150  * algorithm uses a=1 case of gamma deviate with mean 1.0
3151  *
3152  * i.e. if mean is same 1 - values from 0 to inf with mean 1
3153  */
__exec_dist_exp(struct expr_t * ndp)3154 extern void __exec_dist_exp(struct expr_t *ndp)
3155 {
3156  int32 mean, u2;
3157  word32 val;
3158  double x, u;
3159  struct expr_t *fax, *a1xp, *a2xp;
3160  struct xstk_t *xsp, *xsp2;
3161 
3162  /* for func passed func node not first arg */
3163  fax = ndp->ru.x;
3164  /* access the required 2 arguments */
3165  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
3166  a1xp = fax->lu.x;
3167  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3168  a2xp = fax->lu.x;
3169 
3170  /* both arguments required */
3171  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
3172   {
3173    __sgfwarn(588,
3174    "$dist_exponential arguments must not be missing (,, form) - returning 32'bx");
3175    goto ret_x;
3176   }
3177 
3178  /* even though evaling, previous error if seed is not simple WBIT reg */
3179  xsp = __eval_xpr(a1xp);
3180  if (xsp->bp[0] != 0)
3181   {
3182    __sgfwarn(588,
3183     "$dist_exponential seed value %s has x/z bits - returning 32'bx",
3184     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
3185    xsp->bp[0] = 0L;
3186    __pop_xstk();
3187 ret_x:
3188    push_xstk_(xsp, WBITS);
3189    xsp->ap[0] = ALL1W;
3190    xsp->bp[0] = ALL1W;
3191    return;
3192   }
3193  __seed = (int32) xsp->ap[0];
3194  __pop_xstk();
3195 
3196  if (!__get_eval_word(a2xp, &val))
3197   {
3198    __sgfwarn(588,
3199     "$dist_exponential argument 2, mean value %s x/z - returning 32'bx",
3200     __msgexpr_tostr(__xs, a2xp));
3201    goto ret_x;
3202   }
3203  mean = (int32) val;
3204 
3205  /* get the gamma deviate (mean = 1.0, ) */
3206  x = gamma_dev((double) 1, &__seed);
3207 
3208  /* map to real mean mean (expand by multiplying here */
3209  u = x*((double) mean);
3210  /* then to int32 (but will always be positive) using Verilog round rules */
3211  u2 = ver_rint_(u);
3212 
3213  push_xstk_(xsp, WBITS);
3214  xsp->bp[0] = 0L;
3215  /* notice generator returns only 31 (signed +) bits so high bit always 0 */
3216  xsp->ap[0] = (word32) u2;
3217 
3218  push_xstk_(xsp2, WBITS);
3219  xsp2->ap[0] = (word32) __seed;
3220  xsp2->bp[0] = 0L;
3221  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3222  __pop_xstk();
3223 }
3224 
3225 /*
3226  * gamma deviate from normal deviate of order xia
3227  * returns real with mean around 1.0
3228  *
3229  * using seed random seed and setting seed to last generated
3230  * again from Numerical Recipes
3231  * caller must have checked arguments
3232  */
gamma_dev(double xa,int32 * seed)3233 static double gamma_dev(double xa, int32 *seed)
3234 {
3235  double am, e, s, v1, v2, x, y;
3236 
3237  if (xa < 1.0) __arg_terr(__FILE__, __LINE__);
3238  /* direct method for order 1 - exponential */
3239  if (xa == 1.0) { x = uniform(seed, 0, 1); x = -log(x); return(x); }
3240 
3241  /* rejection method for any higher order - works for non integal */
3242  do {
3243   do {
3244    do {
3245     v1 = uniform(seed, 0, 1);
3246     v2 = 2.0*uniform(seed, 0, 1) - 1.0;
3247    } while (v1*v1 + v2*v2 > 1.0);
3248    y = v2/v1;
3249    am = xa - 1.0;
3250    s = sqrt(2.0*am + 1.0);
3251    x = s*y + am;
3252   } while (x <= 0.0);
3253   e = (1.0 + y*y)*exp(am*log(x/am) - s*y);
3254  } while (uniform(seed, 0, 1) > e);
3255  return(x);
3256 }
3257 
3258 /*
3259  * return randomly distributed poisson distribution integer value
3260  *with mean 'mean'
3261  *
3262  * notice requiring both arguments - ,, illegal
3263  * almost same as gamm dist. but integral so computation different
3264  *
3265  * algorithm uses rejection method poisson routine from Numerical
3266  * Recipes this is integral distribution related to binomial
3267  */
__exec_dist_poisson(struct expr_t * ndp)3268 extern void __exec_dist_poisson(struct expr_t *ndp)
3269 {
3270  int32 mean, u2;
3271  word32 val;
3272  struct expr_t *fax, *a1xp, *a2xp;
3273  struct xstk_t *xsp, *xsp2;
3274 
3275  /* for func passed func node not first arg */
3276  fax = ndp->ru.x;
3277  /* access the required 2 arguments */
3278  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
3279  a1xp = fax->lu.x;
3280  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3281  a2xp = fax->lu.x;
3282 
3283  /* both arguments required */
3284  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
3285   {
3286    __sgfwarn(588,
3287    "$dist_poisson arguments must not be missing (,, form) - returning 32'bx");
3288    goto ret_x;
3289   }
3290 
3291  /* even though evaling, previous error if seed is not simple WBIT reg */
3292  xsp = __eval_xpr(a1xp);
3293  if (xsp->bp[0] != 0)
3294   {
3295    __sgfwarn(588,
3296     "$dist_poisson seed value %s has x/z bits - returning 32'bx",
3297     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
3298    xsp->bp[0] = 0L;
3299    __pop_xstk();
3300 ret_x:
3301    push_xstk_(xsp, WBITS);
3302    xsp->ap[0] = ALL1W;
3303    xsp->bp[0] = ALL1W;
3304    return;
3305   }
3306  __seed = (int32) xsp->ap[0];
3307  __pop_xstk();
3308 
3309  if (!__get_eval_word(a2xp, &val))
3310   {
3311    __sgfwarn(588,
3312     "$dist_poisson argument 2, mean value %s x/z - returning 32'bx",
3313     __msgexpr_tostr(__xs, a2xp));
3314    goto ret_x;
3315   }
3316  mean = (int32) val;
3317 
3318  /* get the gamma deviate (mean = 1.0, ) */
3319  u2 = poisson_dev(mean, &__seed);
3320 
3321  push_xstk_(xsp, WBITS);
3322  xsp->bp[0] = 0L;
3323  xsp->ap[0] = (word32) u2;
3324 
3325  push_xstk_(xsp2, WBITS);
3326  xsp2->ap[0] = (word32) __seed;
3327  xsp2->bp[0] = 0L;
3328  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3329  __pop_xstk();
3330 }
3331 
3332 /*
3333  * poission deviate using rejection method (exp for small)
3334  *
3335  * using seed random seed and setting seed to last generated
3336  * random number
3337  *
3338  * again from Numerical Recipes
3339  */
poisson_dev(int32 ixm,int32 * seed)3340 static int32 poisson_dev(int32 ixm, int32 *seed)
3341 {
3342  int32 iem;
3343  double em, g, t, xm, sq, alxm, y;
3344 
3345  /* direct method for small order */
3346  if (ixm < 12)
3347   {
3348    g = exp((double) ixm);
3349    t = 1.0;
3350    iem = -1;
3351    do {
3352     ++iem;
3353     /* "multiplying uniform deviates same as adding exp"? */
3354     t *= uniform(seed, 0, 1);
3355    } while (t > g);
3356    return(iem);
3357   }
3358 
3359  /* otherwise use bounded region rejection method */
3360  xm = (double) ixm;
3361  sq = sqrt(2.0*ixm);
3362  alxm = log (xm);
3363  g = xm*alxm - log_gamma(xm + 1.0);
3364  do {
3365   do {
3366    y = tan(M_PI*uniform(seed, 0, 1));
3367    em = sq*y + xm;
3368    /* reject if in region of 0 probability */
3369   } while (em < 0.0);
3370   /* maybe follow Verilog convention should be rounded? */
3371   iem = (int32) floor(em);
3372   t = 0.9 + (1.0*y*y)*exp(em*alxm - log_gamma(em + 1.0) - g);
3373  /* rejection by probability preserving ratio step */
3374  } while (uniform(seed, 0, 1) > t);
3375  return(iem);
3376 }
3377 
3378 static double gamma_powser_coeff[6] = { 76.18009172947146,
3379  -86.50532032941677, 24.01409824083091, -1.231739572450155,
3380  0.1208650973866179E-2, -0.5395239384953E-5 };
3381 
3382 /*
3383  * log gamma (gamma large so better to calculate with log)
3384  *
3385  * This follows method in Numerical Recipes in C
3386  */
log_gamma(double d1)3387 static double log_gamma(double d1)
3388 {
3389  register int32 j;
3390  double y, x, tmp, ser;
3391 
3392  y = x = d1;
3393  tmp = x + 5.5;
3394  tmp -= (x + 0.5)*log(tmp);
3395  ser = 1.000000000190015;
3396  for (j = 0; j <= 5; j++) ser += gamma_powser_coeff[j]/++y;
3397  return(-tmp + log(2.5066282746310005*ser/x));
3398 }
3399 
3400 /*
3401  * return randomly distributed chi-square with freedeg degrees
3402  * of freedom
3403  *
3404  * notice requiring both arguments - ,, illegal
3405  *
3406  * algorithm uses gamma dist. of order v/2 and mean 1
3407  */
3408 extern void __exec_chi_square(struct expr_t *ndp)
3409 {
3410  int32 u2;
3411  word32 val;
3412  double x, u;
3413  struct expr_t *fax, *a1xp, *a2xp;
3414  struct xstk_t *xsp, *xsp2;
3415 
3416  /* for func passed func node not first arg */
3417  fax = ndp->ru.x;
3418  /* access the required 2 arguments */
3419  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
3420  a1xp = fax->lu.x;
3421  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3422  a2xp = fax->lu.x;
3423 
3424  /* both arguments required */
3425  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
3426   {
3427    __sgfwarn(588,
3428    "$chi_square arguments must not be missing (,, form) - returning 32'bx");
3429    goto ret_x;
3430   }
3431 
3432  /* although evaling, previous error if seed is not simple WBIT reg */
3433  xsp = __eval_xpr(a1xp);
3434  if (xsp->bp[0] != 0)
3435   {
3436    __sgfwarn(588,
3437     "$dist_chi_square seed value %s has x/z bits - returning 32'bx",
3438     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
3439    xsp->bp[0] = 0L;
3440    __pop_xstk();
3441 ret_x:
3442    push_xstk_(xsp, WBITS);
3443    xsp->ap[0] = ALL1W;
3444    xsp->bp[0] = ALL1W;
3445    return;
3446   }
3447  __seed = (int32) xsp->ap[0];
3448  __pop_xstk();
3449 
3450  if (!__get_eval_word(a2xp, &val))
3451   {
3452    __sgfwarn(588,
3453     "$dist_chi_square argument 2, degree_of_freedom value %s x/z - returning 32'bx",
3454     __msgexpr_tostr(__xs, a2xp));
3455    goto ret_x;
3456   }
3457  /* look at me - are odd case right?, i.e. does rounding work? */
3458  /* for <= 2 degress of freedom same as exponential */
3459  u = val;
3460  if (u <= 2.0) u = 1.0; else u = u/2.0;
3461 
3462  /* chi-square is 2 times gamma deviate of degree_of_freedom/2 */
3463  x = gamma_dev(u, &__seed);
3464 
3465  /* map to real mean for chi-square always 1 */
3466  /* then to int32 (will always be positive) using Verilog round rules */
3467  u2 = ver_rint_(x);
3468 
3469  push_xstk_(xsp, WBITS);
3470  xsp->bp[0] = 0L;
3471  /* notice generator returns only 31 (signed +) bits so high bit always 0 */
3472  xsp->ap[0] = (word32) u2;
3473 
3474  push_xstk_(xsp2, WBITS);
3475  xsp2->ap[0] = (word32) __seed;
3476  xsp2->bp[0] = 0L;
3477  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3478  __pop_xstk();
3479 }
3480 
3481 /*
3482  * return randomly distributed t-distribution with freedeg degrees
3483  * of freedom
3484  *
3485  * notice requiring both arguments - ,, illegal
3486  *
3487  * t distribution is std normal (real) Y1 with mean 1 and var. 0
3488  * and chi-square Y2 with v degress of freed and mean 1 (see above)
3489  * t is then y1/sqrt(y2/v)
3490  */
3491 extern void __exec_dist_t(struct expr_t *ndp)
3492 {
3493  int32 u2;
3494  word32 val;
3495  double y1, y2, x, u, v;
3496  struct expr_t *fax, *a1xp, *a2xp;
3497  struct xstk_t *xsp, *xsp2;
3498 
3499  /* for func passed func node not first arg */
3500  fax = ndp->ru.x;
3501  /* access the required 2 arguments */
3502  if (fax == NULL) __arg_terr(__FILE__, __LINE__);
3503  a1xp = fax->lu.x;
3504  if ((fax = fax->ru.x) == NULL) __arg_terr(__FILE__, __LINE__);
3505  a2xp = fax->lu.x;
3506 
3507  /* both arguments required */
3508  if (a1xp->optyp == OPEMPTY || a2xp->optyp == OPEMPTY)
3509   {
3510    __sgfwarn(588,
3511    "$dist_t arguments must not be missing (,, form) - returning 32'bx");
3512    goto ret_x;
3513   }
3514 
3515  /* although evaling, previous error if seed is not simple WBIT reg */
3516  xsp = __eval_xpr(a1xp);
3517  if (xsp->bp[0] != 0)
3518   {
3519    __sgfwarn(588,
3520     "$dist_t seed value %s has x/z bits - returning 32'bx",
3521     __regab_tostr(__xs, xsp->ap, xsp->bp, xsp->xslen, BHEX, FALSE));
3522    xsp->bp[0] = 0L;
3523    __pop_xstk();
3524 ret_x:
3525    push_xstk_(xsp, WBITS);
3526    xsp->ap[0] = ALL1W;
3527    xsp->bp[0] = ALL1W;
3528    return;
3529   }
3530  __seed = (int32) xsp->ap[0];
3531  __pop_xstk();
3532 
3533  if (!__get_eval_word(a2xp, &val))
3534   {
3535    __sgfwarn(588,
3536     "$dist_t argument 2, degree_of_freedom value %s x/z - returning 32'bx",
3537     __msgexpr_tostr(__xs, a2xp));
3538    goto ret_x;
3539   }
3540  /* look at me - are odd case right?, i.e. does rounding work? */
3541  /* for <= 2 degress of freedom same as exponential */
3542  v = (double) val;
3543  if (v <= 2.0) u = 1.0; else u = v/2.0;
3544 
3545 
3546  /* Y1 is stdnorm with 0 mean and 1.0 variance */
3547  y1 = stdnorm_dev(&__seed);
3548 
3549  /* Y2 real chi-square is 2*gamma deviate of degree_of_freedom/2 */
3550  y2 = gamma_dev(u, &__seed);
3551  x = y1/sqrt(y2/v);
3552 
3553  /* map to real mean for chi-square always 1 */
3554  /* then to int32 (will always be positive) using Verilog round rules */
3555  u2 = ver_rint_(x);
3556 
3557  push_xstk_(xsp, WBITS);
3558  xsp->bp[0] = 0L;
3559  /* generator returns only 31 (signed +) bits so high bit always 0 */
3560  xsp->ap[0] = (word32) u2;
3561 
3562  push_xstk_(xsp2, WBITS);
3563  xsp2->ap[0] = (word32) __seed;
3564  xsp2->bp[0] = 0L;
3565  __exec2_proc_assign(a1xp, xsp2->ap, xsp2->bp);
3566  __pop_xstk();
3567 }
3568 
3569 /*
3570  * SPECIAL OPERATOR EVALUATION ROUTINES
3571  */
3572 
3573 /*
3574  * evaluate a rhs concatenate on to top of reg stack
3575  * key is that { op. node width is same as starting high bit of value
3576  *
3577  * this requires inst ptr set
3578  */
3579 extern void __rhs_concat(struct expr_t *lcbndp)
3580 {
3581  register int32 catxlen;
3582  register struct expr_t *catndp, *catrhsx;
3583  register word32 *ap, *bp;
3584  word32 *wp, *sawp, *sbwp, tmpa, tmpb;
3585  int32 wlen, bi1;
3586  struct xstk_t *catreg, *xsp;
3587  struct net_t *np;
3588 
3589  /* build concatenate from high (right) to low since faster */
3590  push_xstk_(catreg, lcbndp->szu.xclen);
3591  ap = catreg->ap;
3592  bp = catreg->bp;
3593  /* never z extend for rhs concat eval. - only assigns */
3594  zero_allbits_(ap, catreg->xslen);
3595  zero_allbits_(bp, catreg->xslen);
3596 
3597  /* now evaluate components and assign to section of ap/bp */
3598  /* first concat component is highest bit(s) so work from high bits to low */
3599  for (catndp = lcbndp->ru.x; catndp != NULL; catndp = catndp->ru.x)
3600   {
3601    /* catrhsx actual rhs concat component expr. with width catxlen */
3602    catrhsx = catndp->lu.x;
3603    catxlen = catrhsx->szu.xclen;
3604    /* catndp comma node is dist. to low bit, bi1 is low bit of rhs psel */
3605    bi1 = catndp->szu.xclen - catxlen;
3606 
3607    /* DBG remove ---
3608    if (__debug_flg)
3609     __dbg_msg(
3610      "+++rhs: total concat wid=%u, low index=%d, wid=%u, remaining wid=%u\n",
3611       lcbndp->szu.xclen, bi1, catxlen, catndp->szu.xclen);
3612    --- */
3613    switch ((byte) catrhsx->optyp) {
3614     /* notice IS number just falls through to expr load case */
3615     case NUMBER:
3616      wlen = wlen_(catxlen);
3617      sawp = &(__contab[catrhsx->ru.xvi]);
3618      sbwp = &(sawp[wlen]);
3619 do_lhssel:
3620      /* notice lhs bsel takes value not ptr to value */
3621      if (catxlen == 1)
3622       { __lhsbsel(ap, bi1, sawp[0]); __lhsbsel(bp, bi1, sbwp[0]); }
3623      else
3624       {
3625        __lhspsel(ap, bi1, sawp, catxlen);
3626        __lhspsel(bp, bi1, sbwp, catxlen);
3627       }
3628      break;
3629     case ISNUMBER:
3630      wlen = wlen_(catxlen);
3631      wp = &(__contab[catrhsx->ru.xvi]);
3632      sawp = &(wp[2*wlen*__inum]);
3633      sbwp = &(sawp[wlen]);
3634      goto do_lhssel;
3635     case ID:
3636      /* optimize if fits in word32 case - else just use eval mechanism */
3637      if (catxlen <= WBITS)
3638       {
3639        np = catrhsx->lu.sy->el.enp;
3640        /* cannot optimize more because can be scalar or strength rep */
3641        __ld_wire_val(&tmpa, &tmpb, np);
3642        if (catxlen == 1)
3643 	{
3644 	 __lhsbsel(ap, bi1, tmpa & 1L);
3645 	 __lhsbsel(bp, bi1, tmpb & 1L);
3646 	}
3647        else
3648 	{
3649          __lhspsel(ap, bi1, &tmpa, catxlen);
3650          __lhspsel(bp, bi1, &tmpb, catxlen);
3651 	}
3652        break;
3653       }
3654      /* > WBITS so fall thru */
3655      /* cases PARTSEL, LSB, GLBREF, ... fall thru */
3656      /* just evaluate normally */
3657      /* and then assigned like a normal expression */
3658      /* so far do not have a way of doing these special cases faster */
3659     default:
3660      xsp = __eval2_xpr(catrhsx);
3661      /* get rid of this stuff when debugged */
3662      /* expression in concatenate has wrong width */
3663      if (xsp->xslen != catxlen) __misc_terr(__FILE__, __LINE__);
3664      if (catxlen == 1)
3665       { __lhsbsel(ap, bi1, xsp->ap[0]); __lhsbsel(bp, bi1, xsp->bp[0]); }
3666      else
3667       {
3668        __lhspsel(ap, bi1, xsp->ap, catxlen);
3669        __lhspsel(bp, bi1, xsp->bp, catxlen);
3670       }
3671      __pop_xstk();
3672    }
3673   }
3674 }
3675 
3676 /*
3677  * load rhs only address of a part of contiguous coded variable
3678  * returned value is read only - must use st_ routines to store
3679  *
3680  * this must not be used for strength values
3681  * for scalars and packed moves to tmp so not really load address
3682  * i.e. address returned cannot be indirectly stored into
3683  *
3684  * notice xmr must be converted to net before here
3685  */
3686 extern void __ld_addr(word32 **aap, word32 **abp, register struct net_t *np)
3687 {
3688  register word32 *ap, *bp;
3689  register int32 wlen;
3690 
3691  switch ((byte) np->srep) {
3692   case SR_VEC:
3693    wlen = wlen_(np->nwid);
3694    ap = &(np->nva.wp[2*wlen*__inum]);
3695    bp = &(ap[wlen]);
3696    break;
3697   case SR_SCAL:
3698    ap = __addrtmp;
3699    bp = &(__addrtmp[1]);
3700    ld_scalval_(ap, bp, np->nva.bp);
3701    break;
3702   default: __case_terr(__FILE__, __LINE__); return;
3703  }
3704  *aap = ap;
3705  *abp = bp;
3706 }
3707 
3708 /*
3709  * evaluate a question ?: expression
3710  *
3711  * SJM 01/14/99 - fixed bug - previously always evaluatged expr 1 and 2
3712  * that was wrong since only need to do that if selector has x/z bits
3713  */
3714 extern void __eval_qcol(register struct expr_t *ndp)
3715 {
3716  struct xstk_t *xspq, *xsp1, *xsp2;
3717 
3718  xspq = __eval_xpr(ndp->lu.x);
3719  /* case 1: some x bits in selector, need both to be result (widest) wide */
3720  if (!vval_is0_(xspq->bp, xspq->xslen))
3721   {
3722    xsp1 = __eval_xpr(ndp->ru.x->lu.x);
3723    xsp2 = __eval_xpr(ndp->ru.x->ru.x);
3724    /* xspq overwritten with x case (i.e. 2 down from top) */
3725    /* SJM 09/30/03 - select self determined so may or may not be signed */
3726    /* : operands either both signed or neither signed */
3727    /* AIV 01/04/07 - was passing the wrong expr parts for has_sign bit */
3728    lxqcol(xspq, xsp1, xsp2, ndp->szu.xclen, ndp->ru.x->lu.x->has_sign,
3729     ndp->ru.x->ru.x->has_sign);
3730    /* pop top 2 arguments leaving result that is always down 2 */
3731    __pop_xstk();
3732    __pop_xstk();
3733    return;
3734   }
3735  /* case 2: non x/z selector */
3736  /* case 2a: non 0 is true - only evaluate first for non x/z selector */
3737  if (!vval_is0_(xspq->ap, xspq->xslen))
3738   {
3739    /* pop selector */
3740    __pop_xstk();
3741    /* evaluate expression 1 */
3742    xsp1 = __eval_xpr(ndp->ru.x->lu.x);
3743 
3744    /* need to change width to widest if 1 and 2 differ */
3745    /* SJM 09/30/03 - widen only but can be sign extend */
3746    if (xsp1->xslen != ndp->szu.xclen)
3747     {
3748      if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
3749      else __sizchg_widen(xsp1, ndp->szu.xclen);
3750     }
3751    return;
3752   }
3753  /* case 2b: 0 is FALSE - only evaluate first for non x/z selector */
3754  /* pop selector */
3755  __pop_xstk();
3756  /* evaluate expression 2 */
3757  xsp1 = __eval_xpr(ndp->ru.x->ru.x);
3758  /* need to change width to widest if 1 and 2 differ */
3759 
3760  /* need to change width to widest if 1 and 2 differ */
3761  /* SJM 09/30/03 - widen only but can be sign extend */
3762  if (xsp1->xslen < ndp->szu.xclen)
3763   {
3764    if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
3765    else __sizchg_widen(xsp1, ndp->szu.xclen);
3766   }
3767 }
3768 
3769 /*
3770  * eval real ?: both condition and : operands reals
3771  *
3772  * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
3773  * that was always wrong for reals
3774  */
3775 extern void __eval_realrealqcol(register struct expr_t *ndp)
3776 {
3777  double d1;
3778  register struct xstk_t *xspq, *xsp;
3779  register struct expr_t *xp;
3780 
3781  /* know this is real to get here */
3782  xspq = __eval2_xpr(ndp->lu.x);
3783  memcpy(&d1, xspq->ap, sizeof(double));
3784 
3785  /* T case - evaluate first */
3786  if (d1 != 0.0)
3787   {
3788    __pop_xstk();
3789    xp = ndp->ru.x->lu.x;
3790    xsp = __eval_xpr(xp);
3791    if (xp->cnvt_to_real)
3792     {
3793      d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
3794      /* this works because minimum stack every allocated is 8 bytes */
3795      /* PORTABILITY - stack must always be at least 8 bytes */
3796      memcpy(xsp->ap, &d1, sizeof(double));
3797     }
3798    return;
3799   }
3800  /* F case - evaluate 2nd */
3801  __pop_xstk();
3802  xp = ndp->ru.x->ru.x;
3803  xsp = __eval_xpr(xp);
3804  if (xp->cnvt_to_real)
3805   {
3806    d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
3807    /* this works because minimum stack every allocated is 8 bytes */
3808 
3809    /* PORTABILITY - stack must always be at least 8 bytes */
3810    memcpy(xsp->ap, &d1, sizeof(double));
3811   }
3812 }
3813 
3814 /*
3815  * eval realreg ?: condition real but : operands regs
3816  *
3817  * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
3818  * now since selector real only evaluate right one
3819  */
3820 extern void __eval_realregqcol(struct expr_t *ndp)
3821 {
3822  struct xstk_t *xspq, *xsp;
3823  double d1;
3824 
3825  xspq = __eval_xpr(ndp->lu.x);
3826  memcpy(&d1, xspq->ap, sizeof(double));
3827  /* case 2a: non 0 is true - only evaluate first for non x/z selector */
3828  if (d1 != 0.0)
3829   {
3830    /* pop selector */
3831    __pop_xstk();
3832    /* evaluate expression 1 */
3833    xsp = __eval_xpr(ndp->ru.x->lu.x);
3834    /* need to change width to widest if 1 and 2 differ */
3835 
3836    /* need to change width to widest if 1 and 2 differ */
3837    /* SJM 09/30/03 - widen only but can be sign extend */
3838    if (xsp->xslen < ndp->szu.xclen)
3839     {
3840      if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
3841      else __sizchg_widen(xsp, ndp->szu.xclen);
3842     }
3843    return;
3844   }
3845  /* case 2b: 0 is FALSE - only evaluate first for non x/z selector */
3846  /* pop selector */
3847  __pop_xstk();
3848  /* evaluate expression 2 */
3849  xsp = __eval_xpr(ndp->ru.x->ru.x);
3850  /* need to change width to widest if 1 and 2 differ */
3851  /* SJM 09/30/03 - widen only but can be sign extend */
3852  if (xsp->xslen < ndp->szu.xclen)
3853   {
3854    if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
3855    else __sizchg_widen(xsp, ndp->szu.xclen);
3856   }
3857 }
3858 
3859 /*
3860  * eval regreal ?: condition reg but : operands real
3861  *
3862  * SJM 01/14/99 - fixed bug - previously always evaluated expr 1 and 2
3863  * now only evaluate if selector has x/z bits
3864  */
3865 extern void __eval_regrealqcol(register struct expr_t *ndp)
3866 {
3867  register struct xstk_t *xspq, *xsp;
3868  register struct expr_t *xp;
3869  double d1;
3870 
3871  xspq = __eval_xpr(ndp->lu.x);
3872  /* case 1: selector has x/z bits */
3873  if (!vval_is0_(xspq->bp, xspq->xslen))
3874   {
3875    __sgferr(730,
3876      "?: operator select condition x/z but values are real - 0.0 returned");
3877    d1 = 0.0;
3878    memcpy(xspq->ap, &d1, sizeof(double));
3879    return;
3880   }
3881 
3882  /* T (non zero) case */
3883  if (!vval_is0_(xspq->ap, xspq->xslen))
3884   {
3885    __pop_xstk();
3886    xp = ndp->ru.x->lu.x;
3887    xsp = __eval_xpr(xp);
3888    if (xp->cnvt_to_real)
3889     {
3890      d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
3891      /* this works because minimum stack every allocated is 8 bytes */
3892 
3893      /* PORTABILITY - stack must always be at least 8 bytes */
3894      memcpy(xsp->ap, &d1, sizeof(double));
3895     }
3896    return;
3897   }
3898  /* F case */
3899  __pop_xstk();
3900  xp = ndp->ru.x->ru.x;
3901  xsp = __eval_xpr(xp);
3902  if (xp->cnvt_to_real)
3903   {
3904    d1 = __cnvt_stk_to_real(xsp, (xp->has_sign == 1));
3905    /* this works because minimum stack every allocated is 8 bytes */
3906    /* PORTABILITY - stack must always be at least 8 bytes */
3907    memcpy(xsp->ap, &d1, sizeof(double));
3908   }
3909 }
3910 
3911 /*
3912  * evaluate a qcol x form (at least one x bit) truth table
3913  *
3914  * notice this overwrites conditional but works because once know any x's
3915  * in conditional, then value obtained purely from combination of args.
3916  * LOOKATME - one word32 form could be more efficient but used for all
3917  *
3918  * SJM 09/30/03 - need different widen if signed - : operand either both
3919  * signed or both no signed
3920  */
3921 static void lxqcol(register struct xstk_t *xspq, register struct xstk_t *xsp1,
3922  register struct xstk_t *xsp2, int32 opbits, int32 sel_sign, int32 col_sign)
3923 {
3924  register int32 wi;
3925  word32 *resap, *resbp;
3926  struct xstk_t *tmpq;
3927  int32 wlen, ubits;
3928 
3929  /* LOOKATME - LRM 2.0 is wrong to match OVIsim any 1 in value is T */
3930  /* any one implies use T */
3931  /* notice must use qcol word32 width here */
3932  wlen = wlen_(xspq->xslen);
3933  for (wi = 0; wi < wlen; wi++)
3934   { if ((xspq->ap[wi] & ~xspq->bp[wi]) != 0) goto true_has_1bit; }
3935 
3936  wlen = wlen_(opbits);
3937 
3938  /* SJM 09/30/03 - widen only but can be sign extend - know : opands same */
3939  if (xsp1->xslen < opbits)
3940   {
3941    /* AIV 01/10/07 - was using col sign for sel part sign */
3942    if (sel_sign) __sgn_xtnd_widen(xsp1, opbits);
3943    else __sizchg_widen(xsp1, opbits);
3944   }
3945  if (xsp2->xslen < opbits)
3946   {
3947    if (col_sign) __sgn_xtnd_widen(xsp2, opbits);
3948    else __sizchg_widen(xsp2, opbits);
3949   }
3950 
3951  /* SJM 05/21/04 - if select is wider need to narrow it - the : arms */
3952  /* can only be widened because max width set in return val node */
3953  if (xspq->xslen > opbits) __narrow_sizchg(xspq, opbits);
3954  else if (xspq->xslen < opbits)
3955   {
3956    if (sel_sign) __sgn_xtnd_widen(xspq, opbits);
3957    else __sizchg_widen(xspq, opbits);
3958   }
3959 
3960  resap = xspq->ap; resbp = xspq->bp;
3961  for (wi = 0; wi < wlen; wi++)
3962   {
3963    /* widened already with 0's before using table */
3964    /* truth table is 0-0 = 0, 1-1 = 1, else x */
3965    resbp[wi] = xsp2->bp[wi] | xsp1->bp[wi] | (xsp2->ap[wi] ^ xsp1->ap[wi]);
3966    /* if resbp bit zero, know either both 1 or both 0 */
3967    resap[wi] = resbp[wi] | xsp1->ap[wi];
3968   }
3969  ubits = ubits_(opbits);
3970  resap[wlen - 1] &= __masktab[ubits];
3971  resbp[wlen - 1] &= __masktab[ubits];
3972  return;
3973 
3974 true_has_1bit:
3975  /* T case because at least one bit 1 */
3976  /* just shuffle pointers to stack regs here */
3977  tmpq = __xstk[__xspi - 2];
3978  __xstk[__xspi - 2] = __xstk[__xspi - 1];
3979  __xstk[__xspi - 1] = tmpq;
3980 }
3981 
3982 /*
3983  * ROUTINES TO EVALUATE NORMAL UNARY OPERATORS
3984  */
3985 
3986 /*
3987  * evaluate a unary operator
3988  * replaces tos expr. value with result
3989  * for now routine always uses long form, need too routines
3990  *
3991  * never need stack conversion here to real because will not be real op
3992  * if operand not real
3993  */
3994 static void eval_unary(struct expr_t *ndp)
3995 {
3996  register word32 op1a, op1b;
3997  register struct xstk_t *xsp;
3998  word32 mask;
3999  int32 ida;
4000  double d1;
4001 
4002  xsp = __eval2_xpr(ndp->lu.x);
4003  /* notice double must not be > WBITS (i.e 64 bits no b part - width WBITS) */
4004  if (ndp->szu.xclen > WBITS || xsp->xslen > WBITS)
4005   {
4006    eval_wide_unary(ndp, xsp);
4007    return;
4008   }
4009  op1a = xsp->ap[0];
4010  op1b = xsp->bp[0];
4011 
4012  /* SJM 03/11/02 - beware - this uses fact that op1b same as xsp b part */
4013  /* operand so if op1b 0, know xsp, bp part also 0 */
4014  switch ((byte) ndp->optyp) {
4015   /* both unary and binary but used as unary here */
4016   case /* + */ PLUS:
4017    /* plus removed (no op) before here */
4018    __misc_terr(__FILE__, __LINE__);
4019    return;
4020   case /* - */ MINUS:
4021    /* only if operand value too wide, need mask to narrow */
4022    if (op1b == 0L)
4023     {
4024      if (ndp->has_sign && ndp->lu.x->szu.xclen != WBITS)
4025       {
4026        /* SJM 06/01/04 - may need to sign extend operand */
4027        if ((op1a & (1 << (ndp->lu.x->szu.xclen - 1))) != 0)
4028         op1a |= ~(__masktab[ndp->lu.x->szu.xclen]);
4029        /* AIV 09/25/06 - if the sign bit is on converting to size of expr */
4030        /* was wrong - since sign extended/mask here just set needed size */
4031        xsp->xslen = ndp->szu.xclen;
4032       }
4033      /* convert to signed 32 bit then copy back to word32 */
4034      /* works because narrower than 32 signed extended already */
4035      ida = (int32) op1a;
4036      xsp->ap[0] = ((word32) -ida) & __masktab[ndp->szu.xclen];
4037     }
4038    else xsp->ap[0] = xsp->bp[0] = __masktab[ndp->szu.xclen];
4039    return;
4040   case /* real - */ REALMINUS:
4041    /* notice double may be on only 4 byte boundary so need to copy and op */
4042    /* also width of xsp is WBITS - 8 bytes for double - known real */
4043    /* FIXME ??? - this is stupid - should use endianness */
4044    memcpy(&d1, xsp->ap, sizeof(double));
4045    d1 = -d1;
4046    memcpy(xsp->ap, &d1, sizeof(double));
4047    return;
4048   case /* ~ */ BITNOT:
4049    mask = __masktab[ndp->szu.xclen];
4050    xsp->ap[0] = (~op1a | op1b) & mask;
4051    xsp->bp[0] = op1b & mask;
4052    return;
4053   /* notice for reduction and logicals - must set xsp stack width to 1 */
4054   case /* logical ! */ NOT:
4055    /* know a val unused bits will be 0 */
4056    if (op1b == 0L) xsp->ap[0] = (xsp->ap[0] == 0L) ? 1L : 0L;
4057    else xsp->ap[0] = xsp->bp[0] = 1L;
4058    break;
4059   case /* logical real ! */ REALNOT:
4060    /* real only uses x stack a part */
4061    /* width of xsp is WBITS - 8 bytes for double - known real */
4062    memcpy(&d1, xsp->ap, sizeof(double));
4063    /* notice overwriting place dp points */
4064    /* SJM 01/04/99 - had logic backward */
4065    if (d1 > -EPSILON && d1 < EPSILON) xsp->ap[0] = 1L; else xsp->ap[0] = 0L;
4066    xsp->bp[0] = 0L;
4067    break;
4068   case /* & */ BITREDAND:
4069    /* width here is just unary operand width since unary self determined */
4070    /* must use operand width since result node width will be 1 probably */
4071    mask = __masktab[xsp->xslen];
4072    /* if even 1 0 value in any used bit, result is 0 */
4073    if (op1b == 0L) xsp->ap[0] = (op1a != mask) ? 0L : 1L;
4074    else if ((op1a | op1b) != mask) xsp->ap[0] = xsp->bp[0] = 0L;
4075    else xsp->ap[0] = xsp->bp[0] = 1L;
4076    break;
4077   case /* | */ BITREDOR:
4078    /* here wide will be zero's so no need for width change */
4079    if (op1b == 0L) xsp->ap[0] = (op1a != 0L) ? 1L : 0L;
4080    else if ((op1a & ~op1b) != 0L) { xsp->ap[0] = 1L; xsp->bp[0] = 0L; }
4081    else xsp->ap[0] = xsp->bp[0] = 1L;
4082    break;
4083   case /* ^ */ BITREDXOR:
4084    if (op1b != 0L) { xsp->ap[0] = xsp->bp[0] = 1L; break; }
4085    /* notice here any high unused 0's will not effect result */
4086    xsp->bp[0] = 0L;
4087    xsp->ap[0] = __wrd_redxor(op1a);
4088    break;
4089   case /* ^~ */ REDXNOR:
4090    /* exec as first the ^ then take opposite of 1 bit */
4091    /* truth table is: 00 = 1, 01 = 0,  10 = 0, 11 = 1 */
4092    /* odd numer of 1 bits value 1, else value 0 */
4093    if (op1b != 0L) { xsp->ap[0] = xsp->bp[0] = 1L; break; }
4094    /* use mask as tmp */
4095    xsp->ap[0] = !__wrd_redxor(op1a);
4096    xsp->bp[0] = 0L;
4097    break;
4098   default: __case_terr(__FILE__, __LINE__);
4099  }
4100  xsp->xslen = 1;
4101 }
4102 
4103 /*
4104  * evaluate a wide unary
4105  * notice xsp widened to same width as ndp above here for - and ~
4106  * but not for reduction and logical
4107  */
4108 static void eval_wide_unary(register struct expr_t *ndp,
4109  register struct xstk_t *xsp)
4110 {
4111  int32 rta, rtb;
4112 
4113  switch ((byte) ndp->optyp) {
4114   /* both unary and binary but used as unary here */
4115   case /* + */ PLUS:
4116    /* unary plus eliminated before here */
4117    __misc_terr(__FILE__, __LINE__);
4118    return;
4119   case /* - */ MINUS:
4120    /* SJM 05/10/04 FIXME - since sign extended, do not need signed l uminus */
4121    /* SJM 09/29/03 - change to handle sign extension and separate types */
4122    if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
4123    else if (xsp->xslen < ndp->szu.xclen)
4124     {
4125      if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
4126      else __sizchg_widen(xsp, ndp->szu.xclen);
4127     }
4128 
4129    __luminus(xsp->ap, xsp->bp, ndp->szu.xclen);
4130    /* must fix since stack exchanged */
4131    xsp->xslen = ndp->szu.xclen;
4132    return;
4133   case /* ~ */ BITNOT:
4134    /* SJM 05/10/04 FIXME - since sign extended, do not need signed l bitnot */
4135    /* SJM 09/29/03 - change to handle sign extension and separate types */
4136    if (xsp->xslen > ndp->szu.xclen) __narrow_sizchg(xsp, ndp->szu.xclen);
4137    else if (xsp->xslen < ndp->szu.xclen)
4138     {
4139      if (ndp->has_sign) __sgn_xtnd_widen(xsp, ndp->szu.xclen);
4140      else __sizchg_widen(xsp, ndp->szu.xclen);
4141     }
4142 
4143    __lunbitnot(xsp->ap, xsp->bp, ndp->szu.xclen);
4144    /* know bit not in place and size changed already */
4145    return;
4146   /* notice for logicals and reductions must set width to 1 */
4147   case /* logical ! */ NOT:
4148    if (vval_is0_(xsp->bp, xsp->xslen))
4149     {
4150      rtb = 0L;
4151      if (vval_is0_(xsp->ap, xsp->xslen)) rta = 1L; else rta = 0L;
4152     }
4153    else rta = rtb = 1L;
4154    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
4155    __narrow_to1bit(xsp);
4156    xsp->ap[0] = rta;
4157    xsp->bp[0] = rtb;
4158    break;
4159   case /* & */ BITREDAND:
4160    /* this changes tos to 1 bit value */
4161    __lunredand(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
4162    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
4163    __narrow_to1bit(xsp);
4164    xsp->ap[0] = (word32) rta;
4165    xsp->bp[0] = (word32) rtb;
4166    break;
4167   case /* | */ BITREDOR:
4168    __lunredor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
4169    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
4170    __narrow_to1bit(xsp);
4171    xsp->ap[0] = (word32) rta;
4172    xsp->bp[0] = (word32) rtb;
4173    break;
4174   case /* ^ */ BITREDXOR:
4175    __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
4176    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
4177    __narrow_to1bit(xsp);
4178    xsp->ap[0] = (word32) rta;
4179    xsp->bp[0] = (word32) rtb;
4180    break;
4181   case /* ^~ */ REDXNOR:
4182    /* truth table is logical not of bit wire reducing */
4183    /* odd numer of 1 bits value 1, else value 0 */
4184    __lunredxor(&rta, &rtb, xsp->ap, xsp->bp, xsp->xslen);
4185    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
4186    __narrow_to1bit(xsp);
4187    xsp->ap[0] = (word32) rta;
4188    xsp->bp[0] = (word32) rtb;
4189    if (rtb == 0L) xsp->ap[0] = (word32) !rta;
4190    /* this produces the 1 bit result */
4191    break;
4192   default: __case_terr(__FILE__, __LINE__);
4193  }
4194  xsp->xslen = 1;
4195 }
4196 
4197 /*
4198  * unary bit not - notice this is bit for bit
4199  */
4200 extern void __lunbitnot(word32 *op1ap, word32 *op1bp, int32 opwid)
4201 {
4202  register int32 wi;
4203  int32 wlen;
4204 
4205  wlen = wlen_(opwid);
4206  for (wi = 0; wi < wlen; wi++)
4207   {
4208    op1ap[wi] = (~op1ap[wi] | op1bp[wi]);
4209    /* b value remains unchanged */
4210   }
4211  op1ap[wlen - 1] &= __masktab[ubits_(opwid)];
4212 }
4213 
4214 /*
4215  * unary minus (0 - value)
4216  * know op1ap and op1bp are just pointers to tos values
4217  *
4218  * SJM 09/30/03 - signed just works because 2's complement
4219  */
4220 extern void __luminus(word32 *op1ap, word32 *op1bp, int32 opbits)
4221 {
4222  struct xstk_t *xsp0, *xspr;
4223 
4224  if (!vval_is0_(op1bp, opbits))
4225   { one_allbits_(op1ap, opbits); one_allbits_(op1bp, opbits); }
4226  else
4227   {
4228    /* need real multi-bit subtract */
4229    push_xstk_(xsp0, opbits);
4230    zero_allbits_(xsp0->ap, opbits);
4231    zero_allbits_(xsp0->bp, opbits);
4232 
4233    push_xstk_(xspr, opbits);
4234    /* result on tos above 2 operands */
4235    __lsub(xspr->ap, xsp0->ap, op1ap, opbits);
4236    zero_allbits_(xspr->bp, opbits);
4237    /* now must adjust tos stack */
4238    xchg_stk(__xspi - 2, __xspi);
4239    __pop_xstk();
4240    __pop_xstk();
4241   }
4242 }
4243 
4244 /*
4245  * exchange 2 eval. stack locations
4246  */
4247 static void xchg_stk(int32 xspi1, int32 xspi2)
4248 {
4249  struct xstk_t *xstmp;
4250 
4251  xstmp = __xstk[xspi1]; __xstk[xspi1] = __xstk[xspi2]; __xstk[xspi2] = xstmp;
4252 }
4253 
4254 /*
4255  * compute reduction xor for 32 bit word32 (or part)
4256  * this returns 1 bit
4257  * notice this is 32 bit word32 dependent
4258  *
4259  * FIXME - if processor has instruction for word32 reducing xor should use
4260  */
4261 extern word32 __wrd_redxor(word32 opa)
4262 {
4263  register word32 t, rta;
4264 
4265  t = opa;
4266  t = t ^ (t >> 16);
4267  t = t ^ (t >> 8);
4268  t = t ^ (t >> 4);
4269  t = t ^ (t >> 2);
4270  rta = (t ^ (t >> 1)) & 1L;
4271  return(rta);
4272 }
4273 
4274 /*
4275  * compute reduction xor for 64 bit lword (or word64) (or part of lword)
4276  * this returns 1 bit
4277  * notice this is 64 bit word32 dependent
4278  *
4279  * FIXME - if processor has instruction for word32 reducing xor should use
4280  */
4281 extern word64 __lwrd_redxor(word64 opa)
4282 {
4283  register word64 t, rta;
4284 
4285  t = opa;
4286  t = t ^ (t >> 32);
4287  t = t ^ (t >> 16);
4288  t = t ^ (t >> 8);
4289  t = t ^ (t >> 4);
4290  t = t ^ (t >> 2);
4291  rta = (t ^ (t >> 1)) & 1ULL;
4292  return(rta);
4293 }
4294 
4295 /*
4296  * ROUTINES FOR WIDE UNARY OPERATORS
4297  */
4298 
4299 /*
4300  * wide bit reducing and - set tos to 1 bit result
4301  * if not all 1's, reduction and will turn to 0
4302  */
4303 extern void __lunredand(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
4304  int32 opwid)
4305 {
4306  register int32 wi;
4307  int32 wlen, ubits;
4308 
4309  /* handle non x/z case */
4310  if (vval_is0_(op1bp, opwid))
4311   {
4312    *rtb = 0;
4313    if (!__vval_is1(op1ap, opwid)) *rta = 0; else *rta = 1;
4314    return;
4315   }
4316 
4317  /* if even one 0 => 0, else x, know high op1a and op1b bit 0 */
4318  wlen = wlen_(opwid);
4319  ubits = ubits_(opwid);
4320  if (ubits != 0) wlen--;
4321 
4322  for (wi = 0; wi < wlen; wi++)
4323   {
4324    /* if any 0 value bits in either, reducing and will be 0 */
4325    if ((op1ap[wi] | op1bp[wi]) != ALL1W) { *rtb = *rta = 0; return; }
4326   }
4327  if (ubits != 0)
4328   {
4329    if ((op1ap[wlen] | op1bp[wlen]) != __masktab[ubits])
4330     { *rtb = *rta = 0; return; }
4331   }
4332  /* did not find 0, must be x */
4333  *rtb = *rta = 1;
4334 }
4335 
4336 /*
4337  * wide bit reducing or - set tos to 1 bit result
4338  * if not all 0's, reduction and will turn to 1
4339  */
4340 extern void __lunredor(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
4341  int32 opwid)
4342 {
4343  register int32 wi;
4344  register word32 rta2, rtb2;
4345 
4346  /* if even 1 1 and no x/z bits, reduction and will turn to 1 */
4347  if (vval_is0_(op1bp, opwid))
4348   {
4349    rtb2 = 0;
4350    if (!vval_is0_(op1ap, opwid)) rta2 = 1; else rta2 = 0;
4351    goto done;
4352   }
4353  /* if even one 1 => 1, else x, know high op1a and op1b bit 0 */
4354  /* since know high bits will be 0, no need to handle separately */
4355  for (wi = 0; wi < wlen_(opwid); wi++)
4356   {
4357    /* if a bit is 1 and b bit is 0, have the one needed 1 */
4358    if ((op1ap[wi] & ~op1bp[wi]) != 0L)
4359     { rtb2 = 0; rta2 = 1; goto done; }
4360   }
4361  /* did not find a 1, must be x */
4362  rtb2 = rta2 = 1;
4363 done:
4364  *rta = rta2;
4365  *rtb = rtb2;
4366  return;
4367 }
4368 
4369 /*
4370  * wide bit reducing xor - set tos to 1 bit result
4371  * counts number of 1 bits
4372  */
4373 extern void __lunredxor(int32 *rta, int32 *rtb, word32 *op1ap, word32 *op1bp,
4374  int32 opwid)
4375 {
4376  register int32 wi;
4377  register word32 rtmp, rtmp2;
4378 
4379  /* if any x/zs, return is x */
4380  if (!vval_is0_(op1bp, opwid)) { *rta = *rtb = 1; return; }
4381 
4382  /* any unused 0's can be ignored - just produce 0 */
4383  for (rtmp = 0, wi = 0; wi < wlen_(opwid); wi++)
4384   {
4385    /* this returns 1 bit result */
4386    rtmp2 = __wrd_redxor(op1ap[wi]);
4387    rtmp ^= rtmp2;
4388   }
4389  *rta = rtmp;
4390  *rtb = 0L;
4391  return;
4392 }
4393 
4394 /*
4395  * ROUTINES TO EVALUATE NORMAL BINARY OPERATORS
4396  */
4397 
4398 /*
4399  * evaluate a binary operator
4400  * know all high (unused) bits set to zero - and left as zero
4401  * evaluates 2 operands and places result on tos (i.e. stack shrinks by 1)
4402  *
4403  * SJM 10/22/03 - the signed narrower than 32 bits consistently wrong
4404  * because sign bit not in bit 32 as was case when only 32 bit ints
4405  * could be signed - now either sign extend or use signed magnitude operation
4406  *
4407  * notice are tmps that can be changed during evaluation
4408  */
4409 static void eval_binary(struct expr_t *ndp)
4410 {
4411  register word32 rta, rtb;
4412  register word32 op1a, op1b, op2a, op2b, mask;
4413  int32 tmp1, tmp2, nd_signop, opwid, has_sign;
4414  double d1, d2;
4415  struct xstk_t *xsp1, *xsp2;
4416  struct expr_t *lx, *rx;
4417 
4418  xsp1 = __eval2_xpr(ndp->lu.x);
4419  xsp2 = __eval2_xpr(ndp->ru.x);
4420 
4421  /* need to separate off wide case */
4422  /* notice this code depends on real width == W BITS */
4423  if (ndp->szu.xclen > WBITS || xsp1->xslen > WBITS || xsp2->xslen > WBITS)
4424   {
4425    /* this replaces tos 2 values with 1 value */
4426    /* wide always word32 */
4427    eval_wide_binary(ndp, xsp1, xsp2);
4428    return;
4429   }
4430  opwid = ndp->szu.xclen;
4431  /* set during checking - result has sign if < WBITS and not 1 bit */
4432  /* and one or both operaads have sign */
4433  if (ndp->has_sign || ndp->rel_ndssign) nd_signop = TRUE;
4434  else nd_signop = FALSE;
4435 
4436  op1a = xsp1->ap[0]; op1b = xsp1->bp[0];
4437  op2a = xsp2->ap[0]; op2b = xsp2->bp[0];
4438  mask = __masktab[ubits_(opwid)];
4439 
4440  /* this is result operator not operands width */
4441  rta = rtb = 0L;
4442  switch ((byte) ndp->optyp) {
4443   case /* + */ PLUS:
4444    if (op1b == 0L && op2b == 0L)
4445     {
4446      rtb = 0;
4447      /* SJM 09/30/03 - need signed for c signed add (hardware sign xtnd) */
4448      if (!nd_signop) rta = (op1a + op2a) & mask;
4449      else
4450       {
4451        /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */
4452        if (ndp->lu.x->szu.xclen != WBITS)
4453         {
4454          /* complex narrower than 32 bit signed case - sign extend to c int */
4455          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4456           op1a |= ~(__masktab[xsp1->xslen]);
4457         }
4458        if (ndp->ru.x->szu.xclen != WBITS)
4459         {
4460          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4461           op2a |= ~(__masktab[xsp2->xslen]);
4462         }
4463        /* mask even if 32 bits */
4464        rta = (word32) ((((sword32) op1a) + ((sword32) op2a)) & mask);
4465       }
4466     }
4467    else rta = rtb = mask;
4468    break;
4469   case /* + real */ REALPLUS:
4470    /* is it portable to pass 1 bit bit field? */
4471    lx = ndp->lu.x;
4472    rx = ndp->ru.x;
4473    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4474    else memcpy(&d1, xsp1->ap, sizeof(double));
4475 
4476    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4477    else memcpy(&d2, xsp2->ap, sizeof(double));
4478 
4479    /* notice never a size change since both must be real */
4480    d1 += d2;
4481    /* this works because minimum stack every allocated is 8 bytes */
4482    /* PORTABILITY - stack must always be at least 8 bytes */
4483    memcpy(xsp1->ap, &d1, sizeof(double));
4484    __pop_xstk();
4485    return;
4486   case  /* - */ MINUS:
4487    if (op1b == 0L && op2b == 0L)
4488     {
4489      rtb = 0L;
4490      /* SJM 09/30/03 - need signed for c signed - (hardware sign xtnd) */
4491      if (!nd_signop)
4492       {
4493        rta = op1a + op2a;
4494        rta = (op1a - op2a) & mask;
4495       }
4496      /* since know 32 bits, no need to mask */
4497      else
4498       {
4499        /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */
4500        if (ndp->lu.x->szu.xclen != WBITS)
4501         {
4502          /* complex narrower than 32 bit signed case - sign extend to c int */
4503          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4504           op1a |= ~(__masktab[xsp1->xslen]);
4505         }
4506        if (ndp->ru.x->szu.xclen != WBITS)
4507         {
4508          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4509           op2a |= ~(__masktab[xsp2->xslen]);
4510         }
4511        rta = (word32) ((((sword32) op1a) - ((sword32) op2a)) & mask);
4512       }
4513     }
4514    else rta = rtb = mask;
4515    break;
4516   case /* - real */ REALMINUS:
4517    lx = ndp->lu.x;
4518    rx = ndp->ru.x;
4519    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4520    else memcpy(&d1, xsp1->ap, sizeof(double));
4521 
4522    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4523    else memcpy(&d2, xsp2->ap, sizeof(double));
4524    d1 -= d2;
4525    /* notice never a size change since both must be real */
4526    memcpy(xsp1->ap, &d1, sizeof(double));
4527    __pop_xstk();
4528    return;
4529   case /* * */ TIMES:
4530    if (op1b != 0L || op2b != 0L) rta = rtb = mask;
4531    else
4532     {
4533      /* SJM 09/30/03 - need ints for c signed op to work */
4534      if (!nd_signop) rta = (op1a * op2a) & mask;
4535      /* never need to mask for 32 bits */
4536      /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */
4537      else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
4538       rta = (word32) (((sword32) op1a) * ((sword32) op2a));
4539      else
4540       {
4541        /* SJM 10/22/03 - LOOKATME - think this must use sign/magnitude */
4542        /* complex narrower than 32 bit signed case */
4543        has_sign = FALSE;
4544        /* 2's complement makes positive if needed */
4545        if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4546         {
4547          /* since c - of cast to int can only handle 32 bit ints, sign xtnd */
4548          op1a |= ~(__masktab[xsp1->xslen]);
4549          op1a = (word32) (-((sword32) op1a));
4550          has_sign = TRUE;
4551         }
4552        if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4553         {
4554          /* since c - of cast to int can only handle 32 bit ints, sign xtnd */
4555          op2a |= ~(__masktab[xsp2->xslen]);
4556          op2a = (word32) (-((sword32) op2a));
4557          has_sign = !has_sign;
4558         }
4559 
4560        /* know op1a and op2a positive */
4561        rta = op1a * op2a;
4562        if (has_sign) rta = (word32) (-((sword32) rta));
4563        /* must mask so product fits in widest operand size */
4564        rta &= mask;
4565       }
4566      rtb = 0;
4567     }
4568    break;
4569   case /* * real */ REALTIMES:
4570    lx = ndp->lu.x;
4571    rx = ndp->ru.x;
4572    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4573    else memcpy(&d1, xsp1->ap, sizeof(double));
4574 
4575    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4576    else memcpy(&d2, xsp2->ap, sizeof(double));
4577 
4578    /* notice never a size change since both must be real */
4579    d1 *= d2;
4580    memcpy(xsp1->ap, &d1, sizeof(double));
4581    __pop_xstk();
4582    return;
4583   case /* / */ DIV:
4584    if (op1b != 0L || op2b != 0L || op2a == 0L) rta = rtb = mask;
4585    /* case 1: unsigned */
4586    else if (!nd_signop) rta = op1a / op2a;
4587    /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */
4588    else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
4589     {
4590      /* case 2 signed but int32 so can use c casts */
4591      rta = (word32) ((sword32) op1a / (sword32) op2a);
4592      rtb = 0L;
4593      /* SJM 05/13/04 - no need to mask since know WBITS */
4594     }
4595    else
4596     {
4597      /* SJM 10/22/03 - must extract signs (sign of result from 1st) */
4598      /* and do operation word32 and then put back sign */
4599      if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4600       {
4601        /* SJM 05/13/04 - must sign extend to WBITS int32 size */
4602        op1a = op1a | ~(__masktab[xsp1->xslen]);
4603        op1a = (word32) (-((sword32) op1a));
4604        has_sign = TRUE;
4605       }
4606      else has_sign = FALSE;
4607 
4608      /* for mod, first operand determines sign of result */
4609      if ((op2a & (1 <<( xsp2->xslen - 1))) != 0)
4610       {
4611        /* SJM 05/13/04 - must sign extend to WBITS int32 size */
4612        op2a = op2a | ~(__masktab[xsp2->xslen]);
4613        op2a = (word32) (-((sword32) op2a));
4614        /* sign combination rules for div same as mult */
4615        has_sign = !has_sign;
4616       }
4617 
4618      /* know op1a and op2a positive */
4619      rta = op1a / op2a;
4620      /* if result signed, first comp WBITS signed - */
4621      if (has_sign) rta = (word32) (-((sword32) rta));
4622      rta &= mask;
4623      rtb = 0L;
4624     }
4625    break;
4626   case /* * real */ REALDIV:
4627    lx = ndp->lu.x;
4628    rx = ndp->ru.x;
4629    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4630    else memcpy(&d1, xsp1->ap, sizeof(double));
4631 
4632    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4633    else memcpy(&d2, xsp2->ap, sizeof(double));
4634 
4635    /* notice never a size change since both must be real */
4636    d1 /= d2;
4637    memcpy(xsp1->ap, &d1, sizeof(double));
4638    __pop_xstk();
4639    return;
4640   case /* % */ MOD:
4641    if (op1b != 0L || op2b != 0L || op2a == 0L) rta = rtb = mask;
4642    /* case 1: unsigned */
4643    else if (!nd_signop) rta = op1a % op2a;
4644    /* SJM 09/29/04 - but do need to mask if either operand not 32 bits */
4645    else if (ndp->lu.x->szu.xclen == WBITS && ndp->ru.x->szu.xclen == WBITS)
4646     {
4647      /* case 2 signed but int32 so can use c casts */
4648      /* case 2 signed but int32 so can use c casts */
4649      rta = (word32) ((sword32) op1a % (sword32) op2a);
4650      rtb = 0L;
4651      /* think value narrower but needed for signed */
4652      rta &= mask;
4653     }
4654    else
4655     {
4656      /* SJM 10/22/03 - must extract signs (sign of result from 1st) */
4657      /* and do operation word32 and then put back sign */
4658      if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4659       {
4660        /* SJM 05/13/04 - must sign extend to WBITS int32 size */
4661        op1a = op1a | ~(__masktab[xsp1->xslen]);
4662        /* AIV 10/12/06 - forgot to do the sign cast */
4663        op1a = (word32) (-((sword32) op1a));
4664        has_sign = TRUE;
4665       }
4666      else has_sign = FALSE;
4667 
4668      /* for mod, first operand determines sign of result */
4669      if ((op2a & (1 <<( xsp2->xslen - 1))) != 0)
4670       {
4671        /* SJM 05/13/04 - must sign extend to WBITS int32 size */
4672        op2a = op2a | ~(__masktab[xsp2->xslen]);
4673        op2a = (word32) (-((sword32) op2a));
4674       }
4675 
4676      /* know op1a and op2a positive */
4677      rta = op1a % op2a;
4678      if (has_sign) rta = (word32) (-((sword32) rta));
4679      rta &= mask;
4680      rtb = 0L;
4681     }
4682    break;
4683   case /* & */ BITREDAND:
4684    /* idea is if both op1b and op2b 1 (x), need rta to be 1 for x result */
4685    if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a & op2a); }
4686    else
4687     {
4688      rta = (op1a | op1b) & (op2a | op2b);
4689      rtb = rta & (op2b | op1b);
4690     }
4691    break;
4692   case /* | */ BITREDOR:
4693    if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a | op2a); }
4694    else
4695     {
4696      rtb = op2b ^ op1b ^ ((op1a | op1b) & (op2b | (op2a & op1b)));
4697      rta = rtb | op2a | op1a;
4698     }
4699    break;
4700   case /* ^ */ BITREDXOR:
4701    /* know same width so high non 0 never possible */
4702    if ((op1b | op2b) == 0L) { rtb = 0L; rta = (op1a ^ op2a); }
4703    else { rtb = op1b | op2b; rta = rtb | (op1a ^ op2a);  }
4704    break;
4705   case /* not ^ */ REDXNOR:
4706    /* since same length, xor 0 0 is 1, not of 1 is 0 so works */
4707    if ((op1b | op2b) == 0L)
4708     { rtb = 0L; rta = ~(op1a ^ op2a) & mask; }
4709    else
4710     /* must mask here because 0 xnor 0 is 1 for high unused bits */
4711     { rtb = op1b | op2b; rta = (rtb | ~(op1a ^ op2a)) & mask; }
4712    break;
4713   case /* >= */ RELGE:
4714    if ((op1b | op2b) == 0L)
4715     {
4716      rtb = 0L;
4717      /* C result for true is always 1 */
4718      if (nd_signop)
4719       {
4720        /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
4721        /* SJM 05/13/04 - width is opand not result width */
4722        if (xsp1->xslen < WBITS)
4723         {
4724          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4725           op1a |= ~(__masktab[xsp1->xslen]);
4726         }
4727        if (xsp2->xslen < WBITS)
4728         {
4729          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4730           op2a |= ~(__masktab[xsp2->xslen]);
4731         }
4732        rta = (word32) (((sword32) op1a) >= ((sword32) op2a));
4733       }
4734      else rta = op1a >= op2a;
4735     }
4736    else rta = rtb = 1L;
4737    break;
4738   case /* >= real */ REALRELGE:
4739    lx = ndp->lu.x;
4740    rx = ndp->ru.x;
4741    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4742    else memcpy(&d1, xsp1->ap, sizeof(double));
4743 
4744    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4745    else memcpy(&d2, xsp2->ap, sizeof(double));
4746 
4747    rta = (d1 >= d2) ? 1L : 0L;
4748    rtb = 0L;
4749    break;
4750   case /* > */ RELGT:
4751    if ((op1b | op2b)== 0L)
4752     {
4753      rtb = 0L;
4754      if (nd_signop)
4755       {
4756        /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
4757        /* SJM 05/13/04 - width is opand not result width */
4758        if (xsp1->xslen < WBITS)
4759         {
4760          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4761           op1a |= ~(__masktab[xsp1->xslen]);
4762         }
4763        if (xsp2->xslen < WBITS)
4764         {
4765          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4766           op2a |= ~(__masktab[xsp2->xslen]);
4767         }
4768        rta = (word32) (((sword32) op1a) > ((sword32) op2a));
4769       }
4770      else rta = op1a > op2a;
4771     }
4772    else rta = rtb = 1L;
4773    break;
4774   case /* > real */ REALRELGT:
4775    lx = ndp->lu.x;
4776    rx = ndp->ru.x;
4777    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4778    else memcpy(&d1, xsp1->ap, sizeof(double));
4779    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4780    else memcpy(&d2, xsp2->ap, sizeof(double));
4781    rta = (d1 > d2) ? 1L : 0L;
4782    rtb = 0L;
4783    break;
4784   case /* <= */ RELLE:
4785    if ((op1b | op2b) == 0L)
4786     {
4787      rtb = 0L;
4788      if (nd_signop)
4789       {
4790        /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
4791        /* SJM 05/13/04 - width is opand not result width */
4792        if (xsp1->xslen < WBITS)
4793         {
4794          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4795           op1a |= ~(__masktab[xsp1->xslen]);
4796         }
4797        if (xsp2->xslen < WBITS)
4798         {
4799          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4800           op2a |= ~(__masktab[xsp2->xslen]);
4801         }
4802        rta = (word32) (((sword32) op1a) <= ((sword32) op2a));
4803       }
4804      else rta = op1a <= op2a;
4805     }
4806    else rta = rtb = 1L;
4807    break;
4808   case /* <= real */ REALRELLE:
4809    lx = ndp->lu.x;
4810    rx = ndp->ru.x;
4811    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4812    else memcpy(&d1, xsp1->ap, sizeof(double));
4813    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4814    else memcpy(&d2, xsp2->ap, sizeof(double));
4815    rta = (d1 <= d2) ? 1L : 0L;
4816    rtb = 0L;
4817    break;
4818   case /* < */ RELLT:
4819    if ((op1b | op2b) == 0L)
4820     {
4821      rtb = 0L;
4822      if (nd_signop)
4823       {
4824        /* SJM 10/22/03 - easiest here to just sign extend - does it work? */
4825        /* SJM 05/13/04 - width is opand not result width */
4826        if (xsp1->xslen < WBITS)
4827         {
4828          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4829           op1a |= ~(__masktab[xsp1->xslen]);
4830         }
4831        if (xsp2->xslen < WBITS)
4832         {
4833          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4834           op2a |= ~(__masktab[xsp2->xslen]);
4835         }
4836        rta = (word32) (((sword32) op1a) < ((sword32) op2a));
4837       }
4838      else rta = op1a < op2a;
4839     }
4840    else rta = rtb = 1L;
4841    break;
4842   case /* < real */ REALRELLT:
4843    lx = ndp->lu.x;
4844    rx = ndp->ru.x;
4845    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4846    else memcpy(&d1, xsp1->ap, sizeof(double));
4847 
4848    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4849    else memcpy(&d2, xsp2->ap, sizeof(double));
4850    /* notice never a size change since both must be real */
4851    rta = (d1 < d2) ? 1L : 0L;
4852    rtb = 0L;
4853    break;
4854   case /* != */ RELNEQ:
4855 
4856    if ((op1b | op2b) == 0L)
4857     {
4858      if (nd_signop)
4859       {
4860        /* SJM 05/13/04 - width is opand not result width */
4861        if (xsp1->xslen < WBITS)
4862         {
4863          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4864           op1a |= ~(__masktab[xsp1->xslen]);
4865         }
4866        if (xsp2->xslen < WBITS)
4867         {
4868          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4869           op2a |= ~(__masktab[xsp2->xslen]);
4870         }
4871       }
4872      rtb = 0L;
4873      rta = (op1a != op2a);
4874      break;
4875     }
4876 
4877    /* SJM 06/16/00 - was wrong for x cases because if non equal where both */
4878    /* operands non x/z, should be 0 not unknown */
4879    /* new algorithm - if compare with a parts all x/z bits set to 1 */
4880    /* not equal then x/z bits can not effect not equal result */
4881    /* know at least one bit x/z to get here */
4882 
4883    if (nd_signop)
4884     {
4885      /* SJM 05/13/04 - width is opand not result width */
4886      if (xsp1->xslen < WBITS)
4887       {
4888        if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4889         op1a |= ~(__masktab[xsp1->xslen]);
4890        /* if any x/z bits must x/z extned if signed */
4891        if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
4892         op1b |= ~(__masktab[xsp1->xslen]);
4893       }
4894      if (xsp2->xslen < WBITS)
4895       {
4896        if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4897         op2a |= ~(__masktab[xsp2->xslen]);
4898        if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
4899         op2b |= ~(__masktab[xsp2->xslen]);
4900       }
4901     }
4902    if ((op1a | (op1b | op2b)) != (op2a | (op1b | op2b)))
4903     { rtb = 0L; rta = 1L; }
4904    else rta = rtb = 1L;
4905    break;
4906   case /* != real */ REALRELNEQ:
4907    lx = ndp->lu.x;
4908    rx = ndp->ru.x;
4909    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4910    else memcpy(&d1, xsp1->ap, sizeof(double));
4911 
4912    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4913    else memcpy(&d2, xsp2->ap, sizeof(double));
4914 
4915    /* notice never a size change since both must be real */
4916    /* this is ieee float point dependent */
4917    rta = (fabs(d1 - d2) >= EPSILON) ? 1L : 0L;
4918    rtb = 0L;
4919    break;
4920   case /* == */ RELEQ:
4921    /* relation true in C is always 1 */
4922    if ((op1b | op2b) == 0L)
4923     {
4924      if (nd_signop)
4925       {
4926        /* SJM 05/13/04 - width is opand not result width */
4927        if (xsp1->xslen < WBITS)
4928         {
4929          if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4930           op1a |= ~(__masktab[xsp1->xslen]);
4931         }
4932        if (xsp2->xslen < WBITS)
4933         {
4934          if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4935           op2a |= ~(__masktab[xsp2->xslen]);
4936         }
4937       }
4938      rtb = 0L;
4939      rta = (op1a == op2a);
4940      break;
4941     }
4942 
4943    /* SJM 06/16/00 - wrong for x cases because if non equal where both */
4944    /* operands non x/z, should be 0 not unknown */
4945    /* new algorithm - if compare with a parts all x/z bits set to 1 */
4946    /* not equal then x/z bits can not effect not equal result */
4947    /* know at least one bit x/z to get here */
4948 
4949    if (nd_signop)
4950     {
4951      /* SJM 05/13/04 - width is opand not result width */
4952      if (xsp1->xslen < WBITS)
4953       {
4954        if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4955         op1a |= ~(__masktab[xsp1->xslen]);
4956        /* if any x/z bits must x/z extned if signed */
4957        if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
4958         op1b |= ~(__masktab[xsp1->xslen]);
4959       }
4960      if (xsp2->xslen < WBITS)
4961       {
4962        if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
4963         op2a |= ~(__masktab[xsp2->xslen]);
4964        if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
4965         op2b |= ~(__masktab[xsp2->xslen]);
4966       }
4967     }
4968 
4969    if ((op1a | (op1b | op2b)) != (op2a | (op1b | op2b)))
4970     { rtb = 0L; rta = 0L; }
4971    else rta = rtb = 1L;
4972    break;
4973   case /* == real */ REALRELEQ:
4974    lx = ndp->lu.x;
4975    rx = ndp->ru.x;
4976    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
4977    else memcpy(&d1, xsp1->ap, sizeof(double));
4978    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
4979    else memcpy(&d2, xsp2->ap, sizeof(double));
4980    /* notice never a size change since both must be real */
4981    /* this is ieee float point dependent */
4982    rta = (fabs(d1 - d2) >= EPSILON) ? 0L : 1L;
4983    rtb = 0L;
4984    break;
4985   case /* === */ RELCEQ:
4986 
4987    if (nd_signop)
4988     {
4989      /* SJM 05/13/04 - width is opand not result width */
4990      if (xsp1->xslen < WBITS)
4991       {
4992        if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
4993         op1a |= ~(__masktab[xsp1->xslen]);
4994        /* if any x/z bits must x/z extned if signed */
4995        if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
4996         op1b |= ~(__masktab[xsp1->xslen]);
4997       }
4998      if (xsp2->xslen < WBITS)
4999       {
5000        if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
5001         op2a |= ~(__masktab[xsp2->xslen]);
5002        if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
5003         op2b |= ~(__masktab[xsp2->xslen]);
5004       }
5005     }
5006    rtb = 0L;
5007    /* works without masking since semantics requires 0 extending */
5008    rta = (0L == ((op1a ^ op2a) | (op1b ^ op2b)));
5009    break;
5010   case /* !== */ RELCNEQ:
5011 
5012    if (nd_signop)
5013     {
5014      /* SJM 05/13/04 - width is opand not result width */
5015      if (xsp1->xslen < WBITS)
5016       {
5017        if ((op1a & (1 << (xsp1->xslen - 1))) != 0)
5018         op1a |= ~(__masktab[xsp1->xslen]);
5019        /* if any x/z bits must x/z extned if signed */
5020        if ((op1b & (1 << (xsp1->xslen - 1))) != 0)
5021         op1b |= ~(__masktab[xsp1->xslen]);
5022       }
5023      if (xsp2->xslen < WBITS)
5024       {
5025        if ((op2a & (1 << (xsp2->xslen - 1))) != 0)
5026         op2a |= ~(__masktab[xsp2->xslen]);
5027        if ((op2b & (1 << (xsp2->xslen - 1))) != 0)
5028         op2b |= ~(__masktab[xsp2->xslen]);
5029       }
5030     }
5031    rtb = 0L;
5032    /* works without masking since semantics requires 0 extending */
5033    rta = (0L != ((op1a ^ op2a) | (op1b ^ op2b)));
5034    break;
5035   case /* && */ BOOLAND:
5036    /* notice this complicated algorithm is needed because if a bit */
5037    /* is some position is 0 other bit does not matter - i.e. this is */
5038    /* really 32 bool ands */
5039    rtb = 0L;
5040    tmp1 = cvt_wrdbool_(op1a, op1b);
5041    if (tmp1 == 0) { rta = 0L; break; }
5042    tmp2 = cvt_wrdbool_(op2a, op2b);
5043    if (tmp2 == 0) { rta = 0L; break; }
5044    if (tmp1 == 1 && tmp2 == 1) rta = 1L; else rta = rtb = 1L;
5045    break;
5046   case /* && real */ REALBOOLAND:
5047    lx = ndp->lu.x;
5048    rx = ndp->ru.x;
5049    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5050    else memcpy(&d1, xsp1->ap, sizeof(double));
5051    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5052    else memcpy(&d2, xsp2->ap, sizeof(double));
5053    /* notice never a size change since both must be real */
5054    rta = (d1 != 0.0 && d2 != 0.0) ? 1L : 0L;
5055    rtb = 0L;
5056    break;
5057   case /* || */ BOOLOR:
5058    rtb = 0L;
5059    tmp1 = cvt_wrdbool_(op1a, op1b);
5060    if (tmp1 == 1) { rta = 1L; break; }
5061    tmp2 = cvt_wrdbool_(op2a, op2b);
5062    if (tmp2 == 1) { rta = 1L; break; }
5063    /* if not both 0, some bit x&x or x&1 */
5064    if (tmp1 == 0 && tmp2 == 0) rta = 0L; else rta = rtb = 1L;
5065    break;
5066   case /* && real */ REALBOOLOR:
5067    lx = ndp->lu.x;
5068    rx = ndp->ru.x;
5069    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5070    else memcpy(&d1, xsp1->ap, sizeof(double));
5071    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5072    else memcpy(&d2, xsp2->ap, sizeof(double));
5073 
5074    /* notice never a size change since both must be real */
5075    rta = (d1 != 0.0 || d2 != 0.0) ? 1L : 0L;
5076    rtb = 0L;
5077    break;
5078   case /* << */ SHIFTL:
5079   case /* <<< */ ASHIFTL:
5080    /* if shift amt x/z, result is 0 */
5081    if (op2b != 0L) rtb = rta = mask;
5082    /* if shift length wider than op1, result is 0 */
5083    /* 2nd shift width operand is interpreted as range index (word32) */
5084    /* AIV 03/14/06 - shift >= set to zero */
5085    else if (op2a >= (word32) opwid) rtb = rta = 0L;
5086    else
5087     {
5088      if (nd_signop && xsp1->xslen < ndp->szu.xclen)
5089       {
5090        __sgn_xtnd_wrd(xsp1, ndp->szu.xclen);
5091        op1a = xsp1->ap[0];
5092        op1b = xsp1->bp[0];
5093       }
5094      rtb = (op1b << op2a) & mask;
5095      rta = (op1a << op2a) & mask;
5096     }
5097    break;
5098   case /* >> */ SHIFTR:
5099    /* SJM 09/30/03 - logical shift right stays same even if sign bit 1 */
5100    /* if shift amt x/z, result is 0 */
5101    if (op2b != 0L) rtb = rta = mask;
5102    /* AIV 03/14/06 - shift >= set to zero */
5103    else if (op2a >= (word32) ndp->szu.xclen)
5104     {
5105      /* if shift length wider than op1, result is 0 */
5106      /* 2nd shift width operand is interpreted as range index (word32) */
5107      rtb = rta = 0L;
5108     }
5109    else
5110     {
5111      /* notice no need to mask since 0's injected into high bits */
5112      rtb = op1b >> op2a;
5113      rta = op1a >> op2a;
5114      }
5115    break;
5116   case /* >>> */ ASHIFTR:
5117    /* SJM 09/30/03 - arithmetic shift right inserts sign bit if on not 0 */
5118    /* if shift amt x/z, result is x */
5119    if (op2b != 0L)
5120     {
5121      rtb = rta = mask;
5122     }
5123    /* AIV 03/14/06 - shift >= set to zero */
5124    else if (op2a >= (word32) ndp->szu.xclen)
5125     {
5126      /* 2nd shift width operand is interpreted as range index (word32) */
5127      /* notice if word32, no sign bit */
5128      if (nd_signop)
5129       {
5130        if ((op1a & (1 << (ndp->szu.xclen - 1))) != 0)
5131         {
5132          /* since shift amount wider than var, if sign bit on */
5133          /* 1's shifted into each bit position, else 0 */
5134          rta = mask;
5135          rtb = 0;
5136         }
5137        else rta = rtb = 0;
5138       }
5139      else rtb = rta = 0L;
5140     }
5141    else
5142     {
5143      /* notice no need to mask since 0's injected into high bits */
5144      if (nd_signop)
5145       {
5146        /* SJM 05/10/04 - could use c signed arithmetic shift for WBITS wide */
5147        /* SJM for word32 arithmetic right shift use c arithmetic shift */
5148        /* AIV 06/02/05 - if shift amt is wrong for 0 - don't mask */
5149        if (op2a != 0 && (op1a & (1 << (ndp->szu.xclen - 1))) != 0)
5150         {
5151          /* first shift as if 0 bits then or in the bits shifted in from */
5152          /* injected sign bits */
5153          rta = (word32) (op1a >> op2a);
5154          rtb = (word32) (op1b >> op2a);
5155          rta |= (__masktab[op2a] << (ndp->szu.xclen - op2a));
5156         }
5157        else
5158         {
5159          /* if sign bit off - same as logical right shift */
5160          rta = (word32) (op1a >> op2a);
5161          rtb = (word32) (op1b >> op2a);
5162         }
5163       }
5164      else
5165       {
5166        rtb = op1b >> op2a;
5167        rta = op1a >> op2a;
5168       }
5169     }
5170    break;
5171   default: __case_terr(__FILE__, __LINE__);
5172  }
5173  /* DB remove after debugged ---
5174  if ((rta & ~mask) != 0L || (rtb & ~mask) != 0L)
5175   {
5176    __pv_warn(528,
5177     "INTERNAL - binary op truncation wrong - width %d, av=%lx,bv=%lx",
5178     ndp->szu.xclen, rta, rtb);
5179   }
5180  --- */
5181  xsp1->ap[0] = rta;
5182  xsp1->bp[0] = rtb;
5183  xsp1->xslen = ndp->szu.xclen;
5184  __pop_xstk();
5185 }
5186 
5187 /*
5188  * ROUTINES FOR WIDE BINARY OPERATORS
5189  */
5190 
5191 /*
5192  * evaluate binary operators where at least 1 operand wider than 32
5193  * what about 1 extension here and in <32 case
5194  * notice operation must be done in wider of operands and then copied
5195  * if needed
5196  *
5197  * this expects 2 operands on tos and leaves 1 result on tos
5198  * xsp2 is above xsp1 and arith routines called from here need 3 on stack
5199  * wider than 32 never signed - no checking
5200  */
5201 static void eval_wide_binary(struct expr_t *ndp, register struct xstk_t *xsp1,
5202  register struct xstk_t *xsp2)
5203 {
5204  register word32 rta, rtb;
5205  int32 isxz, cmpval, tmp1, tmp2, nd_signop;
5206  word32 shiftamt;
5207  struct xstk_t *xspr;
5208  struct expr_t *lx, *rx;
5209  double d1, d2;
5210 
5211  if (ndp->has_sign || ndp->rel_ndssign) nd_signop = TRUE;
5212  else nd_signop = FALSE;
5213 
5214  /* impossible for both operands <32 but result > 32 */
5215  switch ((byte) ndp->optyp) {
5216   case /* + */ PLUS:
5217   case /* - */ MINUS:
5218   case /* * */ TIMES:
5219   case /* / */ DIV:
5220   case /* % */ MOD:
5221    /* SJM 09/30/03 - change to handle sign extension and separate types */
5222    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5223    else if (xsp1->xslen < ndp->szu.xclen)
5224     {
5225      /* if any signed all will be */
5226      if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
5227      else __sizchg_widen(xsp1, ndp->szu.xclen);
5228     }
5229    if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
5230    else if (xsp2->xslen < ndp->szu.xclen)
5231     {
5232      /* if any signed all will be */
5233      if (ndp->has_sign) __sgn_xtnd_widen(xsp2, ndp->szu.xclen);
5234      else __sizchg_widen(xsp2, ndp->szu.xclen);
5235     }
5236 
5237    if (__set_binxresult(xsp1->ap, xsp1->bp, xsp1->bp, xsp2->bp,
5238      ndp->szu.xclen))
5239     {
5240      __pop_xstk();
5241      return;
5242     }
5243 
5244    /* for 0 divisor, result is x */
5245    if ((ndp->optyp == DIV || ndp->optyp == MOD)
5246     && vval_is0_(xsp2->ap, xsp2->xslen))
5247     {
5248      one_allbits_(xsp1->ap, xsp1->xslen);
5249      one_allbits_(xsp1->bp, xsp1->xslen);
5250      __pop_xstk();
5251      return;
5252     }
5253    /* in routine will fill all of xspr with value - no need to init */
5254    push_xstk_(xspr, ndp->szu.xclen);
5255    /* add/sub to accumulator */
5256    /* SJM 09/30/03 - since using sign mult and div others 2 complement work */
5257    switch ((byte) ndp->optyp) {
5258     case /* + */ PLUS:
5259      __ladd(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
5260      break;
5261     case /* - */ MINUS:
5262      __lsub(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
5263      break;
5264     case /* * */ TIMES:
5265      /* SJM 09/30/03 - need wapper for signed since wide needs positive */
5266      if (ndp->has_sign)
5267       __sgn_lmult(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
5268      else __lmult(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen);
5269      break;
5270     case /* / */ DIV:
5271      /* SJM 09/30/03 - need wapper for signed since wide needs positive */
5272      if (ndp->has_sign)
5273       __sgn_ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, TRUE);
5274      else __ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, TRUE);
5275      break;
5276     case /* % */ MOD:
5277      /* SJM 09/30/03 - need wapper for signed since wide needs positive */
5278      if (ndp->has_sign)
5279       __sgn_ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, FALSE);
5280       else __ldivmod(xspr->ap, xsp1->ap, xsp2->ap, xspr->xslen, FALSE);
5281      break;
5282     default: __case_terr(__FILE__, __LINE__);
5283    }
5284    /* zero result b value */
5285    zero_allbits_(xspr->bp, xspr->xslen);
5286    /* move result down 2 and then pop top 2 (old tmp result and op2) */
5287    xchg_stk(__xspi - 2, __xspi);
5288    __pop_xstk();
5289    __pop_xstk();
5290    break;
5291   case /* << */ SHIFTL:
5292   case /* >>> */ ASHIFTL:
5293   case /* >> */ SHIFTR:
5294    /* this replaces top 2 args with shifted result replacing 2nd down */
5295    /* if shift width has any x/z's, even if will be truncated, result x */
5296    /* need to widen from context before shift - need overflow bits */
5297 
5298    /* SJM 09/29/03 - change to handle sign extension but left arithmetic */
5299    /* shift same as left logical shift (only change is signed widening) */
5300    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5301    else if (xsp1->xslen < ndp->szu.xclen)
5302     {
5303      if (ndp->has_sign) __sgn_xtnd_widen(xsp1, ndp->szu.xclen);
5304      else __sizchg_widen(xsp1, ndp->szu.xclen);
5305     }
5306 
5307    if (!vval_is0_(xsp2->bp, xsp2->xslen))
5308     {
5309      one_allbits_(xsp1->ap, xsp1->xslen);
5310      one_allbits_(xsp1->bp, xsp1->xslen);
5311     }
5312    else
5313     {
5314      /* if op value is 0 or shift amount wider than op */
5315      /* SJM 12/28/98 - this was wrongly checking first word32 of long */
5316      /* SJM 03/28/03 - for shift of case with only z's in op1 was wrong */
5317      /* because if a part 0 but b part 1 (z in val) wrongly setting to 0 */
5318      if ((vval_is0_(xsp1->ap, xsp1->xslen)
5319       && vval_is0_(xsp1->bp, xsp1->xslen))
5320       || (xsp2->xslen > WBITS && !vval_is0_(&(xsp2->ap[1]),
5321        xsp2->xslen - WBITS)) || xsp2->ap[0] >= (word32) xsp1->xslen)
5322        memset(xsp1->ap, 0, 2*WRDBYTES*wlen_(xsp1->xslen));
5323      else
5324       {
5325        if ((shiftamt = xsp2->ap[0]) != 0)
5326         {
5327          if (vval_is0_(xsp1->bp, xsp1->xslen)) isxz = FALSE;
5328          else isxz = TRUE;
5329          if (ndp->optyp != SHIFTR)
5330           {
5331            __mwlshift(xsp1->ap, shiftamt, xsp1->xslen);
5332            if (isxz) __mwlshift(xsp1->bp, shiftamt, xsp1->xslen);
5333           }
5334          else
5335           {
5336            __mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
5337            if (isxz) __mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
5338           }
5339         }
5340       }
5341     }
5342    __pop_xstk();
5343    break;
5344   case /* >>> */ ASHIFTR:
5345    /* SJM 05/11/04 - split arithmetic right shift off */
5346    /* main different is that if sign bit on, need to shift in 1's for both */
5347    /* a and b parts */
5348    /* SJM 05/11/04 - notice that shift amount always treated as word32, */
5349    /* i.e. no minus opposite direction shifts */
5350    if (!vval_is0_(xsp2->bp, xsp2->xslen))
5351     {
5352      one_allbits_(xsp1->ap, xsp1->xslen);
5353      one_allbits_(xsp1->bp, xsp1->xslen);
5354      goto ashift_pop;
5355     }
5356    if (vval_is0_(xsp1->ap, xsp1->xslen) && vval_is0_(xsp1->bp, xsp1->xslen))
5357     {
5358      /* opand 1 value 0 - shift can't change */
5359      memset(xsp1->ap, 0, 2*WRDBYTES*wlen_(xsp1->xslen));
5360      goto ashift_pop;
5361     }
5362    if ((xsp2->xslen > WBITS && !vval_is0_(&(xsp2->ap[1]),
5363     xsp2->xslen - WBITS)) || xsp2->ap[0] >= (word32) xsp1->xslen)
5364     {
5365      int32 bi, wlen;
5366 
5367      /* shift amount wider than value */
5368      bi = get_bofs_(xsp1->xslen);
5369      wlen = wlen_(xsp1->xslen);
5370 
5371      /* SJM 06/20/04 - if right ashift opand word32 - no sign extend */
5372      if (ndp->has_sign && (xsp1->ap[wlen - 1] & (1 << bi)) != 0)
5373       {
5374        /* since shift amount wider than var, if sign bit on */
5375        /* 1's shifted into each bit position, i.e. set all bits to 1 */
5376        one_allbits_(xsp1->ap, xsp1->xslen);
5377       }
5378      else memset(xsp1->ap, 0, 2*WRDBYTES*wlen);
5379 
5380      /* if b part high bit on, all bits become x/z */
5381      if (ndp->has_sign && (xsp1->bp[wlen - 1] & (1 << bi)) != 0)
5382       {
5383        one_allbits_(xsp1->bp, xsp1->xslen);
5384       }
5385      else memset(xsp1->ap, 0, 2*WRDBYTES*wlen);
5386      goto ashift_pop;
5387     }
5388    if ((shiftamt = xsp2->ap[0]) != 0)
5389     {
5390      if (vval_is0_(xsp1->bp, xsp1->xslen)) isxz = FALSE;
5391      else isxz = TRUE;
5392 
5393      if (nd_signop)
5394       {
5395        __arith_mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
5396        if (isxz) __arith_mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
5397       }
5398      else
5399       {
5400        /* arithmetic right shift for word32 same as logical */
5401        __mwrshift(xsp1->ap, shiftamt, xsp1->xslen);
5402        if (isxz) __mwrshift(xsp1->bp, shiftamt, xsp1->xslen);
5403       }
5404     }
5405 ashift_pop:
5406    __pop_xstk();
5407    break;
5408   /* binary of these is bit by bit not reducing and ndp width is needed */
5409   case /* & */ BITREDAND:
5410    /* SJM 09/29/03 - change to handle sign extension and separate types */
5411    /* AIV 10/13/06 - need to ignore sign here */
5412    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5413    else if (xsp1->xslen < ndp->szu.xclen) __sizchg_widen(xsp1, ndp->szu.xclen);
5414 
5415    if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
5416    else if (xsp2->xslen < ndp->szu.xclen) __sizchg_widen(xsp2, ndp->szu.xclen);
5417 
5418    __lbitand(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
5419    __pop_xstk();
5420    break;
5421   case /* | */ BITREDOR:
5422    /* SJM 09/29/03 - change to handle sign extension and separate types */
5423    /* AIV 10/13/06 - need to ignore sign here */
5424    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5425    else if (xsp1->xslen < ndp->szu.xclen) __sizchg_widen(xsp1, ndp->szu.xclen);
5426 
5427    if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
5428    else if (xsp2->xslen < ndp->szu.xclen) __sizchg_widen(xsp2, ndp->szu.xclen);
5429 
5430    __lbitor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
5431    __pop_xstk();
5432    break;
5433   case /* ^ */ BITREDXOR:
5434    /* SJM 09/29/03 - change to handle sign extension and separate types */
5435    /* AIV 10/13/06 - need to ignore sign here */
5436    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5437    else if (xsp1->xslen < ndp->szu.xclen) __sizchg_widen(xsp1, ndp->szu.xclen);
5438 
5439    if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
5440    else if (xsp2->xslen < ndp->szu.xclen) __sizchg_widen(xsp2, ndp->szu.xclen);
5441 
5442    __lbitxor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
5443    __pop_xstk();
5444    break;
5445   case /* ^~ */ REDXNOR:
5446    /* SJM 09/29/03 - change to handle sign extension and separate types */
5447    /* AIV 10/13/06 - need to ignore sign here */
5448    if (xsp1->xslen > ndp->szu.xclen) __narrow_sizchg(xsp1, ndp->szu.xclen);
5449    else if (xsp1->xslen < ndp->szu.xclen) __sizchg_widen(xsp1, ndp->szu.xclen);
5450 
5451    if (xsp2->xslen > ndp->szu.xclen) __narrow_sizchg(xsp2, ndp->szu.xclen);
5452    else if (xsp2->xslen < ndp->szu.xclen) __sizchg_widen(xsp2, ndp->szu.xclen);
5453 
5454    __lbitxnor(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp, xsp1->xslen);
5455    __pop_xstk();
5456    break;
5457   case /* != */ RELNEQ:
5458   case /* == */ RELEQ:
5459    /* SJM 10/16/00 - for non equal when x/z in either not counted must be */
5460    /* less pessimistic not equal */
5461    /* LOOKATME - this is complex - can it be simplified? */
5462 
5463    /* widen narrower to be same as wider - may need sign xtnd */
5464    /* SJM 05/13/04 - was wrongly using the 1 bit result not other opand */
5465    if (xsp1->xslen > xsp2->xslen)
5466     {
5467      /* SJM 05/13/04 - since result 1 bit word32 but operand cmp signed */
5468      if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
5469      else __sizchg_widen(xsp2, xsp1->xslen);
5470     }
5471    else if (xsp2->xslen > xsp1->xslen)
5472     {
5473      if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
5474      else __sizchg_widen(xsp1, xsp2->xslen);
5475     }
5476 
5477    /* result goes into 1 bit tos and know ndp xclen is 1 here */
5478    /* SJM 05/13/04 - compare can't be signed since eq */
5479    cmpval = __do_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
5480      xsp1->xslen);
5481 
5482    rtb = 0;
5483    if (isxz)
5484     {
5485      if (!__omitxz_widenoteq(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
5486       xsp1->xslen)) rtb = rta = 1L;
5487      else { if (ndp->optyp == RELEQ) rta = 0; else rta = 1; }
5488     }
5489    else
5490     {
5491      if (ndp->optyp == RELEQ) rta = (cmpval == 0); else rta = (cmpval != 0);
5492     }
5493    goto make_1bit;
5494   case /* >= */ RELGE:
5495   case /* > */ RELGT:
5496   case /* <= */ RELLE:
5497   case /* < */ RELLT:
5498    /* widen narrower to be same as wider - may need sign xtnd */
5499    /* SJM 05/13/04 - was wrongly using the 1 bit result not other opand */
5500    if (xsp1->xslen > xsp2->xslen)
5501     {
5502      /* SJM 05/13/04 - since result 1 bit word32 but operand cmp signed */
5503      if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
5504      else __sizchg_widen(xsp2, xsp1->xslen);
5505     }
5506    else if (xsp2->xslen > xsp1->xslen)
5507     {
5508      if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
5509      else __sizchg_widen(xsp1, xsp2->xslen);
5510     }
5511 
5512    /* result goes into 1 bit tos and know ndp xclen is 1 here */
5513    /* AIV 05/27/04 - must be nd sign not res node has sign since res 1 bit */
5514    if (ndp->rel_ndssign)
5515     {
5516      /* SJM 05/10/04 - wide sign compare casts to int32 on not == */
5517      cmpval = __do_sign_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap,
5518       xsp2->bp, xsp1->xslen);
5519     }
5520    else
5521     {
5522      cmpval = __do_widecmp(&isxz, xsp1->ap, xsp1->bp, xsp2->ap,
5523       xsp2->bp, xsp1->xslen);
5524     }
5525    if (isxz) { rtb = rta = 1L; goto make_1bit; }
5526    rta = rtb = 0L;
5527 
5528    switch ((byte) ndp->optyp) {
5529     case RELGE: rta = (cmpval >= 0); break;
5530     case RELGT: rta = (cmpval > 0); break;
5531     case RELLE: rta = (cmpval <= 0); break;
5532     case RELLT: rta = (cmpval < 0); break;
5533    }
5534 make_1bit:
5535    /* this is need because a and b parts must be kept contiguous */
5536    /* SJM 09/30/03 - can use simpler narrow to 1 bit */
5537    __narrow_to1bit(xsp1);
5538    xsp1->ap[0] = rta;
5539    xsp1->bp[0] = rtb;
5540    xsp1->xslen = 1;
5541    __pop_xstk();
5542    break;
5543   case /* === */ RELCEQ:
5544   case /* !== */ RELCNEQ:
5545    /* SJM 09/29/03 - only widen - can be signed */
5546    if (xsp1->xslen > xsp2->xslen)
5547     {
5548      /* only signed if both signed */
5549      if (ndp->rel_ndssign) __sgn_xtnd_widen(xsp2, xsp1->xslen);
5550      else __sizchg_widen(xsp2, xsp1->xslen);
5551     }
5552    else if (xsp2->xslen > xsp1->xslen)
5553     {
5554      if (ndp->lu.x->has_sign) __sgn_xtnd_widen(xsp1, xsp2->xslen);
5555      else __sizchg_widen(xsp1, xsp2->xslen);
5556     }
5557 
5558    /* returns 1 if not equal, 0 if equal */
5559    cmpval = __do_xzwidecmp(xsp1->ap, xsp1->bp, xsp2->ap, xsp2->bp,
5560     xsp1->xslen);
5561    rtb = 0L;
5562    if (ndp->optyp == RELCEQ) rta = (cmpval == 0); else rta = (cmpval != 0);
5563    goto make_1bit;
5564   case /* && */ BOOLAND:
5565    rtb = 0L;
5566    tmp1 = __cvt_lngbool(xsp1->ap, xsp1->bp, wlen_(xsp1->xslen));
5567    if (tmp1 == 0) { rta = 0L; goto make_1bit; }
5568    tmp2 = __cvt_lngbool(xsp2->ap, xsp2->bp, wlen_(xsp2->xslen));
5569    if (tmp2 == 0) { rta = 0L; goto make_1bit; }
5570    if (tmp1 == 1 && tmp2 == 1) rta = 1L; else rta = rtb = 1L;
5571    goto make_1bit;
5572   case /* || */ BOOLOR:
5573    rtb = 0L;
5574    tmp1 = __cvt_lngbool(xsp1->ap, xsp1->bp, wlen_(xsp1->xslen));
5575    if (tmp1 == 1) { rta = 1L; goto make_1bit; }
5576    tmp2 = __cvt_lngbool(xsp2->ap, xsp2->bp, wlen_(xsp2->xslen));
5577    if (tmp2 == 1) { rta = 1L; goto make_1bit; }
5578    if (tmp1 == 0 && tmp2 == 0) rta = 0L; else rta = rtb = 1L;
5579    goto make_1bit;
5580 
5581   /* SJM 03/01/00 - all real binaries can be wide if one wide operand and */
5582   /* other real (usually 64 bit time) - need to be converted to real and */
5583   /* evaled as real - same as non wide case be duplicated here so no */
5584   /* need for extra test in eval inner loop - the non real arg converted */
5585   /* to real */
5586   case /* + real */ REALPLUS:
5587    /* is it portable to pass 1 bit bit field? */
5588    lx = ndp->lu.x;
5589    rx = ndp->ru.x;
5590    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5591    else memcpy(&d1, xsp1->ap, sizeof(double));
5592 
5593    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5594    else memcpy(&d2, xsp2->ap, sizeof(double));
5595 
5596    /* notice never a size change since both must be real */
5597    d1 += d2;
5598    /* this works because minimum stack every allocated is 8 bytes */
5599    /* PORTABILITY - stack must always be at least 8 bytes */
5600    memcpy(xsp1->ap, &d1, sizeof(double));
5601    __pop_xstk();
5602    return;
5603   case /* - real */ REALMINUS:
5604    lx = ndp->lu.x;
5605    rx = ndp->ru.x;
5606    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5607    else memcpy(&d1, xsp1->ap, sizeof(double));
5608 
5609    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5610    else memcpy(&d2, xsp2->ap, sizeof(double));
5611    d1 -= d2;
5612    /* notice never a size change since both must be real */
5613    memcpy(xsp1->ap, &d1, sizeof(double));
5614    __pop_xstk();
5615    return;
5616   case /* * real */ REALTIMES:
5617    lx = ndp->lu.x;
5618    rx = ndp->ru.x;
5619    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5620    else memcpy(&d1, xsp1->ap, sizeof(double));
5621 
5622    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5623    else memcpy(&d2, xsp2->ap, sizeof(double));
5624    /* notice never a size change since both must be real */
5625    d1 *= d2;
5626    memcpy(xsp1->ap, &d1, sizeof(double));
5627    __pop_xstk();
5628    return;
5629   case /* * real */ REALDIV:
5630    lx = ndp->lu.x;
5631    rx = ndp->ru.x;
5632    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5633    else memcpy(&d1, xsp1->ap, sizeof(double));
5634 
5635    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5636    else memcpy(&d2, xsp2->ap, sizeof(double));
5637    /* notice never a size change since both must be real */
5638    d1 /= d2;
5639    memcpy(xsp1->ap, &d1, sizeof(double));
5640    __pop_xstk();
5641    return;
5642   case /* >= real */ REALRELGE:
5643    lx = ndp->lu.x;
5644    rx = ndp->ru.x;
5645    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5646    else memcpy(&d1, xsp1->ap, sizeof(double));
5647    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5648    else memcpy(&d2, xsp2->ap, sizeof(double));
5649    rta = (d1 >= d2) ? 1L : 0L;
5650    rtb = 0L;
5651    goto make_1bit;
5652   case /* > real */ REALRELGT:
5653    lx = ndp->lu.x;
5654    rx = ndp->ru.x;
5655    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5656    else memcpy(&d1, xsp1->ap, sizeof(double));
5657 
5658    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5659    else memcpy(&d2, xsp2->ap, sizeof(double));
5660    rta = (d1 > d2) ? 1L : 0L;
5661    rtb = 0L;
5662    goto make_1bit;
5663   case /* <= real */ REALRELLE:
5664    lx = ndp->lu.x;
5665    rx = ndp->ru.x;
5666    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5667    else memcpy(&d1, xsp1->ap, sizeof(double));
5668 
5669    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5670    else memcpy(&d2, xsp2->ap, sizeof(double));
5671    rta = (d1 <= d2) ? 1L : 0L;
5672    rtb = 0L;
5673    goto make_1bit;
5674   case /* < real */ REALRELLT:
5675    lx = ndp->lu.x;
5676    rx = ndp->ru.x;
5677    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5678    else memcpy(&d1, xsp1->ap, sizeof(double));
5679 
5680    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5681    else memcpy(&d2, xsp2->ap, sizeof(double));
5682 
5683    /* notice never a size change since both must be real */
5684    rta = (d1 < d2) ? 1L : 0L;
5685    rtb = 0L;
5686    goto make_1bit;
5687   case /* != real */ REALRELNEQ:
5688    lx = ndp->lu.x;
5689    rx = ndp->ru.x;
5690    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5691    else memcpy(&d1, xsp1->ap, sizeof(double));
5692 
5693    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5694    else memcpy(&d2, xsp2->ap, sizeof(double));
5695 
5696    /* notice never a size change since both must be real */
5697    /* this is ieee float point dependent */
5698    rta = (fabs(d1 - d2) >= EPSILON) ? 1L : 0L;
5699    rtb = 0L;
5700    goto make_1bit;
5701   case /* == real */ REALRELEQ:
5702    lx = ndp->lu.x;
5703    rx = ndp->ru.x;
5704    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5705    else memcpy(&d1, xsp1->ap, sizeof(double));
5706    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5707    else memcpy(&d2, xsp2->ap, sizeof(double));
5708    /* notice never a size change since both must be real */
5709    /* this is ieee float point dependent */
5710    rta = (fabs(d1 - d2) >= EPSILON) ? 0L : 1L;
5711    rtb = 0L;
5712    goto make_1bit;
5713   case /* && real */ REALBOOLAND:
5714    lx = ndp->lu.x;
5715    rx = ndp->ru.x;
5716    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5717    else memcpy(&d1, xsp1->ap, sizeof(double));
5718 
5719    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5720    else memcpy(&d2, xsp2->ap, sizeof(double));
5721    /* notice never a size change since both must be real */
5722    rta = (d1 != 0.0 && d2 != 0.0) ? 1L : 0L;
5723    rtb = 0L;
5724    goto make_1bit;
5725   case /* && real */ REALBOOLOR:
5726    lx = ndp->lu.x;
5727    rx = ndp->ru.x;
5728    if (lx->cnvt_to_real) d1 = __cnvt_stk_to_real(xsp1, (lx->has_sign == 1));
5729    else memcpy(&d1, xsp1->ap, sizeof(double));
5730 
5731    if (rx->cnvt_to_real) d2 = __cnvt_stk_to_real(xsp2, (rx->has_sign == 1));
5732    else memcpy(&d2, xsp2->ap, sizeof(double));
5733    /* notice never a size change since both must be real */
5734    rta = (d1 != 0.0 || d2 != 0.0) ? 1L : 0L;
5735    rtb = 0L;
5736    goto make_1bit;
5737   default: __case_terr(__FILE__, __LINE__);
5738  }
5739 }
5740 
5741 /*
5742  * if any x in bin. operand nodes set accumulator to all x's and return T
5743  */
5744 extern int32 __set_binxresult(word32 *resap, word32 *resbp, word32 *op1bp,
5745  word32 *op2bp, int32 opbits)
5746 {
5747  if (!vval_is0_(op1bp, opbits)) goto not_zero;
5748  if (!vval_is0_(op2bp, opbits)) goto not_zero;
5749  return(FALSE);
5750 
5751 not_zero:
5752  one_allbits_(resap, opbits);
5753  one_allbits_(resbp, opbits);
5754  return(TRUE);
5755 }
5756 
5757 /*
5758  * right shift multiword value into new valune - shift value <1m (1 word32)
5759  * know shiftval <= lwlen
5760  *
5761  * notice no need to mask off high bits here;
5762  */
5763 extern void __mwrshift(word32 *valwp, word32 shiftval, int32 blen)
5764 {
5765  int32 shwords, shbits, lwlen;
5766 
5767  lwlen = wlen_(blen);
5768  shwords = get_wofs_(shiftval);
5769  /* notice value here is 0-31 */
5770  shbits = ubits_(shiftval);
5771 
5772  /* DBG remove ---
5773  if (__debug_flg)
5774   __dbg_msg("---> mw right shift of %d was %lx", shiftval, valwp[0]);
5775  --- */
5776  if (shwords != 0) wrdmwrshift(valwp, shwords, lwlen);
5777  if (shbits != 0) bitmwrshift(valwp, shbits, lwlen);
5778  /* DBG remove --
5779  if (__debug_flg) __dbg_msg("after %lx\n", valwp[0]);
5780  */
5781 }
5782 
5783 /*
5784  * arithmetic right shift multiword value into new value
5785  *
5786  * arithmetic (signed) version of multi-word right shift - if sign 1,
5787  * then set area to 1's not 0
5788  *
5789  * SJM 10/08/04 - this shifts both a and b part
5790  */
5791 extern void __arith_mwrshift(word32 *valwp, word32 shiftval, int32 blen)
5792 {
5793  register int32 wlen, wi;
5794  int32 sign_bi, bi, shwords, shbits, nblen, is_signed;
5795 
5796  wlen = wlen_(blen);
5797  sign_bi = get_bofs_(blen - 1);
5798 
5799  if ((valwp[wlen - 1] & (1 << sign_bi)) != 0) is_signed = TRUE;
5800  else is_signed = FALSE;
5801 
5802  shwords = get_wofs_(shiftval);
5803  /* notice ubits and get_bofs macros are the same */
5804  shbits = get_bofs_(shiftval);
5805  /* do normal shift */
5806  if (shwords != 0) wrdmwrshift(valwp, shwords, wlen);
5807  if (shbits != 0) bitmwrshift(valwp, shbits, wlen);
5808 
5809  if (!is_signed) return;
5810 
5811  /* tricky part is making sure sign/x/z bit gets shifted in (duplicated) */
5812  /* new sign bit is one less than new bit len */
5813  nblen = blen - shiftval;
5814  /* set 1 bits for wi+1 to end and high bits in wi word32 */
5815  bi = get_bofs_(nblen);
5816  wi = get_wofs_(nblen);
5817  if (bi != 0)
5818   {
5819    valwp[wi] |= (__masktab[WBITS - bi] << bi);
5820    one_allbits_(&(valwp[wi + 1]), shiftval - (WBITS - bi));
5821   }
5822  else one_allbits_(&(valwp[wi]), shiftval);
5823 }
5824 
5825 /*
5826  * wide left shift - know value will not be wider than WBITS
5827  * for left shift must mask off high bits
5828  *
5829  * SJM 10/01/03 - for wide left shift arithmetic is same
5830  */
5831 extern void __mwlshift(word32 *valwp, word32 shiftval, int32 blen)
5832 {
5833  int32 shwords, shbits, lwlen, ubits;
5834 
5835  lwlen = wlen_(blen);
5836  /* this and 1f for 32 mask on number of bits */
5837  shwords = get_wofs_(shiftval);
5838  /* notice value here is 0-31 */
5839  shbits = ubits_(shiftval);
5840 
5841  /* DBG remove --
5842  if (__debug_flg)
5843   __dbg_msg("---> mw left shift of %d was %lx", shiftval, valwp[0]);
5844  -- */
5845  if (shwords != 0) wrdmwlshift(valwp, shwords, lwlen);
5846  if (shbits != 0) bitmwlshift(valwp, shbits, lwlen);
5847  ubits = ubits_(blen);
5848  valwp[lwlen - 1] &= __masktab[ubits];
5849  /* DBG remove ---
5850  if (__debug_flg) __dbg_msg("after %lx\n", valwp[0]);
5851  --- */
5852 }
5853 
5854 /*
5855  * partial word32 shift within multiword value
5856  * k < WBITS bits mw right shift (high bits toward low bits - divide)
5857  * this handles bit shifting - other part does word32 shifting
5858  */
5859 static void bitmwrshift(register word32 *wp, register int32 k, register int32 lwlen)
5860 {
5861  register int32 i;
5862  register word32 cy;
5863 
5864  wp[0] >>= k;
5865  for (i = 1; i < lwlen; i++)
5866   {
5867    cy = (wp[i] & __masktab[k]) << (WBITS - k);
5868    wp[i - 1] |= cy;
5869    /* C language right shift of word32 defined to shift in 0's */
5870    wp[i] >>= k;
5871   }
5872  /* since know wp right width with high zero's - know anwswer is right */
5873 }
5874 
5875 /*
5876  * partial word32 shift within multiword value
5877  * k < WBITS bits mw left shift (low bits toward high - mult.)
5878  * this handles bit shifting - other part does word32 shifting
5879  */
5880 static void bitmwlshift(register word32 *wp, register int32 k, register int32 lwlen)
5881 {
5882  register int32 i;
5883  register word32 cy;
5884 
5885  wp[lwlen - 1] <<= k;
5886  for (i = lwlen - 2; i >= 0; i--)
5887   {
5888    cy = ((wp[i] >> (WBITS - k)) & __masktab[k]);
5889    wp[i + 1] |= cy;
5890    /* C language left logical shift of word32 defined to shift in 0's */
5891    wp[i] <<= k;
5892   }
5893 }
5894 
5895 /*
5896  * whole word32 right shift within multiword value
5897  * kwrds is number of words
5898  * high words toward low - divide by 2**32 units
5899  * this handles word32 shifting - other part does bit shifting
5900  * know kwrds never 0
5901  */
5902 static void wrdmwrshift(register word32 *wp, register int32 kwrds,
5903  register int32 lwlen)
5904 {
5905  register int32 wi;
5906 
5907  for (wi = kwrds; wi < lwlen; wi++)  wp[wi - kwrds] = wp[wi];
5908  for (wi = lwlen - kwrds; wi < lwlen; wi++) wp[wi] = 0L;
5909 }
5910 
5911 /*
5912  * whole word32 left shift within multiword value
5913  * kwrds is number of words
5914  * low words toward high- multiply by 2**32 units
5915  * this handles word32 shifting - other part does bit shifting
5916  * know kwrds never 0
5917  */
5918 static void wrdmwlshift(register word32 *wp, register int32 kwrds,
5919  register int32 lwlen)
5920 {
5921  register int32 swi, wi;
5922 
5923  for (swi = lwlen - 1; swi >= kwrds; swi--) wp[swi] = wp[swi - kwrds];
5924  for (wi = 0; wi < kwrds; wi++) wp[wi] = 0L;
5925 }
5926 
5927 /*
5928  * long binary bit and - in place from top to 1 down
5929  * know both operands correct final width
5930  */
5931 extern void __lbitand(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
5932  int32 opbits)
5933 {
5934  register int32 wi;
5935 
5936  for (wi = 0; wi < wlen_(opbits); wi++)
5937   {
5938    if ((op1bp[wi] | op2bp[wi]) == 0L)
5939     { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] & op2ap[wi]; }
5940    else
5941     {
5942      op1ap[wi] = (op1ap[wi] | op1bp[wi]) & (op2ap[wi] | op2bp[wi]);
5943      op1bp[wi] = op1ap[wi] & (op2bp[wi] | op1bp[wi]);
5944     }
5945   }
5946 }
5947 
5948 /*
5949  * long binary bit or - both operands on stack already widened to same size
5950  * no reason to mask off high since both xor and or of 0 and 0 are 0
5951  */
5952 extern void __lbitor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
5953  int32 opbits)
5954 {
5955  register int32 wi;
5956 
5957  for (wi = 0; wi < wlen_(opbits); wi++)
5958   {
5959    if ((op1bp[wi] | op2bp[wi]) == 0L)
5960     { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] | op2ap[wi]; }
5961    else
5962     {
5963      op1bp[wi] = op2bp[wi] ^ op1bp[wi] ^ ((op1ap[wi] | op1bp[wi])
5964       & (op2bp[wi] | (op2ap[wi] & op1bp[wi])));
5965      op1ap[wi] = op1bp[wi] | op2ap[wi] | op1ap[wi];
5966     }
5967   }
5968 }
5969 
5970 /*
5971  * long binary bit xor - both operands on stack already widened
5972  * to exactly same width
5973  */
5974 extern void __lbitxor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
5975  int32 opbits)
5976 {
5977  register int32 wi;
5978  int32 wlen;
5979 
5980  wlen = wlen_(opbits);
5981  for (wi = 0; wi < wlen; wi++)
5982   {
5983    if ((op1bp[wi] | op2bp[wi]) == 0L)
5984     { op1bp[wi] = 0L; op1ap[wi] = op1ap[wi] ^ op2ap[wi]; }
5985    else
5986     {
5987      op1bp[wi] = op1bp[wi] | op2bp[wi];
5988      op1ap[wi] = op1bp[wi] | (op1ap[wi] ^ op2ap[wi]);
5989     }
5990   }
5991  /* know high bits are 0, since both op's high bits 0 */
5992 }
5993 
5994 /*
5995  * long binary bit xnor - both operands on stack already widened
5996  */
5997 extern void __lbitxnor(word32 *op1ap, word32 *op1bp, word32 *op2ap, word32 *op2bp,
5998  int32 opbits)
5999 {
6000  register int32 wi;
6001  int32 wlen;
6002 
6003  wlen = wlen_(opbits);
6004  for (wi = 0; wi < wlen; wi++)
6005   {
6006    if ((op1bp[wi] | op2bp[wi]) == 0L)
6007     { op1bp[wi] = 0L; op1ap[wi] = ~(op1ap[wi] ^ op2ap[wi]); }
6008    else
6009     {
6010      op1bp[wi] = op1bp[wi] | op2bp[wi];
6011      op1ap[wi] = op1bp[wi] | ~(op1ap[wi] ^ op2ap[wi]);
6012     }
6013   }
6014  op1ap[wlen - 1] &= __masktab[ubits_(opbits)];
6015  /* know high bits in b part are 0, since both op's high bits 0 */
6016 }
6017 
6018 /*
6019  * convert wide value on top of reg stack to boolean - any 1=1,0,x(3)
6020  * must be extern since invoked by macro
6021  */
6022 extern int32 __cvt_lngbool(word32 *ap, word32 *bp, int32 wlen)
6023 {
6024  register int32 wi;
6025  int32 hasxs;
6026 
6027  for (hasxs = FALSE, wi = 0; wi < wlen; wi++)
6028   {
6029    if ((ap[wi] & ~bp[wi]) != 0L) return(1);
6030    if (bp[wi] != 0L) hasxs = TRUE;
6031   }
6032  if (hasxs) return(3);
6033  return(0);
6034 }
6035 
6036 /*
6037  * compare word32 first with second - know widths the same
6038  *
6039  * set isx if either has x or z, else -1 <, 0 = , 1 >
6040  * know all wider than WBITS values in Verilog are unsigned
6041  * not for === or !== sincd non x even if x's or z's
6042  *
6043  * know size change made so both same no. words and high bits of narrow now 0
6044  */
6045 extern int32 __do_widecmp(int32 *isx, register word32 *op1ap, register word32 *op1bp,
6046  register word32 *op2ap, register word32 *op2bp, int32 opwid)
6047 {
6048  register int32 i;
6049 
6050  *isx = TRUE;
6051  if (!vval_is0_(op1bp, opwid)) return(0);
6052  if (!vval_is0_(op2bp, opwid)) return(0);
6053 
6054  *isx = FALSE;
6055  /* know unused parts of high words will both be zero */
6056  for (i = wlen_(opwid) - 1; i >= 0; i--)
6057   {
6058    if (op1ap[i] != op2ap[i])
6059     { if (op1ap[i] < op2ap[i]) return(-1); else return(1); }
6060   }
6061  return(0);
6062 }
6063 
6064 /*
6065  * compare signed wide first with second - know widths the same
6066  *
6067  * set isx if either has x or z, else -1 <, 0 = , 1 >
6068  * not for === or !== sincd non x even if x's or z's
6069  *
6070  * know size change made so both same no. words and high bits of narrow now 0
6071  */
6072 extern int32 __do_sign_widecmp(int32 *isx, register word32 *op1ap,
6073  register word32 *op1bp, register word32 *op2ap, register word32 *op2bp, int32 opwid)
6074 {
6075  register int32 i, i1, i2;
6076  int32 wlen;
6077 
6078  *isx = TRUE;
6079  if (!vval_is0_(op1bp, opwid)) return(0);
6080  if (!vval_is0_(op2bp, opwid)) return(0);
6081 
6082  *isx = FALSE;
6083  /* wi is index of high word32 */
6084  wlen = wlen_(opwid);
6085 
6086  /* if op1 is negative */
6087  if ((op1ap[wlen - 1] & (1 << ubits_(opwid - 1))) != 0)
6088   {
6089    /* if op1 is negative and op2 is positive */
6090    if ((op2ap[wlen - 1] & (1 << ubits_(opwid - 1))) == 0) return(-1);
6091   }
6092  /* op1 is positive and op2 is negative */
6093  else if ((op2ap[wlen - 1] & (1 << ubits_(opwid - 1))) != 0) return(1);
6094 
6095  /* here both will have the same sign (especially high word32) */
6096  /* know unused parts of high words will both be zero */
6097  for (i = wlen_(opwid) - 1; i >= 0; i--)
6098   {
6099    if (op1ap[i] != op2ap[i])
6100     {
6101      i1 = (sword32) op1ap[i];
6102      i2 = (sword32) op2ap[i];
6103      if (i1 < i2) return(-1);
6104      else return(1);
6105     }
6106   }
6107  return(0);
6108 }
6109 
6110 /*
6111  * compare known x/z wide values and return T if not equal when x/z bits
6112  * ignored
6113  *
6114  * SJM 10/16/00 - routine for wide == or != return T if non x/z
6115  * comparision is not equal (i.e. if for every word32 any x/z bits in either
6116  * 1st or 2nd operand are set to same 1 for comparison, then if value not
6117  * equal x/z bits do not effect outcome so result must be not equal)
6118  *
6119  * no need for high bit masking because high unused set to 0 and size
6120  * change made to make bits same width
6121  * know size change made before calling this so both same words with narrower's
6122  * high bits 0 (if one was narrower)
6123  */
6124 extern int32 __omitxz_widenoteq(register word32 *op1ap, register word32 *op1bp,
6125  register word32 *op2ap, register word32 *op2bp, int32 opwid)
6126 {
6127  register word32 xzmask;
6128  int32 i;
6129 
6130  /* know unused parts of high words will both be zero */
6131  /* when find first bit that makes not equal after masking all x/z in both */
6132  /* to same, done */
6133  for (i = wlen_(opwid) - 1; i >= 0; i--)
6134   {
6135    xzmask = op1bp[i] | op2bp[i];
6136    if ((op1ap[i] | xzmask) != (op2ap[i] | xzmask)) return(TRUE);
6137   }
6138  return(FALSE);
6139 }
6140 
6141 /*
6142  * compare word32 first with second - know widths the same
6143  * returns 1 if non equal 0 if equal
6144  * for === and !== compare cannot be used for greater or less
6145  *
6146  * do not need to worry about high bits since sematics requires 0 extend
6147  * and 0 and 0 will match as 0 (never effect result)
6148  */
6149 extern int32 __do_xzwidecmp(register word32 *op1ap, register word32 *op1bp,
6150  register word32 *op2ap, register word32 *op2bp, int32 opbits)
6151 {
6152  int32 bytlen;
6153 
6154  bytlen = WRDBYTES*wlen_(opbits);
6155  if (memcmp(op1ap, op2ap, bytlen) != 0 || memcmp(op1bp, op2bp, bytlen) != 0)
6156   return(1);
6157  return(0);
6158 }
6159 
6160 /*
6161  * MULTIWORD ARITHMETIC ROUTINES
6162  */
6163 
6164 /*
6165  * routines taken from BSD style license mpexpr package and modified
6166  * to match Verilog internal storage requirements and operation semantics
6167  * routines mostly stright forward implementations from Knuht Vol. 2
6168  *
6169  * here is copyright notice in mpexpr package zmath.c file:
6170  *
6171  * Copyright (c) 1994 David I. Bell
6172  * Permission is granted to use, distribute, or modify this source,
6173  * provided that this copyright notice remains intact.
6174  *
6175  * Extended precision integral arithmetic primitives
6176  *
6177  * I have re-written these routines to use Cver endian code and to use
6178  * result wrap around trick for determining add/sub carry from 32 bit
6179  * words without using 64 bit arithemtic - also not using packages n**1.6
6180  * multiply routine since more then 300 (or so) bit multiples rare in
6181  * verilog
6182  */
6183 
6184 /*
6185  * wide word32 add
6186  * know u and v same width and resp wide enough and high zeroed
6187  * >WBITS always unsigned
6188  *
6189  * result and operands can't be same
6190  * LOOKATME - think not worth converting to word32 64 array
6191  *
6192  * SJM 09/30/03 - for signed just works because of 2's complement
6193  */
6194 extern void __ladd(word32 *res, word32 *u, word32 *v, int32 blen)
6195 {
6196  register word32 a2;
6197  register word32 *u_end, cy;
6198  int32 ublen, vblen, trimblen, wlen, hzwlen, verwlen;
6199  extern void __my_fprintf(FILE *, char *, ...);
6200 
6201  ublen = __trim1_0val(u, blen);
6202  vblen = __trim1_0val(v, blen);
6203  trimblen = (ublen >= vblen) ? ublen : vblen;
6204  /* if trimmed max fits, need 1 more word32 for carry that is needed */
6205  if ((wlen = wlen_(trimblen)) < (verwlen = wlen_(blen))) wlen++;
6206  if ((hzwlen = verwlen - wlen) > 0)
6207   memset(&(res[wlen]), 0, WRDBYTES*hzwlen);
6208 
6209  u_end = &(u[wlen]);
6210  cy = 0;
6211  do {
6212    /* DBG remove --
6213    __dbg_msg("at top of loop: cy=%0x\n", cy);
6214    -- */
6215    a2 = *v++;
6216    *res = *u++ + a2 + cy;
6217    /* use wrap around 32 bit test and auto incr instead of mpexpr cast */
6218    /* to word32 64 although current gcc does not handle auto inc/dec well */
6219 
6220    /* notice if cy on if res and v equal, must not turn off */
6221    /* also if cy off if res and v equal, do not turn on */
6222    if (cy == 0) { if (*res < a2) cy = 1; }
6223    else { if (*res > a2) cy = 0; }
6224    res++;
6225 
6226    /* DBG remove ---
6227    __dbg_msg("*u=%0x, *v=%0x, a2=%0x, *res=%0x, cy=%0x\n", u[-1], v[-1],
6228      a2, res[-1], cy);
6229    --- */
6230   } while (u < u_end);
6231 
6232  /* usually do not need this but faster to mask than test and then mask */
6233  res--;
6234  *res &= __masktab[ubits_(blen)];
6235 }
6236 
6237 /*
6238  * wide subtract
6239  * know u and v same width and resp wide enough and zeroed
6240  * also res can be same as u or v (needed for ldiv2)
6241  * can get by with 32 bit arithmetic here
6242  * since mask any unused high bits - can borrow from unused
6243  *
6244  * LOOKATME - think not worth converting to word32 64 array
6245  * SJM 09/28/03 - 2's complement means signed just interpretation
6246  * i.e. if sign bit on then negative
6247  */
6248 extern word32 __lsub(word32 *res, word32 *u, word32 *v, int32 blen)
6249 {
6250  register word32 *u_end, borrow, tmpres;
6251  int32 wlen;
6252 
6253  wlen = wlen_(blen);
6254  borrow = 0;
6255  u_end = &(u[wlen]);
6256  do {
6257    /* modified to use only 32 bit arithmetic and ptr inc */
6258    if ((tmpres = *u++ - borrow) > (ALL1W - borrow)) tmpres = ALL1W - *v;
6259    else if ((tmpres -= *v) > (ALL1W - *v)) borrow = 1;
6260    else borrow = 0;
6261    *res++ = tmpres;
6262    v++;
6263  } while (u < u_end);
6264  /* notice in Verilog borrow always taken - even though nothing higher */
6265  res--;
6266  *res &= __masktab[ubits_(blen)];
6267  return(borrow);
6268 }
6269 
6270 /*
6271  * multiple 2 multi-word32 signed numbers
6272  *
6273  * wrapper that use normal word32 lmult on absolute values
6274  * since no x/z part (already handled) no x/z extension
6275  * BEWARE - this depends on fact that xstk ap/bp parts contiguous
6276  */
6277 extern void __sgn_lmult(register word32 *res, register word32 *u,
6278  register word32 *v, int32 blen)
6279 {
6280  int32 wlen, usign, vsign;
6281  word32 *wrku, *wrkv;
6282  struct xstk_t *uxsp, *vxsp;
6283 
6284  wlen = wlen_(blen);
6285  usign = vsign = 1;
6286  uxsp = vxsp = NULL;
6287  if (__is_lnegative(u, blen))
6288   {
6289    /* SJM 09/15/04 - lnegate need both a and b parts */
6290    push_xstk_(uxsp, blen);
6291    usign = -1;
6292    /* ignoring carry */
6293    __cp_lnegate(uxsp->ap, u, blen);
6294    wrku = uxsp->ap;
6295   }
6296  else wrku = u;
6297  if (__is_lnegative(v, blen))
6298   {
6299    /* SJM 09/15/04 - lnegate need both a and b parts */
6300    push_xstk_(vxsp, blen);
6301    vsign = -1;
6302    /* ignoring carry */
6303    __cp_lnegate(vxsp->ap, v, blen);
6304    wrkv = vxsp->ap;
6305   }
6306  else wrkv = v;
6307 
6308  __lmult(res, wrku, wrkv, blen);
6309  if ((usign*vsign) == -1)
6310   {
6311    __inplace_lnegate(res, blen);
6312   }
6313  if (uxsp != NULL) __pop_xstk();
6314  if (vxsp != NULL) __pop_xstk();
6315 }
6316 
6317 /*
6318  * routine to determine if signed val negative by checking sign bit
6319  *
6320  * FIXME - this should be macro
6321  */
6322 extern int32 __is_lnegative(word32 *u, int32 blen)
6323 {
6324  register int32 wi, bi;
6325 
6326  blen--;
6327  wi = get_wofs_(blen);
6328  bi = get_bofs_(blen);
6329  if ((u[wi] & (1 << bi)) != 0) return(TRUE);
6330  return(FALSE);
6331 }
6332 
6333 /*
6334  * in place routine to compute 2's complement negation of signed wide number
6335  * formula is ~(value) + 1
6336  * return carry if any but not used for now
6337  * in place
6338  *
6339  * LOOKATME - copy version - maybe in place better
6340  */
6341 extern word32 __inplace_lnegate(register word32 *u, int32 blen)
6342 {
6343  register int32 wi, ubits;
6344  int32 wlen;
6345  word32 cy;
6346 
6347  wlen = wlen_(blen);
6348  for (wi = 0; wi < wlen; wi++) u[wi] = ~(u[wi]);
6349  ubits = ubits_(blen);
6350  u[wlen - 1] &= __masktab[ubits];
6351  /* SJM 09/15/04 - was wrongly passes ubits so was not incing high words */
6352  cy = sgn_linc(u, blen);
6353  return(cy);
6354 }
6355 
6356 /*
6357  * copy routine to compute 2's complement negation of signed wide number
6358  * formula is ~(value) + 1
6359  * return carry if any but not used for now
6360  * in place
6361  *
6362  * LOOKATME - copy version - maybe in place better
6363  */
6364 extern word32 __cp_lnegate(word32 *u, register word32 *v, int32 blen)
6365 {
6366  register int32 wi, ubits;
6367  word32 cy;
6368  int32 wlen;
6369 
6370  wlen = wlen_(blen);
6371  for (wi = 0; wi < wlen; wi++, v++) u[wi] = ~(*v);
6372  ubits = ubits_(blen);
6373  u[wlen - 1] &= __masktab[ubits];
6374 
6375  cy = sgn_linc(u, blen);
6376  return(cy);
6377 }
6378 
6379 /*
6380  * inc (add 1) in place to wide signed value
6381  */
6382 static int32 sgn_linc(register word32 *u, int32 blen)
6383 {
6384  register int32 wi, ubits;
6385  register int32 wlen;
6386 
6387  wlen = wlen_(blen);
6388  /* done when no carry - special case speed up attmpt */
6389  if (++(u[0]) != 0) return(0);
6390 
6391  /* enter loop with cy */
6392  for (wi = 1; wi < wlen; wi++)
6393   {
6394    /* add the carry from last one */
6395    if (++(u[wi]) != 0)
6396     {
6397      if (wi != wlen - 1) return(0);
6398      ubits = ubits_(blen);
6399      u[wi] &= __masktab[ubits];
6400      return(1);
6401     }
6402   }
6403  /* value was all 1's and fills high word32, no mask but return cy */
6404  /* 2's complement of 0 is 0 plus carry */
6405  return(1);
6406 }
6407 
6408 /*
6409  * multiply two multi-word32 numbers to obtain the double len product
6410  *
6411  * notice res must not be same addr as u or v
6412  * original idea for this routine came from Dr. Dobbs article
6413  *
6414  * this does not use mpexpr recursive 1.6 power multiply since Verilog
6415  * numbers rarely wider than 300 bits - algorithm is simple distributed
6416  * accumulate
6417  *
6418  * SJM 09/28/03 - must multply with absolute values so there is sign
6419  * handling wrapper for signed wide multiply
6420  */
6421 extern void __lmult(register word32 *res, register word32 *u, register word32 *v,
6422  int32 blen)
6423 {
6424  register int32 i;
6425  int32 wlen, ublen, vblen, uwlen, vwlen, prodwlen;
6426  word32 *wp;
6427  w64_u w64res;
6428  struct xstk_t *xsp;
6429 
6430  /* set result to zero for special case - not using b part - left as 0 */
6431  wlen = wlen_(blen);
6432  memset(res, 0, wlen*WRDBYTES);
6433 
6434  /* normalize - by finding bit widths for u and v */
6435  ublen = __trim1_0val(u, blen);
6436  vblen = __trim1_0val(v, blen);
6437  if (ublen == 0 || vblen == 0) return;
6438  /* if trim so that both multipliers fit in 32 bits use 64 prod routine */
6439  /* know blen > WBITS or will not be called */
6440  if (ublen <= WBITS && vblen <= WBITS)
6441   {
6442    /* notice if blen wider then 64 - values already 0ed and left 0ed */
6443    w64res.w64v = ((word64) *u)*((word64) *v);
6444    res[0] = w64res.w_u.low;
6445    /* SJM 12/07/01 - and out any bits wider than blen if blen < 64 */
6446    /* very wide blen can trim to here, if so no mask needed */
6447    res[1] = w64res.w_u.high;
6448    if (blen < 64) res[1] &= __masktab[ubits_(blen)];
6449    return;
6450   }
6451  /* at least one trim wider than 32 but no carry to high since blen <= 64 */
6452  if (blen <= 64)
6453   {
6454    w64_u w64op1, w64op2;
6455 
6456    /* LOOKATME - could just use pointer for little endia X86 */
6457    w64op1.w_u.low = u[0];
6458    w64op1.w_u.high = u[1];
6459    w64op2.w_u.low = v[0];
6460    w64op2.w_u.high = v[1];
6461    w64res.w64v = w64op1.w64v * w64op2.w64v;
6462    res[0] = w64res.w_u.low;
6463    /* SJM 12/07/01 - and out any bits wider than blen - fastest always mask */
6464    res[1] = w64res.w_u.high & __masktab[ubits_(blen)];
6465    return;
6466   }
6467  uwlen = wlen_(ublen);
6468  vwlen = wlen_(vblen);
6469  prodwlen = uwlen + vwlen;
6470  /* multiply into double trimmed width product - but use all no b part */
6471  push_xstk_(xsp, prodwlen*WBITS/2);
6472  wp = xsp->ap;
6473  memset(wp, 0, WRDBYTES*prodwlen);
6474  for (i = 0; i < uwlen; i++)
6475   {
6476    wp[i + vwlen] += accmuladd32(&(wp[i]), &(wp[i]), u[i], v, vwlen);
6477   }
6478 
6479  memcpy(res, wp, ((wlen < prodwlen) ? wlen : prodwlen)*WRDBYTES);
6480  /* SJM 04/07/03 - need to mask high bits in high word32 here */
6481  /* AIV 12/20/06 - was masking wrong pointer should be res not wp */
6482  res[wlen - 1] &= __masktab[ubits_(blen)];
6483  __pop_xstk();
6484 }
6485 
6486 /*
6487  * a[] = b[] + c*d[] - compute array per word32, word32 product sum
6488  * returns carry
6489  */
6490 static int32 accmuladd32(word32 *a, word32 *b, word32 c, word32 *d, int32 wlen)
6491 {
6492  register int32 i;
6493  register word32 t0, t1, cy;
6494  w64_u res;
6495  word64 c64;
6496 
6497  c64 = (word64) c;
6498  for (cy = 0, i = 0; i < wlen; i++)
6499   {
6500    /* know product of 2 32 bit values fits in 64 bits */
6501    res.w64v = c64*((word64) d[i]);
6502    t0 = res.w_u.low;
6503    t1 = res.w_u.high;
6504 
6505    if ((a[i] = b[i] + cy) < cy) cy = 1; else cy = 0;
6506    if ((a[i] += t0) < t0) cy++;
6507    cy += t1;
6508   }
6509  return(cy);
6510 }
6511 
6512 /*
6513  * interfact to signed long div and mod (keep rem) that select needed result
6514  *
6515  * wrapper that use normal word32 on absolute values then adjusts signs
6516  * since no x/z part (already handled) no x/z extension
6517  * BEWARE - this depends on fact that xstk ap/bp parts contiguous
6518  */
6519 extern void __sgn_ldivmod(register word32 *res, register word32 *u,
6520  register word32 *v, int32 blen, int32 nd_quot)
6521 {
6522  int32 wlen, usign, vsign;
6523  word32 *wrku, *wrkv;
6524  struct xstk_t *uxsp, *vxsp, *tmpxsp;
6525 
6526  /* always need unused tmp area for unused of mod/div results */
6527  wlen = wlen_(blen);
6528  push_xstk_(tmpxsp, wlen*WBITS/2);
6529 
6530  wlen = wlen_(blen);
6531  usign = vsign = 1;
6532  uxsp = vxsp = NULL;
6533  /* div/mod routine assumes both operands positive */
6534  if (__is_lnegative(u, blen))
6535   {
6536    /* SJM 09/15/04 - lnegate need both a and b parts */
6537    push_xstk_(uxsp, blen);
6538    usign = -1;
6539    /* ignoring carry */
6540    __cp_lnegate(uxsp->ap, u, blen);
6541    wrku = uxsp->ap;
6542   }
6543  else wrku = u;
6544  if (__is_lnegative(v, blen))
6545   {
6546    /* SJM 09/15/04 - lnegate need both a and b parts */
6547    push_xstk_(vxsp, blen);
6548    vsign = -1;
6549    /* ignoring carry */
6550    __cp_lnegate(vxsp->ap, v, blen);
6551    wrkv = vxsp->ap;
6552   }
6553  else wrkv = v;
6554 
6555  /* separate into div/mod and adjust sign according to different rules */
6556  if (nd_quot)
6557   {
6558    __ldivmod2(res, tmpxsp->ap, wrku, wrkv, blen);
6559    /* for div sign negative if one but not both negative */
6560    if ((usign*vsign) == -1) __inplace_lnegate(res, blen);
6561   }
6562  else
6563   {
6564    __ldivmod2(tmpxsp->ap, res, wrku, wrkv, blen);
6565    /* for mod sign same as sign of first but must do word32 wide div/mod */
6566    if (usign == -1) __inplace_lnegate(res, blen);
6567   }
6568  if (uxsp != NULL) __pop_xstk();
6569  if (vxsp != NULL) __pop_xstk();
6570  __pop_xstk();
6571 }
6572 
6573 /*
6574  * interfact to long div and mod (keep rem) that select needed result
6575  */
6576 extern void __ldivmod(word32 *res, word32 *u, word32 *v, int32 blen, int32 nd_quot)
6577 {
6578  int32 wlen;
6579  struct xstk_t *tmpxsp;
6580 
6581  wlen = wlen_(blen);
6582  push_xstk_(tmpxsp, wlen*WBITS/2);
6583 
6584  if (nd_quot) __ldivmod2(res, tmpxsp->ap, u, v, blen);
6585  else __ldivmod2(tmpxsp->ap, res, u, v, blen);
6586  __pop_xstk();
6587 }
6588 
6589 /*
6590  * Divide two numbers to obtain a quotient and remainder.
6591  *
6592  * dividing u by v - know if v 0 already returned x value
6593  * res, quot, u and v must all be different addresses
6594  * u and v are preserved and no b parts are assumed to exist
6595  *
6596  * blen is width of both u and z (one widened if needed from Ver semantics)
6597  * fills blen wide result
6598  *
6599  * SJM 09/30/03 - wrapper insures operands here are positive
6600  */
6601 extern void __ldivmod2(word32 *quot, word32 *rem, word32 *u, word32 *v, int32 blen)
6602 {
6603  register word32 *uwp, *vwp;
6604  word32 r0;
6605  int32 ublen, vblen, uwlen, vwlen, wlen, normdist, ubits;
6606  struct xstk_t *xsp;
6607 
6608  /* set rem and quotient to zero */
6609  wlen = wlen_(blen);
6610 
6611  memset(quot, 0, wlen*WRDBYTES);
6612  memset(rem, 0, wlen*WRDBYTES);
6613 
6614  /* normalize - by finding bit widths for u and v */
6615  ublen = __trim1_0val(u, blen);
6616  vblen = __trim1_0val(v, blen);
6617  /* 0 over anything is quotient and remainder of 0 */
6618  if (ublen == 0) return;
6619 
6620  /* can use c division - know not signed */
6621  if (ublen <= WBITS && vblen <= WBITS)
6622   { quot[0] = u[0] / v[0]; rem[0] = u[0] % v[0]; return; }
6623 
6624  /* if divisor fits in half word32, use fast linear algorithm */
6625  if (vblen <= WBITS/2)
6626   {
6627    /* special divide by 1 - rem is 0 (already initialized and quot is u) */
6628    if (v[0] == 1)
6629     {
6630      cp_walign_(quot, u, ublen);
6631      return;
6632     }
6633    __by16_ldivmod(quot, &r0, u, v[0], ublen);
6634    rem[0] = r0;
6635    return;
6636   }
6637  /* if u smaller in abs. value then v, answer immediate */
6638  uwlen = wlen_(ublen);
6639  vwlen = wlen_(vblen);
6640  /* if u smaller than v, then rem is u and quotient is 0 */
6641  /* think this is wrong - what about extra high part of 1 ? */
6642  if (ldiv_cmp(u, v, ((uwlen < vwlen) ? vwlen : uwlen)) < 0)
6643   { cp_walign_(rem, u, blen); return; }
6644 
6645  /* need long division */
6646  /* normalizing divisor (bottom)(v) first */
6647  /* high bit of divisor (v) must be 1 - compute number of leading 0s */
6648  /* AIV 06/25/04 - only nomalize if not multiple of WBITS */
6649  ubits = ubits_(vblen);
6650  normdist = (ubits == 0) ? 0 : WBITS - ubits;
6651 
6652  /* since must shift, need copy of if stacked v (divisor) can be changed */
6653  /* could just shift */
6654  push_xstk_(xsp, vwlen*WBITS/2);
6655  vwp = xsp->ap;
6656  memcpy(vwp, v, vwlen*WRDBYTES);
6657 
6658  if (normdist != 0) bitmwlshift(vwp, normdist, vwlen);
6659 
6660  /* normalize dividend next */
6661  /* need 1 extra 0 digit in work numerator (u) so shift fits */
6662  push_xstk_(xsp, (uwlen + 1)*WBITS/2);
6663  uwp = xsp->ap;
6664  memcpy(uwp, u, uwlen*WRDBYTES);
6665 
6666  uwp[uwlen] = 0;
6667  if (normdist != 0) bitmwlshift(uwp, normdist, uwlen + 1);
6668 
6669  /* use basic algorithm of mpexpr long div routine */
6670  /* notice length of dividend (u) is plus 1 because divisor (v) gets */
6671  /* normalized probably causing shift of part of u into 1 higher word32 */
6672  mpexpr_zdiv(quot, rem, uwp, uwlen + 1, vwp, vwlen);
6673  if (normdist != 0) bitmwrshift(rem, normdist, vwlen);
6674  __pop_xstk();
6675  __pop_xstk();
6676 }
6677 
6678 
6679 /*
6680  * EXTENDED PRECISION DIVISION ROUTINE
6681  */
6682 
6683 #define BASE 0x100000000ULL
6684 #define BASE1 BASE - 1ULL
6685 
6686 /*
6687  * Divide ztmp1/ztmp2 and set quotient in quot and remainder in rem
6688  *
6689  * user must allocate large enough area for quot and rem and they must
6690  * be zeroed before call
6691  *
6692  * know ztmp1 and zmp2 normalized copies of u and v (u/v) so this can
6693  * overright values
6694  *
6695  * routine is taken exactly from mpexpr except changed to verilog number
6696  * representation and special cases handled by ldiv/lmod removed
6697  *
6698  * "digit" here is word32 32 bit word32, lengths are no. of words
6699  * uwp is top and vwp is bottom
6700  *
6701  * changed endian word64/word32 access to follow Cver conventions and set
6702  * 64 long long 32 long that is only supported by modern c compilers
6703  * know both zu and v normalized and dividend > 0 when called
6704  *
6705  * uwp and vwp are copies of u and v and both normalized before calling zdiv
6706  *
6707  * Comments in mpexpr:
6708  *   This algorithm is taken from
6709  *   Knuth, The Art of Computer Programming, vol 2: Seminumerical Algorithms.
6710  *   Slight modifications were made to speed this mess up.
6711  *
6712  */
6713 static void mpexpr_zdiv(word32 *quot, word32 *rem, word32 *ztmp1, int32 ztmp1_len,
6714  word32 *ztmp2, int32 ztmp2_len)
6715 {
6716  register word32 *q, *pp;
6717  int32 quot_len, y, ztmp3_len, k;
6718  word64 x;
6719  word32 *ztmp3, h2, v2;
6720  /* pair of word32 values to make word64 value - uses endianess */
6721  w64_u pair;
6722  struct xstk_t *ztmp3_xsp;
6723 
6724  /* know u/v both normalized and remainder only case remove before here */
6725  quot_len = ztmp1_len - ztmp2_len;
6726  q = &(quot[quot_len]);
6727  y = ztmp1_len - 1;
6728  h2 = ztmp2[ztmp2_len - 1];
6729  v2 = 0;
6730  k = ztmp1_len - ztmp2_len;
6731 
6732  /* need ztmp3 of width v_len (denominator size) + 1 & b part for dbg print */
6733  /* LOOKATME - except for debugging this does not need b part */
6734  push_xstk_(ztmp3_xsp, (ztmp2_len + 1)*WBITS);
6735  ztmp3 = ztmp3_xsp->ap;
6736  ztmp3_len = ztmp2_len + 1;
6737  /* zero b part for debugging */
6738  memset(&(ztmp3[ztmp3_len]), 0, ztmp3_len*WRDBYTES);
6739  if (ztmp2_len >= 2) v2 = ztmp2[ztmp2_len - 2];
6740 
6741  /* y starts at trimmed len of u - 1 in words and is deced each time thru */
6742  /* k is how many "digits" more in numerator than denominator */
6743  for (; k--; --y)
6744   {
6745    pp = &(ztmp1[y - 1]);
6746    pair.w_u.low = pp[0];
6747    pair.w_u.high = pp[1];
6748 
6749    if (ztmp1[y] == h2) x = BASE1; else x = pair.w64v/(word64) h2;
6750    if (x != 0ULL)
6751     {
6752      /* this computes one word32 ("digit") x */
6753      while ((pair.w64v - x*h2 < BASE) && (y > 1)
6754       && (v2*x > (pair.w64v - x*h2) * BASE + ztmp1[y-2]))
6755       {
6756        x--;
6757       }
6758      /* multiply high digit by numerator in preparation for subtract */
6759      /* carry may go into one digit wider than denominator w2tmp size */
6760      /* notice reversed order from mpexpr zdiv so result in 1st arg */
6761      dmul(ztmp3, ztmp3_len, ztmp2, ztmp2_len, x);
6762 
6763      /* DBG remove ---
6764      if (__debug_flg)
6765       {
6766        __dbg_msg("** zdiv: x = %ld\n", x);
6767        __dbg_msg("         ztmp1 = %s\n", __regab_tostr(__xs, ztmp1,
6768         &(ztmp1[ztmp1_len]), ztmp1_len*WBITS, BHEX, FALSE));
6769        __dbg_msg("         ztmp2 = %s\n", __regab_tostr(__xs, ztmp2,
6770         &(ztmp2[ztmp2_len]), ztmp2_len*WBITS, BHEX, FALSE));
6771        memset(&ztmp3[ztmp3_len], 0, ztmp3_len*WRDBYTES);
6772        __dbg_msg("         ztmp3 = %s\n", __regab_tostr(__xs, ztmp3,
6773         &(ztmp3[ztmp3_len]), ztmp3_len*WBITS, BHEX, FALSE));
6774       }
6775      --- */
6776 
6777      /* subtract new "high" digit ("word") from numerator */
6778      if (dsub(ztmp1, ztmp1_len, ztmp3, ztmp3_len, y, ztmp2_len))
6779       {
6780        --x;
6781        /* DBG remove --
6782        if (__debug_flg) __dbg_msg("** zdiv: adding back\n");
6783        -- */
6784        dadd(ztmp1, ztmp2, y, ztmp2_len);
6785       }
6786     }
6787    ztmp1_len = ztrim(ztmp1, ztmp1_len);
6788    /* each time thru set one current high digit of quotient to value */
6789    *--q = (word32) x;
6790   }
6791 
6792  /* remainder is value now in ztmp1, caller unnormalizes rem */
6793  memcpy(rem, ztmp1, ztmp1_len*WRDBYTES);
6794 
6795  /* quot has right value - no need to unnormalize */
6796  __pop_xstk();
6797 }
6798 
6799 /*
6800  * 32 bit "digit" trim - unlike mpexpr ztrim returns trimmed width
6801  */
6802 static int32 ztrim(word32 *zp, int32 z_len)
6803 {
6804  register word32 *h;
6805  register int32 len;
6806 
6807  h = &(zp[z_len - 1]);
6808  len = z_len;
6809  while (*h == 0 && len > 1) { --h; --len; }
6810  return (len);
6811 }
6812 
6813 /*
6814  * internal add in place z1 += z2
6815  *
6816  * what are y and n
6817  * need len to save extra work for high 0s
6818  */
6819 static void dadd(word32 *z1p, word32 *z2p, int32 y, int32 n)
6820 {
6821  word32 *s1p, *s2p;
6822  word32 carry;
6823  word64 sum;
6824 
6825  s1p = &(z1p[y - n]);
6826  s2p = z2p;
6827  carry = 0;
6828  while (n--)
6829   {
6830    sum = ((word64) *s1p) + ((word64) *s2p) + ((word64) carry);
6831    carry = 0;
6832    if (sum >= BASE) { sum -= BASE; carry = 1; }
6833    *s1p = (word32) sum;
6834    ++s1p;
6835    ++s2p;
6836   }
6837  sum = ((word64) *s1p) + ((word64) carry);
6838  *s1p = (word32) sum;
6839 }
6840 
6841 /*
6842  * subtract z2p from z1p with result in place into z1p for divide
6843  * returns T result goes negative.
6844  *
6845  * LOOKATME - what are y and n?
6846  * "digits" unsigned
6847  */
6848 static int32 dsub(word32 *z1p, int32 z1_len, word32 *z2p, int32 z2_len, int32 y, int32 n)
6849 {
6850  word32 *s1p, *s2p, *s3p;
6851  word64 i1;
6852  int32 neg;
6853 
6854  neg = FALSE;
6855  s1p = &(z1p[y - n]);
6856  s2p = z2p;
6857  if (++n > z2_len) n = z2_len;
6858 
6859  while (n--)
6860   {
6861    i1 = (word64) *s1p;
6862    if (i1 < (word64) *s2p)
6863     {
6864      s3p = &(s1p[1]);
6865      while (s3p < &(z1p[z1_len]) && !(*s3p))
6866       { *s3p = (word32) BASE1; ++s3p; }
6867 
6868      if (s3p >= &(z1p[z1_len])) neg = TRUE; else --(s3p[0]);
6869      i1 += BASE;
6870     }
6871   *s1p = (word32) (i1 - (word64) *s2p);
6872   ++s1p;
6873   ++s2p;
6874  }
6875  return neg;
6876 }
6877 
6878 /*
6879  * multiply into tmp dest zp times one word32 ("digit") in mul
6880  *
6881  * mpexpr comments:
6882  * Multiply a number by a single 'digit'.
6883  * This is meant to be used only by the divide routine, and so the
6884  * destination area must already be allocated and be large enough.
6885  */
6886 static void dmul(word32 *destp, int32 dest_len, word32 *z1p, int32 z1_len, word64 mul)
6887 {
6888  register word32 *zp, *dp;
6889  w64_u pair;
6890  word64 carry;
6891  long len;
6892 
6893  memset(destp, 0, dest_len*WRDBYTES);
6894  /* multiple by 0 result is 0 */
6895  if (mul == 0ULL) return;
6896 
6897  len = z1_len;
6898  zp = &(z1p[len - 1]);
6899  dp = destp;
6900  /* trim each time to save work */
6901  while ((*zp == 0) && (len > 1)) { len--; zp--; }
6902  zp = z1p;
6903 
6904  carry = 0;
6905  /* compute 4 word("digits") sections with unrolled loop */
6906  while (len >= 4) {
6907   len -= 4;
6908   pair.w64v = (mul * ((word64) *zp++)) + carry;
6909   *dp++ = pair.w_u.low;
6910   pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
6911   *dp++ = pair.w_u.low;
6912   pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
6913   *dp++ = pair.w_u.low;
6914   pair.w64v = (mul * ((word64) *zp++)) + ((word64) pair.w_u.high);
6915   *dp++ = pair.w_u.low;
6916   carry = pair.w_u.high;
6917  }
6918  /* copmute final ending left over digits ("words") */
6919  while (--len >= 0) {
6920   pair.w64v = (mul * ((word64) *zp++)) + carry;
6921   *dp++ = pair.w_u.low;
6922   carry = pair.w_u.high;
6923  }
6924  /* LOOKATME - how make sure enough room in dest if there is a carry? */
6925  if (carry != 0) *dp = (word32) carry;
6926 }
6927 
6928 /*
6929  * compare only a parts - know wider than WBITS bits
6930  */
6931 static int32 ldiv_cmp(register word32 *u, register word32 *v, int32 wlen)
6932 {
6933  register int32 i;
6934 
6935  /* know unused parts of high words will both be zero */
6936  for (i = wlen - 1; i >= 0; i--)
6937   {
6938    if (u[i] < v[i]) return(-1);
6939    else if (u[i] > v[i]) return(1);
6940   }
6941  return(0);
6942 }
6943 
6944 /*
6945  * divide a number by 1 half word32 (digit based 16 bits)
6946  * notice all values must be separate addresses
6947  *
6948  * also quot and rem assumed to be initialized to 0 before passing to here
6949  * also this works on words not half words
6950  */
6951 extern void __by16_ldivmod(word32 *quot, word32 *r0, word32 *u, word32 v0, int32 ublen)
6952 {
6953  register int32 i;
6954  int32 uwlen;
6955  word32 r, newn;
6956 
6957  uwlen = wlen_(ublen);
6958  r = 0L;
6959  for (i = uwlen - 1; i >= 0; i--)
6960   {
6961    newn = r*SHORTBASE + (u[i] >> (WBITS/2));
6962    quot[i] = (newn / v0) << (WBITS/2);
6963    r = newn % v0;
6964    /* notice since r < d0, newn / v0 will aways fit in half word32 */
6965    newn = r*SHORTBASE + (u[i] & ALL1HW);
6966    quot[i] |= (newn / v0);
6967    r = newn % v0;
6968   }
6969  *r0 = r;
6970 }
6971