Second attempt: I now have a modified GCC 4.4.3 which recognizes -mcmodel=smallhigh; in CM_SMALLHIGH, pic_32bit_operand acts as it does for PIC (to get lea instead of movabs), and legitimate_address_p accepts SYMBOLIC_CONSTs with no indexing (for anything with a memory constraint).
Beyond that, the defaults (i.e., what happens if the code model isn't any of the previously defined ones) happen to be more or less what I want. In particular, the operand printer chooses %rip-relative mode over plain disp32 for any symbolic displacement in all the smallish modes; this is commented as if it were just a space optimization (avoiding the SIB byte), but in fact it's necessary for -fPIC to work, so I think I can depend on it. One thing I'm not so sure about is accepting any SYMBOLIC_CONST as a legitimate address. That allows, for example, a symbol address cast to uintptr_t and added to (6ULL << 32), which will never fit. On the other hand, -fPIC allows offsets of up to +/- 16Mib for some unexplained reason, meaning that I can break it by pushing the code+data size almost to 2GiB with a large .bss and evaluating (uintptr_t)&_end+0xffffff. I think I could try to fix that by interrogating the SYMBOL_REF_DECL for the object's size, but given that -fPIC doesn't go that far, it's not clear that I need to. Thoughts? Also, it may actually work now. I've successfully bootstrapped with BOOT_CFLAGS='-mcmodel=smallhigh -O2 -g', after which the only _32 or _32S relocations in the gcc/ subdirectory of the objdir were either .debug references that I assume are safe, or in crtstuff that's part of the libgcc build and not affected by BOOT_CFLAGS. (It also successfully builds ESXi with kernel coverage enabled, but that's less informative for people on this list.) Once our lawyers approve, I can also send the actual diff; by my count, it makes nontrivial changes to a whole seven lines of code. --Jed