diff options
author | malc <av1474@comtv.ru> | 2009-09-06 06:31:09 +0400 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2009-09-06 07:24:37 +0400 |
commit | c45851c44a414e15cd0971c228202f27c127ab78 (patch) | |
tree | ec8c679743f132cc7302583c5d9dbd36a075100e /tcg | |
parent | b3d6fb4a6a53d9d16bfe3cafe805e0b41f9ccb8b (diff) | |
download | qemu-c45851c44a414e15cd0971c228202f27c127ab78.zip qemu-c45851c44a414e15cd0971c228202f27c127ab78.tar.gz qemu-c45851c44a414e15cd0971c228202f27c127ab78.tar.bz2 |
When targeting PPU use rlwinm instead of andi. if possible
andi. is microcoded and slow there.
Signed-off-by: malc <av1474@comtv.ru>
Diffstat (limited to 'tcg')
-rw-r--r-- | tcg/ppc/tcg-target.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 2409288..0739515 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -1253,14 +1253,60 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, case INDEX_op_and_i32: if (const_args[2]) { - if ((args[2] & 0xffff) == args[2]) - tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | args[2]); - else if ((args[2] & 0xffff0000) == args[2]) - tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0]) - | ((args[2] >> 16) & 0xffff)); - else { - tcg_out_movi (s, TCG_TYPE_I32, 0, args[2]); - tcg_out32 (s, AND | SAB (args[1], args[0], 0)); + uint32_t c; + + c = args[2]; + + if (!c) { + tcg_out_movi (s, TCG_TYPE_I32, args[0], 0); + break; + } +#ifdef __PPU__ + uint32_t t, n; + int mb, me; + + n = c ^ -(c & 1); + t = n + (n & -n); + + if ((t & (t - 1)) == 0) { + int lzc, tzc; + + if ((c & 0x80000001) == 0x80000001) { + lzc = clz32 (n); + tzc = ctz32 (n); + + mb = 32 - tzc; + me = lzc - 1; + } + else { + lzc = clz32 (c); + tzc = ctz32 (c); + + mb = lzc; + me = 31 - tzc; + } + + tcg_out32 (s, (RLWINM + | RA (args[0]) + | RS (args[1]) + | SH (0) + | MB (mb) + | ME (me) + ) + ); + } + else +#endif /* !__PPU__ */ + { + if ((c & 0xffff) == c) + tcg_out32 (s, ANDI | RS (args[1]) | RA (args[0]) | c); + else if ((c & 0xffff0000) == c) + tcg_out32 (s, ANDIS | RS (args[1]) | RA (args[0]) + | ((c >> 16) & 0xffff)); + else { + tcg_out_movi (s, TCG_TYPE_I32, 0, c); + tcg_out32 (s, AND | SAB (args[1], args[0], 0)); + } } } else |