YAP 7.1.0
Regs.h
1/*************************************************************************
2* *
3* YAP Prolog %W% %G% *
4* Yap Prolog was developed at NCCUP - Universidade do Porto *
5* *
6* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
7* *
8**************************************************************************
9* *
10* File: Regs.h *
11* mods: *
12* comments: YAP abstract machine registers *
13* version: $Id: Regs.h,v 1.42 2008-08-12 01:27:22 vsc Exp $ *
14*************************************************************************/
15
16#ifndef REGS_H
17#define REGS_H 1
18
19#include <amidefs.h>
20
21/********* abstract machine registers **********************************/
22#ifdef YAP_H
23#include "cut_c.h"
24#endif
25
26#define MaxTemps (128*512)
27#define MaxArithms 32
28
29#ifdef i386
30#define PUSH_REGS 1
31#undef PUSH_X
32#endif
33
34#ifdef sparc
35#define PUSH_REGS 1
36#undef PUSH_X
37#endif
38
39#ifdef __x86_64__
40#define PUSH_REGS 1
41#undef PUSH_X
42#endif
43
44#ifdef __alpha
45#undef PUSH_REGS
46#undef PUSH_X
47#endif
48
49#if defined(_POWER) || defined(__POWERPC__)
50#undef PUSH_REGS
51#undef PUSH_X
52#endif
53
54#ifdef hppa
55#undef PUSH_REGS
56#undef PUSH_X
57#endif
58
59
60/* force a cache of WAM regs for multi-threaded architectures! */
61#ifdef THREADS
62#ifndef PUSH_REGS
63#define PUSH_REGS 1
64#endif
65#ifndef PUSH_X
66#define PUSH_X 1
67#endif
68#endif
69
70#if _MSC_VER
71// no support for __builtin_expect
72#define __builtin_expect(Exp, Val) (Exp)
73#endif
74
75#include "inline-only.h"
76
77INLINE_ONLY void restore_machine_regs(void);
78INLINE_ONLY void save_machine_regs(void);
79INLINE_ONLY void restore_H(void);
80INLINE_ONLY void save_H(void);
81INLINE_ONLY void restore_B(void);
82INLINE_ONLY void save_B(void);
83
84#define CACHE_REGS
85#define REFRESH_CACHE_REGS
86#define INIT_REGS
87#define PASS_REGS1
88#define PASS_REGS
89#define USES_REGS1 void
90#define USES_REGS
91#define WORKER_REGS(WID)
92
93typedef struct regstore_t
94 {
95 CELL EventFlag_; /* 13 */
96 CELL CreepFlag_; /* 13 */
97 yamop *P_; /* 7 prolog machine program counter */
98 CELL *HB_; /* 4 heap (global) stack top at latest c.p. */
99#if defined(YAPOR_SBA) || defined(TABLING)
100 choiceptr BB_; /* 4 local stack top at latest c.p. */
101#endif /* YAPOR_SBA || TABLING */
102 CELL *H0_; /* 2 base of heap (global) stack */
103 tr_fr_ptr TR_; /* 24 top of trail */
104 CELL *H_; /* 25 top of heap (global) stack */
105 choiceptr B_; /* 26 latest choice point */
106#ifdef DEPTH_LIMIT
107 CELL DEPTH_; /* 27 */
108#endif /* DEPTH_LIMIT */
109 yamop *CP_; /* 28 continuation program counter */
110 CELL *ENV_; /* 1 current environment */
111 struct cut_c_str *CUT_C_TOP;
112
113 CELL *YENV_; /* 5 current environment (may differ from ENV)*/
114 CELL *S_; /* 6 structure pointer */
115 CELL *ASP_; /* 8 top of local stack */
116 CELL *LCL0_; /* 3 local stack base */
117 tr_fr_ptr CurrentTrailTop_; /* 10 Auxiliary stack top */
118 ADDR AuxBase_; /* 9 Auxiliary base pointer */
119 CELL *AuxSp_; /* 9 Auxiliary stack pointer */
120 ADDR AuxTop_; /* 10 Auxiliary stack top */
121/* visualc*/
122 Term CurrentModule_;
123 struct myddas_global *MYDDAS_GLOBAL_POINTER;
124#if defined(YAPOR_SBA) || defined(TABLING)
125 CELL *H_FZ_;
126 choiceptr B_FZ_;
127 tr_fr_ptr TR_FZ_;
128#endif /* YAPOR_SBA || TABLING */
129 struct pred_entry *PP_;
130#if defined(YAPOR) || defined(THREADS)
131 unsigned int worker_id_;
132 struct worker_local *worker_local_;
133 /* recursive write-locks for PredEntry */
134 yamop **PREG_ADDR_;
135#ifdef YAPOR_SBA
136 choiceptr BSEG_;
137 struct or_frame *frame_head_, *frame_tail_;
138 char *binding_array_;
139 int sba_offset_;
140 int sba_end_;
141 int sba_size_;
142#endif /* YAPOR_SBA */
143#endif /* YAPOR || THREADS */
144#if PUSH_REGS
145 /* On a X86 machine, the best solution is to keep the
146 X registers on a global variable, whose address is known between
147 runs, and to push the remaining registers to the stack.
148
149 On a register based machine, one can have a dedicated register,
150 always pointing to the XREG global variable. This spends an
151 extra register, but makes it easier to access X[1].
152 */
153
154#ifdef PUSH_X
155 Term XTERMS[MaxTemps]; /* 29 */
156#endif
157 yamop *ARITH_EXCEPTION_;
158 }
160
161extern REGSTORE *Yap_regp;
162
163#ifdef PUSH_X
164
165#define XREGS (Yap_REGS.XTERMS)
166
167#else
168
169/* keep X as a global variable */
170
171extern Term Yap_XREGS[MaxTemps]; /* 29 */
172
173#define XREGS Yap_XREGS
174
175#endif
176
177#ifdef THREADS
178
179extern pthread_key_t Yap_yaamregs_key;
180
181#undef CACHE_REGS
182#undef REFRESH_CACHE_REGS
183#undef INIT_REGS
184#undef CACHE_REGS
185#undef PASS_REGS
186#undef PASS_REGS1
187#undef USES_REGS
188#undef USES_REGS1
189#undef WORKER_REGS
190#define CACHE_REGS REGSTORE *regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
191#define REFRESH_CACHE_REGS regcache = ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key));
192#define INIT_REGS , ((REGSTORE *)pthread_getspecific(Yap_yaamregs_key))
193#define WORKER_REGS(WID) REGSTORE *regcache = REMOTE_ThreadHandle(WID).current_yaam_regs;
194#define PASS_REGS1 regcache
195#define PASS_REGS , regcache
196#define USES_REGS1 struct regstore_t *regcache
197#define USES_REGS , struct regstore_t *regcache
198#define Yap_regp regcache
199
200#endif
201
202#define Yap_REGS ((*Yap_regp))
203
204#else /* !PUSH_REGS */
205
206 Term X[MaxTemps]; /* 29 */
207
208#define XREGS Yap_REGS.X
209 }
211
212extern REGSTORE Yap_REGS;
213#endif /* PUSH_REGS */
214
215#define MinTrailGap (sizeof(CELL)*1024)
216#define MinHeapGap (sizeof(CELL)*4096)
217#define MinStackGap (sizeof(CELL)*8*1024)
218
219
220#define ENV Yap_REGS.ENV_ /* current environment */
221#define ASP Yap_REGS.ASP_ /* top of local stack */
222#define H0 Yap_REGS.H0_ /* base of heap (global) stack */
223#define LCL0 Yap_REGS.LCL0_ /* local stack base */
224
225#define YENV2MEM
226#define YENV_ADDRESS (&(YENV))
227#define MEM2YENV
228
229#if defined(__GNUC__) && defined(__alpha)
230
231#define P Yap_REGS.P_ /* prolog machine program counter */
232#define YENV Yap_REGS.YENV_ /* current environment (may differ from ENV) */
233register CELL *HR asm ("$9");
234register CELL *HB asm ("$10");
235register choiceptr B asm ("$11");
236register yamop *CP asm ("$12");
237register CELL *S asm ("$13");
238register tr_fr_ptr TR asm ("$14");
239/* gcc+debug chokes if $15 is in use on alphas */
240#ifdef DEBUG
241#define CreepFlag Yap_REGS.CreepFlag_
242#else
243register CELL CreepFlag asm ("$15");
244#endif
245
246/* Interface with foreign code, make sure the foreign code sees all the
247 registers the way they used to be */
248INLINE_ONLY inline void save_machine_regs(void) {
249 Yap_REGS.H_ = HR;
250 Yap_REGS.HB_ = HB;
251 Yap_REGS.B_ = B;
252 Yap_REGS.CP_ = CP;
253#ifndef DEBUG
254 Yap_REGS.CreepFlag_ = CreepFlag;
255#endif
256 Yap_REGS.TR_ = TR;
257}
258
259INLINE_ONLY inline void restore_machine_regs(void) {
260 HR = Yap_REGS.H_;
261 HB = Yap_REGS.HB_;
262 B = Yap_REGS.B_;
263 CP = Yap_REGS.CP_;
264#ifndef DEBUG
265 CreepFlag = Yap_REGS.CreepFlag_;
266#endif
267 TR = Yap_REGS.TR_;
268}
269
270#define BACKUP_MACHINE_REGS() \
271 CELL *BK_H = H; \
272 CELL *BK_HB = HB; \
273 choiceptr BK_B = B; \
274 CELL BK_CreepFlag = CreepFlag; \
275 yamop *BK_CP = CP; \
276 tr_fr_ptr BK_TR = TR; \
277 restore_machine_regs()
278
279#define RECOVER_MACHINE_REGS() \
280 save_machine_regs(); \
281 H = BK_H; \
282 HB = BK_HB; \
283 B = BK_B; \
284 CreepFlag = BK_CreepFlag; \
285 CP = BK_CP; \
286 TR = BK_TR
287
288INLINE_ONLY inline void save_H(void) {
289 Yap_REGS.H_ = HR;
290}
291
292INLINE_ONLY inline void restore_H(void) {
293 HR = Yap_REGS.H_;
294}
295
296#define BACKUP_H() CELL *BK_H = HR; restore_H()
297
298#define RECOVER_H() save_H(); HR = BK_H
299
300INLINE_ONLY inline void save_B(void) {
301 Yap_REGS.B_ = B;
302}
303
304INLINE_ONLY inline void restore_B(void) {
305 B = Yap_REGS.B_;
306}
307
308#define BACKUP_B() choiceptr BK_B = B; restore_B()
309
310#define RECOVER_B() save_B(); B = BK_B
311
312INLINE_ONLY void restore_TR(void);
313INLINE_ONLY void save_TR(void);
314
315INLINE_ONLY inline void save_TR(void) {
316 Yap_REGS.TR_ = TR;
317}
318
319INLINE_ONLY inline void restore_TR(void) {
320 TR = Yap_REGS.TR_;
321}
322
323#elif defined(__GNUC__) && defined(hppa)
324
325#define P Yap_REGS.P_ /* prolog machine program counter */
326#define YENV Yap_REGS.YENV_ /* current environment (may differ from ENV) */
327register CELL *HR asm ("r12");
328register CELL *HB asm ("r13");
329register choiceptr B asm ("r14");
330register yamop *CP asm ("r15");
331register CELL *S asm ("r16");
332register CELL CreepFlag asm ("r17");
333register tr_fr_ptr TR asm ("r18");
334
335INLINE_ONLY inline void save_machine_regs(void) {
336 Yap_REGS.H_ = HR;
337 Yap_REGS.HB_ = HB;
338 Yap_REGS.B_ = B;
339 Yap_REGS.CP_ = CP;
340 Yap_REGS.CreepFlag_ = CreepFlag;
341 Yap_REGS.TR_ = TR;
342}
343
344INLINE_ONLY inline void restore_machine_regs(void) {
345 HR = Yap_REGS.H_;
346 HB = Yap_REGS.HB_;
347 B = Yap_REGS.B_;
348 CP = Yap_REGS.CP_;
349 CreepFlag = Yap_REGS.CreepFlag_;
350 TR = Yap_REGS.TR_;
351}
352
353#define BACKUP_MACHINE_REGS() \
354 CELL *BK_H = HR; \
355 CELL *BK_HB = HB; \
356 choiceptr BK_B = B; \
357 CELL BK_CreepFlag = CreepFlag; \
358 yamop *BK_CP = CP; \
359 tr_fr_ptr BK_TR = TR; \
360 restore_machine_regs()
361
362#define RECOVER_MACHINE_REGS() \
363 save_machine_regs(); \
364 HR = BK_H; \
365 HB = BK_HB; \
366 B = BK_B; \
367 CreepFlag = BK_CreepFlag; \
368 CP = BK_CP; \
369 TR = BK_TR
370
371INLINE_ONLY inline void save_H(void) {
372 Yap_REGS.H_ = HR;
373}
374
375INLINE_ONLY inline void restore_H(void) {
376 HR = Yap_REGS.H_;
377}
378
379#define BACKUP_H() CELL *BK_H = HR; restore_H()
380
381#define RECOVER_H() save_H(); HR = BK_H
382
383INLINE_ONLY inline void save_B(void) {
384 Yap_REGS.B_ = B;
385}
386
387INLINE_ONLY inline void restore_B(void) {
388 B = Yap_REGS.B_;
389}
390
391#define BACKUP_B() choiceptr BK_B = B; restore_B()
392
393#define RECOVER_B() save_B(); B = BK_B
394
395INLINE_ONLY void restore_TR(void);
396INLINE_ONLY void save_TR(void);
397
398INLINE_ONLY inline void save_TR(void) {
399 Yap_REGS.TR_ = TR;
400}
401
402INLINE_ONLY inline void restore_TR(void) {
403 TR = Yap_REGS.TR_;
404}
405
406#elif defined(__GNUC__) && (defined(_POWER) || defined(__POWERPC__))
407
408/*
409
410 Because of a bug in GCC, we should always start from the first available
411 general register. According to rs6000.h, this is r13 everywhere
412 except for svr4 machines, where r13 is fixed.
413
414 If we don't do so, GCC will generate move multiple instructions for
415 entering complex functions. These instructions will save and
416 restore the global registers :-(.
417
418 */
419#define CreepFlag Yap_REGS.CreepFlag_
420/*
421 vsc: this MUST start from register 13, otherwise GCC will break down in flames and
422 use the registers for evil purposes. :-(
423 */
424#ifndef __svr4__
425register tr_fr_ptr TR asm ("r13");
426#else
427register tr_fr_ptr TR asm ("r21");
428#endif
429register CELL *HR asm ("r14");
430register CELL *HB asm ("r15");
431register choiceptr B asm ("r16");
432register yamop *CP asm ("r17");
433register CELL *S asm ("r18");
434register CELL *YENV asm ("r19");
435#define P Yap_REGS.P_ /* prolog machine program counter */
436
437#undef YENV2MEM
438#undef YENV_ADDRESS (&(YENV))
439#undef MEM2YENV
440
441#define YENV2MEM { CELL *YENV_MEM = YENV
442#define YENV_ADDRESS (&YENV_MEM)
443#define MEM2YENV YENV = YENV_MEM; }
444
445
446
447INLINE_ONLY void save_machine_regs(void) {
448 Yap_REGS.H_ = HR;
449 Yap_REGS.HB_ = HB;
450 Yap_REGS.B_ = B;
451 Yap_REGS.CP_ = CP;
452 Yap_REGS.YENV_ = YENV;
453 Yap_REGS.TR_ = TR;
454}
455
456INLINE_ONLY void restore_machine_regs(void) {
457 HR = Yap_REGS.H_;
458 HB = Yap_REGS.HB_;
459 B = Yap_REGS.B_;
460 CP = Yap_REGS.CP_;
461 YENV = Yap_REGS.YENV_;
462 TR = Yap_REGS.TR_;
463}
464
465#define BACKUP_MACHINE_REGS() \
466 CELL *BK_H = HR; \
467 CELL *BK_HB = HB; \
468 choiceptr BK_B = B; \
469 yamop *BK_CP = CP; \
470 tr_fr_ptr BK_TR = TR; \
471 restore_machine_regs()
472
473#define RECOVER_MACHINE_REGS() \
474 save_machine_regs(); \
475 HR = BK_H; \
476 HB = BK_HB; \
477 B = BK_B; \
478 CP = BK_CP; \
479 TR = BK_TR
480
481INLINE_ONLY void save_H(void) {
482 Yap_REGS.H_ = HR;
483}
484
485INLINE_ONLY void restore_H(void) {
486 HR = Yap_REGS.H_;
487}
488
489#define BACKUP_H() CELL *BK_H = HR; restore_H()
490
491#define RECOVER_H() save_H(); HR = BK_H
492
493INLINE_ONLY void save_B(void) {
494 Yap_REGS.B_ = B;
495}
496
497INLINE_ONLY void restore_B(void) {
498 B = Yap_REGS.B_;
499}
500
501#define BACKUP_B() choiceptr BK_B = B; restore_B()
502
503#define RECOVER_B() save_B(); B = BK_B
504
505INLINE_ONLY void restore_TR(void);
506INLINE_ONLY void save_TR(void);
507
508INLINE_ONLY void save_TR(void) {
509 Yap_REGS.TR_ = TR;
510}
511
512INLINE_ONLY void restore_TR(void) {
513 TR = Yap_REGS.TR_;
514}
515
516#else
518#define CP (Yap_REGS.CP_)
519#define P Yap_REGS.P_ /* prolog machine program counter */
521#define YENV (Yap_REGS).YENV_
522#define S Yap_REGS.S_ /* structure pointer */
523#define HR Yap_REGS.H_ /* top of heap (global) stack */
524#define B Yap_REGS.B_ /* latest choice point */
525#define TR Yap_REGS.TR_ /* top of trail */
526#define HB Yap_REGS.HB_ /* heap (global) stack top at time of latest c.p. */
527#define CreepFlag Yap_REGS.CreepFlag_
528
529INLINE_ONLY void save_machine_regs(void) {}
530INLINE_ONLY void restore_machine_regs(void) {}
531
532#define BACKUP_MACHINE_REGS() {}
533
534#define RECOVER_MACHINE_REGS() {}
535
536INLINE_ONLY void save_H(void) {}
537
538INLINE_ONLY void restore_H(void) {}
539
540#define BACKUP_H()
541
542#define RECOVER_H()
543
544INLINE_ONLY void save_B(void) {
545}
546
547INLINE_ONLY void restore_B(void) {
548}
549
550#define BACKUP_B()
551
552#define RECOVER_B()
553
554#define restore_TR()
555
556#endif
557
558#define AuxBase Yap_REGS.AuxBase_
559#define AuxSp Yap_REGS.AuxSp_
560#define AuxTop Yap_REGS.AuxTop_
561#define CurrentTrailTop Yap_REGS.CurrentTrailTop_
562#define DEPTH Yap_REGS.DEPTH_
563#if defined(YAPOR_SBA) || defined(TABLING)
564#define H_FZ Yap_REGS.H_FZ_
565#define B_FZ Yap_REGS.B_FZ_
566#define TR_FZ Yap_REGS.TR_FZ_
567#endif /* YAPOR_SBA || TABLING */
568#define PP (Yap_REGS.PP_)
569#if defined(YAPOR) || defined(THREADS)
570#define worker_id (Yap_REGS.worker_id_)
571#define LOCAL (Yap_REGS.worker_local_)
572#define PREG_ADDR (Yap_REGS.PREG_ADDR_)
573#ifdef YAPOR_SBA
574#define binding_array Yap_REGS.binding_array_
575#define BSEG Yap_REGS.BSEG_
576#define sba_offset Yap_REGS.sba_offset_
577#define sba_end Yap_REGS.sba_end_
578#define sba_size Yap_REGS.sba_size_
579#define frame_head Yap_REGS.frame_head_
580#define frame_tail Yap_REGS.frame_tail_
581#endif /* YAPOR_SBA */
582#else
583#define worker_id 0
584#define LOCAL (&Yap_local)
585#endif /* YAPOR || THREADS */
586#define CurrentModule Yap_REGS.CurrentModule_
587#define ARITH_EXCEPTION Yap_REGS.ARITH_EXCEPTION_
588#define Yap_isint Yap_REGS.isint_
589#define Yap_Floats Yap_REGS.Floats_
590#define Yap_Ints Yap_REGS.Ints_
591#define EventFlag Yap_REGS.EventFlag_
592
593#define REG_SIZE sizeof(REGS)/sizeof(CELL *)
594
595#define ARG1 XREGS[1]
596#define ARG2 XREGS[2]
597#define ARG3 XREGS[3]
598#define ARG4 XREGS[4]
599#define ARG5 XREGS[5]
600#define ARG6 XREGS[6]
601#define ARG7 XREGS[7]
602#define ARG8 XREGS[8]
603#define ARG9 XREGS[9]
604#define ARG10 XREGS[10]
605#define ARG11 XREGS[11]
606#define ARG12 XREGS[12]
607#define ARG13 XREGS[13]
608#define ARG14 XREGS[14]
609#define ARG15 XREGS[15]
610#define ARG16 XREGS[16]
611
612/* by default, define HBREG to be HB */
613
614#define HBREG HB
615
616#if defined(YAPOR_SBA) || defined(TABLING)
617#define BB Yap_REGS.BB_
618#define BBREG BB
619#endif /* YAPOR_SBA || TABLING */
620
621// define how to handle frozen segments in tabling, etv.
622#ifdef FROZEN_STACKS
623#ifdef YAPOR_SBA
624#define PROTECT_FROZEN_H(CPTR) \
625 ((Unsigned((Int)((CPTR)->cp_h)-(Int)(H_FZ)) < \
626 Unsigned((Int)(B_FZ)-(Int)(H_FZ))) ? \
627 (CPTR)->cp_h : H_FZ)
628#define PROTECT_FROZEN_B(CPTR) \
629 ((Unsigned((Int)(CPTR)-(Int)(H_FZ)) < \
630 Unsigned((Int)(B_FZ)-(Int)(H_FZ))) ? \
631 (CPTR) : B_FZ)
632 /*
633#define PROTECT_FROZEN_H(CPTR) ((CPTR)->cp_h > H_FZ && (CPTR)->cp_h < (CELL *)B_FZ ? (CPTR)->cp_h : H_FZ )
634
635#define PROTECT_FROZEN_B(CPTR) ((CPTR) < B_FZ && (CPTR) > (choiceptr)H_FZ ? (CPTR) : B_FZ )
636 */
637#else /* TABLING */
638#define PROTECT_FROZEN_B(CPTR) (YOUNGER_CP(CPTR, B_FZ) ? CPTR : B_FZ)
639#define PROTECT_FROZEN_H(CPTR) (((CPTR)->cp_h > H_FZ) ? (CPTR)->cp_h : H_FZ)
640#endif /* YAPOR_SBA */
641#else
642#define PROTECT_FROZEN_B(CPTR) (CPTR)
643#define PROTECT_FROZEN_H(CPTR) (CPTR)->cp_h
644#endif /* FROZEN_STACKS */
645
646
647#if !defined(THREADS)
648/* use actual addresses for regs */
649#define PRECOMPUTE_REGADDRESS 1
650#endif /* THREADS */
651
652
653/* aggregate several abstract machine operations in a single */
654#define AGGREGATE_OPS 1
655
656/* make standard registers globally accessible so that they are there
657 when we come from a longjmp */
658#if PUSH_REGS
659/* In this case we need to initialize the abstract registers */
660extern REGSTORE Yap_standard_regs;
661#endif /* PUSH_REGS */
662
663/******************* controlling debugging ****************************/
664static inline UInt
665StackGap( USES_REGS1 )
666{
667 UInt gmin = (LCL0-H0)>>2;
668
669 if (gmin < MinStackGap) gmin = MinStackGap;
670 // if (gmin > 1024*1024) return 1024*1024;
671 return gmin;
672}
673
674static inline void
675CalculateStackGap( USES_REGS1 )
676{
677 CreepFlag = EventFlag = StackGap( PASS_REGS1 );
678}
679
680#define AS_CELLS(S) -((S)/sizeof(CELL))
681
682#define SET_ASP(Y,S) SET_ASP__(Y,S PASS_REGS)
683
684// sz is the* number of cells neededsfFFF
685static inline
686void SET_ASP__(CELL *yreg, size_t sz USES_REGS) {
687 ASP = yreg - sz;
688 if (ASP > (CELL *)PROTECT_FROZEN_B(B))
689 ASP = (CELL *)PROTECT_FROZEN_B(B);
690}
691
692#endif
693
694
Definition: Yatom.h:544
Definition: amidefs.h:264