Revision c596defd
b/tcg/ppc/tcg-target.c | ||
---|---|---|
282 | 282 |
|
283 | 283 |
#define RLWINM OPCD(21) |
284 | 284 |
|
285 |
#define BCLR XO19(16) |
|
285 |
#define BCLR XO19( 16)
|
|
286 | 286 |
#define BCCTR XO19(528) |
287 | 287 |
#define CRAND XO19(257) |
288 |
#define CRANDC XO19(129) |
|
289 |
#define CRNAND XO19(225) |
|
290 |
#define CROR XO19(449) |
|
288 | 291 |
|
289 | 292 |
#define EXTSB XO31(954) |
290 | 293 |
#define EXTSH XO31(922) |
... | ... | |
870 | 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 | 879 |
int imm; |
879 | 880 |
uint32_t op; |
880 | 881 |
|
... | ... | |
930 | 931 |
default: |
931 | 932 |
tcg_abort (); |
932 | 933 |
} |
933 |
op |= BF (7);
|
|
934 |
op |= BF (cr);
|
|
934 | 935 |
|
935 | 936 |
if (imm) |
936 | 937 |
tcg_out32 (s, op | RA (arg1) | (arg2 & 0xffff)); |
... | ... | |
943 | 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 | 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 | 955 |
else { |
950 | 956 |
uint16_t val = *(uint16_t *) &s->code_ptr[2]; |
951 | 957 |
|
952 | 958 |
/* Thanks to Andrzej Zaborowski */ |
953 |
tcg_out32 (s, tcg_to_bc[cond] | (val & 0xfffc));
|
|
959 |
tcg_out32 (s, bc | (val & 0xfffc));
|
|
954 | 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 | 972 |
/* XXX: we implement it at the target level to avoid having to |
960 | 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 | 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 | 994 |
break; |
971 | 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 | 999 |
break; |
975 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1014 |
break; |
1015 | 1015 |
default: |
1016 | 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 | 1022 |
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
Also available in: Unified diff