Commit 5a63bcb2d27675a3fc2c5bc8a8c323e5c756e749
1 parent
acd858d9
Fix rotr immediate ops, mask shift/rotate arguments to their allowed
size. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2614 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
103 additions
and
48 deletions
target-mips/op.c
| ... | ... | @@ -493,19 +493,19 @@ void op_xor (void) |
| 493 | 493 | |
| 494 | 494 | void op_sll (void) |
| 495 | 495 | { |
| 496 | - T0 = (int32_t)((uint32_t)T0 << (uint32_t)T1); | |
| 496 | + T0 = (int32_t)((uint32_t)T0 << T1); | |
| 497 | 497 | RETURN(); |
| 498 | 498 | } |
| 499 | 499 | |
| 500 | 500 | void op_sra (void) |
| 501 | 501 | { |
| 502 | - T0 = (int32_t)((int32_t)T0 >> (uint32_t)T1); | |
| 502 | + T0 = (int32_t)((int32_t)T0 >> T1); | |
| 503 | 503 | RETURN(); |
| 504 | 504 | } |
| 505 | 505 | |
| 506 | 506 | void op_srl (void) |
| 507 | 507 | { |
| 508 | - T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1); | |
| 508 | + T0 = (int32_t)((uint32_t)T0 >> T1); | |
| 509 | 509 | RETURN(); |
| 510 | 510 | } |
| 511 | 511 | |
| ... | ... | @@ -514,10 +514,9 @@ void op_rotr (void) |
| 514 | 514 | target_ulong tmp; |
| 515 | 515 | |
| 516 | 516 | if (T1) { |
| 517 | - tmp = (int32_t)((uint32_t)T0 << (0x20 - (uint32_t)T1)); | |
| 518 | - T0 = (int32_t)((uint32_t)T0 >> (uint32_t)T1) | tmp; | |
| 519 | - } else | |
| 520 | - T0 = T1; | |
| 517 | + tmp = (int32_t)((uint32_t)T0 << (0x20 - T1)); | |
| 518 | + T0 = (int32_t)((uint32_t)T0 >> T1) | tmp; | |
| 519 | + } | |
| 521 | 520 | RETURN(); |
| 522 | 521 | } |
| 523 | 522 | |
| ... | ... | @@ -707,8 +706,7 @@ void op_drotr (void) |
| 707 | 706 | if (T1) { |
| 708 | 707 | tmp = T0 << (0x40 - T1); |
| 709 | 708 | T0 = (T0 >> T1) | tmp; |
| 710 | - } else | |
| 711 | - T0 = T1; | |
| 709 | + } | |
| 712 | 710 | RETURN(); |
| 713 | 711 | } |
| 714 | 712 | |
| ... | ... | @@ -719,8 +717,7 @@ void op_drotr32 (void) |
| 719 | 717 | if (T1) { |
| 720 | 718 | tmp = T0 << (0x40 - (32 + T1)); |
| 721 | 719 | T0 = (T0 >> (32 + T1)) | tmp; |
| 722 | - } else | |
| 723 | - T0 = T1; | |
| 720 | + } | |
| 724 | 721 | RETURN(); |
| 725 | 722 | } |
| 726 | 723 | ... | ... |
target-mips/op_helper.c
| ... | ... | @@ -120,8 +120,7 @@ void do_drotr (void) |
| 120 | 120 | if (T1) { |
| 121 | 121 | tmp = T0 << (0x40 - T1); |
| 122 | 122 | T0 = (T0 >> T1) | tmp; |
| 123 | - } else | |
| 124 | - T0 = T1; | |
| 123 | + } | |
| 125 | 124 | } |
| 126 | 125 | |
| 127 | 126 | void do_drotr32 (void) |
| ... | ... | @@ -131,8 +130,7 @@ void do_drotr32 (void) |
| 131 | 130 | if (T1) { |
| 132 | 131 | tmp = T0 << (0x40 - (32 + T1)); |
| 133 | 132 | T0 = (T0 >> (32 + T1)) | tmp; |
| 134 | - } else | |
| 135 | - T0 = T1; | |
| 133 | + } | |
| 136 | 134 | } |
| 137 | 135 | |
| 138 | 136 | void do_dsllv (void) | ... | ... |
target-mips/translate.c
| ... | ... | @@ -849,18 +849,43 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
| 849 | 849 | MIPS_DEBUG("NOP"); |
| 850 | 850 | return; |
| 851 | 851 | } |
| 852 | - if (opc == OPC_ADDI || opc == OPC_ADDIU || | |
| 853 | - opc == OPC_DADDI || opc == OPC_DADDIU || | |
| 854 | - opc == OPC_SLTI || opc == OPC_SLTIU) | |
| 852 | + uimm = (uint16_t)imm; | |
| 853 | + switch (opc) { | |
| 854 | + case OPC_ADDI: | |
| 855 | + case OPC_ADDIU: | |
| 856 | +#ifdef TARGET_MIPS64 | |
| 857 | + case OPC_DADDI: | |
| 858 | + case OPC_DADDIU: | |
| 859 | +#endif | |
| 860 | + case OPC_SLTI: | |
| 861 | + case OPC_SLTIU: | |
| 855 | 862 | uimm = (int32_t)imm; /* Sign extend to 32 bits */ |
| 856 | - else | |
| 857 | - uimm = (uint16_t)imm; | |
| 858 | - if (opc != OPC_LUI) { | |
| 863 | + /* Fall through. */ | |
| 864 | + case OPC_ANDI: | |
| 865 | + case OPC_ORI: | |
| 866 | + case OPC_XORI: | |
| 859 | 867 | GEN_LOAD_REG_TN(T0, rs); |
| 860 | 868 | GEN_LOAD_IMM_TN(T1, uimm); |
| 861 | - } else { | |
| 862 | - uimm = uimm << 16; | |
| 869 | + break; | |
| 870 | + case OPC_LUI: | |
| 871 | + uimm <<= 16; | |
| 863 | 872 | GEN_LOAD_IMM_TN(T0, uimm); |
| 873 | + break; | |
| 874 | + case OPC_SLL: | |
| 875 | + case OPC_SRA: | |
| 876 | + case OPC_SRL: | |
| 877 | +#ifdef TARGET_MIPS64 | |
| 878 | + case OPC_DSLL: | |
| 879 | + case OPC_DSRA: | |
| 880 | + case OPC_DSRL: | |
| 881 | + case OPC_DSLL32: | |
| 882 | + case OPC_DSRA32: | |
| 883 | + case OPC_DSRL32: | |
| 884 | +#endif | |
| 885 | + uimm &= 0x1f; | |
| 886 | + GEN_LOAD_REG_TN(T0, rs); | |
| 887 | + GEN_LOAD_IMM_TN(T1, uimm); | |
| 888 | + break; | |
| 864 | 889 | } |
| 865 | 890 | switch (opc) { |
| 866 | 891 | case OPC_ADDI: |
| ... | ... | @@ -915,13 +940,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
| 915 | 940 | opn = "sra"; |
| 916 | 941 | break; |
| 917 | 942 | case OPC_SRL: |
| 918 | - if ((ctx->opcode >> 21) & 1) { | |
| 919 | - gen_op_rotr(); | |
| 920 | - opn = "rotr"; | |
| 921 | - } else { | |
| 943 | + switch ((ctx->opcode >> 21) & 0x1f) { | |
| 944 | + case 0: | |
| 922 | 945 | gen_op_srl(); |
| 923 | 946 | opn = "srl"; |
| 924 | - } | |
| 947 | + break; | |
| 948 | + case 1: | |
| 949 | + gen_op_rotr(); | |
| 950 | + opn = "rotr"; | |
| 951 | + break; | |
| 952 | + default: | |
| 953 | + MIPS_INVAL("invalid srl flag"); | |
| 954 | + generate_exception(ctx, EXCP_RI); | |
| 955 | + break; | |
| 956 | + } | |
| 925 | 957 | break; |
| 926 | 958 | #ifdef TARGET_MIPS64 |
| 927 | 959 | case OPC_DSLL: |
| ... | ... | @@ -933,13 +965,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
| 933 | 965 | opn = "dsra"; |
| 934 | 966 | break; |
| 935 | 967 | case OPC_DSRL: |
| 936 | - if ((ctx->opcode >> 21) & 1) { | |
| 937 | - gen_op_drotr(); | |
| 938 | - opn = "drotr"; | |
| 939 | - } else { | |
| 968 | + switch ((ctx->opcode >> 21) & 0x1f) { | |
| 969 | + case 0: | |
| 940 | 970 | gen_op_dsrl(); |
| 941 | 971 | opn = "dsrl"; |
| 942 | - } | |
| 972 | + break; | |
| 973 | + case 1: | |
| 974 | + gen_op_drotr(); | |
| 975 | + opn = "drotr"; | |
| 976 | + break; | |
| 977 | + default: | |
| 978 | + MIPS_INVAL("invalid dsrl flag"); | |
| 979 | + generate_exception(ctx, EXCP_RI); | |
| 980 | + break; | |
| 981 | + } | |
| 943 | 982 | break; |
| 944 | 983 | case OPC_DSLL32: |
| 945 | 984 | gen_op_dsll32(); |
| ... | ... | @@ -950,13 +989,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
| 950 | 989 | opn = "dsra32"; |
| 951 | 990 | break; |
| 952 | 991 | case OPC_DSRL32: |
| 953 | - if ((ctx->opcode >> 21) & 1) { | |
| 954 | - gen_op_drotr32(); | |
| 955 | - opn = "drotr32"; | |
| 956 | - } else { | |
| 992 | + switch ((ctx->opcode >> 21) & 0x1f) { | |
| 993 | + case 0: | |
| 957 | 994 | gen_op_dsrl32(); |
| 958 | 995 | opn = "dsrl32"; |
| 959 | - } | |
| 996 | + break; | |
| 997 | + case 1: | |
| 998 | + gen_op_drotr32(); | |
| 999 | + opn = "drotr32"; | |
| 1000 | + break; | |
| 1001 | + default: | |
| 1002 | + MIPS_INVAL("invalid dsrl32 flag"); | |
| 1003 | + generate_exception(ctx, EXCP_RI); | |
| 1004 | + break; | |
| 1005 | + } | |
| 960 | 1006 | break; |
| 961 | 1007 | #endif |
| 962 | 1008 | default: |
| ... | ... | @@ -1068,13 +1114,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, |
| 1068 | 1114 | opn = "srav"; |
| 1069 | 1115 | break; |
| 1070 | 1116 | case OPC_SRLV: |
| 1071 | - if ((ctx->opcode >> 6) & 1) { | |
| 1072 | - gen_op_rotrv(); | |
| 1073 | - opn = "rotrv"; | |
| 1074 | - } else { | |
| 1117 | + switch ((ctx->opcode >> 6) & 0x1f) { | |
| 1118 | + case 0: | |
| 1075 | 1119 | gen_op_srlv(); |
| 1076 | 1120 | opn = "srlv"; |
| 1077 | - } | |
| 1121 | + break; | |
| 1122 | + case 1: | |
| 1123 | + gen_op_rotrv(); | |
| 1124 | + opn = "rotrv"; | |
| 1125 | + break; | |
| 1126 | + default: | |
| 1127 | + MIPS_INVAL("invalid srlv flag"); | |
| 1128 | + generate_exception(ctx, EXCP_RI); | |
| 1129 | + break; | |
| 1130 | + } | |
| 1078 | 1131 | break; |
| 1079 | 1132 | #ifdef TARGET_MIPS64 |
| 1080 | 1133 | case OPC_DSLLV: |
| ... | ... | @@ -1086,13 +1139,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, |
| 1086 | 1139 | opn = "dsrav"; |
| 1087 | 1140 | break; |
| 1088 | 1141 | case OPC_DSRLV: |
| 1089 | - if ((ctx->opcode >> 6) & 1) { | |
| 1090 | - gen_op_drotrv(); | |
| 1091 | - opn = "drotrv"; | |
| 1092 | - } else { | |
| 1142 | + switch ((ctx->opcode >> 6) & 0x1f) { | |
| 1143 | + case 0: | |
| 1093 | 1144 | gen_op_dsrlv(); |
| 1094 | 1145 | opn = "dsrlv"; |
| 1095 | - } | |
| 1146 | + break; | |
| 1147 | + case 1: | |
| 1148 | + gen_op_drotrv(); | |
| 1149 | + opn = "drotrv"; | |
| 1150 | + break; | |
| 1151 | + default: | |
| 1152 | + MIPS_INVAL("invalid dsrlv flag"); | |
| 1153 | + generate_exception(ctx, EXCP_RI); | |
| 1154 | + break; | |
| 1155 | + } | |
| 1096 | 1156 | break; |
| 1097 | 1157 | #endif |
| 1098 | 1158 | default: | ... | ... |