JVM: dadd, fadd, iadd, ladd. Addition for double, float, int, and long data, respectively.
CIL: add, add.ovf, add.ovf.un. Addition, signed addition with overflow check, and unsigned addition with overflow check.
JVM: dadd, fadd, iadd, ladd. Addition for double, float, int, and long data, respectively.
CIL: add, add.ovf, add.ovf.un. Addition, signed addition with overflow check, and unsigned addition with overflow check.
You can see this design choice even today in how the JVM and CLR work. The JVM starts execution in an interpreter mode, then gradually compiles pieces of code as it detects bottlenecks. So the compilation that happens at runtime is very gradual and based on runtime measurements.
The CLR on the other hand has done JIT compilation, with the ability to cache the compiled code for faster startup (e.g. Ngen). So it has been oriented towards ahead of time compilation.
Different trade-offs.
JVM - Bytecodes only for Java
CIL - Bytecodes for VB.NET, C#, Managed C++ and the 1.0 SDK contained examples for Lisp, Pascal, Eiffel, Ada, ....
Of course, history then took another path for the JVM.
EDIT: Forgot that C++/CLI replaced Managed C++, which was the C++ variant on 1.0.
Although it should be mentioned that java language semantics are largely (depending on how you measure them :-) absent from the jvm. (Default methods were a very unusual change in that respect)
And, as you say, subsequent history has weirdly inverted the JVM and CIL. The former is a lot less 'J' and the latter is a lot less 'C' ;-)
(I was really referring to the healthy non-java jvm language community. JRuby, Scala, and Clojure have lively communities and commercial backing)