Revision aaa9128a target-mips/translate.c
b/target-mips/translate.c | ||
---|---|---|
488 | 488 |
tcg_gen_st_tl(cpu_T[0], r_tmp, sizeof(target_ulong) * reg); |
489 | 489 |
} |
490 | 490 |
|
491 |
/* Load immediates, zero being a special case. */ |
|
492 |
static inline void gen_op_set_T0(target_ulong arg) |
|
493 |
{ |
|
494 |
tcg_gen_movi_tl(cpu_T[0], arg); |
|
495 |
} |
|
496 |
|
|
497 |
static inline void gen_op_set_T1(target_ulong arg) |
|
498 |
{ |
|
499 |
tcg_gen_movi_tl(cpu_T[1], arg); |
|
500 |
} |
|
501 |
|
|
502 |
static inline void gen_op_reset_T0(void) |
|
503 |
{ |
|
504 |
tcg_gen_movi_tl(cpu_T[0], 0); |
|
505 |
} |
|
506 |
|
|
507 |
static inline void gen_op_reset_T1(void) |
|
508 |
{ |
|
509 |
tcg_gen_movi_tl(cpu_T[1], 0); |
|
510 |
} |
|
511 |
|
|
512 |
/* Moves to/from HI/LO registers. */ |
|
513 |
static inline void gen_op_load_HI(int reg) |
|
514 |
{ |
|
515 |
tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, HI[reg])); |
|
516 |
} |
|
517 |
|
|
518 |
static inline void gen_op_store_HI(int reg) |
|
519 |
{ |
|
520 |
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, HI[reg])); |
|
521 |
} |
|
522 |
|
|
523 |
static inline void gen_op_load_LO(int reg) |
|
524 |
{ |
|
525 |
tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUState, LO[reg])); |
|
526 |
} |
|
527 |
|
|
528 |
static inline void gen_op_store_LO(int reg) |
|
529 |
{ |
|
530 |
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, LO[reg])); |
|
531 |
} |
|
532 |
|
|
533 |
|
|
534 |
/* Floating point register moves. */ |
|
491 | 535 |
static const char *fregnames[] = |
492 | 536 |
{ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
493 | 537 |
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
... | ... | |
639 | 683 |
} \ |
640 | 684 |
} while (0) |
641 | 685 |
|
642 |
#if defined(TARGET_MIPS64) |
|
643 |
#define GEN_LOAD_IMM_TN(Tn, Imm) \ |
|
644 |
do { \ |
|
645 |
if (Imm == 0) { \ |
|
646 |
glue(gen_op_reset_, Tn)(); \ |
|
647 |
} else if ((int32_t)Imm == Imm) { \ |
|
648 |
glue(gen_op_set_, Tn)(Imm); \ |
|
649 |
} else { \ |
|
650 |
glue(gen_op_set64_, Tn)(((uint64_t)Imm) >> 32, (uint32_t)Imm); \ |
|
651 |
} \ |
|
652 |
} while (0) |
|
653 |
#else |
|
654 | 686 |
#define GEN_LOAD_IMM_TN(Tn, Imm) \ |
655 | 687 |
do { \ |
656 | 688 |
if (Imm == 0) { \ |
... | ... | |
659 | 691 |
glue(gen_op_set_, Tn)(Imm); \ |
660 | 692 |
} \ |
661 | 693 |
} while (0) |
662 |
#endif |
|
663 | 694 |
|
664 | 695 |
#define GEN_STORE_T0_REG(Rn) \ |
665 | 696 |
do { \ |
... | ... | |
759 | 790 |
} |
760 | 791 |
} |
761 | 792 |
|
793 |
static always_inline void |
|
794 |
generate_tcg_exception_err (DisasContext *ctx, int excp, int err) |
|
795 |
{ |
|
796 |
save_cpu_state(ctx, 1); |
|
797 |
if (err == 0) |
|
798 |
gen_op_raise_exception(excp); |
|
799 |
else |
|
800 |
gen_op_raise_exception_err(excp, err); |
|
801 |
gen_op_interrupt_restart(); |
|
802 |
tcg_gen_exit_tb(0); |
|
803 |
} |
|
804 |
|
|
805 |
static always_inline void |
|
806 |
generate_tcg_exception (DisasContext *ctx, int excp) |
|
807 |
{ |
|
808 |
generate_tcg_exception_err (ctx, excp, 0); |
|
809 |
} |
|
810 |
|
|
762 | 811 |
static always_inline void generate_exception_err (DisasContext *ctx, int excp, int err) |
763 | 812 |
{ |
764 | 813 |
#if defined MIPS_DEBUG_DISAS |
... | ... | |
864 | 913 |
#endif |
865 | 914 |
|
866 | 915 |
#if defined(TARGET_MIPS64) |
867 |
OP_LD_TABLE(d); |
|
868 | 916 |
OP_LD_TABLE(dl); |
869 | 917 |
OP_LD_TABLE(dr); |
870 |
OP_ST_TABLE(d); |
|
871 | 918 |
OP_ST_TABLE(dl); |
872 | 919 |
OP_ST_TABLE(dr); |
873 |
OP_LD_TABLE(ld); |
|
874 |
OP_ST_TABLE(cd); |
|
875 |
OP_LD_TABLE(wu); |
|
876 | 920 |
#endif |
877 |
OP_LD_TABLE(w); |
|
878 | 921 |
OP_LD_TABLE(wl); |
879 | 922 |
OP_LD_TABLE(wr); |
880 |
OP_ST_TABLE(w); |
|
881 | 923 |
OP_ST_TABLE(wl); |
882 | 924 |
OP_ST_TABLE(wr); |
883 |
OP_LD_TABLE(h); |
|
884 |
OP_LD_TABLE(hu); |
|
885 |
OP_ST_TABLE(h); |
|
886 |
OP_LD_TABLE(b); |
|
887 |
OP_LD_TABLE(bu); |
|
888 |
OP_ST_TABLE(b); |
|
889 |
OP_LD_TABLE(l); |
|
890 |
OP_ST_TABLE(c); |
|
891 | 925 |
OP_LD_TABLE(wc1); |
892 | 926 |
OP_ST_TABLE(wc1); |
893 | 927 |
OP_LD_TABLE(dc1); |
... | ... | |
895 | 929 |
OP_LD_TABLE(uxc1); |
896 | 930 |
OP_ST_TABLE(uxc1); |
897 | 931 |
|
932 |
#define OP_LD(insn,fname) \ |
|
933 |
void inline op_ldst_##insn(DisasContext *ctx) \ |
|
934 |
{ \ |
|
935 |
tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \ |
|
936 |
} |
|
937 |
OP_LD(lb,ld8s); |
|
938 |
OP_LD(lbu,ld8u); |
|
939 |
OP_LD(lh,ld16s); |
|
940 |
OP_LD(lhu,ld16u); |
|
941 |
OP_LD(lw,ld32s); |
|
942 |
#if defined(TARGET_MIPS64) |
|
943 |
OP_LD(lwu,ld32u); |
|
944 |
OP_LD(ld,ld64); |
|
945 |
#endif |
|
946 |
#undef OP_LD |
|
947 |
|
|
948 |
#define OP_ST(insn,fname) \ |
|
949 |
void inline op_ldst_##insn(DisasContext *ctx) \ |
|
950 |
{ \ |
|
951 |
tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \ |
|
952 |
} |
|
953 |
OP_ST(sb,st8); |
|
954 |
OP_ST(sh,st16); |
|
955 |
OP_ST(sw,st32); |
|
956 |
#if defined(TARGET_MIPS64) |
|
957 |
OP_ST(sd,st64); |
|
958 |
#endif |
|
959 |
#undef OP_ST |
|
960 |
|
|
961 |
#define OP_LD_ATOMIC(insn,fname) \ |
|
962 |
void inline op_ldst_##insn(DisasContext *ctx) \ |
|
963 |
{ \ |
|
964 |
tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); \ |
|
965 |
tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx); \ |
|
966 |
tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
|
967 |
} |
|
968 |
OP_LD_ATOMIC(ll,ld32s); |
|
969 |
#if defined(TARGET_MIPS64) |
|
970 |
OP_LD_ATOMIC(lld,ld64); |
|
971 |
#endif |
|
972 |
#undef OP_LD_ATOMIC |
|
973 |
|
|
974 |
#define OP_ST_ATOMIC(insn,fname,almask) \ |
|
975 |
void inline op_ldst_##insn(DisasContext *ctx) \ |
|
976 |
{ \ |
|
977 |
int r_tmp = tcg_temp_new(TCG_TYPE_TL); \ |
|
978 |
int l1 = gen_new_label(); \ |
|
979 |
int l2 = gen_new_label(); \ |
|
980 |
int l3 = gen_new_label(); \ |
|
981 |
\ |
|
982 |
tcg_gen_andi_tl(r_tmp, cpu_T[0], almask); \ |
|
983 |
tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp, tcg_const_tl(0), l1); \ |
|
984 |
tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \ |
|
985 |
generate_tcg_exception(ctx, EXCP_AdES); \ |
|
986 |
gen_set_label(l1); \ |
|
987 |
tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr)); \ |
|
988 |
tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2); \ |
|
989 |
tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx); \ |
|
990 |
tcg_gen_movi_tl(cpu_T[0], 1); \ |
|
991 |
tcg_gen_br(l3); \ |
|
992 |
gen_set_label(l2); \ |
|
993 |
tcg_gen_movi_tl(cpu_T[0], 0); \ |
|
994 |
gen_set_label(l3); \ |
|
995 |
} |
|
996 |
OP_ST_ATOMIC(sc,st32,0x3); |
|
997 |
#if defined(TARGET_MIPS64) |
|
998 |
OP_ST_ATOMIC(scd,st64,0x7); |
|
999 |
#endif |
|
1000 |
#undef OP_ST_ATOMIC |
|
1001 |
|
|
1002 |
void inline op_ldst_lwc1(DisasContext *ctx) |
|
1003 |
{ |
|
1004 |
op_ldst(lwc1); |
|
1005 |
} |
|
1006 |
|
|
1007 |
void inline op_ldst_ldc1(DisasContext *ctx) |
|
1008 |
{ |
|
1009 |
op_ldst(ldc1); |
|
1010 |
} |
|
1011 |
|
|
1012 |
void inline op_ldst_swc1(DisasContext *ctx) |
|
1013 |
{ |
|
1014 |
op_ldst(swc1); |
|
1015 |
} |
|
1016 |
|
|
1017 |
void inline op_ldst_sdc1(DisasContext *ctx) |
|
1018 |
{ |
|
1019 |
op_ldst(sdc1); |
|
1020 |
} |
|
1021 |
|
|
898 | 1022 |
/* Load and store */ |
899 | 1023 |
static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
900 | 1024 |
int base, int16_t offset) |
... | ... | |
915 | 1039 |
switch (opc) { |
916 | 1040 |
#if defined(TARGET_MIPS64) |
917 | 1041 |
case OPC_LWU: |
918 |
op_ldst(lwu);
|
|
1042 |
op_ldst_lwu(ctx);
|
|
919 | 1043 |
GEN_STORE_T0_REG(rt); |
920 | 1044 |
opn = "lwu"; |
921 | 1045 |
break; |
922 | 1046 |
case OPC_LD: |
923 |
op_ldst(ld);
|
|
1047 |
op_ldst_ld(ctx);
|
|
924 | 1048 |
GEN_STORE_T0_REG(rt); |
925 | 1049 |
opn = "ld"; |
926 | 1050 |
break; |
927 | 1051 |
case OPC_LLD: |
928 |
op_ldst(lld);
|
|
1052 |
op_ldst_lld(ctx);
|
|
929 | 1053 |
GEN_STORE_T0_REG(rt); |
930 | 1054 |
opn = "lld"; |
931 | 1055 |
break; |
932 | 1056 |
case OPC_SD: |
933 | 1057 |
GEN_LOAD_REG_T1(rt); |
934 |
op_ldst(sd);
|
|
1058 |
op_ldst_sd(ctx);
|
|
935 | 1059 |
opn = "sd"; |
936 | 1060 |
break; |
937 | 1061 |
case OPC_SCD: |
938 | 1062 |
save_cpu_state(ctx, 1); |
939 | 1063 |
GEN_LOAD_REG_T1(rt); |
940 |
op_ldst(scd);
|
|
1064 |
op_ldst_scd(ctx);
|
|
941 | 1065 |
GEN_STORE_T0_REG(rt); |
942 | 1066 |
opn = "scd"; |
943 | 1067 |
break; |
... | ... | |
965 | 1089 |
break; |
966 | 1090 |
#endif |
967 | 1091 |
case OPC_LW: |
968 |
op_ldst(lw);
|
|
1092 |
op_ldst_lw(ctx);
|
|
969 | 1093 |
GEN_STORE_T0_REG(rt); |
970 | 1094 |
opn = "lw"; |
971 | 1095 |
break; |
972 | 1096 |
case OPC_SW: |
973 | 1097 |
GEN_LOAD_REG_T1(rt); |
974 |
op_ldst(sw);
|
|
1098 |
op_ldst_sw(ctx);
|
|
975 | 1099 |
opn = "sw"; |
976 | 1100 |
break; |
977 | 1101 |
case OPC_LH: |
978 |
op_ldst(lh);
|
|
1102 |
op_ldst_lh(ctx);
|
|
979 | 1103 |
GEN_STORE_T0_REG(rt); |
980 | 1104 |
opn = "lh"; |
981 | 1105 |
break; |
982 | 1106 |
case OPC_SH: |
983 | 1107 |
GEN_LOAD_REG_T1(rt); |
984 |
op_ldst(sh);
|
|
1108 |
op_ldst_sh(ctx);
|
|
985 | 1109 |
opn = "sh"; |
986 | 1110 |
break; |
987 | 1111 |
case OPC_LHU: |
988 |
op_ldst(lhu);
|
|
1112 |
op_ldst_lhu(ctx);
|
|
989 | 1113 |
GEN_STORE_T0_REG(rt); |
990 | 1114 |
opn = "lhu"; |
991 | 1115 |
break; |
992 | 1116 |
case OPC_LB: |
993 |
op_ldst(lb);
|
|
1117 |
op_ldst_lb(ctx);
|
|
994 | 1118 |
GEN_STORE_T0_REG(rt); |
995 | 1119 |
opn = "lb"; |
996 | 1120 |
break; |
997 | 1121 |
case OPC_SB: |
998 | 1122 |
GEN_LOAD_REG_T1(rt); |
999 |
op_ldst(sb);
|
|
1123 |
op_ldst_sb(ctx);
|
|
1000 | 1124 |
opn = "sb"; |
1001 | 1125 |
break; |
1002 | 1126 |
case OPC_LBU: |
1003 |
op_ldst(lbu);
|
|
1127 |
op_ldst_lbu(ctx);
|
|
1004 | 1128 |
GEN_STORE_T0_REG(rt); |
1005 | 1129 |
opn = "lbu"; |
1006 | 1130 |
break; |
... | ... | |
1027 | 1151 |
opn = "swr"; |
1028 | 1152 |
break; |
1029 | 1153 |
case OPC_LL: |
1030 |
op_ldst(ll);
|
|
1154 |
op_ldst_ll(ctx);
|
|
1031 | 1155 |
GEN_STORE_T0_REG(rt); |
1032 | 1156 |
opn = "ll"; |
1033 | 1157 |
break; |
1034 | 1158 |
case OPC_SC: |
1035 | 1159 |
save_cpu_state(ctx, 1); |
1036 | 1160 |
GEN_LOAD_REG_T1(rt); |
1037 |
op_ldst(sc);
|
|
1161 |
op_ldst_sc(ctx);
|
|
1038 | 1162 |
GEN_STORE_T0_REG(rt); |
1039 | 1163 |
opn = "sc"; |
1040 | 1164 |
break; |
... | ... | |
1065 | 1189 |
memory access. */ |
1066 | 1190 |
switch (opc) { |
1067 | 1191 |
case OPC_LWC1: |
1068 |
op_ldst(lwc1);
|
|
1192 |
op_ldst_lwc1(ctx);
|
|
1069 | 1193 |
GEN_STORE_FTN_FREG(ft, WT0); |
1070 | 1194 |
opn = "lwc1"; |
1071 | 1195 |
break; |
1072 | 1196 |
case OPC_SWC1: |
1073 | 1197 |
GEN_LOAD_FREG_FTN(WT0, ft); |
1074 |
op_ldst(swc1);
|
|
1198 |
op_ldst_swc1(ctx);
|
|
1075 | 1199 |
opn = "swc1"; |
1076 | 1200 |
break; |
1077 | 1201 |
case OPC_LDC1: |
1078 |
op_ldst(ldc1);
|
|
1202 |
op_ldst_ldc1(ctx);
|
|
1079 | 1203 |
GEN_STORE_FTN_FREG(ft, DT0); |
1080 | 1204 |
opn = "ldc1"; |
1081 | 1205 |
break; |
1082 | 1206 |
case OPC_SDC1: |
1083 | 1207 |
GEN_LOAD_FREG_FTN(DT0, ft); |
1084 |
op_ldst(sdc1);
|
|
1208 |
op_ldst_sdc1(ctx);
|
|
1085 | 1209 |
opn = "sdc1"; |
1086 | 1210 |
break; |
1087 | 1211 |
default: |
... | ... | |
5852 | 5976 |
switch (opc) { |
5853 | 5977 |
case OPC_LWXC1: |
5854 | 5978 |
check_cop1x(ctx); |
5855 |
op_ldst(lwc1);
|
|
5979 |
op_ldst_lwc1(ctx);
|
|
5856 | 5980 |
GEN_STORE_FTN_FREG(fd, WT0); |
5857 | 5981 |
opn = "lwxc1"; |
5858 | 5982 |
break; |
5859 | 5983 |
case OPC_LDXC1: |
5860 | 5984 |
check_cop1x(ctx); |
5861 | 5985 |
check_cp1_registers(ctx, fd); |
5862 |
op_ldst(ldc1);
|
|
5986 |
op_ldst_ldc1(ctx);
|
|
5863 | 5987 |
GEN_STORE_FTN_FREG(fd, DT0); |
5864 | 5988 |
opn = "ldxc1"; |
5865 | 5989 |
break; |
... | ... | |
5872 | 5996 |
case OPC_SWXC1: |
5873 | 5997 |
check_cop1x(ctx); |
5874 | 5998 |
GEN_LOAD_FREG_FTN(WT0, fs); |
5875 |
op_ldst(swc1);
|
|
5999 |
op_ldst_swc1(ctx);
|
|
5876 | 6000 |
opn = "swxc1"; |
5877 | 6001 |
store = 1; |
5878 | 6002 |
break; |
... | ... | |
5880 | 6004 |
check_cop1x(ctx); |
5881 | 6005 |
check_cp1_registers(ctx, fs); |
5882 | 6006 |
GEN_LOAD_FREG_FTN(DT0, fs); |
5883 |
op_ldst(sdc1);
|
|
6007 |
op_ldst_sdc1(ctx);
|
|
5884 | 6008 |
opn = "sdxc1"; |
5885 | 6009 |
store = 1; |
5886 | 6010 |
break; |
Also available in: Unified diff