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,19 +493,19 @@ void op_xor (void) | ||
| 493 | 493 | ||
| 494 | void op_sll (void) | 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 | RETURN(); | 497 | RETURN(); |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | void op_sra (void) | 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 | RETURN(); | 503 | RETURN(); |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | void op_srl (void) | 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 | RETURN(); | 509 | RETURN(); |
| 510 | } | 510 | } |
| 511 | 511 | ||
| @@ -514,10 +514,9 @@ void op_rotr (void) | @@ -514,10 +514,9 @@ void op_rotr (void) | ||
| 514 | target_ulong tmp; | 514 | target_ulong tmp; |
| 515 | 515 | ||
| 516 | if (T1) { | 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 | RETURN(); | 520 | RETURN(); |
| 522 | } | 521 | } |
| 523 | 522 | ||
| @@ -707,8 +706,7 @@ void op_drotr (void) | @@ -707,8 +706,7 @@ void op_drotr (void) | ||
| 707 | if (T1) { | 706 | if (T1) { |
| 708 | tmp = T0 << (0x40 - T1); | 707 | tmp = T0 << (0x40 - T1); |
| 709 | T0 = (T0 >> T1) | tmp; | 708 | T0 = (T0 >> T1) | tmp; |
| 710 | - } else | ||
| 711 | - T0 = T1; | 709 | + } |
| 712 | RETURN(); | 710 | RETURN(); |
| 713 | } | 711 | } |
| 714 | 712 | ||
| @@ -719,8 +717,7 @@ void op_drotr32 (void) | @@ -719,8 +717,7 @@ void op_drotr32 (void) | ||
| 719 | if (T1) { | 717 | if (T1) { |
| 720 | tmp = T0 << (0x40 - (32 + T1)); | 718 | tmp = T0 << (0x40 - (32 + T1)); |
| 721 | T0 = (T0 >> (32 + T1)) | tmp; | 719 | T0 = (T0 >> (32 + T1)) | tmp; |
| 722 | - } else | ||
| 723 | - T0 = T1; | 720 | + } |
| 724 | RETURN(); | 721 | RETURN(); |
| 725 | } | 722 | } |
| 726 | 723 |
target-mips/op_helper.c
| @@ -120,8 +120,7 @@ void do_drotr (void) | @@ -120,8 +120,7 @@ void do_drotr (void) | ||
| 120 | if (T1) { | 120 | if (T1) { |
| 121 | tmp = T0 << (0x40 - T1); | 121 | tmp = T0 << (0x40 - T1); |
| 122 | T0 = (T0 >> T1) | tmp; | 122 | T0 = (T0 >> T1) | tmp; |
| 123 | - } else | ||
| 124 | - T0 = T1; | 123 | + } |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | void do_drotr32 (void) | 126 | void do_drotr32 (void) |
| @@ -131,8 +130,7 @@ void do_drotr32 (void) | @@ -131,8 +130,7 @@ void do_drotr32 (void) | ||
| 131 | if (T1) { | 130 | if (T1) { |
| 132 | tmp = T0 << (0x40 - (32 + T1)); | 131 | tmp = T0 << (0x40 - (32 + T1)); |
| 133 | T0 = (T0 >> (32 + T1)) | tmp; | 132 | T0 = (T0 >> (32 + T1)) | tmp; |
| 134 | - } else | ||
| 135 | - T0 = T1; | 133 | + } |
| 136 | } | 134 | } |
| 137 | 135 | ||
| 138 | void do_dsllv (void) | 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,18 +849,43 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | ||
| 849 | MIPS_DEBUG("NOP"); | 849 | MIPS_DEBUG("NOP"); |
| 850 | return; | 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 | uimm = (int32_t)imm; /* Sign extend to 32 bits */ | 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 | GEN_LOAD_REG_TN(T0, rs); | 867 | GEN_LOAD_REG_TN(T0, rs); |
| 860 | GEN_LOAD_IMM_TN(T1, uimm); | 868 | GEN_LOAD_IMM_TN(T1, uimm); |
| 861 | - } else { | ||
| 862 | - uimm = uimm << 16; | 869 | + break; |
| 870 | + case OPC_LUI: | ||
| 871 | + uimm <<= 16; | ||
| 863 | GEN_LOAD_IMM_TN(T0, uimm); | 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 | switch (opc) { | 890 | switch (opc) { |
| 866 | case OPC_ADDI: | 891 | case OPC_ADDI: |
| @@ -915,13 +940,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | @@ -915,13 +940,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | ||
| 915 | opn = "sra"; | 940 | opn = "sra"; |
| 916 | break; | 941 | break; |
| 917 | case OPC_SRL: | 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 | gen_op_srl(); | 945 | gen_op_srl(); |
| 923 | opn = "srl"; | 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 | break; | 957 | break; |
| 926 | #ifdef TARGET_MIPS64 | 958 | #ifdef TARGET_MIPS64 |
| 927 | case OPC_DSLL: | 959 | case OPC_DSLL: |
| @@ -933,13 +965,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | @@ -933,13 +965,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | ||
| 933 | opn = "dsra"; | 965 | opn = "dsra"; |
| 934 | break; | 966 | break; |
| 935 | case OPC_DSRL: | 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 | gen_op_dsrl(); | 970 | gen_op_dsrl(); |
| 941 | opn = "dsrl"; | 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 | break; | 982 | break; |
| 944 | case OPC_DSLL32: | 983 | case OPC_DSLL32: |
| 945 | gen_op_dsll32(); | 984 | gen_op_dsll32(); |
| @@ -950,13 +989,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | @@ -950,13 +989,20 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, | ||
| 950 | opn = "dsra32"; | 989 | opn = "dsra32"; |
| 951 | break; | 990 | break; |
| 952 | case OPC_DSRL32: | 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 | gen_op_dsrl32(); | 994 | gen_op_dsrl32(); |
| 958 | opn = "dsrl32"; | 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 | break; | 1006 | break; |
| 961 | #endif | 1007 | #endif |
| 962 | default: | 1008 | default: |
| @@ -1068,13 +1114,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, | @@ -1068,13 +1114,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, | ||
| 1068 | opn = "srav"; | 1114 | opn = "srav"; |
| 1069 | break; | 1115 | break; |
| 1070 | case OPC_SRLV: | 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 | gen_op_srlv(); | 1119 | gen_op_srlv(); |
| 1076 | opn = "srlv"; | 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 | break; | 1131 | break; |
| 1079 | #ifdef TARGET_MIPS64 | 1132 | #ifdef TARGET_MIPS64 |
| 1080 | case OPC_DSLLV: | 1133 | case OPC_DSLLV: |
| @@ -1086,13 +1139,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, | @@ -1086,13 +1139,20 @@ static void gen_arith (DisasContext *ctx, uint32_t opc, | ||
| 1086 | opn = "dsrav"; | 1139 | opn = "dsrav"; |
| 1087 | break; | 1140 | break; |
| 1088 | case OPC_DSRLV: | 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 | gen_op_dsrlv(); | 1144 | gen_op_dsrlv(); |
| 1094 | opn = "dsrlv"; | 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 | break; | 1156 | break; |
| 1097 | #endif | 1157 | #endif |
| 1098 | default: | 1158 | default: |