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: | ... | ... |