Fix dyngen failure on PPC.
PATCH 1/1 Fix dyngen failure on PPC.
GCC 4 occasionally generates functions with the 'blr' somewhere in the middle and a branch at the end.
dyngen.c renamed from dyngen.c.orig +4 -2
@@ -1396,11 +1395,13 @@ void gen_code(const char *name, host_ulo#elif defined(HOST_PPC ) {uint8_t *p; +uint32_t insn; p = (void *)(p_end -4 );if (p == p_start)error ("empty code for %s" , name); -if (get32 ((uint32_t *)p) !=0x4e800020 ) -error ("blr expected at the end of %s" , name); + insn =get32 ((uint32_t *)p); +if (insn !=0x4e800020 && (insn &0xfc000002 ) !=0x48000000 ) +error ("blr or b expected at the end of %s" , name); copy_size = p - p_start; }#elif defined(HOST_S390 )
Signature · 1 line
dwmw2
Quoted 11 lines · David Woodhouse
GCC 4 occasionally generates functions with the 'blr' somewhere in the middle and a branch at the end.
dyngen.c renamed from dyngen.c.orig +1
-0@@ -1396,11 +1395,13 @@ void gen_code(const char *name, host_ulo#elif defined(HOST_PPC ) {uint8_t *p; +uint32_t insn; p = (void *)(p_end -4 );
dyngen.c void gen_code(const char *name, host_ulo · line 1407
Quoted 10 lines
dyngen.c renamed from dyngen.c.orig +3
-2if (p == p_start)error ("empty code for %s" , name); -if (get32 ((uint32_t *)p) !=0x4e800020 ) -error ("blr expected at the end of %s" , name); + insn =get32 ((uint32_t *)p); +if (insn !=0x4e800020 && (insn &0xfc000002 ) !=0x48000000 ) +error ("blr or b expected at the end of %s" , name); copy_size = p - p_start; }#elif defined(HOST_S390)
This is not correct.
If the blr is not at the end of the function, things will break. dyngen assumes the last instruction is the only return instruction in the function. This allows it to remove the blr insn and concatenate multiple functions together.
This basically only ever worked because gcc could be coerced into generating relatively simple code. GCC4 contains much more aggressive high level optimizers, so this is no longer possible.
Paul
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 2 lines
This is not correct.
If the blr is not at the end of the function, things will break.
[SNIP]
Quoted 3 lines
This basically only ever worked because gcc could be coerced into generating relatively simple code. GCC4 contains much more aggressive high level optimizers, so this is no longer possible.
I don't know almost anything about gcc, so I'm asking two questions:
1) Isn't there any kind of compiler directive to force no optimization only for a portion of the code?
2) If there aren't such directives is it possible to link together optimized obj with not optimized obj? In this case you could group functions that require no optimization and link them with the other optimized code.
Maybe I asked 2 dumb questions, but I'm courious and I'd like to learn something new :-)
TNX
P.S. I apologize for my bad English :-)
- --
Flavio Visentin
| \|||/ | @/0.0\@ | \ - / +------------------oOOo---oOOo------------------
There are only 10 types of people in this world:
those who understand binary, and those who don't.
GPG Key: http://www.zipman.it/gpgkey.asc
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCdTj0usUmHkh1cnoRAs3hAJ48/9uEbjEqNTsa24mKm6Ol62774ACdGpnF N+EC/lngLa6oytEfDVUO3eA=
=lVHN
-----END PGP SIGNATURE-----
Quoted 5 lines · Flavio Visentin
Quoted 2 lines
This is not correct.
If the blr is not at the end of the function, things will break.[SNIP]
Quoted 8 lines
Quoted 3 lines
This basically only ever worked because gcc could be coerced into generating relatively simple code. GCC4 contains much more aggressive high level optimizers, so this is no longer possible.
I don't know almost anything about gcc, so I'm asking two questions:
1) Isn't there any kind of compiler directive to force no optimization only for a portion of the code?
Optimiziation is controlled on a per-file bases.
Quoted 4 lines
2) If there aren't such directives is it possible to link together optimized obj with not optimized obj? In this case you could group functions that require no optimization and link them with the other optimized code.
Linking together objects compiled with and without optimization isn't a problem, however...
Disabling optimization isn't really an option because (a) it causes other problems, and (b) the code generate is awfully slow.
The real solution is to teach qemu how to generate native code from and remove dyngen altogether, but that's a lot of work. Look in the list archives for more details.
Paul
Quoted 5 lines · Paul Brook
This is not correct.
If the blr is not at the end of the function, things will break. dyngen assumes the last instruction is the only return instruction in the function. This allows it to remove the blr insn and concatenate multiple functions together.
Can't we on PPC just replace all blr's with plain branches to the instruction after end of the function? (since all instructions are 32 bit long)
Jonas
Quoted 9 lines · Jonas Maebe
Quoted 7 lines · Paul Brook
This is not correct.
If the blr is not at the end of the function, things will break. dyngen assumes the last instruction is the only return instruction in the
function. This allows it to remove the blr insn and concatenate multiple
functions together.
Quoted 3 lines
Can't we on PPC just replace all blr's with plain branches to the instruction after end of the function? (since all instructions are 32 bit long)
Yes, that should be work for ppc.
Obviously this doesn't help on x86/amd64 where a jump is longer than a ret. you would have to copy the preceeding instruction[s] to make room for the branch. You'd then need to redirect any jumps directly to the ret instruction, and make them point at the copy.
Sparc may have similar problems because of jump delay slots (a jump is effectively two instructions long.
Arm needs a bit of logic to follow jumps and figure out where the end of the function is (ie. where the constant pool starts), but other that than the same trick should work.
Overall it sounds like a tractable problem. It shouldn't matter if this analysis takes a while because it's don'e while building qemu, not at runtime.
Paul