- Setting -pagezero_size to anything less than 4 GB seems to make
 macOS refuse to run the executable. So this makes it impossible to
 map anything into the lower 4 GB of the address space. For now,
 I've worked it around by moving the address at which user_shared_data
 is allocated.

Shouldn't you be able to forcefully remap parts in the zero page? To my knowledge the only thing you can't do is unmap pages that the dynamic loader thinks are allocated - if it gets them again when loading a different .dylib it will crash and burn. But you can map stuff there with MAP_FIXED yourself as long as you can be sure you don't overwrite anything important - which shouldn't be the case in the zero page.

- Memory mappings can't be writable and executable at the same time.
 If one mmap()s a page and request it to be both writable and
 executable, writing to it fails, same if changing protection with
 mprotect().

In Catalina you can bypass that with the right protected runtime entitlements. That means you'll have to sign your executable with a manifest that enables the protected runtime and requests the entitlements. Do you know if this still works in Big Sur x86_64 and/or big sur ARM?

- Darwin also treats x18 as reserved, just like windows, but IIRC
 the system can spuriously(?) overwrite the register to zero at
 some times. I haven't run into this in the context of wine on macOS
 yet though.

Yeah someone warned me that this happens on iOS. The Darwin kernel code should be accessible I think. Any way to find out under which conditions this happens?