Well, so based on your code, level is not considered volatile. You'd need something like:
volatile uint16 level;
level = buf*256 + buf;
for it to be marked as volatile. See http://www.keil.com/support/man/docs/c51/c51_le_volatile.htm.The reason Keil is optimizing out your variable is it looks at the assignment and the singular use case and it can either replace the usage with the assignment value, or keep the assignment in a CPU register instead of commiting it back. If you mark the variable volatile as the link above specfies, does it work as expected?