Rework the use of `usize` versus `u32` in RawSyscalls.

I previously used `usize` for every value, because `usize` is register-sized on all platforms. However, I no longer think that is the correct thing to do. Having the values be register-sized only matters for `libtock_runtime::TockSyscalls`; it does not matter for `libtock_unittest::FakeSyscalls`. For the fake system calls, it is better to pass u32 where possible to minimize the number of invalid value representable in the API.

This rework follows a simple rule: values that can potentially contain pointers have type `usize`; all other register values have type `u32`. This extends to the function signature of `subscribe` callbacks: unsafe extern fn(u32, u32, u32, usize).
diff --git a/core/platform/src/raw_syscalls.rs b/core/platform/src/raw_syscalls.rs
index 5a87b2d..1743e3f 100644
--- a/core/platform/src/raw_syscalls.rs
+++ b/core/platform/src/raw_syscalls.rs
@@ -57,10 +57,13 @@
 // clobbered, not r2 and r3. This choice of clobbers will need to be revisited
 // if and when a memop operation that returns more data is added.
 //
-// Because the variables passed in and out of raw system calls represent
-// register values, they are of type usize. In cases where it doesn't make sense
-// to pass a pointer-sized value, libtock_unittest::FakeSyscalls may panic if a
-// too-large value is passed.
+// The decision of where to use u32 and usize can be a bit tricky. The Tock
+// syscall ABI is currently only specified for 32-bit systems, so on real Tock
+// systems both types match the size of a register, but the unit test
+// environment can be either 32 bit or 64 bit. This interface uses usize for
+// values that can contain pointers, so that pointers are not truncated in the
+// unit test environment. To keep types as consistent as possible, it uses u32
+// for all values that cannot be pointers.
 pub trait RawSyscalls {
     // raw_yield should:
     //     1. Call syscall class 0
@@ -82,7 +85,7 @@
     // pass YieldType rather than a usize because if we used usize directly then
     // this API becomes unsound if the kernel adds support for an unsafe yield
     // type (or even one that takes one more argument).
-    fn raw_yield(r0_in: YieldType) -> usize;
+    fn raw_yield(r0_in: YieldType) -> u32;
 
     // four_arg_syscall is used to invoke the subscribe, command, read-write
     // allow, and read-only allow system calls.
@@ -101,17 +104,23 @@
     //            readonly  (rw allow can modify memory)
     //            noreturn  (all these system calls are expected to return)
     //
+    // Note that subscribe's application data argument can potentially contain a
+    // pointer, so r3 can contain a pointer (in addition to r1 and r2, which
+    // more obviously contain pointers for subscribe and memop).
+    //
+    // For subscribe(), the callback pointer should be either 0 (for the null
+    // callback) or an `unsafe extern fn(u32, u32, u32, usize)`.
     /// # Safety
     /// `four_arg_syscall` must NOT be used to invoke yield. Otherwise, it has
     /// the same safety invariants as the underlying system call, which varies
     /// depending on the system call class.
     unsafe fn four_arg_syscall(
-        r0: usize,
+        r0: u32,
         r1: usize,
         r2: usize,
         r3: usize,
         class: u8,
-    ) -> (usize, usize, usize, usize);
+    ) -> (u32, usize, usize, usize);
 
     // zero_arg_memop is used to invoke memop operations that do not accept an
     // argument register. Because there are no memop commands that set r2 or r3,
@@ -137,10 +146,10 @@
     //            noreturn
     //
     // Design note: like raw_yield, this is safe because memops that currently
-    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
-    // so that if the kernel adds an unsafe memop -- or one that can clobber
-    // r2/r3 --  this API doesn't become unsound.
-    fn zero_arg_memop(r0_in: ZeroArgMemop) -> (usize, usize);
+    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a u32 so
+    // that if the kernel adds an unsafe memop -- or one that can clobber r2/r3
+    // --  this API doesn't become unsound.
+    fn zero_arg_memop(r0_in: ZeroArgMemop) -> (u32, usize);
 
     // one_arg_memop is used to invoke memop operations that take an argument.
     // Because there are no memop operations that set r2 or r3, this only needs
@@ -161,14 +170,14 @@
     //            noreturn
     //
     // Design note: like raw_yield, this is safe because memops that currently
-    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a usize
-    // so that if the kernel adds an unsafe memop -- or one that can clobber
-    // r2/r3 -- this API doesn't become unsound.
-    fn one_arg_memop(r0_in: OneArgMemop, r1: usize) -> (usize, usize);
+    // exist are safe. zero_arg_memop takes a ZeroArgMemop rather than a u32 so
+    // that if the kernel adds an unsafe memop -- or one that can clobber r2/r3
+    // -- this API doesn't become unsound.
+    fn one_arg_memop(r0_in: OneArgMemop, r1: usize) -> (u32, usize);
 }
 
 #[non_exhaustive]
-#[repr(usize)]
+#[repr(u32)]
 pub enum OneArgMemop {
     Brk = 0,
     Sbrk = 1,
@@ -183,14 +192,14 @@
 // TODO: When the numeric values (0 and 1) are assigned to the yield types,
 // specify those values here.
 #[non_exhaustive]
-#[repr(usize)]
+#[repr(u32)]
 pub enum YieldType {
     Wait,
     NoWait,
 }
 
 #[non_exhaustive]
-#[repr(usize)]
+#[repr(u32)]
 pub enum ZeroArgMemop {
     MemoryStart = 2,
     MemoryEnd = 3,