The following is the only info I could find:
RV32E and RV64E use the same instruction-set encoding as RV32I and RV64I respectively, except that only registers x0–x15 are provided. All encodings specifying the other registers x16–x31 are reserved.
This change requires a different calling convention and ABI. In particular, RV32E is only used with a soft-float calling convention. A new embedded ABI is under consideration that would work across RV32E and RV32I.
To be uber specific, my concern is the ability to compile programs which will run on a RV32I machine but which will only utilize the first 16 registers - hence the rationale to compile for RV32E. The reasoning for this is to support more performant translation to 16-register x86 CPUs running the RV32I VM.
To be even more specific to my own concerns, I have no interest in implementing any native float operations.
If RV32E programs ran on a RV32I machine will produce less deterministic results, I would like to be aware.
It depends whether we are talking about ISA or ABI.
RV32E and RV64E use the same instruction-set encoding as RV32I and RV64I respectively, except that only registers x0–x15 are provided. All encodings specifying the other registers x16–x31 are reserved.
This means RV32E ISA is a strict subset of RV32I ISA, so some bit of RV32E machine code would run on RV32I CPU just as well, and will result in the same effects.
Now, regarding interoperability of code written for RV32E and RV32I.
This change requires a different calling convention and ABI. In particular, RV32E is only used with a soft-float calling convention. A new embedded ABI is under consideration that would work across RV32E and RV32I.
It's not just soft-float. If we look at psABI doc, it designates x10-x17 as a0-a7, x18-x27 as s2-s11, and x28-x31 as t3-t6 (that is for RV32I). The same doc also specifies (not ratified atm) ILP32E calling convention for the RV32E, which designates x10-x15 as a0-a5. So, sN and tN registers won't cause any issues when calling RV32E->RV32I or vice versa; but a0-a7 vs a0-a5 would - any inter-ABI call with more than 6 arguments (or more than 3 64-bit arguments) would result in an error. There's also a difference in required stack alignment - RV32I ABI wants 16 byte alignment while RV32E wants 4 byte. Thus RV32I->RV32E call would be OK as far as alignment goes, but RV32E->RV32I function call might be illegal.
To sum up: you can't just intermingle RV32E code with RV32I code without any care in the world. However, you should be able to call RV32E code from RV32I code on RV32I CPU, as long as it doesn't call back into RV32I functions. And you can run RV32E only code on RV32I CPU.
From your specific use case, you seem to want the latter, i.e. to run RV32E only code on RV32I emulator (I assume it is a somewhat optimizing JIT translator, otherwise I don't see much gain from limiting guest ABI). You should be fine doing so.