Commit c596defdb9507d9f98269e760616773e2acde371
1 parent
200ae688
Reimplement brcond2 and refactor brcond
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4738 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
52 additions
and
51 deletions
tcg/ppc/tcg-target.c
| @@ -282,9 +282,12 @@ static int tcg_target_const_match(tcg_target_long val, | @@ -282,9 +282,12 @@ static int tcg_target_const_match(tcg_target_long val, | ||
| 282 | 282 | ||
| 283 | #define RLWINM OPCD(21) | 283 | #define RLWINM OPCD(21) |
| 284 | 284 | ||
| 285 | -#define BCLR XO19(16) | 285 | +#define BCLR XO19( 16) |
| 286 | #define BCCTR XO19(528) | 286 | #define BCCTR XO19(528) |
| 287 | #define CRAND XO19(257) | 287 | #define CRAND XO19(257) |
| 288 | +#define CRANDC XO19(129) | ||
| 289 | +#define CRNAND XO19(225) | ||
| 290 | +#define CROR XO19(449) | ||
| 288 | 291 | ||
| 289 | #define EXTSB XO31(954) | 292 | #define EXTSB XO31(954) |
| 290 | #define EXTSH XO31(922) | 293 | #define EXTSH XO31(922) |
| @@ -870,11 +873,9 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) | @@ -870,11 +873,9 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) | ||
| 870 | ppc_addi (s, reg, reg, val); | 873 | ppc_addi (s, reg, reg, val); |
| 871 | } | 874 | } |
| 872 | 875 | ||
| 873 | -static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 874 | - TCGArg arg1, TCGArg arg2, int const_arg2, | ||
| 875 | - int label_index) | 876 | +static void tcg_out_cmp (TCGContext *s, int cond, TCGArg arg1, TCGArg arg2, |
| 877 | + int const_arg2, int cr) | ||
| 876 | { | 878 | { |
| 877 | - TCGLabel *l = &s->labels[label_index]; | ||
| 878 | int imm; | 879 | int imm; |
| 879 | uint32_t op; | 880 | uint32_t op; |
| 880 | 881 | ||
| @@ -930,7 +931,7 @@ static void tcg_out_brcond(TCGContext *s, int cond, | @@ -930,7 +931,7 @@ static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 930 | default: | 931 | default: |
| 931 | tcg_abort (); | 932 | tcg_abort (); |
| 932 | } | 933 | } |
| 933 | - op |= BF (7); | 934 | + op |= BF (cr); |
| 934 | 935 | ||
| 935 | if (imm) | 936 | if (imm) |
| 936 | tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); | 937 | tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); |
| @@ -943,79 +944,79 @@ static void tcg_out_brcond(TCGContext *s, int cond, | @@ -943,79 +944,79 @@ static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 943 | tcg_out32 (s, op | RA (arg1) | RB (arg2)); | 944 | tcg_out32 (s, op | RA (arg1) | RB (arg2)); |
| 944 | } | 945 | } |
| 945 | 946 | ||
| 947 | +} | ||
| 948 | + | ||
| 949 | +static void tcg_out_bc (TCGContext *s, int bc, int label_index) | ||
| 950 | +{ | ||
| 951 | + TCGLabel *l = &s->labels[label_index]; | ||
| 952 | + | ||
| 946 | if (l->has_value) | 953 | if (l->has_value) |
| 947 | - tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr, | ||
| 948 | - l->u.value)); | 954 | + tcg_out32 (s, bc | reloc_pc14_val (s->code_ptr, l->u.value)); |
| 949 | else { | 955 | else { |
| 950 | uint16_t val = *(uint16_t *) &s->code_ptr[2]; | 956 | uint16_t val = *(uint16_t *) &s->code_ptr[2]; |
| 951 | 957 | ||
| 952 | /* Thanks to Andrzej Zaborowski */ | 958 | /* Thanks to Andrzej Zaborowski */ |
| 953 | - tcg_out32 (s, tcg_to_bc[cond] | (val & 0xfffc)); | 959 | + tcg_out32 (s, bc | (val & 0xfffc)); |
| 954 | tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); | 960 | tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); |
| 955 | } | 961 | } |
| 956 | } | 962 | } |
| 957 | 963 | ||
| 958 | -/* brcond2 is taken verbatim from i386 tcg-target */ | 964 | +static void tcg_out_brcond (TCGContext *s, int cond, |
| 965 | + TCGArg arg1, TCGArg arg2, int const_arg2, | ||
| 966 | + int label_index) | ||
| 967 | +{ | ||
| 968 | + tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7); | ||
| 969 | + tcg_out_bc (s, tcg_to_bc[cond], label_index); | ||
| 970 | +} | ||
| 971 | + | ||
| 959 | /* XXX: we implement it at the target level to avoid having to | 972 | /* XXX: we implement it at the target level to avoid having to |
| 960 | handle cross basic blocks temporaries */ | 973 | handle cross basic blocks temporaries */ |
| 961 | -static void tcg_out_brcond2(TCGContext *s, | ||
| 962 | - const TCGArg *args, const int *const_args) | 974 | +static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args, |
| 975 | + const int *const_args) | ||
| 963 | { | 976 | { |
| 964 | - int label_next; | ||
| 965 | - label_next = gen_new_label(); | ||
| 966 | - switch(args[4]) { | 977 | + int cond = args[4], label_index = args[5], op; |
| 978 | + struct { int bit1; int bit2; int cond2; } bits[] = { | ||
| 979 | + [TCG_COND_LT ] = { CR_LT, CR_LT, TCG_COND_LT }, | ||
| 980 | + [TCG_COND_LE ] = { CR_LT, CR_GT, TCG_COND_LT }, | ||
| 981 | + [TCG_COND_GT ] = { CR_GT, CR_GT, TCG_COND_GT }, | ||
| 982 | + [TCG_COND_GE ] = { CR_GT, CR_LT, TCG_COND_GT }, | ||
| 983 | + [TCG_COND_LTU] = { CR_LT, CR_LT, TCG_COND_LTU }, | ||
| 984 | + [TCG_COND_LEU] = { CR_LT, CR_GT, TCG_COND_LTU }, | ||
| 985 | + [TCG_COND_GTU] = { CR_GT, CR_GT, TCG_COND_GTU }, | ||
| 986 | + [TCG_COND_GEU] = { CR_GT, CR_LT, TCG_COND_GTU }, | ||
| 987 | + }, *b = &bits[cond]; | ||
| 988 | + | ||
| 989 | + switch (cond) { | ||
| 967 | case TCG_COND_EQ: | 990 | case TCG_COND_EQ: |
| 968 | - tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next); | ||
| 969 | - tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]); | 991 | + tcg_out_cmp (s, TCG_COND_EQ, args[0], args[2], const_args[2], 6); |
| 992 | + tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 7); | ||
| 993 | + tcg_out32 (s, CRAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); | ||
| 970 | break; | 994 | break; |
| 971 | case TCG_COND_NE: | 995 | case TCG_COND_NE: |
| 972 | - tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]); | ||
| 973 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]); | 996 | + tcg_out_cmp (s, TCG_COND_NE, args[0], args[2], const_args[2], 6); |
| 997 | + tcg_out_cmp (s, TCG_COND_NE, args[1], args[3], const_args[3], 7); | ||
| 998 | + tcg_out32 (s, CRNAND | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, CR_EQ)); | ||
| 974 | break; | 999 | break; |
| 975 | case TCG_COND_LT: | 1000 | case TCG_COND_LT: |
| 976 | - tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); | ||
| 977 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 978 | - tcg_out_brcond(s, TCG_COND_LT, args[0], args[2], const_args[2], args[5]); | ||
| 979 | - break; | ||
| 980 | case TCG_COND_LE: | 1001 | case TCG_COND_LE: |
| 981 | - tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]); | ||
| 982 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 983 | - tcg_out_brcond(s, TCG_COND_LE, args[0], args[2], const_args[2], args[5]); | ||
| 984 | - break; | ||
| 985 | case TCG_COND_GT: | 1002 | case TCG_COND_GT: |
| 986 | - tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); | ||
| 987 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 988 | - tcg_out_brcond(s, TCG_COND_GT, args[0], args[2], const_args[2], args[5]); | ||
| 989 | - break; | ||
| 990 | case TCG_COND_GE: | 1003 | case TCG_COND_GE: |
| 991 | - tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]); | ||
| 992 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 993 | - tcg_out_brcond(s, TCG_COND_GE, args[0], args[2], const_args[2], args[5]); | ||
| 994 | - break; | ||
| 995 | case TCG_COND_LTU: | 1004 | case TCG_COND_LTU: |
| 996 | - tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]); | ||
| 997 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 998 | - tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]); | ||
| 999 | - break; | ||
| 1000 | case TCG_COND_LEU: | 1005 | case TCG_COND_LEU: |
| 1001 | - tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]); | ||
| 1002 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 1003 | - tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]); | ||
| 1004 | - break; | ||
| 1005 | case TCG_COND_GTU: | 1006 | case TCG_COND_GTU: |
| 1006 | - tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]); | ||
| 1007 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 1008 | - tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]); | ||
| 1009 | - break; | ||
| 1010 | case TCG_COND_GEU: | 1007 | case TCG_COND_GEU: |
| 1011 | - tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]); | ||
| 1012 | - tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next); | ||
| 1013 | - tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]); | 1008 | + op = (b->bit1 != b->bit2) ? CRANDC : CRAND; |
| 1009 | + tcg_out_cmp (s, b->cond2, args[1], args[3], const_args[3], 5); | ||
| 1010 | + tcg_out_cmp (s, TCG_COND_EQ, args[1], args[3], const_args[3], 6); | ||
| 1011 | + tcg_out_cmp (s, cond, args[0], args[2], const_args[2], 7); | ||
| 1012 | + tcg_out32 (s, op | BT (7, CR_EQ) | BA (6, CR_EQ) | BB (7, b->bit2)); | ||
| 1013 | + tcg_out32 (s, CROR | BT (7, CR_EQ) | BA (5, b->bit1) | BB (7, CR_EQ)); | ||
| 1014 | break; | 1014 | break; |
| 1015 | default: | 1015 | default: |
| 1016 | tcg_abort(); | 1016 | tcg_abort(); |
| 1017 | } | 1017 | } |
| 1018 | - tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); | 1018 | + |
| 1019 | + tcg_out_bc (s, (BC | BI (7, CR_EQ) | BO_COND_TRUE), label_index); | ||
| 1019 | } | 1020 | } |
| 1020 | 1021 | ||
| 1021 | static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | 1022 | static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |