The solution is to simply add a star (*) before the register, like this:
__asm volatile ("jmp *%eax");
I'm not exactly sure what the star means. According to this SO post:
The star is some syntactical sugar indicating that control is to be passed indirectly, by reference/pointer.
As for why it works with 64-bit TCC, I assume that it's a bug; 64-bit GCC complains with Error: operand type mismatch for 'jmp'
, as it should.