[project @ 2002-06-26 08:18:38 by stolz]
[ghc-hetmet.git] / ghc / rts / PrimOps.hc
index 083031a..44bedf6 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.87 2001/12/06 13:05:03 sewardj Exp $
+ * $Id: PrimOps.hc,v 1.99 2002/06/26 08:18:41 stolz Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -244,40 +244,57 @@ StgWord GHC_ZCCReturnable_static_info[1];
 
 #define BYTES_TO_STGWORDS(n) ((n) + sizeof(W_) - 1)/sizeof(W_)
 
-FN_(newByteArrayzh_fast)                               \
- {                                                     \
-   W_ size, stuff_size, n;                             \
-   StgArrWords* p;                                     \
-   FB_                                                 \
-     MAYBE_GC(NO_PTRS,newByteArrayzh_fast);            \
-     n = R1.w;                                         \
-     stuff_size = BYTES_TO_STGWORDS(n);                        \
-     size = sizeofW(StgArrWords)+ stuff_size;          \
-     p = (StgArrWords *)RET_STGCALL1(P_,allocate,size);        \
-     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0); \
-     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);            \
-     p->words = stuff_size;                            \
-     TICK_RET_UNBOXED_TUP(1)                           \
-     RET_P(p);                                         \
-   FE_                                                 \
+FN_(newByteArrayzh_fast)
+ {
+   W_ size, stuff_size, n;
+   StgArrWords* p;
+   FB_
+     MAYBE_GC(NO_PTRS,newByteArrayzh_fast);
+     n = R1.w;
+     stuff_size = BYTES_TO_STGWORDS(n);
+     size = sizeofW(StgArrWords)+ stuff_size;
+     p = (StgArrWords *)RET_STGCALL1(P_,allocate,size);
+     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);
+     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);
+     p->words = stuff_size;
+     TICK_RET_UNBOXED_TUP(1)
+     RET_P(p);
+   FE_
  }
 
-FN_(newPinnedByteArrayzh_fast)                                 \
- {                                                             \
-   W_ size, stuff_size, n;                                     \
-   StgArrWords* p;                                             \
-   FB_                                                         \
-     MAYBE_GC(NO_PTRS,newPinnedByteArrayzh_fast);              \
-     n = R1.w;                                                 \
-     stuff_size = BYTES_TO_STGWORDS(n);                                \
-     size = sizeofW(StgArrWords)+ stuff_size;                  \
-     p = (StgArrWords *)RET_STGCALL1(P_,allocatePinned,size);  \
-     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);       \
-     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);                    \
-     p->words = stuff_size;                                    \
-     TICK_RET_UNBOXED_TUP(1)                                   \
-     RET_P(p);                                                 \
-   FE_                                                         \
+FN_(newPinnedByteArrayzh_fast)
+ {
+   W_ size, stuff_size, n;
+   StgArrWords* p;
+   FB_
+     MAYBE_GC(NO_PTRS,newPinnedByteArrayzh_fast);
+     n = R1.w;
+     stuff_size = BYTES_TO_STGWORDS(n);
+
+     // We want an 8-byte aligned array.  allocatePinned() gives us
+     // 8-byte aligned memory by default, but we want to align the
+     // *goods* inside the ArrWords object, so we have to check the
+     // size of the ArrWords header and adjust our size accordingly.
+     size = sizeofW(StgArrWords)+ stuff_size;
+     if ((sizeof(StgArrWords) & 7) != 0) {
+        size++;
+     }
+
+     p = (StgArrWords *)RET_STGCALL1(P_,allocatePinned,size);
+     TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0);
+
+     // Again, if the ArrWords header isn't a multiple of 8 bytes, we
+     // have to push the object forward one word so that the goods
+     // fall on an 8-byte boundary.
+     if ((sizeof(StgArrWords) & 7) != 0) {
+        ((StgPtr)p)++;
+     }
+
+     SET_HDR(p, &stg_ARR_WORDS_info, CCCS);
+     p->words = stuff_size;
+     TICK_RET_UNBOXED_TUP(1)
+     RET_P(p);
+   FE_
  }
 
 FN_(newArrayzh_fast)
@@ -774,11 +791,14 @@ FN_(gcdIntzh_fast)
 {
   /* R1 = the first Int#; R2 = the second Int# */
   mp_limb_t aa;
-  I_        r;
+  I_ r;
   FB_
   aa = (mp_limb_t)(R1.i);
   r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(&aa), 1, (mp_limb_t)(R2.i));
-  RET_N(r);
+
+  R1.i = r;
+  /* Result parked in R1, return via info-pointer at TOS */
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
@@ -787,42 +807,99 @@ FN_(gcdIntegerIntzh_fast)
   /* R1 = s1; R2 = d1; R3 = the int */
   I_ r;
   FB_
-  MAYBE_GC(R2_PTR, gcdIntegerIntzh_fast);
-  r = RET_STGCALL3(I_,mpn_gcd_1,(mp_limb_t *)(BYTE_ARR_CTS(R2.p)), R1.i, R3.i);
-  RET_N(r);
+  r = RET_STGCALL3(StgInt,mpn_gcd_1,(mp_limb_t *)(BYTE_ARR_CTS(R2.p)), R1.i, R3.i);
+
+  R1.i = r;
+  /* Result parked in R1, return via info-pointer at TOS */
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
 FN_(cmpIntegerIntzh_fast)
 {
   /* R1 = s1; R2 = d1; R3 = the int */
-  MP_INT arg;
-  I_ r;
+  I_ usize;
+  I_ vsize;
+  I_ v_digit;
+  mp_limb_t u_digit;
   FB_
-  MAYBE_GC(R2_PTR, cmpIntegerIntzh_fast);
-  arg._mp_size = R1.i;
-  arg._mp_alloc = ((StgArrWords *)R2.p)->words;
-  arg._mp_d    = (mp_limb_t *) (BYTE_ARR_CTS(R2.p));
-  r = RET_STGCALL2(I_,mpz_cmp_si,&arg,R3.i);
-  RET_N(r);
+
+  usize = R1.i;
+  vsize = 0;
+  v_digit = R3.i;
+
+  // paraphrased from mpz_cmp_si() in the GMP sources
+  if (v_digit > 0) {
+      vsize = 1;
+  } else if (v_digit < 0) {
+      vsize = -1;
+      v_digit = -v_digit;
+  }
+
+  if (usize != vsize) {
+    R1.i = usize - vsize; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  if (usize == 0) {
+    R1.i = 0; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  u_digit = *(mp_limb_t *)(BYTE_ARR_CTS(R2.p));
+
+  if (u_digit == (mp_limb_t) (unsigned long) v_digit) {
+    R1.i = 0; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  if (u_digit > (mp_limb_t) (unsigned long) v_digit) {
+    R1.i = usize; 
+  } else {
+    R1.i = -usize; 
+  }
+
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
 FN_(cmpIntegerzh_fast)
 {
   /* R1 = s1; R2 = d1; R3 = s2; R4 = d2 */
-  MP_INT arg1, arg2;
-  I_ r;
+  I_ usize;
+  I_ vsize;
+  I_ size;
+  StgPtr up, vp;
+  int cmp;
   FB_
-  MAYBE_GC(R2_PTR | R4_PTR, cmpIntegerIntzh_fast);
-  arg1._mp_size        = R1.i;
-  arg1._mp_alloc= ((StgArrWords *)R2.p)->words;
-  arg1._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(R2.p));
-  arg2._mp_size        = R3.i;
-  arg2._mp_alloc= ((StgArrWords *)R4.p)->words;
-  arg2._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(R4.p));
-  r = RET_STGCALL2(I_,mpz_cmp,&arg1,&arg2);
-  RET_N(r);
+
+  // paraphrased from mpz_cmp() in the GMP sources
+  usize = R1.i;
+  vsize = R3.i;
+
+  if (usize != vsize) {
+    R1.i = usize - vsize; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  if (usize == 0) {
+    R1.i = 0; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  size = abs(usize);
+
+  up = BYTE_ARR_CTS(R2.p);
+  vp = BYTE_ARR_CTS(R4.p);
+
+  cmp = RET_STGCALL3(I_, mpn_cmp, (mp_limb_t *)up, (mp_limb_t *)vp, size);
+
+  if (cmp == 0) {
+    R1.i = 0; JMP_(ENTRY_CODE(Sp[0]));
+  }
+
+  if ((cmp < 0) == (usize < 0)) {
+    R1.i = 1;
+  } else {
+    R1.i = (-1); 
+  }
+  /* Result parked in R1, return via info-pointer at TOS */
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
@@ -838,7 +915,9 @@ FN_(integer2Intzh_fast)
     r = ((mp_limb_t *) (BYTE_ARR_CTS(R2.p)))[0];
     if (s < 0) r = -r;
   }
-  RET_N(r);
+  /* Result parked in R1, return via info-pointer at TOS */
+  R1.i = r;
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
@@ -855,7 +934,9 @@ FN_(integer2Wordzh_fast)
     r = ((mp_limb_t *) (BYTE_ARR_CTS(R2.p)))[0];
     if (s < 0) r = -r;
   }
-  RET_N(r);
+  /* Result parked in R1, return via info-pointer at TOS */
+  R1.w = r;
+  JMP_(ENTRY_CODE(Sp[0]));
   FE_
 }
 
@@ -935,13 +1016,28 @@ FN_(forkzh_fast)
 
   /* create it right now, return ThreadID in R1 */
   R1.t = RET_STGCALL2(StgTSO *, createIOThread, 
-                     RtsFlags.GcFlags.initialStkSize, R1.cl);
+                    RtsFlags.GcFlags.initialStkSize, R1.cl);
   STGCALL1(scheduleThread, R1.t);
       
   /* switch at the earliest opportunity */ 
   context_switch = 1;
   
+  RET_P(R1.t);
+  FE_
+}
+
+FN_(forkProcesszh_fast)
+{
+  pid_t pid;
+
+  FB_
+  /* args: none */
+  /* result: Pid */
+
+  R1.i = RET_STGCALL1(StgInt, forkProcess, CurrentTSO);
+
   JMP_(ENTRY_CODE(Sp[0]));
+
   FE_
 }
 
@@ -952,6 +1048,28 @@ FN_(yieldzh_fast)
   FE_
 }
 
+FN_(myThreadIdzh_fast)
+{
+  /* no args. */
+  FB_
+  RET_P((P_)CurrentTSO);
+  FE_
+}
+
+FN_(labelThreadzh_fast)
+{
+  FB_
+  /* args: 
+       R1.p = ThreadId#
+       R2.p = Addr# */
+#ifdef DEBUG
+  STGCALL2(labelThread,(StgTSO *)R1.p,(char *)R2.p);
+#endif
+  JMP_(ENTRY_CODE(Sp[0]));
+  FE_
+}
+
+
 /* -----------------------------------------------------------------------------
  * MVar primitives
  *
@@ -1017,14 +1135,23 @@ FN_(newMVarzh_fast)
   FE_
 }
 
-#define PerformTake(tso, value) ({                     \
-    (tso)->sp[1] = (W_)value;                          \
-    (tso)->sp[0] = (W_)&stg_gc_unpt_r1_ret_info;       \
+/* If R1 isn't available, pass it on the stack */
+#ifdef REG_R1
+#define PerformTake(tso, value) ({             \
+    (tso)->sp[1] = (W_)value;                  \
+    (tso)->sp[0] = (W_)&stg_gc_unpt_r1_info;   \
+  })
+#else
+#define PerformTake(tso, value) ({             \
+    (tso)->sp[1] = (W_)value;                  \
+    (tso)->sp[0] = (W_)&stg_ut_1_0_unreg_info; \
   })
+#endif
+
 
 #define PerformPut(tso) ({                             \
     StgClosure *val = (StgClosure *)(tso)->sp[2];      \
-    (tso)->sp[2] = (W_)&stg_gc_noregs_ret_info;                \
+    (tso)->sp[2] = (W_)&stg_gc_noregs_info;            \
     (tso)->sp += 2;                                    \
     val;                                               \
   })
@@ -1163,19 +1290,18 @@ FN_(tryTakeMVarzh_fast)
       /* unlock in the SMP case */
       SET_INFO(mvar,&stg_FULL_MVAR_info);
 #endif
-      TICK_RET_UNBOXED_TUP(1);
-      RET_P(val);
   } else {
       /* No further putMVars, MVar is now empty */
+      mvar->value = (StgClosure *)&stg_END_TSO_QUEUE_closure;
 
       /* do this last... we might have locked the MVar in the SMP case,
        * and writing the info pointer will unlock it.
        */
       SET_INFO(mvar,&stg_EMPTY_MVAR_info);
-      mvar->value = (StgClosure *)&stg_END_TSO_QUEUE_closure;
-      TICK_RET_UNBOXED_TUP(1);
-      RET_P(val);
   }
+
+  TICK_RET_UNBOXED_TUP(1);
+  RET_NP((I_)1, val);
   FE_
 }