diff -Naur gdb-6.8.orig/gdb/breakpoint.c gdb-6.8/gdb/breakpoint.c
--- gdb-6.8.orig/gdb/breakpoint.c	2008-02-26 09:14:11.000000000 +0100
+++ gdb-6.8/gdb/breakpoint.c	2008-09-17 16:32:32.000000000 +0200
@@ -55,6 +55,7 @@
 #include "memattr.h"
 #include "ada-lang.h"
 #include "top.h"
+#include "wrapper.h"
 
 #include "gdb-events.h"
 #include "mi/mi-common.h"
@@ -826,7 +827,65 @@
 	  || bpt->type == bp_access_watchpoint);
 }
 
-/* Assuming that B is a hardware breakpoint:
+/* Find the current value of a watchpoint on EXP.  Return the value in
+   *VALP and *RESULTP and the chain of intermediate and final values
+   in *VAL_CHAIN.  RESULTP and VAL_CHAIN may be NULL if the caller does
+   not need them.
+
+   If an error occurs while evaluating the expression, *RESULTP will
+   be set to NULL.  *RESULTP may be a lazy value, if the result could
+   not be read from memory.  It is used to determine whether a value
+   is user-specified (we should watch the whole value) or intermediate
+   (we should watch only the bit used to locate the final value).
+
+   If the final value, or any intermediate value, could not be read
+   from memory, *VALP will be set to NULL.  *VAL_CHAIN will still be
+   set to any referenced values.  *VALP will never be a lazy value.
+   This is the value which we store in struct breakpoint.
+
+   If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the
+   value chain.  The caller must free the values individually.  If
+   VAL_CHAIN is NULL, all generated values will be left on the value
+   chain.  */
+
+static void
+fetch_watchpoint_value (struct expression *exp, struct value **valp,
+			struct value **resultp, struct value **val_chain)
+{
+  struct value *mark, *new_mark, *result;
+
+  *valp = NULL;
+  if (resultp)
+    *resultp = NULL;
+  if (val_chain)
+    *val_chain = NULL;
+
+  /* Evaluate the expression.  */
+  mark = value_mark ();
+  result = NULL;
+  gdb_evaluate_expression (exp, &result);
+  new_mark = value_mark ();
+  if (mark == new_mark)
+    return;
+  if (resultp)
+    *resultp = result;
+
+  /* Make sure it's not lazy, so that after the target stops again we
+     have a non-lazy previous value to compare with.  */
+  if (result != NULL
+      && (!value_lazy (result) || gdb_value_fetch_lazy (result)))
+    *valp = result;
+
+  if (val_chain)
+    {
+      /* Return the chain of intermediate values.  We use this to
+	 decide which addresses to watch.  */
+      *val_chain = new_mark;
+      value_release_to_mark (mark);
+    }
+}
+
+/* Assuming that B is a hardware watchpoint:
    - Reparse watchpoint expression, is REPARSE is non-zero
    - Evaluate expression and store the result in B->val
    - Update the list of values that must be watched in B->loc.
@@ -837,7 +896,6 @@
 update_watchpoint (struct breakpoint *b, int reparse)
 {
   int within_current_scope;
-  struct value *mark = value_mark ();
   struct frame_id saved_frame_id;
   struct bp_location *loc;
   bpstat bs;
@@ -889,9 +947,9 @@
 	 to the user when the old value and the new value may actually
 	 be completely different objects.  */
       value_free (b->val);
-      b->val = NULL;      
+      b->val = NULL;
+      b->val_valid = 0;
     }
-  
 
   /* If we failed to parse the expression, for example because
      it refers to a global variable in a not-yet-loaded shared library,
@@ -900,43 +958,37 @@
      is different from out-of-scope watchpoint.  */
   if (within_current_scope && b->exp)
     {
-      struct value *v, *next;
+      struct value *val_chain, *v, *result, *next;
+
+      fetch_watchpoint_value (b->exp, &v, &result, &val_chain);
 
-      /* Evaluate the expression and make sure it's not lazy, so that
-	 after target stops again, we have a non-lazy previous value
-	 to compare with. Also, making the value non-lazy will fetch
-	 intermediate values as needed, which we use to decide which
-	 addresses to watch.
-
-	 The value returned by evaluate_expression is stored in b->val.
-	 In addition, we look at all values which were created
-	 during evaluation, and set watchoints at addresses as needed.
-	 Those values are explicitly deleted here.  */
-      v = evaluate_expression (b->exp);
       /* Avoid setting b->val if it's already set.  The meaning of
 	 b->val is 'the last value' user saw, and we should update
 	 it only if we reported that last value to user.  As it
 	 happens, the code that reports it updates b->val directly.  */
-      if (b->val == NULL)
-	b->val = v;
-      value_contents (v);
-      value_release_to_mark (mark);
+      if (!b->val_valid)
+	{
+	  b->val = v;
+	  b->val_valid = 1;
+	}
 
       /* Look at each value on the value chain.  */
-      for (; v; v = next)
+      for (v = val_chain; v; v = next)
 	{
 	  /* If it's a memory location, and GDB actually needed
 	     its contents to evaluate the expression, then we
-	     must watch it.  */
+	     must watch it.  If the first value returned is
+	     still lazy, that means an error occurred reading it;
+	     watch it anyway in case it becomes readable.  */
 	  if (VALUE_LVAL (v) == lval_memory
-	      && ! value_lazy (v))
+	      && (v == val_chain || ! value_lazy (v)))
 	    {
 	      struct type *vtype = check_typedef (value_type (v));
 
 	      /* We only watch structs and arrays if user asked
 		 for it explicitly, never if they just happen to
 		 appear in the middle of some value chain.  */
-	      if (v == b->val
+	      if (v == result
 		  || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
 		      && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
 		{
@@ -1681,6 +1733,7 @@
 	    if (b->val)
 	      value_free (b->val);
 	    b->val = NULL;
+	    b->val_valid = 0;
 	  }
 	break;
       default:
@@ -2103,6 +2156,17 @@
   do_cleanups (old_chain);
 }
 
+/* Print out the (old or new) value associated with a watchpoint.  */
+
+static void
+watchpoint_value_print (struct value *val, struct ui_file *stream)
+{
+  if (val == NULL)
+    fprintf_unfiltered (stream, _("<unreadable>"));
+  else
+    value_print (val, stream, 0, Val_pretty_default);
+}
+
 /* This is the normal print function for a bpstat.  In the future,
    much of this logic could (should?) be moved to bpstat_stop_status,
    by having it set different print_it values.
@@ -2221,26 +2285,21 @@
 
     case bp_watchpoint:
     case bp_hardware_watchpoint:
-      if (bs->old_val != NULL)
-	{
-	  annotate_watchpoint (b->number);
-	  if (ui_out_is_mi_like_p (uiout))
-	    ui_out_field_string
-	      (uiout, "reason",
-	       async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
-	  mention (b);
-	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
-	  ui_out_text (uiout, "\nOld value = ");
-	  value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
-	  ui_out_field_stream (uiout, "old", stb);
-	  ui_out_text (uiout, "\nNew value = ");
-	  value_print (b->val, stb->stream, 0, Val_pretty_default);
-	  ui_out_field_stream (uiout, "new", stb);
-	  do_cleanups (ui_out_chain);
-	  ui_out_text (uiout, "\n");
-	  value_free (bs->old_val);
-	  bs->old_val = NULL;
-	}
+      annotate_watchpoint (b->number);
+      if (ui_out_is_mi_like_p (uiout))
+	ui_out_field_string
+	  (uiout, "reason",
+	   async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
+      mention (b);
+      ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
+      ui_out_text (uiout, "\nOld value = ");
+      watchpoint_value_print (bs->old_val, stb->stream);
+      ui_out_field_stream (uiout, "old", stb);
+      ui_out_text (uiout, "\nNew value = ");
+      watchpoint_value_print (b->val, stb->stream);
+      ui_out_field_stream (uiout, "new", stb);
+      do_cleanups (ui_out_chain);
+      ui_out_text (uiout, "\n");
       /* More than one watchpoint may have been triggered.  */
       return PRINT_UNKNOWN;
       break;
@@ -2253,7 +2312,7 @@
       mention (b);
       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
       ui_out_text (uiout, "\nValue = ");
-      value_print (b->val, stb->stream, 0, Val_pretty_default);
+      watchpoint_value_print (b->val, stb->stream);
       ui_out_field_stream (uiout, "value", stb);
       do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
@@ -2261,7 +2320,7 @@
       break;
 
     case bp_access_watchpoint:
-      if (bs->old_val != NULL)     
+      if (bs->old_val != NULL)
 	{
 	  annotate_watchpoint (b->number);
 	  if (ui_out_is_mi_like_p (uiout))
@@ -2271,10 +2330,8 @@
 	  mention (b);
 	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
 	  ui_out_text (uiout, "\nOld value = ");
-	  value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
+	  watchpoint_value_print (bs->old_val, stb->stream);
 	  ui_out_field_stream (uiout, "old", stb);
-	  value_free (bs->old_val);
-	  bs->old_val = NULL;
 	  ui_out_text (uiout, "\nNew value = ");
 	}
       else 
@@ -2287,7 +2344,7 @@
 	  ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
 	  ui_out_text (uiout, "\nValue = ");
 	}
-      value_print (b->val, stb->stream, 0,Val_pretty_default);
+      watchpoint_value_print (b->val, stb->stream);
       ui_out_field_stream (uiout, "new", stb);
       do_cleanups (ui_out_chain);
       ui_out_text (uiout, "\n");
@@ -2574,13 +2631,20 @@
          we might be in the middle of evaluating a function call.  */
 
       struct value *mark = value_mark ();
-      struct value *new_val = evaluate_expression (b->exp);
-      if (!value_equal (b->val, new_val))
+      struct value *new_val;
+
+      fetch_watchpoint_value (b->exp, &new_val, NULL, NULL);
+      if ((b->val != NULL) != (new_val != NULL)
+	  || (b->val != NULL && !value_equal (b->val, new_val)))
 	{
-	  release_value (new_val);
-	  value_free_to_mark (mark);
+	  if (new_val != NULL)
+	    {
+	      release_value (new_val);
+	      value_free_to_mark (mark);
+	    }
 	  bs->old_val = b->val;
 	  b->val = new_val;
+	  b->val_valid = 1;
 	  /* We will stop here */
 	  return WP_VALUE_CHANGED;
 	}
@@ -5722,10 +5786,9 @@
   exp_end = arg;
   exp_valid_block = innermost_block;
   mark = value_mark ();
-  val = evaluate_expression (exp);
-  release_value (val);
-  if (value_lazy (val))
-    value_fetch_lazy (val);
+  fetch_watchpoint_value (exp, &val, NULL, NULL);
+  if (val != NULL)
+    release_value (val);
 
   tok = arg;
   while (*tok == ' ' || *tok == '\t')
@@ -5814,6 +5877,7 @@
   b->exp_valid_block = exp_valid_block;
   b->exp_string = savestring (exp_start, exp_end - exp_start);
   b->val = val;
+  b->val_valid = 1;
   b->loc->cond = cond;
   if (cond_start)
     b->cond_string = savestring (cond_start, cond_end - cond_start);
@@ -7697,11 +7761,11 @@
       if (bpt->val)
 	value_free (bpt->val);
       mark = value_mark ();
-      bpt->val = evaluate_expression (bpt->exp);
-      release_value (bpt->val);
-      if (value_lazy (bpt->val))
-	value_fetch_lazy (bpt->val);
-      
+      fetch_watchpoint_value (bpt->exp, &bpt->val, NULL, NULL);
+      if (bpt->val)
+	release_value (bpt->val);
+      bpt->val_valid = 1;
+
       if (bpt->type == bp_hardware_watchpoint ||
 	  bpt->type == bp_read_watchpoint ||
 	  bpt->type == bp_access_watchpoint)
diff -Naur gdb-6.8.orig/gdb/breakpoint.h gdb-6.8/gdb/breakpoint.h
--- gdb-6.8.orig/gdb/breakpoint.h	2008-02-01 17:24:46.000000000 +0100
+++ gdb-6.8/gdb/breakpoint.h	2008-09-17 16:32:32.000000000 +0200
@@ -391,8 +391,13 @@
     /* The largest block within which it is valid, or NULL if it is
        valid anywhere (e.g. consists just of global symbols).  */
     struct block *exp_valid_block;
-    /* Value of the watchpoint the last time we checked it.  */
+    /* Value of the watchpoint the last time we checked it, or NULL
+       when we do not know the value yet or the value was not
+       readable.  VAL is never lazy.  */
     struct value *val;
+    /* Nonzero if VAL is valid.  If VAL_VALID is set but VAL is NULL,
+       then an error occurred reading the value.  */
+    int val_valid;
 
     /* Holds the address of the related watchpoint_scope breakpoint
        when using watchpoints on local variables (might the concept
diff -Naur gdb-6.8.orig/gdb/NEWS gdb-6.8/gdb/NEWS
--- gdb-6.8.orig/gdb/NEWS	2008-03-27 19:14:10.000000000 +0100
+++ gdb-6.8/gdb/NEWS	2008-09-17 16:32:32.000000000 +0200
@@ -1,6 +1,9 @@
 		What has changed in GDB?
 	     (Organized release by release)
 
+* Watchpoints can now be set on unreadable memory locations, e.g. addresses
+which will be allocated using malloc later in program execution.
+
 *** Changes in GDB 6.8
 
 * New native configurations
diff -Naur gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.c gdb-6.8/gdb/testsuite/gdb.base/watchpoint.c
--- gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.c	2003-03-17 20:51:58.000000000 +0100
+++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint.c	2008-09-17 16:32:32.000000000 +0200
@@ -39,6 +39,8 @@
 
 int doread = 0;
 
+char *global_ptr;
+
 void marker1 ()
 {
 }
@@ -110,6 +112,14 @@
   return 73;
 }
 
+void
+func4 ()
+{
+  buf[0] = 3;
+  global_ptr = buf;
+  buf[0] = 7;
+}
+
 int main ()
 {
 #ifdef usestubs
@@ -185,5 +195,7 @@
 
   func3 ();
 
+  func4 ();
+
   return 0;
 }
diff -Naur gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.exp gdb-6.8/gdb/testsuite/gdb.base/watchpoint.exp
--- gdb-6.8.orig/gdb/testsuite/gdb.base/watchpoint.exp	2008-01-01 23:53:19.000000000 +0100
+++ gdb-6.8/gdb/testsuite/gdb.base/watchpoint.exp	2008-09-17 16:32:32.000000000 +0200
@@ -645,6 +645,30 @@
     }
 }
     
+proc test_inaccessible_watchpoint {} {
+    global gdb_prompt
+
+    # This is a test for watchpoints on currently inaccessible (but later
+    # valid) memory.
+
+    if [runto func4] then {
+	gdb_test "watch *global_ptr" ".*atchpoint \[0-9\]+: \\*global_ptr"
+	gdb_test "next" ".*global_ptr = buf.*"
+	gdb_test_multiple "next" "next over ptr init" {
+	    -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = .*\r\nNew value = 3 .*\r\n.*$gdb_prompt $" {
+		# We can not test for <unknown> here because NULL may be readable.
+		# This test does rely on *NULL != 3.
+		pass "next over ptr init"
+	    }
+	}
+	gdb_test_multiple "next" "next over buffer set" {
+	    -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = 3 .*\r\nNew value = 7 .*\r\n.*$gdb_prompt $" {
+		pass "next over buffer set"
+	    }
+	}
+    }
+}
+    
 # Start with a fresh gdb.
 
 gdb_exit
@@ -797,6 +821,8 @@
       }
     }
 
+    test_inaccessible_watchpoint
+
     # See above.
     if [istarget "mips-idt-*"] then {
 	gdb_exit
diff -Naur gdb-6.8.orig/sim/erc32/erc32.c gdb-6.8/sim/erc32/erc32.c
--- gdb-6.8.orig/sim/erc32/erc32.c	1999-04-16 03:35:00.000000000 +0200
+++ gdb-6.8/sim/erc32/erc32.c	2008-09-17 16:33:00.000000000 +0200
@@ -24,6 +24,7 @@
 
 #include <sys/types.h>
 #include <stdio.h>
+#include <string.h>
 #include <termios.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
@@ -413,7 +414,7 @@
     if (rom8) mec_memcfg &= ~0x20000;
     else mec_memcfg |= 0x20000;
 
-    mem_ramsz = (256 * 1024) << ((mec_memcfg >> 10) & 7);
+    mem_ramsz = (512 * 1024) << ((mec_memcfg >> 10) & 7);
     mem_romsz = (128 * 1024) << ((mec_memcfg >> 18) & 7);
 
     if (sparclite_board) {
@@ -1659,7 +1660,7 @@
 	errmec = 0;
 	return(1);
     }
-#endif;
+#endif
 
     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
 	fetch_bytes (asi, &ramb[addr & mem_rammask], data, sz);
@@ -1736,7 +1737,7 @@
 	errmec = 0;
 	return(1);
     }
-#endif;
+#endif
 
     if ((addr >= mem_ramstart) && (addr < (mem_ramstart + mem_ramsz))) {
 	if (mem_accprot) {
diff -Naur gdb-6.8.orig/sim/erc32/exec.c gdb-6.8/sim/erc32/exec.c
--- gdb-6.8.orig/sim/erc32/exec.c	2005-03-07 12:09:05.000000000 +0100
+++ gdb-6.8/sim/erc32/exec.c	2008-09-17 16:33:00.000000000 +0200
@@ -1713,7 +1713,7 @@
     	    sregs->fdp[rs2 | 1] = sregs->fs[rs2 & ~1];
     	    sregs->fdp[rs2 & ~1] = sregs->fs[rs2 | 1];
     default:
-      ;
+      break;
     }
 #endif
 
@@ -1886,7 +1886,7 @@
 	sregs->fs[rd & ~1] = sregs->fdp[rd | 1];
 	sregs->fs[rd | 1] = sregs->fdp[rd & ~1];
     default:
-      ;
+      break;
     }
 #endif
     if (sregs->fpstate == FP_EXC_PE) {
diff -Naur gdb-6.8.orig/sim/ppc/configure.ac gdb-6.8/sim/ppc/configure.ac
--- gdb-6.8.orig/sim/ppc/configure.ac	2008-03-14 22:35:27.000000000 +0100
+++ gdb-6.8/sim/ppc/configure.ac	2008-09-17 16:33:00.000000000 +0200
@@ -209,10 +209,105 @@
 esac
 ])dnl
 
+AC_CACHE_CHECK([if union semun defined],
+  ac_cv_HAS_UNION_SEMUN,
+  [AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>],
+[union semun arg ;],
+[ac_cv_has_union_semun="yes"],
+[ac_cv_has_union_semun="no"])
+AC_MSG_RESULT($ac_cv_has_union_semun)
+])
+
+
+if test "$ac_cv_has_union_semun" = "yes"; then
+  AC_CACHE_CHECK(whether System V semaphores are supported,
+  ac_cv_sysv_sem,
+  [
+  AC_TRY_RUN(
+  [
+  #include <sys/types.h>
+  #include <sys/ipc.h>
+  #include <sys/sem.h>
+  int main () {
+    union semun arg ;
+
+    int id=semget(IPC_PRIVATE,1,IPC_CREAT|0400);
+    if (id == -1)
+      exit(1);
+    arg.val = 0; /* avoid implicit type cast to union */
+    if (semctl(id, 0, IPC_RMID, arg) == -1)
+      exit(1);
+    exit(0);
+  }
+  ],
+  ac_cv_sysv_sem="yes", ac_cv_sysv_sem="no", :)
+  ])
+else  # semun is not defined
+  AC_CACHE_CHECK(whether System V semaphores are supported,
+  ac_cv_sysv_sem,
+  [
+  AC_TRY_RUN(
+  [
+  #include <sys/types.h>
+  #include <sys/ipc.h>
+  #include <sys/sem.h>
+  union semun {
+    int val;
+    struct semid_ds *buf;
+    ushort *array;
+  };
+  int main () {
+    union semun arg ;
+
+    int id=semget(IPC_PRIVATE,1,IPC_CREAT|0400);
+    if (id == -1)
+      exit(1);
+    arg.val = 0; /* avoid implicit type cast to union */
+    if (semctl(id, 0, IPC_RMID, arg) == -1)
+      exit(1);
+    exit(0);
+  }
+  ],
+  ac_cv_sysv_sem="yes", ac_cv_sysv_sem="no", :)
+  ])
+fi
+
+AC_CACHE_CHECK(whether System V shared memory is supported,
+ac_cv_sysv_shm,
+[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+int main () {
+  int id=shmget(IPC_PRIVATE,1,IPC_CREAT|0400);
+  if (id == -1)
+    exit(1);
+  if (shmctl(id, IPC_RMID, 0) == -1)
+    exit(1);
+  exit(0);
+}
+],
+ac_cv_sysv_shm="yes", ac_cv_sysv_shm="no", :)
+])
+
+if test x"$ac_cv_sysv_shm" = x"yes" -a x"$ac_cv_sysv_sem" = x"yes" ; then
+  sim_sysv_ipc_hw=",sem,shm";
+else
+  sim_sysv_ipc_hw="";
+fi
+
+if test x"$ac_cv_has_union_semun" = x"yes" -a x"$ac_cv_sysv_sem" = x"yes" ; then
+  sim_hwflags="-DHAS_UNION_SEMUN";
+fi
+
 
 AC_ARG_ENABLE(sim-hardware,
 [  --enable-sim-hardware=list		Specify the hardware to be included in the build.],
-[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide${sim_sysv_ipc_hw}"
 case "${enableval}" in
   yes)	;;
   no)	AC_MSG_ERROR("List of hardware must be specified for --enable-sim-hardware"); hardware="";;
@@ -224,14 +319,13 @@
 sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
 if test x"$silent" != x"yes" && test x"$hardware" != x""; then
   echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
-fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide${sim_sysv_ipc_hw}"
 sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
 sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
 if test x"$silent" != x"yes"; then
   echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
 fi])dnl
 
-
 AC_ARG_ENABLE(sim-hostbitsize,
 [  --enable-sim-hostbitsize=32|64	Specify host bitsize (32 or 64).],
 [case "${enableval}" in
diff -Naur gdb-6.8.orig/sim/ppc/debug.c gdb-6.8/sim/ppc/debug.c
--- gdb-6.8.orig/sim/ppc/debug.c	1999-04-16 03:35:08.000000000 +0200
+++ gdb-6.8/sim/ppc/debug.c	2008-09-17 16:33:00.000000000 +0200
@@ -70,6 +70,8 @@
   { trace_pass_device, "pass-device" },
   { trace_phb_device, "phb-device" },
   { trace_register_device, "register-device", "Device initializing registers" },
+  { trace_sem_device, "sem-device" },
+  { trace_shm_device, "shm-device" },
   { trace_stack_device, "stack-device" },
   { trace_vm_device, "vm-device" },
   /* packages */
diff -Naur gdb-6.8.orig/sim/ppc/debug.h gdb-6.8/sim/ppc/debug.h
--- gdb-6.8.orig/sim/ppc/debug.h	1999-04-16 03:35:08.000000000 +0200
+++ gdb-6.8/sim/ppc/debug.h	2008-09-17 16:33:00.000000000 +0200
@@ -51,6 +51,8 @@
   trace_pal_device,
   trace_pass_device,
   trace_phb_device,
+  trace_sem_device,
+  trace_shm_device,
   trace_stack_device,
   trace_register_device,
   trace_vm_device,
diff -Naur gdb-6.8.orig/sim/ppc/hw_sem.c gdb-6.8/sim/ppc/hw_sem.c
--- gdb-6.8.orig/sim/ppc/hw_sem.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8/sim/ppc/hw_sem.c	2008-09-17 16:33:00.000000000 +0200
@@ -0,0 +1,301 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _HW_SEM_C_
+#define _HW_SEM_C_
+
+#include "device_table.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#include <errno.h>
+
+/* DEVICE
+
+
+   sem - provide access to a unix semaphore
+
+
+   DESCRIPTION
+
+
+   This device implements an interface to a unix semaphore.
+
+
+   PROPERTIES
+
+
+   reg = <address> <size> (required)
+
+   Determine where the memory lives in the parents address space.
+
+   key = <integer> (required)
+
+   This is the key of the unix semaphore.
+
+   EXAMPLES
+
+
+   Enable tracing of the sem:
+
+   |  bash$ psim -t sem-device \
+
+
+   Configure a UNIX semaphore using key 0x12345678 mapped into psim
+   address space at 0xfff00000:
+
+   |  -o '/sem@0xfff00000/reg 0xfff00000 0x80000' \
+   |  -o '/sem@0xfff00000/key 0x12345678' \
+
+   sim/ppc/run -o '/#address-cells 1' \
+         -o '/sem@0xc0000000/reg 0xc0000000 0x80000' \
+         -o '/sem@0xc0000000/key 0x12345678' ../psim-hello/hello
+
+   REGISTERS
+
+   offset 0 - lock count
+   offset 4 - lock operation
+   offset 8 - unlock operation
+
+   All reads return the current or resulting count.
+
+   BUGS
+
+   None known.
+
+   */
+
+typedef struct _hw_sem_device {
+  unsigned_word  physical_address;
+  key_t          key;
+  int            id;
+  int            initial;
+  int            count;
+} hw_sem_device;
+
+static void
+hw_sem_init_data(device *me)
+{
+  hw_sem_device *sem = (hw_sem_device*)device_data(me);
+  const device_unit *d;
+  int status;
+#if !HAS_UNION_SEMUN
+        union semun {
+          int val;
+          struct semid_ds *buf;
+          unsigned short int *array;
+#if defined(__linux__)
+          struct seminfo *__buf;
+#endif
+        } ;
+#endif
+  union semun help;
+
+  /* initialize the properties of the sem */
+
+  if (device_find_property(me, "key") == NULL)
+    error("sem_init_data() required key property is missing\n");
+
+  if (device_find_property(me, "value") == NULL)
+    error("sem_init_data() required value property is missing\n");
+
+  sem->key = (key_t) device_find_integer_property(me, "key");
+  DTRACE(sem, ("semaphore key (%d)\n", sem->key) );
+
+  sem->initial = (int) device_find_integer_property(me, "value");
+  DTRACE(sem, ("semaphore initial value (%d)\n", sem->initial) );
+
+  d = device_unit_address(me);
+  sem->physical_address = d->cells[ d->nr_cells-1 ];
+  DTRACE(sem, ("semaphore physical_address=0x%x\n", sem->physical_address));
+
+  /* Now to initialize the semaphore */
+
+  if ( sem->initial != -1 ) {
+
+    sem->id = semget(sem->key, 1, IPC_CREAT | 0660);
+    if (sem->id == -1)
+      error("hw_sem_init_data() semget failed\n");
+
+    help.val = sem->initial;
+    status = semctl( sem->id, 0, SETVAL, help );
+    if (status == -1)
+      error("hw_sem_init_data() semctl -- set value failed\n");
+
+  } else {
+    sem->id = semget(sem->key, 1, 0660);
+    if (sem->id == -1)
+      error("hw_sem_init_data() semget failed\n");
+  }
+
+  sem->count = semctl( sem->id, 0, GETVAL, help );
+  if (sem->count == -1)
+    error("hw_sem_init_data() semctl -- get value failed\n");
+  DTRACE(sem, ("semaphore OS value (%d)\n", sem->count) );
+
+  if (sizeof(int) != 4)
+    error("hw_sem_init_data() typing problem\n");
+}
+
+static void
+hw_sem_attach_address_callback(device *me,
+				attach_type attach,
+				int space,
+				unsigned_word addr,
+				unsigned nr_bytes,
+				access_type access,
+				device *client) /*callback/default*/
+{
+  hw_sem_device *sem = (hw_sem_device*)device_data(me);
+
+  if (space != 0)
+    error("sem_attach_address_callback() invalid address space\n");
+
+  if (nr_bytes == 12)
+    error("sem_attach_address_callback() invalid size\n");
+
+  sem->physical_address = addr;
+  DTRACE(sem, ("semaphore physical_address=0x%x\n", addr));
+}
+
+static unsigned
+hw_sem_io_read_buffer(device *me,
+			 void *dest,
+			 int space,
+			 unsigned_word addr,
+			 unsigned nr_bytes,
+			 cpu *processor,
+			 unsigned_word cia)
+{
+  hw_sem_device *sem = (hw_sem_device*)device_data(me);
+  struct sembuf sb;
+  int status;
+  unsigned32 u32;
+#if !HAS_UNION_SEMUN
+        union semun {
+          int val;
+          struct semid_ds *buf;
+          unsigned short int *array;
+#if defined(__linux__)
+          struct seminfo *__buf;
+#endif
+        } ;
+#endif
+  union semun help;
+
+  /* do we need to worry about out of range addresses? */
+
+  DTRACE(sem, ("semaphore read addr=0x%x length=%d\n", addr, nr_bytes));
+
+  if (!(addr >= sem->physical_address && addr <= sem->physical_address + 11))
+    error("hw_sem_io_read_buffer() invalid address - out of range\n");
+
+  if ((addr % 4) != 0)
+    error("hw_sem_io_read_buffer() invalid address - alignment\n");
+
+  if (nr_bytes != 4)
+    error("hw_sem_io_read_buffer() invalid length\n");
+
+  switch ( (addr - sem->physical_address) / 4 ) {
+
+    case 0:  /* OBTAIN CURRENT VALUE */
+      break; 
+
+    case 1:  /* LOCK */
+      sb.sem_num = 0;
+      sb.sem_op  = -1;
+      sb.sem_flg = 0;
+
+      status = semop(sem->id, &sb, 1);
+      if (status == -1) {
+        perror( "hw_sem.c: lock" );
+        error("hw_sem_io_read_buffer() sem lock\n");
+      }
+
+      DTRACE(sem, ("semaphore lock %d\n", sem->count));
+      break; 
+
+    case 2: /* UNLOCK */
+      sb.sem_num = 0;
+      sb.sem_op  = 1;
+      sb.sem_flg = 0;
+
+      status = semop(sem->id, &sb, 1);
+      if (status == -1) {
+        perror( "hw_sem.c: unlock" );
+        error("hw_sem_io_read_buffer() sem unlock\n");
+      }
+      DTRACE(sem, ("semaphore unlock %d\n", sem->count));
+      break; 
+
+    default:
+      error("hw_sem_io_read_buffer() invalid address - unknown error\n");
+      break; 
+  }
+
+  /* assume target is big endian */
+  u32 = H2T_4(semctl( sem->id, 0, GETVAL, help ));
+
+  DTRACE(sem, ("semaphore OS value (%d)\n", u32) );
+  if (u32 == 0xffffffff) {
+    perror( "hw_sem.c: getval" );
+    error("hw_sem_io_read_buffer() semctl -- get value failed\n");
+  }
+
+  memcpy(dest, &u32, nr_bytes);
+  return nr_bytes;
+
+}
+
+static device_callbacks const hw_sem_callbacks = {
+  { generic_device_init_address, hw_sem_init_data },
+  { hw_sem_attach_address_callback, }, /* address */
+  { hw_sem_io_read_buffer, NULL }, /* IO */
+  { NULL, }, /* DMA */
+  { NULL, }, /* interrupt */
+  { NULL, }, /* unit */
+  NULL,
+};
+
+static void *
+hw_sem_create(const char *name,
+		 const device_unit *unit_address,
+		 const char *args)
+{
+  hw_sem_device *sem = ZALLOC(hw_sem_device);
+  return sem;
+}
+
+const device_descriptor hw_sem_device_descriptor[] = {
+  { "sem", hw_sem_create, &hw_sem_callbacks },
+  { NULL },
+};
+
+#endif /* _HW_SEM_C_ */
diff -Naur gdb-6.8.orig/sim/ppc/hw_shm.c gdb-6.8/sim/ppc/hw_shm.c
--- gdb-6.8.orig/sim/ppc/hw_shm.c	1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8/sim/ppc/hw_shm.c	2008-09-17 16:33:00.000000000 +0200
@@ -0,0 +1,236 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1997,2008, Joel Sherrill <joel@OARcorp.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+    */
+
+
+#ifndef _HW_SHM_C_
+#define _HW_SHM_C_
+
+#include "device_table.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+
+/* DEVICE
+
+
+   shm - map unix shared memory into psim address space
+
+
+   DESCRIPTION
+
+
+   This device implements an area of memory which is mapped into UNIX
+   shared memory.
+
+
+   PROPERTIES
+
+
+   reg = <address> <size> (required)
+
+   Determine where the memory lives in the parents address space.
+   The SHM area is assumed to be of the same length.
+
+   key = <integer> (required)
+
+   This is the key of the unix shared memory area.
+
+   EXAMPLES
+
+
+   Enable tracing of the shm:
+
+   |  bash$ psim -t shm-device \
+
+
+   Configure a 512 kilobytes of UNIX shared memory with the key 0x12345678
+   mapped into psim address space at 0x0c000000.
+
+   |  -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
+   |  -o '/shm@0x0c000000/key 0x12345678' \
+
+   sim/ppc/run -o '/#address-cells 1' \
+         -o '/shm@0x0c000000/reg 0x0c000000 0x80000' \
+         -o '/shm@0x0c000000/key 0x12345678' ../psim-hello/hello
+
+   BUGS
+
+   None known.
+
+   */
+
+typedef struct _hw_shm_device {
+  unsigned_word  physical_address;
+  char          *shm_address;
+  unsigned       sizeof_memory;
+  key_t          key;
+  int            id;
+} hw_shm_device;
+
+static void
+hw_shm_init_data(device *me)
+{
+  hw_shm_device *shm = (hw_shm_device*)device_data(me);
+  const device_unit *d;
+  reg_property_spec reg;
+  int i;
+
+  /* Obtain the Key Value */
+  if (device_find_property(me, "key") == NULL)
+    error("shm_init_data() required key property is missing\n");
+
+  shm->key = (key_t) device_find_integer_property(me, "key");
+  DTRACE(shm, ("shm key (0x%08x)\n", shm->key) );
+  
+  /* Figure out where this memory is in address space and how long it is */
+  if ( !device_find_reg_array_property(me, "reg", 0, &reg) )
+    error("hw_shm_init_data() no address registered\n");
+
+  /* Determine the address and length being as paranoid as possible */
+  shm->physical_address = 0xffffffff;
+  shm->sizeof_memory = 0xffffffff;
+
+  for ( i=0 ; i<reg.address.nr_cells; i++ ) {
+    if (reg.address.cells[0] == 0 && reg.size.cells[0] == 0)
+      continue;
+
+    if ( shm->physical_address != 0xffffffff )
+      device_error(me, "Only single celled address ranges supported\n");
+
+    shm->physical_address = reg.address.cells[i];
+    DTRACE(shm, ("shm physical_address=0x%x\n", shm->physical_address));
+
+    shm->sizeof_memory = reg.size.cells[i];
+    DTRACE(shm, ("shm length=0x%x\n", shm->sizeof_memory));
+  }
+
+  if ( shm->physical_address == 0xffffffff )
+    device_error(me, "Address not specified\n" );
+
+  if ( shm->sizeof_memory == 0xffffffff )
+    device_error(me, "Length not specified\n" );
+
+  /* Now actually attach to or create the shared memory area */
+  shm->id = shmget(shm->key, shm->sizeof_memory, IPC_CREAT | 0660);
+  if (shm->id == -1)
+    error("hw_shm_init_data() shmget failed\n");
+
+  shm->shm_address = shmat(shm->id, (char *)0, SHM_RND);
+  if (shm->shm_address == (void *)-1)
+    error("hw_shm_init_data() shmat failed\n");
+}
+
+static void
+hw_shm_attach_address_callback(device *me,
+				attach_type attach,
+				int space,
+				unsigned_word addr,
+				unsigned nr_bytes,
+				access_type access,
+				device *client) /*callback/default*/
+{
+  hw_shm_device *shm = (hw_shm_device*)device_data(me);
+
+  if (space != 0)
+    error("shm_attach_address_callback() invalid address space\n");
+
+  if (nr_bytes == 0)
+    error("shm_attach_address_callback() invalid size\n");
+}
+
+
+static unsigned
+hw_shm_io_read_buffer(device *me,
+			 void *dest,
+			 int space,
+			 unsigned_word addr,
+			 unsigned nr_bytes,
+			 cpu *processor,
+			 unsigned_word cia)
+{
+  hw_shm_device *shm = (hw_shm_device*)device_data(me);
+
+  /* do we need to worry about out of range addresses? */
+
+  DTRACE(shm, ("read %p %x %x %x\n", \
+     shm->shm_address, shm->physical_address, addr, nr_bytes) );
+
+  memcpy(dest, &shm->shm_address[addr - shm->physical_address], nr_bytes);
+  return nr_bytes;
+}
+
+
+static unsigned
+hw_shm_io_write_buffer(device *me,
+			  const void *source,
+			  int space,
+			  unsigned_word addr,
+			  unsigned nr_bytes,
+			  cpu *processor,
+			  unsigned_word cia)
+{
+  hw_shm_device *shm = (hw_shm_device*)device_data(me);
+
+  /* do we need to worry about out of range addresses? */
+
+  DTRACE(shm, ("write %p %x %x %x\n", \
+     shm->shm_address, shm->physical_address, addr, nr_bytes) );
+
+  memcpy(&shm->shm_address[addr - shm->physical_address], source, nr_bytes);
+  return nr_bytes;
+}
+
+static device_callbacks const hw_shm_callbacks = {
+  { generic_device_init_address, hw_shm_init_data },
+  { hw_shm_attach_address_callback, }, /* address */
+  { hw_shm_io_read_buffer,
+    hw_shm_io_write_buffer }, /* IO */
+  { NULL, }, /* DMA */
+  { NULL, }, /* interrupt */
+  { NULL, }, /* unit */
+  NULL,
+};
+
+static void *
+hw_shm_create(const char *name,
+		 const device_unit *unit_address,
+		 const char *args)
+{
+  hw_shm_device *shm = ZALLOC(hw_shm_device);
+  return shm;
+}
+
+
+
+const device_descriptor hw_shm_device_descriptor[] = {
+  { "shm", hw_shm_create, &hw_shm_callbacks },
+  { NULL },
+};
+
+#endif /* _HW_SHM_C_ */
diff -Naur gdb-6.8.orig/sim/ppc/Makefile.in gdb-6.8/sim/ppc/Makefile.in
--- gdb-6.8.orig/sim/ppc/Makefile.in	2006-05-31 17:14:45.000000000 +0200
+++ gdb-6.8/sim/ppc/Makefile.in	2008-09-17 16:33:00.000000000 +0200
@@ -834,6 +834,8 @@
 hw_pal.o: hw_pal.c $(DEVICE_TABLE_H) $(CPU_H)
 hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) $(HW_PHB_H) $(COREFILE_H)
 hw_register.o: hw_register.c $(DEVICE_TABLE_H) $(PSIM_H)
+hw_sem.o: hw_sem.c $(DEVICE_TABLE_H) $(PSIM_H)
+hw_shm.o: hw_shm.c $(DEVICE_TABLE_H) $(PSIM_H)
 hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
 hw_vm.o: hw_vm.c $(DEVICE_TABLE_H) $(CPU_H)
 # ignore this line, it stops make from getting confused
diff -Naur gdb-6.8.orig/sim/ppc/ppc-instructions gdb-6.8/sim/ppc/ppc-instructions
--- gdb-6.8.orig/sim/ppc/ppc-instructions	2006-11-29 16:20:55.000000000 +0100
+++ gdb-6.8/sim/ppc/ppc-instructions	2008-09-17 16:33:00.000000000 +0200
@@ -3402,6 +3402,14 @@
 	    case spr_dec:
 	      *rT = cpu_get_decrementer(processor);
 	      break;
+		case spr_tbrl:
+	  	  if (is_64bit_implementation) *rT = TB;
+	  	  else                         *rT = EXTRACTED64(TB, 32, 63);
+		break;
+		case spr_tbru:
+	  	  if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
+		  else                         *rT = EXTRACTED64(TB, 0, 31);
+		break;
 	    case spr_tbu:
 	    case spr_tbl:
 	      /* NOTE - these SPR's are not readable. Use mftb[ul] */
diff -Naur gdb-6.8.orig/sim/ppc/ppc-spr-table gdb-6.8/sim/ppc/ppc-spr-table
--- gdb-6.8.orig/sim/ppc/ppc-spr-table	2003-06-22 18:48:12.000000000 +0200
+++ gdb-6.8/sim/ppc/ppc-spr-table	2008-09-17 16:33:00.000000000 +0200
@@ -32,6 +32,8 @@
 SRR0:26:0:0
 SRR1:27:0:0
 VRSAVE:256:0:0
+TBRL:268:0:0
+TBRU:269:0:0
 SPRG0:272:0:0
 SPRG1:273:0:0
 SPRG2:274:0:0
