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