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